81dee5cba2
- ad_connector: страницы управления OU и импорта из AD, поле ad_ou_dn в Directory, ADSyncLog; расширение sync-сервиса и клиента - mattermost_connector: personal access token шифруется (Fernet, token_service), бот-сервис, команды создания бота и синхронизации; публикация постов в каналы. Тесты (19) - core: ConnectorConfig, Directory (ad_ou_dn), обновления админки Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
127 lines
9.0 KiB
HTML
127 lines
9.0 KiB
HTML
<div class="page-content" id="ad-ou-manage-page">
|
|
|
|
<div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:1rem; gap:1rem; flex-wrap:wrap;">
|
|
<div>
|
|
<h1 style="font-size:1.25rem; font-weight:500; color:var(--color-foreground);">Організаційні юніти Active Directory</h1>
|
|
<p style="font-size:0.875rem; color:var(--color-muted-foreground); margin-top:0.25rem;">Управління OU та їх прив'язкою до відділів (Directory.ad_ou_dn)</p>
|
|
</div>
|
|
<a href="#" class="btn btn-primary"
|
|
hx-get="/ad-ou-manage/" hx-target="#main-content" hx-push-url="/ad-ou-manage/" hx-indicator="#loader">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/>
|
|
</svg>
|
|
Оновити
|
|
</a>
|
|
</div>
|
|
|
|
{% include "partials/ad_connector_tabs.html" with active="ou" %}
|
|
|
|
{% if notice %}
|
|
<div style="background:rgba(22,163,74,0.08); border:1px solid rgba(22,163,74,0.3); border-radius:0.75rem; padding:1rem 1.25rem; margin-bottom:1.5rem; font-size:0.875rem; color:#16a34a;">
|
|
{{ notice }}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if ad_error %}
|
|
<div style="background:color-mix(in srgb, var(--color-destructive) 8%, transparent); border:1px solid color-mix(in srgb, var(--color-destructive) 30%, transparent); border-radius:0.75rem; padding:1rem 1.25rem; margin-bottom:1.5rem; display:flex; align-items:center; gap:0.75rem;">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--color-destructive)" stroke-width="2" style="flex-shrink:0;">
|
|
<circle cx="12" cy="12" r="10"/><line x1="12" x2="12" y1="8" y2="12"/><line x1="12" x2="12.01" y1="16" y2="16"/>
|
|
</svg>
|
|
<div style="font-size:0.875rem; color:var(--color-destructive);">{{ ad_error }}</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Создание OU -->
|
|
<div style="background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); box-shadow:0 1px 2px rgb(0 0 0 / 0.05); margin-bottom:1.5rem;">
|
|
<div style="padding:1.25rem 1.5rem; border-bottom:1px solid var(--color-border);">
|
|
<h3 style="font-weight:600; color:var(--color-card-foreground); font-size:0.9375rem;">Нова OU</h3>
|
|
</div>
|
|
<form hx-post="/ad-ou-manage/" hx-target="#main-content" hx-indicator="#loader"
|
|
style="padding:1.25rem 1.5rem; display:flex; align-items:flex-end; gap:0.75rem; flex-wrap:wrap;">
|
|
{% csrf_token %}
|
|
<input type="hidden" name="action" value="create">
|
|
<div>
|
|
<label style="display:block; font-size:0.8125rem; color:var(--color-muted-foreground); margin-bottom:0.25rem;">Назва</label>
|
|
<input type="text" name="name" required class="input" style="max-width:16rem;">
|
|
</div>
|
|
<div>
|
|
<label style="display:block; font-size:0.8125rem; color:var(--color-muted-foreground); margin-bottom:0.25rem;">Батьківська OU</label>
|
|
<select name="parent_dn" class="input" style="max-width:26rem;">
|
|
<option value="{{ root_ou }}">{{ root_ou }} (корінь)</option>
|
|
{% for ou in ous %}
|
|
<option value="{{ ou.dn }}">{{ ou.dn }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary" style="font-size:0.8125rem;">Створити</button>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- Список OU -->
|
|
<div style="background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); box-shadow:0 1px 2px rgb(0 0 0 / 0.05);">
|
|
<div style="padding:1.25rem 1.5rem; border-bottom:1px solid var(--color-border);">
|
|
<h3 style="font-weight:600; color:var(--color-card-foreground); font-size:0.9375rem;">OU в домені</h3>
|
|
<p style="font-size:0.8125rem; color:var(--color-muted-foreground); margin-top:0.125rem;">{{ ous_page.paginator.count }} організаційних юнітів</p>
|
|
</div>
|
|
<div style="overflow-x:auto;">
|
|
<table style="width:100%; border-collapse:collapse; font-size:0.875rem;">
|
|
<thead>
|
|
<tr style="border-bottom:1px solid var(--color-border);">
|
|
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">OU</th>
|
|
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">Відділ</th>
|
|
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">Перейменувати</th>
|
|
<th style="padding:0.75rem 1rem; text-align:right; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">Дії</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for ou in ous_page %}
|
|
<tr style="border-bottom:1px solid var(--color-border);" class="tr-hover">
|
|
<td style="padding:0.875rem 1rem; vertical-align:middle;">
|
|
<div style="font-weight:500; color:var(--color-card-foreground);">{{ ou.name }}</div>
|
|
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.125rem; max-width:24rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;" title="{{ ou.dn }}">{{ ou.dn }}</div>
|
|
</td>
|
|
<td style="padding:0.875rem 1rem; vertical-align:middle;">
|
|
{% if ou.department %}
|
|
<span style="display:inline-flex; align-items:center; padding:0.125rem 0.625rem; border-radius:9999px; font-size:0.75rem; font-weight:500; background:rgba(37,99,235,0.1); color:#2563eb;">{{ ou.department }}</span>
|
|
{% else %}
|
|
<span style="color:var(--color-muted-foreground); font-size:0.8125rem;">—</span>
|
|
{% endif %}
|
|
</td>
|
|
<td style="padding:0.875rem 1rem; vertical-align:middle;">
|
|
<form hx-post="/ad-ou-manage/" hx-target="#main-content" hx-indicator="#loader" style="display:flex; align-items:center; gap:0.5rem; margin:0;">
|
|
{% csrf_token %}
|
|
<input type="hidden" name="action" value="rename">
|
|
<input type="hidden" name="dn" value="{{ ou.dn }}">
|
|
<input type="text" name="new_name" value="{{ ou.name }}" class="input" style="font-size:0.8125rem; padding:0.3rem 0.5rem; height:auto; max-width:12rem;">
|
|
<button type="submit" class="btn btn-ghost" style="font-size:0.8125rem; padding:0.3rem 0.75rem;">Перейменувати</button>
|
|
</form>
|
|
</td>
|
|
<td style="padding:0.875rem 1rem; vertical-align:middle; text-align:right; white-space:nowrap;">
|
|
<form hx-post="/ad-ou-manage/" hx-target="#main-content" hx-indicator="#loader"
|
|
hx-confirm="Видалити OU «{{ ou.name }}»? Дія доступна лише для порожніх OU."
|
|
style="display:inline; margin:0;">
|
|
{% csrf_token %}
|
|
<input type="hidden" name="action" value="delete">
|
|
<input type="hidden" name="dn" value="{{ ou.dn }}">
|
|
<button type="submit" class="btn btn-ghost" style="font-size:0.8125rem; padding:0.3rem 0.75rem; color:var(--color-destructive);">Видалити</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
{% empty %}
|
|
<tr>
|
|
<td colspan="4" style="padding:2rem; text-align:center; color:var(--color-muted-foreground);">OU не знайдено</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% include "partials/pagination.html" with page=ous_page base_url="/ad-ou-manage/" page_param="ou_page" size_param="ou_per_page" item_label="OU" %}
|
|
</div>
|
|
|
|
<p style="font-size:0.8125rem; color:var(--color-muted-foreground); margin-top:1rem;">
|
|
Щоб прив'язати OU до відділу, вкажіть її DN у полі «OU в Active Directory» картки відділу (Довідники → Відділи).
|
|
При синхронізації співробітник переноситься в OU свого відділу автоматично.
|
|
</p>
|
|
|
|
</div>
|