express-user
Advanced tools
Comparing version 1.0.0 to 1.0.1
@@ -186,14 +186,16 @@ //Copyright (c) 2015 Eric Vallee <eric_vallee2003@yahoo.ca> | ||
return(function(Req, Res, Next) { | ||
if(!(Req.session&&Req.session.User)) | ||
{ | ||
var Err = new Error(); | ||
Err.Source = "ExpressUser"; | ||
Err.Type = "NoSessionUser"; | ||
Next(Err); | ||
} | ||
else | ||
{ | ||
delete Req.session['User']; | ||
Next(); | ||
} | ||
GetRoutingVars(Req, Res, Next, function(RoutingVars) { | ||
if(!(Req.session&&Req.session.User)) | ||
{ | ||
var Err = new Error(); | ||
Err.Source = "ExpressUser"; | ||
Err.Type = "NoSessionUser"; | ||
Next(Err); | ||
} | ||
else | ||
{ | ||
delete Req.session['User']; | ||
Next(); | ||
} | ||
}); | ||
}); | ||
@@ -200,0 +202,0 @@ }; |
{ | ||
"name": "express-user", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"description": "Ressource Oriented Express Middleware to Manage Users.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
104
README.md
@@ -48,13 +48,41 @@ Express-User | ||
... | ||
The module acts as its constructor. | ||
TO DO | ||
It returns a router which can be passed as an argument to Express' app.use method. | ||
It's signature is: | ||
```javascript | ||
function(<UserStore>, <Options>); | ||
``` | ||
The 'UserStore' argument is a user store that is either the user-store library or another that has the same external API. | ||
'Options' is an object containing 2 properties: | ||
- 'Validator' | ||
The validator that performs the following for enabled routes: access control, input checks and sets the correct properties on the res.locals.ExpressUser object that allows express-user to do its work. | ||
- 'Responder' | ||
The responder that returns a response to the client (both status code and body) based on whether or not express-user or the validator threw an error route and what properties they defined on the res.locals.ExpressUser object. | ||
Session Route | ||
------------- | ||
... | ||
This method of the express-user module returns a route that can be passed to Express' app.use method. | ||
TO DO | ||
It's function is to keep a user's session synchronized with his/her profile. | ||
It's signature is: | ||
```javascript | ||
ExpressUser.SessionRoute(<UserStore>, <UniqueProperty>) | ||
``` | ||
The 'UserStore' argument is a user store that is either the user-store library or another that has the same external API. | ||
The 'UniqueProperty' argument is a string that is the name of a field that is present for all users and unique to each user. | ||
Example | ||
@@ -108,6 +136,8 @@ ------- | ||
... | ||
Both the Validator and the Responder that are passed to the express-user constructor are expected to be callable (ie, functions) and take a router (on which express-user defines its own routes) as their sole argument. | ||
TO DO | ||
From there, they can attach their own routes to interact with express-user and each other. | ||
The convention is that express-user calls the validator which sets its routes first. Then, express-user sets its own routes and finally, it calls the responder which sets its routes last. | ||
Intercomponent Communication: Input | ||
@@ -124,44 +154,44 @@ ----------------------------------- | ||
res.locals.User: should contain the fields of the new user | ||
res.locals.ExpressUser.User: should contain the fields of the new user | ||
- PATCH /User/Self and PATCH /User/:Field/:ID | ||
res.locals.User: should contain the fields identifying the user to modify | ||
res.locals.Update: Should contain the new values of fields that are to be modified | ||
res.locals.ExpressUser.User: should contain the fields identifying the user to modify | ||
res.locals.ExpressUser.Update: Should contain the new values of fields that are to be modified | ||
- DELETE /User/Self and DELETE /User/:Field/:ID | ||
res.locals.User: Should contain the fields identifying the user to delete | ||
res.locals.ExpressUser.User: Should contain the fields identifying the user to delete | ||
- GET /User/Self and GET /User/:Field/:ID | ||
res.locals.User: Should contain the fields identifying the user to get | ||
res.locals.ExpressUser.User: Should contain the fields identifying the user to get | ||
- PUT /Session/Self/User | ||
res.locals.User: Should contain the fields identifying the user to store in the session | ||
res.locals.ExpressUser.User: Should contain the fields identifying the user to store in the session | ||
- DELETE /Session/Self/User | ||
No input required. Will just delete the req.session.User, if present. | ||
No input required beyond the res.locals.ExpressUser object existing. Will just delete the req.session.User, if present. | ||
- GET /Users/:Field/:ID/Count | ||
res.locals.User: Should contain the fields that define the users you wish to count | ||
res.locals.ExpressUser.User: Should contain the fields that define the users you wish to count | ||
- PUT /User/Self/Memberships/:Membership and PUT /User/:Field/:ID/Memberships/:Membership | ||
res.locals.User: should contain the fields identifying the user to modify | ||
res.locals.Membership: the membership you wish to add | ||
res.locals.ExpressUser.User: should contain the fields identifying the user to modify | ||
res.locals.ExpressUser.Membership: the membership you wish to add | ||
- DELETE /User/Self/Memberships/:Membership and DELETE /User/:Field/:ID/Memberships/:Membership | ||
res.locals.User: should contain the fields identifying the user to modify | ||
res.locals.Membership: the membership you wish to remove | ||
res.locals.ExpressUser.User: should contain the fields identifying the user to modify | ||
res.locals.ExpressUser.Membership: the membership you wish to remove | ||
- POST /User/Self/Recovery/:SetField and POST /User/:Field/:ID/Recovery/:SetField | ||
res.locals.User: should contain the fields identifying the user to modify | ||
res.locals.Update: Should contain the new values of fields that are to be modified | ||
res.locals.ExpressUser.User: should contain the fields identifying the user to modify | ||
res.locals.ExpressUser.Update: Should contain the new values of fields that are to be modified | ||
Intercomponent Communication: Output | ||
@@ -176,3 +206,3 @@ ------------------------------------ | ||
If res.locals.Express is not defined by the validator, an error route will be triggered with Err.Source having the value of 'ExpressUser' and Err.Type having the value of 'NotValidated'. | ||
If res.locals.ExpressUser is not defined by the validator, an error route will be triggered with Err.Source having the value of 'ExpressUser' and Err.Type having the value of 'NotValidated'. | ||
@@ -185,3 +215,3 @@ If user-store returns an error that isn't a constraint error, an error route will be triggered and the error will be passed to it. | ||
If no error was encountered while manipulating the store, but the user was not inserted, an error route will be triggered with Err.Source having the value of 'ExpressUser' and Err.Type having the value of 'NoInsertion'. | ||
If no error was encountered while manipulating the store, but the user was not inserted, an error route will be triggered with Err.Source having the value of 'ExpressUser' and Err.Type having the value of 'NoInsertion'. | ||
@@ -194,10 +224,24 @@ Otherwise, no properties are set. | ||
If no error was encountered while manipulating the store, but the user was not inserted, an error route will be triggered with Err.Source having the value of 'ExpressUser' and Err.Type having the value of 'NoInsertion'. | ||
If no error was encountered while manipulating the store, but the user was not inserted, an error route will be triggered with Err.Source having the value of 'ExpressUser' and Err.Type having the value of 'NoUpdate'. | ||
Otherwise, no properties are set. | ||
- DELETE /User/Self and DELETE /User/:Field/:ID | ||
If no error was encountered while manipulatinbg the store, but no user was found to update, an error route will be triggered with Err.Source having the value of 'ExpressUser' and Err.Type having the value of 'NoDelete'. | ||
Otherwise, no properties are set. | ||
- GET /User/Self and GET /User/:Field/:ID | ||
If no error was encountered while manipulating the store, but the user was not found, an error route will be triggered with Err.Source having the value of 'ExpressUser' and Err.Type having the value of 'NoUser'. | ||
Otherwise, the retrieved user is stored in the property res.locals.ExpressUser.Result. | ||
... | ||
- Further Note: that whatever is passed to express-user by the validator is also passed to the responder and if an error is encountered by the validator, it can bypass express-user entirely and go straight to the responder by triggering an error route. | ||
- Further Note | ||
Whatever is passed to express-user by the validator is also passed to the responder and if an error is encountered by the validator, it can bypass express-user entirely and go straight to the responder by triggering an error route. | ||
TO FINISH | ||
@@ -286,6 +330,12 @@ | ||
1.0.1 | ||
----- | ||
- Added check to make sure DELETE /Session/Self/User goes through the validator | ||
- Finished tests | ||
- Corrected errors in documentation and added more to it. | ||
1.0.0 | ||
----- | ||
- Fixed a bug where session existence check wouldn't be performed for some of the Self routes | ||
- Moved access control on admin URLs to validator and removed Express-Access-Control as a dependency | ||
@@ -296,3 +346,3 @@ - Moved connection security verification to validator | ||
- Added dev dependencies to run unit tests | ||
- Started unit tests | ||
- Started tests | ||
- Started final version of documentation | ||
@@ -299,0 +349,0 @@ - Updated dev dependency of user-store to version 1.3.0 |
//Copyright (c) 2015 Eric Vallee <eric_vallee2003@yahoo.ca> | ||
//MIT License: https://raw.githubusercontent.com/Magnitus-/ExpressUser/master/License.txt | ||
var Nimble = require('nimble'); | ||
var Express = require('express'); | ||
@@ -79,3 +80,3 @@ var Http = require('http'); | ||
{ | ||
Res.json(Req.session.User); | ||
Res.status(200).json(Req.session.User); | ||
} | ||
@@ -352,3 +353,3 @@ else | ||
'Memberships': function(Test) { | ||
Test.expect(2); | ||
Test.expect(10); | ||
var Requester = new RequestHandler(); | ||
@@ -360,6 +361,47 @@ Requester.Request('PUT', '/User/Self/Memberships/Banned', function(Status, Body) { | ||
Requester.Request('POST', '/Users', function(Status, Body) { | ||
//Remove non-existent membership of user | ||
//Add membership to user | ||
//Remove membership to user | ||
Test.done(); | ||
Requester.Request('DELETE', '/User/Self/Memberships/Banned', function(Status, Body) { | ||
//Might eventually want to change it to report an error like NoMembership | ||
Test.ok(Status===200, "Confirming that deleting non-existent membership on route DELETE /User/Self/Memberships/:Membership works as expected."); | ||
Requester.Request('DELETE', '/User/Username/SomeName/Memberships/Banned', function(Status, Body) { | ||
//Might eventually want to change it to report an error like NoMembership | ||
Test.ok(Status===200, "Confirming that deleting non-existent membership on route DELETE /User/:Field/:ID/Memberships/:Membership works as expected."); | ||
Requester.Request('PUT', '/User/Self/Memberships/Banned1', function(Status, Body) { | ||
Context['UserStore'].Get({'Username': 'SomeName'}, function(Err, User) { | ||
Test.ok(Status===200&&User.Memberships.some(function(Item) { | ||
return Item==="Banned1"; | ||
}), "Confirming that route PUT /User/Self/Memberships/:Membership works for adding memberships"); | ||
Requester.Request('PUT', '/User/Username/SomeName/Memberships/Banned2', function(Status, Body) { | ||
Context['UserStore'].Get({'Username': 'SomeName'}, function(Err, User) { | ||
Test.ok(Status===200&&User.Memberships.some(function(Item) { | ||
return Item==="Banned2"; | ||
}), "Confirming that route PUT /User/:Field/:ID/Memberships/:Membership works for adding memberships"); | ||
Requester.Request('PUT', '/User/Self/Memberships/Banned1', function(Status, Body) { | ||
//Might eventually want to change it to report an error like MembershipExists | ||
Test.ok(Status===200, "Confirming that inserting an already existing membership in route PUT /User/Self/Memberships/:Membership behaves as expected."); | ||
Requester.Request('PUT', '/User/Username/SomeName/Memberships/Banned1', function(Status, Body) { | ||
//Might eventually want to change it to report an error like MembershipExists | ||
Test.ok(Status===200, "Confirming that inserting an already existing membership in route PUT /User/:Field/:ID/Memberships/:Membership behaves as expected."); | ||
Requester.Request('DELETE', '/User/Self/Memberships/Banned1', function(Status, Body) { | ||
Context['UserStore'].Get({'Username': 'SomeName'}, function(Err, User) { | ||
Test.ok(Status===200&&User.Memberships.every(function(Item) { | ||
return Item!=="Banned1"; | ||
}), "Confirming that route DELETE /User/Self/Memberships/:Membership works for deleting memberships"); | ||
Requester.Request('DELETE', '/User/Username/SomeName/Memberships/Banned2', function(Status, Body) { | ||
Context['UserStore'].Get({'Username': 'SomeName'}, function(Err, User) { | ||
Test.ok(Status===200&&User.Memberships.every(function(Item) { | ||
return Item!=="Banned2"; | ||
}), "Confirming that route DELETE /User/:Field/:ID/Memberships/:Membership works for deleting memberships"); | ||
Test.done(); | ||
}); | ||
}, {'User': {'Username': 'SomeName'}, 'Membership': 'Banned2'}, true); | ||
}); | ||
}, {'User': {'Username': 'SomeName'}, 'Membership': 'Banned1'}, true); | ||
}, {'User': {'Username': 'SomeName'}, 'Membership': 'Banned1'}, true); | ||
}, {'User': {'Username': 'SomeName'}, 'Membership': 'Banned1'}, true); | ||
}); | ||
}, {'User': {'Username': 'SomeName'}, 'Membership': 'Banned2'}, true); | ||
}); | ||
}, {'User': {'Username': 'SomeName'}, 'Membership': 'Banned1'}, true); | ||
}, {'User': {'Username': 'SomeName'}, 'Membership': 'Banned'}, true); | ||
}, {'User': {'Username': 'SomeName'}, 'Membership': 'Banned'}, true); | ||
}, {'User': {'Username': 'SomeName', 'Email': 'SomeEmail@Email.com', 'Password': 'Qwerty!'}}, false); | ||
@@ -370,17 +412,51 @@ }, {'User': {'Username': 'SomeName'}, 'Membership': 'Banned'}, true); | ||
'SessionSync': function(Test) { | ||
Test.expect(0); | ||
//Create User | ||
//Login | ||
//Modify user | ||
//Check session | ||
//Delete user | ||
//Check session | ||
Test.done(); | ||
Test.expect(2); | ||
var Requester = new RequestHandler(); | ||
Requester.Request('POST', '/Users', function(Status, Body) { | ||
Requester.Request('PUT', '/Session/Self/User', function(Status, Body) { | ||
Requester.Request('PATCH', '/User/Username/SomeName', function(Status, Body) { | ||
Requester.Request('GET', '/Session/Self/User', function(Status, Body) { | ||
Test.ok(Status===200 && Body.Username && Body.Username === 'SomeName2' && Body.Email && Body.Email === 'SomeEmail2@Email.com', "Confirming that sessions are kept in sync during profile updates"); | ||
Requester.Request('DELETE', '/User/Username/SomeName', function(Status, Body) { | ||
Requester.Request('GET', '/Session/Self/User', function(Status, Body) { | ||
Test.ok(Status===400, "Confirming that sessions are kept in sync during profile deletions"); | ||
Test.done(); | ||
}, null, true); | ||
}, {'User': {'Username': 'SomeName2'}}, false); | ||
}, null, true); | ||
}, {'User': {'Username': 'SomeName'}, 'Update': {'Username': 'SomeName2', 'Email': 'SomeEmail2@Email.com'}}, false); | ||
}, {'User': {'Username': 'SomeName'}}, false); | ||
}, {'User': {'Username': 'SomeName', 'Email': 'SomeEmail@Email.com', 'Password': 'Qwerty!'}}, false); | ||
}, | ||
'ValidationCheck': function(Test) { | ||
Test.expect(0); | ||
//Check all routes without session res.locals.ExpressUser | ||
Test.done(); | ||
var Routes = [['POST', '/Users'], | ||
['PATCH', '/User/Self'], | ||
['DELETE', '/User/Self'], | ||
['GET', '/User/Self'], | ||
['PATCH', '/User/Username/Test'], | ||
['DELETE', '/User/Username/Test'], | ||
['GET', '/User/Username/Test'], | ||
['PUT', '/User/Self/Memberships/Test'], | ||
['DELETE', '/User/Self/Memberships/Test'], | ||
['PUT', '/User/Username/Test/Memberships/Test'], | ||
['DELETE', '/User/Username/Test/Memberships/Test'], | ||
['POST', '/User/Self/Recovery/Test'], | ||
['POST', '/User/Username/Test/Recovery/Test'], | ||
['PUT', '/Session/Self/User'], | ||
['DELETE', '/Session/Self/User'], | ||
['GET', '/Users/Username/SomeName/Count']]; | ||
Test.expect(Routes.length); | ||
var Requester = new RequestHandler(); | ||
var Calls = []; | ||
Routes.forEach(function(Route) { | ||
Calls.push(function(Callback) { | ||
Requester.Request(Route[0], Route[1], function(Status, Body) { | ||
Test.ok(Status===400 && Body.ErrType && Body.ErrType === "NotValidated", "Confirming validation check is performed on route "+Route[0]+" "+Route[1]+"."); | ||
Callback(); | ||
}, null, true); | ||
}); | ||
}); | ||
Nimble.series(Calls, function(Err) {Test.done();}); | ||
} | ||
}; | ||
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
134324
743
443