324 lines
21 KiB
HTML
324 lines
21 KiB
HTML
{{ template "account_shell_start" . }}
|
|
<main class="account-window" aria-labelledby="user-edit-title">
|
|
{{ template "account_window_titlebar" . }}
|
|
|
|
<nav class="menu-bar" aria-label="User edit toolbar">
|
|
<div class="menu-item">
|
|
<button class="menu-button" type="button" aria-expanded="false">File</button>
|
|
<div class="menu-popup" role="menu">
|
|
<button class="menu-action" type="button" data-ue-command="save"><span>💾</span><span>Save user</span><span class="shortcut">Ctrl+S</span></button>
|
|
<button class="menu-action" type="button" data-ue-command="discard"><span>↩</span><span>Discard changes</span><span class="shortcut">Esc</span></button>
|
|
{{ if .CanManage }}
|
|
<div class="menu-separator"></div>
|
|
{{ if .IsPending }}
|
|
<form method="post" action="/account/users/{{ .Target.ID }}/invite/resend" style="margin:0">
|
|
{{ template "account_csrf_field" . }}
|
|
<button class="menu-action" type="submit"><span>✉</span><span>Send invite again</span><span></span></button>
|
|
</form>
|
|
{{ end }}
|
|
<button class="menu-action" type="button" data-ue-command="reset-password"><span>🔑</span><span>Reset password</span><span></span></button>
|
|
{{ end }}
|
|
</div>
|
|
</div>
|
|
<div class="menu-item">
|
|
<button class="menu-button" type="button" aria-expanded="false">User</button>
|
|
<div class="menu-popup" role="menu">
|
|
{{ if .CanManage }}
|
|
{{ if not .IsSelf }}
|
|
<form method="post" action="/account/users/{{ .Target.ID }}/enable" style="margin:0">
|
|
{{ template "account_csrf_field" . }}
|
|
<button class="menu-action" type="submit"><span>✔</span><span>Enable user</span><span></span></button>
|
|
</form>
|
|
<form method="post" action="/account/users/{{ .Target.ID }}/disable" style="margin:0">
|
|
{{ template "account_csrf_field" . }}
|
|
<button class="menu-action" type="submit"><span>⛔</span><span>Disable user</span><span></span></button>
|
|
</form>
|
|
<div class="menu-separator"></div>
|
|
{{ end }}
|
|
<form method="post" action="/account/users/{{ .Target.ID }}/sessions/revoke" style="margin:0">
|
|
{{ template "account_csrf_field" . }}
|
|
<button class="menu-action" type="submit"><span>◌</span><span>Revoke all sessions</span><span></span></button>
|
|
</form>
|
|
{{ end }}
|
|
<a class="menu-action" href="/account/users"><span>←</span><span>Back to users</span><span></span></a>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="account-body-content">
|
|
{{ if .Error }}
|
|
<div class="account-error-banner">{{ .Error }}</div>
|
|
{{ end }}
|
|
{{ if .Success }}
|
|
<div class="account-success-banner">{{ .Success }}</div>
|
|
{{ end }}
|
|
|
|
<section class="stats-grid" aria-label="User summary">
|
|
{{ if eq .Status "active" }}
|
|
<article class="stat-card sunken-panel is-ok">
|
|
{{ else if eq .Status "pending" }}
|
|
<article class="stat-card sunken-panel is-warning">
|
|
{{ else }}
|
|
<article class="stat-card sunken-panel is-danger">
|
|
{{ end }}
|
|
<p class="stat-label">Status</p>
|
|
<p class="stat-value">{{ .Status }}</p>
|
|
<p class="stat-note">
|
|
{{ if eq .Status "active" }}<span class="stat-note-pill">can sign in</span>
|
|
{{ else if eq .Status "pending" }}<span class="stat-note-pill">invite not accepted</span>
|
|
{{ else }}<span class="stat-note-pill">blocked</span>{{ end }}
|
|
</p>
|
|
</article>
|
|
{{ if .IsAdmin }}
|
|
<article class="stat-card sunken-panel is-info">
|
|
{{ else }}
|
|
<article class="stat-card sunken-panel">
|
|
{{ end }}
|
|
<p class="stat-label">Role</p>
|
|
<p class="stat-value">{{ if .IsAdmin }}admin{{ else }}user{{ end }}</p>
|
|
<p class="stat-note">
|
|
{{ if .TagNames }}<span class="stat-note-pill">{{ .TagNames }}</span>{{ else }}<span class="stat-note-pill">no tags</span>{{ end }}
|
|
</p>
|
|
</article>
|
|
<article class="stat-card sunken-panel">
|
|
<p class="stat-label">Max file size</p>
|
|
<p class="stat-value">{{ if .MaxFileSizeStr }}{{ .MaxFileSizeStr }}{{ else }}default{{ end }}</p>
|
|
<p class="stat-note"><span class="stat-note-pill">bytes</span></p>
|
|
</article>
|
|
<article class="stat-card sunken-panel">
|
|
<p class="stat-label">Max expiry</p>
|
|
<p class="stat-value">{{ if .MaxExpiryStr }}{{ .MaxExpiryStr }}s{{ else }}default{{ end }}</p>
|
|
<p class="stat-note"><span class="stat-note-pill">seconds</span></p>
|
|
</article>
|
|
</section>
|
|
|
|
<form method="post" action="/account/users/{{ .Target.ID }}" id="user-edit-form" data-ue-form>
|
|
{{ template "account_csrf_field" . }}
|
|
|
|
<div class="ue-content-grid">
|
|
<div class="ue-column">
|
|
|
|
<section class="win98-window section-window">
|
|
<div class="win98-titlebar">
|
|
<div class="win98-titlebar-label">
|
|
<span class="win98-titlebar-icon">A</span>
|
|
<h2>Account <span class="ue-panel-sub">identity and basic state</span></h2>
|
|
</div>
|
|
</div>
|
|
<div class="section-body sunken-panel ue-panel-body">
|
|
<div class="ue-form-grid">
|
|
<div class="ue-field">
|
|
<label for="ue-username">Username</label>
|
|
<input class="win98-input" id="ue-username" name="username" type="text" value="{{ .Target.Username }}" {{ if not .CanManage }}disabled{{ end }} autocomplete="off">
|
|
<span class="ue-help">Visible login name.</span>
|
|
</div>
|
|
<div class="ue-field">
|
|
<label for="ue-email">Email</label>
|
|
<input class="win98-input" id="ue-email" name="email" type="email" value="{{ .Target.Email }}" {{ if not .CanManage }}disabled{{ end }} autocomplete="off">
|
|
<span class="ue-help">Account contact and invite destination.</span>
|
|
</div>
|
|
{{ if not .IsPending }}
|
|
<div class="ue-field">
|
|
<label for="ue-state">State</label>
|
|
<select class="win98-select" id="ue-state" name="state" {{ if or (not .CanManage) .IsSelf }}disabled{{ end }}>
|
|
<option value="active" {{ if eq .Status "active" }}selected{{ end }}>Active</option>
|
|
<option value="disabled" {{ if eq .Status "disabled" }}selected{{ end }}>Disabled</option>
|
|
</select>
|
|
<span class="ue-help">{{ if .IsSelf }}Cannot disable yourself.{{ else }}Account state.{{ end }}</span>
|
|
</div>
|
|
{{ end }}
|
|
<div class="ue-field">
|
|
<label for="ue-admin-note">Admin note</label>
|
|
<input class="win98-input" id="ue-admin-note" name="admin_note" type="text" value="{{ .Target.AdminNote }}" {{ if not .CanManage }}disabled{{ end }}>
|
|
<span class="ue-help">Private note. Not shown to the user.</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="win98-window section-window">
|
|
<div class="win98-titlebar">
|
|
<div class="win98-titlebar-label">
|
|
<span class="win98-titlebar-icon">R</span>
|
|
<h2>Access rights <span class="ue-panel-sub">what this account can do</span></h2>
|
|
</div>
|
|
</div>
|
|
<div class="section-body sunken-panel ue-panel-body">
|
|
<div class="ue-check-grid">
|
|
<label class="ue-check-card">
|
|
<input type="checkbox" name="upload_allowed" value="1" {{ if index .Check "upload_allowed" }}checked{{ end }} {{ if not .CanManage }}disabled{{ end }}>
|
|
<span class="ue-check-copy"><strong>Create boxes</strong><span>Allow browser or API box creation.</span></span>
|
|
</label>
|
|
<label class="ue-check-card">
|
|
<input type="checkbox" name="manage_own_boxes" value="1" {{ if index .Check "manage_own_boxes" }}checked{{ end }} {{ if not .CanManage }}disabled{{ end }}>
|
|
<span class="ue-check-copy"><strong>Manage own boxes</strong><span>Edit sharing, password, or expiry for owned boxes.</span></span>
|
|
</label>
|
|
<label class="ue-check-card">
|
|
<input type="checkbox" name="renewable_allowed" value="1" {{ if index .Check "renewable_allowed" }}checked{{ end }} {{ if not .CanManage }}disabled{{ end }}>
|
|
<span class="ue-check-copy"><strong>Refresh own box expiry</strong><span>Permits time extension within limits.</span></span>
|
|
</label>
|
|
<label class="ue-check-card">
|
|
<input type="checkbox" name="zip_download_allowed" value="1" {{ if index .Check "zip_download_allowed" }}checked{{ end }} {{ if not .CanManage }}disabled{{ end }}>
|
|
<span class="ue-check-copy"><strong>Use ZIP downloads</strong><span>Allow ZIP generation on this user's boxes.</span></span>
|
|
</label>
|
|
<label class="ue-check-card">
|
|
<input type="checkbox" name="one_time_download_allowed" value="1" {{ if index .Check "one_time_download_allowed" }}checked{{ end }} {{ if not .CanManage }}disabled{{ end }}>
|
|
<span class="ue-check-copy"><strong>Use one-time boxes</strong><span>Permit one-time ZIP handoff boxes.</span></span>
|
|
</label>
|
|
<label class="ue-check-card">
|
|
<input type="checkbox" name="is_admin" value="1" {{ if .IsAdmin }}checked{{ end }} {{ if or (not .CanManage) .IsSelf }}disabled{{ end }}>
|
|
<span class="ue-check-copy"><strong>Administrator</strong><span>Grants full admin area access. Last admin is protected.</span></span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="win98-window section-window">
|
|
<div class="win98-titlebar">
|
|
<div class="win98-titlebar-label">
|
|
<span class="win98-titlebar-icon">L</span>
|
|
<h2>Limits <span class="ue-panel-sub">0 = unlimited, empty = system default</span></h2>
|
|
</div>
|
|
</div>
|
|
<div class="section-body sunken-panel ue-panel-body">
|
|
<div class="ue-form-grid">
|
|
<div class="ue-field">
|
|
<label for="ue-max-file">Max file size (bytes)</label>
|
|
<input class="win98-input" id="ue-max-file" name="max_file_size_bytes" type="number" min="0"
|
|
value="{{ .MaxFileSizeStr }}" {{ if not .CanManage }}disabled{{ end }}>
|
|
<span class="ue-help">Per-file cap. Empty = system default.</span>
|
|
</div>
|
|
<div class="ue-field">
|
|
<label for="ue-max-box">Max box size (bytes)</label>
|
|
<input class="win98-input" id="ue-max-box" name="max_box_size_bytes" type="number" min="0"
|
|
value="{{ .MaxBoxSizeStr }}" {{ if not .CanManage }}disabled{{ end }}>
|
|
<span class="ue-help">Total size per box. Empty = system default.</span>
|
|
</div>
|
|
<div class="ue-field ue-field-full">
|
|
<label for="ue-max-expiry">Max box expiry (seconds)</label>
|
|
<input class="win98-input" id="ue-max-expiry" name="max_expiry_seconds" type="number" min="0"
|
|
value="{{ .MaxExpiryStr }}" {{ if not .CanManage }}disabled{{ end }}>
|
|
<span class="ue-help">Maximum expiry when creating or editing a box. Empty = system default.</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
</div>
|
|
|
|
<div class="ue-column">
|
|
|
|
<section class="win98-window section-window">
|
|
<div class="win98-titlebar">
|
|
<div class="win98-titlebar-label">
|
|
<span class="win98-titlebar-icon">O</span>
|
|
<h2>Setting overrides <span class="ue-panel-sub">account-specific behavior</span></h2>
|
|
</div>
|
|
</div>
|
|
<div class="section-body sunken-panel ue-panel-body">
|
|
<div class="ue-check-grid ue-check-grid-1col">
|
|
<label class="ue-check-card">
|
|
<input type="checkbox" name="allow_password_protected" value="1" {{ if index .Check "allow_password_protected" }}checked{{ end }} {{ if not .CanManage }}disabled{{ end }}>
|
|
<span class="ue-check-copy"><strong>Allow password-protected boxes</strong><span>Overrides system default for this account.</span></span>
|
|
</label>
|
|
<label class="ue-check-card">
|
|
<input type="checkbox" name="renew_on_access" value="1" {{ if index .Check "renew_on_access" }}checked{{ end }} {{ if not .CanManage }}disabled{{ end }}>
|
|
<span class="ue-check-copy"><strong>Allow renew on access</strong><span>Only applies when the global feature is enabled.</span></span>
|
|
</label>
|
|
<label class="ue-check-card">
|
|
<input type="checkbox" name="renew_on_download" value="1" {{ if index .Check "renew_on_download" }}checked{{ end }} {{ if not .CanManage }}disabled{{ end }}>
|
|
<span class="ue-check-copy"><strong>Allow renew on download</strong><span>Only applies when the global feature is enabled.</span></span>
|
|
</label>
|
|
<label class="ue-check-card">
|
|
<input type="checkbox" name="allow_owner_box_editing" value="1" {{ if index .Check "allow_owner_box_editing" }}checked{{ end }} {{ if not .CanManage }}disabled{{ end }}>
|
|
<span class="ue-check-copy"><strong>Allow owner box editing</strong><span>Lets the user open the box edit page for owned boxes.</span></span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="win98-window section-window">
|
|
<div class="win98-titlebar">
|
|
<div class="win98-titlebar-label">
|
|
<span class="win98-titlebar-icon">P</span>
|
|
<h2>Resolved policy <span class="ue-panel-sub">effective permissions after all overrides</span></h2>
|
|
</div>
|
|
</div>
|
|
<div class="section-body sunken-panel ue-panel-body">
|
|
<pre class="ue-policy-pre">{{ .PolicyJSON }}</pre>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="win98-window section-window">
|
|
<div class="win98-titlebar">
|
|
<div class="win98-titlebar-label">
|
|
<span class="win98-titlebar-icon">I</span>
|
|
<h2>Account info <span class="ue-panel-sub">read-only details</span></h2>
|
|
</div>
|
|
</div>
|
|
<div class="section-body sunken-panel ue-panel-body">
|
|
<ul class="ue-info-list">
|
|
<li class="ue-info-item"><strong>User ID</strong><span>{{ .Target.ID }}</span></li>
|
|
<li class="ue-info-item"><strong>Created</strong><span>{{ .CreatedAtStr }}</span></li>
|
|
<li class="ue-info-item"><strong>Updated</strong><span>{{ .UpdatedAtStr }}</span></li>
|
|
<li class="ue-info-item"><strong>Tags</strong><span>{{ if .TagNames }}{{ .TagNames }}{{ else }}none{{ end }}</span></li>
|
|
<li class="ue-info-item"><strong>Password</strong><span>{{ if .IsPending }}pending invite{{ else }}set{{ end }}</span></li>
|
|
</ul>
|
|
</div>
|
|
</section>
|
|
|
|
{{ if .CanManage }}
|
|
<section class="win98-window section-window">
|
|
<div class="win98-titlebar">
|
|
<div class="win98-titlebar-label">
|
|
<span class="win98-titlebar-icon">!</span>
|
|
<h2>Danger zone</h2>
|
|
</div>
|
|
</div>
|
|
<div class="section-body sunken-panel ue-panel-body">
|
|
<div class="ue-danger-row">
|
|
<form method="post" action="/account/users/{{ .Target.ID }}/password/reset">
|
|
{{ template "account_csrf_field" . }}
|
|
<button class="win98-button ue-danger-btn" type="submit">Reset password</button>
|
|
</form>
|
|
<form method="post" action="/account/users/{{ .Target.ID }}/sessions/revoke">
|
|
{{ template "account_csrf_field" . }}
|
|
<button class="win98-button" type="submit">Revoke sessions</button>
|
|
</form>
|
|
{{ if not .IsSelf }}
|
|
<form method="post" action="/account/users/{{ .Target.ID }}/{{ if .Target.Disabled }}enable{{ else }}disable{{ end }}">
|
|
{{ template "account_csrf_field" . }}
|
|
<button class="win98-button ue-danger-btn" type="submit">{{ if .Target.Disabled }}Enable{{ else }}Disable{{ end }} user</button>
|
|
</form>
|
|
{{ end }}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
{{ end }}
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<div class="ue-footer">
|
|
<div class="ue-footer-left">
|
|
<span class="stat-note-pill" data-ue-dirty>No unsaved changes</span>
|
|
<a class="stat-note-pill" href="/account/users">← Back to users</a>
|
|
</div>
|
|
<div class="ue-footer-right">
|
|
{{ if .CanManage }}
|
|
<button class="win98-button" type="button" data-ue-command="discard">Discard</button>
|
|
<button class="win98-button" type="submit">Save user</button>
|
|
{{ end }}
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<footer class="win98-statusbar" aria-label="User edit status">
|
|
<span>editing: {{ .Target.Username }}</span>
|
|
<span>signed in: {{ .AccountNav.Username }}</span>
|
|
<span>{{ .Status }}</span>
|
|
</footer>
|
|
</main>
|
|
{{ template "account_shell_end" . }}
|