-
Notifications
You must be signed in to change notification settings - Fork 65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
support for disabled modules, multiple database connections, lazy models creation, further implementation of core modules according to original idea given by Andrija Petrovic, support for submenu items ... #37
Conversation
Here is lazy model creation example structure, bit twisted original users schema : var UserSchema = {
fields: {
_id: {
type: String,
unique: [true, 'There is already a user with that username'],
required: [true, 'Please provide a username']
},
snapshot: {
type:Schema.Types.ObjectId,
ref:'UserSnapshot'
},
hashed_password: {
type: String,
validate: [validatePresenceOf, 'Password cannot be blank']
},
provider: {
type: String,
default: 'local'
},
roles: {
type: Array,
default: ['notapproved']
},
salt: String,
resetPasswordToken: String,
resetPasswordExpires: Date
},
virtual: {
password: {
set: function(password) {
this._password = password;
this.salt = this.makeSalt();
this.hashed_password = this.hashPassword(password);
},
get: function () {
return this._password;
}
}
},
pre: {
'save': function(next) {
if (this.isNew && this.provider === 'local' && this.password && !this.password.length)
return next(new Error('Invalid password'));
next();
}
},
statics : {
getUser: function (id, cb, full_profile) {
this.findOne({ _id:id }, full_profile ? undefined : '-salt -hashed_password -__v')
.populate('snapshot', '-_id -__v')
.exec(cb);
},
createUser: function (userdata, cb) {
var Ussm = mongoose.get_MEANIODB_connection('users').model('UserSnapshot');
var uss = new Ussm (userdata);
uss.save(function (e,d) {
if (e) return cb (e);
userdata._id = userdata.username;
userdata.snapshot = d._id;
var User = mongoose.get_MEANIODB_connection('users').model('User');
var user = new User(userdata);
user.save (cb);
});
}
},
methods: {
/**
* HasRole - check if the user has required role
*
* @param {String} plainText
* @return {Boolean}
* @api public
*/
hasRole: function(role) {
var roles = this.roles;
return roles.indexOf('admin') !== -1 || roles.indexOf(role) !== -1;
},
/**
* IsAdmin - check if the user is an administrator
*
* @return {Boolean}
* @api public
*/
isAdmin: function() {
return this.roles.indexOf('admin') !== -1;
},
/**
* Authenticate - check if the passwords are the same
*
* @param {String} plainText
* @return {Boolean}
* @api public
*/
authenticate: function(plainText) {
return this.hashPassword(plainText) === this.hashed_password;
},
/**
* Make salt
*
* @return {String}
* @api public
*/
makeSalt: function() {
return crypto.randomBytes(16).toString('base64');
},
/**
* Hash password
*
* @param {String} password
* @return {String}
* @api public
*/
hashPassword: function(password) {
if (!password || !this.salt) return '';
var salt = new Buffer(this.salt, 'base64');
return crypto.pbkdf2Sync(password, salt, 10000, 64).toString('base64');
}
}
}; |
I'll take the opportunity to point out how all the core functionality is now split into core modules:
Another important refactor: Config is now created without a callback in the constructor. So, Config is created before the DBs are initiated. Config initially does the util.loadSettings() and this function is now called only during Config creation. It makes no sense (both logically and in performance terms) to let other layers of the software do the util.loadSettings again. After the Config is created, the Meanio.prototype.loadSettings method refers to Meanio.Singleton.config.clean, of course. |
Its the weekend here but I can't wait to check this.
|
hi @andrija-hers firstlly thanks so much for this awesome contribution. I like the direction now we just have to go over the PR, better understand it and see when/how it will integrate with the project etc |
Submenu items support has just been implemented ... Unfortunately, without client side code nothing can be seen, so I am about to create a PR for client side within few minutes as well ... Complete implementation is fully backwards compatible, so anyone who uses old code should be ok. News are path and name fields within dictionary given to Modulename.menus.add function. Path is slash separated string which should point to parent menu item. Name is, of course, name of given menu item which will serve for future reference. Test.menus.add({
title: 'Test',
link: 'test example page',
name: 'test',
path: 'main'
}); Omitting path will add item to main menu node by default. Test.menus.add({
title:'Test1',
link:'test1',
name: 'test1',
path:'main/test'
}); This way, test1 will become submenu item of test ... And so on ... Best regards ... |
error when using mean-admin package on fresh version of linnovate/mean branch master TypeError: Cannot call method 'get' of undefined |
Dear Yonatan, many thanks for the info! We'll get down to it - and eventually ask for On Wed, Sep 17, 2014 at 11:49 AM, Yonatan Ellman notifications@github.com
|
@ellman : thanx, got it, will fix it asap ... |
@veljkopopovic thanks. I see that sorted the issue with the menu I will continue testing. |
@ellman you've been bit faster :D Anyway, this should fix defaultMenu problem, allowing menu-admin package to actually display side bar, but my humble opinion is that defaultMenu is bit a dirty hack. In other words, why admin package does not register menu items within, let's say, 'side' menu within its register function staying consistent with other packages? |
@ellman, @liorkesos : will write some comments tonight, no problem ... as well as bit of doc on this lazy mechanism as well |
@veljkopopovic - We've been looking in to this - it looks very cool till now. |
https://github.com/linnovate/mean-cli/tree/0.4.1 created for now as a common tinkering ground in preparation for the next major release. @fyockm We merged the PR and pushed 0.4.1 branch which will mainly just be a placeholder for 0.5.0. In this branch we will test, benchmark and refine overall direction. If you get any time it will be great to get your opinion on the overall direction |
@veljkopopovic regarding the defaultMenu being a dirty hack.... Yes, you are 100% correct but we are kind of stuck with it at least until a major version. Main problem is changes breaking packages. In theory we could just refactor mean-admin and maybe one or 2 others. Which would probably be a better direction. @liorkesos what do you think? |
@ellman, @liorkesos sorry being late for this doc thing, we're in bit a rush here in Belgrade, had no time to write something ... Hopefully, I'll grab some time this weekend ... |
…a loop, with no 'code' variable being passed to
* lirantal-cleanup-spellings: fixing spellings adding my own CLA to the list
…/mean-cli into lirantal-cleanup-jshint-warnings * 'cleanup-jshint-warnings' of https://github.com/lirantal/mean-cli: cleaning up jshints issues adding javascript implicit strict cleaning up jshint semi-colon issues fixed jshint issues - removed anonymous function() definition within a loop, with no 'code' variable being passed to
Let's close these and move along |
First of all, thank you for a fantastic project you have delivered to us :D I hope I will be able to help a bit.
Few things has been addressed here:
After setting these functions, rest of bootstrap is done so these functions remains visible to the rest of program ...
3. model loading helper has been introduced. It is backward compatible to support current implementation. If model.js file set to module.exports register field with model settings, model will be registered within requireModel function. This way, model file writer has some typing help: with previous solution, programmer should, in every model write something like this
With this solution model programmer should set :
and requireModel function will do rest of job ...
On the other hand if UserSchema is a simple hash, not instance of mongoose.Schema, lazy model creation is invoked. This way every file invoked through module load process can extend schema object. Once all modules are loaded, lazy models creation is started: createModels will take resulting structure and create schema and model on designated db connection out of it ...
4. Last (for now) but not least, core modules has been implemented as far as possible ...
Best regards ...