cloudcms-server 0.9.301 → 3.2.280
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.
- package/.last_command +7 -0
- package/LICENSE +1 -1
- package/README.md +1 -1
- package/broadcast/providers/redis.js +24 -49
- package/clients/nrp.js +117 -0
- package/clients/redis.js +64 -0
- package/framework/controllers.js +4 -4
- package/index.js +13 -10
- package/insight/insight.js +1 -1
- package/launchpad/index.js +174 -11
- package/launchpad/launchers/cluster.js +103 -110
- package/launchpad/launchers/redis.js +70 -0
- package/launchpad/launchers/single.js +36 -22
- package/locks/locks.js +53 -7
- package/locks/providers/cluster.js +3 -1
- package/locks/providers/memory.js +10 -7
- package/locks/providers/redis.js +62 -82
- package/middleware/admin/admin.js +2 -2
- package/middleware/authentication/adapters/session.js +11 -8
- package/middleware/authentication/authentication.js +28 -16
- package/middleware/authentication/authenticators/default.js +5 -2
- package/middleware/authentication/authenticators/session.js +5 -2
- package/middleware/authentication/providers/saml.js +1 -1
- package/middleware/authorization/authorization.js +11 -8
- package/middleware/awareness/awareness.js +51 -29
- package/middleware/awareness/plugins/editorial.js +4 -4
- package/middleware/awareness/providers/abstract-async.js +107 -84
- package/middleware/awareness/providers/abstract.js +1 -1
- package/middleware/awareness/providers/memory.js +0 -14
- package/middleware/awareness/providers/redis.js +186 -279
- package/middleware/cache/providers/redis.js +127 -89
- package/middleware/cloudcms/cloudcms.js +22 -16
- package/middleware/form/form.js +2 -2
- package/middleware/proxy/proxy.js +7 -21
- package/middleware/stores/stores.js +2 -2
- package/middleware/virtual-config/virtual-config.js +7 -7
- package/middleware/wcm/wcm.js +4 -4
- package/package.json +54 -52
- package/server/index.js +517 -399
- package/server/standalone.js +9 -0
- package/temp/clusterlock/index.js +3 -3
- package/temp/clusterlock/package.json +1 -1
- package/temp/passport-saml/LICENSE +23 -0
- package/temp/passport-saml/README.md +406 -0
- package/temp/passport-saml/lib/node-saml/algorithms.d.ts +5 -0
- package/temp/passport-saml/lib/node-saml/algorithms.js +41 -0
- package/temp/passport-saml/lib/node-saml/algorithms.js.map +1 -0
- package/temp/passport-saml/lib/node-saml/index.d.ts +3 -0
- package/temp/passport-saml/lib/node-saml/index.js +6 -0
- package/temp/passport-saml/lib/node-saml/index.js.map +1 -0
- package/temp/passport-saml/lib/node-saml/inmemory-cache-provider.d.ts +45 -0
- package/temp/passport-saml/lib/node-saml/inmemory-cache-provider.js +86 -0
- package/temp/passport-saml/lib/node-saml/inmemory-cache-provider.js.map +1 -0
- package/temp/passport-saml/lib/node-saml/saml-post-signing.d.ts +3 -0
- package/temp/passport-saml/lib/node-saml/saml-post-signing.js +15 -0
- package/temp/passport-saml/lib/node-saml/saml-post-signing.js.map +1 -0
- package/temp/passport-saml/lib/node-saml/saml.d.ts +77 -0
- package/temp/passport-saml/lib/node-saml/saml.js +1170 -0
- package/temp/passport-saml/lib/node-saml/saml.js.map +1 -0
- package/temp/passport-saml/lib/node-saml/types.d.ts +95 -0
- package/temp/passport-saml/lib/node-saml/types.js +8 -0
- package/temp/passport-saml/lib/node-saml/types.js.map +1 -0
- package/temp/passport-saml/lib/node-saml/utility.d.ts +3 -0
- package/temp/passport-saml/lib/node-saml/utility.js +19 -0
- package/temp/passport-saml/lib/node-saml/utility.js.map +1 -0
- package/temp/passport-saml/lib/node-saml/xml.d.ts +21 -0
- package/temp/passport-saml/lib/node-saml/xml.js +140 -0
- package/temp/passport-saml/lib/node-saml/xml.js.map +1 -0
- package/temp/passport-saml/lib/passport-saml/index.d.ts +6 -0
- package/temp/passport-saml/lib/passport-saml/index.js +11 -0
- package/temp/passport-saml/lib/passport-saml/index.js.map +1 -0
- package/temp/passport-saml/lib/passport-saml/multiSamlStrategy.d.ts +13 -0
- package/temp/passport-saml/lib/passport-saml/multiSamlStrategy.js +63 -0
- package/temp/passport-saml/lib/passport-saml/multiSamlStrategy.js.map +1 -0
- package/temp/passport-saml/lib/passport-saml/strategy.d.ts +20 -0
- package/temp/passport-saml/lib/passport-saml/strategy.js +167 -0
- package/temp/passport-saml/lib/passport-saml/strategy.js.map +1 -0
- package/temp/passport-saml/lib/passport-saml/types.d.ts +51 -0
- package/temp/passport-saml/lib/passport-saml/types.js +11 -0
- package/temp/passport-saml/lib/passport-saml/types.js.map +1 -0
- package/temp/passport-saml/package.json +96 -0
- package/util/auth.js +1 -1
- package/util/cloudcms.js +72 -93
- package/util/proxy-factory.js +230 -260
- package/util/redis.js +113 -0
- package/util/renditions.js +1 -1
- package/util/util.js +15 -2
- package/launchpad/launchers/sticky-cluster.js +0 -43
- package/web/cms/ice.js +0 -109
- package/web/cms/preview.js +0 -106
- package/web/socket.io/socket.io.js +0 -2
|
@@ -9,15 +9,18 @@ class SessionAdapter extends AbstractAdapter
|
|
|
9
9
|
|
|
10
10
|
identify(req, callback)
|
|
11
11
|
{
|
|
12
|
-
if (req.session
|
|
12
|
+
if (req.session)
|
|
13
13
|
{
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
if (req.session._auth_profile)
|
|
15
|
+
{
|
|
16
|
+
var properties = {
|
|
17
|
+
"token": req.session._auth_profile.unique_name,
|
|
18
|
+
"trusted": true,
|
|
19
|
+
"profile": req.session._auth_profile
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return callback(null, properties);
|
|
23
|
+
}
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
return super.identify(req, callback);
|
|
@@ -436,15 +436,21 @@ exports = module.exports = function()
|
|
|
436
436
|
}
|
|
437
437
|
else
|
|
438
438
|
{
|
|
439
|
-
req.session.
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
439
|
+
return req.session.reload(function() {
|
|
440
|
+
|
|
441
|
+
req.session.registration_strategy_id = strategyId;
|
|
442
|
+
req.session.registration_user_object = userObject;
|
|
443
|
+
req.session.registration_user_identifier = userIdentifier;
|
|
444
|
+
req.session.registration_groups_array = groupsArray;
|
|
445
|
+
req.session.registration_mandatory_groups_array = mandatoryGroupsArray;
|
|
446
|
+
req.session.registration_token = info.token;
|
|
447
|
+
req.session.registration_refresh_token = info.refresh_token;
|
|
448
|
+
|
|
449
|
+
req.session.save(function() {
|
|
450
|
+
res.redirect(registrationRedirectUrl);
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
});
|
|
448
454
|
}
|
|
449
455
|
});
|
|
450
456
|
}
|
|
@@ -765,13 +771,19 @@ exports = module.exports = function()
|
|
|
765
771
|
}
|
|
766
772
|
else
|
|
767
773
|
{
|
|
768
|
-
req.session.
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
774
|
+
return req.session.reload(function() {
|
|
775
|
+
|
|
776
|
+
req.session.registration_strategy_id = strategyId;
|
|
777
|
+
req.session.registration_user_object = properties.user_object;
|
|
778
|
+
req.session.registration_user_identifier = properties.user_identifier;
|
|
779
|
+
req.session.registration_token = properties.token;
|
|
780
|
+
req.session.registration_refresh_token = properties.refresh_token;
|
|
781
|
+
|
|
782
|
+
req.session.save(function() {
|
|
783
|
+
res.redirect(registrationRedirect);
|
|
784
|
+
});
|
|
785
|
+
|
|
786
|
+
});
|
|
775
787
|
}
|
|
776
788
|
}
|
|
777
789
|
|
|
@@ -15,8 +15,11 @@ class DefaultAuthenticator extends AbstractAuthenticator
|
|
|
15
15
|
{
|
|
16
16
|
return req.logIn(gitanaUser, function() {
|
|
17
17
|
|
|
18
|
-
if (req.session
|
|
19
|
-
|
|
18
|
+
if (req.session)
|
|
19
|
+
{
|
|
20
|
+
return req.session.save(function() {
|
|
21
|
+
callback();
|
|
22
|
+
});
|
|
20
23
|
}
|
|
21
24
|
|
|
22
25
|
callback();
|
|
@@ -25,8 +25,11 @@ class SessionAuthenticator extends DefaultAuthenticator
|
|
|
25
25
|
|
|
26
26
|
req.user = gitanaUser;
|
|
27
27
|
|
|
28
|
-
if (req.session
|
|
29
|
-
|
|
28
|
+
if (req.session)
|
|
29
|
+
{
|
|
30
|
+
return req.session.save(function() {
|
|
31
|
+
callback();
|
|
32
|
+
});
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
callback();
|
|
@@ -41,17 +41,20 @@ exports = module.exports = function()
|
|
|
41
41
|
}
|
|
42
42
|
*/
|
|
43
43
|
|
|
44
|
-
if (pathRequiresAuthorization)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
res.redirect("/login");
|
|
50
|
-
}
|
|
44
|
+
if (!pathRequiresAuthorization)
|
|
45
|
+
{
|
|
46
|
+
return next();
|
|
51
47
|
}
|
|
52
|
-
|
|
48
|
+
|
|
49
|
+
if (req.session && req.session.requestContext)
|
|
50
|
+
{
|
|
53
51
|
next();
|
|
54
52
|
}
|
|
53
|
+
else
|
|
54
|
+
{
|
|
55
|
+
res.redirect("/login");
|
|
56
|
+
}
|
|
57
|
+
|
|
55
58
|
});
|
|
56
59
|
};
|
|
57
60
|
|
|
@@ -60,10 +60,15 @@ exports = module.exports = function()
|
|
|
60
60
|
if (!process.configuration.awareness.config) {
|
|
61
61
|
process.configuration.awareness.config = {};
|
|
62
62
|
}
|
|
63
|
-
|
|
63
|
+
|
|
64
|
+
// init any plugins?
|
|
65
|
+
if (!process.configuration.awareness.plugins) {
|
|
66
|
+
process.configuration.awareness.plugins = [];
|
|
67
|
+
}
|
|
68
|
+
|
|
64
69
|
var type = process.configuration.awareness.type;
|
|
65
70
|
var config = process.configuration.awareness.config;
|
|
66
|
-
|
|
71
|
+
|
|
67
72
|
var providerFactory = require("./providers/" + type);
|
|
68
73
|
provider = new providerFactory(config);
|
|
69
74
|
|
|
@@ -74,12 +79,6 @@ exports = module.exports = function()
|
|
|
74
79
|
return callback(err);
|
|
75
80
|
}
|
|
76
81
|
|
|
77
|
-
// init any plugins?
|
|
78
|
-
if (!process.configuration.awareness.plugins) {
|
|
79
|
-
process.configuration.awareness.plugins = [];
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
82
|
var fns = [];
|
|
84
83
|
for (var i = 0; i < pluginPaths.length; i++)
|
|
85
84
|
{
|
|
@@ -115,15 +114,18 @@ exports = module.exports = function()
|
|
|
115
114
|
/**
|
|
116
115
|
* This gets called whenever a new socket is connected to the Cloud CMS server.
|
|
117
116
|
*
|
|
117
|
+
* @param io
|
|
118
|
+
* @param callback
|
|
119
|
+
*
|
|
118
120
|
* @type {Function}
|
|
119
121
|
*/
|
|
120
|
-
var initSocketIO = r.initSocketIO = function(callback) {
|
|
121
|
-
|
|
122
|
+
var initSocketIO = r.initSocketIO = function(io, callback) {
|
|
123
|
+
|
|
122
124
|
// initialize socket IO event handlers so that awareness binds to any new, incoming sockets
|
|
123
|
-
socketInit(
|
|
125
|
+
socketInit(io);
|
|
124
126
|
|
|
125
127
|
// ensure the reaper is initialized
|
|
126
|
-
reaperInit(
|
|
128
|
+
reaperInit(io, REAP_FREQUENCY_MS, REAP_MAX_AGE_MS, function(err) {
|
|
127
129
|
callback(err);
|
|
128
130
|
});
|
|
129
131
|
};
|
|
@@ -172,7 +174,7 @@ exports = module.exports = function()
|
|
|
172
174
|
// when a socket.io connection is established, we set up some default listeners for events that the client
|
|
173
175
|
// may emit to us
|
|
174
176
|
io.on("connection", function(socket) {
|
|
175
|
-
|
|
177
|
+
|
|
176
178
|
// "register" -> indicates that a user is in a channel
|
|
177
179
|
socket.on("register", function(channelId, user, dirty, callback) {
|
|
178
180
|
|
|
@@ -193,24 +195,32 @@ exports = module.exports = function()
|
|
|
193
195
|
return callback(err);
|
|
194
196
|
}
|
|
195
197
|
|
|
196
|
-
// if we were already registered, just callback
|
|
197
|
-
// however, if "dirty" is set, then we always hand back membership
|
|
198
|
-
if (!dirty && alreadyRegistered)
|
|
199
|
-
{
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
198
|
+
// // if we were already registered, just callback
|
|
199
|
+
// // however, if "dirty" is set, then we always hand back membership
|
|
200
|
+
// if (!dirty && alreadyRegistered)
|
|
201
|
+
// {
|
|
202
|
+
// logger.info("Already registered, not dirty - channelId: " + channelId + ",userId=" + user.id + " (" + user.name + ")");
|
|
203
|
+
//
|
|
204
|
+
// return callback();
|
|
205
|
+
// }
|
|
206
|
+
//
|
|
207
|
+
// if (!alreadyRegistered)
|
|
208
|
+
// {
|
|
209
|
+
// logger.info("New registration - channelId: " + channelId + ",userId=" + user.id + " (" + user.name + ")");
|
|
210
|
+
|
|
211
|
+
//logger.info("Register - channelId: " + channelId + ", userId=" + user.id + " (" + user.name + ")");
|
|
207
212
|
socket.join(channelId);
|
|
208
|
-
}
|
|
213
|
+
//}
|
|
209
214
|
|
|
210
215
|
discover(channelId, function(err, userArray) {
|
|
211
216
|
|
|
212
|
-
if (
|
|
213
|
-
|
|
217
|
+
if (err)
|
|
218
|
+
{
|
|
219
|
+
logger.info("Discover - channelId: " + channelId + ", err: " + JSON.stringify(err));
|
|
220
|
+
}
|
|
221
|
+
else
|
|
222
|
+
{
|
|
223
|
+
//logger.info("Discover - channelId: " + channelId + ", userId=" + user.id + " (" + user.name + ") handing back: " + userArray.length);
|
|
214
224
|
io.sockets.in(channelId).emit("membershipChanged", channelId, userArray);
|
|
215
225
|
}
|
|
216
226
|
|
|
@@ -412,6 +422,8 @@ exports = module.exports = function()
|
|
|
412
422
|
*/
|
|
413
423
|
var register = r.register = function(channelId, user, callback)
|
|
414
424
|
{
|
|
425
|
+
//console.log("Awareness - heard register, channel: " + channelId + ", user: " + user.id);
|
|
426
|
+
|
|
415
427
|
provider.register(channelId, user, callback);
|
|
416
428
|
};
|
|
417
429
|
|
|
@@ -458,7 +470,12 @@ exports = module.exports = function()
|
|
|
458
470
|
{
|
|
459
471
|
// take out a cluster-wide lock on the "channelId"
|
|
460
472
|
// so that two "threads" can't acquire/release at the same time for a given channel
|
|
461
|
-
_LOCK(channelId, function (releaseLockFn) {
|
|
473
|
+
_LOCK(channelId, function (err, releaseLockFn) {
|
|
474
|
+
|
|
475
|
+
if (err) {
|
|
476
|
+
return callback(err);
|
|
477
|
+
}
|
|
478
|
+
|
|
462
479
|
provider.acquireLock(channelId, user, function(err, success) {
|
|
463
480
|
releaseLockFn();
|
|
464
481
|
callback(err, success);
|
|
@@ -477,7 +494,12 @@ exports = module.exports = function()
|
|
|
477
494
|
{
|
|
478
495
|
// take out a cluster-wide lock on the "channelId"
|
|
479
496
|
// so that two "threads" can't acquire/release at the same time for a given channel
|
|
480
|
-
_LOCK(channelId, function (releaseLockFn) {
|
|
497
|
+
_LOCK(channelId, function (err, releaseLockFn) {
|
|
498
|
+
|
|
499
|
+
if (err) {
|
|
500
|
+
return callback(err);
|
|
501
|
+
}
|
|
502
|
+
|
|
481
503
|
provider.releaseLock(channelId, userId, function(err, success) {
|
|
482
504
|
releaseLockFn();
|
|
483
505
|
callback(err, success);
|
|
@@ -43,7 +43,7 @@ exports.bindSocket = function(socket, provider)
|
|
|
43
43
|
var acquireEditorialSession = function(socket, provider, sessionKey, repositoryId, branchId, force, callback)
|
|
44
44
|
{
|
|
45
45
|
// send an HTTP command to acquire an editorial session for this repository and branch
|
|
46
|
-
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT) + "/oneteam/editorial/session/acquire";
|
|
46
|
+
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT, process.env.GITANA_PROXY_PATH) + "/oneteam/editorial/session/acquire";
|
|
47
47
|
|
|
48
48
|
var headers = {};
|
|
49
49
|
//headers["Authorization"] = socket.gitana.platform().getDriver().getHttpHeaders()["Authorization"];
|
|
@@ -101,7 +101,7 @@ exports.bindSocket = function(socket, provider)
|
|
|
101
101
|
var releaseEditorialSession = function(socket, provider, sessionKey, repositoryId, branchId, callback)
|
|
102
102
|
{
|
|
103
103
|
// send an HTTP command to release the session
|
|
104
|
-
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT) + "/oneteam/editorial/session/release";
|
|
104
|
+
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT, process.env.GITANA_PROXY_PATH) + "/oneteam/editorial/session/release";
|
|
105
105
|
|
|
106
106
|
var json = {};
|
|
107
107
|
json.repositoryId = repositoryId;
|
|
@@ -152,7 +152,7 @@ exports.bindSocket = function(socket, provider)
|
|
|
152
152
|
*/
|
|
153
153
|
var commitEditorialSession = function(socket, provider, sessionKey, repositoryId, branchId, callback)
|
|
154
154
|
{
|
|
155
|
-
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT) + "/oneteam/editorial/session/commit";
|
|
155
|
+
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT, process.env.GITANA_PROXY_PATH) + "/oneteam/editorial/session/commit";
|
|
156
156
|
|
|
157
157
|
var json = {};
|
|
158
158
|
json.repositoryId = repositoryId;
|
|
@@ -202,7 +202,7 @@ exports.bindSocket = function(socket, provider)
|
|
|
202
202
|
*/
|
|
203
203
|
var editorialSessionInfo = function(socket, provider, sessionKey, repositoryId, branchId, callback)
|
|
204
204
|
{
|
|
205
|
-
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT) + "/oneteam/editorial/session/info";
|
|
205
|
+
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT, process.env.GITANA_PROXY_PATH) + "/oneteam/editorial/session/info";
|
|
206
206
|
|
|
207
207
|
var json = {};
|
|
208
208
|
json.repositoryId = repositoryId;
|
|
@@ -14,28 +14,33 @@ class AbstractAsyncProvider extends AbstractProvider
|
|
|
14
14
|
{
|
|
15
15
|
super(config);
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
|
|
18
|
+
_lock(lockKey, workFunction)
|
|
19
|
+
{
|
|
20
|
+
process.locks.lock(lockKey, workFunction);
|
|
21
|
+
}
|
|
22
|
+
|
|
18
23
|
readOrCreateChannel(channelId, callback) {
|
|
19
24
|
|
|
20
25
|
var self = this;
|
|
21
26
|
|
|
22
27
|
self.readChannel(channelId, function(err, channel) {
|
|
23
|
-
|
|
28
|
+
|
|
24
29
|
if (err) {
|
|
25
30
|
return callback(err);
|
|
26
31
|
}
|
|
27
|
-
|
|
32
|
+
|
|
28
33
|
if (channel) {
|
|
29
34
|
return callback(null, channel);
|
|
30
35
|
}
|
|
31
36
|
|
|
32
37
|
var channel = {};
|
|
33
38
|
self.writeChannel(channelId, channel, function(err) {
|
|
34
|
-
|
|
39
|
+
|
|
35
40
|
if (err) {
|
|
36
41
|
return callback(err);
|
|
37
42
|
}
|
|
38
|
-
|
|
43
|
+
|
|
39
44
|
callback(null, channel);
|
|
40
45
|
});
|
|
41
46
|
});
|
|
@@ -46,26 +51,44 @@ class AbstractAsyncProvider extends AbstractProvider
|
|
|
46
51
|
register(channelId, user, callback)
|
|
47
52
|
{
|
|
48
53
|
var self = this;
|
|
49
|
-
|
|
54
|
+
|
|
55
|
+
self.doRegister(channelId, user, function(err) {
|
|
56
|
+
callback(err);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Workhorse method.
|
|
62
|
+
*
|
|
63
|
+
* @param channelId
|
|
64
|
+
* @param user
|
|
65
|
+
* @param callback
|
|
66
|
+
* @private
|
|
67
|
+
*/
|
|
68
|
+
doRegister(channelId, user, callback)
|
|
69
|
+
{
|
|
70
|
+
var self = this;
|
|
71
|
+
|
|
50
72
|
self.readOrCreateChannel(channelId, function (err, channel) {
|
|
51
|
-
|
|
73
|
+
|
|
52
74
|
if (err) {
|
|
53
75
|
return callback(err);
|
|
54
76
|
}
|
|
55
|
-
|
|
77
|
+
|
|
56
78
|
if (!channel.users) {
|
|
57
79
|
channel.users = {};
|
|
58
80
|
}
|
|
59
|
-
|
|
81
|
+
|
|
60
82
|
channel.users[user.id] = {
|
|
61
83
|
"user": user,
|
|
62
84
|
"time": new Date().getTime()
|
|
63
85
|
};
|
|
64
|
-
|
|
86
|
+
|
|
65
87
|
self.writeChannel(channelId, channel, function (err) {
|
|
66
88
|
callback(err);
|
|
67
89
|
});
|
|
68
90
|
});
|
|
91
|
+
|
|
69
92
|
}
|
|
70
93
|
|
|
71
94
|
discover(channelId, callback)
|
|
@@ -101,123 +124,121 @@ class AbstractAsyncProvider extends AbstractProvider
|
|
|
101
124
|
});
|
|
102
125
|
}
|
|
103
126
|
|
|
104
|
-
|
|
127
|
+
checkRegistered(channelId, userId, callback)
|
|
105
128
|
{
|
|
106
129
|
var self = this;
|
|
107
130
|
|
|
108
|
-
self.
|
|
131
|
+
self.readChannel(channelId, function(err, channel) {
|
|
109
132
|
|
|
110
133
|
if (err) {
|
|
111
134
|
return callback(err);
|
|
112
135
|
}
|
|
113
136
|
|
|
137
|
+
if (!channel) {
|
|
138
|
+
return callback(null, false);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (!channel.users) {
|
|
142
|
+
return callback(null, false);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (channel.users[userId]) {
|
|
146
|
+
return callback(null, true);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
callback(null, false);
|
|
150
|
+
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
expire(beforeMs, callback)
|
|
155
|
+
{
|
|
156
|
+
var self = this;
|
|
157
|
+
|
|
158
|
+
self.listChannelIds(function(err, channelIds) {
|
|
159
|
+
|
|
160
|
+
if (err) {
|
|
161
|
+
return callback(err);
|
|
162
|
+
}
|
|
163
|
+
|
|
114
164
|
if (!channelIds || channelIds.length === 0) {
|
|
115
165
|
return callback(null, [], {});
|
|
116
166
|
}
|
|
117
|
-
|
|
167
|
+
|
|
118
168
|
// a list of channel IDs whose memberships were updated
|
|
119
169
|
var updatedMembershipChannelIds = [];
|
|
120
170
|
var expiredUserIdsByChannelId = {};
|
|
121
|
-
|
|
171
|
+
|
|
122
172
|
var fns = [];
|
|
123
|
-
|
|
173
|
+
|
|
124
174
|
for (var i = 0; i < channelIds.length; i++)
|
|
125
175
|
{
|
|
126
176
|
var channelId = channelIds[i];
|
|
127
|
-
|
|
177
|
+
|
|
128
178
|
var fn = function (channelId, updatedMembershipChannelIds, expiredUserIdsByChannelId, beforeMs) {
|
|
129
179
|
return function (done) {
|
|
130
|
-
|
|
180
|
+
|
|
131
181
|
self.readChannel(channelId, function(err, channel) {
|
|
132
|
-
|
|
182
|
+
|
|
133
183
|
if (err) {
|
|
134
184
|
return done(err);
|
|
135
185
|
}
|
|
136
|
-
|
|
186
|
+
|
|
137
187
|
if (!channel) {
|
|
138
188
|
return done();
|
|
139
189
|
}
|
|
190
|
+
|
|
191
|
+
if (!channel.users || Object.keys(channel.users).length === 0)
|
|
192
|
+
{
|
|
193
|
+
return done();
|
|
194
|
+
}
|
|
140
195
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
196
|
+
// populate all of the user IDs that need to be removed
|
|
197
|
+
var userIdsToRemove = [];
|
|
198
|
+
for (var userId in channel.users)
|
|
144
199
|
{
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
for (var userId in channel.users)
|
|
200
|
+
var entry = channel.users[userId];
|
|
201
|
+
if (entry.time < beforeMs)
|
|
148
202
|
{
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
var expiredUserIds = expiredUserIdsByChannelId[channelId]
|
|
156
|
-
if (!expiredUserIds) {
|
|
157
|
-
expiredUserIds = expiredUserIdsByChannelId[channelId] = [];
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
expiredUserIds.push(userId);
|
|
203
|
+
updatedMembershipChannelIds.push(channelId);
|
|
204
|
+
userIdsToRemove.push(userId);
|
|
205
|
+
|
|
206
|
+
var expiredUserIds = expiredUserIdsByChannelId[channelId]
|
|
207
|
+
if (!expiredUserIds) {
|
|
208
|
+
expiredUserIds = expiredUserIdsByChannelId[channelId] = [];
|
|
161
209
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
// remove the user IDs
|
|
165
|
-
for (var i = 0; i < userIdsToRemove.length; i++)
|
|
166
|
-
{
|
|
167
|
-
delete channel.users[userIdsToRemove[i]];
|
|
210
|
+
|
|
211
|
+
expiredUserIds.push(userId);
|
|
168
212
|
}
|
|
169
213
|
}
|
|
170
|
-
|
|
171
|
-
|
|
214
|
+
|
|
215
|
+
// remove the user IDs
|
|
216
|
+
for (var i = 0; i < userIdsToRemove.length; i++)
|
|
172
217
|
{
|
|
173
|
-
|
|
218
|
+
delete channel.users[userIdsToRemove[i]];
|
|
174
219
|
}
|
|
175
|
-
|
|
176
|
-
|
|
220
|
+
|
|
221
|
+
self.writeChannel(channelId, channel, function() {
|
|
222
|
+
done();
|
|
223
|
+
});
|
|
224
|
+
|
|
177
225
|
});
|
|
178
226
|
};
|
|
179
227
|
}(channelId, updatedMembershipChannelIds, expiredUserIdsByChannelId, beforeMs);
|
|
180
228
|
fns.push(fn);
|
|
181
229
|
}
|
|
182
|
-
|
|
230
|
+
|
|
183
231
|
async.parallel(fns, function(err) {
|
|
184
|
-
|
|
232
|
+
|
|
185
233
|
if (err) {
|
|
186
234
|
return callback(err);
|
|
187
235
|
}
|
|
188
|
-
|
|
236
|
+
|
|
189
237
|
callback(null, updatedMembershipChannelIds, expiredUserIdsByChannelId);
|
|
190
238
|
});
|
|
191
239
|
});
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
checkRegistered(channelId, userId, callback)
|
|
195
|
-
{
|
|
196
|
-
var self = this;
|
|
197
|
-
|
|
198
|
-
self.readChannel(channelId, function(err, channel) {
|
|
199
|
-
|
|
200
|
-
if (err) {
|
|
201
|
-
return callback(err);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (!channel) {
|
|
205
|
-
return callback(null, false);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
if (!channel.users) {
|
|
209
|
-
return callback(null, false);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
if (channel.users[userId]) {
|
|
213
|
-
return callback(null, true);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
callback(null, false);
|
|
217
|
-
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
|
|
240
|
+
};
|
|
241
|
+
|
|
221
242
|
acquireLock(channelId, user, callback)
|
|
222
243
|
{
|
|
223
244
|
var self = this;
|
|
@@ -303,14 +324,16 @@ class AbstractAsyncProvider extends AbstractProvider
|
|
|
303
324
|
callback(null, lock);
|
|
304
325
|
});
|
|
305
326
|
}
|
|
306
|
-
|
|
307
|
-
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
|
|
308
331
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
309
332
|
//
|
|
310
333
|
// ABSTRACT METHODS
|
|
311
334
|
//
|
|
312
335
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
313
|
-
|
|
336
|
+
|
|
314
337
|
// ABSTRACT
|
|
315
338
|
readChannel(channelId, callback)
|
|
316
339
|
{
|
|
@@ -328,7 +351,7 @@ class AbstractAsyncProvider extends AbstractProvider
|
|
|
328
351
|
{
|
|
329
352
|
throw new Error("listChannelIds() method is not implemented");
|
|
330
353
|
}
|
|
331
|
-
|
|
354
|
+
|
|
332
355
|
// ABSTRACT
|
|
333
356
|
readLock(lockId, callback)
|
|
334
357
|
{
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Abstract class for an Awareness Provider.
|
|
3
3
|
*
|
|
4
4
|
* This class provides an interface or base functions that any implementation class must implement in order to
|
|
5
|
-
* work with the Awareness Service.
|
|
5
|
+
* work with the Awareness Service.
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
class AbstractProvider
|