package usecase import ( "bytes" "encoding/json" "errors" "io/ioutil" "net/http" "time" "users_management/m/config" "users_management/m/model/dto" "users_management/m/model/dto/res" "users_management/m/model/entity" "users_management/m/repository" "users_management/m/utils" "github.com/go-playground/validator/v10" "github.com/google/uuid" "gorm.io/gorm" ) type AuthUsecase interface { Login(login dto.UserLoginDTO) (string,string, string ,error) Logout(token string) error } type authUsecase struct { userRepo repository.UsersRepo validate *validator.Validate cfg *config.Config } func NewAuthUsecase(userRepo repository.UsersRepo, cfg *config.Config) AuthUsecase { return &authUsecase{ userRepo: userRepo, validate: validator.New(), cfg: cfg, } } func (u *authUsecase) Login(login dto.UserLoginDTO) (string, string, string, error) { err := u.validate.Struct(login) if err != nil { return "","","", err } payload, err := json.Marshal(login) if err != nil { return "","","", err } req, err := http.NewRequest("POST", u.cfg.LoginAPI, bytes.NewBuffer(payload)) if err != nil { return "","","", err } req.Header.Set("Content-Type", "application/json") req.Header.Set("Accept", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { return "","","", err } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return "","","", errors.New("wrong password or username") } body, err := ioutil.ReadAll(resp.Body) if err != nil { return "","","", err } var authResponse res.AuthResponses err = json.Unmarshal(body, &authResponse) if err != nil { return "","","", err } token := authResponse.Token meReq, err := http.NewRequest("POST", u.cfg.AuthMeAPI, nil) if err != nil { return "","","", err } meReq.Header.Set("Authorization", "Bearer "+token) meReq.Header.Set("Accept", "application/json") meResp, err := client.Do(meReq) if err != nil { return "","","", err } defer meResp.Body.Close() if meResp.StatusCode != http.StatusOK { return "","","", errors.New("failed to validate token: " + meResp.Status) } meBody, err := ioutil.ReadAll(meResp.Body) if err != nil { return "","","", err } var meResponse res.AuthMeResponse err = json.Unmarshal(meBody, &meResponse) if err != nil { return "","","", err } departemen := meResponse.Data.Departemen if departemen != "Teknisi" { return "","","", errors.New("user is not a technician") } role , err := u.userRepo.GetRoleByDepartment(departemen) if err != nil { return "","","", err } password, err := utils.HashPassword(login.Password) if err != nil { return "error while hasing password: ","", "", err } isUserExist, err := u.userRepo.GetUserByUsername(login.Username) if isUserExist.ID != uuid.Nil { // Validate the password if !utils.CheckPasswordHash(login.Password, isUserExist.Password) { return "","","", errors.New("incorrect password") } return token, role.Name, isUserExist.Name, nil }else if err != nil && err != gorm.ErrRecordNotFound { return "ERROR WHILE SEARCHING USERNAME","", "", err } user := entity.User{ ID: uuid.New(), Name: meResponse.Data.Nama, Username: login.Username, Password: password, RoleID: role.Id, CreatedAt: time.Now(), UpdatedAt: time.Now(), } err = u.userRepo.Post(user) if err != nil { return "","","", err } return token, user.Role.Name, user.Name, nil } func (u *authUsecase) Logout(token string) error { req, err := http.NewRequest("POST", u.cfg.LogoutAPI, nil) if err != nil { return err } req.Header.Set("Authorization", "Bearer "+token) req.Header.Set("Accept", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return errors.New("failed to logout: " + resp.Status) } return nil }