feat(auth): enhance login flow with notifications and path normalization
Some checks failed
CI / Test (1.22) (push) Failing after -30m33s
CI / Test (1.23) (push) Failing after -30m32s
CI / Lint (push) Failing after -30m39s
CI / Build (push) Failing after -30m35s

- add success notification on successful login
- show error notification with detailed message on login failure
- normalize API paths to prevent double slashes and trailing slashes
- redirect to login page only if not on login request or page
This commit is contained in:
2026-03-05 01:03:50 +02:00
parent 1490e0b596
commit 271a0603b8
10 changed files with 230 additions and 29 deletions

View File

@@ -30,6 +30,7 @@ import (
"github.com/bitechdev/ResolveSpec/pkg/server"
"github.com/gorilla/mux"
"github.com/uptrace/bun"
"golang.org/x/crypto/bcrypt"
)
// WhatsHookedInterface defines the interface for accessing WhatsHooked components
@@ -681,6 +682,27 @@ func handleQueryCreate(w http.ResponseWriter, r *http.Request, db *bun.DB, req Q
}
}
if req.Table == "users" {
rawPassword, exists := req.Data["password"]
if !exists {
http.Error(w, "Password is required", http.StatusBadRequest)
return
}
password, ok := rawPassword.(string)
if !ok || password == "" {
http.Error(w, "Password is required", http.StatusBadRequest)
return
}
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
http.Error(w, "Failed to process password", http.StatusInternalServerError)
return
}
req.Data["password"] = string(hashedPassword)
}
// Convert data map to model using JSON marshaling
dataJSON, err := json.Marshal(req.Data)
if err != nil {
@@ -732,6 +754,27 @@ func handleQueryUpdate(w http.ResponseWriter, r *http.Request, db *bun.DB, req Q
return
}
if req.Table == "users" {
if rawPassword, exists := req.Data["password"]; exists {
password, ok := rawPassword.(string)
if !ok {
http.Error(w, "Invalid password format", http.StatusBadRequest)
return
}
if password == "" {
delete(req.Data, "password")
} else {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
http.Error(w, "Failed to process password", http.StatusInternalServerError)
return
}
req.Data["password"] = string(hashedPassword)
}
}
}
updateQuery := db.NewUpdate().Model(model).Where("id = ?", req.ID)
updatedColumns := 0

File diff suppressed because one or more lines are too long

View File

@@ -5,7 +5,7 @@
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>web</title>
<script type="module" crossorigin src="/ui/assets/index-BKXFy3Jy.js"></script>
<script type="module" crossorigin src="/ui/assets/index-CAlNxuwF.js"></script>
<link rel="stylesheet" crossorigin href="/ui/assets/index-Bfia8Lvm.css">
</head>
<body>