Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -21,6 +21,9 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- panel: the user edit form disables role change and delete for the only global
|
||||||
|
administrator, with a short note, instead of allowing the action and showing
|
||||||
|
an error on submit.
|
||||||
- panel: the user create/edit form hides **Assigned domains** when the role is
|
- panel: the user create/edit form hides **Assigned domains** when the role is
|
||||||
global administrator, since that role manages every domain anyway.
|
global administrator, since that role manages every domain anyway.
|
||||||
- panel: **Settings** shows panel credentials and DMARC aggregate reports side
|
- panel: **Settings** shows panel credentials and DMARC aggregate reports side
|
||||||
|
|||||||
@@ -132,9 +132,18 @@ func (h *Handlers) renderUserForm(w http.ResponseWriter, r *http.Request, status
|
|||||||
data["FormDomains"] = view.FormDomains
|
data["FormDomains"] = view.FormDomains
|
||||||
data["FormPassword"] = view.FormPassword
|
data["FormPassword"] = view.FormPassword
|
||||||
data["IsEdit"] = userID != 0
|
data["IsEdit"] = userID != 0
|
||||||
|
data["LastGlobalLocked"] = lastGlobalLocked(h, userID, view.FormRole)
|
||||||
h.view.Render(w, status, "user_form", data)
|
h.view.Render(w, status, "user_form", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func lastGlobalLocked(h *Handlers, userID int64, formRole string) bool {
|
||||||
|
if userID == 0 || formRole != string(store.RoleGlobal) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
n, err := h.store.CountGlobalUsers()
|
||||||
|
return err == nil && n <= 1
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handlers) submitUserCreate(w http.ResponseWriter, r *http.Request) {
|
func (h *Handlers) submitUserCreate(w http.ResponseWriter, r *http.Request) {
|
||||||
if err := r.ParseForm(); err != nil {
|
if err := r.ParseForm(); err != nil {
|
||||||
h.renderUserForm(w, r, http.StatusBadRequest, 0, userFormView{FormErr: "Invalid form submission."})
|
h.renderUserForm(w, r, http.StatusBadRequest, 0, userFormView{FormErr: "Invalid form submission."})
|
||||||
|
|||||||
@@ -193,6 +193,14 @@ button, a.btn, a.danger {
|
|||||||
color: var(--on-accent); background: var(--accent-fill); border: 0; border-radius: 5px; cursor: pointer;
|
color: var(--on-accent); background: var(--accent-fill); border: 0; border-radius: 5px; cursor: pointer;
|
||||||
}
|
}
|
||||||
button:hover, a.btn:hover { background: var(--accent-fill-hover); }
|
button:hover, a.btn:hover { background: var(--accent-fill-hover); }
|
||||||
|
button:disabled, button.danger:disabled {
|
||||||
|
opacity: 0.45; cursor: not-allowed;
|
||||||
|
}
|
||||||
|
button:disabled:hover { background: var(--accent-fill); }
|
||||||
|
button.danger:disabled:hover { background: var(--danger-fill); }
|
||||||
|
select:disabled {
|
||||||
|
opacity: 0.65; cursor: not-allowed; background: var(--code-bg);
|
||||||
|
}
|
||||||
.error { color: var(--danger-fg); margin: 0.6rem 0 0; font-weight: 600; }
|
.error { color: var(--danger-fg); margin: 0.6rem 0 0; font-weight: 600; }
|
||||||
.muted { color: var(--muted); }
|
.muted { color: var(--muted); }
|
||||||
/* Links take the accent. The panel never set a colour here and ran on the
|
/* Links take the accent. The panel never set a colour here and ran on the
|
||||||
|
|||||||
@@ -14,10 +14,12 @@
|
|||||||
<input id="password" name="password" type="password" autocomplete="new-password" {{if not .IsEdit}}required{{end}}>
|
<input id="password" name="password" type="password" autocomplete="new-password" {{if not .IsEdit}}required{{end}}>
|
||||||
|
|
||||||
<label for="role">Role</label>
|
<label for="role">Role</label>
|
||||||
<select id="role" name="role" data-global-role="{{.GlobalRole}}">
|
{{if .LastGlobalLocked}}<input type="hidden" name="role" value="{{.FormRole}}">{{end}}
|
||||||
|
<select id="role" name="role" data-global-role="{{.GlobalRole}}"{{if .LastGlobalLocked}} disabled{{end}}>
|
||||||
<option value="domain_admin" {{if eq .FormRole "domain_admin"}}selected{{end}}>Domain administrator</option>
|
<option value="domain_admin" {{if eq .FormRole "domain_admin"}}selected{{end}}>Domain administrator</option>
|
||||||
<option value="global" {{if eq .FormRole "global"}}selected{{end}}>Global administrator</option>
|
<option value="global" {{if eq .FormRole "global"}}selected{{end}}>Global administrator</option>
|
||||||
</select>
|
</select>
|
||||||
|
{{if .LastGlobalLocked}}<p class="muted">The only global administrator cannot be demoted.</p>{{end}}
|
||||||
|
|
||||||
<fieldset id="domain-pick" data-domain-pick>
|
<fieldset id="domain-pick" data-domain-pick>
|
||||||
<legend>Assigned domains</legend>
|
<legend>Assigned domains</legend>
|
||||||
@@ -32,7 +34,8 @@
|
|||||||
|
|
||||||
<button type="submit">{{if .IsEdit}}Save{{else}}Create{{end}}</button>
|
<button type="submit">{{if .IsEdit}}Save{{else}}Create{{end}}</button>
|
||||||
{{if .IsEdit}}
|
{{if .IsEdit}}
|
||||||
<button type="submit" name="action" value="delete" class="danger">Delete user</button>
|
<button type="submit" name="action" value="delete" class="danger"{{if .LastGlobalLocked}} disabled{{end}}>Delete user</button>
|
||||||
|
{{if .LastGlobalLocked}}<p class="muted">The only global administrator cannot be deleted.</p>{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user