Medication Update
This commit is contained in:
@@ -106,7 +106,7 @@ func (r *repository) FindUserByEmail(ctx context.Context, email string) (*User,
|
||||
|
||||
var user User
|
||||
q := query.DynamicQuery{
|
||||
From: "users", // GORM default table name for User struct
|
||||
From: "public.users", // Gunakan nama tabel yang eksplisit
|
||||
Filters: []query.FilterGroup{{
|
||||
Filters: []query.DynamicFilter{
|
||||
query.CreateEqualFilter("Email", email),
|
||||
@@ -117,7 +117,8 @@ func (r *repository) FindUserByEmail(ctx context.Context, email string) (*User,
|
||||
|
||||
if err := r.qb.ExecuteQueryRow(ctx, sqlxDB, q, &user); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, nil // Not found is not an error, service layer will handle it
|
||||
// Not found is not an error, service layer will handle it
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("failed to find user by email: %w", err)
|
||||
}
|
||||
@@ -159,7 +160,7 @@ func (r *repository) ChangePasswordInTx(ctx context.Context, userID int64, newPa
|
||||
}}
|
||||
|
||||
// Berikan objek transaksi 'tx' ke Query Builder
|
||||
if _, err = r.qb.ExecuteUpdate(ctx, tx, "users", updateData, filters); err != nil {
|
||||
if _, err = r.qb.ExecuteUpdate(ctx, tx, "public.users", updateData, filters); err != nil {
|
||||
return fmt.Errorf("failed to update password in tx: %w", err)
|
||||
}
|
||||
|
||||
@@ -170,7 +171,7 @@ func (r *repository) ChangePasswordInTx(ctx context.Context, userID int64, newPa
|
||||
}
|
||||
|
||||
// Gunakan objek transaksi 'tx' yang sama
|
||||
if _, err = r.qb.ExecuteInsert(ctx, tx, "user_activity_logs", logData); err != nil {
|
||||
if _, err = r.qb.ExecuteInsert(ctx, tx, "public.user_activity_logs", logData); err != nil {
|
||||
// Asumsikan tabel 'user_activity_logs' ada
|
||||
return fmt.Errorf("failed to log activity in tx: %w", err)
|
||||
}
|
||||
@@ -187,7 +188,7 @@ func (r *repository) FindUserByID(ctx context.Context, id int64) (*User, error)
|
||||
|
||||
var user User
|
||||
q := query.DynamicQuery{
|
||||
From: "users", // GORM default table name for User struct
|
||||
From: "public.users",
|
||||
Filters: []query.FilterGroup{{
|
||||
Filters: []query.DynamicFilter{
|
||||
query.CreateEqualFilter("Id", id),
|
||||
@@ -198,7 +199,8 @@ func (r *repository) FindUserByID(ctx context.Context, id int64) (*User, error)
|
||||
|
||||
if err := r.qb.ExecuteQueryRow(ctx, sqlxDB, q, &user); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, nil // Not found is not an error, service layer will handle it
|
||||
// Not found is not an error, service layer will handle it
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("failed to find user by id: %w", err)
|
||||
}
|
||||
@@ -213,7 +215,7 @@ func (r *repository) FindRefreshToken(ctx context.Context, token string) (*Store
|
||||
|
||||
var stored StoredToken
|
||||
q := query.DynamicQuery{
|
||||
From: "refresh_tokens",
|
||||
From: "public.refresh_tokens",
|
||||
Filters: []query.FilterGroup{{
|
||||
Filters: []query.DynamicFilter{query.CreateEqualFilter("Token", token)},
|
||||
}},
|
||||
@@ -238,5 +240,5 @@ func (r *repository) RevokeAndSaveTokens(ctx context.Context, oldToken string, n
|
||||
|
||||
// TODO: Sesuaikan dengan struktur tabel Refresh Token yang Anda miliki di database
|
||||
// Ini adalah stub untuk memenuhi kontrak interface
|
||||
return writeDB.WithContext(ctx).Exec("UPDATE refresh_tokens SET is_revoked = ? WHERE token = ?", true, oldToken).Error
|
||||
return writeDB.WithContext(ctx).Exec("UPDATE public.refresh_tokens SET is_revoked = ? WHERE token = ?", true, oldToken).Error
|
||||
}
|
||||
|
||||
+50
-21
@@ -14,6 +14,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
type StoredToken struct {
|
||||
@@ -53,25 +54,39 @@ func NewService(cmdRepo CommandRepository, queryRepo QueryRepository, cache *cac
|
||||
|
||||
// Login mengimplementasikan otentikasi menggunakan data dummy untuk keperluan testing.
|
||||
func (s *service) Login(ctx context.Context, req LoginRequest) (*LoginResponse, error) {
|
||||
// Simulasi pengecekan kredensial dengan beberapa akun dummy
|
||||
type dummyUser struct {
|
||||
Password string
|
||||
UserID string
|
||||
RoleID string
|
||||
Name string
|
||||
// Prioritaskan pengecekan dummy users untuk development, terutama untuk akun sistem seperti worker.
|
||||
if dummyUser, exists := dummyUsers[req.Email]; exists {
|
||||
if dummyUser.Password == req.Password {
|
||||
// Jika kredensial cocok dengan dummy user, langsung generate token.
|
||||
return s.generateTokens(dummyUser.UserID, req.Email, dummyUser.RoleID, dummyUser.Name)
|
||||
}
|
||||
}
|
||||
|
||||
dummyUsers := map[string]dummyUser{
|
||||
"[email protected]": {"password123", "1001", "admin", "Admin Dummy"},
|
||||
"[email protected]": {"password123", "1002", "user", "User Dummy"},
|
||||
"[email protected]": {"password123", "1003", "manager", "Manager Dummy"},
|
||||
// Jika tidak ditemukan di dummy users atau password salah, lanjutkan pengecekan ke database.
|
||||
user, err := s.queryRepo.FindUserByEmail(ctx, req.Email)
|
||||
if err != nil {
|
||||
// Jika terjadi error saat query, kembalikan internal error
|
||||
return nil, errors.InternalError().Cause(err).Message("Gagal mencari pengguna").Build()
|
||||
}
|
||||
|
||||
user, exists := dummyUsers[req.Email]
|
||||
if !exists || user.Password != req.Password {
|
||||
return nil, errors.UnauthorizedError().Message("Email atau password salah. Coba: [email protected], [email protected], [email protected] (password123)").Build()
|
||||
// Jika pengguna tidak ditemukan di mana pun (dummy atau DB).
|
||||
if user == nil {
|
||||
return nil, errors.UnauthorizedError().Message("Email atau password salah.").Build()
|
||||
}
|
||||
|
||||
// Jika pengguna ditemukan di database, validasi password
|
||||
// Asumsi password di database di-hash menggunakan bcrypt
|
||||
err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password))
|
||||
if err != nil {
|
||||
// Jika password tidak cocok
|
||||
return nil, errors.UnauthorizedError().Message("Email atau password salah.").Build()
|
||||
}
|
||||
|
||||
// Jika login berhasil, generate token
|
||||
return s.generateTokens(fmt.Sprintf("%d", user.Id), user.Email, fmt.Sprintf("%d", *user.RoleID), user.Email)
|
||||
}
|
||||
|
||||
func (s *service) generateTokens(userID, email, roleID, name string) (*LoginResponse, error) {
|
||||
secret := os.Getenv("JWT_SECRET")
|
||||
if secret == "" {
|
||||
secret = "fallback_secret_key_change_in_production"
|
||||
@@ -79,20 +94,20 @@ func (s *service) Login(ctx context.Context, req LoginRequest) (*LoginResponse,
|
||||
|
||||
// Buat Access Token baru (Umur pendek, misal 15 Menit)
|
||||
accessToken := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
||||
"user_id": user.UserID,
|
||||
"email": req.Email,
|
||||
"role_id": user.RoleID,
|
||||
"name": user.Name,
|
||||
"user_id": userID,
|
||||
"email": email,
|
||||
"role_id": roleID,
|
||||
"name": name,
|
||||
"exp": time.Now().Add(60 * time.Minute).Unix(),
|
||||
})
|
||||
newAccessTokenStr, _ := accessToken.SignedString([]byte(secret))
|
||||
|
||||
// Buat Refresh Token baru (Umur panjang, misal 7 Hari)
|
||||
refreshToken := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
||||
"user_id": user.UserID,
|
||||
"email": req.Email,
|
||||
"role_id": user.RoleID,
|
||||
"name": user.Name,
|
||||
"user_id": userID,
|
||||
"email": email,
|
||||
"role_id": roleID,
|
||||
"name": name,
|
||||
"exp": time.Now().Add(7 * 24 * time.Hour).Unix(),
|
||||
})
|
||||
newRefreshTokenStr, _ := refreshToken.SignedString([]byte(secret))
|
||||
@@ -106,6 +121,20 @@ func (s *service) Login(ctx context.Context, req LoginRequest) (*LoginResponse,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type dummyUser struct {
|
||||
Password string
|
||||
UserID string
|
||||
RoleID string
|
||||
Name string
|
||||
}
|
||||
|
||||
var dummyUsers = map[string]dummyUser{
|
||||
"[email protected]": {"password123", "1001", "admin", "Admin Dummy"},
|
||||
"[email protected]": {"password123", "1002", "user", "User Dummy"},
|
||||
"[email protected]": {"password123", "1003", "manager", "Manager Dummy"},
|
||||
"[email protected]": {"password123", "1004", "worker", "Worker Dummy"},
|
||||
}
|
||||
|
||||
// Register mengimplementasikan pendaftaran user dengan respons data json dummy.
|
||||
func (s *service) Register(ctx context.Context, req RegisterRequest) (interface{}, error) {
|
||||
// Mengembalikan response dummy seolah-olah user berhasil dibuat di DB
|
||||
|
||||
Reference in New Issue
Block a user