feat(ui): added teaser styling for CE EE-3780 (#7323)

* added teaser styling for CE
pull/7467/head
Richard Wei 2022-08-12 12:03:30 +12:00 committed by GitHub
parent 1fbaf5fcbf
commit a247db7e93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 529 additions and 434 deletions

View File

@ -886,6 +886,10 @@ json-tree .branch-preview {
text-decoration-line: underline;
}
reach-portal > div {
z-index: 10;
}
input[style*='background-image: url("data:image/png'] + [data-cy='auth-passwordInputToggle'] {
right: 20px;
}

View File

@ -86,7 +86,7 @@
--orange-1: #e86925;
--BE-only: var(--orange-1);
--BE-only: var(--ui-warning-7);
/* Default Theme */
--bg-card-color: var(--white-color);

4
app/assets/ico/lock.svg Normal file
View File

@ -0,0 +1,4 @@
<svg width="76" height="75" viewBox="0 0 76 75" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect opacity="0.2" x="0.5" width="75" height="75" rx="37.5" fill="#713B12"/>
<path d="M31.5353 36.1666V30.8333C31.5353 29.0652 32.2164 27.3695 33.4288 26.1192C34.6412 24.869 36.2855 24.1666 38 24.1666C39.7145 24.1666 41.3588 24.869 42.5712 26.1192C43.7835 27.3695 44.4646 29.0652 44.4646 30.8333V36.1666M28.9495 36.1666H47.0505C48.4786 36.1666 49.6364 37.3605 49.6364 38.8333V48.1666C49.6364 49.6394 48.4786 50.8333 47.0505 50.8333H28.9495C27.5214 50.8333 26.3636 49.6394 26.3636 48.1666V38.8333C26.3636 37.3605 27.5214 36.1666 28.9495 36.1666Z" stroke="#FEC84B" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 735 B

View File

@ -1,5 +1,5 @@
<a class="ml-5 vertical-center" href="{{ $ctrl.url }}" target="_blank" rel="noopener" ng-if="$ctrl.limitedToBE">
<ng-transclude></ng-transclude>
<pr-icon icon="'briefcase'" feather="true" class="icon-primary"></pr-icon>
<pr-icon icon="'briefcase'" feather="true" class-name="'icon icon-sm vertical-center'"></pr-icon>
<span class="be-indicator-label">Business Edition Feature</span>
</a>

View File

@ -20,14 +20,59 @@ button.limited-be.oauth-save-settings-button {
ng-form.limited-be,
form.limited-be,
div.limited-be {
border: solid 1px var(--BE-only);
box-shadow: var(--shadow-boxselector-color);
padding: 10px;
border: solid 2px var(--BE-only);
border-radius: 8px;
pointer-events: none;
touch-action: none;
display: block;
}
.limited-be-content {
background: rgba(247, 144, 9, 0.1);
opacity: 0.5;
padding: 10px;
}
.limited-be-link {
z-index: 5;
position: relative;
width: 270px;
height: 40px;
top: 0px;
right: 0px;
float: right;
border-top-right-radius: 8px;
border-bottom-left-radius: 8px;
background-color: var(--ui-warning-5);
color: var(--ui-warning-9);
padding: 5px 10px;
touch-action: auto;
cursor: hand;
pointer-events: auto;
}
.limited-be-link a {
cursor: hand;
pointer-events: auto;
color: var(--ui-warning-9);
}
.limited-be-link a:hover {
text-decoration: underline;
color: var(--ui-warning-9);
}
.overlay {
background-image: url(../../assets/ico/lock.svg);
background-repeat: no-repeat;
background-position: center;
}
.limited-be input,
.limited-be .widget-body {
background: rgba(247, 144, 9, 0.05);
}
.form-control.limited-be[disabled] {
background-color: transparent !important;
}

View File

@ -1,170 +1,176 @@
<ng-form class="ad-settings" limited-feature-dir="{{::$ctrl.limitedFeatureId}}" limited-feature-class="limited-be">
<be-feature-indicator feature="$ctrl.limitedFeatureId" class="my-8 block"></be-feature-indicator>
<div class="overlay">
<div class="limited-be-link vertical-center"
><be-feature-indicator feature="$ctrl.limitedFeatureId"></be-feature-indicator
><portainer-tooltip message="'This feature is currently limited to Business Edition users only. '"></portainer-tooltip
></div>
<div class="limited-be-content">
<auto-user-provision-toggle ng-model="$ctrl.settings.AutoCreateUsers">
<field-description>
With automatic user provisioning enabled, Portainer will create user(s) automatically with standard user role and assign them to team(s) which matches to LDAP group
name(s). If disabled, users must be created in Portainer beforehand.
</field-description>
</auto-user-provision-toggle>
<auto-user-provision-toggle ng-model="$ctrl.settings.AutoCreateUsers">
<field-description>
With automatic user provisioning enabled, Portainer will create user(s) automatically with standard user role and assign them to team(s) which matches to LDAP group name(s).
If disabled, users must be created in Portainer beforehand.
</field-description>
</auto-user-provision-toggle>
<div>
<div class="col-sm-12 form-section-title"> Information </div>
<div class="form-group col-sm-12 text-muted small">
When using Microsoft AD authentication, Portainer will delegate user authentication to the Domain Controller(s) configured below; if there is no connectivity, Portainer will
fallback to internal authentication.
</div>
</div>
<div class="col-sm-12 form-section-title"> AD configuration </div>
<div class="form-group">
<div class="col-sm-12 small text-muted">
<p class="vertical-center">
<pr-icon icon="'info'" feather="true" mode="'primary'"></pr-icon>
You can configure multiple AD Controllers for authentication fallback. Make sure all servers are using the same configuration (i.e. if TLS is enabled, they should all use
the same certificates).
</p>
</div>
</div>
<div class="form-group">
<label for="ldap_url" class="col-sm-3 col-lg-2 control-label text-left" style="display: flex; flex-wrap: wrap">
AD Controller
<button
type="button"
class="label label-default interactive vertical-center"
style="border: 0"
ng-click="$ctrl.addLDAPUrl()"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
>
<pr-icon icon="'plus-circle'" feather="true"></pr-icon>
Add additional server
</button>
</label>
<div class="col-sm-9 col-lg-10">
<div ng-repeat="url in $ctrl.settings.URLs track by $index" style="display: flex; margin-bottom: 10px">
<input
type="text"
class="form-control"
id="ldap_url"
ng-model="$ctrl.settings.URLs[$index]"
placeholder="e.g. 10.0.0.10:389 or myldap.domain.tld:389"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
/>
<button
ng-if="$index > 0"
class="btn btn-sm btn-danger"
type="button"
ng-click="$ctrl.removeLDAPUrl($index)"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
>
<pr-icon icon="'trash-2'" feather="true"></pr-icon>
</button>
<div>
<div class="col-sm-12 form-section-title"> Information </div>
<div class="form-group col-sm-12 text-muted small">
When using Microsoft AD authentication, Portainer will delegate user authentication to the Domain Controller(s) configured below; if there is no connectivity, Portainer
will fallback to internal authentication.
</div>
</div>
<div class="col-sm-12 form-section-title"> AD configuration </div>
<div class="form-group">
<div class="col-sm-12 small text-muted">
<p class="vertical-center">
<pr-icon icon="'info'" feather="true" mode="'primary'"></pr-icon>
You can configure multiple AD Controllers for authentication fallback. Make sure all servers are using the same configuration (i.e. if TLS is enabled, they should all
use the same certificates).
</p>
</div>
</div>
<div class="form-group">
<label for="ldap_url" class="col-sm-3 col-lg-2 control-label text-left" style="display: flex; flex-wrap: wrap">
AD Controller
<button
type="button"
class="label label-default interactive vertical-center"
style="border: 0"
ng-click="$ctrl.addLDAPUrl()"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
>
<pr-icon icon="'plus-circle'" feather="true"></pr-icon>
Add additional server
</button>
</label>
<div class="col-sm-9 col-lg-10">
<div ng-repeat="url in $ctrl.settings.URLs track by $index" style="display: flex; margin-bottom: 10px">
<input
type="text"
class="form-control"
id="ldap_url"
ng-model="$ctrl.settings.URLs[$index]"
placeholder="e.g. 10.0.0.10:389 or myldap.domain.tld:389"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
/>
<button
ng-if="$index > 0"
class="btn btn-sm btn-danger"
type="button"
ng-click="$ctrl.removeLDAPUrl($index)"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
>
<pr-icon icon="'trash-2'" feather="true"></pr-icon>
</button>
</div>
</div>
</div>
<div class="form-group">
<label for="ldap_username" class="col-sm-3 control-label text-left">
Service Account
<portainer-tooltip message="'Account that will be used to search for users.'"></portainer-tooltip>
</label>
<div class="col-sm-9">
<input
type="text"
class="form-control"
id="ldap_username"
ng-model="$ctrl.settings.ReaderDN"
placeholder="reader@domain.tld"
ng-change="$ctrl.onAccountChange($ctrl.settings.ReaderDN)"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
/>
</div>
</div>
<div class="form-group">
<label for="ldap_password" class="col-sm-3 control-label text-left">
Service Account Password
<portainer-tooltip message="'If you do not enter a password, Portainer will leave the current password unchanged.'"></portainer-tooltip>
</label>
<div class="col-sm-9">
<input
type="password"
class="form-control"
id="ldap_password"
ng-model="$ctrl.settings.Password"
placeholder="password"
autocomplete="new-password"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
/>
</div>
</div>
<ldap-connectivity-check
ng-if="!$ctrl.settings.TLSConfig.TLS && !$ctrl.settings.StartTLS"
settings="$ctrl.settings"
state="$ctrl.state"
connectivity-check="$ctrl.connectivityCheck"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-connectivity-check>
<ldap-settings-security
title="AD Connectivity Security"
settings="$ctrl.settings"
tlsca-cert="$ctrl.tlscaCert"
upload-in-progress="$ctrl.state.uploadInProgress"
on-tlsca-cert-change="($ctrl.onTlscaCertChange)"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-settings-security>
<ldap-connectivity-check
ng-if="$ctrl.settings.TLSConfig.TLS || $ctrl.settings.StartTLS"
settings="$ctrl.settings"
state="$ctrl.state"
connectivity-check="$ctrl.connectivityCheck"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-connectivity-check>
<ldap-user-search
style="margin-top: 5px"
show-username-format="true"
settings="$ctrl.settings.SearchSettings"
domain-suffix="{{ $ctrl.domainSuffix }}"
base-filter="(objectClass=user)"
on-search-click="($ctrl.searchUsers)"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-user-search>
<ldap-group-search
style="margin-top: 5px"
settings="$ctrl.settings.GroupSearchSettings"
domain-suffix="{{ $ctrl.domainSuffix }}"
base-filter="(objectClass=group)"
on-search-click="($ctrl.searchGroups)"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-group-search>
<ldap-custom-admin-group
style="margin-top: 5px"
settings="$ctrl.settings"
on-search-click="($ctrl.onSearchAdminGroupsClick)"
selected-admin-groups="$ctrl.selectedAdminGroups"
default-admin-group-search-filter="'(objectClass=groupOfNames)'"
limited-feature-id="$ctrl.limitedFeatureId"
is-limited-feature-self-contained="false"
></ldap-custom-admin-group>
<ldap-settings-test-login settings="$ctrl.settings" limited-feature-id="$ctrl.limitedFeatureId" is-limited-feature-self-contained="false"></ldap-settings-test-login>
<save-auth-settings-button
on-save-settings="($ctrl.onSaveSettings)"
save-button-state="($ctrl.saveButtonState)"
limited-feature-id="$ctrl.limitedFeatureId"
save-button-disabled="($ctrl.isSaveSettingButtonDisabled())"
></save-auth-settings-button>
</div>
</div>
<div class="form-group">
<label for="ldap_username" class="col-sm-3 control-label text-left">
Service Account
<portainer-tooltip message="'Account that will be used to search for users.'"></portainer-tooltip>
</label>
<div class="col-sm-9">
<input
type="text"
class="form-control"
id="ldap_username"
ng-model="$ctrl.settings.ReaderDN"
placeholder="reader@domain.tld"
ng-change="$ctrl.onAccountChange($ctrl.settings.ReaderDN)"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
/>
</div>
</div>
<div class="form-group">
<label for="ldap_password" class="col-sm-3 control-label text-left">
Service Account Password
<portainer-tooltip message="'If you do not enter a password, Portainer will leave the current password unchanged.'"></portainer-tooltip>
</label>
<div class="col-sm-9">
<input
type="password"
class="form-control"
id="ldap_password"
ng-model="$ctrl.settings.Password"
placeholder="password"
autocomplete="new-password"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
/>
</div>
</div>
<ldap-connectivity-check
ng-if="!$ctrl.settings.TLSConfig.TLS && !$ctrl.settings.StartTLS"
settings="$ctrl.settings"
state="$ctrl.state"
connectivity-check="$ctrl.connectivityCheck"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-connectivity-check>
<ldap-settings-security
title="AD Connectivity Security"
settings="$ctrl.settings"
tlsca-cert="$ctrl.tlscaCert"
upload-in-progress="$ctrl.state.uploadInProgress"
on-tlsca-cert-change="($ctrl.onTlscaCertChange)"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-settings-security>
<ldap-connectivity-check
ng-if="$ctrl.settings.TLSConfig.TLS || $ctrl.settings.StartTLS"
settings="$ctrl.settings"
state="$ctrl.state"
connectivity-check="$ctrl.connectivityCheck"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-connectivity-check>
<ldap-user-search
style="margin-top: 5px"
show-username-format="true"
settings="$ctrl.settings.SearchSettings"
domain-suffix="{{ $ctrl.domainSuffix }}"
base-filter="(objectClass=user)"
on-search-click="($ctrl.searchUsers)"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-user-search>
<ldap-group-search
style="margin-top: 5px"
settings="$ctrl.settings.GroupSearchSettings"
domain-suffix="{{ $ctrl.domainSuffix }}"
base-filter="(objectClass=group)"
on-search-click="($ctrl.searchGroups)"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-group-search>
<ldap-custom-admin-group
style="margin-top: 5px"
settings="$ctrl.settings"
on-search-click="($ctrl.onSearchAdminGroupsClick)"
selected-admin-groups="$ctrl.selectedAdminGroups"
default-admin-group-search-filter="'(objectClass=groupOfNames)'"
limited-feature-id="$ctrl.limitedFeatureId"
is-limited-feature-self-contained="false"
></ldap-custom-admin-group>
<ldap-settings-test-login settings="$ctrl.settings" limited-feature-id="$ctrl.limitedFeatureId" is-limited-feature-self-contained="false"></ldap-settings-test-login>
<save-auth-settings-button
on-save-settings="($ctrl.onSaveSettings)"
save-button-state="($ctrl.saveButtonState)"
limited-feature-id="$ctrl.limitedFeatureId"
save-button-disabled="($ctrl.isSaveSettingButtonDisabled())"
></save-auth-settings-button>
</ng-form>

View File

@ -1,184 +1,192 @@
<ng-form limited-feature-dir="{{::$ctrl.limitedFeatureId}}" limited-feature-class="limited-be" class="ldap-settings-openldap">
<be-feature-indicator feature="$ctrl.limitedFeatureId"></be-feature-indicator>
<div>
<div class="col-sm-12 form-section-title"> Information </div>
<div class="form-group col-sm-12 text-muted small">
When using LDAP authentication, Portainer will delegate user authentication to a LDAP server and fallback to internal authentication if LDAP authentication fails.
</div>
</div>
<div class="col-sm-12 form-section-title"> LDAP configuration </div>
<div class="form-group">
<div class="col-sm-12 small text-muted">
<p class="vertical-center">
<pr-icon icon="'info'" feather="true" mode="'primary'"></pr-icon>
You can configure multiple LDAP Servers for authentication fallback. Make sure all servers are using the same configuration (i.e. if TLS is enabled, they should all use the
same certificates).
</p>
</div>
</div>
<div class="form-group">
<label for="ldap_url" class="col-sm-3 col-lg-2 control-label text-left" style="display: flex; flex-wrap: wrap">
LDAP Server
<button
type="button"
class="label label-default interactive vertical-center"
style="border: 0"
ng-click="$ctrl.addLDAPUrl()"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
>
<pr-icon icon="'plus-circle'" feather="true"></pr-icon>
Add additional server
</button>
</label>
<div class="col-sm-9 col-lg-10">
<div ng-repeat="url in $ctrl.settings.URLs track by $index" style="display: flex; margin-bottom: 10px">
<input
type="text"
class="form-control"
id="ldap_url"
ng-model="$ctrl.settings.URLs[$index]"
placeholder="e.g. 10.0.0.10:389 or myldap.domain.tld:389"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
/>
<button
ng-if="$index > 0"
class="btn btn-sm btn-danger"
type="button"
ng-click="$ctrl.removeLDAPUrl($index)"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
>
<pr-icon icon="'trash-2'" feather="true" size="'md'"></pr-icon>
</button>
<div class="overlay">
<div class="limited-be-link vertical-center"
><be-feature-indicator feature="$ctrl.limitedFeatureId"></be-feature-indicator
><portainer-tooltip message="'This feature is currently limited to Business Edition users only. '"></portainer-tooltip
></div>
<div class="limited-be-content">
<div>
<div class="col-sm-12 form-section-title"> Information </div>
<div class="form-group col-sm-12 text-muted small">
When using LDAP authentication, Portainer will delegate user authentication to a LDAP server and fallback to internal authentication if LDAP authentication fails.
</div>
</div>
</div>
</div>
<!-- Anonymous mode-->
<div class="form-group">
<label for="anonymous_mode" class="control-label text-left col-sm-3 col-lg-2">
Anonymous mode
<portainer-tooltip message="'Enable this option if the server is configured for Anonymous access.'"></portainer-tooltip>
</label>
<div class="col-sm-12 form-section-title"> LDAP configuration </div>
<div class="col-sm-9 col-lg-10">
<label class="switch">
<input type="checkbox" id="anonymous_mode" ng-model="$ctrl.settings.AnonymousMode" limited-feature-dir="{{::$ctrl.limitedFeatureId}}" limited-feature-tabindex="-1" />
<span class="slider round"></span>
</label>
</div>
</div>
<!-- !Anonymous mode-->
<div ng-if="!$ctrl.settings.AnonymousMode">
<div class="form-group">
<label for="ldap_username" class="col-sm-3 col-lg-2 control-label text-left">
Reader DN
<portainer-tooltip message="'Account that will be used to search for users.'"></portainer-tooltip>
</label>
<div class="col-sm-9 col-lg-10">
<input
type="text"
class="form-control"
id="ldap_username"
ng-model="$ctrl.settings.ReaderDN"
placeholder="cn=user,dc=domain,dc=tld"
ng-change="$ctrl.onAccountChange($ctrl.settings.ReaderDN)"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
/>
<div class="form-group">
<div class="col-sm-12 small text-muted">
<p class="vertical-center">
<pr-icon icon="'info'" feather="true" mode="'primary'"></pr-icon>
You can configure multiple LDAP Servers for authentication fallback. Make sure all servers are using the same configuration (i.e. if TLS is enabled, they should all use
the same certificates).
</p>
</div>
</div>
</div>
<div class="form-group">
<label for="ldap_password" class="col-sm-3 col-lg-2 control-label text-left">
Password
<portainer-tooltip message="'If you do not enter a password, Portainer will leave the current password unchanged.'"></portainer-tooltip>
</label>
<div class="col-sm-9">
<input
type="password"
class="form-control"
id="ldap_password"
ng-model="$ctrl.settings.Password"
placeholder="password"
autocomplete="new-password"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
/>
<div class="form-group">
<label for="ldap_url" class="col-sm-3 col-lg-2 control-label text-left" style="display: flex; flex-wrap: wrap">
LDAP Server
<button
type="button"
class="label label-default interactive vertical-center"
style="border: 0"
ng-click="$ctrl.addLDAPUrl()"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
>
<pr-icon icon="'plus-circle'" feather="true"></pr-icon>
Add additional server
</button>
</label>
<div class="col-sm-9 col-lg-10">
<div ng-repeat="url in $ctrl.settings.URLs track by $index" style="display: flex; margin-bottom: 10px">
<input
type="text"
class="form-control"
id="ldap_url"
ng-model="$ctrl.settings.URLs[$index]"
placeholder="e.g. 10.0.0.10:389 or myldap.domain.tld:389"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
/>
<button
ng-if="$index > 0"
class="btn btn-sm btn-danger"
type="button"
ng-click="$ctrl.removeLDAPUrl($index)"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
>
<pr-icon icon="'trash-2'" feather="true" size="'md'"></pr-icon>
</button>
</div>
</div>
</div>
<!-- Anonymous mode-->
<div class="form-group">
<div class="col-sm-12">
<label for="anonymous_mode" class="control-label text-left col-sm-3 col-lg-2">
Anonymous mode
<portainer-tooltip message="'Enable this option if the server is configured for Anonymous access.'"></portainer-tooltip>
</label>
<div class="col-sm-9 col-lg-10">
<label class="switch">
<input type="checkbox" id="anonymous_mode" ng-model="$ctrl.settings.AnonymousMode" limited-feature-dir="{{::$ctrl.limitedFeatureId}}" limited-feature-tabindex="-1" />
<span class="slider round"></span>
</label>
</div>
</div>
</div>
<!-- !Anonymous mode-->
<div ng-if="!$ctrl.settings.AnonymousMode">
<div class="form-group">
<label for="ldap_username" class="col-sm-3 col-lg-2 control-label text-left">
Reader DN
<portainer-tooltip message="'Account that will be used to search for users.'"></portainer-tooltip>
</label>
<div class="col-sm-9 col-lg-10">
<input
type="text"
class="form-control"
id="ldap_username"
ng-model="$ctrl.settings.ReaderDN"
placeholder="cn=user,dc=domain,dc=tld"
ng-change="$ctrl.onAccountChange($ctrl.settings.ReaderDN)"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
/>
</div>
</div>
<div class="form-group">
<label for="ldap_password" class="col-sm-3 col-lg-2 control-label text-left">
Password
<portainer-tooltip message="'If you do not enter a password, Portainer will leave the current password unchanged.'"></portainer-tooltip>
</label>
<div class="col-sm-9">
<input
type="password"
class="form-control"
id="ldap_password"
ng-model="$ctrl.settings.Password"
placeholder="password"
autocomplete="new-password"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
/>
</div>
</div>
</div>
<div class="form-group" ng-if="$ctrl.settings.AnonymousMode">
<label for="ldap_domain_root" class="col-sm-3 col-lg-2 control-label text-left"> Domain root </label>
<div class="col-sm-9">
<input
type="text"
class="form-control"
id="ldap_domain_root"
ng-model="$ctrl.domainSuffix"
placeholder="dc=domain,dc=tld"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
/>
</div>
</div>
<ldap-connectivity-check
ng-if="!$ctrl.settings.TLSConfig.TLS && !$ctrl.settings.StartTLS"
settings="$ctrl.settings"
state="$ctrl.state"
connectivity-check="$ctrl.connectivityCheck"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-connectivity-check>
<ldap-settings-security
title="Connectivity Security"
settings="$ctrl.settings"
tlsca-cert="$ctrl.tlscaCert"
upload-in-progress="$ctrl.state.uploadInProgress"
on-tlsca-cert-change="($ctrl.onTlscaCertChange)"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-settings-security>
<ldap-connectivity-check
ng-if="$ctrl.settings.TLSConfig.TLS || $ctrl.settings.StartTLS"
settings="$ctrl.settings"
state="$ctrl.state"
connectivity-check="$ctrl.connectivityCheck"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-connectivity-check>
<ldap-user-search
style="margin-top: 5px"
settings="$ctrl.settings.SearchSettings"
domain-suffix="{{ $ctrl.domainSuffix }}"
base-filter="(objectClass=inetOrgPerson)"
on-search-click="($ctrl.onSearchUsersClick)"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-user-search>
<ldap-group-search
style="margin-top: 5px"
settings="$ctrl.settings.GroupSearchSettings"
domain-suffix="{{ $ctrl.domainSuffix }}"
base-filter="(objectClass=groupOfNames)"
on-search-click="($ctrl.onSearchGroupsClick)"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-group-search>
<ldap-settings-test-login settings="$ctrl.settings" limited-feature-id="$ctrl.limitedFeatureId"></ldap-settings-test-login>
<save-auth-settings-button
on-save-settings="($ctrl.onSaveSettings)"
save-button-state="($ctrl.saveButtonState)"
save-button-disabled="!$ctrl.saveButtonDisabled()"
limited-feature-id="$ctrl.limitedFeatureId"
></save-auth-settings-button>
</div>
</div>
<div class="form-group" ng-if="$ctrl.settings.AnonymousMode">
<label for="ldap_domain_root" class="col-sm-3 col-lg-2 control-label text-left"> Domain root </label>
<div class="col-sm-9">
<input
type="text"
class="form-control"
id="ldap_domain_root"
ng-model="$ctrl.domainSuffix"
placeholder="dc=domain,dc=tld"
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
limited-feature-tabindex="-1"
/>
</div>
</div>
<ldap-connectivity-check
ng-if="!$ctrl.settings.TLSConfig.TLS && !$ctrl.settings.StartTLS"
settings="$ctrl.settings"
state="$ctrl.state"
connectivity-check="$ctrl.connectivityCheck"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-connectivity-check>
<ldap-settings-security
title="Connectivity Security"
settings="$ctrl.settings"
tlsca-cert="$ctrl.tlscaCert"
upload-in-progress="$ctrl.state.uploadInProgress"
on-tlsca-cert-change="($ctrl.onTlscaCertChange)"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-settings-security>
<ldap-connectivity-check
ng-if="$ctrl.settings.TLSConfig.TLS || $ctrl.settings.StartTLS"
settings="$ctrl.settings"
state="$ctrl.state"
connectivity-check="$ctrl.connectivityCheck"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-connectivity-check>
<ldap-user-search
style="margin-top: 5px"
settings="$ctrl.settings.SearchSettings"
domain-suffix="{{ $ctrl.domainSuffix }}"
base-filter="(objectClass=inetOrgPerson)"
on-search-click="($ctrl.onSearchUsersClick)"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-user-search>
<ldap-group-search
style="margin-top: 5px"
settings="$ctrl.settings.GroupSearchSettings"
domain-suffix="{{ $ctrl.domainSuffix }}"
base-filter="(objectClass=groupOfNames)"
on-search-click="($ctrl.onSearchGroupsClick)"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-group-search>
<ldap-settings-test-login settings="$ctrl.settings" limited-feature-id="$ctrl.limitedFeatureId"></ldap-settings-test-login>
<save-auth-settings-button
on-save-settings="($ctrl.onSaveSettings)"
save-button-state="($ctrl.saveButtonState)"
save-button-disabled="!$ctrl.saveButtonDisabled()"
limited-feature-id="$ctrl.limitedFeatureId"
></save-auth-settings-button>
</ng-form>

View File

@ -1,46 +1,61 @@
<page-header title="'User Activity'" breadcrumbs="['Activity Logs']" reload="true"> </page-header>
<div class="be-indicator-container">
<rd-widget>
<rd-widget-body>
<div class="form-horizontal">
<div class="form-group">
<label for="dateRangeInput" class="col-sm-2 control-label text-left">Date Range</label>
<div class="col-sm-6">
<input type="text" class="form-control" disabled />
<div class="be-indicator-container limited-be">
<div class="overlay">
<div class="limited-be-link vertical-center"
><be-feature-indicator feature="$ctrl.limitedFeature"></be-feature-indicator
><portainer-tooltip message="'This feature is currently limited to Business Edition users only. '"></portainer-tooltip
></div>
<div class="limited-be-content">
<rd-widget>
<rd-widget-body>
<div class="form-horizontal">
<div class="form-group">
<label for="dateRangeInput" class="col-sm-2 control-label text-left">Date Range</label>
<div class="col-sm-6">
<input type="text" class="form-control" disabled />
</div>
</div>
</div>
</div>
</div>
<p class="text-muted small vertical-center">
<pr-icon icon="'info'" feather="true" class-name="'icon icon-sm icon-primary'"></pr-icon>
Portainer user activity logs have a maximum retention of 7 days.
</p>
<div>
<button type="button" class="btn btn-sm btn-primary" limited-feature-dir="{{::$ctrl.limitedFeature}}" limited-feature-class="limited-be" limited-feature-disabled>
<pr-icon icon="'download'" feather="true" icon-class="'icon icon-sm'"></pr-icon>
Export as CSV
</button>
<be-feature-indicator feature="$ctrl.limitedFeature"></be-feature-indicator>
</div>
</rd-widget-body>
</rd-widget>
</div>
<div class="be-indicator-container">
<div class="row">
<activity-logs-datatable
logs="$ctrl.state.logs"
keyword="$ctrl.state.keyword"
sort="$ctrl.state.sort"
limit="$ctrl.state.limit"
context-filter="$ctrl.state.contextFilter"
total-items="$ctrl.state.totalItems"
current-page="$ctrl.state.currentPage"
feature="{{:: $ctrl.limitedFeature}}"
on-change-keyword="($ctrl.onChangeKeyword)"
on-change-sort="($ctrl.onChangeSort)"
on-change-limit="($ctrl.onChangeLimit)"
on-change-page="($ctrl.onChangePage)"
></activity-logs-datatable>
<p class="text-muted small vertical-center">
<pr-icon icon="'info'" feather="true" class-name="'icon icon-sm icon-primary'"></pr-icon>
Portainer user activity logs have a maximum retention of 7 days.
</p>
<div>
<button type="button" class="btn btn-sm btn-primary" limited-feature-dir="{{::$ctrl.limitedFeature}}" limited-feature-class="limited-be" limited-feature-disabled>
<pr-icon icon="'download'" feather="true" icon-class="'icon icon-sm'"></pr-icon>
Export as CSV
</button>
</div>
</rd-widget-body>
</rd-widget>
</div>
</div>
</div>
<div class="be-indicator-container limited-be">
<div class="overlay">
<div class="limited-be-link vertical-center"
><be-feature-indicator feature="$ctrl.limitedFeature"></be-feature-indicator
><portainer-tooltip message="'This feature is currently limited to Business Edition users only. '"></portainer-tooltip
></div>
<div class="limited-be-content">
<div class="row">
<activity-logs-datatable
logs="$ctrl.state.logs"
keyword="$ctrl.state.keyword"
sort="$ctrl.state.sort"
limit="$ctrl.state.limit"
context-filter="$ctrl.state.contextFilter"
total-items="$ctrl.state.totalItems"
current-page="$ctrl.state.currentPage"
feature="{{:: $ctrl.limitedFeature}}"
on-change-keyword="($ctrl.onChangeKeyword)"
on-change-sort="($ctrl.onChangeSort)"
on-change-limit="($ctrl.onChangeLimit)"
on-change-page="($ctrl.onChangePage)"
></activity-logs-datatable>
</div>
</div>
</div>
</div>

View File

@ -11,7 +11,7 @@
<be-feature-indicator feature="{{::$ctrl.feature}}"></be-feature-indicator>
</div>
<div class="vertical-center">
<datatable-searchbar on-change="($ctrl.onChangeKeyword)" value="$ctrl.keyword"></datatable-searchbar>
<datatable-searchbar on-change="($ctrl.onChangeKeyword)"></datatable-searchbar>
</div>
</div>
<div class="table-responsive">

View File

@ -1,48 +1,63 @@
<page-header title="'User Activity'" breadcrumbs="['User authentication activity']" reload="true"> </page-header>
<div class="be-indicator-container">
<rd-widget>
<rd-widget-body>
<div class="form-horizontal">
<div class="form-group">
<label for="dateRangeInput" class="col-sm-2 control-label text-left">Date Range</label>
<div class="col-sm-6">
<input type="text" class="form-control" disabled />
<div class="be-indicator-container limited-be">
<div class="overlay">
<div class="limited-be-link vertical-center"
><be-feature-indicator feature="$ctrl.limitedFeature"></be-feature-indicator
><portainer-tooltip message="'This feature is currently limited to Business Edition users only. '"></portainer-tooltip
></div>
<div class="limited-be-content">
<rd-widget>
<rd-widget-body>
<div class="form-horizontal">
<div class="form-group">
<label for="dateRangeInput" class="col-sm-2 control-label text-left">Date Range</label>
<div class="col-sm-6">
<input type="text" class="form-control" disabled />
</div>
</div>
</div>
</div>
</div>
<p class="text-muted small vertical-center">
<pr-icon icon="'info'" feather="true" class-name="'icon icon-sm icon-primary'"></pr-icon>
Portainer user authentication activity logs have a maximum retention of 7 days.
</p>
<div>
<button type="button" class="btn btn-sm btn-primary" limited-feature-dir="{{::$ctrl.limitedFeature}}" limited-feature-class="limited-be" limited-feature-disabled
><pr-icon icon="'download'" feather="true" icon-class="'icon icon-sm'"></pr-icon>Export as CSV
</button>
<be-feature-indicator feature="$ctrl.limitedFeature"></be-feature-indicator>
</div>
</rd-widget-body>
</rd-widget>
</div>
<div class="be-indicator-container">
<div class="row">
<auth-logs-datatable
logs="$ctrl.state.logs"
keyword="$ctrl.state.keyword"
sort="$ctrl.state.sort"
limit="$ctrl.state.limit"
context-filter="$ctrl.state.contextFilter"
type-filter="$ctrl.state.typeFilter"
total-items="$ctrl.state.totalItems"
current-page="$ctrl.state.currentPage"
feature="{{:: $ctrl.limitedFeature}}"
on-change-context-filter="($ctrl.onChangeContextFilter)"
on-change-type-filter="($ctrl.onChangeTypeFilter)"
on-change-keyword="($ctrl.onChangeKeyword)"
on-change-sort="($ctrl.onChangeSort)"
on-change-limit="($ctrl.onChangeLimit)"
on-change-page="($ctrl.onChangePage)"
></auth-logs-datatable>
<p class="text-muted small vertical-center">
<pr-icon icon="'info'" feather="true" class-name="'icon icon-sm icon-primary'"></pr-icon>
Portainer user authentication activity logs have a maximum retention of 7 days.
</p>
<div>
<button type="button" class="btn btn-sm btn-primary" limited-feature-dir="{{::$ctrl.limitedFeature}}" limited-feature-class="limited-be" limited-feature-disabled
><pr-icon icon="'download'" feather="true" icon-class="'icon icon-sm'"></pr-icon>Export as CSV
</button>
</div>
</rd-widget-body>
</rd-widget>
</div>
</div>
</div>
<div class="be-indicator-container limited-be">
<div class="overlay">
<div class="limited-be-link vertical-center"
><be-feature-indicator feature="$ctrl.limitedFeature"></be-feature-indicator
><portainer-tooltip message="'This feature is currently limited to Business Edition users only. '"></portainer-tooltip
></div>
<div class="limited-be-content">
<div class="row">
<auth-logs-datatable
logs="$ctrl.state.logs"
keyword="$ctrl.state.keyword"
sort="$ctrl.state.sort"
limit="$ctrl.state.limit"
context-filter="$ctrl.state.contextFilter"
type-filter="$ctrl.state.typeFilter"
total-items="$ctrl.state.totalItems"
current-page="$ctrl.state.currentPage"
feature="{{:: $ctrl.limitedFeature}}"
on-change-context-filter="($ctrl.onChangeContextFilter)"
on-change-type-filter="($ctrl.onChangeTypeFilter)"
on-change-keyword="($ctrl.onChangeKeyword)"
on-change-sort="($ctrl.onChangeSort)"
on-change-limit="($ctrl.onChangeLimit)"
on-change-page="($ctrl.onChangePage)"
></auth-logs-datatable>
</div>
</div>
</div>
</div>

View File

@ -1,5 +1,6 @@
import { PropsWithChildren } from 'react';
import clsx from 'clsx';
import { Briefcase } from 'react-feather';
import './BEFeatureIndicator.css';
@ -24,19 +25,16 @@ export function BEFeatureIndicator({
if (!limitedToBE) {
return null;
}
return (
<a
className={clsx('be-indicator', className)}
className={clsx('be-indicator vertical-center', className)}
href={url}
target="_blank"
rel="noopener noreferrer"
>
{children}
{showIcon && (
<i className="fas fa-briefcase space-right be-indicator-icon" />
)}
<span className="be-indicator-label break-words">
{showIcon && <Briefcase className="icon icon-sm vertical-center" />}
<span className="be-indicator-label break-words space-left">
Business Edition Feature
</span>
</a>