diff --git a/internal/dis/component/auth/panel/panel.go b/internal/dis/component/auth/panel/panel.go index 96395e4..fc2c4ee 100644 --- a/internal/dis/component/auth/panel/panel.go +++ b/internal/dis/component/auth/panel/panel.go @@ -30,6 +30,7 @@ type UserPanel struct { var ( _ component.Routeable = (*UserPanel)(nil) + _ component.Menuable = (*UserPanel)(nil) ) func (panel *UserPanel) Routes() component.Routes { @@ -37,9 +38,18 @@ func (panel *UserPanel) Routes() component.Routes { Prefix: "/user/", CSRF: true, Decorator: panel.Dependencies.Auth.Require(nil), + } +} - MenuPriority: component.MenuUser, - MenuTitle: "User", +func (panel *UserPanel) Menu(r *http.Request) []component.MenuItem { + title := "Login" + + user, err := panel.Dependencies.Auth.UserOf(r) + if user != nil && err == nil { + title = user.User.User + } + return []component.MenuItem{ + {Title: title, Priority: component.MenuUser, Path: "/user/"}, } } diff --git a/internal/dis/component/auth/panel/templates/user.html b/internal/dis/component/auth/panel/templates/user.html index b266052..00932d3 100644 --- a/internal/dis/component/auth/panel/templates/user.html +++ b/internal/dis/component/auth/panel/templates/user.html @@ -1,10 +1,11 @@ {{ template "_base.html" . }} -{{ define "title" }}User{{ end }} +{{ define "title" }}{{ .User.User }}{{ end }} {{ define "content" }}

diff --git a/internal/dis/component/control/admin/users.go b/internal/dis/component/control/admin/users.go index 575d813..af565d7 100644 --- a/internal/dis/component/control/admin/users.go +++ b/internal/dis/component/control/admin/users.go @@ -219,3 +219,40 @@ func (admin *Admin) usersPasswordHandler(ctx context.Context) http.Handler { return user.SetPassword(r.Context(), []byte(password)) }) } + +func (admin *Admin) usersUnsetPasswordHandler(ctx context.Context) http.Handler { + return admin.useraction(ctx, "unset password", func(r *http.Request, user *auth.AuthUser) error { + user.PasswordHash = nil + return user.Save(r.Context()) + }) +} + +func (admin *Admin) usersImpersonateHandler(ctx context.Context) http.Handler { + logger := zerolog.Ctx(ctx) + + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if err := r.ParseForm(); err != nil { + logger.Err(err).Str("action", "impersonate").Msg("failed to parse form") + httpx.HTMLInterceptor.Fallback.ServeHTTP(w, r) + return + } + + username := r.PostFormValue("user") + user, err := admin.Dependencies.Auth.User(r.Context(), username) + if err != nil { + logger.Err(err).Str("action", "impersonate").Msg("failed to get user") + httpx.HTMLInterceptor.Fallback.ServeHTTP(w, r) + return + } + + // login the user into the session of the provided user + if err := admin.Dependencies.Auth.Login(w, r, user); err != nil { + logger.Err(err).Str("action", "impersonate").Msg("failed to login user") + httpx.HTMLInterceptor.Fallback.ServeHTTP(w, r) + return + } + + // and go there + http.Redirect(w, r, "/user/", http.StatusSeeOther) + }) +} diff --git a/internal/models/user.go b/internal/models/user.go index 8c80215..8105c8f 100644 --- a/internal/models/user.go +++ b/internal/models/user.go @@ -17,6 +17,10 @@ type User struct { Admin *bool `gorm:"column:admin;not null"` } +func (user *User) HasPassword() bool { + return len(user.PasswordHash) != 0 +} + func (user *User) IsAdmin() bool { return user.Admin != nil && *user.Admin }