user management pack for express framework app.
you can use this package in typescript too.
npm install umpack-express -S -E
- accessTokenExpiresIn time span string description
var umpack = require('umpack-express')({
mongodbConnectionString: 'mongodb://172.17.7.92:27017/umpack',
accessTokenSecret: 'myrandomstring',
passwordHashSecret: 'mypasswordsecret',
accessTokenExpiresIn: '1m',
cookieAccessTokenName: 'accessToken',
passwordResetData: {
smtpData: {
host: 'smtp host',
port: 'smtp port. optional',
user: 'username for logging into smtp',
password: 'password for logging into smtp',
timeout: 5000, // number of milliseconds to wait. default 5000
ssl: false //boolean or object with fields: key, ca, cert. default false
},
senderEmail: '[email protected]',
resetKeyExpiresIn: '2h', //password reset key expiration
passwordMessageFunction: function (key /*password reset key*/) {
return 'message to send. use key. for example: http://example.com?key=' + key;
},
passwordWrongEmailInstruction: function (clientIp) {
return 'someone with ip: ' + clientIp + ' requested password reset on the site example.com'; //message to send to input email, when user with input email does not exist
}
},
passwordResetPhoneData: {
resetKeyExpiresIn: '2h',
sendResetKey: function (phone, resetKey) {
// send sms to the phone.
// return promise or nothing.
}
},
deviceControl: false, // default false. if it is true, user's devices access is controlled
userNameCaseSensitive: false, // if it is true, userName is case sensitive, if false - it is not.
logger: loggerObject, // loggerObject should have methods: error, warn, info, debug and trace. it should have logging level restriction itself.
// by default logger field is logger object that logs only warnings and errors.
activateOnSignup: false, // if true, when user signs up account doesn't need to activate
userDefaultRole: 'user' //not works if activateOnSignup is false. on signup user has this role
});
//.....
app.use('/um', umpack.router);
//.....
POST : {baseurl}/login
request - data/body : {
userName: 'user',
email: '[email protected]', // userName or email is required
password: 'userpassword',
deviceToken: 'device token' //required if device control is enabled
}
response - 'user access token'
POST : {baseurl}/signup
request - data/body : {
userName: 'user', //required
password: 'userpassword', //required
firstName: 'first name',
lastName: 'last name',
email: '[email protected]',
phone: '123456',
address: 'usa/de',
additionalInfo: 'user additional info',
}
response - { success: true, message: 'Thanks for signUp' }
headers:{'authorization': 'user access token'}
POST : {baseurl}/resetpass
request - data/body : {
userName: 'admin',
oldPassword: 'admin',
newPassword: '123456789'
}
response - { success: true, message: 'Password Reset Done' }
GET : {baseurl}/users
response - {
id: '34jhb5jh45b6',
userName: 'user name',
isActivated: 'true/false',
roles: ['admin','provider','root','etc.']
}
GET : {baseurl}/roles
response - [{name:'admin', description: ''},{name:'user', description: ''},{name:'provider', description: ''},{name:'root', description: ''},{name:'organizationUser', description: ''}]
POST : {baseurl}/updateUserStatus
request - data/body : {
id: 'user id',
isActivated: true/false,
}
response - {
id: 'user id',
isActivated: 'true/false',
userName: 'user name',
roles: ['admin','provider','root','sys','etc.']
}
POST : {baseurl}/updateUserRoles
request - data/body : {
userId: 'user id',
roleName: 'admin',
enable: 'true/false'
}
response - {
id: 'user id',
isActivated: 'true/false',
userName: 'user name',
roles: ['admin','provider','root','sys','etc.']
}
GET : {baseurl}/users/{userId}
response - {
id: '',
userName: 'name',
firstName: 'firstName',
lastName: 'lastName',
email: '[email protected]',
phone: '',
address: '',
additionalInfo: '',
isActivated: true/false,
roles: ['user', 'admin'],
metaData: {}
}
GET : {baseurl}/users/{userName}/full
response - {
id: '',
userName: 'name',
firstName: 'firstName',
lastName: 'lastName',
email: '[email protected]',
phone: '',
address: '',
additionalInfo: '',
isActivated: true/false,
roles: ['user', 'admin'],
metaData: {}
}
PUT : {baseurl}/users/{userId}/username
request - data/body : {
userName: 'userName'
}
response - {success : true}
PUT : {baseurl}/users/{userId}/info
request - data/body : {
firstName: '',
lastName: '',
email: '',
phone: '',
address: '',
additionalInfo: ''
}
response - {success : true}
DELETE : {baseurl}/users/{userId}
response - {
success: true
}
POST : {baseurl}/users/passwordResetRequest
request - data/body : {
email: '[email protected]'
}
response - {success : true}
instructions are sent to the email
POST : {baseurl}/users/passwordReset
request - data/body : {
resetKey: '', //password reset key sent to the email
newPassword: 'password'
}
response - {success : true}
POST : {baseurl}/users/{userName}/passwordResetRequestByPhone
request - data/body : {} //empty object
response - {success : true}
password reset key is sent to the user phone
POST : {baseurl}/users/{userName}/passwordResetByPhone
request - data/body : {
resetKey: '', //key sent to the phone
newPassword: 'password'
}
response - {success : true}
GET : {baseurl}/users/{userName}/devices
response - [
{
deviceToken: 'token',
canAccess: true/false,
lastUsageDate: new Date() //last usage date
}
]
GET : {baseurl}/users/{userName}/devices/permitted
response - [
{
deviceToken: 'token',
canAccess: true,
lastUsageDate: new Date() //last usage date
}
]
POST : {baseurl}/users/{userName}/devices/access
request - data/body : {
deviceToken: 'device token'
}
response - { success: true }
POST : {baseurl}/users/{userName}/devices/restriction
request - data/body : {
deviceToken: 'token'
}
response - { success: true }
GET : {baseurl}/metadata
response - metadata object
PUT : {baseurl}/metadata
request - data/body : metadata object
response - { success: true, message: 'metadata updated' }
PUT : {baseurl}/metadata/{fieldName}
request - data/body : {
value: 'some value of any type'
}
response - { success: true, message: 'metadata key: {fieldName} updated' }
POST : {baseurl}/roles
request - data/body : {
name: 'admin',
description: 'description'
}
response - { success: true }
GET : {baseurl}/roles/{roleName}
response - {
name: 'admin',
description: 'description',
actions: [{
id: '464sadfsdf6',
pattern: '/api/*',
name: 'action name',
verbGet: true,
verbPost: true,
verbPut: true,
verbDelete: true,
verbHead: true
}]
}
PUT : {baseurl}/roles/{roleName}
request - data/body : {
name: 'role name',
description: 'role description'
}
response - { success: true }
DELETE : {baseurl}/roles/{roleName}
response: { success: true }
POST : {baseurl}/roles/{roleName}/actions
request - data/body : {
pattern: '/api/*',
name: 'name',
verbGet: true,
verbPost: true,
verbPut: true,
verbDelete: true,
verbHead: true
}
response - {
success: true,
actionId: 'action id'
}
PUT : {baseurl}/roles/{roleName}/actions/{actionId}
request - data/body : {
pattern: '/api/something',
name: 'name',
verbGet: true,
verbPost: true,
verbPut: true,
verbDelete: false,
verbHead: false
}
response - { success : true }
DELETE : {baseurl}/roles/{roleName}/actions/{actionId}
response - { success: true }
- saves root user and admin role if they do not exist.
- if device control is enabled, it saves one permitted device of the root for administration.
POST : {baseurl}/initialization
request - data/body : {
umBaseUrl: '/um',
deviceToken: 'token', //not required if device control is disabled
password: '123' // password for root user. optional. if it isn't passed new password is generated randomly.
}
response - {
success: true,
password: 'password' //generated or parameter password for root user
}
it is used for validating access token
HEAD : {baseurl}/authorization
- Every response with status 400/401 has also internal status for example :
{message:User Is Not Activated, internalStatus:601}
- All internal status
{ code: 601, message: 'User Is Not Activated' }
{ code: 602, message: 'User Name Or Email Already Exists' }
{ code: 603, message: 'Wrong User Name Or Password' }
{ code: 604, message: 'Wrong Password' }
{ code: 605, message: 'User Does Not Exists' }
{ code: 606, message: 'Can\'t Find JWT Token Inside The Request Header' }
{ code: 607, message: 'Invalid JWT Token' }
{ code: 608, message: 'Token Expired' }
{ code: 609, message: 'Access Denied' }
{ code: 701, message: 'Wrong Role Name' }
{ code: 702, message: 'Role Already Exists'}
{ code: 703, message: 'Invalid Action Pattern'}
{ code: 704, message: 'Action Pattern Already Exists'}
{ code: 800, message: 'password reset key is expired' }
{ code: 801, message: 'password reset key is invalid' }
{ code: 802, message: 'password reset by email is not supported' }
{ code: 803, message: 'password reset by phone is not supported' }
{ code: 804, message: 'invalid phone number' }
{ code: 805, message: 'invalid device token' }
{ code: 806, message: 'access is denied for your device' }
{ code: 807, message: 'devices control is not supported' }
{ code: 900, message: 'invalid userName' }
{ code: 901, message: 'invalid email' }
- if user is not authorized then response status is 401
- if user has no access right then response status is 403
- if device control is enabled and user's device has no access right then response status is 403 too
- if response status is 401 or 403 response body is object with error message and internalStatus
{ message: err.message, internalStatus: err.internalStatus }
var umpack = require('./umpack')();
router.get('/', umpack.isAuthorized, function(req, res, next) {
return res.send('your resources');
});
- if you need to add additional info, attribute, etc. you can use user's metadata to manage it.
- metadata is custom field/subdocument of user doc which can contains any kind of object.
- example :
var organizationInfo = {
organizationId: '2222',
organiationName: 'bbbbb',
organizationTaxCode: '777777'
};
umpack.updateUserMetaData('admin', organizationInfo)
.then(function(result) {
console.log(result);
})
.catch(function(err) {
console.log(err.message);
});
router.get('/usermetadata', function(req, res, next) {
umpack.getUserMetaDataByUserName('admin')
.then(function(result) {
return res.send(result);
})
.catch(function(err) {
console.log(err.message);
return res.send({ message: err.message });
});
});
router.get('/usermetadata', function(req, res, next) {
umpack.getUserMetaDataByRequest(req)
.then(function(result) {
return res.send(result);
})
.catch(function(err) {
//console.log(err.message);
return res.status(400).send({ message: err.message });
});
});
router.get('/usersbymeta', function(req, res, next) {
umpack.filterUsersByMetaData('organizationId', '2222')
.then(function(users) {
res.send(users);
})
.catch(function(err) {
return res.status(400).send({ message: err.message });
});
});
router.get('/userFullName', function(req, res, next) {
umpack.getFullName('admin')
.then(function(fullName) {
res.send(fullName);
})
.catch(function(err) {
return res.status(400).send({ message: err.message });
});
});
router.get('/userRoles', function(req, res, next) {
umpack.getUserRolesByUserName('admin')
.then(function(result) {
res.send(result);
})
.catch(function(err) {
return res.status(400).send({ message: err.message });
});
});
router.get('/userRoles', function(req, res, next) {
umpack.getUserRolesFromRequest(req)
.then(function(result) {
res.send(result);
})
.catch(function(err) {
return res.status(400).send({ message: err.message });
});
});
router.get('/usersbyrole', function(req, res, next) {
umpack.filterUsersByRole('user')
.then(function(result) {
res.send(result);
})
.catch(function(err) {
return res.status(400).send({ message: err.message });
});
});
router.get('/fullUserObject', function(req, res, next) {
umpack.getFullUserObject('admin')
.then(function(result) {
res.send(result);
})
.catch(function(err) {
return res.status(400).send({ message: err.message });
});
});
router.get('/fullUserObject', function(req, res, next) {
umpack.getFullUserObjectFromRequest(req)
.then(function(result) {
res.send(result);
})
.catch(function(err) {
return res.status(400).send({ message: err.message });
});
});
- saves root user and admin role if they do not exist.
- if device control is enabled, it saves one permitted device of the root for administration.
router.get('/initialization', function(req, res, next) {
//password is optional
umpack.init(req.body.umBaseUrl, req.body.password, req.body.deviceToken) // if deviceControl is disabled deviceToken is not required else it is required
.then(function(password) {
// randomly generated password or passed parameter password for the root user is returned
res.send(password);
})
.catch(function(err) {
return res.status(400).send({ message: err.message });
});
});
- saves root user and admin role if they do not exist.
- saved admin role has permission of everything.
- if device control is enabled, it saves one permitted device of the root for administration.
router.get('/initialization', function(req, res, next) {
//password is optional
umpack.initWithFullAccess(req.body.password, req.body.deviceToken) // if deviceControl is disabled deviceToken is not required else it is required
.then(function(password) {
// randomly generated password or passed parameter password for the root user is returned
res.send(password);
})
.catch(function(err) {
return res.status(400).send({ message: err.message });
});
});
router.get('/userRoles', isAuthorized, function(req, res, next) {
// Request Must Have authorization Header
umpack.getUserNameFromRequest(req)
.then(function(userName) {
res.send(userName);
})
.catch(function(err) {
return res.status(400).send({ message: err.message });
});
});
router.get('/signup', function(req, res, next) {
// {
// userName: 'user',
// password: 'userpassword',
// firstName: 'first name',
// lastName: 'last name',
// email: '[email protected]',
// phone: '123456',
// address: 'usa/de',
// additionalInfo: 'user additional info',
// }
// parameters are exactly same as in /{baseurl}/signup
umpack.signup(req.body)
.then(function() {
res.send({success: true});
})
.catch(function(err) {
return res.status(400).send({ message: err.message });
});
});