From 2119f49b9b7f3ee90fe73f54f56e8f0258b3d014 Mon Sep 17 00:00:00 2001 From: "n.nakhostin" Date: Sun, 10 Aug 2025 19:06:20 +0330 Subject: [PATCH] Refactor health check and user management endpoints for improved structure and clarity - Replaced the existing health check endpoint with a new handler at `/admin/v1/health` to align with the updated API structure. - Introduced a dedicated `health.go` file to encapsulate health check logic and response formatting. - Updated Swagger documentation to reflect the new health check endpoint and its response structure. - Refined user management routes to enhance clarity and maintainability, including changes to login, logout, and profile management endpoints. - Ensured all user-related endpoints are now prefixed appropriately and documented in Swagger for better API usability. --- cmd/web/bootstrap.go | 8 +- cmd/web/docs/docs.go | 909 ++++++++++++++++++++------------------ cmd/web/docs/swagger.json | 909 ++++++++++++++++++++------------------ cmd/web/docs/swagger.yaml | 575 +++++++++++++----------- cmd/web/health.go | 30 ++ cmd/web/main.go | 34 +- internal/user/handler.go | 70 +-- 7 files changed, 1345 insertions(+), 1190 deletions(-) create mode 100644 cmd/web/health.go diff --git a/cmd/web/bootstrap.go b/cmd/web/bootstrap.go index 768e303..2756073 100644 --- a/cmd/web/bootstrap.go +++ b/cmd/web/bootstrap.go @@ -116,13 +116,7 @@ func initHTTPServer(conf infra.Config, log logger.Logger) *echo.Echo { }) // Add health check endpoint - e.GET("/health", func(c echo.Context) error { - return c.JSON(http.StatusOK, map[string]interface{}{ - "status": "healthy", - "time": time.Now().Unix(), - "version": "1.0.0", - }) - }) + e.GET("/admin/v1/health", healthHandler) // Add Swagger documentation endpoint e.GET("/swagger/*", echoSwagger.WrapHandler) diff --git a/cmd/web/docs/docs.go b/cmd/web/docs/docs.go index 2c47e2e..730915d 100644 --- a/cmd/web/docs/docs.go +++ b/cmd/web/docs/docs.go @@ -24,7 +24,426 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { - "/users/admin": { + "/change-password": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Change current user password", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Change password", + "parameters": [ + { + "description": "Password change data", + "name": "password", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/user.ChangePasswordForm" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + } + }, + "/health": { + "get": { + "description": "Get server health status", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Health" + ], + "summary": "Health check", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/main.HealthResponse" + } + } + } + } + }, + "/login": { + "post": { + "description": "Authenticate user with username and password", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Authorization" + ], + "summary": "Login user", + "parameters": [ + { + "description": "Login credentials", + "name": "login", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/user.LoginForm" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/user.AuthResponse" + } + } + } + ] + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + } + }, + "/logout": { + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Logout current user and invalidate tokens", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Logout user", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + } + }, + "/profile": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get current user profile information", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user profile", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/user.UserResponse" + } + } + } + ] + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + }, + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Update current user profile information", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Update user profile", + "parameters": [ + { + "description": "Profile update data", + "name": "profile", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/user.UpdateUserForm" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/user.UserResponse" + } + } + } + ] + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + } + }, + "/refresh-token": { + "post": { + "description": "Refresh access token using refresh token", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Authorization" + ], + "summary": "Refresh access token", + "parameters": [ + { + "description": "Refresh token", + "name": "refresh", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/user.RefreshTokenForm" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/user.AuthResponse" + } + } + } + ] + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + } + }, + "/reset-password": { + "post": { + "description": "Send password reset email to user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Authorization" + ], + "summary": "Reset password", + "parameters": [ + { + "description": "Password reset request", + "name": "reset", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/user.ResetPasswordForm" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + } + }, + "/users": { "get": { "security": [ { @@ -39,7 +458,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "Users" ], "summary": "List users", "parameters": [ @@ -151,7 +570,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "Users" ], "summary": "Create user", "parameters": [ @@ -211,7 +630,7 @@ const docTemplate = `{ } } }, - "/users/admin/company/{company_id}": { + "/users/company/{company_id}": { "get": { "security": [ { @@ -226,7 +645,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "Users" ], "summary": "Get users by company ID", "parameters": [ @@ -252,9 +671,22 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", + "description": "Users with pagination metadata", "schema": { - "$ref": "#/definitions/response.APIResponse" + "allOf": [ + { + "$ref": "#/definitions/response.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": true + } + } + } + ] } }, "400": { @@ -284,7 +716,7 @@ const docTemplate = `{ } } }, - "/users/admin/role/{role}": { + "/users/role/{role}": { "get": { "security": [ { @@ -299,7 +731,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "Users" ], "summary": "Get users by role", "parameters": [ @@ -325,9 +757,22 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", + "description": "Users with pagination metadata", "schema": { - "$ref": "#/definitions/response.APIResponse" + "allOf": [ + { + "$ref": "#/definitions/response.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": true + } + } + } + ] } }, "400": { @@ -357,7 +802,7 @@ const docTemplate = `{ } } }, - "/users/admin/{id}": { + "/users/{id}": { "get": { "security": [ { @@ -372,7 +817,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "Users" ], "summary": "Get user by ID", "parameters": [ @@ -449,7 +894,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "Users" ], "summary": "Update user", "parameters": [ @@ -535,7 +980,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "Users" ], "summary": "Delete user", "parameters": [ @@ -587,7 +1032,7 @@ const docTemplate = `{ } } }, - "/users/admin/{id}/role": { + "/users/{id}/role": { "put": { "security": [ { @@ -602,7 +1047,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "Users" ], "summary": "Update user role", "parameters": [ @@ -663,7 +1108,7 @@ const docTemplate = `{ } } }, - "/users/admin/{id}/status": { + "/users/{id}/status": { "put": { "security": [ { @@ -678,7 +1123,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "users" + "Users" ], "summary": "Update user status", "parameters": [ @@ -738,405 +1183,23 @@ const docTemplate = `{ } } } - }, - "/users/change-password": { - "put": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Change current user password", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Change password", - "parameters": [ - { - "description": "Password change data", - "name": "password", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/user.ChangePasswordForm" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - } - } - } - }, - "/users/login": { - "post": { - "description": "Authenticate user with email/username and password", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Login user", - "parameters": [ - { - "description": "Login credentials", - "name": "login", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/user.LoginForm" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/response.APIResponse" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/user.AuthResponse" - } - } - } - ] - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - } - } - } - }, - "/users/logout": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Logout current user and invalidate tokens", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Logout user", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - } - } - } - }, - "/users/profile": { - "get": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Get current user profile information", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Get user profile", - "responses": { - "200": { - "description": "OK", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/response.APIResponse" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/user.UserResponse" - } - } - } - ] - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - } - } - }, - "put": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Update current user profile information", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Update user profile", - "parameters": [ - { - "description": "Profile update data", - "name": "profile", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/user.UpdateUserForm" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/response.APIResponse" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/user.UserResponse" - } - } - } - ] - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - } - } - } - }, - "/users/refresh-token": { - "post": { - "description": "Refresh access token using refresh token", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Refresh access token", - "parameters": [ - { - "description": "Refresh token", - "name": "refresh", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/user.RefreshTokenForm" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/response.APIResponse" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/user.AuthResponse" - } - } - } - ] - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - } - } - } - }, - "/users/reset-password": { - "post": { - "description": "Send password reset email to user", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Reset password", - "parameters": [ - { - "description": "Password reset request", - "name": "reset", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/user.ResetPasswordForm" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - } - } - } } }, "definitions": { + "main.HealthResponse": { + "type": "object", + "properties": { + "status": { + "type": "string" + }, + "time": { + "type": "integer" + }, + "version": { + "type": "string" + } + } + }, "response.APIError": { "type": "object", "properties": { @@ -1420,20 +1483,16 @@ const docTemplate = `{ }, "tags": [ { - "description": "Customer management operations", - "name": "customers" + "description": "User management operations including authentication, profile management, and admin operations", + "name": "Users" }, { - "description": "User management operations", - "name": "users" + "description": "Authentication operations including login, logout, and token management", + "name": "Authorization" }, { "description": "Health check operations", - "name": "health" - }, - { - "description": "Authentication operations", - "name": "auth" + "name": "Health" } ] }` @@ -1442,7 +1501,7 @@ const docTemplate = `{ var SwaggerInfo = &swag.Spec{ Version: "1.0.0", Host: "localhost:8081", - BasePath: "/api/v1", + BasePath: "/admin/v1", Schemes: []string{}, Title: "Tender Management API", Description: "This is the API documentation for the Tender Management System.", diff --git a/cmd/web/docs/swagger.json b/cmd/web/docs/swagger.json index ffdb6eb..4d6022d 100644 --- a/cmd/web/docs/swagger.json +++ b/cmd/web/docs/swagger.json @@ -16,9 +16,428 @@ "version": "1.0.0" }, "host": "localhost:8081", - "basePath": "/api/v1", + "basePath": "/admin/v1", "paths": { - "/users/admin": { + "/change-password": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Change current user password", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Change password", + "parameters": [ + { + "description": "Password change data", + "name": "password", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/user.ChangePasswordForm" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + } + }, + "/health": { + "get": { + "description": "Get server health status", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Health" + ], + "summary": "Health check", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/main.HealthResponse" + } + } + } + } + }, + "/login": { + "post": { + "description": "Authenticate user with username and password", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Authorization" + ], + "summary": "Login user", + "parameters": [ + { + "description": "Login credentials", + "name": "login", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/user.LoginForm" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/user.AuthResponse" + } + } + } + ] + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + } + }, + "/logout": { + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Logout current user and invalidate tokens", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Logout user", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + } + }, + "/profile": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get current user profile information", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user profile", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/user.UserResponse" + } + } + } + ] + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + }, + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Update current user profile information", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Update user profile", + "parameters": [ + { + "description": "Profile update data", + "name": "profile", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/user.UpdateUserForm" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/user.UserResponse" + } + } + } + ] + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + } + }, + "/refresh-token": { + "post": { + "description": "Refresh access token using refresh token", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Authorization" + ], + "summary": "Refresh access token", + "parameters": [ + { + "description": "Refresh token", + "name": "refresh", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/user.RefreshTokenForm" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/user.AuthResponse" + } + } + } + ] + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + } + }, + "/reset-password": { + "post": { + "description": "Send password reset email to user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Authorization" + ], + "summary": "Reset password", + "parameters": [ + { + "description": "Password reset request", + "name": "reset", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/user.ResetPasswordForm" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + } + }, + "/users": { "get": { "security": [ { @@ -33,7 +452,7 @@ "application/json" ], "tags": [ - "users" + "Users" ], "summary": "List users", "parameters": [ @@ -145,7 +564,7 @@ "application/json" ], "tags": [ - "users" + "Users" ], "summary": "Create user", "parameters": [ @@ -205,7 +624,7 @@ } } }, - "/users/admin/company/{company_id}": { + "/users/company/{company_id}": { "get": { "security": [ { @@ -220,7 +639,7 @@ "application/json" ], "tags": [ - "users" + "Users" ], "summary": "Get users by company ID", "parameters": [ @@ -246,9 +665,22 @@ ], "responses": { "200": { - "description": "OK", + "description": "Users with pagination metadata", "schema": { - "$ref": "#/definitions/response.APIResponse" + "allOf": [ + { + "$ref": "#/definitions/response.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": true + } + } + } + ] } }, "400": { @@ -278,7 +710,7 @@ } } }, - "/users/admin/role/{role}": { + "/users/role/{role}": { "get": { "security": [ { @@ -293,7 +725,7 @@ "application/json" ], "tags": [ - "users" + "Users" ], "summary": "Get users by role", "parameters": [ @@ -319,9 +751,22 @@ ], "responses": { "200": { - "description": "OK", + "description": "Users with pagination metadata", "schema": { - "$ref": "#/definitions/response.APIResponse" + "allOf": [ + { + "$ref": "#/definitions/response.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": true + } + } + } + ] } }, "400": { @@ -351,7 +796,7 @@ } } }, - "/users/admin/{id}": { + "/users/{id}": { "get": { "security": [ { @@ -366,7 +811,7 @@ "application/json" ], "tags": [ - "users" + "Users" ], "summary": "Get user by ID", "parameters": [ @@ -443,7 +888,7 @@ "application/json" ], "tags": [ - "users" + "Users" ], "summary": "Update user", "parameters": [ @@ -529,7 +974,7 @@ "application/json" ], "tags": [ - "users" + "Users" ], "summary": "Delete user", "parameters": [ @@ -581,7 +1026,7 @@ } } }, - "/users/admin/{id}/role": { + "/users/{id}/role": { "put": { "security": [ { @@ -596,7 +1041,7 @@ "application/json" ], "tags": [ - "users" + "Users" ], "summary": "Update user role", "parameters": [ @@ -657,7 +1102,7 @@ } } }, - "/users/admin/{id}/status": { + "/users/{id}/status": { "put": { "security": [ { @@ -672,7 +1117,7 @@ "application/json" ], "tags": [ - "users" + "Users" ], "summary": "Update user status", "parameters": [ @@ -732,405 +1177,23 @@ } } } - }, - "/users/change-password": { - "put": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Change current user password", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Change password", - "parameters": [ - { - "description": "Password change data", - "name": "password", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/user.ChangePasswordForm" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - } - } - } - }, - "/users/login": { - "post": { - "description": "Authenticate user with email/username and password", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Login user", - "parameters": [ - { - "description": "Login credentials", - "name": "login", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/user.LoginForm" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/response.APIResponse" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/user.AuthResponse" - } - } - } - ] - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - } - } - } - }, - "/users/logout": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Logout current user and invalidate tokens", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Logout user", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - } - } - } - }, - "/users/profile": { - "get": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Get current user profile information", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Get user profile", - "responses": { - "200": { - "description": "OK", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/response.APIResponse" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/user.UserResponse" - } - } - } - ] - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - } - } - }, - "put": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Update current user profile information", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Update user profile", - "parameters": [ - { - "description": "Profile update data", - "name": "profile", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/user.UpdateUserForm" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/response.APIResponse" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/user.UserResponse" - } - } - } - ] - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - } - } - } - }, - "/users/refresh-token": { - "post": { - "description": "Refresh access token using refresh token", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Refresh access token", - "parameters": [ - { - "description": "Refresh token", - "name": "refresh", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/user.RefreshTokenForm" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/response.APIResponse" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/user.AuthResponse" - } - } - } - ] - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - } - } - } - }, - "/users/reset-password": { - "post": { - "description": "Send password reset email to user", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Reset password", - "parameters": [ - { - "description": "Password reset request", - "name": "reset", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/user.ResetPasswordForm" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - } - } - } } }, "definitions": { + "main.HealthResponse": { + "type": "object", + "properties": { + "status": { + "type": "string" + }, + "time": { + "type": "integer" + }, + "version": { + "type": "string" + } + } + }, "response.APIError": { "type": "object", "properties": { @@ -1414,20 +1477,16 @@ }, "tags": [ { - "description": "Customer management operations", - "name": "customers" + "description": "User management operations including authentication, profile management, and admin operations", + "name": "Users" }, { - "description": "User management operations", - "name": "users" + "description": "Authentication operations including login, logout, and token management", + "name": "Authorization" }, { "description": "Health check operations", - "name": "health" - }, - { - "description": "Authentication operations", - "name": "auth" + "name": "Health" } ] } \ No newline at end of file diff --git a/cmd/web/docs/swagger.yaml b/cmd/web/docs/swagger.yaml index d53749b..74261b3 100644 --- a/cmd/web/docs/swagger.yaml +++ b/cmd/web/docs/swagger.yaml @@ -1,5 +1,14 @@ -basePath: /api/v1 +basePath: /admin/v1 definitions: + main.HealthResponse: + properties: + status: + type: string + time: + type: integer + version: + type: string + type: object response.APIError: properties: code: @@ -191,7 +200,265 @@ info: title: Tender Management API version: 1.0.0 paths: - /users/admin: + /change-password: + put: + consumes: + - application/json + description: Change current user password + parameters: + - description: Password change data + in: body + name: password + required: true + schema: + $ref: '#/definitions/user.ChangePasswordForm' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.APIResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.APIResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.APIResponse' + security: + - BearerAuth: [] + summary: Change password + tags: + - Users + /health: + get: + consumes: + - application/json + description: Get server health status + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/main.HealthResponse' + summary: Health check + tags: + - Health + /login: + post: + consumes: + - application/json + description: Authenticate user with username and password + parameters: + - description: Login credentials + in: body + name: login + required: true + schema: + $ref: '#/definitions/user.LoginForm' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/response.APIResponse' + - properties: + data: + $ref: '#/definitions/user.AuthResponse' + type: object + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.APIResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.APIResponse' + summary: Login user + tags: + - Authorization + /logout: + delete: + consumes: + - application/json + description: Logout current user and invalidate tokens + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.APIResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.APIResponse' + security: + - BearerAuth: [] + summary: Logout user + tags: + - Users + /profile: + get: + consumes: + - application/json + description: Get current user profile information + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/response.APIResponse' + - properties: + data: + $ref: '#/definitions/user.UserResponse' + type: object + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.APIResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/response.APIResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.APIResponse' + security: + - BearerAuth: [] + summary: Get user profile + tags: + - Users + put: + consumes: + - application/json + description: Update current user profile information + parameters: + - description: Profile update data + in: body + name: profile + required: true + schema: + $ref: '#/definitions/user.UpdateUserForm' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/response.APIResponse' + - properties: + data: + $ref: '#/definitions/user.UserResponse' + type: object + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.APIResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.APIResponse' + security: + - BearerAuth: [] + summary: Update user profile + tags: + - Users + /refresh-token: + post: + consumes: + - application/json + description: Refresh access token using refresh token + parameters: + - description: Refresh token + in: body + name: refresh + required: true + schema: + $ref: '#/definitions/user.RefreshTokenForm' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/response.APIResponse' + - properties: + data: + $ref: '#/definitions/user.AuthResponse' + type: object + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.APIResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.APIResponse' + summary: Refresh access token + tags: + - Authorization + /reset-password: + post: + consumes: + - application/json + description: Send password reset email to user + parameters: + - description: Password reset request + in: body + name: reset + required: true + schema: + $ref: '#/definitions/user.ResetPasswordForm' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.APIResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.APIResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.APIResponse' + summary: Reset password + tags: + - Authorization + /users: get: consumes: - application/json @@ -261,7 +528,7 @@ paths: - BearerAuth: [] summary: List users tags: - - users + - Users post: consumes: - application/json @@ -305,8 +572,8 @@ paths: - BearerAuth: [] summary: Create user tags: - - users - /users/admin/{id}: + - Users + /users/{id}: delete: consumes: - application/json @@ -348,7 +615,7 @@ paths: - BearerAuth: [] summary: Delete user tags: - - users + - Users get: consumes: - application/json @@ -395,7 +662,7 @@ paths: - BearerAuth: [] summary: Get user by ID tags: - - users + - Users put: consumes: - application/json @@ -448,8 +715,8 @@ paths: - BearerAuth: [] summary: Update user tags: - - users - /users/admin/{id}/role: + - Users + /users/{id}/role: put: consumes: - application/json @@ -497,8 +764,8 @@ paths: - BearerAuth: [] summary: Update user role tags: - - users - /users/admin/{id}/status: + - Users + /users/{id}/status: put: consumes: - application/json @@ -546,8 +813,8 @@ paths: - BearerAuth: [] summary: Update user status tags: - - users - /users/admin/company/{company_id}: + - Users + /users/company/{company_id}: get: consumes: - application/json @@ -570,9 +837,15 @@ paths: - application/json responses: "200": - description: OK + description: Users with pagination metadata schema: - $ref: '#/definitions/response.APIResponse' + allOf: + - $ref: '#/definitions/response.APIResponse' + - properties: + data: + additionalProperties: true + type: object + type: object "400": description: Bad Request schema: @@ -593,8 +866,8 @@ paths: - BearerAuth: [] summary: Get users by company ID tags: - - users - /users/admin/role/{role}: + - Users + /users/role/{role}: get: consumes: - application/json @@ -617,9 +890,15 @@ paths: - application/json responses: "200": - description: OK + description: Users with pagination metadata schema: - $ref: '#/definitions/response.APIResponse' + allOf: + - $ref: '#/definitions/response.APIResponse' + - properties: + data: + additionalProperties: true + type: object + type: object "400": description: Bad Request schema: @@ -640,250 +919,7 @@ paths: - BearerAuth: [] summary: Get users by role tags: - - users - /users/change-password: - put: - consumes: - - application/json - description: Change current user password - parameters: - - description: Password change data - in: body - name: password - required: true - schema: - $ref: '#/definitions/user.ChangePasswordForm' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.APIResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/response.APIResponse' - "401": - description: Unauthorized - schema: - $ref: '#/definitions/response.APIResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/response.APIResponse' - security: - - BearerAuth: [] - summary: Change password - tags: - - users - /users/login: - post: - consumes: - - application/json - description: Authenticate user with email/username and password - parameters: - - description: Login credentials - in: body - name: login - required: true - schema: - $ref: '#/definitions/user.LoginForm' - produces: - - application/json - responses: - "200": - description: OK - schema: - allOf: - - $ref: '#/definitions/response.APIResponse' - - properties: - data: - $ref: '#/definitions/user.AuthResponse' - type: object - "400": - description: Bad Request - schema: - $ref: '#/definitions/response.APIResponse' - "401": - description: Unauthorized - schema: - $ref: '#/definitions/response.APIResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/response.APIResponse' - summary: Login user - tags: - - users - /users/logout: - post: - consumes: - - application/json - description: Logout current user and invalidate tokens - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.APIResponse' - "401": - description: Unauthorized - schema: - $ref: '#/definitions/response.APIResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/response.APIResponse' - security: - - BearerAuth: [] - summary: Logout user - tags: - - users - /users/profile: - get: - consumes: - - application/json - description: Get current user profile information - produces: - - application/json - responses: - "200": - description: OK - schema: - allOf: - - $ref: '#/definitions/response.APIResponse' - - properties: - data: - $ref: '#/definitions/user.UserResponse' - type: object - "401": - description: Unauthorized - schema: - $ref: '#/definitions/response.APIResponse' - "404": - description: Not Found - schema: - $ref: '#/definitions/response.APIResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/response.APIResponse' - security: - - BearerAuth: [] - summary: Get user profile - tags: - - users - put: - consumes: - - application/json - description: Update current user profile information - parameters: - - description: Profile update data - in: body - name: profile - required: true - schema: - $ref: '#/definitions/user.UpdateUserForm' - produces: - - application/json - responses: - "200": - description: OK - schema: - allOf: - - $ref: '#/definitions/response.APIResponse' - - properties: - data: - $ref: '#/definitions/user.UserResponse' - type: object - "400": - description: Bad Request - schema: - $ref: '#/definitions/response.APIResponse' - "401": - description: Unauthorized - schema: - $ref: '#/definitions/response.APIResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/response.APIResponse' - security: - - BearerAuth: [] - summary: Update user profile - tags: - - users - /users/refresh-token: - post: - consumes: - - application/json - description: Refresh access token using refresh token - parameters: - - description: Refresh token - in: body - name: refresh - required: true - schema: - $ref: '#/definitions/user.RefreshTokenForm' - produces: - - application/json - responses: - "200": - description: OK - schema: - allOf: - - $ref: '#/definitions/response.APIResponse' - - properties: - data: - $ref: '#/definitions/user.AuthResponse' - type: object - "400": - description: Bad Request - schema: - $ref: '#/definitions/response.APIResponse' - "401": - description: Unauthorized - schema: - $ref: '#/definitions/response.APIResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/response.APIResponse' - summary: Refresh access token - tags: - - users - /users/reset-password: - post: - consumes: - - application/json - description: Send password reset email to user - parameters: - - description: Password reset request - in: body - name: reset - required: true - schema: - $ref: '#/definitions/user.ResetPasswordForm' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.APIResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/response.APIResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/response.APIResponse' - summary: Reset password - tags: - - users + - Users securityDefinitions: BearerAuth: description: Type "Bearer" followed by a space and JWT token. @@ -892,11 +928,10 @@ securityDefinitions: type: apiKey swagger: "2.0" tags: -- description: Customer management operations - name: customers -- description: User management operations - name: users +- description: User management operations including authentication, profile management, + and admin operations + name: Users +- description: Authentication operations including login, logout, and token management + name: Authorization - description: Health check operations - name: health -- description: Authentication operations - name: auth + name: Health diff --git a/cmd/web/health.go b/cmd/web/health.go new file mode 100644 index 0000000..73d8332 --- /dev/null +++ b/cmd/web/health.go @@ -0,0 +1,30 @@ +package main + +import ( + "net/http" + "time" + + "github.com/labstack/echo/v4" +) + +// @Summary Health check +// @Description Get server health status +// @Tags Health +// @Accept json +// @Produce json +// @Success 200 {object} HealthResponse +// @Router /health [get] +func healthHandler(c echo.Context) error { + return c.JSON(http.StatusOK, HealthResponse{ + Status: "healthy", + Time: time.Now().Unix(), + Version: "1.0.0", + }) +} + +// HealthResponse represents the health check response +type HealthResponse struct { + Status string `json:"status"` + Time int64 `json:"time"` + Version string `json:"version"` +} diff --git a/cmd/web/main.go b/cmd/web/main.go index cdf8b31..9532887 100644 --- a/cmd/web/main.go +++ b/cmd/web/main.go @@ -1,22 +1,3 @@ -// Package main Tender Management API -// -// This is the API documentation for the Tender Management System. -// -// Schemes: http, https -// Host: localhost:8081 -// BasePath: /api/v1 -// Version: 1.0.0 -// -// Consumes: -// - application/json -// -// Produces: -// - application/json -// -// Security: -// - bearer -// -// swagger:meta package main // @title Tender Management API @@ -32,25 +13,22 @@ package main // @license.url http://www.apache.org/licenses/LICENSE-2.0.html // @host localhost:8081 -// @BasePath /api/v1 +// @BasePath /admin/v1 // @securityDefinitions.apikey BearerAuth // @in header // @name Authorization // @description Type "Bearer" followed by a space and JWT token. -// @tag.name customers -// @tag.description Customer management operations +// @tag.name Users +// @tag.description User management operations including authentication, profile management, and admin operations -// @tag.name users -// @tag.description User management operations +// @tag.name Authorization +// @tag.description Authentication operations including login, logout, and token management -// @tag.name health +// @tag.name Health // @tag.description Health check operations -// @tag.name auth -// @tag.description Authentication operations - import ( "context" "fmt" diff --git a/internal/user/handler.go b/internal/user/handler.go index 457d8ea..c5d14fb 100644 --- a/internal/user/handler.go +++ b/internal/user/handler.go @@ -63,8 +63,8 @@ func (h *Handler) RegisterRoutes(e *echo.Echo) { // Login handles user login // @Summary Login user -// @Description Authenticate user with email/username and password -// @Tags users +// @Description Authenticate user with username and password +// @Tags Authorization // @Accept json // @Produce json // @Param login body LoginForm true "Login credentials" @@ -72,7 +72,7 @@ func (h *Handler) RegisterRoutes(e *echo.Echo) { // @Failure 400 {object} response.APIResponse // @Failure 401 {object} response.APIResponse // @Failure 500 {object} response.APIResponse -// @Router /users/login [post] +// @Router /login [post] func (h *Handler) Login(c echo.Context) error { form, err := response.Parse[LoginForm](c) if err != nil { @@ -91,7 +91,7 @@ func (h *Handler) Login(c echo.Context) error { // RefreshToken handles token refresh // @Summary Refresh access token // @Description Refresh access token using refresh token -// @Tags users +// @Tags Authorization // @Accept json // @Produce json // @Param refresh body RefreshTokenForm true "Refresh token" @@ -99,7 +99,7 @@ func (h *Handler) Login(c echo.Context) error { // @Failure 400 {object} response.APIResponse // @Failure 401 {object} response.APIResponse // @Failure 500 {object} response.APIResponse -// @Router /users/refresh-token [post] +// @Router /refresh-token [post] func (h *Handler) RefreshToken(c echo.Context) error { form, err := response.Parse[RefreshTokenForm](c) if err != nil { @@ -117,14 +117,14 @@ func (h *Handler) RefreshToken(c echo.Context) error { // ResetPassword handles password reset request // @Summary Reset password // @Description Send password reset email to user -// @Tags users +// @Tags Authorization // @Accept json // @Produce json // @Param reset body ResetPasswordForm true "Password reset request" // @Success 200 {object} response.APIResponse // @Failure 400 {object} response.APIResponse // @Failure 500 {object} response.APIResponse -// @Router /users/reset-password [post] +// @Router /reset-password [post] func (h *Handler) ResetPassword(c echo.Context) error { form, err := response.Parse[ResetPasswordForm](c) if err != nil { @@ -144,7 +144,7 @@ func (h *Handler) ResetPassword(c echo.Context) error { // GetProfile gets current user profile // @Summary Get user profile // @Description Get current user profile information -// @Tags users +// @Tags Users // @Accept json // @Produce json // @Security BearerAuth @@ -152,7 +152,7 @@ func (h *Handler) ResetPassword(c echo.Context) error { // @Failure 401 {object} response.APIResponse // @Failure 404 {object} response.APIResponse // @Failure 500 {object} response.APIResponse -// @Router /users/profile [get] +// @Router /profile [get] func (h *Handler) GetProfile(c echo.Context) error { // Extract user ID from JWT token context userID, err := GetUserIDFromContext(c) @@ -171,7 +171,7 @@ func (h *Handler) GetProfile(c echo.Context) error { // UpdateProfile updates current user profile // @Summary Update user profile // @Description Update current user profile information -// @Tags users +// @Tags Users // @Accept json // @Produce json // @Security BearerAuth @@ -180,7 +180,7 @@ func (h *Handler) GetProfile(c echo.Context) error { // @Failure 400 {object} response.APIResponse // @Failure 401 {object} response.APIResponse // @Failure 500 {object} response.APIResponse -// @Router /users/profile [put] +// @Router /profile [put] func (h *Handler) UpdateProfile(c echo.Context) error { // Extract user ID from JWT token context userID, err := GetUserIDFromContext(c) @@ -204,7 +204,7 @@ func (h *Handler) UpdateProfile(c echo.Context) error { // ChangePassword changes current user password // @Summary Change password // @Description Change current user password -// @Tags users +// @Tags Users // @Accept json // @Produce json // @Security BearerAuth @@ -213,7 +213,7 @@ func (h *Handler) UpdateProfile(c echo.Context) error { // @Failure 400 {object} response.APIResponse // @Failure 401 {object} response.APIResponse // @Failure 500 {object} response.APIResponse -// @Router /users/change-password [put] +// @Router /change-password [put] func (h *Handler) ChangePassword(c echo.Context) error { userID, err := GetUserIDFromContext(c) if err != nil { @@ -238,14 +238,14 @@ func (h *Handler) ChangePassword(c echo.Context) error { // Logout handles user logout // @Summary Logout user // @Description Logout current user and invalidate tokens -// @Tags users +// @Tags Users // @Accept json // @Produce json // @Security BearerAuth // @Success 200 {object} response.APIResponse // @Failure 401 {object} response.APIResponse // @Failure 500 {object} response.APIResponse -// @Router /users/logout [post] +// @Router /logout [delete] func (h *Handler) Logout(c echo.Context) error { // Extract user ID and access token from context userID, err := GetUserIDFromContext(c) @@ -271,7 +271,7 @@ func (h *Handler) Logout(c echo.Context) error { // CreateUser creates a new user (admin only) // @Summary Create user // @Description Create a new user (admin only) -// @Tags users +// @Tags Users // @Accept json // @Produce json // @Security BearerAuth @@ -281,7 +281,7 @@ func (h *Handler) Logout(c echo.Context) error { // @Failure 401 {object} response.APIResponse // @Failure 403 {object} response.APIResponse // @Failure 500 {object} response.APIResponse -// @Router /users/admin [post] +// @Router /users [post] func (h *Handler) CreateUser(c echo.Context) error { // Get current user ID from JWT token currentUserID, err := GetUserIDFromContext(c) @@ -311,7 +311,7 @@ func (h *Handler) CreateUser(c echo.Context) error { // ListUsers lists users with search and filters (admin only) // @Summary List users // @Description List users with search and filters (admin only) -// @Tags users +// @Tags Users // @Accept json // @Produce json // @Security BearerAuth @@ -328,7 +328,7 @@ func (h *Handler) CreateUser(c echo.Context) error { // @Failure 401 {object} response.APIResponse // @Failure 403 {object} response.APIResponse // @Failure 500 {object} response.APIResponse -// @Router /users/admin [get] +// @Router /users [get] func (h *Handler) ListUsers(c echo.Context) error { var form ListUsersForm if err := c.Bind(&form); err != nil { @@ -352,7 +352,7 @@ func (h *Handler) ListUsers(c echo.Context) error { // GetUserByID gets a user by ID (admin only) // @Summary Get user by ID // @Description Get user details by ID (admin only) -// @Tags users +// @Tags Users // @Accept json // @Produce json // @Security BearerAuth @@ -363,7 +363,7 @@ func (h *Handler) ListUsers(c echo.Context) error { // @Failure 403 {object} response.APIResponse // @Failure 404 {object} response.APIResponse // @Failure 500 {object} response.APIResponse -// @Router /users/admin/{id} [get] +// @Router /users/{id} [get] func (h *Handler) GetUserByID(c echo.Context) error { idStr := c.Param("id") userID, err := uuid.Parse(idStr) @@ -382,7 +382,7 @@ func (h *Handler) GetUserByID(c echo.Context) error { // UpdateUser updates a user (admin only) // @Summary Update user // @Description Update user information (admin only) -// @Tags users +// @Tags Users // @Accept json // @Produce json // @Security BearerAuth @@ -394,7 +394,7 @@ func (h *Handler) GetUserByID(c echo.Context) error { // @Failure 403 {object} response.APIResponse // @Failure 404 {object} response.APIResponse // @Failure 500 {object} response.APIResponse -// @Router /users/admin/{id} [put] +// @Router /users/{id} [put] func (h *Handler) UpdateUser(c echo.Context) error { // Extract user ID from JWT token context currentUserID, err := GetUserIDFromContext(c) @@ -430,7 +430,7 @@ func (h *Handler) UpdateUser(c echo.Context) error { // DeleteUser deletes a user (admin only) // @Summary Delete user // @Description Delete a user (admin only) -// @Tags users +// @Tags Users // @Accept json // @Produce json // @Security BearerAuth @@ -441,7 +441,7 @@ func (h *Handler) UpdateUser(c echo.Context) error { // @Failure 403 {object} response.APIResponse // @Failure 404 {object} response.APIResponse // @Failure 500 {object} response.APIResponse -// @Router /users/admin/{id} [delete] +// @Router /users/{id} [delete] func (h *Handler) DeleteUser(c echo.Context) error { // Extract user ID from JWT token context currentUserID, err := GetUserIDFromContext(c) @@ -468,7 +468,7 @@ func (h *Handler) DeleteUser(c echo.Context) error { // UpdateUserStatus updates user status (admin only) // @Summary Update user status // @Description Update user account status (admin only) -// @Tags users +// @Tags Users // @Accept json // @Produce json // @Security BearerAuth @@ -480,7 +480,7 @@ func (h *Handler) DeleteUser(c echo.Context) error { // @Failure 403 {object} response.APIResponse // @Failure 404 {object} response.APIResponse // @Failure 500 {object} response.APIResponse -// @Router /users/admin/{id}/status [put] +// @Router /users/{id}/status [put] func (h *Handler) UpdateUserStatus(c echo.Context) error { currentUserID, err := GetUserIDFromContext(c) if err != nil { @@ -517,7 +517,7 @@ func (h *Handler) UpdateUserStatus(c echo.Context) error { // UpdateUserRole updates user role (admin only) // @Summary Update user role // @Description Update user role (admin only) -// @Tags users +// @Tags Users // @Accept json // @Produce json // @Security BearerAuth @@ -529,7 +529,7 @@ func (h *Handler) UpdateUserStatus(c echo.Context) error { // @Failure 403 {object} response.APIResponse // @Failure 404 {object} response.APIResponse // @Failure 500 {object} response.APIResponse -// @Router /users/admin/{id}/role [put] +// @Router /users/{id}/role [put] func (h *Handler) UpdateUserRole(c echo.Context) error { // Extract user ID from JWT token context currentUserID, err := GetUserIDFromContext(c) @@ -567,19 +567,19 @@ func (h *Handler) UpdateUserRole(c echo.Context) error { // GetUsersByCompanyID gets users by company ID (admin only) // @Summary Get users by company ID // @Description Get users belonging to a specific company (admin only) -// @Tags users +// @Tags Users // @Accept json // @Produce json // @Security BearerAuth // @Param company_id path string true "Company ID" // @Param limit query int false "Limit results" // @Param offset query int false "Offset results" -// @Success 200 {object} response.APIResponse +// @Success 200 {object} response.APIResponse{data=map[string]interface{}} "Users with pagination metadata" // @Failure 400 {object} response.APIResponse // @Failure 401 {object} response.APIResponse // @Failure 403 {object} response.APIResponse // @Failure 500 {object} response.APIResponse -// @Router /users/admin/company/{company_id} [get] +// @Router /users/company/{company_id} [get] func (h *Handler) GetUsersByCompanyID(c echo.Context) error { companyIDStr := c.Param("company_id") companyID, err := uuid.Parse(companyIDStr) @@ -631,19 +631,19 @@ func (h *Handler) GetUsersByCompanyID(c echo.Context) error { // GetUsersByRole gets users by role (admin only) // @Summary Get users by role // @Description Get users with a specific role (admin only) -// @Tags users +// @Tags Users // @Accept json // @Produce json // @Security BearerAuth // @Param role path string true "User role" // @Param limit query int false "Limit results" // @Param offset query int false "Offset results" -// @Success 200 {object} response.APIResponse +// @Success 200 {object} response.APIResponse{data=map[string]interface{}} "Users with pagination metadata" // @Failure 400 {object} response.APIResponse // @Failure 401 {object} response.APIResponse // @Failure 403 {object} response.APIResponse // @Failure 500 {object} response.APIResponse -// @Router /users/admin/role/{role} [get] +// @Router /users/role/{role} [get] func (h *Handler) GetUsersByRole(c echo.Context) error { roleStr := c.Param("role") role := UserRole(roleStr)