Enhance cursor rules and add user management functionality
- Updated cursor rules to emphasize the importance of dependency injection and logging practices. - Introduced a new user management domain, including entities, services, handlers, and validation. - Implemented user authentication features such as login, registration, and role-based access control. - Added Redis integration for token management and caching. - Enhanced API documentation with Swagger for user-related endpoints. - Updated configuration to support new JWT settings and Redis connection parameters.
This commit is contained in:
Executable
BIN
Binary file not shown.
@@ -5,8 +5,10 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
"tm/infra"
|
||||
"tm/pkg/authorization"
|
||||
"tm/pkg/logger"
|
||||
"tm/pkg/mongo"
|
||||
"tm/pkg/redis"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
@@ -131,3 +133,53 @@ func initHTTPServer(conf infra.Config, log logger.Logger) *echo.Echo {
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
// Init Redis Connection Manager
|
||||
func initRedis(conf infra.RedisConfig, log logger.Logger) redis.Client {
|
||||
connectionConfig := &redis.Config{
|
||||
Host: conf.Host,
|
||||
Port: conf.Port,
|
||||
Password: conf.Password,
|
||||
DB: conf.DB,
|
||||
PoolSize: conf.PoolSize,
|
||||
}
|
||||
|
||||
redisClient, err := redis.NewClient(connectionConfig, log)
|
||||
if err != nil {
|
||||
log.Error("Failed to initialize Redis connection", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"host": conf.Host,
|
||||
"port": conf.Port,
|
||||
})
|
||||
panic(fmt.Sprintf("Failed to initialize Redis connection: %v", err))
|
||||
}
|
||||
|
||||
log.Info("Redis connection manager initialized successfully", map[string]interface{}{
|
||||
"host": conf.Host,
|
||||
"port": conf.Port,
|
||||
"pool_size": conf.PoolSize,
|
||||
})
|
||||
|
||||
return redisClient
|
||||
}
|
||||
|
||||
// Init Authorization Service
|
||||
func initAuthorizationService(conf infra.JWTConfig, redisClient redis.Client, log logger.Logger) authorization.AuthorizationService {
|
||||
authConfig := &authorization.AuthorizationConfig{
|
||||
AccessTokenSecret: conf.AccessSecret,
|
||||
RefreshTokenSecret: conf.RefreshSecret,
|
||||
AccessTokenExpiry: time.Duration(conf.AccessExpiresIn) * time.Second,
|
||||
RefreshTokenExpiry: time.Duration(conf.RefreshExpiresIn) * time.Second,
|
||||
Issuer: "tender-management-system",
|
||||
Audience: "tender-management-users",
|
||||
}
|
||||
|
||||
authService := authorization.NewAuthorizationService(authConfig, log, redisClient)
|
||||
|
||||
log.Info("Authorization service initialized successfully", map[string]interface{}{
|
||||
"access_expires_in": conf.AccessExpiresIn,
|
||||
"refresh_expires_in": conf.RefreshExpiresIn,
|
||||
})
|
||||
|
||||
return authService
|
||||
}
|
||||
|
||||
+4
-3
@@ -38,9 +38,10 @@ search:
|
||||
|
||||
auth:
|
||||
jwt:
|
||||
secret: "your-super-secret-key"
|
||||
access_token_duration: "24h"
|
||||
refresh_token_duration: "168h" # 7 days
|
||||
access_secret: "your-super-secret-access-token-key-here-make-it-long-and-secure"
|
||||
refresh_secret: "your-super-secret-refresh-token-key-here-make-it-long-and-secure"
|
||||
access_expires_in: 3600 # 1 hour in seconds
|
||||
refresh_expires_in: 2592000 # 30 days in seconds
|
||||
|
||||
ai:
|
||||
openai:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -183,6 +183,149 @@ definitions:
|
||||
total:
|
||||
type: integer
|
||||
type: object
|
||||
user.AuthResponse:
|
||||
properties:
|
||||
access_token:
|
||||
type: string
|
||||
expires_at:
|
||||
type: integer
|
||||
refresh_token:
|
||||
type: string
|
||||
user:
|
||||
$ref: '#/definitions/user.UserResponse'
|
||||
type: object
|
||||
user.ChangePasswordForm:
|
||||
properties:
|
||||
new_password:
|
||||
type: string
|
||||
old_password:
|
||||
type: string
|
||||
type: object
|
||||
user.CreateUserForm:
|
||||
properties:
|
||||
company_id:
|
||||
type: string
|
||||
department:
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
full_name:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
phone:
|
||||
type: string
|
||||
position:
|
||||
type: string
|
||||
profile_image:
|
||||
type: string
|
||||
role:
|
||||
type: string
|
||||
username:
|
||||
type: string
|
||||
type: object
|
||||
user.LoginForm:
|
||||
properties:
|
||||
email_or_username:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
type: object
|
||||
user.RefreshTokenForm:
|
||||
properties:
|
||||
refresh_token:
|
||||
type: string
|
||||
type: object
|
||||
user.ResetPasswordForm:
|
||||
properties:
|
||||
email:
|
||||
type: string
|
||||
type: object
|
||||
user.UpdateUserForm:
|
||||
properties:
|
||||
company_id:
|
||||
type: string
|
||||
department:
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
full_name:
|
||||
type: string
|
||||
phone:
|
||||
type: string
|
||||
position:
|
||||
type: string
|
||||
profile_image:
|
||||
type: string
|
||||
role:
|
||||
type: string
|
||||
status:
|
||||
type: string
|
||||
username:
|
||||
type: string
|
||||
type: object
|
||||
user.UpdateUserRoleForm:
|
||||
properties:
|
||||
role:
|
||||
type: string
|
||||
type: object
|
||||
user.UpdateUserStatusForm:
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
type: object
|
||||
user.UserListResponse:
|
||||
properties:
|
||||
limit:
|
||||
type: integer
|
||||
offset:
|
||||
type: integer
|
||||
total:
|
||||
type: integer
|
||||
total_pages:
|
||||
type: integer
|
||||
users:
|
||||
items:
|
||||
$ref: '#/definitions/user.UserResponse'
|
||||
type: array
|
||||
type: object
|
||||
user.UserResponse:
|
||||
properties:
|
||||
company_id:
|
||||
type: string
|
||||
created_at:
|
||||
type: integer
|
||||
created_by:
|
||||
type: string
|
||||
department:
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
full_name:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
is_verified:
|
||||
type: boolean
|
||||
last_login_at:
|
||||
type: integer
|
||||
phone:
|
||||
type: string
|
||||
position:
|
||||
type: string
|
||||
profile_image:
|
||||
type: string
|
||||
role:
|
||||
type: string
|
||||
status:
|
||||
type: string
|
||||
updated_at:
|
||||
type: integer
|
||||
updated_by:
|
||||
type: string
|
||||
username:
|
||||
type: string
|
||||
type: object
|
||||
host: localhost:8081
|
||||
info:
|
||||
contact:
|
||||
@@ -703,6 +846,699 @@ paths:
|
||||
summary: Refresh access token
|
||||
tags:
|
||||
- customers
|
||||
/users/admin:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: List users with search and filters (admin only)
|
||||
parameters:
|
||||
- description: Search term
|
||||
in: query
|
||||
name: search
|
||||
type: string
|
||||
- description: User status filter
|
||||
in: query
|
||||
name: status
|
||||
type: string
|
||||
- description: User role filter
|
||||
in: query
|
||||
name: role
|
||||
type: string
|
||||
- description: Company ID filter
|
||||
in: query
|
||||
name: company_id
|
||||
type: string
|
||||
- description: Limit results
|
||||
in: query
|
||||
name: limit
|
||||
type: integer
|
||||
- description: Offset results
|
||||
in: query
|
||||
name: offset
|
||||
type: integer
|
||||
- description: Sort field
|
||||
in: query
|
||||
name: sort_by
|
||||
type: string
|
||||
- description: Sort order
|
||||
in: query
|
||||
name: sort_order
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/response.APIResponse'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/user.UserListResponse'
|
||||
type: object
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"403":
|
||||
description: Forbidden
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: List users
|
||||
tags:
|
||||
- users
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Create a new user (admin only)
|
||||
parameters:
|
||||
- description: User creation data
|
||||
in: body
|
||||
name: user
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/user.CreateUserForm'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"201":
|
||||
description: Created
|
||||
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'
|
||||
"403":
|
||||
description: Forbidden
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: Create user
|
||||
tags:
|
||||
- users
|
||||
/users/admin/{id}:
|
||||
delete:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Delete a user (admin only)
|
||||
parameters:
|
||||
- description: User ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
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'
|
||||
"403":
|
||||
description: Forbidden
|
||||
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: Delete user
|
||||
tags:
|
||||
- users
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Get user details by ID (admin only)
|
||||
parameters:
|
||||
- description: User ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
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'
|
||||
"403":
|
||||
description: Forbidden
|
||||
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 by ID
|
||||
tags:
|
||||
- users
|
||||
put:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Update user information (admin only)
|
||||
parameters:
|
||||
- description: User ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
- description: User update data
|
||||
in: body
|
||||
name: user
|
||||
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'
|
||||
"403":
|
||||
description: Forbidden
|
||||
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: Update user
|
||||
tags:
|
||||
- users
|
||||
/users/admin/{id}/role:
|
||||
put:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Update user role (admin only)
|
||||
parameters:
|
||||
- description: User ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
- description: Role update data
|
||||
in: body
|
||||
name: role
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/user.UpdateUserRoleForm'
|
||||
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'
|
||||
"403":
|
||||
description: Forbidden
|
||||
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: Update user role
|
||||
tags:
|
||||
- users
|
||||
/users/admin/{id}/status:
|
||||
put:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Update user account status (admin only)
|
||||
parameters:
|
||||
- description: User ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
- description: Status update data
|
||||
in: body
|
||||
name: status
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/user.UpdateUserStatusForm'
|
||||
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'
|
||||
"403":
|
||||
description: Forbidden
|
||||
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: Update user status
|
||||
tags:
|
||||
- users
|
||||
/users/admin/company/{company_id}:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Get users belonging to a specific company (admin only)
|
||||
parameters:
|
||||
- description: Company ID
|
||||
in: path
|
||||
name: company_id
|
||||
required: true
|
||||
type: string
|
||||
- description: Limit results
|
||||
in: query
|
||||
name: limit
|
||||
type: integer
|
||||
- description: Offset results
|
||||
in: query
|
||||
name: offset
|
||||
type: integer
|
||||
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'
|
||||
"403":
|
||||
description: Forbidden
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: Get users by company ID
|
||||
tags:
|
||||
- users
|
||||
/users/admin/role/{role}:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Get users with a specific role (admin only)
|
||||
parameters:
|
||||
- description: User role
|
||||
in: path
|
||||
name: role
|
||||
required: true
|
||||
type: string
|
||||
- description: Limit results
|
||||
in: query
|
||||
name: limit
|
||||
type: integer
|
||||
- description: Offset results
|
||||
in: query
|
||||
name: offset
|
||||
type: integer
|
||||
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'
|
||||
"403":
|
||||
description: Forbidden
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
security:
|
||||
- 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
|
||||
securityDefinitions:
|
||||
BearerAuth:
|
||||
description: Type "Bearer" followed by a space and JWT token.
|
||||
@@ -713,6 +1549,8 @@ swagger: "2.0"
|
||||
tags:
|
||||
- description: Customer management operations
|
||||
name: customers
|
||||
- description: User management operations
|
||||
name: users
|
||||
- description: Health check operations
|
||||
name: health
|
||||
- description: Authentication operations
|
||||
|
||||
+31
-10
@@ -42,6 +42,9 @@ package main
|
||||
// @tag.name customers
|
||||
// @tag.description Customer management operations
|
||||
|
||||
// @tag.name users
|
||||
// @tag.description User management operations
|
||||
|
||||
// @tag.name health
|
||||
// @tag.description Health check operations
|
||||
|
||||
@@ -54,6 +57,7 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
"tm/internal/customer"
|
||||
"tm/internal/user"
|
||||
|
||||
_ "tm/cmd/web/docs" // This is generated by swag
|
||||
)
|
||||
@@ -76,33 +80,43 @@ func main() {
|
||||
}
|
||||
}()
|
||||
|
||||
logger.Info(
|
||||
"Starting Tender Management API Server",
|
||||
map[string]interface{}{
|
||||
"version": "1.0.0",
|
||||
"host": conf.Server.Host,
|
||||
"port": conf.Server.Port,
|
||||
})
|
||||
// Initialize Redis connection manager
|
||||
redisClient := initRedis(conf.Cache.Redis, logger)
|
||||
defer func() {
|
||||
if err := redisClient.Close(); err != nil {
|
||||
logger.Error("Failed to close Redis connection", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
}()
|
||||
|
||||
// Initialize authorization service
|
||||
authService := initAuthorizationService(conf.Auth.JWT, redisClient, logger)
|
||||
// Initialize repositories with MongoDB connection manager
|
||||
customerRepository := customer.NewCustomerRepository(mongoManager, logger)
|
||||
userRepository := user.NewUserRepository(mongoManager, logger)
|
||||
|
||||
logger.Info("Repositories initialized successfully", map[string]interface{}{
|
||||
"repositories": []string{"customer"},
|
||||
"repositories": []string{"customer", "user"},
|
||||
})
|
||||
|
||||
// Initialize validation service
|
||||
userValidator := user.NewValidationService()
|
||||
|
||||
// Initialize services with repositories
|
||||
customerService := customer.NewCustomerService(customerRepository, logger)
|
||||
userService := user.NewUserService(userRepository, logger, authService, userValidator)
|
||||
|
||||
logger.Info("Services initialized successfully", map[string]interface{}{
|
||||
"services": []string{"customer"},
|
||||
"services": []string{"customer", "user"},
|
||||
})
|
||||
|
||||
// Initialize handlers with services
|
||||
customerHandler := customer.NewHandler(customerService)
|
||||
userHandler := user.NewUserHandler(userService, logger, userValidator, authService)
|
||||
|
||||
logger.Info("Handlers initialized successfully", map[string]interface{}{
|
||||
"handlers": []string{"customer"},
|
||||
"handlers": []string{"customer", "user"},
|
||||
})
|
||||
|
||||
// Initialize HTTP server
|
||||
@@ -110,17 +124,24 @@ func main() {
|
||||
|
||||
// Register routes
|
||||
customerHandler.RegisterRoutes(e)
|
||||
userHandler.RegisterRoutes(e)
|
||||
|
||||
// Start server
|
||||
serverAddr := fmt.Sprintf("%s:%d", conf.Server.Host, conf.Server.Port)
|
||||
logger.Info("HTTP server starting", map[string]interface{}{
|
||||
"address": serverAddr,
|
||||
"version": "1.0.0",
|
||||
"host": conf.Server.Host,
|
||||
"port": conf.Server.Port,
|
||||
})
|
||||
|
||||
if err := e.Start(serverAddr); err != nil && err != http.ErrServerClosed {
|
||||
logger.Error("Failed to start HTTP server", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"address": serverAddr,
|
||||
"version": "1.0.0",
|
||||
"host": conf.Server.Host,
|
||||
"port": conf.Server.Port,
|
||||
})
|
||||
panic(fmt.Sprintf("Failed to start HTTP server: %v", err))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user