ilk
This commit is contained in:
116
svc/routes/password_forgot.go
Normal file
116
svc/routes/password_forgot.go
Normal file
@@ -0,0 +1,116 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"bssapp-backend/internal/auditlog"
|
||||
"bssapp-backend/internal/mailer"
|
||||
"bssapp-backend/internal/security"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ForgotPasswordHandler(
|
||||
db *sql.DB,
|
||||
mailer *mailer.GraphMailer,
|
||||
) http.HandlerFunc {
|
||||
|
||||
type request struct {
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
// -------------------------------------------------------
|
||||
// 1️⃣ Request parse (enumeration yok)
|
||||
// -------------------------------------------------------
|
||||
var req request
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
respondOK(w)
|
||||
return
|
||||
}
|
||||
|
||||
email := strings.TrimSpace(strings.ToLower(req.Email))
|
||||
if email == "" {
|
||||
respondOK(w)
|
||||
return
|
||||
}
|
||||
|
||||
// -------------------------------------------------------
|
||||
// 2️⃣ Aktif kullanıcıyı bul
|
||||
// -------------------------------------------------------
|
||||
var userID int64
|
||||
err := db.QueryRow(`
|
||||
SELECT id
|
||||
FROM mk_dfusr
|
||||
WHERE email = $1
|
||||
AND is_active = true
|
||||
`, email).Scan(&userID)
|
||||
|
||||
if err != nil {
|
||||
// ❗ kullanıcı yok → bilgi sızdırma yok
|
||||
respondOK(w)
|
||||
return
|
||||
}
|
||||
|
||||
// -------------------------------------------------------
|
||||
// 3️⃣ Reset token üret
|
||||
// -------------------------------------------------------
|
||||
plain, hash, err := security.GenerateResetToken()
|
||||
if err != nil {
|
||||
respondOK(w)
|
||||
return
|
||||
}
|
||||
|
||||
expires := time.Now().Add(30 * time.Minute)
|
||||
|
||||
// -------------------------------------------------------
|
||||
// 4️⃣ DB’ye SADECE HASH kaydet
|
||||
// -------------------------------------------------------
|
||||
_, _ = db.Exec(`
|
||||
INSERT INTO dfusr_password_reset (
|
||||
dfusr_id,
|
||||
token,
|
||||
expires_at
|
||||
)
|
||||
VALUES ($1, $2, $3)
|
||||
`, userID, hash, expires)
|
||||
|
||||
// -------------------------------------------------------
|
||||
// 5️⃣ Reset URL (PLAIN token)
|
||||
// -------------------------------------------------------
|
||||
resetURL := fmt.Sprintf(
|
||||
"%s/password-reset/%s",
|
||||
os.Getenv("FRONTEND_URL"),
|
||||
plain,
|
||||
)
|
||||
|
||||
// -------------------------------------------------------
|
||||
// 6️⃣ Mail gönder (fail olsa bile enumeration yok)
|
||||
// -------------------------------------------------------
|
||||
_ = mailer.SendPasswordResetMail(email, resetURL)
|
||||
|
||||
// -------------------------------------------------------
|
||||
// 7️⃣ AUDIT LOG
|
||||
// -------------------------------------------------------
|
||||
auditlog.Write(auditlog.ActivityLog{
|
||||
ActionType: "PASSWORD_FORGOT_REQUEST",
|
||||
ActionCategory: "security",
|
||||
ActionTarget: email,
|
||||
IsSuccess: true,
|
||||
})
|
||||
|
||||
respondOK(w)
|
||||
}
|
||||
}
|
||||
|
||||
func respondOK(w http.ResponseWriter) {
|
||||
_ = json.NewEncoder(w).Encode(map[string]bool{
|
||||
"success": true,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user