feat(authz): redirect deleted accounts to /login
detect soft-deleted users during authorization lookup return a dedicated deleted-user result from auth services redirect deleted accounts to /login in the handler update repository, service, and handler tests for the new flow
This commit is contained in:
+19
-14
@@ -126,24 +126,29 @@ func AuthorizeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Return result
|
||||
writeAuthorizationResponse(w, r, result)
|
||||
}
|
||||
|
||||
func writeAuthorizationResponse(w http.ResponseWriter, r *http.Request, result *models.AuthorizationResult) {
|
||||
if result.RedirectRoute != "" {
|
||||
log.Printf("✗ [Handler] Authorization redirect to %s (reason: %s)", result.RedirectRoute, result.Message)
|
||||
http.Redirect(w, r, result.RedirectRoute, http.StatusFound)
|
||||
return
|
||||
}
|
||||
|
||||
response := map[string]interface{}{
|
||||
"allowed": result.Allowed,
|
||||
"reason": result.Message,
|
||||
}
|
||||
|
||||
if result.Allowed {
|
||||
log.Printf("✓ [Handler] Authorization ALLOWED - Returning 200 OK to client")
|
||||
// Return sabat matching Authorizationsabat model for client compatibility
|
||||
response := map[string]interface{}{
|
||||
"allowed": result.Allowed,
|
||||
"reason": result.Message,
|
||||
}
|
||||
sabat.RespondWithJSON(w, http.StatusOK, response)
|
||||
} else {
|
||||
log.Printf("✗ [Handler] Authorization DENIED - Returning 403 Forbidden to client (reason: %s)", result.Message)
|
||||
// Return sabat matching Authorizationsabat model for client compatibility
|
||||
response := map[string]interface{}{
|
||||
"allowed": result.Allowed,
|
||||
"reason": result.Message,
|
||||
}
|
||||
sabat.RespondWithJSON(w, http.StatusForbidden, response)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("✗ [Handler] Authorization DENIED - Returning 403 Forbidden to client (reason: %s)", result.Message)
|
||||
sabat.RespondWithJSON(w, http.StatusForbidden, response)
|
||||
}
|
||||
|
||||
func collectClaimRoles(claims *models.Claims) []int {
|
||||
|
||||
@@ -10,6 +10,24 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestWriteAuthorizationResponseRedirectsToLogin(t *testing.T) {
|
||||
req := httptest.NewRequest("POST", AuthCheckEndpoint, nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
writeAuthorizationResponse(w, req, &models.AuthorizationResult{
|
||||
Allowed: false,
|
||||
RedirectRoute: "/login",
|
||||
Message: "Account deleted",
|
||||
})
|
||||
|
||||
if w.Code != http.StatusFound {
|
||||
t.Fatalf("Expected status %d, got %d", http.StatusFound, w.Code)
|
||||
}
|
||||
if location := w.Header().Get("Location"); location != "/login" {
|
||||
t.Fatalf("Expected redirect location /login, got %q", location)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitAuthService(t *testing.T) {
|
||||
// Test that InitAuthService can be called
|
||||
// It may panic if DB is not available, which is expected behavior
|
||||
|
||||
Reference in New Issue
Block a user