fix: fixing login register method access

This commit is contained in:
pahmiudahgede 2025-01-14 04:13:14 +07:00
parent 7f4bc872c6
commit 0e0aa3b1d1
5 changed files with 84 additions and 67 deletions

View File

@ -5,10 +5,10 @@ import "time"
type User struct { type User struct {
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4();unique;not null" json:"id"` ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4();unique;not null" json:"id"`
Avatar *string `json:"avatar,omitempty"` Avatar *string `json:"avatar,omitempty"`
Username string `gorm:"unique;not null" json:"username"` Username string `gorm:"not null" json:"username"`
Name string `gorm:"not null" json:"name"` Name string `gorm:"not null" json:"name"`
Phone string `gorm:"not null" json:"phone"` Phone string `gorm:"not null" json:"phone"`
Email string `gorm:"unique;not null" json:"email"` Email string `gorm:"not null" json:"email"`
EmailVerified bool `gorm:"default:false" json:"emailVerified"` EmailVerified bool `gorm:"default:false" json:"emailVerified"`
Password string `gorm:"not null" json:"password"` Password string `gorm:"not null" json:"password"`
Pin UserPin `gorm:"foreignKey:UserID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"pin"` Pin UserPin `gorm:"foreignKey:UserID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"pin"`

View File

@ -29,14 +29,14 @@ func Register(c *fiber.Ctx) error {
err := services.RegisterUser(userInput.Username, userInput.Name, userInput.Email, userInput.Phone, userInput.Password, userInput.ConfirmPassword, userInput.RoleId) err := services.RegisterUser(userInput.Username, userInput.Name, userInput.Email, userInput.Phone, userInput.Password, userInput.ConfirmPassword, userInput.RoleId)
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse( return c.Status(fiber.StatusConflict).JSON(utils.FormatResponse(
fiber.StatusInternalServerError, fiber.StatusConflict,
err.Error(), err.Error(),
nil, nil,
)) ))
} }
user, err := repositories.GetUserByEmailOrUsername(userInput.Email) user, err := repositories.GetUserByEmailUsernameOrPhone(userInput.Email, userInput.RoleId)
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse( return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
fiber.StatusInternalServerError, fiber.StatusInternalServerError,
@ -65,7 +65,7 @@ func Register(c *fiber.Ctx) error {
func Login(c *fiber.Ctx) error { func Login(c *fiber.Ctx) error {
var credentials struct { var credentials struct {
EmailOrUsername string `json:"email_or_username"` Identifier string `json:"identifier"`
Password string `json:"password"` Password string `json:"password"`
} }
@ -77,7 +77,7 @@ func Login(c *fiber.Ctx) error {
)) ))
} }
user, err := repositories.GetUserByEmailOrUsername(credentials.EmailOrUsername) token, err := services.LoginUser(credentials.Identifier, credentials.Password)
if err != nil { if err != nil {
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse( return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
fiber.StatusUnauthorized, fiber.StatusUnauthorized,
@ -86,7 +86,7 @@ func Login(c *fiber.Ctx) error {
)) ))
} }
token, err := services.LoginUser(credentials.EmailOrUsername, credentials.Password) user, err := repositories.GetUserByEmailUsernameOrPhone(credentials.Identifier, "")
if err != nil { if err != nil {
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse( return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
fiber.StatusUnauthorized, fiber.StatusUnauthorized,
@ -154,12 +154,19 @@ func UpdateUser(c *fiber.Ctx) error {
)) ))
} }
userID := c.Locals("userID").(string) userID, ok := c.Locals("userID").(string)
if !ok || userID == "" {
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
fiber.StatusUnauthorized,
"Unauthorized access",
nil,
))
}
err := services.UpdateUser(userID, userInput.Email, userInput.Username, userInput.Name, userInput.Phone) err := services.UpdateUser(userID, userInput.Email, userInput.Username, userInput.Name, userInput.Phone)
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse( return c.Status(fiber.StatusConflict).JSON(utils.FormatResponse(
fiber.StatusInternalServerError, fiber.StatusConflict,
err.Error(), err.Error(),
nil, nil,
)) ))

View File

@ -8,44 +8,37 @@ import (
"github.com/pahmiudahgede/senggoldong/domain" "github.com/pahmiudahgede/senggoldong/domain"
) )
func IsEmailExist(email string) bool { func IsEmailExist(email, roleId string) bool {
var user domain.User var user domain.User
if err := config.DB.Where("email = ?", email).First(&user).Error; err == nil { if err := config.DB.Where("email = ?", email).First(&user).Error; err == nil {
if user.RoleID == roleId {
return true return true
} }
}
return false return false
} }
func IsUsernameExist(username string) bool { func IsUsernameExist(username, roleId string) bool {
var user domain.User var user domain.User
if err := config.DB.Where("username = ?", username).First(&user).Error; err == nil { if err := config.DB.Where("username = ?", username).First(&user).Error; err == nil {
if user.RoleID == roleId {
return true return true
} }
}
return false return false
} }
func IsPhoneExist(phone string) bool { func IsPhoneExist(phone, roleId string) bool {
var user domain.User var user domain.User
if err := config.DB.Where("phone = ?", phone).First(&user).Error; err == nil { if err := config.DB.Where("phone = ?", phone).First(&user).Error; err == nil {
if user.RoleID == roleId {
return true return true
} }
}
return false return false
} }
func CreateUser(username, name, email, phone, password, roleId string) error { func CreateUser(username, name, email, phone, password, roleId string) error {
if IsEmailExist(email) {
return errors.New("email is already registered")
}
if IsUsernameExist(username) {
return errors.New("username is already registered")
}
if IsPhoneExist(phone) {
return errors.New("phone number is already registered")
}
user := domain.User{ user := domain.User{
Username: username, Username: username,
Name: name, Name: name,
@ -62,11 +55,17 @@ func CreateUser(username, name, email, phone, password, roleId string) error {
return nil return nil
} }
func GetUserByEmailOrUsername(emailOrUsername string) (domain.User, error) { func GetUserByEmailUsernameOrPhone(identifier, roleId string) (domain.User, error) {
var user domain.User var user domain.User
if err := config.DB.Where("email = ? OR username = ?", emailOrUsername, emailOrUsername).First(&user).Error; err != nil { err := config.DB.Where("email = ? OR username = ? OR phone = ?", identifier, identifier, identifier).First(&user).Error
if err != nil {
return user, errors.New("user not found") return user, errors.New("user not found")
} }
if roleId != "" && user.RoleID != roleId {
return user, errors.New("identifier found but role does not match")
}
return user, nil return user, nil
} }
@ -85,8 +84,9 @@ func GetUserByID(userID string) (domain.User, error) {
} }
func UpdateUser(user *domain.User) error { func UpdateUser(user *domain.User) error {
if err := config.DB.Save(user).Error; err != nil { if err := config.DB.Save(user).Error; err != nil {
return errors.New("failed to save user") return errors.New("failed to update user")
} }
return nil return nil
} }

View File

@ -12,18 +12,21 @@ import (
) )
func RegisterUser(username, name, email, phone, password, confirmPassword, roleId string) error { func RegisterUser(username, name, email, phone, password, confirmPassword, roleId string) error {
if password != confirmPassword { if password != confirmPassword {
return errors.New("password dan confirm password tidak cocok") return errors.New("password dan confirm password tidak cocok")
} }
if repositories.IsEmailExist(email) { if repositories.IsEmailExist(email, roleId) {
return errors.New("email is already registered") return errors.New("email is already registered with the same role")
} }
if repositories.IsUsernameExist(username) {
return errors.New("username is already registered") if repositories.IsUsernameExist(username, roleId) {
return errors.New("username is already registered with the same role")
} }
if repositories.IsPhoneExist(phone) {
return errors.New("phone number is already registered") if repositories.IsPhoneExist(phone, roleId) {
return errors.New("phone number is already registered with the same role")
} }
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
@ -39,19 +42,21 @@ func RegisterUser(username, name, email, phone, password, confirmPassword, roleI
return nil return nil
} }
func LoginUser(emailOrUsername, password string) (string, error) { func LoginUser(identifier, password string) (string, error) {
if emailOrUsername == "" || password == "" { if identifier == "" || password == "" {
return "", errors.New("email/username and password must be provided") return "", errors.New("email/username/phone and password must be provided")
} }
user, err := repositories.GetUserByEmailOrUsername(emailOrUsername) const roleId = ""
user, err := repositories.GetUserByEmailUsernameOrPhone(identifier, roleId)
if err != nil { if err != nil {
return "", errors.New("invalid email/username or password") return "", errors.New("invalid email/username/phone or password")
} }
err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)) err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
if err != nil { if err != nil {
return "", errors.New("invalid email/username or password") return "", errors.New("invalid email/username/phone or password")
} }
token := generateJWT(user.ID, user.RoleID) token := generateJWT(user.ID, user.RoleID)
@ -90,30 +95,30 @@ func UpdateUser(userID, email, username, name, phone string) error {
return errors.New("user not found") return errors.New("user not found")
} }
if email != "" && email != user.Email && repositories.IsEmailExist(email) { if email != "" && email != user.Email {
return errors.New("email is already registered") if repositories.IsEmailExist(email, user.RoleID) {
return errors.New("email is already registered with the same role")
} }
if username != "" && username != user.Username && repositories.IsUsernameExist(username) {
return errors.New("username is already registered")
}
if phone != "" && phone != user.Phone && repositories.IsPhoneExist(phone) {
return errors.New("phone number is already registered")
}
if email != "" {
user.Email = email user.Email = email
} }
if username != "" {
if username != "" && username != user.Username {
if repositories.IsUsernameExist(username, user.RoleID) {
return errors.New("username is already registered with the same role")
}
user.Username = username user.Username = username
} }
if phone != "" && phone != user.Phone {
if repositories.IsPhoneExist(phone, user.RoleID) {
return errors.New("phone number is already registered with the same role")
}
user.Phone = phone
}
if name != "" { if name != "" {
user.Name = name user.Name = name
} }
if phone != "" {
user.Phone = phone
}
err = repositories.UpdateUser(&user) err = repositories.UpdateUser(&user)
if err != nil { if err != nil {
@ -135,6 +140,11 @@ func UpdatePassword(userID, oldPassword, newPassword string) error {
return errors.New("old password is incorrect") return errors.New("old password is incorrect")
} }
err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(newPassword))
if err == nil {
return errors.New("new password cannot be the same as the old password")
}
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost) hashedPassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
if err != nil { if err != nil {
return errors.New("failed to hash new password") return errors.New("failed to hash new password")

View File

@ -1,8 +1,8 @@
package utils package utils
const ( const (
RoleMasyarakat = "3e8cd1f0-205c-488d-9bab-bb53b99a6f49" RoleMasyarakat = "63191315-c59f-4af9-91a7-367c698cc486"
RolePengepul = "88a756fd-e9ab-4257-83a6-c36a0fb944b1" RolePengepul = "bda3827a-3c61-459a-9a95-42e2bb88d737"
RolePengelola = "cb328d60-5d40-4404-bfe1-25224d1bd126" RolePengelola = "fc75351d-eded-4314-a41b-e4a901e6540c"
RoleAdministrator = "229395a8-f26d-445b-ae53-c67e5b25ea03" RoleAdministrator = "fe4a15ce-5a0c-40d0-9be0-a7d4b6d05480"
) )