Compare commits

...

10 Commits

Author SHA1 Message Date
areeqakbr 40178e7fcc delete alphanum tag 2025-02-20 16:32:00 +07:00
areeqakbr 5985ebcb4a adding data for login information 2025-02-20 14:02:12 +07:00
areeqakbr e9d2aeda00 increasing request amount 2025-02-20 13:31:24 +07:00
areeqakbr 41eae2ccc4 edit cors middleware 2025-02-20 13:28:18 +07:00
areeqakbr 7a25952b1d adding cors handlers for routes 2025-02-20 12:44:32 +07:00
areeqakbr 5a613d31f5 delete ratelogin limitter 2025-02-20 12:00:55 +07:00
areeqakbr ef6721af9a adding options handle 2025-02-20 11:50:54 +07:00
areeqakbr a5901d9ac5 edit cors middleware 2025-02-20 11:48:25 +07:00
areeqakbr a5fdd64877 edit cors 2025-02-20 11:21:45 +07:00
areeqakbr d660a030e7 edit the cors headers 2025-02-20 11:17:21 +07:00
5 changed files with 52 additions and 39 deletions

View File

@ -18,8 +18,11 @@ type UsersController struct {
func (uc *UsersController) Route() { func (uc *UsersController) Route() {
rg:= uc.rg.Group("/users") rg:= uc.rg.Group("/users")
rg.Use(middleware.RateLoginMiddleware())
rg.Use(middleware.CORSMiddleware()) rg.Use(middleware.CORSMiddleware())
rg.Use(middleware.RateLoginMiddleware())
rg.OPTIONS("/login", func(c *gin.Context) {
c.Status(http.StatusNoContent)
})
{ {
rg.POST("/login", uc.Login()) rg.POST("/login", uc.Login())
} }
@ -44,7 +47,7 @@ func (uc *UsersController) Login() gin.HandlerFunc {
return return
} }
token, err := uc.ac.Login(login) token,role,name, err := uc.ac.Login(login)
if err != nil { if err != nil {
common.ErrorResponses(c, http.StatusUnauthorized, err.Error()) common.ErrorResponses(c, http.StatusUnauthorized, err.Error())
@ -52,7 +55,7 @@ func (uc *UsersController) Login() gin.HandlerFunc {
} }
common.SingleResponses(c, "Login success", gin.H{"token": token}) common.SingleResponses(c, "Login success", gin.H{"token": token, "role": role, "name": name})
} }
} }

View File

@ -1,21 +1,23 @@
package middleware package middleware
import ( import (
"github.com/gin-gonic/gin" "net/http"
"github.com/gin-gonic/gin"
) )
func CORSMiddleware() gin.HandlerFunc { func CORSMiddleware() gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "*") c.Writer.Header().Set("Access-Control-Allow-Origin", "*") // Change to specific domains if needed
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, DELETE")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With") c.Writer.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type")
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, DELETE")
if c.Request.Method == "OPTIONS" { // Allow OPTIONS method to pass through
c.AbortWithStatus(204) if c.Request.Method == http.MethodOptions {
return c.AbortWithStatus(http.StatusNoContent)
} return
}
c.Next() c.Next()
} }
} }

View File

