Implement OAuth login functionality and enhance documentation

- Added support for Google OAuth login, including new API endpoints for OAuth providers and callbacks.
- Updated user authentication logic to handle OAuth-only users.
- Enhanced README.md and deployment documentation with OAuth setup instructions.
- Modified frontend components to include OAuth login options and improved error handling.
- Updated configuration files to include new environment variables for OAuth integration.
This commit is contained in:
2026-02-25 00:26:38 +03:00
parent 051719381a
commit 2c7bf48719
14 changed files with 470 additions and 29 deletions

View File

@@ -37,6 +37,13 @@ func (a *App) apiLogin(rw http.ResponseWriter, req *http.Request) {
http.Error(rw, "bad request", http.StatusBadRequest)
return
}
// OAuth-only users cannot login with password
if uByName := a.getUserByUsername(body.User); uByName != nil && uByName.Pass == nil {
rw.Header().Set("Content-Type", "application/json")
rw.WriteHeader(http.StatusUnauthorized)
json.NewEncoder(rw).Encode(map[string]string{"error": "Use OAuth to sign in"})
return
}
u := a.getUser(body.User, body.Pass)
if u == nil {
// Bootstrap: first admin via env HNHMAP_BOOTSTRAP_PASSWORD when no users exist
@@ -682,6 +689,27 @@ func (a *App) apiRouter(rw http.ResponseWriter, req *http.Request) {
}
switch {
case path == "oauth/providers":
a.apiOAuthProviders(rw, req)
return
case strings.HasPrefix(path, "oauth/"):
rest := strings.TrimPrefix(path, "oauth/")
parts := strings.SplitN(rest, "/", 2)
if len(parts) != 2 {
http.Error(rw, "not found", http.StatusNotFound)
return
}
provider := parts[0]
action := parts[1]
switch action {
case "login":
a.oauthLogin(rw, req, provider)
case "callback":
a.oauthCallback(rw, req, provider)
default:
http.Error(rw, "not found", http.StatusNotFound)
}
return
case path == "setup":
a.apiSetup(rw, req)
return