add manager and cashier

This commit is contained in:
lafetz 2025-04-10 14:59:31 +03:00
parent 055d28f870
commit 857c5c0696
12 changed files with 1373 additions and 45 deletions

View File

@ -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": {

View File

@ -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": {

View File

@ -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:

View File

@ -58,6 +58,7 @@ type ResetPasswordReq struct {
OtpMedium OtpMedium
}
type UpdateUserReq struct {
UserId int64
FirstName ValidString
LastName ValidString
Suspended ValidBool

View File

@ -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)

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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")),
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
}
}

View File

@ -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
}
}

View File

@ -18,17 +18,24 @@ 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
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"},
@ -36,6 +43,7 @@ func CreateJwt(userId int64, Role domain.Role, key string, expiry int) (string,
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(expiry) * time.Second))},
UserId: userId,
Role: Role,
BranchId: BranchId,
})
jwtToken, err := token.SignedString([]byte(key)) //
return jwtToken, err

View File

@ -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 {

View File

@ -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))