Пример #1
0
 *
 *  ```javascript
 *  get(model, 'validations.attrs.details.isValid')
 *  get(model, 'validations.attrs.details.messages')
 *  ```
 *
 *  @class Belongs To
 *  @module Validators
 *  @extends Base
 */
const BelongsTo = Base.extend({
  validate(value) {
    if (value) {
      if (isPromise(value)) {
        return value.then(model => model ? get(model, 'validations') : true);
      }
      return get(value, 'validations');
    }

    return true;
  }
});

BelongsTo.reopenClass({
  getDependentsFor(attribute) {
    return [ `model.${attribute}.isDeleted` ];
  }
});

export default BelongsTo;
Пример #2
0
 *
 *  ```javascript
 *  get(model, 'validations.attrs.friends.isValid')
 *  get(model, 'validations.attrs.friends.messages')
 *  ```
 *
 *  @class Has Many
 *  @module Validators
 *  @extends Base
 */
const HasMany = Base.extend({
  validate(value) {
    if (value) {
      if (canInvoke(value, 'then')) {
        return value.then(models => models ? models.map(m => m.get('validations')) : true);
      }
      return value.map(m => m.get('validations'));
    }

    return true;
  }
});

HasMany.reopenClass({
  getDependentsFor(attribute) {
    return [ `model.${attribute}.[]`, `${attribute}.@each.isTruelyValid` ];
  }
});

export default HasMany;
Пример #3
0
export default Base.extend({

  _parseDate(date, format, useStrict = false) {
    if (date === 'now' || isEmpty(date)) {
      return moment();
    }

    return isNone(format) ? moment(new Date(date)) : moment(date, format, useStrict);
  },

  validate(value, options) {
    const errorFormat = getWithDefault(options, 'errorFormat', 'MMM Do, YYYY');
    const { format, precision, allowBlank } = getProperties(options, ['format', 'precision', 'allowBlank']);
    let { before, onOrBefore, after, onOrAfter } = getProperties(options, ['before', 'onOrBefore', 'after', 'onOrAfter']);
    let date;

    if (allowBlank && isEmpty(value)) {
      return true;
    }

    if (format) {
      date = this._parseDate(value, format, true);
      if (!date.isValid()) {
        return this.createErrorMessage('wrongDateFormat', value, options);
      }
    } else {
      date = this._parseDate(value);
      if (!date.isValid()) {
        return this.createErrorMessage('date', value, options);
      }
    }

    if (before) {
      before = this._parseDate(before, format);
      if (!date.isBefore(before, precision)) {
        set(options, 'before', before.format(errorFormat));
        return this.createErrorMessage('before', value, options);
      }
    }

    if (onOrBefore) {
      onOrBefore = this._parseDate(onOrBefore, format);
      if (!date.isSameOrBefore(onOrBefore, precision))  {
        set(options, 'onOrBefore', onOrBefore.format(errorFormat));
        return this.createErrorMessage('onOrBefore', value, options);
      }
    }

    if (after) {
      after = this._parseDate(after, format);
      if (!date.isAfter(after, precision)) {
        set(options, 'after', after.format(errorFormat));
        return this.createErrorMessage('after', value, options);
      }
    }

    if (onOrAfter) {
      onOrAfter = this._parseDate(onOrAfter, format);
      if (!date.isSameOrAfter(onOrAfter, precision)) {
        set(options, 'onOrAfter', onOrAfter.format(errorFormat));
        return this.createErrorMessage('onOrAfter', value, options);
      }
    }

    return true;
  }
});
 *  ```javascript
 *  get(model, 'validations.attrs.friends.isValid')
 *  get(model, 'validations.attrs.friends.messages')
 *  ```
 *
 *  @class Has Many
 *  @module Validators
 *  @extends Base
 */
const HasMany = Base.extend({
  validate(value, ...args) {
    if (value) {
      if (isPromise(value)) {
        return value.then(models => this.validate(models, ...args));
      }

      return value.map(m => m.get('validations'));
    }

    return true;
  }
});

