feat(api): add public RESTful API with API key auth and documentation page
This commit is contained in:
@@ -6,8 +6,9 @@
|
||||
</div>
|
||||
|
||||
<div class="tabs" id="tabs">
|
||||
<button class="tab {% if active_tab != 'showcase' %}active{% endif %}" onclick="switchTab('account')">{{ 'settings.tab_account'|t(user.language) }}</button>
|
||||
<button class="tab {% if active_tab != 'showcase' and active_tab != 'apikeys' %}active{% endif %}" onclick="switchTab('account')">{{ 'settings.tab_account'|t(user.language) }}</button>
|
||||
<button class="tab {% if active_tab == 'showcase' %}active{% endif %}" onclick="switchTab('showcase')">{{ 'settings.tab_showcase'|t(user.language) }}</button>
|
||||
<button class="tab {% if active_tab == 'apikeys' %}active{% endif %}" onclick="switchTab('apikeys')">{{ 'settings.tab_apikeys'|t(user.language) }}</button>
|
||||
</div>
|
||||
|
||||
{% if success %}
|
||||
@@ -17,7 +18,7 @@
|
||||
<div class="alert alert-error">{{ error }}</div>
|
||||
{% endif %}
|
||||
|
||||
<div id="tab-account" class="tab-panel" {% if active_tab == 'showcase' %}style="display:none"{% endif %}>
|
||||
<div id="tab-account" class="tab-panel" {% if active_tab == 'showcase' or active_tab == 'apikeys' %}style="display:none"{% endif %}>
|
||||
<div class="form-card">
|
||||
<h3 style="margin-bottom:.75rem">{{ 'settings.change_username'|t(user.language) }}</h3>
|
||||
<form method="post" action="/settings/change-username">
|
||||
@@ -155,6 +156,61 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="tab-apikeys" class="tab-panel" {% if active_tab != 'apikeys' %}style="display:none"{% endif %}>
|
||||
<div class="form-card">
|
||||
<h3 style="margin-bottom:.75rem">{{ 'apikey.title'|t(user.language) }}</h3>
|
||||
<p style="color:var(--text-muted);font-size:.85rem;margin-bottom:1rem">{{ 'apikey.hint'|t(user.language) }}</p>
|
||||
|
||||
{% if new_key %}
|
||||
<div class="alert alert-success" style="margin-bottom:1rem">
|
||||
<strong>{{ 'apikey.created'|t(user.language) }}</strong><br>
|
||||
<code style="word-break:break-all;font-size:.85rem">{{ new_key }}</code><br>
|
||||
<small style="color:var(--text-muted)">{{ 'apikey.copy_now'|t(user.language) }}</small>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="/settings/apikeys/create" style="display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem">
|
||||
<input type="text" name="name" placeholder="{{ 'apikey.name_ph'|t(user.language) }}" style="max-width:200px">
|
||||
<button type="submit" class="btn btn-primary btn-sm">{{ 'apikey.create'|t(user.language) }}</button>
|
||||
</form>
|
||||
|
||||
{% if api_keys %}
|
||||
<div class="table-wrap">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'apikey.name'|t(user.language) }}</th>
|
||||
<th>{{ 'apikey.key'|t(user.language) }}</th>
|
||||
<th>{{ 'apikey.created_at'|t(user.language) }}</th>
|
||||
<th>{{ 'apikey.last_used'|t(user.language) }}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for ak in api_keys %}
|
||||
<tr>
|
||||
<td>{{ ak.name or '—' }}</td>
|
||||
<td><code style="font-size:.8rem">{{ ak.key[:8] }}****</code></td>
|
||||
<td>{{ ak.created_at|to_local|strftime('%Y-%m-%d') }}</td>
|
||||
<td>{% if ak.last_used_at %}{{ ak.last_used_at|to_local|strftime('%Y-%m-%d') }}{% else %}—{% endif %}</td>
|
||||
<td>
|
||||
<form method="post" action="/settings/apikeys/{{ ak.id }}/delete" style="display:inline" onsubmit="return confirm('{{ 'apikey.confirm_delete'|t(user.language) }}')">
|
||||
<button type="submit" class="btn btn-danger btn-sm">{{ 'apikey.delete'|t(user.language) }}</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="empty-state">
|
||||
<p>{{ 'apikey.empty'|t(user.language) }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function switchTab(name) {
|
||||
document.querySelectorAll('.tab').forEach(function(t) { t.classList.remove('active'); });
|
||||
|
||||
Reference in New Issue
Block a user