Skip to content

Instantly share code, notes, and snippets.

@Bajix
Created December 27, 2016 21:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Bajix/1b7e3c16cb9251f214c3a9061c59ade7 to your computer and use it in GitHub Desktop.
Save Bajix/1b7e3c16cb9251f214c3a9061c59ade7 to your computer and use it in GitHub Desktop.
User connection w/ streaming validation
var DefineList = require('can-define/list/'),
DefineMap = require('can-define/map/'),
tag = require('can-connect/can/tag/'),
deepEqual = require('deep-equal'),
connect = require('can-connect'),
validator = require('validator'),
zxcvbn = require('zxcvbn'),
config = require('config'),
set = require('can-set'),
Kefir = require('kefir'),
_ = require('lodash');
require('can-define-stream');
var algebra = new set.Algebra(
set.comparators.id('_id')
);
var User = DefineMap.extend({
_id: {
type: 'string'
},
__v: {
type: 'number',
serialize: false
},
username: {
type: 'string'
},
displayName: {
type: 'string'
},
provider: {
type: 'string',
serialize: false
},
socialID: {
type: 'string',
serialize: false
},
email: {
type: 'string',
set: function( val ) {
if (validator.isEmail(val)) {
return validator.normalizeEmail(val, {
lowercase: true,
remove_dots: true,
remove_extension: true
});
}
return val.toLowerCase();
}
},
emailVerified: {
type: 'boolean'
},
password: {
type: 'string'
},
avatar: {
type: 'string'
},
permission: {
type: 'number',
value: config.permission.default
},
createdAt: {
type: 'date',
serialize: false
},
updatedAt: {
type: 'date',
serialize: false
},
validationErrors: {
stream: function() {
return Kefir.combine([
this.stream('.email').map(function( email ) {
if (email) {
if (!validator.isEmail(email)) {
return {
email: ['email invalid']
};
}
} else {
return {
email: ['email required']
};
}
}),
this.stream('.username').map(function( username ) {
if (!username) {
return {
username: ['username required']
};
}
}),
this.stream('.password').filterBy(this.stream('.provider').map(function( provider ) {
return provider === 'local';
})).map(function( password ) {
if (!password) {
return {
password: ['password required']
};
}
}).filterBy(this.stream('.isNew')).merge(Kefir.constant()),
this.stream('.password').map(function( password ) {
if (password && zxcvbn(password).score < 2) {
return {
password: ['password too weak']
};
}
}).filterBy(this.stream('.isNew')).merge(Kefir.constant())
], function() {
var length = arguments.length,
validationErrors = {};
for (var i = 0; i < length; i++) {
var errors = arguments[i];
if (errors) {
_.merge(validationErrors, errors);
}
}
return validationErrors;
}).debounce(0).skipDuplicates(deepEqual);
},
serialize: false
}
});
User.List = DefineList.extend({
'#': User
});
var cacheConnection = connect([
require('can-connect/data/memory-cache/')
], {
idProp: '_id',
algebra: algebra,
name: 'users'
});
var connection = connect([
require('can-connect/data/url/'),
require('can-connect/data/parse/'),
require('can-connect/cache-requests/'),
// require('can-connect/data/combine-requests/'),
require('can-connect/constructor/'),
require('can-connect/constructor/store/'),
require('can-connect/can/map/'),
require('can-connect/can/ref/'),
require('can-connect/fall-through-cache/'),
// require('can-connect/data/worker'),
require('can-connect/real-time/'),
require('can-connect/data/callbacks-cache/'),
require('can-connect/data/callbacks/'),
require('can-connect/constructor/callbacks-once/'),
require('./behaviors/access-control')
], {
idProp: '_id',
cacheConnection: cacheConnection,
url: {
resource: config.hosts.dashboard + '/api/users'
},
Map: User,
List: User.List,
algebra: algebra,
listSetProp: 'listSet'
});
tag('user-model', connection);
exports.User = User;
exports.algebra = algebra;
exports.connection = connection;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment