Initial commit: web-app boilerplate with auth, OIDC/SSO, admin panel, i18n
Rust (cot framework) + PostgreSQL boilerplate providing: - Session-based auth with Admin/User roles - OIDC/SSO login with PKCE, group-to-role mapping, auto-provisioning - Admin panel: user management, settings, debug/config inspector - 3-tier config system (compiled default → DB → FURU_* env vars) - i18n (English + Russian) with compile-time translations macro - JSON API skeleton (GET /api/me) - DB-backed sessions (survive server restarts) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{% block admin_title %}{{ t.nav_admin }}{% endblock admin_title %} | {{ t.site_name }}{% endblock title %}
|
||||
|
||||
{% block head_extra %}
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body { font-family: system-ui, -apple-system, sans-serif; display: flex; min-height: 100vh; background: #f5f5f5; color: #333; }
|
||||
nav.sidebar { width: 220px; background: #1a1a2e; color: #eee; padding: 1rem; }
|
||||
nav.sidebar h2 { font-size: 1.1rem; margin-bottom: 1.5rem; }
|
||||
nav.sidebar a { color: #ccc; text-decoration: none; display: block; padding: .4rem .6rem; border-radius: 4px; }
|
||||
nav.sidebar a:hover { background: #16213e; color: #fff; }
|
||||
.main-wrap { flex: 1; display: flex; flex-direction: column; }
|
||||
.topbar { display: flex; justify-content: flex-end; align-items: center; gap: 1rem; padding: .5rem 1.5rem; background: #fff; border-bottom: 1px solid #e0e0e0; }
|
||||
.user-info { font-size: .85rem; color: #555; }
|
||||
.lang-switch { display: flex; gap: .25rem; }
|
||||
.lang-switch a { text-decoration: none; padding: .25rem .5rem; border-radius: 4px; font-size: .9rem; color: #555; }
|
||||
.lang-switch a:hover { background: #eee; color: #111; }
|
||||
.lang-switch a.active { font-weight: 700; color: #111; }
|
||||
.logout-link { text-decoration: none; font-size: .85rem; color: #555; padding: .25rem .5rem; border-radius: 4px; }
|
||||
.logout-link:hover { background: #eee; color: #111; }
|
||||
.main { flex: 1; padding: 2rem; overflow-x: auto; }
|
||||
table { border-collapse: collapse; width: 100%; margin-bottom: 1.5rem; background: #fff; border-radius: 6px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,.1); }
|
||||
th, td { text-align: left; padding: .6rem .8rem; border-bottom: 1px solid #eee; }
|
||||
th { background: #f0f0f0; font-weight: 600; }
|
||||
h1 { margin-bottom: 1rem; }
|
||||
h2 { margin: 1.5rem 0 .5rem; }
|
||||
code { background: #f4f4f4; padding: .1rem .35rem; border-radius: 3px; font-size: .85em; }
|
||||
.badge { display: inline-block; padding: .15rem .55rem; border-radius: 4px; font-size: .8rem; font-weight: 600; letter-spacing: .02em; }
|
||||
.badge-default { background: #e9ecef; color: #555; }
|
||||
.badge-database { background: #d1ecf1; color: #0c5460; }
|
||||
.badge-env { background: #fff3cd; color: #856404; }
|
||||
</style>
|
||||
{% endblock head_extra %}
|
||||
|
||||
{% block body %}
|
||||
<nav class="sidebar">
|
||||
<h2>{{ t.site_name }} {{ t.nav_admin }}</h2>
|
||||
<a href="/admin/">{{ t.nav_dashboard }}</a>
|
||||
<a href="/admin/users">{{ t.nav_users }}</a>
|
||||
<a href="/admin/settings">{{ t.nav_settings }}</a>
|
||||
<a href="/admin/debug">{{ t.nav_debug }}</a>
|
||||
</nav>
|
||||
<div class="main-wrap">
|
||||
<div class="topbar">
|
||||
<span class="user-info">{{ user_name }} ({{ user_role }})</span>
|
||||
<div class="lang-switch">
|
||||
<a href="#"{% if t.lang.code() == "en" %} class="active"{% endif %} onclick="location.href='/set-lang?lang=en&next='+encodeURIComponent(location.pathname);return false">EN</a>
|
||||
<a href="#"{% if t.lang.code() == "ru" %} class="active"{% endif %} onclick="location.href='/set-lang?lang=ru&next='+encodeURIComponent(location.pathname);return false">RU</a>
|
||||
</div>
|
||||
<a class="logout-link" href="/logout">{{ t.nav_logout }}</a>
|
||||
</div>
|
||||
<div class="main">
|
||||
{% block content %}{% endblock content %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock body %}
|
||||
Reference in New Issue
Block a user