diff --git a/cmd/web/docs/docs.go b/cmd/web/docs/docs.go index 9be3aae..828c896 100644 --- a/cmd/web/docs/docs.go +++ b/cmd/web/docs/docs.go @@ -2057,7 +2057,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Admin Flags" + "Admin-Flags" ], "summary": "Get flag by country code (Admin)", "parameters": [ @@ -7051,6 +7051,10 @@ const docTemplate = `{ "customer.LoginForm": { "type": "object", "properties": { + "device_token": { + "type": "string", + "example": "device_token" + }, "password": { "type": "string", "example": "App!1234" @@ -8077,6 +8081,11 @@ const docTemplate = `{ "user.LoginForm": { "type": "object", "properties": { + "device_token": { + "description": "Device token", + "type": "string", + "example": "device_token" + }, "password": { "description": "User password", "type": "string", diff --git a/cmd/web/docs/swagger.json b/cmd/web/docs/swagger.json index f652c5f..2528c5a 100644 --- a/cmd/web/docs/swagger.json +++ b/cmd/web/docs/swagger.json @@ -2051,7 +2051,7 @@ "application/json" ], "tags": [ - "Admin Flags" + "Admin-Flags" ], "summary": "Get flag by country code (Admin)", "parameters": [ @@ -7045,6 +7045,10 @@ "customer.LoginForm": { "type": "object", "properties": { + "device_token": { + "type": "string", + "example": "device_token" + }, "password": { "type": "string", "example": "App!1234" @@ -8071,6 +8075,11 @@ "user.LoginForm": { "type": "object", "properties": { + "device_token": { + "description": "Device token", + "type": "string", + "example": "device_token" + }, "password": { "description": "User password", "type": "string", diff --git a/cmd/web/docs/swagger.yaml b/cmd/web/docs/swagger.yaml index f76b758..c3d937d 100644 --- a/cmd/web/docs/swagger.yaml +++ b/cmd/web/docs/swagger.yaml @@ -406,6 +406,9 @@ definitions: type: object customer.LoginForm: properties: + device_token: + example: device_token + type: string password: example: App!1234 type: string @@ -1110,6 +1113,10 @@ definitions: type: object user.LoginForm: properties: + device_token: + description: Device token + example: device_token + type: string password: description: User password example: Admin!1234 @@ -2509,7 +2516,7 @@ paths: - BearerAuth: [] summary: Get flag by country code (Admin) tags: - - Admin Flags + - Admin-Flags /admin/v1/health: get: consumes: diff --git a/internal/customer/entity.go b/internal/customer/entity.go index bf636c4..37aeb02 100644 --- a/internal/customer/entity.go +++ b/internal/customer/entity.go @@ -45,6 +45,7 @@ type Customer struct { Role CustomerRole `bson:"role"` Phone *string `bson:"phone"` CompanyIDs []string `bson:"company_ids"` + DeviceToken []string `bson:"device_token"` LastLoginAt *int64 `bson:"last_login_at"` UpdatedAt int64 `bson:"updated_at"` CreatedAt int64 `bson:"created_at"` diff --git a/internal/customer/form.go b/internal/customer/form.go index 7ab105a..f072887 100644 --- a/internal/customer/form.go +++ b/internal/customer/form.go @@ -89,8 +89,9 @@ type CustomerListResponse struct { } type LoginForm struct { - Username string `json:"username" valid:"required" example:"app"` - Password string `json:"password" valid:"required" example:"App!1234"` + Username string `json:"username" valid:"required" example:"app"` + Password string `json:"password" valid:"required" example:"App!1234"` + DeviceToken string `json:"device_token" valid:"optional" example:"device_token"` } type RefreshTokenForm struct { diff --git a/internal/customer/service.go b/internal/customer/service.go index a744804..dc77816 100644 --- a/internal/customer/service.go +++ b/internal/customer/service.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "math/big" + "slices" "strings" "time" @@ -529,6 +530,11 @@ func (s *customerService) Login(ctx context.Context, form *LoginForm) (*AuthResp return nil, errors.New("failed to generate authentication tokens") } + // append device token to customer if not exists + if !slices.Contains(customer.DeviceToken, form.DeviceToken) { + customer.DeviceToken = append(customer.DeviceToken, form.DeviceToken) + } + err = s.repository.Login(ctx, customer.ID.Hex()) if err != nil { s.logger.Error("Failed to update customer last login", map[string]interface{}{ diff --git a/internal/user/entity.go b/internal/user/entity.go index f13c1e4..40d77ff 100644 --- a/internal/user/entity.go +++ b/internal/user/entity.go @@ -38,6 +38,7 @@ type User struct { Position *string `bson:"position"` Phone *string `bson:"phone"` ProfileImage *string `bson:"profile_image"` + DeviceToken []string `bson:"device_token"` IsVerified bool `bson:"is_verified"` LastLoginAt *int64 `bson:"last_login_at"` } diff --git a/internal/user/form.go b/internal/user/form.go index ef1ed9b..3569f31 100644 --- a/internal/user/form.go +++ b/internal/user/form.go @@ -33,8 +33,9 @@ type UpdateUserForm struct { // LoginForm represents the credentials required for user authentication type LoginForm struct { - Username string `json:"username" valid:"required" example:"admin"` // Username or email address - Password string `json:"password" valid:"required" example:"Admin!1234"` // User password + Username string `json:"username" valid:"required" example:"admin"` // Username or email address + Password string `json:"password" valid:"required" example:"Admin!1234"` // User password + DeviceToken string `json:"device_token" valid:"optional" example:"device_token"` // Device token } // RefreshTokenForm represents the refresh token required to generate new access tokens diff --git a/internal/user/service.go b/internal/user/service.go index cfe70cb..cd06c0a 100644 --- a/internal/user/service.go +++ b/internal/user/service.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "slices" "strings" "time" "tm/pkg/authorization" @@ -311,6 +312,11 @@ func (s *userService) Login(ctx context.Context, form *LoginForm) (*AuthResponse return nil, errors.New("invalid credentials") } + // append device token to user if not exists + if !slices.Contains(user.DeviceToken, form.DeviceToken) { + user.DeviceToken = append(user.DeviceToken, form.DeviceToken) + } + // Update last login err = s.repository.Login(ctx, user.ID.Hex()) if err != nil {