ui(users): oidc chip on list + readonly fields on edit for OIDC users
This commit is contained in:
@@ -51,6 +51,7 @@ type userRow struct {
|
||||
LastLoginAt string // pre-formatted "2006-01-02 15:04:05" or "never"
|
||||
Disabled bool
|
||||
MustChangePassword bool
|
||||
AuthSource string
|
||||
}
|
||||
|
||||
func (s *Server) handleUIUsersList(w stdhttp.ResponseWriter, r *stdhttp.Request) {
|
||||
@@ -104,6 +105,7 @@ func (s *Server) handleUIUsersList(w stdhttp.ResponseWriter, r *stdhttp.Request)
|
||||
Role: string(ux.Role), LastLoginAt: ll,
|
||||
Disabled: ux.DisabledAt != nil,
|
||||
MustChangePassword: ux.MustChangePassword,
|
||||
AuthSource: ux.AuthSource,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -158,6 +160,7 @@ type userFormPage struct {
|
||||
// banner on the edit page explaining why and steering them at
|
||||
// the Re-enable button. See handleUIUserNewPost's collision branch.
|
||||
Reenable bool
|
||||
AuthSource string
|
||||
}
|
||||
|
||||
func (s *Server) handleUIUserNewGet(w stdhttp.ResponseWriter, r *stdhttp.Request) {
|
||||
@@ -296,6 +299,7 @@ func (s *Server) handleUIUserEditGet(w stdhttp.ResponseWriter, r *stdhttp.Reques
|
||||
Email: em, Role: string(target.Role),
|
||||
Disabled: target.DisabledAt != nil,
|
||||
Reenable: r.URL.Query().Get("reenable") == "1",
|
||||
AuthSource: target.AuthSource,
|
||||
}
|
||||
_ = s.deps.UI.Render(w, "user_edit", view)
|
||||
}
|
||||
@@ -315,6 +319,10 @@ func (s *Server) handleUIUserEditPost(w stdhttp.ResponseWriter, r *stdhttp.Reque
|
||||
stdhttp.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
if target.AuthSource == "oidc" {
|
||||
stdhttp.Error(w, "OIDC users cannot have role/email edited locally", stdhttp.StatusForbidden)
|
||||
return
|
||||
}
|
||||
role, ok := validRole(r.PostForm.Get("role"))
|
||||
if !ok {
|
||||
stdhttp.Error(w, "bad role", stdhttp.StatusBadRequest)
|
||||
|
||||
@@ -67,9 +67,20 @@
|
||||
{{end}}
|
||||
{{else}}
|
||||
{{/* new + edit form. */}}
|
||||
{{if and (eq $page.Mode "edit") (eq $page.AuthSource "oidc")}}
|
||||
<div class="panel rounded-[7px] p-4 mb-5 mt-7"
|
||||
style="border-color: color-mix(in oklch, var(--accent), transparent 60%);
|
||||
background: color-mix(in oklch, var(--accent), transparent 95%);">
|
||||
<div class="text-[12.5px] text-ink-mute leading-[1.6]">
|
||||
This user is provisioned via OIDC. Username, role, and email are
|
||||
managed by your IdP and refreshed on each sign-in. Disable /
|
||||
Enable / Force logout still work locally.
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<form method="post"
|
||||
action="{{if eq $page.Mode "new"}}/settings/users/new{{else}}/settings/users/{{$page.ID}}/edit{{end}}"
|
||||
class="panel mt-7 rounded-[7px] p-6 space-y-4">
|
||||
class="panel rounded-[7px] p-6 space-y-4 {{if and (eq $page.Mode "edit") (eq $page.AuthSource "oidc")}}mt-3{{else}}mt-7{{end}}">
|
||||
<div>
|
||||
<label class="field-label" for="username">Username</label>
|
||||
<input id="username" name="username" type="text"
|
||||
@@ -82,11 +93,13 @@
|
||||
<div>
|
||||
<label class="field-label" for="email">Email <span class="text-ink-fade font-normal">· optional</span></label>
|
||||
<input id="email" name="email" type="email" class="field"
|
||||
{{if and (eq $page.Mode "edit") (eq $page.AuthSource "oidc")}}readonly disabled{{end}}
|
||||
value="{{$page.Email}}" autocomplete="off" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="field-label" for="role">Role</label>
|
||||
<select id="role" name="role" class="field">
|
||||
<select id="role" name="role" class="field"
|
||||
{{if and (eq $page.Mode "edit") (eq $page.AuthSource "oidc")}}disabled{{end}}>
|
||||
<option value="admin" {{if eq $page.Role "admin"}}selected{{end}}>admin</option>
|
||||
<option value="operator" {{if eq $page.Role "operator"}}selected{{end}}>operator</option>
|
||||
<option value="viewer" {{if eq $page.Role "viewer"}}selected{{end}}>viewer</option>
|
||||
@@ -104,9 +117,11 @@
|
||||
<div class="panel mt-5 rounded-[7px] p-6">
|
||||
<div class="text-[12.5px] text-ink mb-3 font-medium">Other actions</div>
|
||||
<div class="flex gap-2 flex-wrap">
|
||||
{{if ne $page.AuthSource "oidc"}}
|
||||
<form method="post" action="/settings/users/{{$page.ID}}/regenerate-setup">
|
||||
<button type="submit" class="btn">Regenerate setup link</button>
|
||||
</form>
|
||||
{{end}}
|
||||
<form method="post" action="/settings/users/{{$page.ID}}/force-logout">
|
||||
<button type="submit" class="btn">Force logout</button>
|
||||
</form>
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
{{if .Disabled}}<span class="tag" style="color: var(--ink-fade);">disabled</span>
|
||||
{{else if .MustChangePassword}}<span class="tag" style="color: var(--warn); border-color: color-mix(in oklch, var(--warn), transparent 60%); background: color-mix(in oklch, var(--warn), transparent 92%);">setup pending</span>
|
||||
{{else}}<span class="tag" style="color: var(--ok);">enabled</span>{{end}}
|
||||
{{if eq .AuthSource "oidc"}}<span class="tag" style="color: var(--accent); border-color: color-mix(in oklch, var(--accent), transparent 60%); background: color-mix(in oklch, var(--accent), transparent 92%); margin-left: 4px;">oidc</span>{{end}}
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<a href="/settings/users/{{.ID}}/edit" class="btn">Edit</a>
|
||||
|
||||
Reference in New Issue
Block a user