Add Go rewrite with Postgres 17 and Dokploy Docker Compose
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"amnezia-share/internal/auth"
|
||||
"amnezia-share/internal/settings"
|
||||
"amnezia-share/internal/web"
|
||||
)
|
||||
|
||||
func registerLogin(a *web.App, mux *http.ServeMux) {
|
||||
mux.HandleFunc("GET /login", LoginForm(a))
|
||||
mux.HandleFunc("POST /login", a.CSRFProtect(LoginSubmit(a)))
|
||||
mux.HandleFunc("GET /logout", Logout(a))
|
||||
}
|
||||
|
||||
// oidcConfigFromSettings loads the Pocket ID OIDC settings (shared by login.go
|
||||
// and oidc.go).
|
||||
func oidcConfigFromSettings(a *web.App, r *http.Request) auth.OIDCConfig {
|
||||
ctx := r.Context()
|
||||
vals, _ := a.Settings.GetMany(ctx, settings.KeyPocketURL, settings.KeyPocketClientID, settings.KeyPocketSecret)
|
||||
return auth.OIDCConfig{
|
||||
URL: vals[settings.KeyPocketURL],
|
||||
ClientID: vals[settings.KeyPocketClientID],
|
||||
ClientSecret: vals[settings.KeyPocketSecret],
|
||||
}
|
||||
}
|
||||
|
||||
type loginView struct {
|
||||
Error string
|
||||
PocketEnabled bool
|
||||
NoAdmins bool
|
||||
}
|
||||
|
||||
// LoginForm renders the admin login page, or starts the Pocket ID SSO flow when
|
||||
// called as GET /login?oidc=1 (login.php).
|
||||
func LoginForm(a *web.App) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
if a.CurrentAdmin(r) != nil {
|
||||
redirectTo(w, r, a, "admin")
|
||||
return
|
||||
}
|
||||
|
||||
cfg := oidcConfigFromSettings(a, r)
|
||||
pocketEnabled := cfg.Configured()
|
||||
|
||||
if pocketEnabled && r.URL.Query().Has("oidc") {
|
||||
state, err := auth.GenerateState()
|
||||
if err != nil {
|
||||
http.Error(w, "не удалось начать вход", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
verifier, challenge, err := auth.GeneratePKCE()
|
||||
if err != nil {
|
||||
http.Error(w, "не удалось начать вход", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
a.Sessions.Put(ctx, "oidc_state", state)
|
||||
a.Sessions.Put(ctx, "oidc_verifier", verifier)
|
||||
redirectURI := a.AbsoluteURL(r, "oidc/callback")
|
||||
http.Redirect(w, r, auth.AuthURL(cfg, redirectURI, state, challenge), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
count, _ := a.Auth.AdminCount(ctx)
|
||||
a.Render(w, r, "page_login", loginView{PocketEnabled: pocketEnabled, NoAdmins: count == 0})
|
||||
}
|
||||
}
|
||||
|
||||
// LoginSubmit verifies username/password and signs the admin in (login.php POST).
|
||||
func LoginSubmit(a *web.App) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
username := strings.TrimSpace(r.FormValue("username"))
|
||||
password := r.FormValue("password")
|
||||
|
||||
admin, err := a.Auth.LoginAdmin(ctx, username, password)
|
||||
if err != nil {
|
||||
cfg := oidcConfigFromSettings(a, r)
|
||||
count, _ := a.Auth.AdminCount(ctx)
|
||||
a.Render(w, r, "page_login", loginView{Error: err.Error(), PocketEnabled: cfg.Configured(), NoAdmins: count == 0})
|
||||
return
|
||||
}
|
||||
|
||||
_ = a.Sessions.RenewToken(ctx)
|
||||
a.Sessions.Put(ctx, web.SessionAdminID, admin.ID)
|
||||
redirectTo(w, r, a, "admin")
|
||||
}
|
||||
}
|
||||
|
||||
// Logout clears the admin session (logout.php).
|
||||
func Logout(a *web.App) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
a.Sessions.Remove(r.Context(), web.SessionAdminID)
|
||||
_ = a.Sessions.RenewToken(r.Context())
|
||||
redirectTo(w, r, a, "login")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user