HasMany.reopenClass({
  getDependentsFor(attribute) {
    /*
      The content.@each.isDeleted must be added for older ember-data versions
     */
    return [
      `model.${attribute}.[]`,
      `model.${attribute}.@each.isDeleted`,
Пример #5
0
import { isEmpty } from '@ember/utils';
import RSVP from 'rsvp';
import BaseValidator from 'ember-cp-validations/validators/base';

const { Promise } = RSVP;

export default BaseValidator.extend({
  validate(value, options) {
    let promise = options['in'];
    if (isEmpty(promise)) {
      return true;
    }

    return new Promise(resolve => {
      promise.then(excluded => {
        if (excluded.includes(value)) {
          resolve(this.createErrorMessage('exclusion', value, options));
        } else {
          resolve(true);
        }
      });
    });
  }
});
 *    friends: null
 *  });
 *  ```
 *
 *  From our `user` model, we can now check validation properties on the `friends` attribute.
 *
 *  ```javascript
 *  get(model, 'validations.attrs.friends.isValid')
 *  get(model, 'validations.attrs.friends.messages')
 *  ```
 *
 *  @class Has Many
 *  @module Validators
 *  @extends Base
 */
export default Base.extend({
  validate(value) {
    if (value) {
      if (canInvoke(value, 'then')) {
        return value.then((models) => {
          return models.map(m => m.get('validations'));
        });
      } else {
        return value.map(m => m.get('validations'));
      }
    }

    return true;
  }
});
Пример #7
0
export default Base.extend({

  /**
   * Normalized options passed in.
   * ```js
   * validator('presence', true)
   * // Becomes
   * validator('presence', {
   *   presence: true
   * })
   * ```
   *
   * @method buildOptions
   * @param  {Object}     options
   * @param  {Object}     defaultOptions
   * @param  {Object}     globalOptions
   * @return {Object}
   */
  buildOptions(options = {}, defaultOptions = {}, globalOptions = {}) {
    let opts = options;

    if (typeof options === 'boolean') {
      opts = {
        presence: options
      };
    }
    return this._super(opts, defaultOptions, globalOptions);
  },

  validate(value, options, model, attribute) {
    const { presence, ignoreBlank } = getProperties(options, ['presence', 'ignoreBlank']);

    assert(`[ember-cp-validations] [validator:presence] [${attribute}] option 'presence' is required`, !isEmpty(presence));

    if (presence === true && !this._isPresent(value, ignoreBlank)) {
      return this.createErrorMessage('blank', value, options);
    }

    if (presence === false && this._isPresent(value, ignoreBlank)) {
      return this.createErrorMessage('present', value, options);
    }

    return true;
  },

  /**
   * Handle presence of ember proxy based instances
   */
  _isPresent(value, ignoreBlank = false) {
    if (value instanceof Ember.ObjectProxy || value instanceof Ember.ArrayProxy) {
      return this._isPresent(get(value, 'content'), ignoreBlank);
    }

    if (ignoreBlank) {
      return isPresent(value);
    } else {
      return !isEmpty(value);
    }
  }
});
import Ember from 'ember';
import BaseValidator from 'ember-cp-validations/validators/base';

const { inject: { service }, isEmpty, isBlank } = Ember;

const UniqueUsername = BaseValidator.extend({
  store: service(),

  validate(value /* , options, model, attribute */) {
    if (isBlank) {
      return true;
    }

    return this
      .get('store')
      .query('user', { username: value })
      .then((result) => isEmpty(result) ? true : `The username ${value} already exists`);
  }
});

UniqueUsername.reopenClass({

  /**
   * Define attribute specific dependent keys for your validator
   *
   * @param {String}  attribute   The attribute being evaluated
   * @param {Unknown} options     Options passed into your validator
   * @return {Array}
   */
  getDependentsFor(/* attribute, options */) {
    return [];
Пример #9
0
export default BaseValidator.extend({
    store: Ember.inject.service(),
    validate(value, options, model/*, attribute*/) {
        if (!value) {
            return false;
        }
        var dirty_attr = model.changedAttributes();
        if (!dirty_attr[options['field']]) {
            return true;
        }
        // [old_value, new_vale]
        var dirty_elem = dirty_attr['field'];
        // old value is the same as the current one
        if (Array.isArray(dirty_elem) && dirty_elem[0] === value) {
            return true;
        }
        var server_query = {};
        server_query[options['field']] = value;
        for (var key in options['filter']) {
                server_query[key] = model.get(key);
        }

        var query = {};
        var plural_model = options['model'].pluralize();
        query[plural_model + '/available'] = server_query;
        return this.get('store').queryRecord('result', query).then((result) => {
            var data = JSON.parse(result.get('raw_json'));
            if (data['available']) {
                return true;
            }

            return `A ${options['field']} of ${value} already exists`;
        }, (error) => {
            return error;
        });
    }
});
Пример #10
0
 *  ```javascript
 *  get(model, 'validations.attrs.details.isValid')
 *  get(model, 'validations.attrs.details.messages')
 *  ```
 *
 *  @class Belongs To
 *  @module Validators
 *  @extends Base
 */
const BelongsTo = Base.extend({
  validate(value, ...args) {
    if (value) {
      if (isPromise(value)) {
        return value.then((model) => this.validate(model, ...args));
      }

      return get(value, 'validations');
    }

    return true;
  }
});

BelongsTo.reopenClass({
  getDependentsFor(attribute) {
    return [
      `model.${attribute}.isDeleted`,
      `model.${attribute}.content.isDeleted`,
      `model.${attribute}.validations`,
      `model.${attribute}.content.validations`
    ];
Пример #11
0
export default Base.extend({

  _parseDate(dateStr, format) {
    if (dateStr === 'now' || isEmpty(dateStr)) {
      return moment();
    }
    return format ? moment(dateStr, format) : moment(new Date(dateStr));
  },

  validate(value, options) {
    const errorFormat = options.errorFormat || 'MMM Do, YYYY';
    const format = options.format;
    const percision = options.percision;
    let { before, onOrBefore, after, onOrAfter } = options;

    if (options.allowBlank && isEmpty(value)) {
      return true;
    }

    const date = this._parseDate(value, format);

    if (!date.isValid()) {
      return this.createErrorMessage('date', value, options);
    }

    if (format && !moment(value, format, true).isValid()) {
      return this.createErrorMessage('wrongDateFormat', value, options);
    }

    if (before) {
      before = this._parseDate(before, format);
      if (!date.isBefore(before, percision)) {
        options.before = before.format(errorFormat);
        return this.createErrorMessage('before', value, options);
      }
    }

    if (onOrBefore) {
      onOrBefore = this._parseDate(onOrBefore, format);
      if (!date.isSameOrBefore(onOrBefore, percision))  {
        options.onOrBefore = onOrBefore.format(errorFormat);
        return this.createErrorMessage('onOrBefore', value, options);
      }
    }

    if (after) {
      after = this._parseDate(after, format);
      if (!date.isAfter(after, percision)) {
        options.after = after.format(errorFormat);
        return this.createErrorMessage('after', value, options);
      }
    }

    if (onOrAfter) {
      onOrAfter = this._parseDate(onOrAfter, format);
      if (!date.isSameOrAfter(onOrAfter, percision)) {
        options.onOrAfter = onOrAfter.format(errorFormat);
        return this.createErrorMessage('onOrAfter', value, options);
      }
    }

    return true;
  }
});
Пример #12
0
export default Base.extend({
  validate(value, options) {
    let numValue = Number(value);
    let optionKeys = Object.keys(options);

    if (options.allowBlank && isEmpty(value)) {
      return true;
    }

    if (typeof value === 'string' && (isEmpty(value) || !options.allowString)) {
      return this.createErrorMessage('notANumber', value, options);
    }

    if (!this.isNumber(numValue)) {
      return this.createErrorMessage('notANumber', value, options);
    }

    if (options.integer && !this.isInteger(numValue)) {
      return this.createErrorMessage('notAnInteger', value, options);
    }

    for (let i = 0; i < optionKeys.length; i++) {
      let type = optionKeys[i];
      let m = this._validateType(type, options, numValue);
      if (typeof m === 'string') {
        return m;
      }
    }

    return true;
  },

  _validateType(type, options, value) {
    let expected = options[type];
    let actual = value;

    if (type === 'is' && actual !== expected) {
      return this.createErrorMessage('equalTo', value, options);
    } else if (type === 'not' && actual === expected) {
      return this.createErrorMessage('notEqualTo', value, options);
    } else if (type === 'lt' && actual >= expected) {
      return this.createErrorMessage('lessThan', value, options);
    } else if (type === 'lte' && actual > expected) {
      return this.createErrorMessage('lessThanOrEqualTo', value, options);
    } else if (type === 'gt' && actual <= expected) {
      return this.createErrorMessage('greaterThan', value, options);
    } else if (type === 'gte' && actual < expected) {
      return this.createErrorMessage('greaterThanOrEqualTo', value, options);
    } else if (type === 'positive' && actual < 0) {
      return this.createErrorMessage('positive', value, options);
    } else if (type === 'odd' && actual % 2 === 0) {
      return this.createErrorMessage('odd', value, options);
    } else if (type === 'even' && actual % 2 !== 0) {
      return this.createErrorMessage('even', value, options);
    }

    return true;
  },

  /* Use polyfills instead of Number.isNaN or Number.isInteger to support IE & Safari */

  isNumber(value) {
    return typeof value === 'number' && !isNaN(value);
  },

  isInteger(value) {
    return typeof value === 'number' && isFinite(value) && Math.floor(value) === value;
  }
});
Пример #13
0
const Alias = Base.extend({
  /**
   * Normalized options passed in.
   * ```js
   * validator('alias', 'attribute')
   * // Becomes
   * validator('alias', {
   *   alias: 'attribute'
   * })
   * ```
   *
   * @method buildOptions
   * @param  {Object}     options
   * @param  {Object}     defaultOptions
   * @param  {Object}     globalOptions
   * @return {Object}
   */
  buildOptions(options = {}, defaultOptions = {}, globalOptions = {}) {
    let opts = options;

    if (typeof options === 'string') {
      opts = {
        alias: options
      };
    }
    return this._super(opts, defaultOptions, globalOptions);
  },

  /**
   * @method validate
   * @param {Any} value
   * @param {Object} options
   * @param {String} options.alias The attribute to alias
   * @param {Boolean} options.firstMessageOnly If true, only returns the first error message of the
   *                                           aliased attribute and will not include validation state
   * @param {Object} model
   * @param {String} attribute
   */
  validate(value, options, model, attribute) {
    let { alias, firstMessageOnly } = getProperties(options, ['alias', 'firstMessageOnly']);

    assert(`[validator:alias] [${attribute}] option 'alias' is required`, isPresent(alias));

    let aliasValidation = get(model, `validations.attrs.${alias}`);

    return firstMessageOnly ? get(aliasValidation, 'message') : get(aliasValidation, 'content');
  }
});
Пример #14
0
import Ember from 'ember';
import BaseValidator from 'ember-cp-validations/validators/base';

export default BaseValidator.extend({
  ajax: Ember.inject.service(),
  intl: Ember.inject.service(),
  account: Ember.inject.service(),

  async validate(email, options) {
    if (!email) {
      return;
    }

    let validResults = options.validResults || ['available', 'self'];

    let json = { email };
    let { result } = await this.get('ajax').request('/api/users/check-email', { method: 'POST', json });
    return (validResults.indexOf(result) !== -1) ? true : this.get('intl').t(options.messageKey);
  },
});
Пример #15
0
 *    }
 *  });
 *  ```
 *
 *  From our `user` model, we can now check any validation propery on the `user-details` model.
 *
 *  ```javascript
 *  get(model, 'validations.attrs.details.isValid')
 *  get(model, 'validations.attrs.details.messages')
 *  ```
 *
 *  @class Belongs To
 *  @module Validators
 *  @extends Base
 */
export default Base.extend({
  validate(value) {
    if (value) {
      if (canInvoke(value, 'then')) {
        return value.then((model) => {
          return get(model, 'validations');
        });
      } else {
        return get(value, 'validations');
      }
    }

    return true;
  }
});
import BaseValidator from 'ember-cp-validations/validators/base';

export default BaseValidator.extend({
  validate(/* value, options, model, attribute */) {
    return true;
  }
});
Пример #17
0
const Collection = Base.extend({

  /**
   * Normalized options passed in.
   * ```js
   * validator('collection', true)
   * // Becomes
   * validator('collection', {
   *   collection: true
   * })
   * ```
   *
   * @method buildOptions
   * @param  {Object}     options
   * @param  {Object}     defaultOptions
   * @param  {Object}     globalOptions
   * @return {Object}
   */
  buildOptions(options = {}, defaultOptions = {}, globalOptions = {}) {
    let opts = options;

    if (typeof options === 'boolean') {
      opts = {
        collection: options
      };
    }
    return this._super(opts, defaultOptions, globalOptions);
  },

  validate(value, options) {
    if (options.collection === true && !isArray(value)) {
      return this.createErrorMessage('collection', value, options);
    }

    if (options.collection === false && isArray(value)) {
      return this.createErrorMessage('singular', value, options);
    }

    return true;
  }
});
Пример #18
0
export default Base.extend({
  regularExpressions: {
    email: /^[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i,
    phone: /^([\+]?1\s*[-\/\.]?\s*)?(\((\d{3})\)|(\d{3}))\s*[-\/\.]?\s*(\d{3})\s*[-\/\.]?\s*(\d{4})\s*(([xX]|[eE][xX][tT]?[\.]?|extension)\s*([#*\d]+))*$/,
    url: /(?:([A-Za-z]+):)?(\/{0,3})[a-zA-Z0-9][a-zA-Z-0-9]*(\.[\w-]+)+([\w.,@?^=%&amp;:\/~+#-{}]*[\w@?^=%&amp;\/~+#-{}])??/
  },

  /**
   * Normalized options passed in by applying the desired regex or using the one declared
   *
   * @method buildOptions
   * @param  {Object}     options
   * @param  {Object}     defaultOptions
   * @param  {Object}     globalOptions
   * @return {Object}
   */
  buildOptions(options = {}, defaultOptions = {}, globalOptions = {}) {
    const regularExpressions = get(this, 'regularExpressions');
    const { regex, type } = options;

    if (type && !isNone(regularExpressions[type]) && isNone(regex)) {
      options.regex = regularExpressions[type];
    }

    return this._super(options, defaultOptions, globalOptions);
  },

  validate(value, options, model, attribute) {
    const { regex, type, allowBlank } = getProperties(options, ['regex', 'type', 'allowBlank']);

    assert(`[ember-cp-validations] [validator:format] [${attribute}] no options were passed in`, !isEmpty(Object.keys(options)));

    if (allowBlank && isEmpty(value)) {
      return true;
    }

    if (regex && !regex.test(value)) {
      return this.createErrorMessage(type || 'invalid', value, options);
    }

    return true;
  }
});
Пример #19
0
 */
export default Base.extend({
  validate(value, options) {
    var array = options['in'];
    var range = options.range;

    if (isEmpty(Object.keys(options))) {
      return true;
    }

    if (options.allowBlank && isEmpty(value)) {
      return true;
    }

    if (array && array.indexOf(value) !== -1) {
      return this.createErrorMessage('exclusion', value, options);
    }

    if (range && range.length === 2) {
      var min = range[0];
      var max = range[1];
      var equalType = typeOf(value) === typeOf(min) && typeOf(value) === typeOf(max);
      if (equalType && min <= value && value <= max) {
        return this.createErrorMessage('exclusion', value, options);
      }
    }

    return true;
  }
});
Пример #20
0
 *  ```javascript
 *  // Examples
 *  validator('ds-error')
 *  ```
 *
 *  @class DS Error
 *  @module Validators
 *  @extends Base
 */
const DSError = Base.extend({
  validate(value, options, model, attribute) {
    let { path, key } = getPathAndKey(attribute);

    const errors = get(model, path);

    if (!isNone(errors) && errors instanceof DS.Errors && errors.has(key)) {
      return get(errors.errorsFor(key), 'lastObject.message');
    }

    return true;
  }
});

DSError.reopenClass({
  getDependentsFor(attribute) {
    let { path, key } = getPathAndKey(attribute);

    return [ `model.${path}.${key}.[]` ];
  }
});
Пример #21
0
export default BaseValidator.extend({
  validate(value, options = {}) {
    Ember.assert(
      'options.validFormats must not be set or an array of momentJS format strings',
      Ember.isEmpty(options.validFormats) || Ember.isArray(options.validFormats)
    );

    let valid;
    const validFormats = Ember.isEmpty(options.validFormats) ? ['YYYY-MM-DDTHH:mm:ss.SSSZ'] : options.validFormats;

    if (
      options.active === false ||
      (typeof options.active === 'function' && options.active() === false)
    ) {
      return true;
    }

    options.value = value;

    valid = validFormats.any((validFormat) => {
      return moment(value, validFormat, true).isValid();
    });

    if (valid) {
      return true;
    } else {
      return this.createErrorMessage('iso8601', value, options);
    }
  }
});
Пример #22
0
export default Base.extend({
  /**
   * Normalized options passed in.
   * ```js
   * validator('presence', true)
   * // Becomes
   * validator('presence', {
   *   presence: true
   * })
   * ```
   * @method buildOptions
   * @param  {Object}     options
   * @param  {Object}     defaultOptions
   * @return {Object}
   */
  buildOptions(options, defaultOptions) {
    if(typeof options === 'boolean') {
      options = {
        presence: options
      };
    }
    return this._super(options, defaultOptions);
  },

  validate(value, options) {
    if (options.presence === true && !this._isPresent(value)) {
      return this.createErrorMessage('blank', value, options);
    }

    if(options.presence === false && this._isPresent(value)) {
      return this.createErrorMessage('present', value, options);
    }

    return true;
  },

  /**
   * Handle presence of ember proxy based instances
   */
  _isPresent(value) {
    if(value instanceof Ember.ObjectProxy || value instanceof Ember.ArrayProxy) {
        return this._isPresent(get(value, 'content'));
    }
    return !isEmpty(value);
  }
});
Пример #23
0
import BaseValidator from 'ember-cp-validations/validators/base';

export default BaseValidator.extend({
  validate(value, options) {
    if (options.active === false) {
      return true;
    }

    const valid = value.every((element) => {
      return element.get('validations.isValid');
    });

    if (valid) {
      return true;
    } else {
      return this.createErrorMessage('validCollection', options, value);
    }
  }
});
Пример #24
0
export default BaseValidator.extend({
  ajax: Ember.inject.service(),
  intl: Ember.inject.service(),

  async validate(value, options, model) {
    if (!value) {
      return;
    }

    let name = value.trim();
    if (name === '') {
      return;
    }

    let data = { name };
    let { clubs } = await this.get('ajax').request('/api/clubs', { data });
    if (clubs.length === 0) {
      return true;
    }

    if (options.idKey !== undefined) {
      let selfId = Ember.get(model, options.idKey);
      if (clubs[0].id === selfId) {
        return true;
      }
    }

    return this.get('intl').t(options.messageKey);
  },
});