This commit is contained in:
delete 2026-06-10 20:51:17 +03:00
commit b15b95781c
108 changed files with 14802 additions and 0 deletions

View file

@ -0,0 +1,200 @@
{{define "content"}}
<section class="hero hero-split">
<div>
<p class="eyebrow">{{.Eyebrow}}</p>
<h1>{{.Heading}}</h1>
<p class="lede">{{.Description}}</p>
</div>
{{if .APIKey}}
<div class="hero-meta">
<span class="pill {{if .APIKey.IsActive}}pill-success{{else}}pill-muted{{end}}">
{{if .APIKey.IsActive}}Active{{else}}Revoked{{end}}
</span>
<p class="resource-slug">{{.APIKey.KeyPrefix}}</p>
</div>
{{end}}
</section>
{{if .Form.RevealKey}}
<section class="alert-card alert-success">
<p><strong>Copy this API key now:</strong> <code class="secret-code">{{.Form.RevealKey}}</code></p>
<p>This is the only time the full raw key will be shown. Only the hash and short prefix are stored.</p>
</section>
{{end}}
{{if .Form.Error}}
<section class="alert-card alert-error">
<p>{{.Form.Error}}</p>
</section>
{{end}}
<section class="section-grid">
<article class="section-card">
<div class="section-heading">
<h2>Key Details</h2>
<p>Choose a stable label, minimum permissions, and one scope mode for this key.</p>
</div>
<form class="stack-form" method="post" action="{{.Form.Action}}">
{{template "csrf_field" .}}
<label class="field">
<span>Name</span>
<input type="text" name="name" value="{{.Form.Name}}" maxlength="120" required>
</label>
<label class="field">
<span>Description</span>
<textarea name="description" rows="4">{{.Form.Description}}</textarea>
</label>
<label class="field">
<span>Scope mode</span>
<select name="scope_mode" required>
<option value="all_projects" {{if eq .Form.ScopeMode "all_projects"}}selected{{end}}>all_projects</option>
<option value="project_allow_list" {{if eq .Form.ScopeMode "project_allow_list"}}selected{{end}}>project_allow_list</option>
<option value="project_deny_list" {{if eq .Form.ScopeMode "project_deny_list"}}selected{{end}}>project_deny_list</option>
<option value="tag_allow_list" {{if eq .Form.ScopeMode "tag_allow_list"}}selected{{end}}>tag_allow_list</option>
<option value="tag_deny_list" {{if eq .Form.ScopeMode "tag_deny_list"}}selected{{end}}>tag_deny_list</option>
</select>
</label>
<label class="field">
<span>Expires at</span>
<input type="text" name="expires_at" value="{{.Form.ExpiresAt}}" placeholder="2026-12-31T23:59:59Z or 2026-12-31">
</label>
<fieldset class="choice-group">
<legend>Permissions</legend>
<label class="choice-row">
<input type="checkbox" name="can_download" value="1" {{if .Form.CanDownload}}checked{{end}}>
<span><strong>updates.read</strong> style access for listing or downloading releases.</span>
</label>
<label class="choice-row">
<input type="checkbox" name="can_upload" value="1" {{if .Form.CanUpload}}checked{{end}}>
<span>Upload release artifacts.</span>
</label>
<label class="choice-row">
<input type="checkbox" name="can_delete" value="1" {{if .Form.CanDelete}}checked{{end}}>
<span>Delete or disable release records later.</span>
</label>
<label class="choice-row">
<input type="checkbox" name="can_manage_projects" value="1" {{if .Form.CanManageProjects}}checked{{end}}>
<span>Create or edit projects.</span>
</label>
</fieldset>
<fieldset class="choice-group">
<legend>Project rules</legend>
<p class="helper-copy">Used only for <code>project_allow_list</code> and <code>project_deny_list</code>.</p>
{{if .ProjectChoices}}
<div class="choice-list">
{{range .ProjectChoices}}
<label class="choice-row">
<input type="checkbox" name="project_id" value="{{.Project.ID}}" {{if .Selected}}checked{{end}}>
<span>{{.Project.Name}} <code>{{.Project.Slug}}</code> {{if not .Project.IsActive}}(archived){{end}}</span>
</label>
{{end}}
</div>
{{else}}
<p class="empty-copy">No projects exist yet.</p>
{{end}}
</fieldset>
<fieldset class="choice-group">
<legend>Tag rules</legend>
<p class="helper-copy">Used only for <code>tag_allow_list</code> and <code>tag_deny_list</code>.</p>
{{if .TagChoices}}
<div class="choice-list">
{{range .TagChoices}}
<label class="choice-row">
<input type="checkbox" name="tag_id" value="{{.Tag.ID}}" {{if .Selected}}checked{{end}}>
<span>{{.Tag.Name}} <code>{{.Tag.Slug}}</code></span>
</label>
{{end}}
</div>
{{else}}
<p class="empty-copy">No tags exist yet.</p>
{{end}}
</fieldset>
<div class="button-row">
<button class="button" type="submit">{{.Form.SubmitLabel}}</button>
<a class="button button-secondary" href="/admin/api-keys">Back to API keys</a>
</div>
</form>
</article>
{{if .APIKey}}
<article class="section-card">
<div class="section-heading">
<h2>Lifecycle</h2>
<p>Disabled or expired keys are rejected before any project scope checks happen.</p>
</div>
<p class="meta-line"><strong>Created:</strong> {{.APIKey.CreatedAt.Format "2006-01-02 15:04 UTC"}}</p>
<p class="meta-line"><strong>Updated:</strong> {{.APIKey.UpdatedAt.Format "2006-01-02 15:04 UTC"}}</p>
<p class="meta-line"><strong>Last used:</strong> {{if .APIKey.LastUsedAt}}{{.APIKey.LastUsedAt.Format "2006-01-02 15:04 UTC"}}{{else}}Never{{end}}</p>
<p class="meta-line"><strong>Expires:</strong> {{if .APIKey.ExpiresAt}}{{.APIKey.ExpiresAt.Format "2006-01-02 15:04 UTC"}}{{else}}No expiry{{end}}</p>
<form class="stack-form" method="post" action="{{.ToggleAction}}">
{{template "csrf_field" .}}
<input type="hidden" name="state" value="{{.ToggleState}}">
<button class="button button-secondary" type="submit">{{.ToggleLabel}}</button>
</form>
</article>
{{end}}
</section>
{{if .APIKey}}
<section class="section-card section-card-wide">
<div class="section-heading">
<h2>Effective Access Preview</h2>
<p>This preview shows the active projects currently reachable after scope mode evaluation.</p>
</div>
{{if .AccessibleProjects}}
<div class="resource-grid compact-grid">
{{range .AccessibleProjects}}
<article class="resource-card">
<div class="resource-header">
<div>
<h3>{{.Name}}</h3>
<p class="resource-slug">{{.Slug}}</p>
</div>
<span class="pill pill-success">Active</span>
</div>
<p class="resource-description">{{if .Description}}{{.Description}}{{else}}No description yet.{{end}}</p>
</article>
{{end}}
</div>
{{else}}
<p class="empty-copy">No active projects currently match this key.</p>
{{end}}
</section>
<section class="section-card section-card-wide">
<div class="section-heading">
<h2>Client API Quick Start</h2>
<p>Clients should authenticate with a bearer API key and then discover projects before requesting metadata or downloading an artifact.</p>
</div>
<div class="endpoint-list">
<p class="meta-line"><strong>Bearer header:</strong> <code>Authorization: Bearer {{if .Form.RevealKey}}{{.Form.RevealKey}}{{else}}&lt;paste-api-key&gt;{{end}}</code></p>
<p class="meta-line"><strong>Accessible projects:</strong> <code>{{.BaseURL}}/api/v1/projects</code></p>
</div>
<pre class="code-block"><code>curl -H "Authorization: Bearer {{if .Form.RevealKey}}{{.Form.RevealKey}}{{else}}&lt;paste-api-key&gt;{{end}}" \
{{.BaseURL}}/api/v1/projects</code></pre>
{{if .AccessibleProjects}}
<div class="endpoint-list">
{{range .AccessibleProjects}}
<p class="meta-line"><strong>{{.Name}} latest metadata:</strong> <code>{{printf "%s/api/v1/projects/%s/releases/latest" $.BaseURL .Slug}}</code></p>
{{end}}
</div>
{{else}}
<p class="empty-copy">This key does not currently expose any active projects, so client metadata and download lookups will return no accessible resources.</p>
{{end}}
</section>
{{end}}
{{end}}