diff --git a/docs/docs.go b/docs/docs.go index cd7719d..28a7e62 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -716,6 +716,163 @@ const docTemplate = `{ } } }, + "/cashiers": { + "get": { + "description": "Get all cashiers", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "cashier" + ], + "summary": "Get all cashiers", + "parameters": [ + { + "type": "integer", + "description": "Page number", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "Page size", + "name": "page_size", + "in": "query" + } + ], + "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" + } + } + } + }, + "post": { + "description": "Create cashier", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "cashier" + ], + "summary": "Create cashier", + "parameters": [ + { + "description": "Create cashier", + "name": "cashier", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/handlers.CreateCashierReq" + } + } + ], + "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" + } + } + } + } + }, + "/cashiers/{id}": { + "put": { + "description": "Update cashier", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "cashier" + ], + "summary": "Update cashier", + "parameters": [ + { + "description": "Update cashier", + "name": "cashier", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/handlers.updateUserReq" + } + } + ], + "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" + } + } + } + } + }, "/company/{id}/branch": { "get": { "description": "Gets branches by company id", @@ -810,6 +967,163 @@ const docTemplate = `{ } } }, + "/managers": { + "get": { + "description": "Get all Managers", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "manager" + ], + "summary": "Get all Managers", + "parameters": [ + { + "type": "integer", + "description": "Page number", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "Page size", + "name": "page_size", + "in": "query" + } + ], + "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" + } + } + } + }, + "post": { + "description": "Create Managers", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "manager" + ], + "summary": "Create Managers", + "parameters": [ + { + "description": "Create manager", + "name": "manger", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/handlers.CreateManagerReq" + } + } + ], + "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" + } + } + } + } + }, + "/managers/{id}": { + "put": { + "description": "Update Managers", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Managers" + ], + "summary": "Update Managers", + "parameters": [ + { + "description": "Update Managers", + "name": "Managers", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/handlers.updateUserReq" + } + } + ], + "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" + } + } + } + } + }, "/operation": { "post": { "description": "Creates a operation", @@ -2074,6 +2388,60 @@ const docTemplate = `{ } } }, + "handlers.CreateCashierReq": { + "type": "object", + "properties": { + "email": { + "type": "string", + "example": "john.doe@example.com" + }, + "first_name": { + "type": "string", + "example": "John" + }, + "last_name": { + "type": "string", + "example": "Doe" + }, + "password": { + "type": "string", + "example": "password123" + }, + "phone_number": { + "type": "string", + "example": "1234567890" + } + } + }, + "handlers.CreateManagerReq": { + "type": "object", + "properties": { + "branch_id": { + "type": "integer", + "example": 1 + }, + "email": { + "type": "string", + "example": "john.doe@example.com" + }, + "first_name": { + "type": "string", + "example": "John" + }, + "last_name": { + "type": "string", + "example": "Doe" + }, + "password": { + "type": "string", + "example": "password123" + }, + "phone_number": { + "type": "string", + "example": "1234567890" + } + } + }, "handlers.CreateSupportedOperationReq": { "type": "object", "properties": { @@ -2586,6 +2954,9 @@ const docTemplate = `{ }, "refresh_token": { "type": "string" + }, + "role": { + "type": "string" } } }, @@ -2608,6 +2979,23 @@ const docTemplate = `{ } } }, + "handlers.updateUserReq": { + "type": "object", + "properties": { + "first_name": { + "type": "string", + "example": "John" + }, + "last_name": { + "type": "string", + "example": "Doe" + }, + "suspended": { + "type": "boolean", + "example": false + } + } + }, "response.APIResponse": { "type": "object", "properties": { diff --git a/docs/swagger.json b/docs/swagger.json index 7ecbb4f..cd6c6bd 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -708,6 +708,163 @@ } } }, + "/cashiers": { + "get": { + "description": "Get all cashiers", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "cashier" + ], + "summary": "Get all cashiers", + "parameters": [ + { + "type": "integer", + "description": "Page number", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "Page size", + "name": "page_size", + "in": "query" + } + ], + "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" + } + } + } + }, + "post": { + "description": "Create cashier", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "cashier" + ], + "summary": "Create cashier", + "parameters": [ + { + "description": "Create cashier", + "name": "cashier", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/handlers.CreateCashierReq" + } + } + ], + "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" + } + } + } + } + }, + "/cashiers/{id}": { + "put": { + "description": "Update cashier", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "cashier" + ], + "summary": "Update cashier", + "parameters": [ + { + "description": "Update cashier", + "name": "cashier", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/handlers.updateUserReq" + } + } + ], + "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" + } + } + } + } + }, "/company/{id}/branch": { "get": { "description": "Gets branches by company id", @@ -802,6 +959,163 @@ } } }, + "/managers": { + "get": { + "description": "Get all Managers", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "manager" + ], + "summary": "Get all Managers", + "parameters": [ + { + "type": "integer", + "description": "Page number", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "Page size", + "name": "page_size", + "in": "query" + } + ], + "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" + } + } + } + }, + "post": { + "description": "Create Managers", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "manager" + ], + "summary": "Create Managers", + "parameters": [ + { + "description": "Create manager", + "name": "manger", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/handlers.CreateManagerReq" + } + } + ], + "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" + } + } + } + } + }, + "/managers/{id}": { + "put": { + "description": "Update Managers", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Managers" + ], + "summary": "Update Managers", + "parameters": [ + { + "description": "Update Managers", + "name": "Managers", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/handlers.updateUserReq" + } + } + ], + "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" + } + } + } + } + }, "/operation": { "post": { "description": "Creates a operation", @@ -2066,6 +2380,60 @@ } } }, + "handlers.CreateCashierReq": { + "type": "object", + "properties": { + "email": { + "type": "string", + "example": "john.doe@example.com" + }, + "first_name": { + "type": "string", + "example": "John" + }, + "last_name": { + "type": "string", + "example": "Doe" + }, + "password": { + "type": "string", + "example": "password123" + }, + "phone_number": { + "type": "string", + "example": "1234567890" + } + } + }, + "handlers.CreateManagerReq": { + "type": "object", + "properties": { + "branch_id": { + "type": "integer", + "example": 1 + }, + "email": { + "type": "string", + "example": "john.doe@example.com" + }, + "first_name": { + "type": "string", + "example": "John" + }, + "last_name": { + "type": "string", + "example": "Doe" + }, + "password": { + "type": "string", + "example": "password123" + }, + "phone_number": { + "type": "string", + "example": "1234567890" + } + } + }, "handlers.CreateSupportedOperationReq": { "type": "object", "properties": { @@ -2578,6 +2946,9 @@ }, "refresh_token": { "type": "string" + }, + "role": { + "type": "string" } } }, @@ -2600,6 +2971,23 @@ } } }, + "handlers.updateUserReq": { + "type": "object", + "properties": { + "first_name": { + "type": "string", + "example": "John" + }, + "last_name": { + "type": "string", + "example": "Doe" + }, + "suspended": { + "type": "boolean", + "example": false + } + } + }, "response.APIResponse": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 69e4307..242eb5b 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -204,6 +204,45 @@ definitions: type: integer type: array type: object + handlers.CreateCashierReq: + properties: + email: + example: john.doe@example.com + type: string + first_name: + example: John + type: string + last_name: + example: Doe + type: string + password: + example: password123 + type: string + phone_number: + example: "1234567890" + type: string + type: object + handlers.CreateManagerReq: + properties: + branch_id: + example: 1 + type: integer + email: + example: john.doe@example.com + type: string + first_name: + example: John + type: string + last_name: + example: Doe + type: string + password: + example: password123 + type: string + phone_number: + example: "1234567890" + type: string + type: object handlers.CreateSupportedOperationReq: properties: description: @@ -559,6 +598,8 @@ definitions: type: string refresh_token: type: string + role: + type: string type: object handlers.logoutReq: properties: @@ -572,6 +613,18 @@ definitions: refresh_token: type: string type: object + handlers.updateUserReq: + properties: + first_name: + example: John + type: string + last_name: + example: Doe + type: string + suspended: + example: false + type: boolean + type: object response.APIResponse: properties: data: {} @@ -1061,6 +1114,109 @@ paths: summary: Delete the branch operation tags: - branch + /cashiers: + get: + consumes: + - application/json + description: Get all cashiers + parameters: + - description: Page number + in: query + name: page + type: integer + - description: Page size + in: query + name: page_size + 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' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.APIResponse' + summary: Get all cashiers + tags: + - cashier + post: + consumes: + - application/json + description: Create cashier + parameters: + - description: Create cashier + in: body + name: cashier + required: true + schema: + $ref: '#/definitions/handlers.CreateCashierReq' + 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' + summary: Create cashier + tags: + - cashier + /cashiers/{id}: + put: + consumes: + - application/json + description: Update cashier + parameters: + - description: Update cashier + in: body + name: cashier + required: true + schema: + $ref: '#/definitions/handlers.updateUserReq' + 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' + summary: Update cashier + tags: + - cashier /company/{id}/branch: get: consumes: @@ -1123,6 +1279,109 @@ paths: summary: Gets branches by manager id tags: - branch + /managers: + get: + consumes: + - application/json + description: Get all Managers + parameters: + - description: Page number + in: query + name: page + type: integer + - description: Page size + in: query + name: page_size + 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' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.APIResponse' + summary: Get all Managers + tags: + - manager + post: + consumes: + - application/json + description: Create Managers + parameters: + - description: Create manager + in: body + name: manger + required: true + schema: + $ref: '#/definitions/handlers.CreateManagerReq' + 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' + summary: Create Managers + tags: + - manager + /managers/{id}: + put: + consumes: + - application/json + description: Update Managers + parameters: + - description: Update Managers + in: body + name: Managers + required: true + schema: + $ref: '#/definitions/handlers.updateUserReq' + 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' + summary: Update Managers + tags: + - Managers /operation: post: consumes: diff --git a/internal/domain/user.go b/internal/domain/user.go index 7151eb9..23004f4 100644 --- a/internal/domain/user.go +++ b/internal/domain/user.go @@ -58,6 +58,7 @@ type ResetPasswordReq struct { OtpMedium OtpMedium } type UpdateUserReq struct { + UserId int64 FirstName ValidString LastName ValidString Suspended ValidBool diff --git a/internal/services/authentication/impl.go b/internal/services/authentication/impl.go index 58eb044..2d6bb0b 100644 --- a/internal/services/authentication/impl.go +++ b/internal/services/authentication/impl.go @@ -56,34 +56,31 @@ func (s *Service) Login(ctx context.Context, email, phone string, password strin }, nil } -func (s *Service) RefreshToken(ctx context.Context, refToken string) (string, error) { +func (s *Service) RefreshToken(ctx context.Context, refToken string) error { token, err := s.tokenStore.GetRefreshToken(ctx, refToken) if err != nil { - return "", err + return err } if token.Revoked { - return "", ErrRefreshTokenNotFound + return ErrRefreshTokenNotFound } if token.ExpiresAt.Before(time.Now()) { - return "", ErrExpiredToken + return ErrExpiredToken } - newRefToken, err := generateRefreshToken() - if err != nil { - return "", err - } + // newRefToken, err := generateRefreshToken() + // if err != nil { + // return "", err + // } - err = s.tokenStore.CreateRefreshToken(ctx, domain.RefreshToken{ - Token: newRefToken, - UserID: token.UserID, - CreatedAt: time.Now(), - ExpiresAt: time.Now().Add(time.Duration(s.RefreshExpiry) * time.Second), - }) - if err != nil { - return "", err - } - return newRefToken, nil + // err = s.tokenStore.CreateRefreshToken(ctx, domain.RefreshToken{ + // Token: newRefToken, + // UserID: token.UserID, + // CreatedAt: time.Now(), + // ExpiresAt: time.Now().Add(time.Duration(s.RefreshExpiry) * time.Second), + // }) + return nil } func (s *Service) Logout(ctx context.Context, refToken string) error { token, err := s.tokenStore.GetRefreshToken(ctx, refToken) diff --git a/internal/services/user/direct.go b/internal/services/user/direct.go index a0f61b9..b5fca74 100644 --- a/internal/services/user/direct.go +++ b/internal/services/user/direct.go @@ -6,19 +6,19 @@ import ( "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" ) -func (s *Service) CreateUser(ctx context.Context, User domain.CreateUserReq, createrUserId int64, branchId int64) (domain.User, error) { +func (s *Service) CreateUser(ctx context.Context, User domain.CreateUserReq) (domain.User, error) { // Create User - creator, err := s.userStore.GetUserByID(ctx, createrUserId) - if err != nil { - return domain.User{}, err - } - if creator.Role != domain.RoleAdmin { - User.BranchID = creator.BranchID - User.Role = string(domain.RoleCashier) - } else { - User.BranchID = branchId - User.Role = string(domain.RoleBranchManager) - } + // creator, err := s.userStore.GetUserByID(ctx, createrUserId) + // if err != nil { + // return domain.User{}, err + // } + // if creator.Role != domain.RoleAdmin { + // User.BranchID = creator.BranchID + // User.Role = string(domain.RoleCashier) + // } else { + // User.BranchID = branchId + // User.Role = string(domain.RoleBranchManager) + // } return s.userStore.CreateUserWithoutOtp(ctx, User) } @@ -30,7 +30,7 @@ func (s *Service) DeleteUser(ctx context.Context, id int64) error { type Filter struct { Role string - BranchId int64 + BranchId ValidBranchId Page int PageSize int } @@ -47,3 +47,7 @@ func (s *Service) GetAllUsers(ctx context.Context, filter Filter) ([]domain.User // Get all Users return s.userStore.GetAllUsers(ctx, filter) } +func (s *Service) GetUserById(ctx context.Context, id int64) (domain.User, error) { + + return s.userStore.GetUserByID(ctx, id) +} diff --git a/internal/web_server/handlers/auth_handler.go b/internal/web_server/handlers/auth_handler.go index 8731159..3434ea2 100644 --- a/internal/web_server/handlers/auth_handler.go +++ b/internal/web_server/handlers/auth_handler.go @@ -4,6 +4,7 @@ import ( "errors" "log/slog" + "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication" jwtutil "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/jwt" "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" @@ -66,7 +67,7 @@ func LoginCustomer( return nil } - accessToken, err := jwtutil.CreateJwt(successRes.UserId, successRes.Role, JwtConfig.JwtAccessKey, JwtConfig.JwtAccessExpiry) + accessToken, err := jwtutil.CreateJwt(successRes.UserId, successRes.Role, successRes.BranchId, JwtConfig.JwtAccessKey, JwtConfig.JwtAccessExpiry) res := loginCustomerRes{ AccessToken: accessToken, RefreshToken: successRes.RfToken, @@ -105,7 +106,10 @@ func RefreshToken(logger *slog.Logger, authSvc *authentication.Service, response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) return nil } - rf, err := authSvc.RefreshToken(c.Context(), req.RefreshToken) + userId := c.Locals("user_id").(int64) + role := c.Locals("role").(string) + branchId := c.Locals("branch_id").(int64) + err := authSvc.RefreshToken(c.Context(), req.RefreshToken) if err != nil { logger.Info("Refresh token failed", "error", err) if errors.Is(err, authentication.ErrExpiredToken) { @@ -120,7 +124,7 @@ func RefreshToken(logger *slog.Logger, authSvc *authentication.Service, response.WriteJSON(c, fiber.StatusInternalServerError, "Internal server error", nil, nil) return nil } - accessToken, err := jwtutil.CreateJwt(0, "", JwtConfig.JwtAccessKey, JwtConfig.JwtAccessExpiry) + accessToken, err := jwtutil.CreateJwt(userId, domain.Role(role), branchId, JwtConfig.JwtAccessKey, JwtConfig.JwtAccessExpiry) if err != nil { logger.Error("Create jwt failed", "error", err) response.WriteJSON(c, fiber.StatusInternalServerError, "Internal server error", nil, nil) @@ -129,7 +133,7 @@ func RefreshToken(logger *slog.Logger, authSvc *authentication.Service, res := loginCustomerRes{ AccessToken: accessToken, - RefreshToken: rf, + RefreshToken: req.RefreshToken, } return response.WriteJSON(c, fiber.StatusOK, "refresh successful", res, nil) } diff --git a/internal/web_server/handlers/cashier.go b/internal/web_server/handlers/cashier.go index f63b40e..6ad9874 100644 --- a/internal/web_server/handlers/cashier.go +++ b/internal/web_server/handlers/cashier.go @@ -2,6 +2,7 @@ package handlers import ( "log/slog" + "strconv" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/user" @@ -18,10 +19,22 @@ type CreateCashierReq struct { Password string `json:"password" example:"password123"` } +// CreateCashier godoc +// @Summary Create cashier +// @Description Create cashier +// @Tags cashier +// @Accept json +// @Produce json +// @Param cashier body CreateCashierReq true "Create cashier" +// @Success 200 {object} response.APIResponse +// @Failure 400 {object} response.APIResponse +// @Failure 401 {object} response.APIResponse +// @Failure 500 {object} response.APIResponse +// @Router /cashiers [post] func CreateCashier(logger *slog.Logger, userSvc *user.Service, validator *customvalidator.CustomValidator) fiber.Handler { return func(c *fiber.Ctx) error { - userId := c.Locals("user_id").(int64) + creatorBranch := c.Locals("branch_id").(int64) var req CreateCashierReq if err := c.BodyParser(&req); err != nil { logger.Error("RegisterUser failed", "error", err) @@ -41,8 +54,9 @@ func CreateCashier(logger *slog.Logger, userSvc *user.Service, validator *custom PhoneNumber: req.PhoneNumber, Password: req.Password, Role: string(domain.RoleCashier), + BranchID: creatorBranch, } - _, err := userSvc.CreateUser(c.Context(), user, userId, 0) + _, err := userSvc.CreateUser(c.Context(), user) if err != nil { logger.Error("CreateCashier failed", "error", err) response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create cashier", nil, nil) @@ -53,12 +67,29 @@ func CreateCashier(logger *slog.Logger, userSvc *user.Service, validator *custom } } + +// GetAllCashiers godoc +// @Summary Get all cashiers +// @Description Get all cashiers +// @Tags cashier +// @Accept json +// @Produce json +// @Param page query int false "Page number" +// @Param page_size query int false "Page size" +// @Success 200 {object} response.APIResponse +// @Failure 400 {object} response.APIResponse +// @Failure 401 {object} response.APIResponse +// @Failure 500 {object} response.APIResponse +// @Router /cashiers [get] func GetAllCashiers(logger *slog.Logger, userSvc *user.Service, validator *customvalidator.CustomValidator) fiber.Handler { return func(c *fiber.Ctx) error { - + branchId := int64(12) //c.Locals("branch_id").(int64) filter := user.Filter{ - Role: string(domain.RoleCashier), - BranchId: int64(c.QueryInt("branch_id")), + Role: string(domain.RoleCashier), + BranchId: user.ValidBranchId{ + Value: branchId, + Valid: true, + }, Page: c.QueryInt("page", 1), PageSize: c.QueryInt("page_size", 10), } @@ -78,3 +109,70 @@ func GetAllCashiers(logger *slog.Logger, userSvc *user.Service, validator *custo } } + +type updateUserReq struct { + FirstName string `json:"first_name" example:"John"` + LastName string `json:"last_name" example:"Doe"` + Suspended bool `json:"suspended" example:"false"` +} + +// UpdateCashier godoc +// @Summary Update cashier +// @Description Update cashier +// @Tags cashier +// @Accept json +// @Produce json +// @Param cashier body updateUserReq true "Update cashier" +// @Success 200 {object} response.APIResponse +// @Failure 400 {object} response.APIResponse +// @Failure 401 {object} response.APIResponse +// @Failure 500 {object} response.APIResponse +// @Router /cashiers/{id} [put] +func UpdateCashier(logger *slog.Logger, userSvc *user.Service, validator *customvalidator.CustomValidator) fiber.Handler { + return func(c *fiber.Ctx) error { + var req updateUserReq + if err := c.BodyParser(&req); err != nil { + logger.Error("UpdateCashier failed", "error", err) + response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", nil, nil) + return nil + } + + valErrs, ok := validator.Validate(c, req) + + if !ok { + response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) + return nil + } + cashierIdStr := c.Params("id") + cashierId, err := strconv.ParseInt(cashierIdStr, 10, 64) + if err != nil { + logger.Error("UpdateCashier failed", "error", err) + response.WriteJSON(c, fiber.StatusBadRequest, "Invalid cashier ID", nil, nil) + return nil + } + err = userSvc.UpdateUser(c.Context(), domain.UpdateUserReq{ + UserId: cashierId, + FirstName: domain.ValidString{ + Value: req.FirstName, + Valid: req.FirstName != "", + }, + LastName: domain.ValidString{ + Value: req.LastName, + Valid: req.LastName != "", + }, + Suspended: domain.ValidBool{ + Value: req.Suspended, + Valid: true, + }, + }, + ) + if err != nil { + logger.Error("UpdateCashier failed", "error", err) + response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update cashier", nil, nil) + return nil + } + response.WriteJSON(c, fiber.StatusOK, "Cashier updated successfully", nil, nil) + return nil + } + +} diff --git a/internal/web_server/handlers/manager.go b/internal/web_server/handlers/manager.go new file mode 100644 index 0000000..d0ba39a --- /dev/null +++ b/internal/web_server/handlers/manager.go @@ -0,0 +1,170 @@ +package handlers + +import ( + "log/slog" + "strconv" + + "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" + "github.com/SamuelTariku/FortuneBet-Backend/internal/services/user" + "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" + customvalidator "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/validator" + "github.com/gofiber/fiber/v2" +) + +type CreateManagerReq struct { + FirstName string `json:"first_name" example:"John"` + LastName string `json:"last_name" example:"Doe"` + Email string `json:"email" example:"john.doe@example.com"` + PhoneNumber string `json:"phone_number" example:"1234567890"` + Password string `json:"password" example:"password123"` + BranchId int64 `json:"branch_id" example:"1"` +} + +// CreateManagers godoc +// @Summary Create Managers +// @Description Create Managers +// @Tags manager +// @Accept json +// @Produce json +// @Param manger body CreateManagerReq true "Create manager" +// @Success 200 {object} response.APIResponse +// @Failure 400 {object} response.APIResponse +// @Failure 401 {object} response.APIResponse +// @Failure 500 {object} response.APIResponse +// @Router /managers [post] +func CreateManager(logger *slog.Logger, userSvc *user.Service, validator *customvalidator.CustomValidator) fiber.Handler { + return func(c *fiber.Ctx) error { + var req CreateManagerReq + if err := c.BodyParser(&req); err != nil { + logger.Error("RegisterUser failed", "error", err) + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "Invalid request", + }) + } + valErrs, ok := validator.Validate(c, req) + if !ok { + response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) + return nil + } + user := domain.CreateUserReq{ + FirstName: req.FirstName, + LastName: req.LastName, + Email: req.Email, + PhoneNumber: req.PhoneNumber, + Password: req.Password, + Role: string(domain.RoleBranchManager), + BranchID: req.BranchId, + } + _, err := userSvc.CreateUser(c.Context(), user) + if err != nil { + logger.Error("CreateManagers failed", "error", err) + response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create Managers", nil, nil) + return nil + } + response.WriteJSON(c, fiber.StatusOK, "Managers created successfully", nil, nil) + return nil + } + +} + +// GetAllManagers godoc +// @Summary Get all Managers +// @Description Get all Managers +// @Tags manager +// @Accept json +// @Produce json +// @Param page query int false "Page number" +// @Param page_size query int false "Page size" +// @Success 200 {object} response.APIResponse +// @Failure 400 {object} response.APIResponse +// @Failure 401 {object} response.APIResponse +// @Failure 500 {object} response.APIResponse +// @Router /managers [get] +func GetAllManagers(logger *slog.Logger, userSvc *user.Service, validator *customvalidator.CustomValidator) fiber.Handler { + return func(c *fiber.Ctx) error { + filter := user.Filter{ + Role: string(domain.RoleBranchManager), + BranchId: user.ValidBranchId{ + Value: int64(c.QueryInt("branch_id")), + Valid: true, + }, + Page: c.QueryInt("page", 1), + PageSize: c.QueryInt("page_size", 10), + } + valErrs, ok := validator.Validate(c, filter) + if !ok { + response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) + return nil + } + Managers, err := userSvc.GetAllUsers(c.Context(), filter) + if err != nil { + logger.Error("GetAllManagers failed", "error", err) + response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get Managers", nil, nil) + return nil + } + response.WriteJSON(c, fiber.StatusOK, "Managers retrieved successfully", Managers, nil) + return nil + } + +} + +// UpdateManagers godoc +// @Summary Update Managers +// @Description Update Managers +// @Tags Managers +// @Accept json +// @Produce json +// @Param Managers body updateUserReq true "Update Managers" +// @Success 200 {object} response.APIResponse +// @Failure 400 {object} response.APIResponse +// @Failure 401 {object} response.APIResponse +// @Failure 500 {object} response.APIResponse +// @Router /managers/{id} [put] +func UPdateManagers(logger *slog.Logger, userSvc *user.Service, validator *customvalidator.CustomValidator) fiber.Handler { + return func(c *fiber.Ctx) error { + var req updateUserReq + if err := c.BodyParser(&req); err != nil { + logger.Error("UpdateManagers failed", "error", err) + response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", nil, nil) + return nil + } + + valErrs, ok := validator.Validate(c, req) + + if !ok { + response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) + return nil + } + ManagersIdStr := c.Params("id") + ManagersId, err := strconv.ParseInt(ManagersIdStr, 10, 64) + if err != nil { + logger.Error("UpdateManagers failed", "error", err) + response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Managers ID", nil, nil) + return nil + } + err = userSvc.UpdateUser(c.Context(), domain.UpdateUserReq{ + UserId: ManagersId, + FirstName: domain.ValidString{ + Value: req.FirstName, + Valid: req.FirstName != "", + }, + LastName: domain.ValidString{ + Value: req.LastName, + Valid: req.LastName != "", + }, + Suspended: domain.ValidBool{ + Value: req.Suspended, + Valid: true, + }, + }, + ) + if err != nil { + logger.Error("UpdateManagers failed", "error", err) + response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update Managers", nil, nil) + return nil + } + response.WriteJSON(c, fiber.StatusOK, "Managers updated successfully", nil, nil) + return nil + } + +} diff --git a/internal/web_server/jwt/jwt.go b/internal/web_server/jwt/jwt.go index 530eb12..e53a274 100644 --- a/internal/web_server/jwt/jwt.go +++ b/internal/web_server/jwt/jwt.go @@ -18,24 +18,32 @@ var ( ErrRefreshTokenNotFound = errors.New("refresh token not found") // i.e login again ) +type User struct { + UserId int64 + Role domain.Role + BranchId int64 + RefreshToken string +} type UserClaim struct { jwt.RegisteredClaims - UserId int64 - Role domain.Role + UserId int64 + Role domain.Role + BranchId int64 } type JwtConfig struct { JwtAccessKey string JwtAccessExpiry int } -func CreateJwt(userId int64, Role domain.Role, key string, expiry int) (string, error) { +func CreateJwt(userId int64, Role domain.Role, BranchId int64, key string, expiry int) (string, error) { token := jwt.NewWithClaims(jwt.SigningMethodHS256, UserClaim{RegisteredClaims: jwt.RegisteredClaims{Issuer: "github.com/lafetz/snippitstash", IssuedAt: jwt.NewNumericDate(time.Now()), Audience: jwt.ClaimStrings{"fortune.com"}, NotBefore: jwt.NewNumericDate(time.Now()), ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(expiry) * time.Second))}, - UserId: userId, - Role: Role, + UserId: userId, + Role: Role, + BranchId: BranchId, }) jwtToken, err := token.SignedString([]byte(key)) // return jwtToken, err diff --git a/internal/web_server/middleware.go b/internal/web_server/middleware.go index 46e248b..dc25a1e 100644 --- a/internal/web_server/middleware.go +++ b/internal/web_server/middleware.go @@ -39,6 +39,7 @@ func (a *App) authMiddleware(c *fiber.Ctx) error { } c.Locals("user_id", claim.UserId) c.Locals("role", claim.Role) + c.Locals("branch_id", claim.BranchId) c.Locals("refresh_token", refreshToken) if claim.Role != domain.RoleCustomer { diff --git a/internal/web_server/routes.go b/internal/web_server/routes.go index b25ed9d..7e3fd08 100644 --- a/internal/web_server/routes.go +++ b/internal/web_server/routes.go @@ -39,7 +39,17 @@ func (a *App) initAppRoutes() { a.fiber.Post("/user/sendRegisterCode", handlers.SendRegisterCode(a.logger, a.userSvc, a.validator)) a.fiber.Post("/user/checkPhoneEmailExist", handlers.CheckPhoneEmailExist(a.logger, a.userSvc, a.validator)) a.fiber.Get("/user/profile", a.authMiddleware, handlers.UserProfile(a.logger, a.userSvc)) + // + //, a.authMiddleware + a.fiber.Get("/cashiers", handlers.GetAllCashiers(a.logger, a.userSvc, a.validator)) + a.fiber.Post("/cashiers", handlers.CreateCashier(a.logger, a.userSvc, a.validator)) + a.fiber.Put("/cashiers/:id", handlers.UpdateCashier(a.logger, a.userSvc, a.validator)) + // + a.fiber.Get("/managers", handlers.GetAllManagers(a.logger, a.userSvc, a.validator)) + a.fiber.Post("/managers", handlers.CreateManager(a.logger, a.userSvc, a.validator)) + a.fiber.Put("/managers/:id", handlers.UPdateManagers(a.logger, a.userSvc, a.validator)) + // a.fiber.Get("/user/wallet", a.authMiddleware, handlers.GetCustomerWallet(a.logger, a.walletSvc, a.validator)) a.fiber.Post("/user/search", handlers.SearchUserByNameOrPhone(a.logger, a.userSvc, a.validator))