infinispan 0.13.0 → 0.15.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.
@@ -16,6 +16,8 @@
16
16
  * References:
17
17
  * - [RFC 2831](http://tools.ietf.org/html/rfc2831)
18
18
  *
19
+ * @param {Object} options Configuration options.
20
+ * @returns {void}
19
21
  * @api public
20
22
  */
21
23
  function Mechanism(options) {
@@ -36,7 +38,8 @@
36
38
  * - `serviceType`
37
39
  * - `authzid` authorization identity (optional)
38
40
  *
39
- * @param {Object} cred
41
+ * @param {Object} cred Credentials containing username, password, host, serviceType, and optional authzid.
42
+ * @returns {String} The encoded DIGEST response string.
40
43
  * @api public
41
44
  */
42
45
  Mechanism.prototype.response = function (cred) {
@@ -56,9 +59,9 @@
56
59
  // the fact that TLS has largely superseded this functionality,
57
60
  // implementing it is a low priority.
58
61
 
59
- var uri = cred.serviceType + '/' + cred.host;
62
+ var uri = `${cred.serviceType }/${ cred.host}`;
60
63
  if (cred.serviceName && cred.host !== cred.serviceName) {
61
- uri += '/' + serviceName;
64
+ uri += `/${ serviceName}`;
62
65
  }
63
66
  var realm = cred.realm || this._realm || ''
64
67
  , cnonce = this._genNonce()
@@ -68,13 +71,13 @@
68
71
  , ha2
69
72
  , digest;
70
73
  var str = '';
71
- str += 'username="' + cred.username + '"';
72
- if (realm) { str += ',realm="' + realm + '"'; };
73
- str += ',nonce="' + this._nonce + '"';
74
- str += ',cnonce="' + cnonce + '"';
75
- str += ',nc=' + nc;
76
- str += ',qop=' + qop;
77
- str += ',digest-uri="' + uri + '"';
74
+ str += `username="${ cred.username }"`;
75
+ if (realm) { str += `,realm="${ realm }"`; };
76
+ str += `,nonce="${ this._nonce }"`;
77
+ str += `,cnonce="${ cnonce }"`;
78
+ str += `,nc=${ nc}`;
79
+ str += `,qop=${ qop}`;
80
+ str += `,digest-uri="${ uri }"`;
78
81
  var base = crypto.createHash('md5')
79
82
  .update(cred.username)
80
83
  .update(':')
@@ -112,17 +115,17 @@
112
115
  .update(':')
113
116
  .update(ha2)
114
117
  .digest('hex');
115
- str += ',response=' + digest;
118
+ str += `,response=${ digest}`;
116
119
  if (this._charset == 'utf-8') { str += ',charset=utf-8'; }
117
- if (cred.authzid) { str += 'authzid="' + cred.authzid + '"'; }
120
+ if (cred.authzid) { str += `authzid="${ cred.authzid }"`; }
118
121
  return str;
119
122
  };
120
123
 
121
124
  /**
122
125
  * Decode a challenge issued by the server.
123
126
  *
124
- * @param {String} chal
125
- * @return {Mechanism} for chaining
127
+ * @param {String} chal Challenge string from server.
128
+ * @returns {Mechanism} for chaining
126
129
  * @api public
127
130
  */
128
131
  Mechanism.prototype.challenge = function (chal) {
@@ -146,6 +149,8 @@
146
149
  /**
147
150
  * Parse challenge.
148
151
  *
152
+ * @param {String} chal Challenge string to parse.
153
+ * @returns {Object} Parsed directives.
149
154
  * @api private
150
155
  */
151
156
  function parse(chal) {
@@ -166,8 +171,8 @@
166
171
  * genNonce(10)();
167
172
  * // => "FDaS435D2z"
168
173
  *
169
- * @param {Number} len
170
- * @return {Function}
174
+ * @param {Number} len Length of the nonce.
175
+ * @returns {Function} A function that generates a random nonce.
171
176
  * @api private
172
177
  */
173
178
  function genNonce(len) {
@@ -180,7 +185,7 @@
180
185
  buf.push(chars[Math.random() * charlen | 0]);
181
186
  }
182
187
  return buf.join('');
183
- }
188
+ };
184
189
  }
185
190
 
186
191
  exports = module.exports = Mechanism;
@@ -14,11 +14,12 @@
14
14
  * This class implements the EXTERNAL SASL mechanism.
15
15
  *
16
16
  * The EXTERNAL SASL mechanism provides support for authentication using
17
- * credentials established by external means.
17
+ * credentials established by external means.
18
18
  *
19
19
  * References:
20
20
  * - [RFC 4422](http://tools.ietf.org/html/rfc4422)
21
21
  *
22
+ * @returns {void}
22
23
  * @api public
23
24
  */
24
25
  function Mechanism() {
@@ -33,7 +34,8 @@
33
34
  * Options:
34
35
  * - `authzid` authorization identity (optional)
35
36
  *
36
- * @param {Object} cred
37
+ * @param {Object} cred Credentials containing optional authzid.
38
+ * @returns {String} The authorization identity or empty string.
37
39
  * @api public
38
40
  */
39
41
  Mechanism.prototype.response = function (cred) {
@@ -43,10 +45,11 @@
43
45
  /**
44
46
  * Decode a challenge issued by the server.
45
47
  *
46
- * @param {String} chal
48
+ * @param {String} chal Challenge string from server.
49
+ * @returns {void}
47
50
  * @api public
48
51
  */
49
- Mechanism.prototype.challenge = function (chal) {
52
+ Mechanism.prototype.challenge = function (chal) { // eslint-disable-line no-unused-vars
50
53
  };
51
54
 
52
55
  exports = module.exports = Mechanism;
@@ -11,6 +11,7 @@
11
11
  /**
12
12
  * `Factory` constructor.
13
13
  *
14
+ * @returns {void}
14
15
  * @api public
15
16
  */
16
17
  function Factory() {
@@ -27,9 +28,9 @@
27
28
  *
28
29
  * factory.use('XFOO', FooMechanism);
29
30
  *
30
- * @param {String|Mechanism} name
31
- * @param {Mechanism} mech
32
- * @return {Factory} for chaining
31
+ * @param {String|Mechanism} name Mechanism name or constructor.
32
+ * @param {Mechanism} mech Mechanism constructor when name is a string.
33
+ * @returns {Factory} for chaining
33
34
  * @api public
34
35
  */
35
36
  Factory.prototype.use = function(name, mech) {
@@ -50,8 +51,8 @@
50
51
  *
51
52
  * var mech = factory.create(['FOO', 'BAR']);
52
53
  *
53
- * @param {Array} mechs
54
- * @return {Mechanism}
54
+ * @param {Array} mechs List of supported mechanism names.
55
+ * @returns {Mechanism} A new mechanism instance or null.
55
56
  * @api public
56
57
  */
57
58
  Factory.prototype.create = function(mechs) {
@@ -18,6 +18,7 @@
18
18
  * References:
19
19
  * - [RFC 4616](http://tools.ietf.org/html/rfc4616)
20
20
  *
21
+ * @returns {void}
21
22
  * @api public
22
23
  */
23
24
  function Mechanism() {
@@ -33,13 +34,14 @@
33
34
  * - `token` an OAuth token
34
35
  * - `authzid` authorization identity (optional)
35
36
  *
36
- * @param {Object} cred
37
+ * @param {Object} cred Credentials containing token and optional authzid.
38
+ * @returns {String} The encoded OAUTHBEARER response string.
37
39
  * @api public
38
40
  */
39
41
  Mechanism.prototype.response = function (cred) {
40
42
  var str = 'n,';
41
43
  if (cred.authzid) {
42
- str += 'a=' + cred.authzid;
44
+ str += `a=${ cred.authzid}`;
43
45
  }
44
46
  str += ',%x01,auth=Bearer ';
45
47
  str += cred.token;
@@ -50,11 +52,11 @@
50
52
  /**
51
53
  * Decode a challenge issued by the server.
52
54
  *
53
- * @param {String} chal
54
- * @return {Mechanism} for chaining
55
+ * @param {String} chal Challenge string from server.
56
+ * @returns {Mechanism} for chaining
55
57
  * @api public
56
58
  */
57
- Mechanism.prototype.challenge = function (chal) {
59
+ Mechanism.prototype.challenge = function (chal) { // eslint-disable-line no-unused-vars
58
60
  return this;
59
61
  };
60
62
 
package/lib/sasl/plain.js CHANGED
@@ -20,6 +20,7 @@
20
20
  * References:
21
21
  * - [RFC 4616](http://tools.ietf.org/html/rfc4616)
22
22
  *
23
+ * @returns {void}
23
24
  * @api public
24
25
  */
25
26
  function Mechanism() {
@@ -36,7 +37,8 @@
36
37
  * - `password`
37
38
  * - `authzid` authorization identity (optional)
38
39
  *
39
- * @param {Object} cred
40
+ * @param {Object} cred Credentials containing username, password, and optional authzid.
41
+ * @returns {String} The encoded PLAIN response string.
40
42
  * @api public
41
43
  */
42
44
  Mechanism.prototype.response = function (cred) {
@@ -52,11 +54,11 @@
52
54
  /**
53
55
  * Decode a challenge issued by the server.
54
56
  *
55
- * @param {String} chal
56
- * @return {Mechanism} for chaining
57
+ * @param {String} chal Challenge string from server.
58
+ * @returns {Mechanism} for chaining
57
59
  * @api public
58
60
  */
59
- Mechanism.prototype.challenge = function (chal) {
61
+ Mechanism.prototype.challenge = function (chal) { // eslint-disable-line no-unused-vars
60
62
  return this;
61
63
  };
62
64
 
package/lib/sasl/scram.js CHANGED
@@ -11,6 +11,12 @@
11
11
  var CLIENT_KEY = 'Client Key';
12
12
  var SERVER_KEY = 'Server Key';
13
13
 
14
+ /**
15
+ * Constructs a SCRAM SASL mechanism instance.
16
+ * @param {Object} [options] Optional configuration with a genNonce function.
17
+ * @constructs Mechanism
18
+ * @returns {void}
19
+ */
14
20
  function Mechanism(options) {
15
21
  options = options || {};
16
22
  this._genNonce = options.genNonce || utils.genNonce;
@@ -40,6 +46,8 @@
40
46
  /**
41
47
  * Parse challenge.
42
48
  *
49
+ * @param {String} chal Challenge string to parse.
50
+ * @returns {Object} Parsed key-value pairs.
43
51
  * @api private
44
52
  */
45
53
  function parse(chal) {
@@ -60,15 +68,15 @@
60
68
 
61
69
  var authzid = '';
62
70
  if (cred.authzid) {
63
- authzid = 'a=' + utils.saslname(cred.authzid);
71
+ authzid = `a=${ utils.saslname(cred.authzid)}`;
64
72
  }
65
73
 
66
- mech._gs2Header = 'n,' + authzid + ',';
74
+ mech._gs2Header = `n,${ authzid },`;
67
75
 
68
- var nonce = 'r=' + mech._cnonce;
69
- var username = 'n=' + utils.saslname(cred.username || '');
76
+ var nonce = `r=${ mech._cnonce}`;
77
+ var username = `n=${ utils.saslname(cred.username || '')}`;
70
78
 
71
- mech._clientFirstMessageBare = username + ',' + nonce;
79
+ mech._clientFirstMessageBare = `${username },${ nonce}`;
72
80
  var result = mech._gs2Header + mech._clientFirstMessageBare;
73
81
 
74
82
  mech._stage = 'two';
@@ -79,11 +87,11 @@
79
87
 
80
88
  RESP.two = function (mech, cred) {
81
89
  var gs2Header = Buffer.from(mech._gs2Header).toString('base64');
82
- mech._clientFinalMessageWithoutProof = 'c=' + gs2Header + ',r=' + mech._nonce;
90
+ mech._clientFinalMessageWithoutProof = `c=${ gs2Header },r=${ mech._nonce}`;
83
91
 
84
92
  var saltedPassword, clientKey, serverKey;
85
93
 
86
- var algorithm = cred.mechanism.substring(6).toLowerCase().replace("-", "");
94
+ var algorithm = cred.mechanism.substring(6).toLowerCase().replace('-', '');
87
95
 
88
96
  // If our cached salt is the same, we can reuse cached credentials to speed
89
97
  // up the hashing process.
@@ -103,16 +111,16 @@
103
111
  }
104
112
 
105
113
  var storedKey = bitops.H(algorithm, clientKey);
106
- var authMessage = mech._clientFirstMessageBare + ',' +
107
- mech._challenge + ',' +
108
- mech._clientFinalMessageWithoutProof;
114
+ var authMessage = `${mech._clientFirstMessageBare },${
115
+ mech._challenge },${
116
+ mech._clientFinalMessageWithoutProof}`;
109
117
  var clientSignature = bitops.HMAC(algorithm, storedKey, authMessage);
110
118
 
111
119
  var clientProof = bitops.XOR(clientKey, clientSignature).toString('base64');
112
120
 
113
121
  mech._serverSignature = bitops.HMAC(algorithm, serverKey, authMessage);
114
122
 
115
- var result = mech._clientFinalMessageWithoutProof + ',p=' + clientProof;
123
+ var result = `${mech._clientFinalMessageWithoutProof },p=${ clientProof}`;
116
124
 
117
125
  mech._stage = 'final';
118
126
 
package/lib/uri.js ADDED
@@ -0,0 +1,206 @@
1
+ 'use strict';
2
+
3
+ (function() {
4
+
5
+ var _ = require('underscore');
6
+
7
+ var DEFAULT_PORT = 11222;
8
+
9
+ var QUERY_PARAMS = {
10
+ 'sasl_mechanism': { path: ['authentication', 'saslMechanism'], type: 'string' },
11
+ 'trust_store_file_name': { path: ['ssl', 'trustCerts'], type: 'string_array' },
12
+ 'trust_ca': { path: ['ssl', 'trustCerts'], type: 'string_array' },
13
+ 'key_store_file_name': { path: ['ssl', 'clientAuth', 'cert'], type: 'string' },
14
+ 'client_cert': { path: ['ssl', 'clientAuth', 'cert'], type: 'string' },
15
+ 'key_store_password': { path: ['ssl', 'clientAuth', 'key'], type: 'string' },
16
+ 'client_key': { path: ['ssl', 'clientAuth', 'key'], type: 'string' },
17
+ 'sni_host_name': { path: ['ssl', 'sniHostName'], type: 'string' },
18
+ 'sni_host': { path: ['ssl', 'sniHostName'], type: 'string' },
19
+ 'max_retries': { path: ['maxRetries'], type: 'int' },
20
+ 'cache_name': { path: ['cacheName'], type: 'string' }
21
+ };
22
+
23
+ /**
24
+ * Checks whether the argument is a Hot Rod URI string.
25
+ * @param {*} arg Value to check.
26
+ * @returns {boolean} True if the argument is a hotrod:// or hotrods:// URI.
27
+ */
28
+ function isHotrodURI(arg) {
29
+ return _.isString(arg) &&
30
+ (arg.indexOf('hotrod://') === 0 || arg.indexOf('hotrods://') === 0);
31
+ }
32
+
33
+ /**
34
+ * Splits a host string into host and port, handling IPv6 bracket notation.
35
+ * @param {string} hostStr Host string like "host:port" or "[::1]:port".
36
+ * @returns {{host: string, port: number}} Parsed host and port.
37
+ */
38
+ function splitHostPort(hostStr) {
39
+ hostStr = hostStr.trim();
40
+ if (hostStr.length === 0) {
41
+ throw new Error('Empty host in URI');
42
+ }
43
+
44
+ // IPv6 bracket notation: [::1]:port
45
+ if (hostStr.charAt(0) === '[') {
46
+ var closeBracket = hostStr.indexOf(']');
47
+ if (closeBracket === -1) {
48
+ throw new Error(`Invalid IPv6 address, missing closing bracket: ${hostStr}`);
49
+ }
50
+ var ipv6Host = hostStr.substring(1, closeBracket);
51
+ var afterBracket = hostStr.substring(closeBracket + 1);
52
+ if (afterBracket.length === 0) {
53
+ return { host: ipv6Host, port: DEFAULT_PORT };
54
+ }
55
+ if (afterBracket.charAt(0) === ':') {
56
+ var ipv6Port = parseInt(afterBracket.substring(1), 10);
57
+ if (isNaN(ipv6Port)) {
58
+ throw new Error(`Invalid port in URI: ${afterBracket.substring(1)}`);
59
+ }
60
+ return { host: ipv6Host, port: ipv6Port };
61
+ }
62
+ throw new Error(`Invalid IPv6 host format: ${hostStr}`);
63
+ }
64
+
65
+ var lastColon = hostStr.lastIndexOf(':');
66
+ if (lastColon === -1) {
67
+ return { host: hostStr, port: DEFAULT_PORT };
68
+ }
69
+
70
+ var host = hostStr.substring(0, lastColon);
71
+ var portStr = hostStr.substring(lastColon + 1);
72
+ var port = parseInt(portStr, 10);
73
+ if (isNaN(port)) {
74
+ throw new Error(`Invalid port in URI: ${portStr}`);
75
+ }
76
+ return { host: host, port: port };
77
+ }
78
+
79
+ /**
80
+ * Sets a nested value in an object given a path array.
81
+ * @param {Object} obj Target object.
82
+ * @param {string[]} path Array of keys.
83
+ * @param {*} value Value to set.
84
+ * @returns {void}
85
+ */
86
+ function setNested(obj, path, value) {
87
+ var current = obj;
88
+ for (var i = 0; i < path.length - 1; i++) {
89
+ if (!current[path[i]] || !_.isObject(current[path[i]])) {
90
+ current[path[i]] = {};
91
+ }
92
+ current = current[path[i]];
93
+ }
94
+ current[path[path.length - 1]] = value;
95
+ }
96
+
97
+ /**
98
+ * Parses a Hot Rod URI string into servers and options.
99
+ * @param {string} uriString URI in the format hotrod://[user:pass@]host1[:port1][,host2[:port2]][?params].
100
+ * @returns {{servers: Array<{host: string, port: number}>, options: Object}} Parsed result.
101
+ */
102
+ function parseHotrodURI(uriString) {
103
+ var tls = false;
104
+ var rest;
105
+
106
+ if (uriString.indexOf('hotrods://') === 0) {
107
+ tls = true;
108
+ rest = uriString.substring('hotrods://'.length);
109
+ } else if (uriString.indexOf('hotrod://') === 0) {
110
+ rest = uriString.substring('hotrod://'.length);
111
+ } else {
112
+ throw new Error('Invalid URI scheme, expected hotrod:// or hotrods://');
113
+ }
114
+
115
+ // Split authority from query string
116
+ var queryString = '';
117
+ var qIndex = rest.indexOf('?');
118
+ var authority;
119
+ if (qIndex !== -1) {
120
+ authority = rest.substring(0, qIndex);
121
+ queryString = rest.substring(qIndex + 1);
122
+ } else {
123
+ authority = rest;
124
+ }
125
+
126
+ // Split userinfo from hosts (find last @ to handle passwords with @)
127
+ var userName, password;
128
+ var atIndex = authority.lastIndexOf('@');
129
+ var hostsStr;
130
+ if (atIndex !== -1) {
131
+ var userinfo = authority.substring(0, atIndex);
132
+ hostsStr = authority.substring(atIndex + 1);
133
+ var colonIndex = userinfo.indexOf(':');
134
+ if (colonIndex !== -1) {
135
+ userName = decodeURIComponent(userinfo.substring(0, colonIndex));
136
+ password = decodeURIComponent(userinfo.substring(colonIndex + 1));
137
+ } else {
138
+ userName = decodeURIComponent(userinfo);
139
+ }
140
+ } else {
141
+ hostsStr = authority;
142
+ }
143
+
144
+ if (hostsStr.length === 0) {
145
+ throw new Error('No host specified in URI');
146
+ }
147
+
148
+ // Parse comma-separated hosts
149
+ var hostParts = hostsStr.split(',');
150
+ var servers = [];
151
+ for (var i = 0; i < hostParts.length; i++) {
152
+ if (hostParts[i].length > 0) {
153
+ servers.push(splitHostPort(hostParts[i]));
154
+ }
155
+ }
156
+ if (servers.length === 0) {
157
+ throw new Error('No host specified in URI');
158
+ }
159
+
160
+ // Build options from URI components
161
+ var options = {};
162
+
163
+ if (tls) {
164
+ setNested(options, ['ssl', 'enabled'], true);
165
+ }
166
+
167
+ if (userName !== undefined) {
168
+ setNested(options, ['authentication', 'enabled'], true);
169
+ setNested(options, ['authentication', 'userName'], userName);
170
+ if (password !== undefined) {
171
+ setNested(options, ['authentication', 'password'], password);
172
+ }
173
+ setNested(options, ['authentication', 'saslMechanism'], 'PLAIN');
174
+ }
175
+
176
+ // Parse query parameters
177
+ if (queryString.length > 0) {
178
+ var params = new URLSearchParams(queryString);
179
+ params.forEach(function(value, key) {
180
+ var mapping = QUERY_PARAMS[key];
181
+ if (!mapping) {
182
+ throw new Error(`Unknown URI parameter: ${key}`);
183
+ }
184
+
185
+ var parsed;
186
+ if (mapping.type === 'int') {
187
+ parsed = parseInt(value, 10);
188
+ if (isNaN(parsed)) {
189
+ throw new Error(`Invalid integer value for ${key}: ${value}`);
190
+ }
191
+ } else if (mapping.type === 'string_array') {
192
+ parsed = [value];
193
+ } else {
194
+ parsed = value;
195
+ }
196
+ setNested(options, mapping.path, parsed);
197
+ });
198
+ }
199
+
200
+ return { servers: servers, options: options };
201
+ }
202
+
203
+ exports.isHotrodURI = isHotrodURI;
204
+ exports.parseHotrodURI = parseHotrodURI;
205
+
206
+ }.call(this));