@ -34,7 +34,7 @@ func getLoginLimiter() *rate.Limiter {
limiter, exists := rateLimiters["login"] limiter, exists := rateLimiters["login"]
if !exists { if !exists {
limiter = rate.NewLimiter(rate.Every(1*time.Minute), 4) // 5 request per second with a burst of 10 requests limiter = rate.NewLimiter(rate.Every(1*time.Minute), 10) // 5 request per second with a burst of 10 requests
rateLimiters["login"] = limiter rateLimiters["login"] = limiter
} }
@ -43,6 +43,10 @@ func getLoginLimiter() *rate.Limiter {
func RateLimitMiddleware() gin.HandlerFunc{ func RateLimitMiddleware() gin.HandlerFunc{
return func(c *gin.Context) { return func(c *gin.Context) {
if c.Request.Method == http.MethodOptions {
c.Next()
return
}
userID, exists := c.Get("userID") userID, exists := c.Get("userID")
if !exists { if !exists {
common.ErrorResponses(c, http.StatusUnauthorized, "Unauthorized: No user ID found") common.ErrorResponses(c, http.StatusUnauthorized, "Unauthorized: No user ID found")
@ -64,6 +68,10 @@ func RateLimitMiddleware() gin.HandlerFunc{
func RateLoginMiddleware() gin.HandlerFunc{ func RateLoginMiddleware() gin.HandlerFunc{
return func(c *gin.Context) { return func(c *gin.Context) {
if c.Request.Method == http.MethodOptions {
c.Next()
return
}
limiter := getLoginLimiter() limiter := getLoginLimiter()
if !limiter.Allow() { if !limiter.Allow() {

View File

@ -11,7 +11,7 @@ type TowerDTO struct {
type UpdateTowerDTO struct { type UpdateTowerDTO struct {
DeviceID *string `json:"device_id,omitempty" validate:"omitempty,min=3"` DeviceID *string `json:"device_id,omitempty" validate:"omitempty,min=3"`
TowerCode *string `json:"tower_code,omitempty" validate:"omitempty,alphanum"` TowerCode *string `json:"tower_code,omitempty" validate:"omitempty"`
Longitude *float64 `json:"longitude,omitempty" validate:"omitempty,longitude"` Longitude *float64 `json:"longitude,omitempty" validate:"omitempty,longitude"`
Latitude *float64 `json:"latitude,omitempty" validate:"omitempty,latitude"` Latitude *float64 `json:"latitude,omitempty" validate:"omitempty,latitude"`
} }

View File

@ -20,7 +20,7 @@ import (
) )
type AuthUsecase interface { type AuthUsecase interface {
Login(login dto.UserLoginDTO) (string, error) Login(login dto.UserLoginDTO) (string,string, string ,error)
Logout(token string) error Logout(token string) error
} }
@ -38,20 +38,20 @@ func NewAuthUsecase(userRepo repository.UsersRepo, cfg *config.Config) AuthUseca
} }
} }
func (u *authUsecase) Login(login dto.UserLoginDTO) (string, error) { func (u *authUsecase) Login(login dto.UserLoginDTO) (string, string, string, error) {
err := u.validate.Struct(login) err := u.validate.Struct(login)
if err != nil { if err != nil {
return "", err return "","","", err
} }
payload, err := json.Marshal(login) payload, err := json.Marshal(login)
if err != nil { if err != nil {
return "", err return "","","", err
} }
req, err := http.NewRequest("POST", u.cfg.LoginAPI, bytes.NewBuffer(payload)) req, err := http.NewRequest("POST", u.cfg.LoginAPI, bytes.NewBuffer(payload))
if err != nil { if err != nil {
return "", err return "","","", err
} }
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
@ -60,69 +60,69 @@ func (u *authUsecase) Login(login dto.UserLoginDTO) (string, error) {
client := &http.Client{} client := &http.Client{}
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
return "", err return "","","", err
} }
defer resp.Body.Close() defer resp.Body.Close()
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
return "", errors.New("wrong password or username") return "","","", errors.New("wrong password or username")
} }
body, err := ioutil.ReadAll(resp.Body) body, err := ioutil.ReadAll(resp.Body)
if err != nil { if err != nil {
return "", err return "","","", err
} }
var authResponse res.AuthResponses var authResponse res.AuthResponses
err = json.Unmarshal(body, &authResponse) err = json.Unmarshal(body, &authResponse)
if err != nil { if err != nil {
return "", err return "","","", err
} }
token := authResponse.Token token := authResponse.Token
meReq, err := http.NewRequest("POST", u.cfg.AuthMeAPI, nil) meReq, err := http.NewRequest("POST", u.cfg.AuthMeAPI, nil)
if err != nil { if err != nil {
return "", err return "","","", err
} }
meReq.Header.Set("Authorization", "Bearer "+token) meReq.Header.Set("Authorization", "Bearer "+token)
meReq.Header.Set("Accept", "application/json") meReq.Header.Set("Accept", "application/json")
meResp, err := client.Do(meReq) meResp, err := client.Do(meReq)
if err != nil { if err != nil {
return "",err return "","","", err
} }
defer meResp.Body.Close() defer meResp.Body.Close()
if meResp.StatusCode != http.StatusOK { if meResp.StatusCode != http.StatusOK {
return "", errors.New("failed to validate token: " + meResp.Status) return "","","", errors.New("failed to validate token: " + meResp.Status)
} }
meBody, err := ioutil.ReadAll(meResp.Body) meBody, err := ioutil.ReadAll(meResp.Body)
if err != nil { if err != nil {
return "", err return "","","", err
} }
var meResponse res.AuthMeResponse var meResponse res.AuthMeResponse
err = json.Unmarshal(meBody, &meResponse) err = json.Unmarshal(meBody, &meResponse)
if err != nil { if err != nil {
return "", err return "","","", err
} }
departemen := meResponse.Data.Departemen departemen := meResponse.Data.Departemen
if departemen != "Teknisi" { if departemen != "Teknisi" {
return "", errors.New("user is not a technician") return "","","", errors.New("user is not a technician")
} }
role , err := u.userRepo.GetRoleByDepartment(departemen) role , err := u.userRepo.GetRoleByDepartment(departemen)
if err != nil { if err != nil {
return "", err return "","","", err
} }
password, err := utils.HashPassword(login.Password) password, err := utils.HashPassword(login.Password)
if err != nil { if err != nil {
return "error while hasing password: ", err return "error while hasing password: ","", "", err
} }
isUserExist, err := u.userRepo.GetUserByUsername(login.Username) isUserExist, err := u.userRepo.GetUserByUsername(login.Username)
@ -130,12 +130,12 @@ func (u *authUsecase) Login(login dto.UserLoginDTO) (string, error) {
if isUserExist.ID != uuid.Nil { if isUserExist.ID != uuid.Nil {
// Validate the password // Validate the password
if !utils.CheckPasswordHash(login.Password, isUserExist.Password) { if !utils.CheckPasswordHash(login.Password, isUserExist.Password) {
return "", errors.New("incorrect password") return "","","", errors.New("incorrect password")
} }
return token, nil return token, role.Name, isUserExist.Name, nil
}else if err != nil && err != gorm.ErrRecordNotFound { }else if err != nil && err != gorm.ErrRecordNotFound {
return "ERROR WHILE SEARCHING USERNAME", err return "ERROR WHILE SEARCHING USERNAME","", "", err
} }
@ -151,10 +151,10 @@ func (u *authUsecase) Login(login dto.UserLoginDTO) (string, error) {
err = u.userRepo.Post(user) err = u.userRepo.Post(user)
if err != nil { if err != nil {
return "", err return "","","", err
} }
return token,nil return token, user.Role.Name, user.Name, nil
} }
func (u *authUsecase) Logout(token string) error { func (u *authUsecase) Logout(token string) error {