mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-02-08 05:08:50 -06:00
feat(core/auth/ui): proxy-aware config, optional OIDC, i18n v4, health checks
- core: add ProxyFix, robust logging setup, rate-limit defaults; mask DB URL in logs
- db: prefer Postgres when POSTGRES_* envs present; initialization helpers and safe task table migration check
- i18n: upgrade to Flask-Babel v4 with locale selector; compile catalogs; add set-language route
- auth: optional OIDC via Authlib (login, callback, logout); login rate limiting; profile language and theme persistence; ensure admin promotion
- admin: branding logo upload/serve; PDF layout editor with preview/reset; backup/restore with progress; system info; license-server controls
- ui: new base layout with improved nav, mobile tab bar, theme/density toggles, CSRF meta + auto-injection, DataTables/Chart.js, Socket.IO boot
- ops: add /_health and /_ready endpoints; Docker healthcheck targets /_health; enable top-level templates via ChoiceLoader
- deps: update/add Authlib, Flask-Babel 4, and related security/util packages
Refs: app/__init__.py, app/config.py, app/routes/{auth,admin,main}.py, app/templates/base.html, Dockerfile, requirements.txt, templates/*
79 lines
3.8 KiB
HTML
79 lines
3.8 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}{{ _('New User') }} - {{ app_name }}{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container-fluid">
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<div>
|
|
<nav aria-label="breadcrumb">
|
|
<ol class="breadcrumb">
|
|
<li class="breadcrumb-item"><a href="{{ url_for('admin.admin_dashboard') }}">{{ _('Admin') }}</a></li>
|
|
<li class="breadcrumb-item"><a href="{{ url_for('admin.list_users') }}">{{ _('Users') }}</a></li>
|
|
<li class="breadcrumb-item active">{{ _('New') }}</li>
|
|
</ol>
|
|
</nav>
|
|
<h1 class="h3 mb-0">
|
|
<i class="fas fa-user-plus text-primary"></i> {{ _('New User') }}
|
|
</h1>
|
|
</div>
|
|
<div>
|
|
<a href="{{ url_for('admin.list_users') }}" class="btn btn-secondary">
|
|
<i class="fas fa-arrow-left"></i> {{ _('Back to Users') }}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-lg-8">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-id-card"></i> {{ _('User Information') }}
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<form method="POST" action="{{ url_for('admin.create_user') }}">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label for="username" class="form-label">{{ _('Username') }} *</label>
|
|
<input type="text" class="form-control" id="username" name="username" required value="{{ request.form.get('username','') }}" placeholder="{{ _('Enter username') }}">
|
|
<div class="form-text">{{ _('Lowercase; must be unique.') }}</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label for="role" class="form-label">{{ _('Role') }} *</label>
|
|
<select class="form-select" id="role" name="role" required>
|
|
{% set current_role = request.form.get('role','user') %}
|
|
<option value="user" {% if current_role == 'user' %}selected{% endif %}>{{ _('User') }}</option>
|
|
<option value="admin" {% if current_role == 'admin' %}selected{% endif %}>{{ _('Admin') }}</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="d-flex justify-content-between">
|
|
<a href="{{ url_for('admin.list_users') }}" class="btn btn-secondary">
|
|
<i class="fas fa-times me-2"></i>{{ _('Cancel') }}
|
|
</a>
|
|
<button type="submit" class="btn btn-primary">
|
|
<i class="fas fa-save me-2"></i>{{ _('Create User') }}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
|