Compare commits

...
Sign in to create a new pull request.

3 commits

4 changed files with 147 additions and 5 deletions

View file

@ -12,8 +12,9 @@ REDIRECT_URI=http://localhost:8081/api/auth/callback
CLIENT_ID= CLIENT_ID=
CLIENT_SECRET= CLIENT_SECRET=
# Listening port # Listen address (if the IP address is empty, it will default to 127.0.0.1)
PORT= # e.g. 127.0.0.1:8081 or :8081
LISTEN_ADDRESS=:8081
# S3 # S3
S3_ENDPOINT= S3_ENDPOINT=
@ -32,3 +33,14 @@ POSTGRES_DSN=
# Random secret. Recommended length is 64 characters at minimum. # Random secret. Recommended length is 64 characters at minimum.
JWT_SECRET= JWT_SECRET=
# URL to Boxy's API.
# e.g. http://localhost:8001
# without ending forward slash (/)
BOXY_URL=
# Address by which Boxy can reach us. If it is not set, it will be the address with which we'll reach Boxy's API.
BOXY_CLIENT_ADDRESS=
BOXY_CLIENT_NAME=
BOXY_CLIENT_SECRET=

97
internal/boxy/boxy.go Normal file
View file

@ -0,0 +1,97 @@
package boxy
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"strconv"
)
type BoxyClient struct {
Name string
Secret string
ApiUrl string
Hostnames []string
endpointId int
}
func (b *BoxyClient) Register(address string, port int) error {
rawBody := map[string]any{
"port": port,
"hostname": b.Hostnames,
}
if address != "" {
rawBody["address"] = address
}
jBody, err := json.Marshal(rawBody)
if err != nil {
return err
}
req, err := http.NewRequest("POST", b.ApiUrl+"/register", bytes.NewBuffer(jBody))
if err != nil {
return err
}
req.SetBasicAuth(b.Name, b.Secret)
resp, _ := http.DefaultClient.Do(req)
if resp.StatusCode != 200 {
log.Fatal("Could not register with Boxy.\nStatus Code: " + strconv.Itoa(req.Response.StatusCode))
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
b.endpointId, err = strconv.Atoi(string(body))
if err != nil {
return err
}
return nil
}
func (b *BoxyClient) Unregister() error {
rawBody := map[string]any{}
jBody, err := json.Marshal(rawBody)
if err != nil {
return err
}
req, err := http.NewRequest("DELETE", b.ApiUrl+"/endpoint/"+strconv.Itoa(b.endpointId), bytes.NewBuffer(jBody))
if err != nil {
return err
}
req.SetBasicAuth(b.Name, b.Secret)
resp, _ := http.DefaultClient.Do(req)
body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
if resp.StatusCode != 200 {
return fmt.Errorf("Could not delete endpoint.\nBody: %s", string(body))
}
return nil
}

View file

@ -26,6 +26,7 @@ import (
"github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7"
"gorm.io/gorm" "gorm.io/gorm"
"stereo.cat/backend/internal/auth/client" "stereo.cat/backend/internal/auth/client"
"stereo.cat/backend/internal/boxy"
) )
type Route struct { type Route struct {
@ -45,6 +46,7 @@ type StereoConfig struct {
FrontendUri string FrontendUri string
Domain string Domain string
Context context.Context Context context.Context
BoxyClient boxy.BoxyClient
} }
type File struct { type File struct {

37
main.go
View file

@ -23,6 +23,8 @@ import (
"fmt" "fmt"
"log" "log"
"os" "os"
"strconv"
"strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/joho/godotenv" "github.com/joho/godotenv"
@ -34,6 +36,7 @@ import (
"stereo.cat/backend/internal/api" "stereo.cat/backend/internal/api"
"stereo.cat/backend/internal/auth" "stereo.cat/backend/internal/auth"
"stereo.cat/backend/internal/auth/client" "stereo.cat/backend/internal/auth/client"
"stereo.cat/backend/internal/boxy"
"stereo.cat/backend/internal/types" "stereo.cat/backend/internal/types"
) )
@ -56,6 +59,9 @@ func main() {
databaseType := getEnv("DATABASE_TYPE", "sqlite") databaseType := getEnv("DATABASE_TYPE", "sqlite")
sqliteFile := getEnv("SQLITE_FILE", "stereo.db") sqliteFile := getEnv("SQLITE_FILE", "stereo.db")
boxyApiUrl := getEnv("BOXY_URL", "")
listenAddr := getEnv("LISTEN_ADDRESS", ":8081")
imagePath := getEnv("IMAGE_PATH", os.TempDir()) imagePath := getEnv("IMAGE_PATH", os.TempDir())
if _, err := os.Stat(imagePath); err != nil { if _, err := os.Stat(imagePath); err != nil {
@ -82,7 +88,7 @@ func main() {
Router: gin.Default(), Router: gin.Default(),
MinioClient: minioClient, MinioClient: minioClient,
Bucket: requireEnv("S3_BUCKET"), Bucket: requireEnv("S3_BUCKET"),
Context: context.Background(), Context: context.Background(),
ImagePath: imagePath, ImagePath: imagePath,
Client: client.New( Client: client.New(
requireEnv("REDIRECT_URI"), requireEnv("REDIRECT_URI"),
@ -122,7 +128,32 @@ func main() {
c.Database.AutoMigrate(&auth.User{}, &types.File{}) c.Database.AutoMigrate(&auth.User{}, &types.File{})
if boxyApiUrl != "" {
boxyClientName := requireEnv("BOXY_CLIENT_NAME")
boxyClientSecret := requireEnv("BOXY_CLIENT_SECRET")
boxyClientAddress := getEnv("BOXY_CLIENT_ADDRESS", "")
port, err := strconv.Atoi(strings.Split(listenAddr, ":")[1])
if err != nil {
panic(err)
}
c.BoxyClient = boxy.BoxyClient{
Name: boxyClientName,
Secret: boxyClientSecret,
ApiUrl: boxyApiUrl,
Hostnames: []string{c.Domain},
}
err = c.BoxyClient.Register(boxyClientAddress, port)
if err != nil {
panic(err)
}
}
api.Register(&c) api.Register(&c)
fmt.Printf("Running on port %s\n", getEnv("PORT", "8081")) fmt.Printf("Listening on %s\n", listenAddr)
c.Router.Run() c.Router.Run(listenAddr)
} }