Upravil jsem Google OAuth tak, že Google uživatel se hledá/vytváří přes email, ukládá auth_provider='google', provider_subject, display_name, avatar_url a po úspěšném loginu last_login_at. První Google uživatel v prázdné users tabulce dostane admin, další noví Google uživatelé viewer.
Přidal jsem AUTH_MODE=google|mixed|local: google: jen Google login, lokální/Gitea nejdou ani přes přímý endpoint mixed: Google + lokální/Gitea fallback local: jen lokální login Správa uživatelů zůstává admin-only, guard posledního admina platí pro odebrání role i deaktivaci. Přidal jsem do ní i přehled oprávnění rolí a zobrazení provider/avatar metadat. DB migrace teď přes PRAGMA table_info(users) doplňuje chybějící sloupce bez mazání/recreate existující tabulky; pokud users vůbec neexistuje, bezpečně ji vytvoří. Podporované sloupce zahrnují email, display_name, role, is_enabled, created_at, updated_at, last_login_at, auth_provider, provider_subject, plus kompatibilní sloupce pro lokální login.
This commit is contained in:
+37
-1
@@ -31,6 +31,34 @@ def render_enabled_pill(enabled) -> str:
|
||||
return '<span class="pill pill-muted">disabled</span>'
|
||||
|
||||
|
||||
def render_role_overview() -> str:
|
||||
role_rows = (
|
||||
("admin", "Full administration, user management, role changes, disabling/enabling users, and admin-only operations."),
|
||||
("developer", "Operational portal access for application and service workflows. No access to Administration / Users."),
|
||||
("viewer", "Default Google role. Read-oriented portal access where routes allow it. No access to Administration / Users."),
|
||||
)
|
||||
rows = ""
|
||||
for role, description in role_rows:
|
||||
rows += f"""
|
||||
<tr>
|
||||
<td><span class="pill pill-muted">{html.escape(role)}</span></td>
|
||||
<td>{html.escape(description)}</td>
|
||||
</tr>
|
||||
"""
|
||||
return f"""
|
||||
<div class="card">
|
||||
<h2>Role Permissions</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Role</th>
|
||||
<th>Access</th>
|
||||
</tr>
|
||||
{rows}
|
||||
</table>
|
||||
</div>
|
||||
"""
|
||||
|
||||
|
||||
@router.get("/admin/users", response_class=HTMLResponse)
|
||||
def users_page(request: Request, message: str = "", error: str = "", user=Depends(require_user)):
|
||||
require_admin(user)
|
||||
@@ -49,6 +77,9 @@ def users_page(request: Request, message: str = "", error: str = "", user=Depend
|
||||
display_name = html.escape(managed_user.get("display_name", "") or "")
|
||||
email = html.escape(managed_user.get("email", "") or "")
|
||||
role = html.escape(managed_user.get("role", "") or "")
|
||||
auth_provider = html.escape(managed_user.get("auth_provider", "") or "")
|
||||
avatar_url = html.escape(managed_user.get("avatar_url", "") or "", quote=True)
|
||||
avatar = f'<img class="user-avatar" src="{avatar_url}" alt="">' if avatar_url else ""
|
||||
created_at = html.escape(managed_user.get("created_at", "") or "")
|
||||
last_login_at = html.escape(managed_user.get("last_login_at", "") or "")
|
||||
enabled = bool(managed_user.get("is_enabled", True))
|
||||
@@ -60,7 +91,9 @@ def users_page(request: Request, message: str = "", error: str = "", user=Depend
|
||||
<td>{user_id_html}</td>
|
||||
<td><strong>{username}</strong></td>
|
||||
<td>{display_name}</td>
|
||||
<td>{avatar}</td>
|
||||
<td>{email}</td>
|
||||
<td>{auth_provider}</td>
|
||||
<td>
|
||||
<form method="post" action="/portal/admin/users/{user_id_html}/role" class="inline-form">
|
||||
<select name="role">{render_role_options(role)}</select>
|
||||
@@ -79,7 +112,7 @@ def users_page(request: Request, message: str = "", error: str = "", user=Depend
|
||||
"""
|
||||
|
||||
if not rows:
|
||||
rows = '<tr><td colspan="9">No users found.</td></tr>'
|
||||
rows = '<tr><td colspan="11">No users found.</td></tr>'
|
||||
|
||||
return page(
|
||||
"Users",
|
||||
@@ -97,7 +130,9 @@ def users_page(request: Request, message: str = "", error: str = "", user=Depend
|
||||
<th>ID</th>
|
||||
<th>Username</th>
|
||||
<th>Display name</th>
|
||||
<th>Avatar</th>
|
||||
<th>Email</th>
|
||||
<th>Provider</th>
|
||||
<th>Role</th>
|
||||
<th>Status</th>
|
||||
<th>Created</th>
|
||||
@@ -107,6 +142,7 @@ def users_page(request: Request, message: str = "", error: str = "", user=Depend
|
||||
{rows}
|
||||
</table>
|
||||
</div>
|
||||
{render_role_overview()}
|
||||
""",
|
||||
user=user,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user