@verdaccio/web 9.0.0-next-9.3 → 9.0.0-next-9.5
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/build/_virtual/_rolldown/runtime.js +23 -0
- package/build/_virtual/_rolldown/runtime.mjs +7 -0
- package/build/api/index.d.ts +1 -1
- package/build/api/index.js +26 -37
- package/build/api/index.js.map +1 -1
- package/build/api/index.mjs +27 -0
- package/build/api/index.mjs.map +1 -0
- package/build/api/package.d.ts +3 -3
- package/build/api/package.js +79 -200
- package/build/api/package.js.map +1 -1
- package/build/api/package.mjs +80 -0
- package/build/api/package.mjs.map +1 -0
- package/build/api/readme.d.ts +2 -2
- package/build/api/readme.js +64 -122
- package/build/api/readme.js.map +1 -1
- package/build/api/readme.mjs +67 -0
- package/build/api/readme.mjs.map +1 -0
- package/build/api/search.d.ts +2 -2
- package/build/api/search.js +57 -99
- package/build/api/search.js.map +1 -1
- package/build/api/search.mjs +59 -0
- package/build/api/search.mjs.map +1 -0
- package/build/api/sidebar.d.ts +3 -3
- package/build/api/sidebar.js +56 -109
- package/build/api/sidebar.js.map +1 -1
- package/build/api/sidebar.mjs +57 -0
- package/build/api/sidebar.mjs.map +1 -0
- package/build/api/user.d.ts +2 -2
- package/build/api/user.js +97 -212
- package/build/api/user.js.map +1 -1
- package/build/api/user.mjs +97 -0
- package/build/api/user.mjs.map +1 -0
- package/build/author-utils.d.ts +1 -1
- package/build/author-utils.js +109 -160
- package/build/author-utils.js.map +1 -1
- package/build/author-utils.mjs +117 -0
- package/build/author-utils.mjs.map +1 -0
- package/build/index.js +18 -47
- package/build/index.mjs +4 -0
- package/build/middleware.d.ts +1 -1
- package/build/middleware.js +49 -90
- package/build/middleware.js.map +1 -1
- package/build/middleware.mjs +48 -0
- package/build/middleware.mjs.map +1 -0
- package/build/web-utils.d.ts +2 -1
- package/build/web-utils.js +31 -31
- package/build/web-utils.js.map +1 -1
- package/build/web-utils.mjs +34 -0
- package/build/web-utils.mjs.map +1 -0
- package/package.json +30 -19
- package/build/index.js.map +0 -1
package/build/api/user.js
CHANGED
|
@@ -1,215 +1,100 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
var
|
|
12
|
-
var
|
|
13
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
14
|
-
function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
|
|
15
|
-
function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
|
|
16
|
-
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
17
|
-
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
|
18
|
-
var debug = (0, _debug["default"])('verdaccio:web:api:user');
|
|
19
|
-
var WEB_LOGIN_SESSION_ID = 'web-login-sessionId';
|
|
1
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.js");
|
|
2
|
+
let express = require("express");
|
|
3
|
+
let lodash = require("lodash");
|
|
4
|
+
lodash = require_runtime.__toESM(lodash);
|
|
5
|
+
let _verdaccio_core = require("@verdaccio/core");
|
|
6
|
+
let _verdaccio_middleware = require("@verdaccio/middleware");
|
|
7
|
+
let debug = require("debug");
|
|
8
|
+
debug = require_runtime.__toESM(debug);
|
|
9
|
+
let _verdaccio_auth = require("@verdaccio/auth");
|
|
10
|
+
//#region src/api/user.ts
|
|
11
|
+
var debug$1 = (0, debug.default)("verdaccio:web:api:user");
|
|
12
|
+
var WEB_LOGIN_SESSION_ID = "web-login-sessionId";
|
|
20
13
|
function addUserAuthApi(auth, config, storage) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
case 1:
|
|
104
|
-
return _context2.a(2, next(err));
|
|
105
|
-
case 2:
|
|
106
|
-
_context2.n = 3;
|
|
107
|
-
return storage.readTokens({
|
|
108
|
-
user: sessionId
|
|
109
|
-
});
|
|
110
|
-
case 3:
|
|
111
|
-
tokens = _context2.v;
|
|
112
|
-
debug('tokens found for sessionId %o: %o', sessionId, tokens.length);
|
|
113
|
-
if (!(tokens && tokens.length === 1 && tokens[0].key === WEB_LOGIN_SESSION_ID)) {
|
|
114
|
-
_context2.n = 7;
|
|
115
|
-
break;
|
|
116
|
-
}
|
|
117
|
-
if (!(tokens[0].token.length === 0)) {
|
|
118
|
-
_context2.n = 4;
|
|
119
|
-
break;
|
|
120
|
-
}
|
|
121
|
-
debug('waiting for authentication');
|
|
122
|
-
// Poll again after short delay
|
|
123
|
-
// TODO: make this configurable (default 5 seconds)
|
|
124
|
-
res.status(_core.HTTP_STATUS.ACCEPTED);
|
|
125
|
-
res.set(_core.HEADERS.RETRY_AFTER, '5');
|
|
126
|
-
res.json({});
|
|
127
|
-
return _context2.a(2);
|
|
128
|
-
case 4:
|
|
129
|
-
// session token can only be used once
|
|
130
|
-
debug('deleting session token');
|
|
131
|
-
_context2.n = 5;
|
|
132
|
-
return storage.deleteToken(sessionId, tokens[0].key);
|
|
133
|
-
case 5:
|
|
134
|
-
// Check if token has expired
|
|
135
|
-
// TODO: make this configurable (default 2 minutes)
|
|
136
|
-
tokenCreatedDate = new Date(tokens[0].created);
|
|
137
|
-
minutesAgo = new Date(Date.now() - 2 * 60 * 1000);
|
|
138
|
-
if (!(tokenCreatedDate < minutesAgo)) {
|
|
139
|
-
_context2.n = 6;
|
|
140
|
-
break;
|
|
141
|
-
}
|
|
142
|
-
debug('session token expired');
|
|
143
|
-
return _context2.a(2, next(_core.errorUtils.getUnauthorized(_core.API_ERROR.SESSION_TOKEN_EXPIRED)));
|
|
144
|
-
case 6:
|
|
145
|
-
debug('session token is valid, login successful');
|
|
146
|
-
res.status(_core.HTTP_STATUS.OK);
|
|
147
|
-
res.json({
|
|
148
|
-
token: tokens[0].token
|
|
149
|
-
});
|
|
150
|
-
return _context2.a(2);
|
|
151
|
-
case 7:
|
|
152
|
-
if (!(name && password)) {
|
|
153
|
-
_context2.n = 9;
|
|
154
|
-
break;
|
|
155
|
-
}
|
|
156
|
-
_context2.n = 8;
|
|
157
|
-
return (0, _auth.getApiToken)(auth, config, user, password);
|
|
158
|
-
case 8:
|
|
159
|
-
_t4 = _context2.v;
|
|
160
|
-
_context2.n = 10;
|
|
161
|
-
break;
|
|
162
|
-
case 9:
|
|
163
|
-
_t4 = undefined;
|
|
164
|
-
case 10:
|
|
165
|
-
token = _t4;
|
|
166
|
-
if (!token) {
|
|
167
|
-
_context2.n = 11;
|
|
168
|
-
break;
|
|
169
|
-
}
|
|
170
|
-
debug('adduser: new token %o', _core.cryptoUtils.mask(token, 4));
|
|
171
|
-
return _context2.a(2, next({
|
|
172
|
-
token: token,
|
|
173
|
-
username: name
|
|
174
|
-
}));
|
|
175
|
-
case 11:
|
|
176
|
-
return _context2.a(2, next(_core.errorUtils.getUnauthorized()));
|
|
177
|
-
}
|
|
178
|
-
}, _callee2);
|
|
179
|
-
}));
|
|
180
|
-
return function (_x3, _x4) {
|
|
181
|
-
return _ref2.apply(this, arguments);
|
|
182
|
-
};
|
|
183
|
-
}());
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
if ((config === null || config === void 0 || (_config$flags2 = config.flags) === null || _config$flags2 === void 0 ? void 0 : _config$flags2.changePassword) === true) {
|
|
187
|
-
route.put(_middleware.WebUrls.reset_password, (0, _middleware.rateLimit)(config === null || config === void 0 ? void 0 : config.userRateLimit), function (req, res, next) {
|
|
188
|
-
var _config$server;
|
|
189
|
-
if (_lodash["default"].isNil(req.remote_user.name)) {
|
|
190
|
-
res.status(_core.HTTP_STATUS.UNAUTHORIZED);
|
|
191
|
-
return next({
|
|
192
|
-
// FUTURE: update to a more meaningful message
|
|
193
|
-
message: _core.API_ERROR.MUST_BE_LOGGED
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
var password = req.body.password;
|
|
197
|
-
var name = req.remote_user.name;
|
|
198
|
-
if (_core.validationUtils.validatePassword(password["new"], config === null || config === void 0 || (_config$server = config.server) === null || _config$server === void 0 ? void 0 : _config$server.passwordValidationRegex) === false) {
|
|
199
|
-
return next(_core.errorUtils.getCode(_core.HTTP_STATUS.BAD_REQUEST, _core.APP_ERROR.PASSWORD_VALIDATION));
|
|
200
|
-
}
|
|
201
|
-
auth.changePassword(name, password.old, password["new"], function (err, isUpdated) {
|
|
202
|
-
if (_lodash["default"].isNil(err) && isUpdated) {
|
|
203
|
-
next({
|
|
204
|
-
ok: true
|
|
205
|
-
});
|
|
206
|
-
} else {
|
|
207
|
-
return next(_core.errorUtils.getInternalError(_core.API_ERROR.INTERNAL_SERVER_ERROR));
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
return route;
|
|
14
|
+
const route = (0, express.Router)();
|
|
15
|
+
route.post(_verdaccio_middleware.WebUrls.user_login, (0, _verdaccio_middleware.rateLimit)(config?.userRateLimit), function(req, res, next) {
|
|
16
|
+
const { username, password } = req.body;
|
|
17
|
+
debug$1("authenticate %o", username);
|
|
18
|
+
auth.authenticate(username, password, async (err, user) => {
|
|
19
|
+
if (err) {
|
|
20
|
+
const errorCode = err.message ? _verdaccio_core.HTTP_STATUS.UNAUTHORIZED : _verdaccio_core.HTTP_STATUS.INTERNAL_ERROR;
|
|
21
|
+
debug$1("error authenticate %o", errorCode);
|
|
22
|
+
next(_verdaccio_core.errorUtils.getCode(errorCode, err.message));
|
|
23
|
+
} else {
|
|
24
|
+
req.remote_user = user;
|
|
25
|
+
const jWTSignOptions = config.security.web.sign;
|
|
26
|
+
res.set(_verdaccio_core.HEADERS.CACHE_CONTROL, "no-cache, no-store");
|
|
27
|
+
next({
|
|
28
|
+
token: await auth.jwtEncrypt(user, jWTSignOptions),
|
|
29
|
+
username: req.remote_user.name
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
if (config?.flags?.createUser === true) route.put(_verdaccio_middleware.WebUrls.user_signup, (0, _verdaccio_middleware.rateLimit)(config?.userRateLimit), function(req, res, next) {
|
|
35
|
+
const { name, password, email, sessionId } = req.body;
|
|
36
|
+
debug$1("login or adduser");
|
|
37
|
+
if (typeof sessionId !== "string" || sessionId.length !== 36) {
|
|
38
|
+
debug$1("sessionId is invalid length: %o", sessionId.length);
|
|
39
|
+
return next(_verdaccio_core.errorUtils.getCode(_verdaccio_core.HTTP_STATUS.BAD_REQUEST, _verdaccio_core.API_ERROR.SESSION_ID_INVALID));
|
|
40
|
+
}
|
|
41
|
+
if (!name || !password || !email) return next(_verdaccio_core.errorUtils.getCode(_verdaccio_core.HTTP_STATUS.BAD_REQUEST, _verdaccio_core.API_ERROR.BAD_DATA));
|
|
42
|
+
auth.add_user(name, password, async function(err, user) {
|
|
43
|
+
if (err) {
|
|
44
|
+
if (err.status >= _verdaccio_core.HTTP_STATUS.BAD_REQUEST && err.status < _verdaccio_core.HTTP_STATUS.INTERNAL_ERROR) {
|
|
45
|
+
debug$1("adduser: error on create user");
|
|
46
|
+
return next(_verdaccio_core.errorUtils.getCode(err.status, err.message) || _verdaccio_core.errorUtils.getConflict(err.message));
|
|
47
|
+
}
|
|
48
|
+
return next(err);
|
|
49
|
+
}
|
|
50
|
+
const tokens = await storage.readTokens({ user: sessionId });
|
|
51
|
+
debug$1("tokens found for sessionId %o: %o", sessionId, tokens.length);
|
|
52
|
+
if (tokens && tokens.length === 1 && tokens[0].key === WEB_LOGIN_SESSION_ID) {
|
|
53
|
+
if (tokens[0].token.length === 0) {
|
|
54
|
+
debug$1("waiting for authentication");
|
|
55
|
+
res.status(_verdaccio_core.HTTP_STATUS.ACCEPTED);
|
|
56
|
+
res.set(_verdaccio_core.HEADERS.RETRY_AFTER, "5");
|
|
57
|
+
res.json({});
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
debug$1("deleting session token");
|
|
61
|
+
await storage.deleteToken(sessionId, tokens[0].key);
|
|
62
|
+
if (new Date(tokens[0].created) < /* @__PURE__ */ new Date(Date.now() - 120 * 1e3)) {
|
|
63
|
+
debug$1("session token expired");
|
|
64
|
+
return next(_verdaccio_core.errorUtils.getUnauthorized(_verdaccio_core.API_ERROR.SESSION_TOKEN_EXPIRED));
|
|
65
|
+
}
|
|
66
|
+
debug$1("session token is valid, login successful");
|
|
67
|
+
res.status(_verdaccio_core.HTTP_STATUS.OK);
|
|
68
|
+
res.json({ token: tokens[0].token });
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const token = name && password ? await (0, _verdaccio_auth.getApiToken)(auth, config, user, password) : void 0;
|
|
72
|
+
if (token) {
|
|
73
|
+
debug$1("adduser: new token %o", _verdaccio_core.cryptoUtils.mask(token, 4));
|
|
74
|
+
return next({
|
|
75
|
+
token,
|
|
76
|
+
username: name
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return next(_verdaccio_core.errorUtils.getUnauthorized());
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
if (config?.flags?.changePassword === true) route.put(_verdaccio_middleware.WebUrls.reset_password, (0, _verdaccio_middleware.rateLimit)(config?.userRateLimit), function(req, res, next) {
|
|
83
|
+
if (lodash.default.isNil(req.remote_user.name)) {
|
|
84
|
+
res.status(_verdaccio_core.HTTP_STATUS.UNAUTHORIZED);
|
|
85
|
+
return next({ message: _verdaccio_core.API_ERROR.MUST_BE_LOGGED });
|
|
86
|
+
}
|
|
87
|
+
const { password } = req.body;
|
|
88
|
+
const { name } = req.remote_user;
|
|
89
|
+
if (_verdaccio_core.validationUtils.validatePassword(password.new, config?.server?.passwordValidationRegex) === false) return next(_verdaccio_core.errorUtils.getCode(_verdaccio_core.HTTP_STATUS.BAD_REQUEST, _verdaccio_core.APP_ERROR.PASSWORD_VALIDATION));
|
|
90
|
+
auth.changePassword(name, password.old, password.new, (err, isUpdated) => {
|
|
91
|
+
if (lodash.default.isNil(err) && isUpdated) next({ ok: true });
|
|
92
|
+
else return next(_verdaccio_core.errorUtils.getInternalError(_verdaccio_core.API_ERROR.INTERNAL_SERVER_ERROR));
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
return route;
|
|
213
96
|
}
|
|
214
|
-
|
|
97
|
+
//#endregion
|
|
98
|
+
exports.default = addUserAuthApi;
|
|
99
|
+
|
|
215
100
|
//# sourceMappingURL=user.js.map
|
package/build/api/user.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user.js","names":["_debug","_interopRequireDefault","require","_express","_lodash","_auth","_core","_middleware","e","__esModule","_regenerator","t","r","Symbol","n","iterator","o","toStringTag","i","c","prototype","Generator","u","Object","create","_regeneratorDefine2","f","p","y","G","v","a","d","bind","length","l","TypeError","call","done","value","GeneratorFunction","GeneratorFunctionPrototype","getPrototypeOf","setPrototypeOf","__proto__","displayName","w","m","defineProperty","_regeneratorDefine","_invoke","enumerable","configurable","writable","asyncGeneratorStep","Promise","resolve","then","_asyncToGenerator","arguments","apply","_next","_throw","debug","buildDebug","WEB_LOGIN_SESSION_ID","addUserAuthApi","auth","config","storage","_config$flags","_config$flags2","route","Router","post","WebUrls","user_login","rateLimit","userRateLimit","req","res","next","_req$body","body","username","password","authenticate","_ref","_callee","err","user","errorCode","jWTSignOptions","_t","_t2","_t3","_context","message","HTTP_STATUS","UNAUTHORIZED","INTERNAL_ERROR","errorUtils","getCode","remote_user","security","web","sign","set","HEADERS","CACHE_CONTROL","jwtEncrypt","name","token","_x","_x2","flags","createUser","put","user_signup","_req$body2","email","sessionId","BAD_REQUEST","API_ERROR","SESSION_ID_INVALID","BAD_DATA","add_user","_ref2","_callee2","tokens","tokenCreatedDate","minutesAgo","_t4","_context2","status","getConflict","readTokens","key","ACCEPTED","RETRY_AFTER","json","deleteToken","Date","created","now","getUnauthorized","SESSION_TOKEN_EXPIRED","OK","getApiToken","undefined","cryptoUtils","mask","_x3","_x4","changePassword","reset_password","_config$server","_","isNil","MUST_BE_LOGGED","validationUtils","validatePassword","server","passwordValidationRegex","APP_ERROR","PASSWORD_VALIDATION","old","isUpdated","ok","getInternalError","INTERNAL_SERVER_ERROR","_default","exports"],"sources":["../../src/api/user.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport type { Request, Response } from 'express';\nimport { Router } from 'express';\nimport _ from 'lodash';\n\nimport { type Auth, getApiToken } from '@verdaccio/auth';\nimport type { VerdaccioError } from '@verdaccio/core';\nimport {\n API_ERROR,\n APP_ERROR,\n HEADERS,\n HTTP_STATUS,\n cryptoUtils,\n errorUtils,\n validationUtils,\n} from '@verdaccio/core';\nimport { WebUrls, rateLimit } from '@verdaccio/middleware';\nimport type { Config, JWTSignOptions, RemoteUser } from '@verdaccio/types';\n\nimport type { $NextFunctionVer } from './package';\n\nconst debug = buildDebug('verdaccio:web:api:user');\n\nconst WEB_LOGIN_SESSION_ID = 'web-login-sessionId';\n\nfunction addUserAuthApi(auth: Auth, config: Config, storage: Storage): Router {\n const route = Router(); /* eslint new-cap: 0 */\n route.post(\n WebUrls.user_login,\n rateLimit(config?.userRateLimit),\n function (req: Request, res: Response, next: $NextFunctionVer): void {\n const { username, password } = req.body;\n debug('authenticate %o', username);\n auth.authenticate(\n username,\n password,\n async (err: VerdaccioError | null, user?: RemoteUser): Promise<void> => {\n if (err) {\n const errorCode = err.message ? HTTP_STATUS.UNAUTHORIZED : HTTP_STATUS.INTERNAL_ERROR;\n debug('error authenticate %o', errorCode);\n next(errorUtils.getCode(errorCode, err.message));\n } else {\n req.remote_user = user as RemoteUser;\n const jWTSignOptions: JWTSignOptions = config.security.web.sign;\n res.set(HEADERS.CACHE_CONTROL, 'no-cache, no-store');\n next({\n token: await auth.jwtEncrypt(user as RemoteUser, jWTSignOptions),\n username: req.remote_user.name,\n });\n }\n }\n );\n }\n );\n\n if (config?.flags?.createUser === true) {\n route.put(\n WebUrls.user_signup,\n rateLimit(config?.userRateLimit),\n function (req: Request, res: Response, next: $NextFunctionVer): void {\n const { name, password, email, sessionId } = req.body;\n debug('login or adduser');\n\n // TOOD: reuse with login.ts file\n if (typeof sessionId !== 'string' || sessionId.length !== 36) {\n debug('sessionId is invalid length: %o', sessionId.length);\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.SESSION_ID_INVALID));\n }\n\n if (!name || !password || !email) {\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.BAD_DATA));\n }\n\n auth.add_user(name, password, async function (err, user): Promise<void> {\n if (err) {\n if (err.status >= HTTP_STATUS.BAD_REQUEST && err.status < HTTP_STATUS.INTERNAL_ERROR) {\n debug('adduser: error on create user');\n // With npm registering is the same as logging in,\n // and npm accepts only an 409 error.\n // So, changing status code here.\n return next(\n errorUtils.getCode(err.status, err.message) || errorUtils.getConflict(err.message)\n );\n }\n return next(err);\n }\n\n const tokens = await storage.readTokens({ user: sessionId });\n debug('tokens found for sessionId %o: %o', sessionId, tokens.length);\n if (tokens && tokens.length === 1 && tokens[0].key === WEB_LOGIN_SESSION_ID) {\n if (tokens[0].token.length === 0) {\n debug('waiting for authentication');\n // Poll again after short delay\n // TODO: make this configurable (default 5 seconds)\n res.status(HTTP_STATUS.ACCEPTED);\n res.set(HEADERS.RETRY_AFTER, '5');\n res.json({});\n return;\n }\n\n // session token can only be used once\n debug('deleting session token');\n await storage.deleteToken(sessionId, tokens[0].key);\n\n // Check if token has expired\n // TODO: make this configurable (default 2 minutes)\n const tokenCreatedDate = new Date(tokens[0].created);\n const minutesAgo = new Date(Date.now() - 2 * 60 * 1000);\n if (tokenCreatedDate < minutesAgo) {\n debug('session token expired');\n return next(errorUtils.getUnauthorized(API_ERROR.SESSION_TOKEN_EXPIRED));\n }\n\n debug('session token is valid, login successful');\n res.status(HTTP_STATUS.OK);\n res.json({ token: tokens[0].token });\n return;\n }\n\n const token =\n name && password\n ? await getApiToken(auth, config, user as RemoteUser, password)\n : undefined;\n if (token) {\n debug('adduser: new token %o', cryptoUtils.mask(token as string, 4));\n return next({ token, username: name });\n }\n return next(errorUtils.getUnauthorized());\n });\n }\n );\n }\n\n if (config?.flags?.changePassword === true) {\n route.put(\n WebUrls.reset_password,\n rateLimit(config?.userRateLimit),\n function (req: Request, res: Response, next: $NextFunctionVer): void {\n if (_.isNil(req.remote_user.name)) {\n res.status(HTTP_STATUS.UNAUTHORIZED);\n return next({\n // FUTURE: update to a more meaningful message\n message: API_ERROR.MUST_BE_LOGGED,\n });\n }\n\n const { password } = req.body;\n const { name } = req.remote_user;\n\n if (\n validationUtils.validatePassword(\n password.new,\n config?.server?.passwordValidationRegex\n ) === false\n ) {\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, APP_ERROR.PASSWORD_VALIDATION));\n }\n\n auth.changePassword(name as string, password.old, password.new, (err, isUpdated): void => {\n if (_.isNil(err) && isUpdated) {\n next({\n ok: true,\n });\n } else {\n return next(errorUtils.getInternalError(API_ERROR.INTERNAL_SERVER_ERROR));\n }\n });\n }\n );\n }\n\n return route;\n}\n\nexport default addUserAuthApi;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"user.js","names":[],"sources":["../../src/api/user.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport type { Request, Response } from 'express';\nimport { Router } from 'express';\nimport _ from 'lodash';\n\nimport { type Auth, getApiToken } from '@verdaccio/auth';\nimport type { VerdaccioError } from '@verdaccio/core';\nimport {\n API_ERROR,\n APP_ERROR,\n HEADERS,\n HTTP_STATUS,\n cryptoUtils,\n errorUtils,\n validationUtils,\n} from '@verdaccio/core';\nimport { WebUrls, rateLimit } from '@verdaccio/middleware';\nimport type { Config, JWTSignOptions, RemoteUser } from '@verdaccio/types';\n\nimport type { $NextFunctionVer } from './package';\n\nconst debug = buildDebug('verdaccio:web:api:user');\n\nconst WEB_LOGIN_SESSION_ID = 'web-login-sessionId';\n\nfunction addUserAuthApi(auth: Auth, config: Config, storage: Storage): Router {\n const route = Router(); /* eslint new-cap: 0 */\n route.post(\n WebUrls.user_login,\n rateLimit(config?.userRateLimit),\n function (req: Request, res: Response, next: $NextFunctionVer): void {\n const { username, password } = req.body;\n debug('authenticate %o', username);\n auth.authenticate(\n username,\n password,\n async (err: VerdaccioError | null, user?: RemoteUser): Promise<void> => {\n if (err) {\n const errorCode = err.message ? HTTP_STATUS.UNAUTHORIZED : HTTP_STATUS.INTERNAL_ERROR;\n debug('error authenticate %o', errorCode);\n next(errorUtils.getCode(errorCode, err.message));\n } else {\n req.remote_user = user as RemoteUser;\n const jWTSignOptions: JWTSignOptions = config.security.web.sign;\n res.set(HEADERS.CACHE_CONTROL, 'no-cache, no-store');\n next({\n token: await auth.jwtEncrypt(user as RemoteUser, jWTSignOptions),\n username: req.remote_user.name,\n });\n }\n }\n );\n }\n );\n\n if (config?.flags?.createUser === true) {\n route.put(\n WebUrls.user_signup,\n rateLimit(config?.userRateLimit),\n function (req: Request, res: Response, next: $NextFunctionVer): void {\n const { name, password, email, sessionId } = req.body;\n debug('login or adduser');\n\n // TOOD: reuse with login.ts file\n if (typeof sessionId !== 'string' || sessionId.length !== 36) {\n debug('sessionId is invalid length: %o', sessionId.length);\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.SESSION_ID_INVALID));\n }\n\n if (!name || !password || !email) {\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.BAD_DATA));\n }\n\n auth.add_user(name, password, async function (err, user): Promise<void> {\n if (err) {\n if (err.status >= HTTP_STATUS.BAD_REQUEST && err.status < HTTP_STATUS.INTERNAL_ERROR) {\n debug('adduser: error on create user');\n // With npm registering is the same as logging in,\n // and npm accepts only an 409 error.\n // So, changing status code here.\n return next(\n errorUtils.getCode(err.status, err.message) || errorUtils.getConflict(err.message)\n );\n }\n return next(err);\n }\n\n const tokens = await storage.readTokens({ user: sessionId });\n debug('tokens found for sessionId %o: %o', sessionId, tokens.length);\n if (tokens && tokens.length === 1 && tokens[0].key === WEB_LOGIN_SESSION_ID) {\n if (tokens[0].token.length === 0) {\n debug('waiting for authentication');\n // Poll again after short delay\n // TODO: make this configurable (default 5 seconds)\n res.status(HTTP_STATUS.ACCEPTED);\n res.set(HEADERS.RETRY_AFTER, '5');\n res.json({});\n return;\n }\n\n // session token can only be used once\n debug('deleting session token');\n await storage.deleteToken(sessionId, tokens[0].key);\n\n // Check if token has expired\n // TODO: make this configurable (default 2 minutes)\n const tokenCreatedDate = new Date(tokens[0].created);\n const minutesAgo = new Date(Date.now() - 2 * 60 * 1000);\n if (tokenCreatedDate < minutesAgo) {\n debug('session token expired');\n return next(errorUtils.getUnauthorized(API_ERROR.SESSION_TOKEN_EXPIRED));\n }\n\n debug('session token is valid, login successful');\n res.status(HTTP_STATUS.OK);\n res.json({ token: tokens[0].token });\n return;\n }\n\n const token =\n name && password\n ? await getApiToken(auth, config, user as RemoteUser, password)\n : undefined;\n if (token) {\n debug('adduser: new token %o', cryptoUtils.mask(token as string, 4));\n return next({ token, username: name });\n }\n return next(errorUtils.getUnauthorized());\n });\n }\n );\n }\n\n if (config?.flags?.changePassword === true) {\n route.put(\n WebUrls.reset_password,\n rateLimit(config?.userRateLimit),\n function (req: Request, res: Response, next: $NextFunctionVer): void {\n if (_.isNil(req.remote_user.name)) {\n res.status(HTTP_STATUS.UNAUTHORIZED);\n return next({\n // FUTURE: update to a more meaningful message\n message: API_ERROR.MUST_BE_LOGGED,\n });\n }\n\n const { password } = req.body;\n const { name } = req.remote_user;\n\n if (\n validationUtils.validatePassword(\n password.new,\n config?.server?.passwordValidationRegex\n ) === false\n ) {\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, APP_ERROR.PASSWORD_VALIDATION));\n }\n\n auth.changePassword(name as string, password.old, password.new, (err, isUpdated): void => {\n if (_.isNil(err) && isUpdated) {\n next({\n ok: true,\n });\n } else {\n return next(errorUtils.getInternalError(API_ERROR.INTERNAL_SERVER_ERROR));\n }\n });\n }\n );\n }\n\n return route;\n}\n\nexport default addUserAuthApi;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import _ from "lodash";
|
|
3
|
+
import { API_ERROR, APP_ERROR, HEADERS, HTTP_STATUS, cryptoUtils, errorUtils, validationUtils } from "@verdaccio/core";
|
|
4
|
+
import { WebUrls, rateLimit } from "@verdaccio/middleware";
|
|
5
|
+
import buildDebug from "debug";
|
|
6
|
+
import { getApiToken } from "@verdaccio/auth";
|
|
7
|
+
//#region src/api/user.ts
|
|
8
|
+
var debug = buildDebug("verdaccio:web:api:user");
|
|
9
|
+
var WEB_LOGIN_SESSION_ID = "web-login-sessionId";
|
|
10
|
+
function addUserAuthApi(auth, config, storage) {
|
|
11
|
+
const route = Router();
|
|
12
|
+
route.post(WebUrls.user_login, rateLimit(config?.userRateLimit), function(req, res, next) {
|
|
13
|
+
const { username, password } = req.body;
|
|
14
|
+
debug("authenticate %o", username);
|
|
15
|
+
auth.authenticate(username, password, async (err, user) => {
|
|
16
|
+
if (err) {
|
|
17
|
+
const errorCode = err.message ? HTTP_STATUS.UNAUTHORIZED : HTTP_STATUS.INTERNAL_ERROR;
|
|
18
|
+
debug("error authenticate %o", errorCode);
|
|
19
|
+
next(errorUtils.getCode(errorCode, err.message));
|
|
20
|
+
} else {
|
|
21
|
+
req.remote_user = user;
|
|
22
|
+
const jWTSignOptions = config.security.web.sign;
|
|
23
|
+
res.set(HEADERS.CACHE_CONTROL, "no-cache, no-store");
|
|
24
|
+
next({
|
|
25
|
+
token: await auth.jwtEncrypt(user, jWTSignOptions),
|
|
26
|
+
username: req.remote_user.name
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
if (config?.flags?.createUser === true) route.put(WebUrls.user_signup, rateLimit(config?.userRateLimit), function(req, res, next) {
|
|
32
|
+
const { name, password, email, sessionId } = req.body;
|
|
33
|
+
debug("login or adduser");
|
|
34
|
+
if (typeof sessionId !== "string" || sessionId.length !== 36) {
|
|
35
|
+
debug("sessionId is invalid length: %o", sessionId.length);
|
|
36
|
+
return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.SESSION_ID_INVALID));
|
|
37
|
+
}
|
|
38
|
+
if (!name || !password || !email) return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.BAD_DATA));
|
|
39
|
+
auth.add_user(name, password, async function(err, user) {
|
|
40
|
+
if (err) {
|
|
41
|
+
if (err.status >= HTTP_STATUS.BAD_REQUEST && err.status < HTTP_STATUS.INTERNAL_ERROR) {
|
|
42
|
+
debug("adduser: error on create user");
|
|
43
|
+
return next(errorUtils.getCode(err.status, err.message) || errorUtils.getConflict(err.message));
|
|
44
|
+
}
|
|
45
|
+
return next(err);
|
|
46
|
+
}
|
|
47
|
+
const tokens = await storage.readTokens({ user: sessionId });
|
|
48
|
+
debug("tokens found for sessionId %o: %o", sessionId, tokens.length);
|
|
49
|
+
if (tokens && tokens.length === 1 && tokens[0].key === WEB_LOGIN_SESSION_ID) {
|
|
50
|
+
if (tokens[0].token.length === 0) {
|
|
51
|
+
debug("waiting for authentication");
|
|
52
|
+
res.status(HTTP_STATUS.ACCEPTED);
|
|
53
|
+
res.set(HEADERS.RETRY_AFTER, "5");
|
|
54
|
+
res.json({});
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
debug("deleting session token");
|
|
58
|
+
await storage.deleteToken(sessionId, tokens[0].key);
|
|
59
|
+
if (new Date(tokens[0].created) < /* @__PURE__ */ new Date(Date.now() - 120 * 1e3)) {
|
|
60
|
+
debug("session token expired");
|
|
61
|
+
return next(errorUtils.getUnauthorized(API_ERROR.SESSION_TOKEN_EXPIRED));
|
|
62
|
+
}
|
|
63
|
+
debug("session token is valid, login successful");
|
|
64
|
+
res.status(HTTP_STATUS.OK);
|
|
65
|
+
res.json({ token: tokens[0].token });
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const token = name && password ? await getApiToken(auth, config, user, password) : void 0;
|
|
69
|
+
if (token) {
|
|
70
|
+
debug("adduser: new token %o", cryptoUtils.mask(token, 4));
|
|
71
|
+
return next({
|
|
72
|
+
token,
|
|
73
|
+
username: name
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return next(errorUtils.getUnauthorized());
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
if (config?.flags?.changePassword === true) route.put(WebUrls.reset_password, rateLimit(config?.userRateLimit), function(req, res, next) {
|
|
80
|
+
if (_.isNil(req.remote_user.name)) {
|
|
81
|
+
res.status(HTTP_STATUS.UNAUTHORIZED);
|
|
82
|
+
return next({ message: API_ERROR.MUST_BE_LOGGED });
|
|
83
|
+
}
|
|
84
|
+
const { password } = req.body;
|
|
85
|
+
const { name } = req.remote_user;
|
|
86
|
+
if (validationUtils.validatePassword(password.new, config?.server?.passwordValidationRegex) === false) return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, APP_ERROR.PASSWORD_VALIDATION));
|
|
87
|
+
auth.changePassword(name, password.old, password.new, (err, isUpdated) => {
|
|
88
|
+
if (_.isNil(err) && isUpdated) next({ ok: true });
|
|
89
|
+
else return next(errorUtils.getInternalError(API_ERROR.INTERNAL_SERVER_ERROR));
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
return route;
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
export { addUserAuthApi as default };
|
|
96
|
+
|
|
97
|
+
//# sourceMappingURL=user.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.mjs","names":[],"sources":["../../src/api/user.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport type { Request, Response } from 'express';\nimport { Router } from 'express';\nimport _ from 'lodash';\n\nimport { type Auth, getApiToken } from '@verdaccio/auth';\nimport type { VerdaccioError } from '@verdaccio/core';\nimport {\n API_ERROR,\n APP_ERROR,\n HEADERS,\n HTTP_STATUS,\n cryptoUtils,\n errorUtils,\n validationUtils,\n} from '@verdaccio/core';\nimport { WebUrls, rateLimit } from '@verdaccio/middleware';\nimport type { Config, JWTSignOptions, RemoteUser } from '@verdaccio/types';\n\nimport type { $NextFunctionVer } from './package';\n\nconst debug = buildDebug('verdaccio:web:api:user');\n\nconst WEB_LOGIN_SESSION_ID = 'web-login-sessionId';\n\nfunction addUserAuthApi(auth: Auth, config: Config, storage: Storage): Router {\n const route = Router(); /* eslint new-cap: 0 */\n route.post(\n WebUrls.user_login,\n rateLimit(config?.userRateLimit),\n function (req: Request, res: Response, next: $NextFunctionVer): void {\n const { username, password } = req.body;\n debug('authenticate %o', username);\n auth.authenticate(\n username,\n password,\n async (err: VerdaccioError | null, user?: RemoteUser): Promise<void> => {\n if (err) {\n const errorCode = err.message ? HTTP_STATUS.UNAUTHORIZED : HTTP_STATUS.INTERNAL_ERROR;\n debug('error authenticate %o', errorCode);\n next(errorUtils.getCode(errorCode, err.message));\n } else {\n req.remote_user = user as RemoteUser;\n const jWTSignOptions: JWTSignOptions = config.security.web.sign;\n res.set(HEADERS.CACHE_CONTROL, 'no-cache, no-store');\n next({\n token: await auth.jwtEncrypt(user as RemoteUser, jWTSignOptions),\n username: req.remote_user.name,\n });\n }\n }\n );\n }\n );\n\n if (config?.flags?.createUser === true) {\n route.put(\n WebUrls.user_signup,\n rateLimit(config?.userRateLimit),\n function (req: Request, res: Response, next: $NextFunctionVer): void {\n const { name, password, email, sessionId } = req.body;\n debug('login or adduser');\n\n // TOOD: reuse with login.ts file\n if (typeof sessionId !== 'string' || sessionId.length !== 36) {\n debug('sessionId is invalid length: %o', sessionId.length);\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.SESSION_ID_INVALID));\n }\n\n if (!name || !password || !email) {\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.BAD_DATA));\n }\n\n auth.add_user(name, password, async function (err, user): Promise<void> {\n if (err) {\n if (err.status >= HTTP_STATUS.BAD_REQUEST && err.status < HTTP_STATUS.INTERNAL_ERROR) {\n debug('adduser: error on create user');\n // With npm registering is the same as logging in,\n // and npm accepts only an 409 error.\n // So, changing status code here.\n return next(\n errorUtils.getCode(err.status, err.message) || errorUtils.getConflict(err.message)\n );\n }\n return next(err);\n }\n\n const tokens = await storage.readTokens({ user: sessionId });\n debug('tokens found for sessionId %o: %o', sessionId, tokens.length);\n if (tokens && tokens.length === 1 && tokens[0].key === WEB_LOGIN_SESSION_ID) {\n if (tokens[0].token.length === 0) {\n debug('waiting for authentication');\n // Poll again after short delay\n // TODO: make this configurable (default 5 seconds)\n res.status(HTTP_STATUS.ACCEPTED);\n res.set(HEADERS.RETRY_AFTER, '5');\n res.json({});\n return;\n }\n\n // session token can only be used once\n debug('deleting session token');\n await storage.deleteToken(sessionId, tokens[0].key);\n\n // Check if token has expired\n // TODO: make this configurable (default 2 minutes)\n const tokenCreatedDate = new Date(tokens[0].created);\n const minutesAgo = new Date(Date.now() - 2 * 60 * 1000);\n if (tokenCreatedDate < minutesAgo) {\n debug('session token expired');\n return next(errorUtils.getUnauthorized(API_ERROR.SESSION_TOKEN_EXPIRED));\n }\n\n debug('session token is valid, login successful');\n res.status(HTTP_STATUS.OK);\n res.json({ token: tokens[0].token });\n return;\n }\n\n const token =\n name && password\n ? await getApiToken(auth, config, user as RemoteUser, password)\n : undefined;\n if (token) {\n debug('adduser: new token %o', cryptoUtils.mask(token as string, 4));\n return next({ token, username: name });\n }\n return next(errorUtils.getUnauthorized());\n });\n }\n );\n }\n\n if (config?.flags?.changePassword === true) {\n route.put(\n WebUrls.reset_password,\n rateLimit(config?.userRateLimit),\n function (req: Request, res: Response, next: $NextFunctionVer): void {\n if (_.isNil(req.remote_user.name)) {\n res.status(HTTP_STATUS.UNAUTHORIZED);\n return next({\n // FUTURE: update to a more meaningful message\n message: API_ERROR.MUST_BE_LOGGED,\n });\n }\n\n const { password } = req.body;\n const { name } = req.remote_user;\n\n if (\n validationUtils.validatePassword(\n password.new,\n config?.server?.passwordValidationRegex\n ) === false\n ) {\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, APP_ERROR.PASSWORD_VALIDATION));\n }\n\n auth.changePassword(name as string, password.old, password.new, (err, isUpdated): void => {\n if (_.isNil(err) && isUpdated) {\n next({\n ok: true,\n });\n } else {\n return next(errorUtils.getInternalError(API_ERROR.INTERNAL_SERVER_ERROR));\n }\n });\n }\n );\n }\n\n return route;\n}\n\nexport default addUserAuthApi;\n"],"mappings":"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"}
|
package/build/author-utils.d.ts
CHANGED