cloudcms-server 0.9.256 → 0.9.261
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/README.md +1 -1
- package/broadcast/providers/redis.js +24 -49
- package/clients/nrp.js +117 -0
- package/clients/redis.js +64 -0
- package/launchpad/index.js +161 -11
- package/launchpad/launchers/cluster.js +87 -109
- package/launchpad/launchers/redis.js +53 -0
- package/launchpad/launchers/single.js +30 -22
- package/locks/locks.js +4 -3
- package/locks/providers/cluster.js +1 -1
- package/locks/providers/memory.js +1 -1
- package/locks/providers/redis.js +62 -61
- package/middleware/admin/admin.js +2 -2
- package/middleware/authentication/providers/saml.js +2 -1
- package/middleware/awareness/awareness.js +12 -2
- package/middleware/awareness/providers/redis.js +224 -179
- package/middleware/cache/providers/redis.js +125 -68
- package/middleware/cloudcms/cloudcms.js +5 -1
- package/middleware/proxy/proxy.js +2 -1
- package/middleware/stores/stores.js +2 -2
- package/middleware/virtual-config/virtual-config.js +4 -4
- package/middleware/wcm/wcm.js +4 -4
- package/package.json +11 -7
- package/server/index.js +622 -591
- package/temp/clusterlock/index.js +2 -0
- 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 +6 -6
- package/util/proxy-factory.js +22 -7
- package/util/redis.js +51 -1
- package/util/util.js +1 -1
- package/launchpad/launchers/sticky-cluster.js +0 -43
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MultiSamlStrategy = void 0;
|
|
4
|
+
const node_saml_1 = require("../node-saml");
|
|
5
|
+
const strategy_1 = require("./strategy");
|
|
6
|
+
class MultiSamlStrategy extends strategy_1.AbstractStrategy {
|
|
7
|
+
constructor(options, verify) {
|
|
8
|
+
if (!options || typeof options.getSamlOptions !== "function") {
|
|
9
|
+
throw new Error("Please provide a getSamlOptions function");
|
|
10
|
+
}
|
|
11
|
+
// Force the type on this since we've disabled `newOnConstruct`
|
|
12
|
+
// so the `SAML` constructor will not be called at this time
|
|
13
|
+
// and there are defaults for all `strategy`-required options.
|
|
14
|
+
const samlConfig = {
|
|
15
|
+
...options,
|
|
16
|
+
};
|
|
17
|
+
super(samlConfig, verify);
|
|
18
|
+
this._options = samlConfig;
|
|
19
|
+
}
|
|
20
|
+
authenticate(req, options) {
|
|
21
|
+
this._options.getSamlOptions(req, (err, samlOptions) => {
|
|
22
|
+
if (err) {
|
|
23
|
+
return this.error(err);
|
|
24
|
+
}
|
|
25
|
+
const samlService = new node_saml_1.SAML({ ...this._options, ...samlOptions });
|
|
26
|
+
const strategy = Object.assign({}, this, { _saml: samlService });
|
|
27
|
+
Object.setPrototypeOf(strategy, this);
|
|
28
|
+
super.authenticate.call(strategy, req, options);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
logout(req, callback) {
|
|
32
|
+
this._options.getSamlOptions(req, (err, samlOptions) => {
|
|
33
|
+
if (err) {
|
|
34
|
+
return callback(err);
|
|
35
|
+
}
|
|
36
|
+
const samlService = new node_saml_1.SAML(Object.assign({}, this._options, samlOptions));
|
|
37
|
+
const strategy = Object.assign({}, this, { _saml: samlService });
|
|
38
|
+
Object.setPrototypeOf(strategy, this);
|
|
39
|
+
super.logout.call(strategy, req, callback);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
generateServiceProviderMetadata(req, decryptionCert, signingCert, callback) {
|
|
43
|
+
if (typeof callback !== "function") {
|
|
44
|
+
throw new Error("Metadata can't be provided synchronously for MultiSamlStrategy.");
|
|
45
|
+
}
|
|
46
|
+
return this._options.getSamlOptions(req, (err, samlOptions) => {
|
|
47
|
+
if (err) {
|
|
48
|
+
return callback(err);
|
|
49
|
+
}
|
|
50
|
+
const samlService = new node_saml_1.SAML(Object.assign({}, this._options, samlOptions));
|
|
51
|
+
const strategy = Object.assign({}, this, { _saml: samlService });
|
|
52
|
+
Object.setPrototypeOf(strategy, this);
|
|
53
|
+
return callback(null, this._generateServiceProviderMetadata.call(strategy, decryptionCert, signingCert));
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
// This is reduntant, but helps with testing
|
|
57
|
+
error(err) {
|
|
58
|
+
super.error(err);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.MultiSamlStrategy = MultiSamlStrategy;
|
|
62
|
+
MultiSamlStrategy.newSamlProviderOnConstruct = false;
|
|
63
|
+
//# sourceMappingURL=multiSamlStrategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multiSamlStrategy.js","sourceRoot":"","sources":["../../src/passport-saml/multiSamlStrategy.ts"],"names":[],"mappings":"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","sourcesContent":["import { SAML } from \"../node-saml\";\nimport { AbstractStrategy } from \"./strategy\";\nimport type { Request } from \"express\";\nimport {\n AuthenticateOptions,\n MultiSamlConfig,\n RequestWithUser,\n SamlConfig,\n VerifyWithoutRequest,\n VerifyWithRequest,\n} from \"./types\";\n\nexport class MultiSamlStrategy extends AbstractStrategy {\n static readonly newSamlProviderOnConstruct = false;\n _options: SamlConfig & MultiSamlConfig;\n\n constructor(options: MultiSamlConfig, verify: VerifyWithRequest);\n constructor(options: MultiSamlConfig, verify: VerifyWithoutRequest);\n constructor(options: MultiSamlConfig, verify: never) {\n if (!options || typeof options.getSamlOptions !== \"function\") {\n throw new Error(\"Please provide a getSamlOptions function\");\n }\n\n // Force the type on this since we've disabled `newOnConstruct`\n // so the `SAML` constructor will not be called at this time\n // and there are defaults for all `strategy`-required options.\n const samlConfig = {\n ...options,\n } as SamlConfig & MultiSamlConfig;\n\n super(samlConfig, verify);\n this._options = samlConfig;\n }\n\n authenticate(req: RequestWithUser, options: AuthenticateOptions): void {\n this._options.getSamlOptions(req, (err, samlOptions) => {\n if (err) {\n return this.error(err);\n }\n\n const samlService = new SAML({ ...this._options, ...samlOptions });\n const strategy = Object.assign({}, this, { _saml: samlService });\n Object.setPrototypeOf(strategy, this);\n super.authenticate.call(strategy, req, options);\n });\n }\n\n logout(\n req: RequestWithUser,\n callback: (err: Error | null, url?: string | null | undefined) => void\n ) {\n this._options.getSamlOptions(req, (err, samlOptions) => {\n if (err) {\n return callback(err);\n }\n\n const samlService = new SAML(Object.assign({}, this._options, samlOptions));\n const strategy = Object.assign({}, this, { _saml: samlService });\n Object.setPrototypeOf(strategy, this);\n super.logout.call(strategy, req, callback);\n });\n }\n\n generateServiceProviderMetadata(\n req: Request,\n decryptionCert: string | null,\n signingCert: string | null,\n callback: (err: Error | null, metadata?: string) => void\n ) {\n if (typeof callback !== \"function\") {\n throw new Error(\"Metadata can't be provided synchronously for MultiSamlStrategy.\");\n }\n\n return this._options.getSamlOptions(req, (err, samlOptions) => {\n if (err) {\n return callback(err);\n }\n\n const samlService = new SAML(Object.assign({}, this._options, samlOptions));\n const strategy = Object.assign({}, this, { _saml: samlService });\n Object.setPrototypeOf(strategy, this);\n return callback(\n null,\n this._generateServiceProviderMetadata.call(strategy, decryptionCert, signingCert)\n );\n });\n }\n\n // This is reduntant, but helps with testing\n error(err: Error): void {\n super.error(err);\n }\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Strategy as PassportStrategy } from "passport-strategy";
|
|
2
|
+
import { SAML } from "../node-saml";
|
|
3
|
+
import { AuthenticateOptions, RequestWithUser, SamlConfig, VerifyWithoutRequest, VerifyWithRequest } from "./types";
|
|
4
|
+
export declare abstract class AbstractStrategy extends PassportStrategy {
|
|
5
|
+
static readonly newSamlProviderOnConstruct: boolean;
|
|
6
|
+
name: string;
|
|
7
|
+
_verify: VerifyWithRequest | VerifyWithoutRequest;
|
|
8
|
+
_saml: SAML | undefined;
|
|
9
|
+
_passReqToCallback?: boolean;
|
|
10
|
+
constructor(options: SamlConfig, verify: VerifyWithRequest);
|
|
11
|
+
constructor(options: SamlConfig, verify: VerifyWithoutRequest);
|
|
12
|
+
authenticate(req: RequestWithUser, options: AuthenticateOptions): void;
|
|
13
|
+
logout(req: RequestWithUser, callback: (err: Error | null, url?: string | null) => void): void;
|
|
14
|
+
protected _generateServiceProviderMetadata(decryptionCert: string | null, signingCert?: string | null): string;
|
|
15
|
+
error(err: Error): void;
|
|
16
|
+
}
|
|
17
|
+
export declare class Strategy extends AbstractStrategy {
|
|
18
|
+
static readonly newSamlProviderOnConstruct = true;
|
|
19
|
+
generateServiceProviderMetadata(decryptionCert: string | null, signingCert?: string | null): string;
|
|
20
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Strategy = exports.AbstractStrategy = void 0;
|
|
4
|
+
const passport_strategy_1 = require("passport-strategy");
|
|
5
|
+
const node_saml_1 = require("../node-saml");
|
|
6
|
+
const url = require("url");
|
|
7
|
+
class AbstractStrategy extends passport_strategy_1.Strategy {
|
|
8
|
+
constructor(options, verify) {
|
|
9
|
+
super();
|
|
10
|
+
if (typeof options === "function") {
|
|
11
|
+
throw new Error("Mandatory SAML options missing");
|
|
12
|
+
}
|
|
13
|
+
if (!verify) {
|
|
14
|
+
throw new Error("SAML authentication strategy requires a verify function");
|
|
15
|
+
}
|
|
16
|
+
// Customizing the name can be useful to support multiple SAML configurations at the same time.
|
|
17
|
+
// Unlike other options, this one gets deleted instead of passed along.
|
|
18
|
+
if (options.name) {
|
|
19
|
+
this.name = options.name;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
this.name = "saml";
|
|
23
|
+
}
|
|
24
|
+
this._verify = verify;
|
|
25
|
+
this._validateAssertion = options.validateAssertion;
|
|
26
|
+
if (typeof(this._validateAssertion) === "undefined") {
|
|
27
|
+
this._validateAssertion = true;
|
|
28
|
+
}
|
|
29
|
+
if (this.constructor.newSamlProviderOnConstruct) {
|
|
30
|
+
this._saml = new node_saml_1.SAML(options);
|
|
31
|
+
}
|
|
32
|
+
this._passReqToCallback = !!options.passReqToCallback;
|
|
33
|
+
}
|
|
34
|
+
authenticate(req, options) {
|
|
35
|
+
if (this._saml == null) {
|
|
36
|
+
throw new Error("Can't get authenticate without a SAML provider defined.");
|
|
37
|
+
}
|
|
38
|
+
options.samlFallback = options.samlFallback || "login-request";
|
|
39
|
+
const validateCallback = ({ profile, loggedOut, }) => {
|
|
40
|
+
if (loggedOut) {
|
|
41
|
+
req.logout();
|
|
42
|
+
if (profile) {
|
|
43
|
+
if (this._saml == null) {
|
|
44
|
+
throw new Error("Can't get logout response URL without a SAML provider defined.");
|
|
45
|
+
}
|
|
46
|
+
const RelayState = (req.query && req.query.RelayState) || (req.body && req.body.RelayState);
|
|
47
|
+
return this._saml.getLogoutResponseUrl(profile, RelayState, options, redirectIfSuccess);
|
|
48
|
+
}
|
|
49
|
+
return this.pass();
|
|
50
|
+
}
|
|
51
|
+
const verified = (err, user, info) => {
|
|
52
|
+
if (err) {
|
|
53
|
+
return this.error(err);
|
|
54
|
+
}
|
|
55
|
+
if (!user) {
|
|
56
|
+
return this.fail(info, 401);
|
|
57
|
+
}
|
|
58
|
+
this.success(user, info);
|
|
59
|
+
};
|
|
60
|
+
if (this._passReqToCallback) {
|
|
61
|
+
this._verify(req, profile, verified);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
this._verify(profile, verified);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
const redirectIfSuccess = (err, url) => {
|
|
68
|
+
if (err) {
|
|
69
|
+
this.error(err);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
this.redirect(url);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
if (req.query && (req.query.SAMLResponse || req.query.SAMLRequest)) {
|
|
76
|
+
const originalQuery = url.parse(req.url).query;
|
|
77
|
+
|
|
78
|
+
//console.log("S1: " + this._validateAssertion);
|
|
79
|
+
this._saml
|
|
80
|
+
.validateRedirectAsync(req.query, originalQuery, this._validateAssertion)
|
|
81
|
+
.then(validateCallback)
|
|
82
|
+
.catch((err) => this.error(err));
|
|
83
|
+
}
|
|
84
|
+
else if (req.body && req.body.SAMLResponse) {
|
|
85
|
+
this._saml
|
|
86
|
+
.validatePostResponseAsync(req.body, this._validateAssertion)
|
|
87
|
+
.then(validateCallback)
|
|
88
|
+
.catch((err) => this.error(err));
|
|
89
|
+
}
|
|
90
|
+
else if (req.body && req.body.SAMLRequest) {
|
|
91
|
+
this._saml
|
|
92
|
+
.validatePostRequestAsync(req.body)
|
|
93
|
+
.then(validateCallback)
|
|
94
|
+
.catch((err) => this.error(err));
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
const requestHandler = {
|
|
98
|
+
"login-request": async () => {
|
|
99
|
+
try {
|
|
100
|
+
if (this._saml == null) {
|
|
101
|
+
throw new Error("Can't process login request without a SAML provider defined.");
|
|
102
|
+
}
|
|
103
|
+
const RelayState = (req.query && req.query.RelayState) || (req.body && req.body.RelayState);
|
|
104
|
+
const host = req.headers && req.headers.host;
|
|
105
|
+
if (this._saml.options.authnRequestBinding === "HTTP-POST") {
|
|
106
|
+
const data = await this._saml.getAuthorizeFormAsync(RelayState, host);
|
|
107
|
+
const res = req.res;
|
|
108
|
+
res.send(data);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
// Defaults to HTTP-Redirect
|
|
112
|
+
this.redirect(await this._saml.getAuthorizeUrlAsync(RelayState, host, options));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
this.error(err);
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
"logout-request": async () => {
|
|
120
|
+
if (this._saml == null) {
|
|
121
|
+
throw new Error("Can't process logout request without a SAML provider defined.");
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
const RelayState = (req.query && req.query.RelayState) || (req.body && req.body.RelayState);
|
|
125
|
+
this.redirect(await this._saml.getLogoutUrlAsync(req.user, RelayState, options));
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
this.error(err);
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
}[options.samlFallback];
|
|
132
|
+
if (typeof requestHandler !== "function") {
|
|
133
|
+
return this.fail(401);
|
|
134
|
+
}
|
|
135
|
+
requestHandler();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
logout(req, callback) {
|
|
139
|
+
if (this._saml == null) {
|
|
140
|
+
throw new Error("Can't logout without a SAML provider defined.");
|
|
141
|
+
}
|
|
142
|
+
const RelayState = (req.query && req.query.RelayState) || (req.body && req.body.RelayState);
|
|
143
|
+
this._saml
|
|
144
|
+
.getLogoutUrlAsync(req.user, RelayState, {})
|
|
145
|
+
.then((url) => callback(null, url))
|
|
146
|
+
.catch((err) => callback(err));
|
|
147
|
+
}
|
|
148
|
+
_generateServiceProviderMetadata(decryptionCert, signingCert) {
|
|
149
|
+
if (this._saml == null) {
|
|
150
|
+
throw new Error("Can't generate service provider metadata without a SAML provider defined.");
|
|
151
|
+
}
|
|
152
|
+
return this._saml.generateServiceProviderMetadata(decryptionCert, signingCert);
|
|
153
|
+
}
|
|
154
|
+
// This is reduntant, but helps with testing
|
|
155
|
+
error(err) {
|
|
156
|
+
super.error(err);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
exports.AbstractStrategy = AbstractStrategy;
|
|
160
|
+
class Strategy extends AbstractStrategy {
|
|
161
|
+
generateServiceProviderMetadata(decryptionCert, signingCert) {
|
|
162
|
+
return this._generateServiceProviderMetadata(decryptionCert, signingCert);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
exports.Strategy = Strategy;
|
|
166
|
+
Strategy.newSamlProviderOnConstruct = true;
|
|
167
|
+
//# sourceMappingURL=strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strategy.js","sourceRoot":"","sources":["../../src/passport-saml/strategy.ts"],"names":[],"mappings":"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","sourcesContent":["import { Strategy as PassportStrategy } from \"passport-strategy\";\nimport { SAML } from \"../node-saml\";\nimport * as url from \"url\";\nimport {\n AuthenticateOptions,\n RequestWithUser,\n SamlConfig,\n VerifyWithoutRequest,\n VerifyWithRequest,\n} from \"./types\";\nimport { Profile } from \"./types\";\n\nexport abstract class AbstractStrategy extends PassportStrategy {\n static readonly newSamlProviderOnConstruct: boolean;\n\n name: string;\n _verify: VerifyWithRequest | VerifyWithoutRequest;\n _saml: SAML | undefined;\n _passReqToCallback?: boolean;\n\n constructor(options: SamlConfig, verify: VerifyWithRequest);\n constructor(options: SamlConfig, verify: VerifyWithoutRequest);\n constructor(options: SamlConfig, verify: never) {\n super();\n if (typeof options === \"function\") {\n throw new Error(\"Mandatory SAML options missing\");\n }\n\n if (!verify) {\n throw new Error(\"SAML authentication strategy requires a verify function\");\n }\n\n // Customizing the name can be useful to support multiple SAML configurations at the same time.\n // Unlike other options, this one gets deleted instead of passed along.\n if (options.name) {\n this.name = options.name;\n } else {\n this.name = \"saml\";\n }\n\n this._verify = verify;\n if ((this.constructor as typeof Strategy).newSamlProviderOnConstruct) {\n this._saml = new SAML(options);\n }\n this._passReqToCallback = !!options.passReqToCallback;\n }\n\n authenticate(req: RequestWithUser, options: AuthenticateOptions): void {\n if (this._saml == null) {\n throw new Error(\"Can't get authenticate without a SAML provider defined.\");\n }\n\n options.samlFallback = options.samlFallback || \"login-request\";\n const validateCallback = ({\n profile,\n loggedOut,\n }: {\n profile?: Profile | null;\n loggedOut?: boolean;\n }) => {\n if (loggedOut) {\n req.logout();\n if (profile) {\n if (this._saml == null) {\n throw new Error(\"Can't get logout response URL without a SAML provider defined.\");\n }\n\n const RelayState =\n (req.query && req.query.RelayState) || (req.body && req.body.RelayState);\n return this._saml.getLogoutResponseUrl(profile, RelayState, options, redirectIfSuccess);\n }\n return this.pass();\n }\n\n const verified = (\n err: Error | null,\n user?: Record<string, unknown>,\n info?: Record<string, unknown>\n ) => {\n if (err) {\n return this.error(err);\n }\n\n if (!user) {\n return this.fail(info, 401);\n }\n\n this.success(user, info);\n };\n\n if (this._passReqToCallback) {\n (this._verify as VerifyWithRequest)(req, profile, verified);\n } else {\n (this._verify as VerifyWithoutRequest)(profile, verified);\n }\n };\n\n const redirectIfSuccess = (err: Error | null, url?: string | null) => {\n if (err) {\n this.error(err);\n } else {\n this.redirect(url!);\n }\n };\n\n if (req.query && (req.query.SAMLResponse || req.query.SAMLRequest)) {\n const originalQuery = url.parse(req.url).query;\n this._saml\n .validateRedirectAsync(req.query, originalQuery)\n .then(validateCallback)\n .catch((err) => this.error(err));\n } else if (req.body && req.body.SAMLResponse) {\n this._saml\n .validatePostResponseAsync(req.body)\n .then(validateCallback)\n .catch((err) => this.error(err));\n } else if (req.body && req.body.SAMLRequest) {\n this._saml\n .validatePostRequestAsync(req.body)\n .then(validateCallback)\n .catch((err) => this.error(err));\n } else {\n const requestHandler = {\n \"login-request\": async () => {\n try {\n if (this._saml == null) {\n throw new Error(\"Can't process login request without a SAML provider defined.\");\n }\n\n const RelayState =\n (req.query && req.query.RelayState) || (req.body && req.body.RelayState);\n const host = req.headers && req.headers.host;\n if (this._saml.options.authnRequestBinding === \"HTTP-POST\") {\n const data = await this._saml.getAuthorizeFormAsync(RelayState, host);\n const res = req.res!;\n res.send(data);\n } else {\n // Defaults to HTTP-Redirect\n this.redirect(await this._saml.getAuthorizeUrlAsync(RelayState, host, options));\n }\n } catch (err) {\n this.error(err as Error);\n }\n },\n \"logout-request\": async () => {\n if (this._saml == null) {\n throw new Error(\"Can't process logout request without a SAML provider defined.\");\n }\n\n try {\n const RelayState =\n (req.query && req.query.RelayState) || (req.body && req.body.RelayState);\n this.redirect(\n await this._saml.getLogoutUrlAsync(req.user as Profile, RelayState, options)\n );\n } catch (err) {\n this.error(err as Error);\n }\n },\n }[options.samlFallback];\n\n if (typeof requestHandler !== \"function\") {\n return this.fail(401);\n }\n\n requestHandler();\n }\n }\n\n logout(req: RequestWithUser, callback: (err: Error | null, url?: string | null) => void): void {\n if (this._saml == null) {\n throw new Error(\"Can't logout without a SAML provider defined.\");\n }\n const RelayState = (req.query && req.query.RelayState) || (req.body && req.body.RelayState);\n this._saml\n .getLogoutUrlAsync(req.user as Profile, RelayState, {})\n .then((url) => callback(null, url))\n .catch((err) => callback(err));\n }\n\n protected _generateServiceProviderMetadata(\n decryptionCert: string | null,\n signingCert?: string | null\n ): string {\n if (this._saml == null) {\n throw new Error(\"Can't generate service provider metadata without a SAML provider defined.\");\n }\n\n return this._saml.generateServiceProviderMetadata(decryptionCert, signingCert);\n }\n\n // This is reduntant, but helps with testing\n error(err: Error): void {\n super.error(err);\n }\n}\n\nexport class Strategy extends AbstractStrategy {\n static readonly newSamlProviderOnConstruct = true;\n\n generateServiceProviderMetadata(\n decryptionCert: string | null,\n signingCert?: string | null\n ): string {\n return this._generateServiceProviderMetadata(decryptionCert, signingCert);\n }\n}\n"]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type * as express from "express";
|
|
2
|
+
import * as passport from "passport";
|
|
3
|
+
import type { SamlOptions, MandatorySamlOptions } from "../node-saml/types";
|
|
4
|
+
export interface AuthenticateOptions extends passport.AuthenticateOptions {
|
|
5
|
+
samlFallback?: "login-request" | "logout-request";
|
|
6
|
+
additionalParams?: Record<string, any>;
|
|
7
|
+
}
|
|
8
|
+
export interface AuthorizeOptions extends AuthenticateOptions {
|
|
9
|
+
samlFallback?: "login-request" | "logout-request";
|
|
10
|
+
}
|
|
11
|
+
export interface StrategyOptions {
|
|
12
|
+
name?: string;
|
|
13
|
+
passReqToCallback?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* These options are availble for configuring a SAML strategy
|
|
17
|
+
*/
|
|
18
|
+
export declare type SamlConfig = Partial<SamlOptions> & StrategyOptions & MandatorySamlOptions;
|
|
19
|
+
export interface Profile {
|
|
20
|
+
issuer?: string;
|
|
21
|
+
sessionIndex?: string;
|
|
22
|
+
nameID?: string;
|
|
23
|
+
nameIDFormat?: string;
|
|
24
|
+
nameQualifier?: string;
|
|
25
|
+
spNameQualifier?: string;
|
|
26
|
+
ID?: string;
|
|
27
|
+
mail?: string;
|
|
28
|
+
email?: string;
|
|
29
|
+
["urn:oid:0.9.2342.19200300.100.1.3"]?: string;
|
|
30
|
+
getAssertionXml?(): string;
|
|
31
|
+
getAssertion?(): Record<string, unknown>;
|
|
32
|
+
getSamlResponseXml?(): string;
|
|
33
|
+
[attributeName: string]: unknown;
|
|
34
|
+
}
|
|
35
|
+
export interface RequestWithUser extends express.Request {
|
|
36
|
+
samlLogoutRequest: any;
|
|
37
|
+
user?: Profile;
|
|
38
|
+
}
|
|
39
|
+
export declare type VerifiedCallback = (err: Error | null, user?: Record<string, unknown>, info?: Record<string, unknown>) => void;
|
|
40
|
+
export declare type VerifyWithRequest = (req: express.Request, profile: Profile | null | undefined, done: VerifiedCallback) => void;
|
|
41
|
+
export declare type VerifyWithoutRequest = (profile: Profile | null | undefined, done: VerifiedCallback) => void;
|
|
42
|
+
export declare type SamlOptionsCallback = (err: Error | null, samlOptions?: SamlConfig) => void;
|
|
43
|
+
interface BaseMultiSamlConfig {
|
|
44
|
+
getSamlOptions(req: express.Request, callback: SamlOptionsCallback): void;
|
|
45
|
+
}
|
|
46
|
+
export declare type MultiSamlConfig = Partial<SamlConfig> & StrategyOptions & BaseMultiSamlConfig;
|
|
47
|
+
export declare class ErrorWithXmlStatus extends Error {
|
|
48
|
+
readonly xmlStatus: string;
|
|
49
|
+
constructor(message: string, xmlStatus: string);
|
|
50
|
+
}
|
|
51
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ErrorWithXmlStatus = void 0;
|
|
4
|
+
class ErrorWithXmlStatus extends Error {
|
|
5
|
+
constructor(message, xmlStatus) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.xmlStatus = xmlStatus;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.ErrorWithXmlStatus = ErrorWithXmlStatus;
|
|
11
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/passport-saml/types.ts"],"names":[],"mappings":";;;AAsEA,MAAa,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAe,EAAkB,SAAiB;QAC5D,KAAK,CAAC,OAAO,CAAC,CAAC;QAD4B,cAAS,GAAT,SAAS,CAAQ;IAE9D,CAAC;CACF;AAJD,gDAIC","sourcesContent":["import type * as express from \"express\";\nimport * as passport from \"passport\";\nimport type { SamlOptions, MandatorySamlOptions, SamlIDPListConfig } from \"../node-saml/types\";\n\nexport interface AuthenticateOptions extends passport.AuthenticateOptions {\n samlFallback?: \"login-request\" | \"logout-request\";\n additionalParams?: Record<string, any>;\n}\n\nexport interface AuthorizeOptions extends AuthenticateOptions {\n samlFallback?: \"login-request\" | \"logout-request\";\n}\n\nexport interface StrategyOptions {\n name?: string;\n passReqToCallback?: boolean;\n}\n\n/**\n * These options are availble for configuring a SAML strategy\n */\nexport type SamlConfig = Partial<SamlOptions> & StrategyOptions & MandatorySamlOptions;\n\nexport interface Profile {\n issuer?: string;\n sessionIndex?: string;\n nameID?: string;\n nameIDFormat?: string;\n nameQualifier?: string;\n spNameQualifier?: string;\n ID?: string;\n mail?: string; // InCommon Attribute urn:oid:0.9.2342.19200300.100.1.3\n email?: string; // `mail` if not present in the assertion\n [\"urn:oid:0.9.2342.19200300.100.1.3\"]?: string;\n getAssertionXml?(): string; // get the raw assertion XML\n getAssertion?(): Record<string, unknown>; // get the assertion XML parsed as a JavaScript object\n getSamlResponseXml?(): string; // get the raw SAML response XML\n [attributeName: string]: unknown; // arbitrary `AttributeValue`s\n}\n\nexport interface RequestWithUser extends express.Request {\n samlLogoutRequest: any;\n user?: Profile;\n}\n\nexport type VerifiedCallback = (\n err: Error | null,\n user?: Record<string, unknown>,\n info?: Record<string, unknown>\n) => void;\n\nexport type VerifyWithRequest = (\n req: express.Request,\n profile: Profile | null | undefined,\n done: VerifiedCallback\n) => void;\n\nexport type VerifyWithoutRequest = (\n profile: Profile | null | undefined,\n done: VerifiedCallback\n) => void;\n\nexport type SamlOptionsCallback = (err: Error | null, samlOptions?: SamlConfig) => void;\n\ninterface BaseMultiSamlConfig {\n getSamlOptions(req: express.Request, callback: SamlOptionsCallback): void;\n}\n\nexport type MultiSamlConfig = Partial<SamlConfig> & StrategyOptions & BaseMultiSamlConfig;\n\nexport class ErrorWithXmlStatus extends Error {\n constructor(message: string, public readonly xmlStatus: string) {\n super(message);\n }\n}\n"]}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "passport-saml",
|
|
3
|
+
"version": "3.2.1",
|
|
4
|
+
"description": "SAML 2.0 authentication strategy for Passport",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"saml",
|
|
7
|
+
"adfs",
|
|
8
|
+
"sso",
|
|
9
|
+
"shibboleth"
|
|
10
|
+
],
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://github.com/node-saml/passport-saml.git"
|
|
14
|
+
},
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"author": {
|
|
17
|
+
"name": "Henri Bergius",
|
|
18
|
+
"email": "henri.bergius@iki.fi",
|
|
19
|
+
"url": "http://bergie.iki.fi"
|
|
20
|
+
},
|
|
21
|
+
"contributors": [
|
|
22
|
+
"Michael Bosworth",
|
|
23
|
+
"Herbert Vojčík",
|
|
24
|
+
"Peter Loer",
|
|
25
|
+
"Mark Stosberg",
|
|
26
|
+
"Chris Barth",
|
|
27
|
+
"Andrii Kostenko"
|
|
28
|
+
],
|
|
29
|
+
"main": "./lib/passport-saml",
|
|
30
|
+
"files": [
|
|
31
|
+
"lib",
|
|
32
|
+
"README.md",
|
|
33
|
+
"LICENSE"
|
|
34
|
+
],
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsc",
|
|
37
|
+
"changelog": "gren changelog --override --generate",
|
|
38
|
+
"lint": "eslint --ext .ts \"**/*.ts\" --cache",
|
|
39
|
+
"lint-watch": "onchange -k -p 100 \"**/*.ts\" -- eslint {{file}}",
|
|
40
|
+
"lint:fix": "eslint --ext .ts --fix src",
|
|
41
|
+
"prepare": "tsc",
|
|
42
|
+
"prettier-check": "prettier --config .prettierrc.json --check .",
|
|
43
|
+
"prettier-format": "prettier --config .prettierrc.json --write .",
|
|
44
|
+
"prettier-watch": "onchange -k -p 100 \".\" -- prettier --config .prettierrc.json --write {{file}}",
|
|
45
|
+
"release": "release-it",
|
|
46
|
+
"test": "npm run prettier-check && npm run lint && npm run tsc && mocha",
|
|
47
|
+
"test-watch": "mocha --watch",
|
|
48
|
+
"tsc": "tsc",
|
|
49
|
+
"tsc-watch": "tsc --watch",
|
|
50
|
+
"watch": "concurrently --kill-others \"npm:*-watch\""
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"@xmldom/xmldom": "^0.7.5",
|
|
54
|
+
"debug": "^4.3.2",
|
|
55
|
+
"passport-strategy": "^1.0.0",
|
|
56
|
+
"xml-crypto": "^2.1.3",
|
|
57
|
+
"xml-encryption": "^2.0.0",
|
|
58
|
+
"xml2js": "^0.4.23",
|
|
59
|
+
"xmlbuilder": "^15.1.1"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@types/debug": "^4.1.7",
|
|
63
|
+
"@types/mocha": "^8.2.3",
|
|
64
|
+
"@types/node": "^14.17.17",
|
|
65
|
+
"@types/passport-strategy": "^0.2.35",
|
|
66
|
+
"@types/request": "^2.48.7",
|
|
67
|
+
"@types/sinon": "^10.0.2",
|
|
68
|
+
"@types/xml-crypto": "^1.4.2",
|
|
69
|
+
"@types/xml-encryption": "^1.2.1",
|
|
70
|
+
"@types/xml2js": "^0.4.9",
|
|
71
|
+
"@typescript-eslint/eslint-plugin": "^4.31.1",
|
|
72
|
+
"@typescript-eslint/parser": "^4.31.1",
|
|
73
|
+
"body-parser": "^1.19.0",
|
|
74
|
+
"choma": "^1.2.1",
|
|
75
|
+
"concurrently": "^6.2.1",
|
|
76
|
+
"eslint": "^7.32.0",
|
|
77
|
+
"eslint-config-prettier": "^8.3.0",
|
|
78
|
+
"eslint-plugin-prettier": "^3.4.1",
|
|
79
|
+
"express": "^4.17.1",
|
|
80
|
+
"github-release-notes": "^0.17.3",
|
|
81
|
+
"mocha": "^8.4.0",
|
|
82
|
+
"onchange": "^7.1.0",
|
|
83
|
+
"passport": "^0.4.1",
|
|
84
|
+
"prettier": "^2.4.1",
|
|
85
|
+
"prettier-plugin-packagejson": "^2.2.12",
|
|
86
|
+
"release-it": "^14.12.3",
|
|
87
|
+
"request": "^2.83.0",
|
|
88
|
+
"should": "^13.2.3",
|
|
89
|
+
"sinon": "^10.0.0",
|
|
90
|
+
"ts-node": "^9.1.1",
|
|
91
|
+
"typescript": "^4.4.3"
|
|
92
|
+
},
|
|
93
|
+
"engines": {
|
|
94
|
+
"node": ">= 12"
|
|
95
|
+
}
|
|
96
|
+
}
|
package/util/auth.js
CHANGED
|
@@ -324,7 +324,7 @@ var syncProfile = exports.syncProfile = function(req, res, strategy, domainId, p
|
|
|
324
324
|
}
|
|
325
325
|
}
|
|
326
326
|
|
|
327
|
-
_LOCK([CACHE_IDENTIFIER], function(releaseLockFn) {
|
|
327
|
+
_LOCK([CACHE_IDENTIFIER], function(err, releaseLockFn) {
|
|
328
328
|
_handleSyncUser(req, strategy, settings, key, domainId, providerId, providerUserId, token, refreshToken, userObject, groupsArray, function (err, gitanaUser) {
|
|
329
329
|
|
|
330
330
|
if (err) {
|
package/util/cloudcms.js
CHANGED
|
@@ -1072,7 +1072,7 @@ exports = module.exports = function()
|
|
|
1072
1072
|
r.download = function(contentStore, gitana, repositoryId, branchId, nodeId, attachmentId, nodePath, locale, forceReload, callback)
|
|
1073
1073
|
{
|
|
1074
1074
|
// claim a lock around this node for this server
|
|
1075
|
-
_LOCK(contentStore, _lock_identifier(repositoryId, branchId, nodeId), function(releaseLockFn) {
|
|
1075
|
+
_LOCK(contentStore, _lock_identifier(repositoryId, branchId, nodeId), function(err, releaseLockFn) {
|
|
1076
1076
|
|
|
1077
1077
|
// workhorse - pass releaseLockFn back to callback
|
|
1078
1078
|
downloadNode(contentStore, gitana, repositoryId, branchId, nodeId, attachmentId, nodePath, locale, forceReload, function (err, filePath, cacheInfo) {
|
|
@@ -1085,7 +1085,7 @@ exports = module.exports = function()
|
|
|
1085
1085
|
r.preview = function(contentStore, gitana, repositoryId, branchId, nodeId, nodePath, attachmentId, locale, previewId, size, mimetype, forceReload, callback)
|
|
1086
1086
|
{
|
|
1087
1087
|
// claim a lock around this node for this server
|
|
1088
|
-
_LOCK(contentStore, _lock_identifier(repositoryId, branchId, nodeId), function(releaseLockFn) {
|
|
1088
|
+
_LOCK(contentStore, _lock_identifier(repositoryId, branchId, nodeId), function(err, releaseLockFn) {
|
|
1089
1089
|
|
|
1090
1090
|
// workhorse - pass releaseLockFn back to callback
|
|
1091
1091
|
previewNode(contentStore, gitana, repositoryId, branchId, nodeId, nodePath, attachmentId, locale, previewId, size, mimetype, forceReload, function(err, filePath, cacheInfo) {
|
|
@@ -1098,7 +1098,7 @@ exports = module.exports = function()
|
|
|
1098
1098
|
r.invalidate = function(contentStore, repositoryId, branchId, nodeId, paths, callback)
|
|
1099
1099
|
{
|
|
1100
1100
|
// claim a lock around this node for this server
|
|
1101
|
-
_LOCK(contentStore, _lock_identifier(repositoryId, branchId, nodeId), function(releaseLockFn) {
|
|
1101
|
+
_LOCK(contentStore, _lock_identifier(repositoryId, branchId, nodeId), function(err, releaseLockFn) {
|
|
1102
1102
|
|
|
1103
1103
|
invalidateNode(contentStore, repositoryId, branchId, nodeId, function () {
|
|
1104
1104
|
|
|
@@ -1118,7 +1118,7 @@ exports = module.exports = function()
|
|
|
1118
1118
|
r.downloadAttachable = function(contentStore, gitana, datastoreTypeId, datastoreId, objectTypeId, objectId, attachmentId, locale, forceReload, callback)
|
|
1119
1119
|
{
|
|
1120
1120
|
// claim a lock around this node for this server
|
|
1121
|
-
_LOCK(contentStore, _lock_identifier(datastoreId, objectId), function(releaseLockFn) {
|
|
1121
|
+
_LOCK(contentStore, _lock_identifier(datastoreId, objectId), function(err, releaseLockFn) {
|
|
1122
1122
|
|
|
1123
1123
|
// workhorse - pass releaseLockFn back to callback
|
|
1124
1124
|
downloadAttachable(contentStore, gitana, datastoreTypeId, datastoreId, objectTypeId, objectId, attachmentId, locale, forceReload, function(err, filePath, cacheInfo) {
|
|
@@ -1131,7 +1131,7 @@ exports = module.exports = function()
|
|
|
1131
1131
|
r.previewAttachable = function(contentStore, gitana, datastoreTypeId, datastoreId, objectTypeId, objectId, attachmentId, locale, previewId, size, mimetype, forceReload, callback)
|
|
1132
1132
|
{
|
|
1133
1133
|
// claim a lock around this node for this server
|
|
1134
|
-
_LOCK(contentStore, _lock_identifier(datastoreId, objectId), function(releaseLockFn) {
|
|
1134
|
+
_LOCK(contentStore, _lock_identifier(datastoreId, objectId), function(err, releaseLockFn) {
|
|
1135
1135
|
|
|
1136
1136
|
// workhorse - pass releaseLockFn back to callback
|
|
1137
1137
|
previewAttachable(contentStore, gitana, datastoreTypeId, datastoreId, objectTypeId, objectId, attachmentId, locale, previewId, size, mimetype, forceReload, function (err, filePath, cacheInfo) {
|
|
@@ -1144,7 +1144,7 @@ exports = module.exports = function()
|
|
|
1144
1144
|
r.invalidateAttachable = function(contentStore, datastoreTypeId, datastoreId, objectTypeId, objectId, callback)
|
|
1145
1145
|
{
|
|
1146
1146
|
// claim a lock around this node for this server
|
|
1147
|
-
_LOCK(contentStore, _lock_identifier(datastoreId, objectId), function(releaseLockFn) {
|
|
1147
|
+
_LOCK(contentStore, _lock_identifier(datastoreId, objectId), function(err, releaseLockFn) {
|
|
1148
1148
|
|
|
1149
1149
|
// TODO: not implemented
|
|
1150
1150
|
callback();
|
package/util/proxy-factory.js
CHANGED
|
@@ -15,7 +15,8 @@ var exports = module.exports;
|
|
|
15
15
|
|
|
16
16
|
var _LOCK = function(lockIdentifiers, workFunction)
|
|
17
17
|
{
|
|
18
|
-
|
|
18
|
+
var name = lockIdentifiers.join("_");
|
|
19
|
+
process.locks.lock(name, workFunction);
|
|
19
20
|
};
|
|
20
21
|
|
|
21
22
|
var NAMED_PROXY_HANDLERS_CACHE = require("lru-cache")({
|
|
@@ -34,9 +35,15 @@ var acquireProxyHandler = exports.acquireProxyHandler = function(proxyTarget, pa
|
|
|
34
35
|
{
|
|
35
36
|
return callback(null, _cachedHandler);
|
|
36
37
|
}
|
|
37
|
-
|
|
38
|
+
|
|
38
39
|
// take out a thread lock
|
|
39
|
-
_LOCK(["acquireProxyHandler", name], function(releaseLockFn) {
|
|
40
|
+
_LOCK(["acquireProxyHandler", name], function(err, releaseLockFn) {
|
|
41
|
+
|
|
42
|
+
if (err)
|
|
43
|
+
{
|
|
44
|
+
// failed to acquire lock
|
|
45
|
+
return callback(err);
|
|
46
|
+
}
|
|
40
47
|
|
|
41
48
|
// second check to make sure another thread didn't create the handler in the meantime
|
|
42
49
|
_cachedHandler = NAMED_PROXY_HANDLERS_CACHE[name];
|
|
@@ -48,7 +55,7 @@ var acquireProxyHandler = exports.acquireProxyHandler = function(proxyTarget, pa
|
|
|
48
55
|
|
|
49
56
|
// create the proxy handler and cache it into LRU cache
|
|
50
57
|
_cachedHandler = createProxyHandler(proxyTarget, pathPrefix);
|
|
51
|
-
|
|
58
|
+
|
|
52
59
|
// store back into LRU cache
|
|
53
60
|
NAMED_PROXY_HANDLERS_CACHE[name] = _cachedHandler;
|
|
54
61
|
|
|
@@ -141,8 +148,16 @@ var createProxyHandler = function(proxyTarget, pathPrefix)
|
|
|
141
148
|
{
|
|
142
149
|
var identifier = req.identity_properties.provider_id + "/" + req.identity_properties.user_identifier;
|
|
143
150
|
|
|
144
|
-
_LOCK([identifier], function(releaseLockFn) {
|
|
145
|
-
|
|
151
|
+
_LOCK([identifier], function(err, releaseLockFn) {
|
|
152
|
+
|
|
153
|
+
if (err)
|
|
154
|
+
{
|
|
155
|
+
// failed to acquire lock
|
|
156
|
+
console.log("FAILED TO ACQUIRE LOCK", err);
|
|
157
|
+
req.log("FAILED TO ACQUIRE LOCK", err);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
146
161
|
var cleanup = function (full)
|
|
147
162
|
{
|
|
148
163
|
delete Gitana.APPS[req.identity_properties.token];
|
|
@@ -375,7 +390,7 @@ var createProxyHandler = function(proxyTarget, pathPrefix)
|
|
|
375
390
|
req.headers["authorization"] = "Bearer " + req.gitana_proxy_access_token;
|
|
376
391
|
}
|
|
377
392
|
}
|
|
378
|
-
|
|
393
|
+
|
|
379
394
|
if (pathPrefix) {
|
|
380
395
|
req.url = path.join(pathPrefix, req.url);
|
|
381
396
|
}
|
package/util/redis.js
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
|
+
var redis = require("redis");
|
|
2
|
+
const logFactory = require("./logger");
|
|
3
|
+
|
|
1
4
|
exports = module.exports;
|
|
2
5
|
|
|
6
|
+
var redisLogger = exports.redisLogger = function(name, prefix, defaultLevel)
|
|
7
|
+
{
|
|
8
|
+
if (!defaultLevel) {
|
|
9
|
+
defaultLevel = "error";
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
var level = null;
|
|
13
|
+
|
|
14
|
+
// allow for global redis default
|
|
15
|
+
// allow for prefix specific
|
|
16
|
+
if (typeof(process.env["CLOUDCMS_REDIS_DEBUG_LEVEL"]) !== "undefined") {
|
|
17
|
+
level = "" + process.env["CLOUDCMS_REDIS_DEBUG_LEVEL"].toLowerCase();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (!level && prefix)
|
|
21
|
+
{
|
|
22
|
+
if (typeof(process.env[prefix + "REDIS_DEBUG_LEVEL"]) !== "undefined") {
|
|
23
|
+
level = "" + process.env[prefix + "REDIS_DEBUG_LEVEL"].toLowerCase();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!level) {
|
|
28
|
+
level = defaultLevel;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
var logger = logFactory(name);
|
|
32
|
+
logger.setLevel(level);
|
|
33
|
+
|
|
34
|
+
return logger;
|
|
35
|
+
}
|
|
36
|
+
|
|
3
37
|
var redisOptions = exports.redisOptions = function(config, prefix)
|
|
4
38
|
{
|
|
5
39
|
if (!config) {
|
|
@@ -57,7 +91,23 @@ var redisOptions = exports.redisOptions = function(config, prefix)
|
|
|
57
91
|
|
|
58
92
|
var redisOptions = {};
|
|
59
93
|
redisOptions.url = redisUrl;
|
|
60
|
-
redisOptions.legacyMode = true;
|
|
61
94
|
|
|
62
95
|
return redisOptions;
|
|
63
96
|
}
|
|
97
|
+
|
|
98
|
+
var createAndConnect = exports.createAndConnect = async function(redisOptions, callback)
|
|
99
|
+
{
|
|
100
|
+
var client = redis.createClient(redisOptions);
|
|
101
|
+
|
|
102
|
+
var connectErr = null;
|
|
103
|
+
client.on('error', function(err) {
|
|
104
|
+
console.log('Redis Client Error', err);
|
|
105
|
+
connectErr = err;
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// connect
|
|
109
|
+
await client.connect();
|
|
110
|
+
//console.log("Connected to redis, options: " + JSON.stringify(redisOptions, null, 2) + ", err: " + connectErr + ", client: " + client);
|
|
111
|
+
|
|
112
|
+
return callback(connectErr, client);
|
|
113
|
+
}
|