feat(custom-templates): validate unique template name (#4264)

* feat(custom-template): check for name uniqueness

* feat(custom-templates): check unique name on edit
pull/4265/head
Chaim Lev-Ari 2020-08-24 05:54:02 +03:00 committed by GitHub
parent d5d7b17dc4
commit 45cada05d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 2 deletions

View File

@ -1,3 +1,4 @@
import _ from 'lodash';
import { AccessControlFormData } from 'Portainer/components/accessControlForm/porAccessControlFormModel';
class CreateCustomTemplateViewController {
@ -29,6 +30,7 @@ class CreateCustomTemplateViewController {
fromStack: false,
loading: true,
};
this.templates = [];
this.createCustomTemplate = this.createCustomTemplate.bind(this);
this.createCustomTemplateAsync = this.createCustomTemplateAsync.bind(this);
@ -73,7 +75,7 @@ class CreateCustomTemplateViewController {
this.Notifications.success('Custom template successfully created');
this.$state.go('docker.templates.custom');
} catch (err) {
this.Notifications.error('Deployment error', err, 'Unable to create custom template');
this.Notifications.error('Failure', err, 'A template with the same name already exists');
} finally {
this.state.actionInProgress = false;
}
@ -87,6 +89,13 @@ class CreateCustomTemplateViewController {
return false;
}
const title = this.formValues.Title;
const isNotUnique = _.some(this.templates, (template) => template.Title === title);
if (isNotUnique) {
this.state.formValidationError = 'A template with the same name already exists';
return false;
}
const isAdmin = this.Authentication.isAdmin();
const accessControlData = this.formValues.AccessControlData;
const error = this.FormValidator.validateAccessControl(accessControlData, isAdmin);
@ -145,6 +154,12 @@ class CreateCustomTemplateViewController {
this.formValues.Type = +type;
}
try {
this.templates = await this.CustomTemplateService.customTemplates();
} catch (err) {
this.Notifications.error('Failure loading', err, 'Failed loading custom templates');
}
this.state.loading = false;
}
}

View File

@ -1,3 +1,5 @@
import _ from 'lodash';
import { AccessControlFormData } from 'Portainer/components/accessControlForm/porAccessControlFormModel';
import { ResourceControlViewModel } from 'Portainer/models/resourceControl/resourceControl';
@ -10,6 +12,7 @@ class EditCustomTemplateViewController {
this.state = {
formValidationError: '',
};
this.templates = [];
this.getTemplate = this.getTemplate.bind(this);
this.getTemplateAsync = this.getTemplateAsync.bind(this);
@ -44,6 +47,14 @@ class EditCustomTemplateViewController {
return false;
}
const title = this.formValues.Title;
const id = this.$state.params.id;
const isNotUnique = _.some(this.templates, (template) => template.Title === title && template.Id != id);
if (isNotUnique) {
this.state.formValidationError = `A template with the name ${title} already exists`;
return false;
}
const isAdmin = this.Authentication.isAdmin();
const accessControlData = this.formValues.AccessControlData;
const error = this.FormValidator.validateAccessControl(accessControlData, isAdmin);
@ -85,8 +96,14 @@ class EditCustomTemplateViewController {
this.formValues.fileContent = cm.getValue();
}
$onInit() {
async $onInit() {
this.getTemplate();
try {
this.templates = await this.CustomTemplateService.customTemplates();
} catch (err) {
this.Notifications.error('Failure loading', err, 'Failed loading custom templates');
}
}
}