fix: Render valid urls only in custom attributes (#3921)

This commit is contained in:
Muhsin Keloth 2022-02-07 13:04:27 +05:30 committed by GitHub
parent 047070ad87
commit 9f37a6e2ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 23 additions and 21 deletions

View file

@ -63,7 +63,7 @@
rel="noopener noreferrer" rel="noopener noreferrer"
class="value" class="value"
> >
{{ value || '---' }} {{ urlValue }}
</a> </a>
<p v-else class="value"> <p v-else class="value">
{{ displayValue || '---' }} {{ displayValue || '---' }}
@ -119,7 +119,7 @@ import format from 'date-fns/format';
import { required, url } from 'vuelidate/lib/validators'; import { required, url } from 'vuelidate/lib/validators';
import { BUS_EVENTS } from 'shared/constants/busEvents'; import { BUS_EVENTS } from 'shared/constants/busEvents';
import MultiselectDropdown from 'shared/components/ui/MultiselectDropdown.vue'; import MultiselectDropdown from 'shared/components/ui/MultiselectDropdown.vue';
import { isValidURL } from '../helper/URLHelper';
const DATE_FORMAT = 'yyyy-MM-dd'; const DATE_FORMAT = 'yyyy-MM-dd';
export default { export default {
@ -184,6 +184,9 @@ export default {
isAttributeTypeDate() { isAttributeTypeDate() {
return this.attributeType === 'date'; return this.attributeType === 'date';
}, },
urlValue() {
return isValidURL(this.value) ? this.value : '---';
},
notAttributeTypeCheckboxAndList() { notAttributeTypeCheckboxAndList() {
return !this.isAttributeTypeCheckbox && !this.isAttributeTypeList; return !this.isAttributeTypeCheckbox && !this.isAttributeTypeList;
}, },

View file

@ -37,3 +37,9 @@ export const accountIdFromPathname = pathname => {
const accountId = isScoped ? Number(urlParam) : ''; const accountId = isScoped ? Number(urlParam) : '';
return accountId; return accountId;
}; };
export const isValidURL = value => {
/* eslint-disable no-useless-escape */
const URL_REGEX = /^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$/gm;
return URL_REGEX.test(value);
};

View file

@ -2,6 +2,7 @@ import {
frontendURL, frontendURL,
conversationUrl, conversationUrl,
accountIdFromPathname, accountIdFromPathname,
isValidURL,
} from '../URLHelper'; } from '../URLHelper';
describe('#URL Helpers', () => { describe('#URL Helpers', () => {
@ -48,4 +49,13 @@ describe('#URL Helpers', () => {
expect(accountIdFromPathname('')).toBe(''); expect(accountIdFromPathname('')).toBe('');
}); });
}); });
describe('isValidURL', () => {
it('should return true if valid url is passed', () => {
expect(isValidURL('https://chatwoot.com')).toBe(true);
});
it('should return false if invalid url is passed', () => {
expect(isValidURL('alert.window')).toBe(false);
});
});
}); });

View file

@ -1,5 +1,5 @@
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import { isValidURL } from '../helper/URLHelper';
export default { export default {
computed: { computed: {
...mapGetters({ ...mapGetters({
@ -63,16 +63,11 @@ export default {
Number.isInteger(Number(attributeValue)) && Number(attributeValue) > 0 Number.isInteger(Number(attributeValue)) && Number(attributeValue) > 0
); );
}, },
isAttributeLink(attributeValue) {
/* eslint-disable no-useless-escape */
const URL_REGEX = /^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$/gm;
return URL_REGEX.test(attributeValue);
},
attributeDisplayType(attributeValue) { attributeDisplayType(attributeValue) {
if (this.isAttributeNumber(attributeValue)) { if (this.isAttributeNumber(attributeValue)) {
return 'number'; return 'number';
} }
if (this.isAttributeLink(attributeValue)) { if (isValidURL(attributeValue)) {
return 'link'; return 'link';
} }
return 'text'; return 'text';

View file

@ -92,18 +92,6 @@ describe('attributeMixin', () => {
expect(wrapper.vm.attributeDisplayType(9988)).toBe('number'); expect(wrapper.vm.attributeDisplayType(9988)).toBe('number');
}); });
it('return true if link is passed', () => {
const Component = {
render() {},
title: 'TestComponent',
mixins: [attributeMixin],
};
const wrapper = shallowMount(Component, { store, localVue });
expect(wrapper.vm.isAttributeLink('https://www.chatwoot.com/pricing')).toBe(
true
);
});
it('return true if number is passed', () => { it('return true if number is passed', () => {
const Component = { const Component = {
render() {}, render() {},