* Initial extension build * Add auto login fix auto auth add some message Add extension version Double attempt to login Add auto login from jwt check Add autologin on logout revert sidebar Catch error 401 to relogin cleanup login Add password generator Hide User block and collapse sidebar by default hide user box and toggle sidebar remove defailt dd Integrate extension to portainer Move extension to build remove files from ignore Move extension folder fix alpine try to copy folder try add Change base image move folder extension ignore folder build Fix relative path Move ext to root fix image name versioned index Update extension on same image Update mod * fix kubeshell baseurl * Fix kube shell * move build and remove https * Tidy mod * Remove space * Fix hash test * Password manager * change to building locally * Restore version variable and add local install command * fix local dev image + hide users & auth * Password manageListen on locahost onlyr * FIxes base path * Hide only username * Move default to constants * Update app/portainer/components/PageHeader/HeaderContent.html Co-authored-by: Chaim Lev-Ari <chiptus@users.noreply.github.com> * fix 2 failing FE tests [EE-2938] * remove password autogeneration from v1 * fix webhooks * fix docker container console and attach * fix default for portainer IP * update meta, dockerfile and makefile for new ver * fix basepath in kube and docker console * revert makefile changes * add icon back * Add remote short cut command * make local methods the default * default to 0.0.0 for version for local development * simplify make commands * small build fixes * resolve conflicts * Update api/filesystem/write.go Co-authored-by: Chaim Lev-Ari <chiptus@users.noreply.github.com> * use a more secure default pass Co-authored-by: itsconquest <william.conquest@portainer.io> Co-authored-by: Chaim Lev-Ari <chiptus@users.noreply.github.com>
426 lines
19 KiB
HTML
426 lines
19 KiB
HTML
<rd-header>
|
|
<rd-header-title title-text="Settings"></rd-header-title>
|
|
<rd-header-content>Settings</rd-header-content>
|
|
</rd-header>
|
|
|
|
<div class="row">
|
|
<div class="col-sm-12">
|
|
<rd-widget>
|
|
<rd-widget-header icon="fa-cogs" title-text="Application settings"></rd-widget-header>
|
|
<rd-widget-body>
|
|
<form class="form-horizontal">
|
|
<!-- snapshot-interval -->
|
|
<div class="form-group">
|
|
<label for="snapshot_interval" class="col-sm-2 control-label text-left">Snapshot interval</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" ng-model="settings.SnapshotInterval" id="snapshot_interval" placeholder="e.g. 15m" />
|
|
</div>
|
|
</div>
|
|
<!-- !snapshot-interval -->
|
|
<!-- logo -->
|
|
<div class="form-group">
|
|
<div class="col-sm-12">
|
|
<label for="toggle_logo" class="control-label text-left"> Use custom logo </label>
|
|
<label class="switch" style="margin-left: 20px">
|
|
<input type="checkbox" name="toggle_logo" ng-model="formValues.customLogo" />
|
|
<i></i>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div ng-if="formValues.customLogo">
|
|
<div class="form-group">
|
|
<span class="col-sm-12 text-muted small"> You can specify the URL to your logo here. For an optimal display, logo dimensions should be 155px by 55px. </span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="logo_url" class="col-sm-1 control-label text-left"> URL </label>
|
|
<div class="col-sm-11">
|
|
<input type="text" class="form-control" ng-model="settings.LogoURL" id="logo_url" placeholder="https://mycompany.com/logo.png" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- !logo -->
|
|
<!-- analytics -->
|
|
<div class="form-group">
|
|
<div class="col-sm-12">
|
|
<label for="toggle_enableTelemetry" class="control-label text-left"> Allow the collection of anonymous statistics </label>
|
|
<label class="switch" style="margin-left: 20px">
|
|
<input type="checkbox" name="toggle_enableTelemetry" ng-model="formValues.enableTelemetry" />
|
|
<i></i>
|
|
</label>
|
|
</div>
|
|
<div class="col-sm-12 text-muted small" style="margin-top: 10px">
|
|
You can find more information about this in our
|
|
<a href="https://www.portainer.io/documentation/in-app-analytics-and-privacy-policy/" target="_blank">privacy policy</a>.
|
|
</div>
|
|
</div>
|
|
<!-- !analytics -->
|
|
<!-- templates -->
|
|
<div class="col-sm-12 form-section-title"> App Templates </div>
|
|
<div>
|
|
<div class="form-group">
|
|
<span class="col-sm-12 text-muted small">
|
|
You can specify the URL to your own template definitions file here. See
|
|
<a href="https://documentation.portainer.io/v2.0/settings/apps/#build-and-host-your-own-templates" target="_blank">Portainer documentation</a> for more details.
|
|
</span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="templates_url" class="col-sm-1 control-label text-left"> URL </label>
|
|
<div class="col-sm-11">
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
ng-model="settings.TemplatesURL"
|
|
id="templates_url"
|
|
placeholder="https://myserver.mydomain/templates.json"
|
|
required
|
|
data-cy="settings-templateUrl"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- !templates -->
|
|
<!-- helm charts -->
|
|
<div class="col-sm-12 form-section-title"> Helm Repository </div>
|
|
<div>
|
|
<div class="form-group">
|
|
<span class="col-sm-12 text-muted small">
|
|
You can specify the URL to your own helm repository here. See the
|
|
<a href="https://helm.sh/docs/topics/chart_repository/" target="_blank">official documentation</a> for more details.
|
|
</span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="helmrepository_url" class="col-sm-1 control-label text-left"> URL </label>
|
|
<div class="col-sm-11">
|
|
<input type="text" class="form-control" ng-model="settings.HelmRepositoryURL" id="helmrepository_url" placeholder="https://charts.bitnami.com/bitnami" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- !helm charts -->
|
|
<!-- host-filesystem -->
|
|
<!-- kube -->
|
|
<div class="col-sm-12 form-section-title"> Kubernetes </div>
|
|
<div class="form-group">
|
|
<label for="kubeconfig_expiry" class="col-sm-2 control-label text-left"> Kubeconfig expiry </label>
|
|
<div class="col-sm-10">
|
|
<select
|
|
id="kubeconfig_expiry"
|
|
class="form-control"
|
|
ng-model="settings.KubeconfigExpiry"
|
|
ng-options="opt.value as opt.key for opt in state.availableKubeconfigExpiryOptions"
|
|
></select>
|
|
</div>
|
|
</div>
|
|
<!-- ! kube -->
|
|
<!-- actions -->
|
|
<div class="form-group">
|
|
<div class="col-sm-12">
|
|
<button
|
|
type="button"
|
|
class="btn btn-primary btn-sm"
|
|
ng-click="saveApplicationSettings()"
|
|
ng-disabled="state.actionInProgress || !settings.TemplatesURL"
|
|
button-spinner="state.actionInProgress"
|
|
data-cy="settings-saveSettingsButton"
|
|
>
|
|
<span ng-hide="state.actionInProgress">Save settings</span>
|
|
<span ng-show="state.actionInProgress">Saving...</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<!-- !actions -->
|
|
</form>
|
|
</rd-widget-body>
|
|
</rd-widget>
|
|
</div>
|
|
</div>
|
|
|
|
<ssl-certificate-settings ng-show="$ctrl.showHTTPS"></ssl-certificate-settings>
|
|
|
|
<div class="row">
|
|
<div class="col-sm-12">
|
|
<rd-widget>
|
|
<rd-widget-header icon="fa-tags" title-text="Hidden containers"></rd-widget-header>
|
|
<rd-widget-body>
|
|
<form class="form-horizontal" ng-submit="addFilteredContainerLabel()" name="addTagForm">
|
|
<div class="form-group">
|
|
<span class="col-sm-12 text-muted small"> You can hide containers with specific labels from Portainer UI. You need to specify the label name and value. </span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="header_name" class="col-sm-1 control-label text-left">Name</label>
|
|
<div class="col-sm-11 col-md-4">
|
|
<input type="text" required class="form-control" id="header_name" name="label_name" ng-model="formValues.labelName" placeholder="e.g. com.example.foo" />
|
|
</div>
|
|
<label for="header_value" class="col-sm-1 margin-sm-top control-label text-left">Value</label>
|
|
<div class="col-sm-11 col-md-4 margin-sm-top">
|
|
<input type="text" class="form-control" id="header_value" ng-model="formValues.labelValue" placeholder="e.g. bar" />
|
|
</div>
|
|
<div class="col-sm-12 col-md-2 margin-sm-top">
|
|
<button type="submit" class="btn btn-primary btn-sm" ng-disabled="!formValues.labelName"> <i class="fa fa-plus space-right" aria-hidden="true"></i>Add filter</button>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<div class="col-sm-12 table-responsive">
|
|
<table class="table table-hover">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Value</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr ng-repeat="label in settings.BlackListedLabels">
|
|
<td>{{ label.name }}</td>
|
|
<td>{{ label.value }}</td>
|
|
<td>
|
|
<button type="button" class="btn btn-danger btn-xs" ng-click="removeFilteredContainerLabel($index)">
|
|
<i class="fa fa-trash-alt space-right" aria-hidden="true"></i>Remove</button
|
|
>
|
|
</td>
|
|
</tr>
|
|
<tr ng-if="settings.BlackListedLabels.length === 0">
|
|
<td colspan="3" class="text-center text-muted">No filter available.</td>
|
|
</tr>
|
|
<tr ng-if="!settings.BlackListedLabels">
|
|
<td colspan="3" class="text-center text-muted">Loading...</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<!-- !filtered-labels -->
|
|
</form>
|
|
</rd-widget-body>
|
|
</rd-widget>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-sm-12">
|
|
<rd-widget>
|
|
<rd-widget-header icon="fa-download" title-text="Backup Portainer"></rd-widget-header>
|
|
<rd-widget-body>
|
|
<form class="form-horizontal" ng-submit="backupPortainer()" name="backupPortainerForm">
|
|
<div class="col-sm-12 form-section-title"> Backup configuration </div>
|
|
<box-selector options="backupOptions" value="formValues.backupFormType" on-change="(onBackupOptionsChange)" radio-name="'backupOptions'"></box-selector>
|
|
<div ng-if="formValues.backupFormType === BACKUP_FORM_TYPES.S3">
|
|
<!-- Schedule automatic backups -->
|
|
<div class="form-group">
|
|
<div class="col-sm-12">
|
|
<por-switch-field
|
|
label="'Schedule automatic backups'"
|
|
name="'s3-backup-setting'"
|
|
feature-id="s3BackupFeatureId"
|
|
checked="formValues.scheduleAutomaticBackups"
|
|
label-class="'col-sm-2'"
|
|
on-change="(onToggleAutoBackups)"
|
|
></por-switch-field>
|
|
</div>
|
|
</div>
|
|
<!-- !Schedule automatic backups -->
|
|
<!-- Cron rule -->
|
|
<div class="form-group" ng-if="formValues.scheduleAutomaticBackups">
|
|
<label for="cron_rule" class="col-sm-2 col-lg-2 control-label text-left">Cron rule</label>
|
|
<div class="col-sm-10 col-lg-10">
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
placeholder="0 2 * * *"
|
|
id="cron_rule"
|
|
name="cron_rule"
|
|
ng-model="formValues.cronRule"
|
|
limited-feature-dir="{{::s3BackupFeatureId}}"
|
|
limited-feature-disabled
|
|
limited-feature-class="limited-be"
|
|
required
|
|
cronRule
|
|
/>
|
|
</div>
|
|
</div>
|
|
<!-- !Cron rule -->
|
|
<!-- Access key id -->
|
|
<div class="form-group">
|
|
<label for="access_key_id" class="col-sm-2 col-lg-2 control-label text-left">Access Key ID</label>
|
|
<div class="col-sm-9 col-lg-10">
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="access_key_id"
|
|
name="access_key_id"
|
|
ng-model="formValues.accessKeyId"
|
|
ng-required="formValues.scheduleAutomaticBackups"
|
|
limited-feature-dir="{{::s3BackupFeatureId}}"
|
|
limited-feature-disabled
|
|
limited-feature-class="limited-be"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<!-- !Access key id -->
|
|
<!-- Secret access key -->
|
|
<div class="form-group">
|
|
<label for="secret_access_key" class="col-sm-3 col-lg-2 control-label text-left">Secret Access Key</label>
|
|
<div class="col-sm-9 col-lg-10">
|
|
<input
|
|
type="password"
|
|
class="form-control"
|
|
id="secret_access_key"
|
|
name="secret_access_key"
|
|
ng-model="formValues.secretAccessKey"
|
|
ng-required="formValues.scheduleAutomaticBackups"
|
|
limited-feature-dir="{{::s3BackupFeatureId}}"
|
|
limited-feature-disabled
|
|
limited-feature-class="limited-be"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<!-- !Secret access key -->
|
|
<!-- Region -->
|
|
<div class="form-group">
|
|
<label for="region" class="col-sm-3 col-lg-2 control-label text-left">Region</label>
|
|
<div class="col-sm-9 col-lg-10">
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
placeholder="us-west-1"
|
|
id="region"
|
|
name="region"
|
|
ng-model="formValues.region"
|
|
ng-required="formValues.scheduleAutomaticBackups"
|
|
limited-feature-dir="{{::s3BackupFeatureId}}"
|
|
limited-feature-disabled
|
|
limited-feature-class="limited-be"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<!-- !Region -->
|
|
<!-- Bucket name -->
|
|
<div class="form-group">
|
|
<label for="bucket_name" class="col-sm-3 col-lg-2 control-label text-left">Bucket name</label>
|
|
<div class="col-sm-9 col-lg-10">
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="bucket_name"
|
|
name="bucket_name"
|
|
ng-model="formValues.bucketName"
|
|
ng-required="formValues.scheduleAutomaticBackups"
|
|
limited-feature-dir="{{::s3BackupFeatureId}}"
|
|
limited-feature-disabled
|
|
limited-feature-class="limited-be"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<!-- !Bucket name -->
|
|
<div class="col-sm-12 form-section-title"> Security settings </div>
|
|
<!-- Password protect S3 -->
|
|
<div class="form-group">
|
|
<label for="password_protect" class="col-sm-1 control-label text-left">Password protect</label>
|
|
<div class="col-sm-1">
|
|
<label class="switch" data-cy="settings-s3PasswordToggle">
|
|
<input type="checkbox" id="password_protect_s3" name="password_protect_s3" ng-model="formValues.passwordProtectS3" disabled />
|
|
<i></i>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<!-- !Password protect S3 -->
|
|
<!-- Password S3 -->
|
|
<div class="form-group" ng-if="formValues.passwordProtectS3">
|
|
<label for="password" class="col-sm-1 control-label text-left">Password</label>
|
|
<div class="col-sm-3">
|
|
<input type="password" class="form-control" ng-model="formValues.passwordS3" id="password_S3" name="password_S3" required data-cy="settings-backups3pw" />
|
|
</div>
|
|
</div>
|
|
<div class="form-group col-md-12" ng-show="backupPortainerForm.password_S3.$invalid">
|
|
<div class="small text-warning">
|
|
<div ng-messages="backupPortainerForm.password_S3.$error">
|
|
<p ng-message="required"> <i class="fa fa-exclamation-triangle" aria-hidden="true"></i> This field is required.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- !Password S3 -->
|
|
<div class="form-group">
|
|
<div class="col-sm-12">
|
|
<button
|
|
type="button"
|
|
class="btn btn-primary btn-sm"
|
|
ng-disabled="backupPortainerForm.$invalid"
|
|
ng-click="exportBackup()"
|
|
limited-feature-dir="{{::s3BackupFeatureId}}"
|
|
limited-feature-disabled
|
|
limited-feature-class="limited-be"
|
|
>
|
|
<span> <i class="fa fa-upload" aria-hidden="true"></i> Export backup</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<hr />
|
|
<div class="col-sm-12">
|
|
<button
|
|
type="submit"
|
|
class="btn btn-primary btn-sm"
|
|
ng-disabled="backupPortainerForm.$invalid ||state.backupInProgress"
|
|
ng-click="saveS3BackupSettings()"
|
|
limited-feature-dir="{{::s3BackupFeatureId}}"
|
|
limited-feature-disabled
|
|
limited-feature-class="limited-be"
|
|
>
|
|
<span>Save backup settings</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div ng-if="formValues.backupFormType === BACKUP_FORM_TYPES.FILE">
|
|
<div class="col-sm-12 form-section-title"> Security settings </div>
|
|
<!-- Password protect -->
|
|
<div class="form-group">
|
|
<label for="password_protect" class="col-sm-1 control-label text-left">Password protect</label>
|
|
<div class="col-sm-1">
|
|
<label class="switch" data-cy="settings-passwordProtectLocal">
|
|
<input type="checkbox" id="password_protect" name="password_protect" ng-model="formValues.passwordProtect" />
|
|
<i></i>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<!-- !Password protect -->
|
|
|
|
<!-- Password -->
|
|
<div class="form-group" ng-if="formValues.passwordProtect">
|
|
<label for="password" class="col-sm-1 control-label text-left">Password</label>
|
|
<div class="col-sm-3">
|
|
<input type="password" class="form-control" ng-model="formValues.password" id="password" name="password" required data-cy="settings-backupLocalPassword" />
|
|
</div>
|
|
</div>
|
|
<div class="form-group col-md-12" ng-show="backupPortainerForm.password.$invalid">
|
|
<div class="small text-warning">
|
|
<div ng-messages="backupPortainerForm.password.$error">
|
|
<p ng-message="required"> <i class="fa fa-exclamation-triangle" aria-hidden="true"></i> This field is required.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- !Password -->
|
|
|
|
<!-- actions -->
|
|
<div class="form-group">
|
|
<div class="col-sm-12">
|
|
<button
|
|
type="button"
|
|
class="btn btn-primary btn-sm"
|
|
ng-click="downloadBackup()"
|
|
ng-disabled="backupPortainerForm.$invalid || state.backupInProgress || state.featureLimited"
|
|
button-spinner="state.backupInProgress"
|
|
data-cy="settings-downloadLocalBackup"
|
|
>
|
|
<span ng-hide="state.backupInProgress">Download backup</span>
|
|
<span ng-show="state.backupInProgress">Downloading backup</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- !actions -->
|
|
</form>
|
|
</rd-widget-body>
|
|
</rd-widget>
|
|
</div>
|
|
</div>
|