Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -29,7 +29,7 @@ func FirstPasswordChangeHandler(db *sql.DB) http.HandlerFunc {
|
||||
r.Method,
|
||||
r.URL.Path,
|
||||
)
|
||||
http.Error(w, "unauthorized: token missing or invalid", http.StatusUnauthorized)
|
||||
http.Error(w, "yetkisiz: token eksik veya geçersiz", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -39,14 +39,14 @@ func FirstPasswordChangeHandler(db *sql.DB) http.HandlerFunc {
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, "invalid payload", http.StatusBadRequest)
|
||||
http.Error(w, "geçersiz istek gövdesi", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
req.CurrentPassword = strings.TrimSpace(req.CurrentPassword)
|
||||
req.NewPassword = strings.TrimSpace(req.NewPassword)
|
||||
if req.CurrentPassword == "" || req.NewPassword == "" {
|
||||
http.Error(w, "password fields required", http.StatusUnprocessableEntity)
|
||||
http.Error(w, "şifre alanları zorunludur", http.StatusUnprocessableEntity)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ func FirstPasswordChangeHandler(db *sql.DB) http.HandlerFunc {
|
||||
claims.ID,
|
||||
mkErr,
|
||||
)
|
||||
http.Error(w, "user lookup failed", http.StatusInternalServerError)
|
||||
http.Error(w, "kullanıcı sorgulama hatası", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -79,20 +79,30 @@ func FirstPasswordChangeHandler(db *sql.DB) http.HandlerFunc {
|
||||
claims.ID,
|
||||
claims.Username,
|
||||
)
|
||||
http.Error(w, "mevcut sifre hatali", http.StatusUnauthorized)
|
||||
http.Error(w, "mevcut şifre hatalı", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
var err error
|
||||
legacyUser, err = legacyRepo.GetLegacyUserForLogin(claims.Username)
|
||||
if err != nil || legacyUser == nil || !legacyUser.IsActive || int64(legacyUser.ID) != claims.ID {
|
||||
if err != nil || legacyUser == nil || !legacyUser.IsActive {
|
||||
log.Printf(
|
||||
"FIRST_PASSWORD_CHANGE 401 reason=legacy_user_not_found user_id=%d username=%s err=%v",
|
||||
claims.ID,
|
||||
claims.Username,
|
||||
err,
|
||||
)
|
||||
http.Error(w, "unauthorized: user not found", http.StatusUnauthorized)
|
||||
http.Error(w, "yetkisiz: kullanıcı bulunamadı", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
if !hasMkUser && int64(legacyUser.ID) != claims.ID {
|
||||
log.Printf(
|
||||
"FIRST_PASSWORD_CHANGE 401 reason=legacy_id_mismatch user_id=%d legacy_id=%d username=%s",
|
||||
claims.ID,
|
||||
legacyUser.ID,
|
||||
claims.Username,
|
||||
)
|
||||
http.Error(w, "yetkisiz: kullanıcı bulunamadı", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -102,7 +112,7 @@ func FirstPasswordChangeHandler(db *sql.DB) http.HandlerFunc {
|
||||
claims.ID,
|
||||
claims.Username,
|
||||
)
|
||||
http.Error(w, "mevcut sifre hatali", http.StatusUnauthorized)
|
||||
http.Error(w, "mevcut şifre hatalı", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -117,13 +127,13 @@ func FirstPasswordChangeHandler(db *sql.DB) http.HandlerFunc {
|
||||
bcrypt.DefaultCost,
|
||||
)
|
||||
if err != nil {
|
||||
http.Error(w, "password hash error", http.StatusInternalServerError)
|
||||
http.Error(w, "şifre hash hatası", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
tx, err := db.Begin()
|
||||
if err != nil {
|
||||
http.Error(w, "transaction error", http.StatusInternalServerError)
|
||||
http.Error(w, "işlem başlatılamadı", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer tx.Rollback()
|
||||
@@ -146,7 +156,7 @@ func FirstPasswordChangeHandler(db *sql.DB) http.HandlerFunc {
|
||||
claims.ID,
|
||||
err,
|
||||
)
|
||||
http.Error(w, "password update failed", http.StatusInternalServerError)
|
||||
http.Error(w, "şifre güncellenemedi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -156,21 +166,31 @@ func FirstPasswordChangeHandler(db *sql.DB) http.HandlerFunc {
|
||||
"FIRST_PASSWORD_CHANGE 500 reason=password_update_no_rows user_id=%d",
|
||||
claims.ID,
|
||||
)
|
||||
http.Error(w, "password update failed", http.StatusInternalServerError)
|
||||
http.Error(w, "şifre güncellenemedi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if legacyUser == nil {
|
||||
// Defensive fallback, should not happen.
|
||||
legacyUser, err = legacyRepo.GetLegacyUserForLogin(claims.Username)
|
||||
if err != nil || legacyUser == nil || int64(legacyUser.ID) != claims.ID {
|
||||
if err != nil || legacyUser == nil {
|
||||
log.Printf(
|
||||
"FIRST_PASSWORD_CHANGE 500 reason=legacy_reload_failed user_id=%d username=%s err=%v",
|
||||
claims.ID,
|
||||
claims.Username,
|
||||
err,
|
||||
)
|
||||
http.Error(w, "legacy user reload failed", http.StatusInternalServerError)
|
||||
http.Error(w, "legacy kullanıcı yeniden yüklenemedi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if !hasMkUser && int64(legacyUser.ID) != claims.ID {
|
||||
log.Printf(
|
||||
"FIRST_PASSWORD_CHANGE 500 reason=legacy_reload_id_mismatch user_id=%d legacy_id=%d username=%s",
|
||||
claims.ID,
|
||||
legacyUser.ID,
|
||||
claims.Username,
|
||||
)
|
||||
http.Error(w, "legacy kullanıcı yeniden yüklenemedi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -222,7 +242,7 @@ func FirstPasswordChangeHandler(db *sql.DB) http.HandlerFunc {
|
||||
claims.Username,
|
||||
err,
|
||||
)
|
||||
http.Error(w, "legacy migration failed", http.StatusInternalServerError)
|
||||
http.Error(w, "legacy geçişi başarısız", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -235,7 +255,7 @@ func FirstPasswordChangeHandler(db *sql.DB) http.HandlerFunc {
|
||||
claims.ID,
|
||||
err,
|
||||
)
|
||||
http.Error(w, "commit failed", http.StatusInternalServerError)
|
||||
http.Error(w, "işlem tamamlanamadı", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -262,7 +282,7 @@ func FirstPasswordChangeHandler(db *sql.DB) http.HandlerFunc {
|
||||
false,
|
||||
)
|
||||
if err != nil {
|
||||
http.Error(w, "token generation failed", http.StatusInternalServerError)
|
||||
http.Error(w, "token üretilemedi", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,76 @@ type LoginRequest struct {
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
func ensureLegacyUserReadyForSession(db *sql.DB, legacyUser *models.User) (int64, error) {
|
||||
desiredID := int64(legacyUser.ID)
|
||||
|
||||
_, err := db.Exec(`
|
||||
INSERT INTO mk_dfusr (
|
||||
id,
|
||||
code,
|
||||
username,
|
||||
email,
|
||||
full_name,
|
||||
mobile,
|
||||
address,
|
||||
is_active,
|
||||
password_hash,
|
||||
force_password_change,
|
||||
created_at,
|
||||
updated_at,
|
||||
last_updated_date
|
||||
)
|
||||
VALUES (
|
||||
$1,$2,$3,$4,$5,$6,$7,$8,'',true,NOW(),NOW(),NOW()
|
||||
)
|
||||
ON CONFLICT (id)
|
||||
DO UPDATE SET
|
||||
code = EXCLUDED.code,
|
||||
username = EXCLUDED.username,
|
||||
email = EXCLUDED.email,
|
||||
full_name = COALESCE(NULLIF(EXCLUDED.full_name, ''), mk_dfusr.full_name),
|
||||
mobile = COALESCE(NULLIF(EXCLUDED.mobile, ''), mk_dfusr.mobile),
|
||||
address = COALESCE(NULLIF(EXCLUDED.address, ''), mk_dfusr.address),
|
||||
is_active = EXCLUDED.is_active,
|
||||
force_password_change = true,
|
||||
updated_at = NOW(),
|
||||
last_updated_date = NOW()
|
||||
`,
|
||||
desiredID,
|
||||
strings.TrimSpace(legacyUser.Username),
|
||||
strings.TrimSpace(legacyUser.Username),
|
||||
strings.TrimSpace(legacyUser.Email),
|
||||
strings.TrimSpace(legacyUser.FullName),
|
||||
strings.TrimSpace(legacyUser.Mobile),
|
||||
strings.TrimSpace(legacyUser.Address),
|
||||
legacyUser.IsActive,
|
||||
)
|
||||
if err == nil {
|
||||
return desiredID, nil
|
||||
}
|
||||
|
||||
mkRepo := repository.NewMkUserRepository(db)
|
||||
existing, lookupErr := mkRepo.GetByUsername(legacyUser.Username)
|
||||
if lookupErr != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
_, updErr := db.Exec(`
|
||||
UPDATE mk_dfusr
|
||||
SET
|
||||
is_active = $1,
|
||||
force_password_change = true,
|
||||
updated_at = NOW(),
|
||||
last_updated_date = NOW()
|
||||
WHERE id = $2
|
||||
`, legacyUser.IsActive, existing.ID)
|
||||
if updErr != nil {
|
||||
return 0, updErr
|
||||
}
|
||||
|
||||
return existing.ID, nil
|
||||
}
|
||||
|
||||
func LoginHandler(db *sql.DB) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
@@ -137,8 +207,15 @@ func LoginHandler(db *sql.DB) http.HandlerFunc {
|
||||
// 3️⃣ LEGACY SESSION (PENDING MIGRATION)
|
||||
// - mk_dfusr migration is completed in /api/password/change
|
||||
// ==================================================
|
||||
mkID, err := ensureLegacyUserReadyForSession(db, legacyUser)
|
||||
if err != nil {
|
||||
log.Printf("LEGACY LOGIN MIGRATION BIND FAILED username=%s err=%v", login, err)
|
||||
http.Error(w, "Giriş yapılamadı", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
mkUser = &models.MkUser{
|
||||
ID: int64(legacyUser.ID),
|
||||
ID: mkID,
|
||||
Username: legacyUser.Username,
|
||||
Email: legacyUser.Email,
|
||||
IsActive: legacyUser.IsActive,
|
||||
@@ -150,7 +227,7 @@ func LoginHandler(db *sql.DB) http.HandlerFunc {
|
||||
auditlog.Write(auditlog.ActivityLog{
|
||||
ActionType: "LEGACY_USER_LOGIN_PENDING_MIGRATION",
|
||||
ActionCategory: "security",
|
||||
Description: "legacy login ok, first password change required",
|
||||
Description: "legacy giriş başarılı, ilk şifre değişikliği gerekli",
|
||||
IsSuccess: true,
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user