[Web] add manage identity provider
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
<a class="nav-link dropdown-toggle active" data-bs-toggle="dropdown" href="#" role="button" aria-expanded="false">{{ lang.admin.access }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><button class="dropdown-item active" data-bs-target="#tab-config-admins" aria-selected="false" aria-controls="tab-config-admins" role="tab" data-bs-toggle="tab">{{ lang.admin.admins }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-identity-providers" aria-selected="false" aria-controls="tab-config-identity-providers" role="tab" data-bs-toggle="tab">Identity Providers</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-identity-provider" aria-selected="false" aria-controls="tab-config-identity-provider" role="tab" data-bs-toggle="tab">Identity Provider</button></li>
|
||||
<!-- <li><button class="dropdown-item" data-bs-target="#tab-config-ldap-admins" aria-controls="tab-config-ldap-admins" role="tab" data-bs-toggle="tab">{{ lang.admin.admins_ldap }}</button></li> -->
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-oauth2" aria-selected="false" aria-controls="tab-config-oauth2" role="tab" data-bs-toggle="tab">{{ lang.admin.oauth2_apps }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-rspamd" aria-selected="false" aria-controls="tab-config-rspamd" role="tab" data-bs-toggle="tab">Rspamd UI</button></li>
|
||||
@@ -41,7 +41,7 @@
|
||||
<div class="col-md-12">
|
||||
<div class="tab-content" style="padding-top:20px">
|
||||
{% include 'admin/tab-config-admins.twig' %}
|
||||
{% include 'admin/tab-config-identity-providers.twig' %}
|
||||
{% include 'admin/tab-config-identity-provider.twig' %}
|
||||
{# {% include 'admin/tab-ldap.twig' %} #}
|
||||
{% include 'admin/tab-config-oauth2.twig' %}
|
||||
{% include 'admin/tab-config-rspamd.twig' %}
|
||||
|
95
data/web/templates/admin/tab-config-identity-provider.twig
Normal file
95
data/web/templates/admin/tab-config-identity-provider.twig
Normal file
@@ -0,0 +1,95 @@
|
||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-identity-provider" role="tabpanel" aria-labelledby="tab-config-identity-provider">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-identity-provider" data-bs-toggle="collapse" aria-controls="collapse-tab-config-identity-provider">
|
||||
{{ lang.admin.iam }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.iam }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-identity-provider" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<p class="offset-sm-3 mb-4">{{ lang.admin.iam_description }}</p>
|
||||
<form class="form-horizontal" autocapitalize="none" data-id="iam_sso" autocorrect="off" role="form" method="post">
|
||||
<input type="hidden" name="authsource" value="keycloak">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="iam_url">{{ lang.admin.iam_server_url }}:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="iam_server_url" name="server_url" value="{{ identity_provider_settings.server_url }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="iam_realm">{{ lang.admin.iam_realm }}:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="iam_realm" name="realm" value="{{ identity_provider_settings.realm }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="iam_client_id">{{ lang.admin.iam_client_id }}:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="iam_client_id" name="client_id" value="{{ identity_provider_settings.client_id }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="iam_client_secret">{{ lang.admin.iam_client_secret }}:</label>
|
||||
<div class="col-sm-4">
|
||||
<div class="reveal-password-input input-group">
|
||||
<input type="password" class="password-field form-control" id="iam_client_secret" name="client_secret" value="{{ identity_provider_settings.client_secret }}" required>
|
||||
<button class="toggle-password btn btn-secondary" type="button"><i class="bi bi-eye"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="iam_redirect_url">{{ lang.admin.iam_redirect_url }}:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="iam_redirect_url" name="redirect_url" value="{{ identity_provider_settings.redirect_url }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="iam_version">{{ lang.admin.iam_version }}:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="iam_version" name="version" value="{{ identity_provider_settings.version }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="iam_version">{{ lang.admin.iam_rolemapping }}:</label>
|
||||
<div class="col-4 d-flex mb-2">
|
||||
<span class="w-100 me-2">Role</span>
|
||||
<span class="w-100 ms-2">Template</span>
|
||||
<button id="iam_rolemap_add" class="btn btn-sm d-block d-sm-inline btn-secondary ms-2"><i class="bi bi-plus-lg"></i></button>
|
||||
</div>
|
||||
{% for key, role in identity_provider_settings.roles %}
|
||||
<div class="offset-sm-3 col-4 d-flex mb-2">
|
||||
<input type="text" class="form-control me-2" name="roles" value="{{ identity_provider_settings.roles[key] }}">
|
||||
<select data-live-search="true" name="templates" class="form-control" title="{{ lang.mailbox.template }}">
|
||||
{% for mbox_template in mbox_templates %}
|
||||
<option{% if mbox_template.template == identity_provider_settings.templates[key] %} selected{% endif %}>
|
||||
{{ mbox_template.template }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<button class="iam_rolemap_del btn btn-sm d-block d-sm-inline btn-secondary ms-2"><i class="bi bi-x-lg"></i></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<div class="offset-sm-3 col-4 d-flex mb-2">
|
||||
<input type="text" class="form-control me-2" name="roles" value="">
|
||||
<select data-live-search="true" name="templates" class="form-control" title="{{ lang.mailbox.template }}">
|
||||
{% for mbox_template in mbox_templates %}
|
||||
<option>
|
||||
{{ mbox_template.template }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<button class="iam_rolemap_del btn btn-sm d-block d-sm-inline btn-secondary ms-2"><i class="bi bi-x-lg"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-4 mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<div class="btn-group">
|
||||
<button id="iam_test_connection" class="btn btn-sm d-block d-sm-inline btn-secondary"><i class="bi bi-play"></i> {{ lang.admin.iam_test_connection }}</button>
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-success" data-item="iam_sso" data-action="edit_selected" data-id="iam_sso" data-api-url='edit/identity_provider' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@@ -1,58 +0,0 @@
|
||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-identity-providers" role="tabpanel" aria-labelledby="tab-config-identity-providers">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-identity-providers" data-bs-toggle="collapse" aria-controls="collapse-tab-config-identity-providers">
|
||||
{{ lang.admin.oauth2_apps }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.oauth2_apps }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-identity-providers" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<form class="form-horizontal" autocapitalize="none" data-id="keycloak_sso" autocorrect="off" role="form" method="post">
|
||||
<input type="hidden" name="authsource" value="keycloak">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="keycloak_url">Server URL:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="keycloak_url" name="server_url" value="{{ identity_provider_settings.server_url }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="keycloak_realm">Realm:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="keycloak_realm" name="realm" value="{{ identity_provider_settings.realm }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="keycloak_client_id">Client Id:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="keycloak_client_id" name="client_id" value="{{ identity_provider_settings.client_id }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="keycloak_client_secret">Client Secret:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="keycloak_client_secret" name="client_secret" value="{{ identity_provider_settings.client_secret }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="keycloak_redirect_url">Redirect Url:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="keycloak_redirect_url" name="redirect_url" value="{{ identity_provider_settings.redirect_url }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="keycloak_version">Keycloak Version:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="keycloak_version" name="version" value="{{ identity_provider_settings.version }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-4 mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-success" data-item="keycloak_sso" data-action="edit_selected" data-id="keycloak_sso" data-api-url='edit/identity_provider' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@@ -148,6 +148,8 @@
|
||||
var lang_acl = {{ lang_acl|raw }};
|
||||
var lang_tfa = {{ lang_tfa|raw }};
|
||||
var lang_fido2 = {{ lang_fido2|raw }};
|
||||
var lang_success = {{ lang_success|raw }};
|
||||
var lang_danger = {{ lang_danger|raw }};
|
||||
var docker_timeout = {{ docker_timeout|raw }} * 1000;
|
||||
var mailcow_cc_role = '{{ mailcow_cc_role }}';
|
||||
var last_login = '{{ last_login }}';
|
||||
|
@@ -19,6 +19,15 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="authsource">{{ lang.admin.iam }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="full-width-select" data-live-search="true" id="mbox_template_iam" name="authsource" required>
|
||||
<option {% if template.attributes.authsource == 'mailcow' %}selected{% endif %}>mailcow</option>
|
||||
<option {% if template.attributes.authsource == 'keycloak' %}selected{% endif %}>keycloak</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2">{{ lang.add.tags }}</label>
|
||||
<div class="col-sm-10">
|
||||
|
@@ -17,9 +17,9 @@
|
||||
<input type="hidden" value="0" name="sogo_access">
|
||||
<input type="hidden" value="0" name="protocol_access">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2">{{ lang.edit.full_name }}</label>
|
||||
<label class="control-label col-sm-2">{{ lang.admin.iam }}</label>
|
||||
<div class="col-sm-10">
|
||||
<span>{{ result.authsource }}</span>
|
||||
<h4><span class="badge bg-primary">{{ result.authsource }}<i class="ms-2 bi bi-person-circle"></i></i></span></h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
@@ -188,6 +188,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if result.authsource == 'mailcow' %}
|
||||
<div class="row">
|
||||
<label class="control-label col-sm-2" for="password">{{ lang.edit.password }} (<a href="#" class="generate_password">{{ lang.edit.generate }}</a>)</label>
|
||||
<div class="col-sm-10">
|
||||
@@ -200,6 +201,7 @@
|
||||
<input type="password" data-pwgen-field="true" class="form-control" name="password2" autocomplete="new-password">
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div data-acl="{{ acl.extend_sender_acl }}" class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="extended_sender_acl">{{ lang.edit.extended_sender_acl }}</label>
|
||||
<div class="col-sm-10">
|
||||
|
@@ -23,6 +23,13 @@
|
||||
<div class="my-4 alert alert-info ">{{ lang.login.mobileconfig_info }}</div>
|
||||
{% endif %}
|
||||
<form method="post" autofill="off">
|
||||
{% if invalid_keycloak_sso %}
|
||||
<div class="d-flex mt-3 w-100">
|
||||
<div class="alert alert-danger w-100" role="alert">
|
||||
{{ lang.danger.iam_invalid_sso}}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="d-flex mt-3">
|
||||
<label class="visually-hidden" for="login_user">{{ lang.login.username }}</label>
|
||||
<div class="input-group">
|
||||
@@ -39,13 +46,14 @@
|
||||
</div>
|
||||
<div class="d-flex mt-4" style="position: relative">
|
||||
<div class="btn-group">
|
||||
<div class="btn-group">
|
||||
<button type="submit" class="btn btn-xs-lg btn-success" value="Login">{{ lang.login.login }}</button>
|
||||
<button type="button" class="btn btn-xs-lg btn-success dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#" id="fido2-login"><i class="bi bi-shield-fill-check"></i> {{ lang.login.fido2_webauthn }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-xs-lg btn-success" value="Login">{{ lang.login.login }}</button>
|
||||
<button type="button" class="btn btn-xs-lg btn-success dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#" id="fido2-login"><i class="bi bi-shield-fill-check"></i> {{ lang.login.fido2_webauthn }}</a></li>
|
||||
{% if has_keycloak_sso %}
|
||||
<li><a class="dropdown-item" href="/?keycloak_sso=1"><i class="bi bi-cloud-arrow-up-fill"></i> {{ lang.admin.iam_sso }}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
{% if not oauth2_request %}
|
||||
<button type="button" {% if available_languages|length == 1 %}disabled="true"{% endif %} class="btn btn-xs-lg btn-secondary ms-auto dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
|
@@ -12,6 +12,12 @@
|
||||
<input type="hidden" value="0" name="sogo_access">
|
||||
<input type="hidden" value="0" name="protocol_access">
|
||||
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end text-sm-end" for="name">{{ lang.add.full_name }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="name">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end text-sm-end" for="local_part">{{ lang.add.mailbox_username }}</label>
|
||||
<div class="col-sm-10">
|
||||
@@ -28,38 +34,34 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end text-sm-end" for="authsource">{{ lang.add.domain }}</label>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2 text-sm-end text-sm-end" for="description">{{ lang.mailbox.template }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="full-width-select" data-live-search="true" id="addAuthsource" name="authsource" required>
|
||||
<select data-live-search="true" id="mailbox_templates" class="form-control" title="{{ lang.mailbox.template }}">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end text-sm-end" for="authsource">{{ lang.admin.iam }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="full-width-select" data-live-search="true" id="mbox_add_iam" name="authsource" required>
|
||||
<option selected>mailcow</option>
|
||||
<option>keycloak</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2 text-sm-end text-sm-end" for="name">{{ lang.add.full_name }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="name">
|
||||
<div id="mbox_add_pwds">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end text-sm-end" for="password">{{ lang.add.password }} (<a href="#" class="generate_password">{{ lang.add.generate }}</a>)</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" data-pwgen-field="true" data-hibp="true" class="form-control" name="password" placeholder="" autocomplete="new-password" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end text-sm-end" for="password">{{ lang.add.password }} (<a href="#" class="generate_password">{{ lang.add.generate }}</a>)</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" data-pwgen-field="true" data-hibp="true" class="form-control" name="password" placeholder="" autocomplete="new-password" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2 text-sm-end text-sm-end" for="password2">{{ lang.add.password_repeat }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" data-pwgen-field="true" class="form-control" name="password2" placeholder="" autocomplete="new-password" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end text-sm-end" for="description">{{ lang.mailbox.template }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select data-live-search="true" id="mailbox_templates" class="form-control" title="{{ lang.mailbox.template }}">
|
||||
</select>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2 text-sm-end text-sm-end" for="password2">{{ lang.add.password_repeat }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" data-pwgen-field="true" class="form-control" name="password2" placeholder="" autocomplete="new-password" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
@@ -235,6 +237,15 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end text-sm-end" for="authsource">{{ lang.admin.iam }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="full-width-select" data-live-search="true" id="mbox_template_iam" name="authsource">
|
||||
<option selected>mailcow</option>
|
||||
<option>keycloak</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end text-sm-end">{{ lang.add.tags }}</label>
|
||||
<div class="col-sm-10">
|
||||
|
Reference in New Issue
Block a user