diff --git a/.gitignore b/.gitignore index b0088e0..d17bf15 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .env tmp *.db +imgs \ No newline at end of file diff --git a/README.md b/README.md index b58e450..fb342cc 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,3 @@ # stereo.cat backend written in Go, uses Gin. - -## database shit - -Instead of using Discord oAuth as a database, we instead use it as a login source, only using it to source a username/id, avatar data and a secure login/registration flow. -We store these attributes alongside stereo.cat specific attributes in our own database. There is a trade-off however: this means that avatar & username data is not updated in real-time, only when the oauth flow is executed. diff --git a/internal/api/routes/auth.go b/internal/api/routes/auth.go index 53082dc..a6a634f 100644 --- a/internal/api/routes/auth.go +++ b/internal/api/routes/auth.go @@ -31,21 +31,11 @@ func RegisterAuthRoutes(cfg *types.StereoConfig, api *gin.RouterGroup) { panic(err) } - res := cfg.Database.FirstOrCreate(&user) - - if res.Error != nil { - panic(res.Error) - } - - // TODO: redirect to dashboard - c.JSON(http.StatusOK, gin.H{ - "jwt": jwt, - "known": res.RowsAffected == 0, - }) + c.String(http.StatusOK, jwt) }) api.GET("/auth/me", auth.JwtMiddleware(cfg.JWTSecret), func(c *gin.Context) { - claims, _ := c.Get("claims") + claims, _ := c.Get("claims") c.JSON(http.StatusOK, claims) }) } diff --git a/internal/api/routes/upload.go b/internal/api/routes/upload.go index baed591..d4950e7 100644 --- a/internal/api/routes/upload.go +++ b/internal/api/routes/upload.go @@ -4,22 +4,36 @@ import ( "path/filepath" "github.com/gin-gonic/gin" + "github.com/golang-jwt/jwt/v5" + "stereo.cat/backend/internal/auth" "stereo.cat/backend/internal/types" ) func RegisterUploadRoutes(cfg *types.StereoConfig, api *gin.RouterGroup) { - api.POST("/upload", func(c *gin.Context) { + api.POST("/upload", auth.JwtMiddleware(cfg.JWTSecret), func(c *gin.Context) { + claims := c.MustGet("claims").(jwt.MapClaims) + user := claims["user"].(auth.User) + + uid := user.ID + + if uid == "" { + c.JSON(401, gin.H{"error": "unauthorized"}) + return + } + file, err := c.FormFile("file") if err != nil { c.JSON(400, gin.H{"error": "file is required"}) return } - filePath := filepath.Join(cfg.ImagePath, file.Filename) + filePath := filepath.Join(cfg.ImagePath, uid, file.Filename) if err := c.SaveUploadedFile(file, filePath); err != nil { c.JSON(500, gin.H{"error": "failed to save file"}) return } + + c.JSON(200, gin.H{"message": "file uploaded successfully"}) }) api.GET("/:name", func(c *gin.Context) { diff --git a/internal/auth/jwt.go b/internal/auth/jwt.go index 9e7aec2..1ea6d0f 100644 --- a/internal/auth/jwt.go +++ b/internal/auth/jwt.go @@ -11,9 +11,9 @@ import ( ) func GenerateJWT(key string, user User, expiryTimestamp uint64) (string, error) { - claims := jwt.MapClaims{ - "user": user, - "exp": expiryTimestamp, + claims := Claims{ + User: user, + Exp: expiryTimestamp, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) diff --git a/internal/auth/types.go b/internal/auth/types.go index a83b941..8627df7 100644 --- a/internal/auth/types.go +++ b/internal/auth/types.go @@ -1,6 +1,10 @@ package auth -import "time" +import ( + "time" + + "github.com/golang-jwt/jwt/v5" +) type TokenResponse struct { AccessToken string `json:"access_token"` @@ -28,3 +32,9 @@ type ExchangeCodeRequest struct { Code string `json:"code"` RedirectUri string `json:"redirect_uri"` } + +type Claims struct { + User User `json:"user"` + Exp uint64 `json:"exp"` + jwt.RegisteredClaims +}