Merge remote-tracking branch 'origin/master'

This commit is contained in:
2026-02-16 17:20:58 +03:00
parent 0a14f87a3e
commit 484512ff25
4 changed files with 170 additions and 2 deletions

View File

@@ -325,6 +325,11 @@ func InitRoutes(pgDB *sql.DB, mssql *sql.DB, ml *mailer.GraphMailer) *mux.Router
"user", "update",
wrapV3(routes.UserDetailRoute(pgDB)),
)
bindV3(r, pgDB,
"/api/users/{id}", "DELETE",
"user", "delete",
wrapV3(routes.UserDetailRoute(pgDB)),
)
bindV3(r, pgDB,
"/api/users/{id}/admin-reset-password", "POST",

View File

@@ -1,6 +1,7 @@
package routes
import (
"bssapp-backend/auth"
"bssapp-backend/internal/auditlog"
"bssapp-backend/internal/mailer"
"bssapp-backend/internal/security"
@@ -51,6 +52,8 @@ func UserDetailRoute(db *sql.DB) http.Handler {
handleUserGet(db, w, userID)
case http.MethodPut:
handleUserUpdate(db, w, r, userID)
case http.MethodDelete:
handleUserDelete(db, w, r, userID)
case http.MethodOptions:
w.WriteHeader(http.StatusOK)
default:
@@ -323,6 +326,102 @@ func handleUserUpdate(db *sql.DB, w http.ResponseWriter, r *http.Request, userID
_ = json.NewEncoder(w).Encode(map[string]any{"success": true})
}
// ======================================================
// 🗑️ DELETE USER (HARD DELETE)
// ======================================================
func handleUserDelete(db *sql.DB, w http.ResponseWriter, r *http.Request, userID int64) {
claims, _ := auth.GetClaimsFromContext(r.Context())
if claims != nil && int64(claims.ID) == userID {
http.Error(w, "Kendi kullanicinizi silemezsiniz", http.StatusConflict)
return
}
tx, err := db.Begin()
if err != nil {
http.Error(w, "Transaction baslatilamadi", http.StatusInternalServerError)
return
}
defer tx.Rollback()
var username string
_ = tx.QueryRow(`
SELECT username
FROM mk_dfusr
WHERE id = $1
`, userID).Scan(&username)
if strings.TrimSpace(username) == "" {
_ = tx.QueryRow(`
SELECT code
FROM dfusr
WHERE id = $1
`, userID).Scan(&username)
}
if strings.TrimSpace(username) == "" {
http.Error(w, "Kullanici bulunamadi", http.StatusNotFound)
return
}
cleanupQueries := []string{
`DELETE FROM mk_refresh_tokens WHERE mk_user_id = $1`,
`DELETE FROM mk_dfusr_password_reset WHERE mk_dfusr_id = $1`,
`DELETE FROM dfusr_password_reset WHERE dfusr_id = $1`,
`DELETE FROM mk_sys_user_permissions WHERE user_id = $1`,
`DELETE FROM dfrole_usr WHERE dfusr_id = $1`,
`DELETE FROM dfusr_dprt WHERE dfusr_id = $1`,
`DELETE FROM dfusr_piyasa WHERE dfusr_id = $1`,
`DELETE FROM dfusr_nebim_user WHERE dfusr_id = $1`,
}
for _, q := range cleanupQueries {
if _, err := tx.Exec(q, userID); err != nil {
log.Printf("❌ [UserDetail] cleanup failed user_id=%d err=%v query=%s", userID, err, q)
http.Error(w, "Kullanici baglantilari silinemedi", http.StatusInternalServerError)
return
}
}
if _, err := tx.Exec(`DELETE FROM mk_dfusr WHERE id = $1`, userID); err != nil {
log.Printf("❌ [UserDetail] delete mk_dfusr failed user_id=%d err=%v", userID, err)
http.Error(w, "Kullanici silinemedi", http.StatusInternalServerError)
return
}
if _, err := tx.Exec(`DELETE FROM dfusr WHERE id = $1`, userID); err != nil {
log.Printf("❌ [UserDetail] delete dfusr failed user_id=%d err=%v", userID, err)
http.Error(w, "Kullanici silinemedi", http.StatusInternalServerError)
return
}
if err := tx.Commit(); err != nil {
log.Printf("❌ [UserDetail] delete commit failed user_id=%d err=%v", userID, err)
http.Error(w, "Commit basarisiz", http.StatusInternalServerError)
return
}
if claims != nil {
auditlog.Enqueue(r.Context(), auditlog.ActivityLog{
ActionType: "user_delete",
ActionCategory: "user_admin",
ActionTarget: fmt.Sprintf("/api/users/%d", userID),
Description: "user deleted from mk_dfusr and dfusr",
Username: claims.Username,
RoleCode: claims.RoleCode,
DfUsrID: int64(claims.ID),
TargetDfUsrID: userID,
TargetUsername: username,
IsSuccess: true,
})
}
_ = json.NewEncoder(w).Encode(map[string]any{
"success": true,
"deleted": userID,
"username": username,
})
}
// ======================================================
// 🔐 ADMIN — PASSWORD RESET MAIL
// ======================================================