我是刚看了点bluebird的资料就下手重构了,大家看看我bluebird用的是否正确,是否影响性能,有没其他问题? 下面我吧重构前、重构后的代码都贴出来大家,对比着看看,主要是改了以下 REST API 里的方法:
app.put('/api/v1/user', auth.requiresLogin, putUser, putUserValidations, putUserPostValidate, saveUser);
重构后把putUser, putUserValidations, putUserPostValidate, saveUser 方法合并为putUser一个方法
app.put('/api/v1/admin/user', auth.adminAccess, putUserByAdmin, putUserValidations, putUserPostValidate, saveUser);
重构后把putUserByAdmin, putUserValidations, putUserPostValidate, saveUser 方法合并为putUserByAdmin一个方法
app.put('/api/v1/image/user', auth.requiresLogin, putImage, saveImage,saveUser);
重构后把putImage, saveImage,saveUser 方法合并为putImage一个方法
下面是重构前后的完整代码,大家主要看上面提到的方法就行:
** 一、重构前:**
var mongoose = require(‘mongoose’) , User = mongoose.model(‘User’) , UserList = mongoose.model(‘UserList’) , VerifyCode = mongoose.model(‘VerifyCode’) , MessageThread = mongoose.model(‘MessageThread’) , SystemMessageArchive = mongoose.model(‘SystemMessageArchive’) , TermsAndConditionsArchive = mongoose.model(‘TermsAndConditionsArchive’) , ObjectId = mongoose.Types.ObjectId , restify = require(‘restify’) , config = require(‘…/config/config’).get() , config_path = config.root + ‘/config’ , auth = require(config_path + ‘/middlewares/authorization.js’) , Image = mongoose.model(‘Image’);
var mail = {}; var gUser = {}; // TODO don’t want to globalize user, need to figure out a better way to use Promises or Async var gImage = {}; var gCheckCurrentPassword = true; var gCheckRoleRestriction = true;
module.exports = function (app, mailHelper) { mail = mailHelper;
/**
* This function is responsible for searching and returning multiple users
*
* @param request includes the fields to create a UserList object
* @param response contains a populated UserList object
* @param next method
*/
function searchUsers(req, res, next) {
var userList = new UserList(req.params);
var pageNum = userList.pageNumber;
var itemsPerPage = userList.itemsPerPage;
if (itemsPerPage <= 0 || pageNum <= 0) {
itemsPerPage = 999999999999;
pageNum = 1;
}
pageNum = pageNum - 1;
User.count({}, function(err, count) {
if (!err) {
userList.pageCount = Math.ceil(count / itemsPerPage);
var sortStr = "";
if (userList.sortField !== null && userList.sortField !== '') {
if ('false' === userList.ascendingSortFlag) {
sortStr = "-" + userList.sortField;
} else {
sortStr = userList.sortField;
}
}
// NOTE This sort query is really inefficient, always queries the three columns
var query = User.find({ username: { $regex: userList.username, $options: 'imx' }, name: { $regex: userList.name, $options: 'imx' }, email: { $regex: userList.email, $options: 'imx' } });
// This returns partially populated objects preventing client sessions from seeing too much of the user's info
// if config settings are set to false, then these fields will be excluded
if (config.searchSettings.allowEmail) { query.select('email'); }
if (config.searchSettings.allowName) { query.select('name'); }
if (config.searchSettings.allowUsername) { query.select('username'); }
if (config.searchSettings.allowPhoneNumber) { query.select('phoneNumber');}
if (config.searchSettings.allowRole) {query.select('role');}
// If all selects are 'false' then all fields come back
// So explicity select the The Object Id so ONLY the Object Id plus any of the selected fields come back
query.select('_id');
if (sortStr.length > 0) {
query = query.sort(sortStr);
}
if (itemsPerPage > 0) {
query = query.limit(itemsPerPage).skip(itemsPerPage * pageNum);
}
query.exec(function(err, users) {
if (!err) {
userList.users = users;
// console.log(JSON.stringify(userList))
res.send(userList);
return next();
} else {
var errObj = err;
if (err.err) { errObj = err.err; }
return next(new restify.InternalError(errObj.message));
}
});
} else {
var errObj = err;
if (err.err) { errObj = err.err; }
return next(new restify.InternalError(errObj.message));
}
});
}
/**
* Gateway request routes to other functions based on params
* Search for a user by id or username
* if none given get the logged in user's information
*
* @param request can include an id, a username or no search param
* @param response contains a populated User object
* @param next method
*/
function getUser(req, res, next) {
if (req.session && req.session.user) {
id = req.session.user;
if (req.params.id) { id = req.params.id; }
User.findById(id, function (err, user) {
if (!err) {
res.send(user);
return next();
} else {
var errObj = err;
if (err.err) { errObj = err.err; }
return next(new restify.InternalError(errObj.message));
}
});
} else {
return next(new restify.MissingParameterError('No search params sent.'));
}
}
/**
* Search for a user by id or username
*
* @param request path includes an id or username
* @param response contains a populated User object
* @param next method
*/
function getUserByIdOrUsername(req, res, next) {
var search = req.url;
search = search.substring(search.lastIndexOf("/")+1);
if (search !== null && search !== '') {
var query = User.where( 'username', new RegExp('^'+search+'$', 'i') );
query.findOne(function (err, user) {
if (!err) {
if (user) {
res.send(user);
} else {
User.findById(search, function (err, user) {
if (!err) {
res.send(user);
} else {
res.send(new restify.ResourceNotFoundError('User not found.'));
}
return next();
});
}
} else {
var errObj = err;
if (err.err) { errObj = err.err; }
return next(new restify.InternalError(errObj.message));
}
});
} else {
return next(new restify.MissingParameterError('Username or ID required.'));
}
}
/**
* Admin: Modify an existing user
*
* @param request
* @param response
* @param next method
*/
function putUserByAdmin(req, res, next) {
gCheckCurrentPassword = false;
gCheckRoleRestriction = false;
User.findById(req.params.id, function (err, user) {
if (!err && user) {
// only change data if submit supplied it
if (req.params.name) {
user.name = req.params.name;
}
if (req.params.username) {
user.username = req.params.username;
}
if (req.params.role) {
user.role = req.params.role;
}
gUser = user;
return next();
} else {
return next(new restify.MissingParameterError('ObjectId required.'));
}
});
}
/**
* Modify an existing user with matching id
*
* @param request
* @param response
* @param next method
*/
function putUser(req, res, next) {
gCheckCurrentPassword = true;
gCheckRoleRestriction = true;
gUser = {};
if (req.session && req.session.user) {
if (req.params.id == req.session.user) {
User.findById(req.params.id, function (err, user) {
if (!err) {
// only change data if submit supplied it
if (req.params.name) {
user.name = req.params.name;
}
if (req.params.username) {
user.username = req.params.username;
}
gUser = user;
return next();
} else {
return next(new restify.MissingParameterError('ObjectId required.'));
}
});
} else {
return next(new restify.MissingParameterError('User can only update their own information.'));
}
}
}
/* helper method validate the user changes */
function putUserValidations(req, res, next) {
// validations
if (req.params.email) {
if (!mail.validateEmail(req.params.email)) {
return next(new restify.MissingParameterError('Please enter a valid email address.'));
} else {
gUser.newEmail = req.params.email;
}
}
if (req.params.password) {
if (req.params.password != req.params.vPassword) {
return next(new restify.MissingParameterError('Password and Verify Password must match.'));
}
if (gCheckCurrentPassword && req.params.password && !req.params.cPassword) {
return next(new restify.MissingParameterError('You must enter your current password to verify.'));
}
if (req.params.cPassword) {
if (!gUser.authenticate(req.params.cPassword)) {
return next(new restify.MissingParameterError('You must enter your current password to verify.'));
}
gUser.tempPasswordFlag = true;
gUser.password = req.params.password;
}
}
return next();
}
/* validate change step 2 */
function putUserPostValidate(req, res, next) {
var user = gUser;
if (req.params.role) {
user.role = req.params.role;
if (gCheckRoleRestriction && user.role == 'Admin' && !config.openUserSignup) {
return next(new restify.MissingParameterError('You cannot change this user to an Administrator.'));
}
}
if (user.newEmail) {
var queryObj = {$or :[{'email': new RegExp('^'+user.newEmail+'$', 'i')}, {'newEmail': new RegExp('^'+user.newEmail+'$', 'i')}]};
User.count(queryObj, function (err, count) {
if (!err) {
if (count === 0) {
return next();
} else {
return next(new restify.InternalError('Email already in use, or you must validate your new email before making more changes to your account.'));
}
} else {
var errObj = err;
if (err.err) {
errObj = err.err;
}
return next(new restify.InternalError(errObj.message));
}
});
} else {
return next();
}
}
/** helper function to execute the save */
function saveUser(req, res, next) {
gUser.save(function (err) {
if (!err) {
// generate and send a verification code to swap email address
if (gUser.newEmail) {
// TODO When messaging is available, add a system message to the user telling them to check their email to verify the email address
mail.generateVerifyCodeUpdatedEmail(req, res, next, gUser);
}
res.send(gUser);
return next();
} else {
var errObj = err;
if (err.err) { errObj = err.err; }
return next(new restify.InternalError(errObj.message));
}
});
}
/**
* Delete an existing user with matching id
*
* @param request
* @param response
* @param next method
*/
function deleteUser(req, res, next) {
if (req.session && req.session.user) {
if (req.session.user == req.params.id) {
return next(new restify.InvalidArgumentError('User cannot delete themselves.'));
}
User.findById(req.params.id).remove(function (err) {
if (!err) {
// clean up archived status
var query = SystemMessageArchive.where( 'userId', req.params.id );
query.exec(function (err, sysMessageArr) {
});
var query2 = TermsAndConditionsArchive.where( 'userId', req.params.id );
query2.exec(function (err, sysMessageArr) {
});
res.send({});
return next();
} else {
return next(new restify.MissingParameterError('ObjectId required.'));
}
});
}
}
/**
* create or update an image for current user
*
* @param request
* @param response
* @param next method
*/
function putImage(req, res, next) {
if (req.session && req.session.user) {
if (req.params.id == req.session.user) {
var split = req.params.image.split('base64,');
var type = split[0].split('data:')[1];
type=type.substring(0,type.length-1);//获得文件类型如:image/jpeg
var data = new Buffer(split[1], 'base64');
User.findById(req.params.id, function (err, user) {
if (!err) {
gUser = user;
// only change data if submit supplied it
if(user.imageId ){// 已经存在图片,更新
Image.findById(user.imageId,function(err,image){
if (!err) {
image.img.data=data;
image.img.contentType=type;
gImage=image;
return next();
}else{
return next(new restify.MissingParameterError('Did not find the image with specified id.'));
}
});
}else{ //图片不存在,创建新图片,并更新User.imageId
gImage=new Image({img:{data:data,contentType:type}}); // 必须是png格式
return next();
}
} else {
return next(new restify.MissingParameterError('ObjectId required.'));
}
});
} else {
return next(new restify.MissingParameterError('User can only update their own information.'));
}
}
}
/**
* Save gImage to database
*
* @param request
* @param response
* @param next method
*/
function saveImage(req, res, next) {
gImage.save(function (err) {
if (!err) {
// 图片保存成功,则更新UserImageId属性
gUser.imageId=gImage._id;
return next();
} else {
var errObj = err;
if (err.err) { errObj = err.err; }
return next(errObj);
}
});
}
// Set up routes
// I looked at versioning via header. Lots of arguments pro/con regarding different types of versioning
// I like the embedded version (self documenting) so stuck with that instead
// apt.get({path: 'api/user:id', version: '1.0.0'}, getUser_V1);
// apt.get({path: 'api/user:id', version: '2.0.0'}, getUser_V2);
/**
* Search for users using the legal values in a userList object:
* name: { type: String, default: '' } // search name
* email: { type: String, default: '' } // search email
* username: { type: String, default: '' } // search username
* itemsPerPage: { type: Number, min: -1, default: -1} // number of records to return, -1 is unlimited
* pageNumber: { type: Number, min: -1, default: -1} // page number 1-N
* ascendingSortFlag: { type: Boolean, default: true }
* sortField: { type: String, default: '' }
*
* @param path Optional params: {}
* @param promised callback check authorization
* @param promised 2nd callback searches for users
*/
app.get('/api/v1/userlist', auth.requiresLogin, searchUsers);
// TODO Need to figure out the explicit REST URI
// confused, specified gets by id or username, seemed to be working
// then started getting 405 GET not allowed ??
// app.get('/api/v1/user/:id', getUserById);
// app.get('/api/v1/user/:username', getUserByUsername);
// so went back to a generic path
/**
* Search for users
*
* @param path
* @param promised callback check authorization
* @param promised 2nd callback gets user
*/
// This one is takes no args/params and is for the client to retrieve the authenticated user's information
app.get('/api/v1/user', auth.requiresLogin, getUser);
// get the user by id or username, only admin can do this
app.get('/api/v1/user/:search', auth.adminAccess, getUserByIdOrUsername);
/**
* Update user information
*
* @param path
* @param promised callback check authorization
* @param promised 2nd callback searches for users
*/
app.put('/api/v1/user', auth.requiresLogin, putUser, putUserValidations, putUserPostValidate, saveUser);
/**
* Administrator updating user information
*
* @param path
* @param promised callback check authorization
* @param promised 2nd callback searches for users
*/
app.put('/api/v1/admin/user', auth.adminAccess, putUserByAdmin, putUserValidations, putUserPostValidate, saveUser);
// Delete
// 405 ? app.del('/api/v1/admin/user/:id', deleteUser);
/**
* delete a user
*
* @param path
* @param promised callback check Administrator auth
* @param promised 2nd callback deletes
*/
app.del('/api/v1/admin/user', auth.adminAccess, deleteUser);
/**
* Update user image
*
* @param path
* @param promised callback check authorization
* @param promised 2nd callback searches for users
*/
app.put('/api/v1/image/user', auth.requiresLogin, putImage, saveImage,saveUser);
};
** 二、重构后:**
var mongoose = require(‘mongoose’) , User = mongoose.model(‘User’) , UserList = mongoose.model(‘UserList’) , VerifyCode = mongoose.model(‘VerifyCode’) , MessageThread = mongoose.model(‘MessageThread’) , SystemMessageArchive = mongoose.model(‘SystemMessageArchive’) , TermsAndConditionsArchive = mongoose.model(‘TermsAndConditionsArchive’) , ObjectId = mongoose.Types.ObjectId , restify = require(‘restify’) , config = require(‘…/config/config’).get() , config_path = config.root + ‘/config’ , auth = require(config_path + ‘/middlewares/authorization.js’) , Promise = require(‘bluebird’) , Image = mongoose.model(‘Image’);
var mail = {}; var gCheckCurrentPassword = true; var gCheckRoleRestriction = true;
module.exports = function (app, mailHelper) { mail = mailHelper; /** * This function is responsible for searching and returning multiple users * * @param request includes the fields to create a UserList object * @param response contains a populated UserList object * @param next method */ function searchUsers(req, res, next) { var userList = new UserList(req.params); var pageNum = userList.pageNumber; var itemsPerPage = userList.itemsPerPage;
if (itemsPerPage <= 0 || pageNum <= 0) {
itemsPerPage = 999999999999;
pageNum = 1;
}
pageNum = pageNum - 1;
User.count({}, function(err, count) {
if (!err) {
userList.pageCount = Math.ceil(count / itemsPerPage);
var sortStr = "";
if (userList.sortField !== null && userList.sortField !== '') {
if ('false' === userList.ascendingSortFlag) {
sortStr = "-" + userList.sortField;
} else {
sortStr = userList.sortField;
}
}
// NOTE This sort query is really inefficient, always queries the three columns
var query = User.find({ username: { $regex: userList.username, $options: 'imx' }, name: { $regex: userList.name, $options: 'imx' }, email: { $regex: userList.email, $options: 'imx' } });
// This returns partially populated objects preventing client sessions from seeing too much of the user's info
// if config settings are set to false, then these fields will be excluded
if (config.searchSettings.allowEmail) { query.select('email'); }
if (config.searchSettings.allowName) { query.select('name'); }
if (config.searchSettings.allowUsername) { query.select('username'); }
if (config.searchSettings.allowPhoneNumber) { query.select('phoneNumber');}
if (config.searchSettings.allowRole) {query.select('role');}
// If all selects are 'false' then all fields come back
// So explicity select the The Object Id so ONLY the Object Id plus any of the selected fields come back
query.select('_id');
if (sortStr.length > 0) {
query = query.sort(sortStr);
}
if (itemsPerPage > 0) {
query = query.limit(itemsPerPage).skip(itemsPerPage * pageNum);
}
query.exec(function(err, users) {
if (!err) {
userList.users = users;
// console.log(JSON.stringify(userList))
res.send(userList);
return next();
} else {
var errObj = err;
if (err.err) { errObj = err.err; }
return next(errObj);
}
});
} else {
var errObj = err;
if (err.err) { errObj = err.err; }
return next(errObj);
}
});
}
/**
* Gateway request routes to other functions based on params
* Search for a user by id or username
* if none given get the logged in user's information
*
* @param request can include an id, a username or no search param
* @param response contains a populated User object
* @param next method
*/
function getUser(req, res, next) {
if (req.session && req.session.user) {
id = req.session.user;
if (req.params.id) { id = req.params.id; }
User.findById(id, function (err, user) {
if (!err) {
res.send(user);
return next();
} else {
var errObj = err;
if (err.err) { errObj = err.err; }
return next(errObj);
}
});
} else {
return next(new restify.MissingParameterError('No search params sent.'));
}
}
/**
* Search for a user by id or username
*
* @param request path includes an id or username
* @param response contains a populated User object
* @param next method
*/
function getUserByIdOrUsername(req, res, next) {
var search = req.url;
search = search.substring(search.lastIndexOf("/")+1);
if (search !== null && search !== '') {
var query = User.where( 'username', new RegExp('^'+search+'$', 'i') );
query.findOne(function (err, user) {
if (!err) {
if (user) {
res.send(user);
} else {
User.findById(search, function (err, user) {
if (!err) {
res.send(user);
} else {
res.send(new restify.ResourceNotFoundError('User not found.'));
}
return next();
});
}
} else {
var errObj = err;
if (err.err) { errObj = err.err; }
return next(errObj);
}
});
} else {
return next(new restify.MissingParameterError('Username or ID required.'));
}
}
/**
* Admin: Modify an existing user
*
* @param request
* @param response
* @param next method
*/
function putUserByAdmin(req, res, next) {
gCheckCurrentPassword = false;
gCheckRoleRestriction = false;
return new Promise(function(resolve, reject){
User.findById(req.params.id, function (err, user) {
if (!err && user) {
// only change data if submit supplied it
if (req.params.name) {
user.name = req.params.name;
}
if (req.params.username) {
user.username = req.params.username;
}
if (req.params.role) {
user.role = req.params.role;
}
if (req.params.email) {
user.newEmail = req.params.email;
}
resolve(user);
} else {
reject ( new restify.MissingParameterError('ObjectId required.'));
}
});
}).then(function(user) {
// validations
if (req.params.password) {
if (req.params.password != req.params.vPassword) {
return Promise.reject ( new restify.MissingParameterError('Password and Verify Password must match.'));
}
if (gCheckCurrentPassword && req.params.password && !req.params.cPassword) {
return Promise.reject ( new restify.MissingParameterError('You must enter your current password to verify.'));
}
if (req.params.cPassword) {
if (!user.authenticate(req.params.cPassword)) {
return Promise.reject ( new restify.MissingParameterError('Your current password is invalid.'));
}
user.tempPasswordFlag = true;
user.password = req.params.password;
}
}
return user;
}).then(function(user) {
if (req.params.role) {
user.role = req.params.role;
if (gCheckRoleRestriction && user.role == 'Admin' && !config.openUserSignup) {
return Promise.reject ( new restify.MissingParameterError('You cannot change this user to an Administrator.'));
}
}
if (user.newEmail) {
var queryObj = {$or :[{'email': new RegExp('^'+user.newEmail+'$', 'i')}, {'newEmail': new RegExp('^'+user.newEmail+'$', 'i')}]};
return new Promise(function(resolve, reject) {
User.count(queryObj, function (err, count) {
if (!err) {
if (count === 0) {
resolve(user);
} else {
reject(new restify.MissingParameterError('Email already in use, or you must validate your new email before making more changes to your account.'));
}
} else {
var errObj = err;
if (err.err) {
errObj = err.err;
}
reject(new restify.InternalError(errObj.message));
}
});
});
} else {
return user;
}
}).then(function(user){
return new Promise(function(resolve, reject) {
user.save(function (err) {
if (!err) {
// generate and send a verification code to swap email address
if (user.newEmail) {
// TODO When messaging is available, add a system message to the user telling them to check their email to verify the email address
mail.generateVerifyCodeUpdatedEmail(req, res, next, user);
}
resolve(user);
} else {
var errObj = err;
if (err.err) { errObj = err.err; }
reject(errObj);
}
});
});
}).then(function(user){
res.send(user);
return next();
},function(reject){
return next(reject);
}).error(function(e){
return next(new restify.InternalError(e));
}).catch(function(e){
return next(new restify.InternalError(e));
});
}
/**
* Modify an existing user with matching id
*
* @param request
* @param response
* @param next method
*/
function putUser(req, res, next) {
gCheckCurrentPassword = true;
gCheckRoleRestriction = true;
return new Promise(function(resolve, reject){
if (req.params.id == req.session.user) {
User.findById(req.params.id, function (err, user) {
if (!err) {
// only change data if submit supplied it
if (req.params.name) {
user.name = req.params.name;
}
if (req.params.username) {
user.username = req.params.username;
}
if (req.params.email) {
user.newEmail = req.params.email;
}
resolve(user);
} else {
reject ( new restify.MissingParameterError('ObjectId required.'));
}
});
} else {
reject ( new restify.MissingParameterError('User can only update their own information.'));
}
}).then(function(user) {
// validations
if (req.params.password) {
if (req.params.password != req.params.vPassword) {
return Promise.reject ( new restify.MissingParameterError('Password and Verify Password must match.'));
}
if (gCheckCurrentPassword && req.params.password && !req.params.cPassword) {
return Promise.reject ( new restify.MissingParameterError('You must enter your current password to verify.'));
}
if (req.params.cPassword) {
if (!user.authenticate(req.params.cPassword)) {
return Promise.reject ( new restify.MissingParameterError('Your current password is invalid.'));
}
user.tempPasswordFlag = true;
user.password = req.params.password;
}
}
return user;
}).then(function(user) {
if (req.params.role) {
user.role = req.params.role;
if (gCheckRoleRestriction && user.role == 'Admin' && !config.openUserSignup) {
return Promise.reject ( new restify.MissingParameterError('You cannot change this user to an Administrator.'));
}
}
if (user.newEmail) {
var queryObj = {$or :[{'email': new RegExp('^'+user.newEmail+'$', 'i')}, {'newEmail': new RegExp('^'+user.newEmail+'$', 'i')}]};
return new Promise(function(resolve, reject) {
User.count(queryObj, function (err, count) {
if (!err) {
if (count === 0) {
resolve(user);
} else {
reject(new restify.MissingParameterError('Email already in use, or you must validate your new email before making more changes to your account.'));
}
} else {
var errObj = err;
if (err.err) {
errObj = err.err;
}
reject(new restify.InternalError(errObj.message));
}
});
});
} else {
return user;
}
}).then(function(user){
return new Promise(function(resolve, reject) {
user.save(function (err) {
if (!err) {
// generate and send a verification code to swap email address
if (user.newEmail) {
// TODO When messaging is available, add a system message to the user telling them to check their email to verify the email address
mail.generateVerifyCodeUpdatedEmail(req, res, next, user);
}
resolve(user);
} else {
var errObj = err;
if (err.err) { errObj = err.err; }
reject(errObj);
}
});
});
}).then(function(user){
res.send(user);
return next();
},function(reject){
return next(reject);
}).error(function(e){
return next(new restify.InternalError(e));
}).catch(function(e){
return next(new restify.InternalError(e));
});
}
/**
* Delete an existing user with matching id
*
* @param request
* @param response
* @param next method
*/
function deleteUser(req, res, next) {
if (req.session && req.session.user) {
if (req.session.user == req.params.id) {
return next(new restify.InvalidArgumentError('User cannot delete themselves.'));
}
User.findById(req.params.id, function (err, user) {
if (!err) {
if (user.imageId) { //如果有则删除对应的图片
Image.findById(user.imageId).remove(function (err) {
if (!err) {
// resolve({}); //图片删除成功
} else {
var errObj = err;
if (err.err) {
errObj = err.err;
}
// reject(errObj); //图片删除失败,指定图片不存在 或者其他原因,需要记入log
}
});
}
}
}).remove(function (err) {
if (!err) {
// clean up archived status
var query = SystemMessageArchive.where( 'userId', req.params.id );
query.exec(function (err, sysMessageArr) {
});
var query2 = TermsAndConditionsArchive.where( 'userId', req.params.id );
query2.exec(function (err, sysMessageArr) {
});
res.send({});
return next();
} else {
return next(new restify.MissingParameterError('ObjectId required.'));
}
});
}
}
/**
* create or update an image for current user
*
* @param request
* @param response
* @param next method
*/
function putImage(req, res, next) {
return new Promise(function(resolve, reject){
if (req.params.id == req.session.user) {
if (req.params.image) {
User.findById(req.params.id, function (err, user) {
if (!err) {
resolve(user);
} else {
reject (new restify.MissingParameterError('ObjectId required.'));
}
});
}else{
reject (new restify.MissingParameterError('Please update an image'));
}
} else {
reject (new restify.MissingParameterError('User can only update their own information.'));
}
}).then(function(user){
// only change data if submit supplied it
var split = req.params.image.split('base64,');
var type = split[0].split('data:')[1];
type = type.substring(0, type.length - 1);//获得文件类型如:image/jpeg
var data = new Buffer(split[1], 'base64');
if (user.imageId) {// 已经存在图片,更新
return new Promise(function(resolve, reject){
Image.findById(user.imageId, function (err, image) {
if (!err) {
image.img.data = data;
image.img.contentType = type;
resolve( {image:image,user:user});
} else {
reject (new restify.MissingParameterError('Did not find the image with specified id.'));
}
});
});
} else { //图片不存在,创建新图片,并更新User.imageId
var image = new Image({img: {data: data, contentType: type}}); // 必须是png格式
return {image:image,user:user};
}
}).then(function(collection){
return new Promise(function(resolve, reject){
collection.image.save(function (err) {
if (!err) {
// 图片保存成功,则更新UserImageId属性
collection.user.imageId=collection.image._id;
resolve(collection.user);
} else {
var errObj = err;
if (err.err) { errObj = err.err; }
reject(errObj);
}
});
});
}).then(function(user){
return new Promise(function(resolve, reject){
user.save(function (err) {
if (!err) {
resolve(user);
} else {
var errObj = err;
if (err.err) { errObj = err.err; }
reject(errObj);
}
});
});
}).then(function(user){
res.send(user);
return next();
},function(reject){
return next(reject);
}).error(function(e){
return next(new restify.InternalError(e));
}).catch(function(e){
return next(new restify.InternalError(e));
});
}
// Set up routes
// I looked at versioning via header. Lots of arguments pro/con regarding different types of versioning
// I like the embedded version (self documenting) so stuck with that instead
// apt.get({path: 'api/user:id', version: '1.0.0'}, getUser_V1);
// apt.get({path: 'api/user:id', version: '2.0.0'}, getUser_V2);
/**
* Search for users using the legal values in a userList object:
* name: { type: String, default: '' } // search name
* email: { type: String, default: '' } // search email
* username: { type: String, default: '' } // search username
* itemsPerPage: { type: Number, min: -1, default: -1} // number of records to return, -1 is unlimited
* pageNumber: { type: Number, min: -1, default: -1} // page number 1-N
* ascendingSortFlag: { type: Boolean, default: true }
* sortField: { type: String, default: '' }
*
* @param path Optional params: {}
* @param promised callback check authorization
* @param promised 2nd callback searches for users
*/
app.get('/api/v1/userlist', auth.requiresLogin, searchUsers);
// TODO Need to figure out the explicit REST URI
// confused, specified gets by id or username, seemed to be working
// then started getting 405 GET not allowed ??
// app.get('/api/v1/user/:id', getUserById);
// app.get('/api/v1/user/:username', getUserByUsername);
// so went back to a generic path
/**
* Search for users
*
* @param path
* @param promised callback check authorization
* @param promised 2nd callback gets user
*/
// This one is takes no args/params and is for the client to retrieve the authenticated user's information
app.get('/api/v1/user', auth.requiresLogin, getUser);
// get the user by id or username, only admin can do this
app.get('/api/v1/user/:search', auth.adminAccess, getUserByIdOrUsername);
/**
* Update user information
*
* @param path
* @param promised callback check authorization
* @param promised 2nd callback searches for users
*/
app.put('/api/v1/user', auth.requiresLogin, putUser);
/**
* Administrator updating user information
*
* @param path
* @param promised callback check authorization
* @param promised 2nd callback searches for users
*/
app.put('/api/v1/admin/user', auth.adminAccess, putUserByAdmin);
// Delete
// 405 ? app.del('/api/v1/admin/user/:id', deleteUser);
/**
* delete a user
*
* @param path
* @param promised callback check Administrator auth
* @param promised 2nd callback deletes
*/
app.del('/api/v1/admin/user', auth.adminAccess, deleteUser);
/**
* Update user image
*
* @param path
* @param promised callback check authorization
* @param promised 2nd callback searches for users
*/
app.put('/api/v1/image/user', auth.requiresLogin, putImage);
};