Files
enterprise_digital-platform/IT_asset_management/app/templates/settings/index.html
T
ske087 06b2152331 IT Assets: add portal sync button + wire env vars in start-dev.sh
- Portal: add /api/internal/itassets-users endpoint (returns all portal users
  with itassets access + their effective role)
- IT Assets: add PORTAL_INTERNAL_URL config key
- IT Assets: add POST /settings/sync-from-portal route (admin only) — pulls
  users from the portal API and upserts them locally
- Settings page: 'Sync from Portal' button next to the users table header
- start-dev.sh: pass INTERNAL_SYNC_SECRET and ITASSETS_INTERNAL_URL to portal;
  pass PORTAL_INTERNAL_URL and INTERNAL_SYNC_SECRET to itassets
- Also includes 'Back to Portal' icon button added to sidebar footer
2026-07-08 21:54:08 +03:00

205 lines
9.5 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends 'base.html' %}
{% block title %}Settings IT Asset Management{% endblock %}
{% block breadcrumb %}
<li class="breadcrumb-item"><a href="{{ url_for('dashboard.index') }}">Home</a></li>
<li class="breadcrumb-item active">Settings</li>
{% endblock %}
{% block content %}
<div class="page-header mb-4">
<h1><i class="bi bi-gear me-2"></i>Settings</h1>
</div>
<div class="row g-4">
<!-- App Users -->
<div class="col-md-7">
<div class="card border-0 shadow-sm">
<div class="card-header bg-white fw-semibold py-3 d-flex align-items-center justify-content-between">
<span><i class="bi bi-person-gear me-2 text-primary"></i>Application Users</span>
{% if current_user.is_admin %}
<form method="POST" action="{{ url_for('settings.sync_from_portal') }}" class="d-inline">
<button type="submit" class="btn btn-sm btn-outline-primary">
<i class="bi bi-arrow-repeat me-1"></i>Sync from Portal
</button>
</form>
{% endif %}
</div>
<div class="table-responsive">
<table class="table table-sm table-hover mb-0">
<thead class="table-light">
<tr><th>Username</th><th>Full Name</th><th>Email</th><th>Role</th><th>Last Login</th><th>Active</th>
{% if current_user.is_admin %}<th></th>{% endif %}
</tr>
</thead>
<tbody>
{% for a in admins %}
<tr>
<td><strong>{{ a.username }}</strong>{% if a.id == current_user.id %} <span class="badge bg-light text-secondary">you</span>{% endif %}</td>
<td>{{ a.full_name or '—' }}</td>
<td>{{ a.email }}</td>
<td>
<span class="badge {% if a.role == 'admin' %}bg-danger{% elif a.role == 'editor' %}bg-primary{% else %}bg-secondary{% endif %}">
{{ a.role }}
</span>
</td>
<td>{{ a.last_login.strftime('%d/%m/%Y') if a.last_login else '—' }}</td>
<td>
{% if a.is_active %}<span class="badge bg-success">Active</span>
{% else %}<span class="badge bg-secondary">Inactive</span>{% endif %}
</td>
{% if current_user.is_admin %}
<td class="text-end">
{% if a.id != current_user.id %}
<div class="d-flex gap-1 justify-content-end flex-wrap">
<!-- Toggle active -->
<form method="POST" action="{{ url_for('settings.toggle_admin', admin_id=a.id) }}" class="d-inline">
<button type="submit" class="btn btn-xs btn-sm btn-outline-{{ 'warning' if a.is_active else 'success' }} py-0 px-2">
{{ 'Deactivate' if a.is_active else 'Activate' }}
</button>
</form>
<!-- Change role -->
<form method="POST" action="{{ url_for('settings.change_role', admin_id=a.id) }}" class="d-inline">
<select name="role" class="form-select form-select-sm d-inline-block w-auto py-0" onchange="this.form.submit()">
<option value="admin" {% if a.role == 'admin' %}selected{% endif %}>admin</option>
<option value="editor" {% if a.role == 'editor' %}selected{% endif %}>editor</option>
<option value="readonly" {% if a.role == 'readonly' %}selected{% endif %}>readonly</option>
</select>
</form>
<!-- Reset password -->
<button type="button" class="btn btn-xs btn-sm btn-outline-secondary py-0 px-2"
data-bs-toggle="modal" data-bs-target="#pwModal{{ a.id }}">
<i class="bi bi-key"></i>
</button>
<!-- Delete -->
<form method="POST" action="{{ url_for('settings.delete_admin', admin_id=a.id) }}" class="d-inline"
onsubmit="return confirm('Delete user {{ a.username }}? This cannot be undone.')">
<button type="submit" class="btn btn-xs btn-sm btn-outline-danger py-0 px-2">
<i class="bi bi-trash"></i>
</button>
</form>
</div>
{% endif %}
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Add user form (admin only) -->
{% if current_user.is_admin %}
<div class="card-footer bg-white">
<h6 class="fw-semibold mb-3 mt-1"><i class="bi bi-person-plus me-1"></i>Add User</h6>
<form method="POST" action="{{ url_for('settings.create_admin') }}">
<div class="row g-2">
<div class="col-md-3">
<input type="text" name="username" class="form-control form-control-sm" placeholder="Username" required>
</div>
<div class="col-md-3">
<input type="text" name="full_name" class="form-control form-control-sm" placeholder="Full Name">
</div>
<div class="col-md-3">
<input type="email" name="email" class="form-control form-control-sm" placeholder="Email" required>
</div>
<div class="col-md-2">
<input type="password" name="password" class="form-control form-control-sm" placeholder="Password" required minlength="8">
</div>
<div class="col-md-2">
<select name="role" class="form-select form-select-sm">
<option value="readonly">readonly</option>
<option value="editor">editor</option>
<option value="admin">admin</option>
</select>
</div>
<div class="col-auto">
<button type="submit" class="btn btn-sm btn-primary">Add</button>
</div>
</div>
<small class="text-muted mt-1 d-block">
<strong>readonly</strong> view only &nbsp;|&nbsp;
<strong>editor</strong> create &amp; edit data &nbsp;|&nbsp;
<strong>admin</strong> full access including user management
</small>
</form>
</div>
{% endif %}
</div>
</div>
<!-- LDAP config info -->
<div class="col-md-5">
<div class="card border-0 shadow-sm">
<div class="card-header bg-white fw-semibold py-3">
<i class="bi bi-diagram-3 me-2 text-primary"></i>LDAP / AD Configuration
</div>
<div class="card-body">
<p class="text-muted small mb-3">
LDAP settings are managed via environment variables (see <code>.env</code> file).
Restart the application after changing these values.
</p>
<table class="table table-sm table-bordered mb-0">
<tbody>
<tr><th class="bg-light">LDAP_SERVER</th><td><code>{{ config.LDAP_SERVER or '(not set)' }}</code></td></tr>
<tr><th class="bg-light">LDAP_PORT</th><td>{{ config.LDAP_PORT }}</td></tr>
<tr><th class="bg-light">LDAP_USE_SSL</th><td>{{ config.LDAP_USE_SSL }}</td></tr>
<tr><th class="bg-light">LDAP_BASE_DN</th><td><code>{{ config.LDAP_BASE_DN or '(not set)' }}</code></td></tr>
<tr><th class="bg-light">LDAP_BIND_USER</th><td>{{ config.LDAP_BIND_USER or '(not set)' }}</td></tr>
<tr><th class="bg-light">Windows ID attr</th><td><code>{{ config.LDAP_WINDOWS_ID_ATTR }}</code></td></tr>
</tbody>
</table>
<div class="mt-3">
{% if current_user.is_editor %}
<a href="{{ url_for('users.import_page') }}" class="btn btn-sm btn-outline-primary">
<i class="bi bi-arrow-repeat me-1"></i>Go to Import / Sync
</a>
{% endif %}
</div>
</div>
</div>
<div class="card border-0 shadow-sm mt-3">
<div class="card-header bg-white fw-semibold py-3">
<i class="bi bi-building me-2 text-primary"></i>Company Info (for PDFs)
</div>
<div class="card-body">
<table class="table table-sm table-bordered mb-0">
<tbody>
<tr><th class="bg-light">COMPANY_NAME</th><td>{{ config.COMPANY_NAME or '(not set)' }}</td></tr>
<tr><th class="bg-light">COMPANY_ADDRESS</th><td>{{ config.COMPANY_ADDRESS or '(not set)' }}</td></tr>
</tbody>
</table>
<p class="small text-muted mt-2 mb-0">Edit these in <code>.env</code> and restart.</p>
</div>
</div>
</div>
</div>
<!-- Password reset modals (one per user, admin only) -->
{% if current_user.is_admin %}
{% for a in admins %}
{% if a.id != current_user.id %}
<div class="modal fade" id="pwModal{{ a.id }}" tabindex="-1">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<form method="POST" action="{{ url_for('settings.reset_password', admin_id=a.id) }}">
<div class="modal-header">
<h6 class="modal-title">Reset password — {{ a.username }}</h6>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<input type="password" name="new_password" class="form-control" placeholder="New password (min 8 chars)" required minlength="8">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-sm btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-sm btn-primary">Reset</button>
</div>
</form>
</div>
</div>
</div>
{% endif %}
{% endfor %}
{% endif %}
{% endblock %}