diff --git a/backend/cmd/main.go b/backend/cmd/main.go index 2bce764..6a0cd61 100644 --- a/backend/cmd/main.go +++ b/backend/cmd/main.go @@ -23,7 +23,19 @@ func main() { r := gin.Default() r = routes.SetupRoutes(r) - docs.SwaggerInfo.BasePath = "/api/" + // @title Easywish client API + // @version 1.0 + // @description Easy and feature-rich wishlist. + // @license.name GPL 3.0 + + // @BasePath /api/ + // @Schemes http + + // @securityDefinitions.apikey JWT + // @in header + // @name Authorization + + docs.SwaggerInfo.Schemes = []string{"http"} r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler)) r.Run(":8080") diff --git a/backend/docs/docs.go b/backend/docs/docs.go index 7ed931c..386bef8 100644 --- a/backend/docs/docs.go +++ b/backend/docs/docs.go @@ -10,11 +10,34 @@ const docTemplate = `{ "description": "{{escape .Description}}", "title": "{{.Title}}", "contact": {}, + "license": { + "name": "GPL 3.0" + }, "version": "{{.Version}}" }, "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { + "/account/changePassword": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Change account password", + "responses": {} + } + }, "/auth/login": { "post": { "consumes": [ @@ -105,6 +128,93 @@ const docTemplate = `{ "responses": {} } }, + "/profile/me": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Profile" + ], + "summary": "Get own profile when authorized", + "responses": {} + } + }, + "/profile/privacy": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Profile" + ], + "summary": "Get profile privacy settings", + "responses": {} + }, + "patch": { + "security": [ + { + "JWT": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Profile" + ], + "summary": "Update profile privacy settings", + "responses": {} + } + }, + "/profile/{username}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Profile" + ], + "summary": "Get someone's profile details", + "parameters": [ + { + "type": "string", + "description": "Username", + "name": "username", + "in": "path", + "required": true + } + ], + "responses": {} + } + }, "/service/health": { "get": { "description": "Used internally for checking service health", @@ -138,17 +248,24 @@ const docTemplate = `{ } } } + }, + "securityDefinitions": { + "JWT": { + "type": "apiKey", + "name": "Authorization", + "in": "header" + } } }` // SwaggerInfo holds exported Swagger Info so clients can modify it var SwaggerInfo = &swag.Spec{ - Version: "", + Version: "1.0", Host: "", - BasePath: "", - Schemes: []string{}, - Title: "", - Description: "", + BasePath: "/api/", + Schemes: []string{"http"}, + Title: "Easywish client API", + Description: "Easy and feature-rich wishlist.", InfoInstanceName: "swagger", SwaggerTemplate: docTemplate, LeftDelim: "{{", diff --git a/backend/docs/swagger.json b/backend/docs/swagger.json index 170b194..82c6c89 100644 --- a/backend/docs/swagger.json +++ b/backend/docs/swagger.json @@ -1,9 +1,39 @@ { + "schemes": [ + "http" + ], "swagger": "2.0", "info": { - "contact": {} + "description": "Easy and feature-rich wishlist.", + "title": "Easywish client API", + "contact": {}, + "license": { + "name": "GPL 3.0" + }, + "version": "1.0" }, + "basePath": "/api/", "paths": { + "/account/changePassword": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Change account password", + "responses": {} + } + }, "/auth/login": { "post": { "consumes": [ @@ -94,6 +124,93 @@ "responses": {} } }, + "/profile/me": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Profile" + ], + "summary": "Get own profile when authorized", + "responses": {} + } + }, + "/profile/privacy": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Profile" + ], + "summary": "Get profile privacy settings", + "responses": {} + }, + "patch": { + "security": [ + { + "JWT": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Profile" + ], + "summary": "Update profile privacy settings", + "responses": {} + } + }, + "/profile/{username}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Profile" + ], + "summary": "Get someone's profile details", + "parameters": [ + { + "type": "string", + "description": "Username", + "name": "username", + "in": "path", + "required": true + } + ], + "responses": {} + } + }, "/service/health": { "get": { "description": "Used internally for checking service health", @@ -127,5 +244,12 @@ } } } + }, + "securityDefinitions": { + "JWT": { + "type": "apiKey", + "name": "Authorization", + "in": "header" + } } } \ No newline at end of file diff --git a/backend/docs/swagger.yaml b/backend/docs/swagger.yaml index 7914358..f58f691 100644 --- a/backend/docs/swagger.yaml +++ b/backend/docs/swagger.yaml @@ -1,3 +1,4 @@ +basePath: /api/ definitions: controllers.HealthStatus: properties: @@ -6,7 +7,24 @@ definitions: type: object info: contact: {} + description: Easy and feature-rich wishlist. + license: + name: GPL 3.0 + title: Easywish client API + version: "1.0" paths: + /account/changePassword: + put: + consumes: + - application/json + produces: + - application/json + responses: {} + security: + - JWT: [] + summary: Change account password + tags: + - Account /auth/login: post: consumes: @@ -68,6 +86,59 @@ paths: summary: Confirm with code, finish creating the account tags: - Auth + /profile/{username}: + get: + consumes: + - application/json + parameters: + - description: Username + in: path + name: username + required: true + type: string + produces: + - application/json + responses: {} + security: + - JWT: [] + summary: Get someone's profile details + tags: + - Profile + /profile/me: + get: + consumes: + - application/json + produces: + - application/json + responses: {} + security: + - JWT: [] + summary: Get own profile when authorized + tags: + - Profile + /profile/privacy: + get: + consumes: + - application/json + produces: + - application/json + responses: {} + security: + - JWT: [] + summary: Get profile privacy settings + tags: + - Profile + patch: + consumes: + - application/json + produces: + - application/json + responses: {} + security: + - JWT: [] + summary: Update profile privacy settings + tags: + - Profile /service/health: get: consumes: @@ -83,4 +154,11 @@ paths: summary: Get health status tags: - Service +schemes: +- http +securityDefinitions: + JWT: + in: header + name: Authorization + type: apiKey swagger: "2.0" diff --git a/backend/internal/controllers/account.go b/backend/internal/controllers/account.go new file mode 100644 index 0000000..210c562 --- /dev/null +++ b/backend/internal/controllers/account.go @@ -0,0 +1,18 @@ +package controllers + +import ( + "net/http" + + "github.com/gin-gonic/gin" +) + +// @Summary Change account password +// @Tags Account +// @Accept json +// @Produce json +// @Security JWT +// @Router /account/changePassword [put] +func ChangePassword(c *gin.Context) { + c.Status(http.StatusNotImplemented) +} + diff --git a/backend/internal/controllers/profile.go b/backend/internal/controllers/profile.go new file mode 100644 index 0000000..5cd8321 --- /dev/null +++ b/backend/internal/controllers/profile.go @@ -0,0 +1,65 @@ +package controllers + +import ( + "net/http" + + "github.com/gin-gonic/gin" +) + +// @Summary Get someone's profile details +// @Tags Profile +// @Accept json +// @Produce json +// @Param username path string true "Username" +// @Security JWT +// @Router /profile/{username} [get] +func GetProfile(c *gin.Context) { + + username := c.Param("username") + + if username == "" { + c.JSON(http.StatusBadRequest, gin.H{ + "error": "Username cannot be empty", + }) + return + } + + c.JSON(http.StatusNotImplemented, gin.H{ + "username": username, + }) +} + +// @Summary Get own profile when authorized +// @Tags Profile +// @Accept json +// @Produce json +// @Security JWT +// @Router /profile/me [get] +func GetOwnProfile(c *gin.Context) { + + username := "Gregory House" + + c.JSON(http.StatusNotImplemented, gin.H{ + "username": username, + }) +} + +// @Summary Get profile privacy settings +// @Tags Profile +// @Accept json +// @Produce json +// @Security JWT +// @Router /profile/privacy [get] +func GetPrivacySettings(c *gin.Context) { + c.Status(http.StatusNotImplemented) +} + +// @Summary Update profile privacy settings +// @Tags Profile +// @Accept json +// @Produce json +// @Security JWT +// @Router /profile/privacy [patch] +func UpdatePrivacySettings(c *gin.Context) { + c.Status(http.StatusNotImplemented) +} diff --git a/backend/internal/routes/setup.go b/backend/internal/routes/setup.go index 3b371f2..4f18533 100644 --- a/backend/internal/routes/setup.go +++ b/backend/internal/routes/setup.go @@ -23,6 +23,19 @@ func SetupRoutes(r *gin.Engine) *gin.Engine { authGroup.POST("/passwordResetBegin", controllers.PasswordResetBegin) authGroup.POST("/passwordResetComplete", controllers.PasswordResetComplete) } + + accountGroup := apiGroup.Group("/account") + { + accountGroup.PUT("/changePassword", controllers.ChangePassword) + } + + profileGroup := apiGroup.Group("/profile") + { + profileGroup.GET("/:username", controllers.GetProfile) + profileGroup.GET("/me", controllers.GetOwnProfile) + profileGroup.GET("/privacy", controllers.GetPrivacySettings) + profileGroup.PATCH("/privacy", controllers.UpdatePrivacySettings) + } } return r