auth 0.0.9 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,61 +0,0 @@
1
- var db;
2
-
3
- //how do we handle permissions for super users?
4
- //simple answer is - user permissions have root privileges - there's only ONE root
5
- //level, which is the user itself. a "super" tag maybe applied, but after that, privileges
6
- //
7
-
8
- var user1 = user(),
9
-
10
- //user2 can be a registered user, or it can be a
11
- //public user that's automatically logged in. This could be the
12
- //default option.
13
- user2 = user();
14
-
15
-
16
- //this sort of thing isn't necessary since authentication would be bubbled
17
- //up to the top-most item. in which case, "comments", is owned by post. "Post" is owned
18
- //by user. The authentication would work as follows:
19
- //auth -> posts -> comments
20
- db.collection("post").owns("comments");
21
-
22
-
23
- //in this case, post is owned by community. HOWEVER, "post" can still be shared with
24
- //other users. this use case just follows a different authentication path.
25
- //auth -> community -> post -> comments
26
- //where the post looks to see if the community is its owner - in which case
27
- //modifications can be made against the given post. Before that, community
28
- //checks if a user is the given owner.
29
- //how do we give permissions for the owner of given community to make changes
30
- //to any post? We could modify the query such that if the owner is of the community,
31
- //q = { community: _id }, but if the owner is of the poist, then q = { u: u, p: p }
32
- //In other words, think of this as a faster method short of adding super users in each item which... fndskfsfklds
33
- db.collection("community").owns("post").owns("");
34
-
35
-
36
- //here's a different use case. This would require watching "repositories" for any
37
- //NEW repository that comes in, instead of one shot.
38
- db.collection("repositories").owns("repository");
39
-
40
-
41
- //1 queue job
42
- //2 check if u1 owns someId
43
- //3. add user2 under "owners" in the given item
44
- user1.shareItem("someId", user2, function() {
45
- //on share
46
- });
47
-
48
- //1 add job that gets triggered when a new repository is inserted
49
- //2. follow step "shareItem" when a new item is added
50
- user1.shareCollection("repositories", user2, function() {
51
-
52
- });
53
-
54
- //takes permissions away from the given user
55
- user1.takeAwayItem("someId", user2);
56
- //cron.addJob({ from: user1, update: { $set: permissions: [] }}, to: user2 })
57
-
58
-
59
- //takes away privileges for a particular user
60
- user1.takeAwayCollection("repositories", user2);
61
- //cron.removeJob({ from: user1, collection: "repositories", to: user2 })
package/lib/access.js DELETED
@@ -1,18 +0,0 @@
1
-
2
- var all = [];
3
-
4
- ["GET", "POST", "PUT", "DELETE"].forEach(function(method) {
5
- all.push(exports[method] = method);
6
- });
7
-
8
- //don't want the array to be altered
9
- exports.all = function(isSuper) {
10
- var acc = all.concat();
11
- if(isSuper) {
12
- acc.push(exports.SUPER);
13
- }
14
- return acc;
15
- }
16
-
17
- //outside of all - must be manually set.
18
- exports.SUPER = "SUPER";
@@ -1,31 +0,0 @@
1
- var vine = require("vine"),
2
- comerr = require("comerr");
3
-
4
- exports.plugin = function(auth) {
5
-
6
- var Account = auth.Account;
7
-
8
- return {
9
- authCheckpoint: function(req, res, next) {
10
- if(req.session.token) {
11
- q = { token: req.session.token };
12
- } else {
13
- q = req.query.token || req.query.email ? req.query : req.body || req.query;
14
- }
15
-
16
- Account.login(q, function(err, account) {
17
-
18
- if(err) {
19
-
20
- if(/\.json$/.test(req.path)) return res.send(vine.error(new comerr.Unauthorized("you must be logged in to view this page")));
21
-
22
- return res.redirect("/login?redirect_to=" + encodeURIComponent(req.originalUrl));
23
- // return res.send(vine.error(err));
24
- }
25
- req.account = account;
26
- next();
27
- });
28
- },
29
-
30
- }
31
- }
@@ -1,152 +0,0 @@
1
- var step = require("step"),
2
- vine = require("vine"),
3
- reqOutcome = require("./reqOutcome"),
4
- dust = require("dustjs-linkedin"),
5
- step = require("step"),
6
- fs = require("fs");
7
-
8
- exports.plugin = function(httpServer, emailer, auth, loader) {
9
-
10
- var Account = auth.Account,
11
- InvitedAccount = auth.InvitedAccount,
12
- privateMode = loader.params("privateMode") || false,
13
- domain = loader.params("domain"),
14
- serviceName = loader.params("serviceName");
15
-
16
- eval(dust.compile(fs.readFileSync(loader.params("http.validateEmailTpl"), "utf8"), "validateEmailTpl"));
17
-
18
-
19
- function getToken(req, res, account, render, redirect) {
20
- account.getMainToken(function(err, token) {
21
-
22
- req.session.token = token.key;
23
-
24
- if(!render) {
25
- if(err) {
26
- return res.send(vine.error(err));
27
- } else {
28
- var obj = account.toObject();
29
- delete obj.password; //why is this still here??
30
- obj.token = token;
31
- res.send(vine.result(obj));
32
- }
33
- return;
34
- }
35
-
36
- if(err) return res.render(render, {
37
- error: err.message
38
- });
39
-
40
-
41
- res.redirect(redirect || req.query.redirect_to || loader.params("http.loginRedirect") || "/");
42
- });
43
- }
44
-
45
- httpServer.get("/account.json", auth.middleware.authCheckpoint, function(req, res) {
46
- getToken(req, res, req.account);
47
- });
48
-
49
- httpServer.post("/account.json", function(req, res) {
50
- Account.signup(req.body, function(err, account) {
51
- if(err) return res.send(vine.error(err));
52
- getToken(req, res, account);
53
- })
54
- })
55
-
56
-
57
- httpServer.get("/login", function(req, res) {
58
-
59
- if(!req.secure && req.headers["x-forwarded-proto"] != "https" && !/127.0.0.1|localhost/.test(String(req.headers.host))) {
60
- return res.redirect("https://" + (req.headers.host || loader.params("domain") || loader.params("http.host")) + req.url);
61
- }
62
-
63
- res.render("login", {
64
- redirect_to: req.query.redirect_to
65
- });
66
- });
67
-
68
- httpServer.get("/logout", function(req, res) {
69
- delete req.session.token;
70
- res.redirect("/login");
71
- });
72
-
73
- httpServer.post("/login", function(req, res) {
74
- Account.login(req.body, reqOutcome(req, res, "login").success(function(acc) {
75
- getToken(req, res, acc, "login");
76
- }));
77
- });
78
-
79
- httpServer.get("/signup", function(req, res) {
80
- res.render("signup");
81
- });
82
-
83
-
84
- httpServer.get("/validate_account", function(req, res) {
85
- var on = reqOutcome(req, res, "validate_account");
86
-
87
- step(
88
- function() {
89
- Account.findOne({ _id: req.query.account }, this);
90
- },
91
- on.success(function(account) {
92
- if(!account) return on(new Error("account does not exist"));
93
- // if(account.validated) return on(new Error("this account has already been validated"));
94
-
95
- if(account.validationKey != req.query.validationKey) return on(new Error("incorrect validation key"));
96
- account.validatedAt = new Date();
97
- account.validated = true;
98
- account.save(this);
99
- Account.emit("validated", account);
100
- }),
101
- on.success(function(account) {
102
- res.render("validate_account", {
103
- account: account
104
- });
105
- })
106
- );
107
- });
108
-
109
- Account.on("signup", function(acc) {
110
- step(
111
- function() {
112
- dust.render("validateEmailTpl", { validationKey: acc.validationKey, accountId: acc._id }, this);
113
- },
114
- function(err, tpl) {
115
- if(err) return console.error(err);
116
- var next = this;
117
- console.log("sending validation email");
118
- emailer.send({
119
- to: acc.email,
120
- subject: "Validate Account",
121
- htmlBody: tpl
122
- }, function(err) {
123
- if(err) console.error(err)
124
- next();
125
- });
126
-
127
- },
128
- function() {
129
-
130
- }
131
- );
132
- });
133
-
134
-
135
- httpServer.post("/signup", function(req, res) {
136
-
137
- console.log("signing up")
138
- var on = reqOutcome(req, res, "signup");
139
-
140
- /*if(privateMode && !req.body.referredBy) {
141
- on(new Error("You cannot signup unless you've been invited by someone"));
142
- }*/
143
-
144
- Account.signup(req.body, reqOutcome(req, res, "signup").success(function(acc) {
145
- getToken(req, res, acc, "signup", loader.params("http.signupRedirect"));
146
- }));
147
-
148
- });
149
-
150
-
151
- require("./lostPassword").plugin(Account, auth.LostPassword, httpServer, emailer, getToken, loader);
152
- }
@@ -1,121 +0,0 @@
1
- var vine = require("vine"),
2
- reqOutcome = require("./reqOutcome"),
3
- step = require("step"),
4
- dust = require("dustjs-linkedin"),
5
- fs = require("fs");
6
-
7
- exports.plugin = function(Account, LostPassword, httpServer, emailer, getToken, loader) {
8
-
9
- if(!emailer) return;
10
-
11
- //register the dust tpl ~ fugly >.>
12
- eval(dust.compile(fs.readFileSync(loader.params("http.lostPasswordEmailTpl"), "utf8"), "lostPasswordEmailTpl"));
13
-
14
-
15
- httpServer.get("/lost_password", function(req, res) {
16
- res.render("lost_password");
17
- });
18
-
19
- httpServer.post("/lost_password", function(req, res) {
20
- var on = reqOutcome(req, res, "lost_password");
21
-
22
- step(
23
- function() {
24
- Account.findOne({ email: req.body.email }, this);
25
- },
26
- on.success(function(account) {
27
- if(!account) return on(new Error("account does not exist"));
28
- this.account = account;
29
-
30
- var lostPassword = new LostPassword({ account: account._id });
31
-
32
- lostPassword.save(this);
33
- }),
34
- on.success(function(lostPassword) {
35
- var next = this;
36
-
37
- dust.render("lostPasswordEmailTpl", { email: req.body.email, token: lostPassword._id }, this);
38
-
39
- }),
40
- on.success(function(tpl) {
41
- var next = this;
42
- emailer.send({
43
- to: this.account.email,
44
- subject: "Reset Password",
45
- htmlBody: tpl
46
- }, function(err) {
47
- if(err) return on(new Error("Unable to send password recovery email"));
48
- next();
49
- })
50
- }),
51
- on.success(function() {
52
- res.render("lost_password_sent", {
53
- email: this.account.email
54
- });
55
- })
56
- );
57
- });
58
-
59
- function lostPasswordExists(req, res, next) {
60
- var on = reqOutcome(req, res, "lost_password");
61
-
62
- step(
63
- function() {
64
- LostPassword.findOne({ _id: req.query.token || req.body.token }, this);
65
- },
66
- on.success(function(lostPassword) {
67
- if(!lostPassword) {
68
- return on(new Error("The reset password token does not exist."));
69
- } else
70
- if(lostPassword.expiresAt.getTime() < Date.now()) {
71
- lostPassword.remove();
72
- return on(new Error("The reset password link has expired."));
73
- }
74
-
75
- req.lostPassword = lostPassword;
76
- this();
77
- }),
78
- next
79
- );
80
- }
81
-
82
- httpServer.get("/reset_password", lostPasswordExists, function(req, res) {
83
- res.render("reset_password", {
84
- token: req.query.token
85
- });
86
- });
87
-
88
- httpServer.post("/reset_password", lostPasswordExists, function(req, res) {
89
- var on = reqOutcome(req, res, "reset_password");
90
-
91
- step(
92
- function() {
93
- if(req.body.password.length < 6) {
94
- console.log(vine.error(new Error("password must be at least 6 characters")).data)
95
-
96
- return on(new Error("password must be at least 6 characters"));
97
- }
98
-
99
- if(req.body.password != req.body.password2) {
100
- return on(new Error("passwords don't match"));
101
- }
102
-
103
- this();
104
- },
105
- function() {
106
- Account.findOne({ _id: req.lostPassword.account }, this);
107
- },
108
- on.success(function(account) {
109
- if(!account) return on(new Error("account doesn't exist"));
110
- account.password = req.body.password;
111
- account.save(this);
112
- }),
113
- on.success(function(account) {
114
-
115
- getToken(req, res, account, "reset_password");
116
- // res.render("login", vine.message("Please re-login with your new password").data);
117
- // req.lostPassword.remove();
118
- })
119
- );
120
- });
121
- }
@@ -1,10 +0,0 @@
1
- vine = require("vine"),
2
- outcome = require("outcome"),
3
- _ = require("underscore");
4
-
5
- module.exports = function(req, res, render) {
6
- var on = outcome.error(function(err) {
7
- res.render(render, _.extend(req.query, vine.error(err).data));
8
- });
9
- return on;
10
- }
package/lib/index.js DELETED
@@ -1,65 +0,0 @@
1
- var structr = require("structr"),
2
- ownableModel = require("./mixin/ownableModel"),
3
- Account = require("./models/account"),
4
- LostPassword = require("./models/lostPassword"),
5
- _ = require("underscore"),
6
- middleware = require("./http/middleware");
7
-
8
-
9
- var Auth = structr({
10
-
11
- /**
12
- */
13
-
14
- publicKeys: ["login", "signup"],
15
-
16
- /**
17
- */
18
-
19
- "__construct": function(options) {
20
- this.connection = options.connection;
21
- this.Account = Account.model(options);
22
- this.LostPassword = LostPassword.model(options.connection);
23
- this.middleware = middleware.plugin(this);
24
- this.ownable = function(schema) {
25
- return ownableModel(schema, options.connection);
26
- }
27
- },
28
-
29
- /**
30
- * logs the user in
31
- */
32
-
33
- "login": function(credentials, callback) {
34
- this.Account.login.apply(this.Account, arguments);
35
- },
36
-
37
- /**
38
- * signs a user up
39
- */
40
-
41
- "signup": function() {
42
- this.Account.signup.apply(this.Account, arguments);
43
- }
44
- });
45
-
46
- exports.access = require("./access");
47
-
48
- exports.connect = function(options) {
49
- return new Auth(options);
50
- }
51
-
52
-
53
- exports.require = [["auth.middleware.*"], "emailer", "plugin-mongodb", "plugin-express"];
54
- exports.plugin = function(authMiddleware, emailer, mongodb, httpServer, loader) {
55
-
56
-
57
- var auth = exports.connect(_.extend({
58
- connection: mongodb
59
- }, loader.params("auth")));
60
-
61
-
62
- require("./http/routes").plugin(httpServer, emailer, auth, loader);
63
-
64
- return auth;
65
- }
@@ -1,118 +0,0 @@
1
- var _ = require("underscore"),
2
- access = require("../access"),
3
- comerr = require("comerr");
4
-
5
-
6
-
7
-
8
-
9
- module.exports = function(schema, connection) {
10
-
11
- var Schema = connection.base.Schema,
12
- ObjectId = Schema.ObjectId;
13
-
14
- var Owner = new Schema({
15
- account: ObjectId,
16
- access: [ String ]
17
- });
18
-
19
- var Account = connection.model("accounts").schema,
20
- collectionName;
21
-
22
- //add owners schema to the item
23
- schema.add({
24
- owners: [ Owner ],
25
-
26
- //is the item visible to the public?
27
- isPublic: { type: Boolean, default: false }
28
- });
29
-
30
- //add a method to all
31
- schema.methods.fetchOwner = function(callback) {
32
- var owner = _.find(this.owners, function(owner) {
33
- return ~owner.access.indexOf(access.SUPER);
34
- });
35
- if(!owner) return callback(new Error("item doesn't have an owner"));
36
- this.model("accounts").findOne({ _id: owner.account }, function(err, account) {
37
- if(err) return callback(err);
38
- if(!account) return callback(new comerr.NotFound("account does't exist"));
39
- callback(err, account);
40
- });
41
- }
42
-
43
-
44
- //plucks any access to shared
45
- schema.statics.revokeShared = function(account, callback) {
46
- this.collection.update(account.ownQuery(), {$pull:{ owners:{ account: account._id }}}, { multi: true }, callback);
47
- }
48
-
49
- //model is needed to remove the item if the account is deleted.
50
- //NOTE - database might not be present, so we just grab the name for reference
51
- //later on
52
- schema.once("init", function(m) {
53
- collectionName = m.collection.name;
54
- });
55
-
56
- //on remove, remove the item as well.
57
- Account.pre("remove", function(next) {
58
- if(!collectionName) {
59
- console.warn("model is not provided with an ownable schema");
60
- return next();
61
- }
62
-
63
- var model = this.model(collectionName),
64
- self = this;
65
-
66
- //first remove ALL items that belong to this acocunt
67
- model.collection.remove(this.ownQuery(access.SUPER), { multi: true }, function() {
68
-
69
- //next, pluck ANY items that maybe associated with this account
70
- model.revokeShared(self, function(){});
71
- });
72
- next();
73
- });
74
-
75
- schema.pre("save", function(next) {
76
- if(!this._account) {
77
- return next();
78
- }
79
-
80
- if(this.authorized([this.isNew ? access.POST : access.PUT])) {
81
- next();
82
- } else {
83
- this._account.unauthorized(next);
84
- }
85
- });
86
-
87
- schema.methods.authorized = function(acc, callback) {
88
-
89
- if(typeof access == "function") {
90
- callback = null;
91
- acc = null;
92
- }
93
-
94
- if(!acc) {
95
- acc = access.all();
96
- }
97
-
98
- var authorized = !this._account || this._account.authorized(this, acc);
99
-
100
- return !callback ? authorized : callback(null, authorized);
101
- }
102
-
103
- var oldToJson = schema.methods.toJSON;
104
-
105
- //lockdown serialization
106
- schema.methods.toJSON = function() {
107
-
108
- //locked down?
109
- if(this.authorized([access.GET])) {
110
- return this.toObject();
111
- } else {
112
- return { error: this._account.unauthorized().message };
113
- }
114
- }
115
-
116
-
117
- return schema;
118
- }