diff --git a/lib/content-services/src/lib/i18n/en.json b/lib/content-services/src/lib/i18n/en.json index c58a54faf0..d0272e1e39 100644 --- a/lib/content-services/src/lib/i18n/en.json +++ b/lib/content-services/src/lib/i18n/en.json @@ -155,7 +155,8 @@ "EMPTY_TAG": "Tag name can't contain only spaces", "REQUIRED": "Tag name is required", "FETCH_TAGS": "Error while fetching the tags", - "CREATE_TAGS": "Error while creating the tags" + "CREATE_TAGS": "Error while creating the tags", + "SPECIAL_CHARACTERS": "Tag name cannot contain prohibited characters" }, "TOOLTIPS": { "DELETE_TAG": "Delete tag" diff --git a/lib/content-services/src/lib/tag/tags-creator/tags-creator.component.spec.ts b/lib/content-services/src/lib/tag/tags-creator/tags-creator.component.spec.ts index ee74afb128..a7e6bcd11f 100644 --- a/lib/content-services/src/lib/tag/tags-creator/tags-creator.component.spec.ts +++ b/lib/content-services/src/lib/tag/tags-creator/tags-creator.component.spec.ts @@ -382,6 +382,14 @@ describe('TagsCreatorComponent', () => { expect(getFirstError()).toBe('TAG.TAGS_CREATOR.ERRORS.ALREADY_ADDED_TAG'); })); + it('should show error for prohibited characters', fakeAsync(() => { + typeTag('tag*"<>\\/?:|'); + component.tagNameControl.markAsTouched(); + fixture.detectChanges(); + const error = getFirstError(); + expect(error).toBe('TAG.TAGS_CREATOR.ERRORS.SPECIAL_CHARACTERS'); + })); + it('should show error when duplicated already existing tag', fakeAsync(() => { const tag = 'Some tag'; @@ -518,6 +526,17 @@ describe('TagsCreatorComponent', () => { expect(tagService.findTagByName).toHaveBeenCalledWith(name); })); + it('should not perform search if an illegal character is specified', fakeAsync(() => { + spyOn(tagService, 'findTagByName').and.returnValue(EMPTY); + spyOn(tagService, 'searchTags').and.returnValue(EMPTY); + + const name = 'Tag:"\'>'; + typeTag(name); + + expect(tagService.findTagByName).not.toHaveBeenCalled(); + expect(tagService.searchTags).not.toHaveBeenCalled(); + })); + it('should call searchTags on tagService using name set in input and correct params', fakeAsync(() => { spyOn(tagService, 'searchTags').and.returnValue(EMPTY); diff --git a/lib/content-services/src/lib/tag/tags-creator/tags-creator.component.ts b/lib/content-services/src/lib/tag/tags-creator/tags-creator.component.ts index fb58525f8c..0a383737de 100644 --- a/lib/content-services/src/lib/tag/tags-creator/tags-creator.component.ts +++ b/lib/content-services/src/lib/tag/tags-creator/tags-creator.component.ts @@ -41,6 +41,7 @@ interface TagNameControlErrors { duplicatedAddedTag?: boolean; emptyTag?: boolean; required?: boolean; + specialCharacters?: boolean; } const DEFAULT_TAGS_SORTING = { @@ -132,7 +133,8 @@ export class TagsCreatorComponent implements OnInit, OnDestroy { ['duplicatedExistingTag', 'EXISTING_TAG'], ['duplicatedAddedTag', 'ALREADY_ADDED_TAG'], ['emptyTag', 'EMPTY_TAG'], - ['required', 'REQUIRED'] + ['required', 'REQUIRED'], + ['specialCharacters', 'SPECIAL_CHARACTERS'] ]); private readonly existingTagsListLimit = 15; @@ -144,7 +146,8 @@ export class TagsCreatorComponent implements OnInit, OnDestroy { [ this.validateIfNotAlreadyAdded.bind(this), Validators.required, - this.validateEmptyTag + this.validateEmptyTag, + this.validateSpecialCharacters ], this.validateIfNotExistingTag.bind(this) ); @@ -301,7 +304,7 @@ export class TagsCreatorComponent implements OnInit, OnDestroy { } private loadTags(name: string) { - if (name) { + if (name && !this.tagNameControl.hasError('specialCharacters')) { forkJoin({ exactResult: this.tagService.findTagByName(name), searchedResult: this.tagService.searchTags(name, DEFAULT_TAGS_SORTING, false, 0, this.existingTagsListLimit) @@ -369,6 +372,13 @@ export class TagsCreatorComponent implements OnInit, OnDestroy { : null; } + private validateSpecialCharacters(tagNameControl: FormControl): TagNameControlErrors | null { + const specialSymbolsRegex = /[':"\\|<>/?]/; + return tagNameControl.value.length && specialSymbolsRegex.test(tagNameControl.value) + ? { specialCharacters: true } + : null; + } + private setTagNameControlErrorMessageKey(): void { this._tagNameErrorMessageKey = this.tagNameControl.invalid ? `TAG.TAGS_CREATOR.ERRORS.${this.nameErrorMessagesByErrors.get(