How forms are created and the validations are added in Open Event Frontend

This blog article will illustrate how validations are added to a form  in Open Event Frontend, in a standard format. The form to Edit a Speaker is created in the route /event/<event_identifier>/speakers/edit. For the creation of a form an ember component is generated.

$ ember g component forms/events/view/edit-speaker

This command results in the generation of:

  1. An ember component edit-speaker.js to add the validation rules of the form.
  2. A handlebar edit-speaker.hbs where the HTML code is written.

First the form for editing a speaker is created. All the fields are added.

<form class=”ui form {{if isLoading ‘loading’}}” {{action ‘submit’ on=’submit’}}>


{{input type=’text’ id=’title’ value=data.name}}

{{input type=’text’ id=’email’ value=data.email}}

{{widgets/forms/image-upload
label=(t ‘Photo’)
imageUrl=data.photoUrl
icon=’image’
hint=(t ‘Select Photo’)
maxSizeInKb=1000}}

{{input type=’text’ id=’organisation’ value=data.organisation}}

{{input type=’text’ id=’position’ value=data.position}}

{{input type=’text’ id=’country’ value=data.country}}

{{widgets/forms/rich-text-editor value=data.shortBiography name=’shortBiography’}}

{{input type=’text’ id=’website’ value=data.website}}

{{input type=’text’ id=’twitter’ value=data.twitter}}

<button type=”submit” class=”ui teal submit button update-changes”>
{{t ‘Save Speaker’}}
</button>
</form>

Then validation rules for the fields included in the form are added in the component. The validations of a form are stored as objects, where the  identifier attribute determines which field to apply the validation conditions to. The rules array contains all the rules to be applied to the determined object. Within rules, the type represents the kind of validation, whereas the prompt attribute determines what message shall be displayed in case there is a violation of the validation rule. These validations are in turn implemented by the FormMixin.

import { protocolLessValidUrlPattern, validTwitterProfileUrlPattern } from ‘open-event-frontend/utils/validators’;

export default Component.extend(FormMixin, {

getValidationRules() {
return {
inline : true,
delay  : false,
on     : ‘blur’,
fields : {
email: {
identifier : ’email’,
rules      : [
{
type   : ’empty’,
prompt : this.get(‘l10n’).t(‘Please enter your email ID’)
},
{
type   : ’email’,
prompt : this.get(‘l10n’).t(‘Please enter a valid email ID’)
}
]
},
twitter: {
identifier : ‘twitter’,
optional   : true,
rules      : [
{
type   : ‘regExp’,
value  : validTwitterProfileUrlPattern,
prompt : this.get(‘l10n’).t(‘Please enter a valid twitter url’)
},
{
type   : ‘regExp’,
value  : protocolLessValidUrlPattern,
prompt : this.get(‘l10n’).t(‘Please enter a valid url’)
}
]
},
website: {
identifier : ‘website’,
optional   : ‘true’,
rules      : [
{
type   : ‘regExp’,
value  : protocolLessValidUrlPattern,
prompt : this.get(‘l10n’).t(‘Please enter a valid url’)
}
]
}
}
};
}

Then for adding the validation for the URLs of the speaker’s website and his twitter account regular expressions are used. They are used to perform pattern-matching.

export const  validTwitterProfileUrlPattern = new RegExp(
‘^twitter\\.com\\/([a-zA-Z0-9_]+)$’
);

 

export const protocolLessValidUrlPattern = new RegExp(
‘^’
// user:pass authentication
+ ‘(?:\\S+(?::\\S*)?@)?’
+ ‘(?:’
// IP address exclusion
// private & local networks
+ ‘(?!(?:10|127)(?:\\.\\d{1,3}){3})’
+ ‘(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})’
+ ‘(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})’
// IP address dotted notation octets
// excludes loopback network 0.0.0.0
// excludes reserved space >= 224.0.0.0
// excludes network & broacast addresses
// (first & last IP address of each class)
+ ‘(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])’
+ ‘(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}’
+ ‘(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))’
+ ‘|’
// host name
+ ‘(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)’
// domain name
+ ‘(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*’
// TLD identifier
+ ‘(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))’
// TLD may end with dot
+ ‘\\.?’
+ ‘)’
// port number
+ ‘(?::\\d{2,5})?’
// resource path
+ ‘(?:[/?#]\\S*)?’
+ ‘$’, ‘i’
);

Resources

  • EmberJS Mixins–Official ember documentation: https://guides.emberjs.com/v2.2.0/models
  • Kravvitz, Regular Expression Rules: http://forums.devshed.com/javascript-development/493764-regexp-match-url-pattern-post1944160.html#post1944160
Continue ReadingHow forms are created and the validations are added in Open Event Frontend

How Sanitizer Service Works in Open Event Frontend

This blog article will illustrate how the sanitizer service works  in Open Event Frontend, which allows the frontend to sanitize or clean any piece of text which can cause potential vulnerabilities in the application. To quote the official ember guides:

“An Ember.Service is a long-lived Ember object that can be made available in different parts of your application.”

Thus the chief advantage the service offers is, that the service once injected in the application can be called at  any place in the templates without an explicit import.

For instance, in the route `coc`, the templates make use of the servcie as

{{sanitize model.codeOfConduct}}

The core of the sanitizer service is comprised of npm sanitize-html module. The sanitize-html is a powerful module which offers an extensive set of features and customisations to deal with cleaning of html embedded text. The service efficiently exposes these features to the app, and wraps its features in various functions to offer several methods which can be used to handle html text.

export default Service.extend({

sanitize: null,

options: {
allowedTags       : [‘b’, ‘strong’, ‘i’, ’em’, ‘u’, ‘ol’, ‘ul’, ‘li’, ‘a’, ‘p’],
allowedAttributes : {
‘a’: [‘href’, ‘rel’, ‘target’]
},
selfClosing           : [‘br’],
allowedSchemes        : [‘http’, ‘https’, ‘ftp’, ‘mailto’],
allowedSchemesByTag   : {},
allowProtocolRelative : false,
transformTags         : {
‘i’ : ’em’,
‘b’ : ‘strong’,
‘a’ : sanitizeHtml.simpleTransform(‘a’, { rel: ‘nofollow’, target: ‘_blank’ })

},

purify(string) {
return sanitizeHtml(string, this.options);
},

strip(string) {
return sanitizeHtml(string, {
allowedTags       : [],
allowedAttributes : []
});
}
});

The options parameter of the service allows properties like allowedTags and and allowedAttributes which remove the specified tags and attributes from the text respectively. The transformTags property replaces the specified left hand side tags to the corresponding right hand side tags.

These are the generic requirements of the app and hence are exposed via tha purify method of the service. The purify method returns the sanitized string based on the configuration in the options parameter. Alternatively the strip method does not make use of the options parameter and rather passes a custom set of options with empty values for allowedTags and allowedAttributes. This method is used to completely remove any html tags or attributes from the text.

The service can be used outside of the templates in a controller or a component.

For instance the css helper uses the service to clean any text of html tags passed as a css property. The CSS helper is defined as follows.

export default Helper.extend({
sanitizer: service(),

compute(params, hash) {
let style = ”;
forOwn(hash, (value, key) => {
style += `${key}: ${value};`;
});
return htmlSafe(this.get(‘sanitizer’).strip(style));

});

Resources

  • Ember Services: https://guides.emberjs.com/v2.1.0/applications/services/
  • Sanitize-HTML docs: https://www.npmjs.com/package/sanitize-html

 

Continue ReadingHow Sanitizer Service Works in Open Event Frontend