@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.
Files changed (51) hide show
  1. package/build/_virtual/_rolldown/runtime.js +23 -0
  2. package/build/_virtual/_rolldown/runtime.mjs +7 -0
  3. package/build/api/index.d.ts +1 -1
  4. package/build/api/index.js +26 -37
  5. package/build/api/index.js.map +1 -1
  6. package/build/api/index.mjs +27 -0
  7. package/build/api/index.mjs.map +1 -0
  8. package/build/api/package.d.ts +3 -3
  9. package/build/api/package.js +79 -200
  10. package/build/api/package.js.map +1 -1
  11. package/build/api/package.mjs +80 -0
  12. package/build/api/package.mjs.map +1 -0
  13. package/build/api/readme.d.ts +2 -2
  14. package/build/api/readme.js +64 -122
  15. package/build/api/readme.js.map +1 -1
  16. package/build/api/readme.mjs +67 -0
  17. package/build/api/readme.mjs.map +1 -0
  18. package/build/api/search.d.ts +2 -2
  19. package/build/api/search.js +57 -99
  20. package/build/api/search.js.map +1 -1
  21. package/build/api/search.mjs +59 -0
  22. package/build/api/search.mjs.map +1 -0
  23. package/build/api/sidebar.d.ts +3 -3
  24. package/build/api/sidebar.js +56 -109
  25. package/build/api/sidebar.js.map +1 -1
  26. package/build/api/sidebar.mjs +57 -0
  27. package/build/api/sidebar.mjs.map +1 -0
  28. package/build/api/user.d.ts +2 -2
  29. package/build/api/user.js +97 -212
  30. package/build/api/user.js.map +1 -1
  31. package/build/api/user.mjs +97 -0
  32. package/build/api/user.mjs.map +1 -0
  33. package/build/author-utils.d.ts +1 -1
  34. package/build/author-utils.js +109 -160
  35. package/build/author-utils.js.map +1 -1
  36. package/build/author-utils.mjs +117 -0
  37. package/build/author-utils.mjs.map +1 -0
  38. package/build/index.js +18 -47
  39. package/build/index.mjs +4 -0
  40. package/build/middleware.d.ts +1 -1
  41. package/build/middleware.js +49 -90
  42. package/build/middleware.js.map +1 -1
  43. package/build/middleware.mjs +48 -0
  44. package/build/middleware.mjs.map +1 -0
  45. package/build/web-utils.d.ts +2 -1
  46. package/build/web-utils.js +31 -31
  47. package/build/web-utils.js.map +1 -1
  48. package/build/web-utils.mjs +34 -0
  49. package/build/web-utils.mjs.map +1 -0
  50. package/package.json +30 -19
  51. package/build/index.js.map +0 -1
package/build/api/user.js CHANGED
@@ -1,215 +1,100 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports["default"] = void 0;
7
- var _debug = _interopRequireDefault(require("debug"));
8
- var _express = require("express");
9
- var _lodash = _interopRequireDefault(require("lodash"));
10
- var _auth = require("@verdaccio/auth");
11
- var _core = require("@verdaccio/core");
12
- var _middleware = require("@verdaccio/middleware");
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
- var _config$flags, _config$flags2;
22
- var route = (0, _express.Router)(); /* eslint new-cap: 0 */
23
- route.post(_middleware.WebUrls.user_login, (0, _middleware.rateLimit)(config === null || config === void 0 ? void 0 : config.userRateLimit), function (req, res, next) {
24
- var _req$body = req.body,
25
- username = _req$body.username,
26
- password = _req$body.password;
27
- debug('authenticate %o', username);
28
- auth.authenticate(username, password, /*#__PURE__*/function () {
29
- var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(err, user) {
30
- var errorCode, jWTSignOptions, _t, _t2, _t3;
31
- return _regenerator().w(function (_context) {
32
- while (1) switch (_context.n) {
33
- case 0:
34
- if (!err) {
35
- _context.n = 1;
36
- break;
37
- }
38
- errorCode = err.message ? _core.HTTP_STATUS.UNAUTHORIZED : _core.HTTP_STATUS.INTERNAL_ERROR;
39
- debug('error authenticate %o', errorCode);
40
- next(_core.errorUtils.getCode(errorCode, err.message));
41
- _context.n = 3;
42
- break;
43
- case 1:
44
- req.remote_user = user;
45
- jWTSignOptions = config.security.web.sign;
46
- res.set(_core.HEADERS.CACHE_CONTROL, 'no-cache, no-store');
47
- _t = next;
48
- _context.n = 2;
49
- return auth.jwtEncrypt(user, jWTSignOptions);
50
- case 2:
51
- _t2 = _context.v;
52
- _t3 = req.remote_user.name;
53
- _t({
54
- token: _t2,
55
- username: _t3
56
- });
57
- case 3:
58
- return _context.a(2);
59
- }
60
- }, _callee);
61
- }));
62
- return function (_x, _x2) {
63
- return _ref.apply(this, arguments);
64
- };
65
- }());
66
- });
67
- if ((config === null || config === void 0 || (_config$flags = config.flags) === null || _config$flags === void 0 ? void 0 : _config$flags.createUser) === true) {
68
- route.put(_middleware.WebUrls.user_signup, (0, _middleware.rateLimit)(config === null || config === void 0 ? void 0 : config.userRateLimit), function (req, res, next) {
69
- var _req$body2 = req.body,
70
- name = _req$body2.name,
71
- password = _req$body2.password,
72
- email = _req$body2.email,
73
- sessionId = _req$body2.sessionId;
74
- debug('login or adduser');
75
-
76
- // TOOD: reuse with login.ts file
77
- if (typeof sessionId !== 'string' || sessionId.length !== 36) {
78
- debug('sessionId is invalid length: %o', sessionId.length);
79
- return next(_core.errorUtils.getCode(_core.HTTP_STATUS.BAD_REQUEST, _core.API_ERROR.SESSION_ID_INVALID));
80
- }
81
- if (!name || !password || !email) {
82
- return next(_core.errorUtils.getCode(_core.HTTP_STATUS.BAD_REQUEST, _core.API_ERROR.BAD_DATA));
83
- }
84
- auth.add_user(name, password, /*#__PURE__*/function () {
85
- var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(err, user) {
86
- var tokens, tokenCreatedDate, minutesAgo, token, _t4;
87
- return _regenerator().w(function (_context2) {
88
- while (1) switch (_context2.n) {
89
- case 0:
90
- if (!err) {
91
- _context2.n = 2;
92
- break;
93
- }
94
- if (!(err.status >= _core.HTTP_STATUS.BAD_REQUEST && err.status < _core.HTTP_STATUS.INTERNAL_ERROR)) {
95
- _context2.n = 1;
96
- break;
97
- }
98
- debug('adduser: error on create user');
99
- // With npm registering is the same as logging in,
100
- // and npm accepts only an 409 error.
101
- // So, changing status code here.
102
- return _context2.a(2, next(_core.errorUtils.getCode(err.status, err.message) || _core.errorUtils.getConflict(err.message)));
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
- var _default = exports["default"] = addUserAuthApi;
97
+ //#endregion
98
+ exports.default = addUserAuthApi;
99
+
215
100
  //# sourceMappingURL=user.js.map
@@ -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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"}
@@ -1,4 +1,4 @@
1
- import type { Author, Person, WebManifest } from '@verdaccio/types';
1
+ import { Author, Person, WebManifest } from '@verdaccio/types';
2
2
  export declare const GENERIC_AVATAR: string;
3
3
  /**
4
4
  * Formats author field for webui.