@verdaccio/api 9.0.0-next-9.2 → 9.0.0-next-9.4

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 (67) hide show
  1. package/build/_virtual/_rolldown/runtime.js +23 -0
  2. package/build/dist-tags.d.ts +4 -4
  3. package/build/dist-tags.js +52 -124
  4. package/build/dist-tags.js.map +1 -1
  5. package/build/dist-tags.mjs +52 -0
  6. package/build/dist-tags.mjs.map +1 -0
  7. package/build/index.d.ts +4 -4
  8. package/build/index.js +61 -78
  9. package/build/index.js.map +1 -1
  10. package/build/index.mjs +59 -0
  11. package/build/index.mjs.map +1 -0
  12. package/build/package.d.ts +3 -3
  13. package/build/package.js +69 -120
  14. package/build/package.js.map +1 -1
  15. package/build/package.mjs +69 -0
  16. package/build/package.mjs.map +1 -0
  17. package/build/ping.d.ts +1 -1
  18. package/build/ping.js +10 -11
  19. package/build/ping.js.map +1 -1
  20. package/build/ping.mjs +11 -0
  21. package/build/ping.mjs.map +1 -0
  22. package/build/publish.d.ts +4 -4
  23. package/build/publish.js +192 -268
  24. package/build/publish.js.map +1 -1
  25. package/build/publish.mjs +196 -0
  26. package/build/publish.mjs.map +1 -0
  27. package/build/search.d.ts +1 -1
  28. package/build/search.js +13 -17
  29. package/build/search.js.map +1 -1
  30. package/build/search.mjs +14 -0
  31. package/build/search.mjs.map +1 -0
  32. package/build/stars.d.ts +2 -2
  33. package/build/stars.js +21 -59
  34. package/build/stars.js.map +1 -1
  35. package/build/stars.mjs +21 -0
  36. package/build/stars.mjs.map +1 -0
  37. package/build/user.d.ts +3 -3
  38. package/build/user.js +106 -188
  39. package/build/user.js.map +1 -1
  40. package/build/user.mjs +106 -0
  41. package/build/user.mjs.map +1 -0
  42. package/build/v1/login.d.ts +4 -4
  43. package/build/v1/login.js +115 -246
  44. package/build/v1/login.js.map +1 -1
  45. package/build/v1/login.mjs +115 -0
  46. package/build/v1/login.mjs.map +1 -0
  47. package/build/v1/profile.d.ts +3 -3
  48. package/build/v1/profile.js +45 -67
  49. package/build/v1/profile.js.map +1 -1
  50. package/build/v1/profile.mjs +45 -0
  51. package/build/v1/profile.mjs.map +1 -0
  52. package/build/v1/search.d.ts +3 -3
  53. package/build/v1/search.js +64 -113
  54. package/build/v1/search.js.map +1 -1
  55. package/build/v1/search.mjs +64 -0
  56. package/build/v1/search.mjs.map +1 -0
  57. package/build/v1/token.d.ts +4 -4
  58. package/build/v1/token.js +100 -201
  59. package/build/v1/token.js.map +1 -1
  60. package/build/v1/token.mjs +102 -0
  61. package/build/v1/token.mjs.map +1 -0
  62. package/build/whoami.d.ts +1 -1
  63. package/build/whoami.js +20 -25
  64. package/build/whoami.js.map +1 -1
  65. package/build/whoami.mjs +20 -0
  66. package/build/whoami.mjs.map +1 -0
  67. package/package.json +25 -14
package/build/v1/login.js CHANGED
@@ -1,248 +1,117 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports["default"] = _default;
7
- var _debug = _interopRequireDefault(require("debug"));
8
- var _nodeCrypto = require("node:crypto");
9
- var _auth = require("@verdaccio/auth");
10
- var _config = require("@verdaccio/config");
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:api:login');
19
- var WEB_LOGIN_SESSION_ID = 'web-login-sessionId';
20
-
21
- // https://github.com/npm/npm-profile/blob/main/lib/index.js
22
- function _default(route, auth, storage, config, logger) {
23
- route.post(_middleware.LOGIN_API_ENDPOINTS.login, (0, _middleware.rateLimit)(config === null || config === void 0 ? void 0 : config.userRateLimit), /*#__PURE__*/function () {
24
- var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(req, res) {
25
- var sessionId, protocol, host, port, loginUrl, doneUrl;
26
- return _regenerator().w(function (_context) {
27
- while (1) switch (_context.n) {
28
- case 0:
29
- // create new login session (without token)
30
- sessionId = (0, _nodeCrypto.randomUUID)();
31
- debug('creating login session %o', sessionId);
32
- _context.n = 1;
33
- return storage.saveToken({
34
- user: sessionId,
35
- token: '',
36
- key: WEB_LOGIN_SESSION_ID,
37
- readonly: false,
38
- created: new Date().getTime()
39
- });
40
- case 1:
41
- res.status(_core.HTTP_STATUS.OK);
42
-
43
- // Assuming Web UI is running on the same address as API
44
- protocol = req.protocol;
45
- host = req.hostname;
46
- port = req.socket.localPort;
47
- loginUrl = "".concat(protocol, "://").concat(host, ":").concat(port, "/-/web/login?next=").concat(_middleware.LOGIN_API_ENDPOINTS.login_cli, "/").concat(sessionId);
48
- doneUrl = "".concat(protocol, "://").concat(host, ":").concat(port).concat(_middleware.LOGIN_API_ENDPOINTS.login_done, "/").concat(sessionId);
49
- debug('loginUrl: %o', loginUrl);
50
- debug('doneUrl: %o', doneUrl);
51
- res.json({
52
- loginUrl: loginUrl,
53
- doneUrl: doneUrl
54
- });
55
- case 2:
56
- return _context.a(2);
57
- }
58
- }, _callee);
59
- }));
60
- return function (_x, _x2) {
61
- return _ref.apply(this, arguments);
62
- };
63
- }());
64
- route.get(_middleware.LOGIN_API_ENDPOINTS.login_done_session, (0, _middleware.rateLimit)(config === null || config === void 0 ? void 0 : config.userRateLimit), /*#__PURE__*/function () {
65
- var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(req, res, next) {
66
- var sessionId, tokens, tokenCreatedDate, minutesAgo, _t;
67
- return _regenerator().w(function (_context2) {
68
- while (1) switch (_context2.p = _context2.n) {
69
- case 0:
70
- debug('polling login session %o', req.params.sessionId);
71
- if (req.params.sessionId) {
72
- _context2.n = 1;
73
- break;
74
- }
75
- debug('sessionId is missing');
76
- return _context2.a(2, next(_core.errorUtils.getCode(_core.HTTP_STATUS.BAD_REQUEST, _core.API_ERROR.SESSION_ID_REQUIRED)));
77
- case 1:
78
- sessionId = req.params.sessionId;
79
- if (!(sessionId.length !== 36)) {
80
- _context2.n = 2;
81
- break;
82
- }
83
- debug('sessionId is invalid length: %o', sessionId.length);
84
- return _context2.a(2, next(_core.errorUtils.getCode(_core.HTTP_STATUS.BAD_REQUEST, _core.API_ERROR.SESSION_ID_INVALID)));
85
- case 2:
86
- _context2.p = 2;
87
- _context2.n = 3;
88
- return storage.readTokens({
89
- user: sessionId
90
- });
91
- case 3:
92
- tokens = _context2.v;
93
- debug('tokens found for sessionId %o: %o', sessionId, tokens.length);
94
- if (!(tokens && tokens.length === 1 && tokens[0].key === WEB_LOGIN_SESSION_ID)) {
95
- _context2.n = 8;
96
- break;
97
- }
98
- if (!(tokens[0].token.length === 0)) {
99
- _context2.n = 4;
100
- break;
101
- }
102
- debug('waiting for authentication');
103
- // Poll again after short delay
104
- // TODO: make this configurable (default 5 seconds)
105
- res.status(_core.HTTP_STATUS.ACCEPTED);
106
- res.set(_core.HEADERS.RETRY_AFTER, '5');
107
- res.json({});
108
- _context2.n = 7;
109
- break;
110
- case 4:
111
- // session token can only be used once
112
- debug('deleting session token');
113
- _context2.n = 5;
114
- return storage.deleteToken(sessionId, tokens[0].key);
115
- case 5:
116
- // Check if token has expired
117
- // TODO: make this configurable (default 2 minutes)
118
- tokenCreatedDate = new Date(tokens[0].created);
119
- minutesAgo = new Date(Date.now() - 2 * 60 * 1000);
120
- if (!(tokenCreatedDate < minutesAgo)) {
121
- _context2.n = 6;
122
- break;
123
- }
124
- debug('session token expired');
125
- return _context2.a(2, next(_core.errorUtils.getUnauthorized(_core.API_ERROR.SESSION_TOKEN_EXPIRED)));
126
- case 6:
127
- debug('session token is valid, login successful');
128
- res.status(_core.HTTP_STATUS.OK);
129
- res.json({
130
- token: tokens[0].token
131
- });
132
- case 7:
133
- _context2.n = 9;
134
- break;
135
- case 8:
136
- return _context2.a(2, next(_core.errorUtils.getCode(_core.HTTP_STATUS.BAD_REQUEST, _core.API_ERROR.SESSION_ID_INVALID)));
137
- case 9:
138
- _context2.n = 11;
139
- break;
140
- case 10:
141
- _context2.p = 10;
142
- _t = _context2.v;
143
- logger.error({
144
- error: _t.msg
145
- }, 'token list has failed: @{error}');
146
- return _context2.a(2, next(_core.errorUtils.getCode(_core.HTTP_STATUS.INTERNAL_ERROR, _t.message)));
147
- case 11:
148
- return _context2.a(2);
149
- }
150
- }, _callee2, null, [[2, 10]]);
151
- }));
152
- return function (_x3, _x4, _x5) {
153
- return _ref2.apply(this, arguments);
154
- };
155
- }());
156
- route.post(_middleware.LOGIN_API_ENDPOINTS.login_cli_session, (0, _middleware.rateLimit)(config === null || config === void 0 ? void 0 : config.userRateLimit), /*#__PURE__*/function () {
157
- var _ref3 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(req, res, next) {
158
- var _req$body, username, password, sessionId;
159
- return _regenerator().w(function (_context4) {
160
- while (1) switch (_context4.n) {
161
- case 0:
162
- _req$body = req.body, username = _req$body.username, password = _req$body.password;
163
- debug('authenticating login session %o for user %o', req.params.sessionId, username);
164
- if (req.params.sessionId) {
165
- _context4.n = 1;
166
- break;
167
- }
168
- debug('sessionId is missing');
169
- return _context4.a(2, next(_core.errorUtils.getCode(_core.HTTP_STATUS.BAD_REQUEST, _core.API_ERROR.SESSION_ID_REQUIRED)));
170
- case 1:
171
- sessionId = req.params.sessionId;
172
- if (!(sessionId.length !== 36)) {
173
- _context4.n = 2;
174
- break;
175
- }
176
- debug('sessionId is invalid length: %o', sessionId.length);
177
- return _context4.a(2, next(_core.errorUtils.getCode(_core.HTTP_STATUS.BAD_REQUEST, _core.API_ERROR.SESSION_ID_INVALID)));
178
- case 2:
179
- auth.authenticate(username, password, /*#__PURE__*/function () {
180
- var _callbackAuthenticate = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(err, user) {
181
- var _remoteUser$name;
182
- var remoteUser, token, message;
183
- return _regenerator().w(function (_context3) {
184
- while (1) switch (_context3.n) {
185
- case 0:
186
- if (!err) {
187
- _context3.n = 1;
188
- break;
189
- }
190
- logger.trace({
191
- username: username,
192
- err: err
193
- }, 'authenticating for user @{username} failed. Error: @{err.message}');
194
- return _context3.a(2, next(_core.errorUtils.getCode(_core.HTTP_STATUS.UNAUTHORIZED, err.message)));
195
- case 1:
196
- remoteUser = (0, _config.createRemoteUser)(username, (user === null || user === void 0 ? void 0 : user.groups) || []);
197
- _context3.n = 2;
198
- return (0, _auth.getApiToken)(auth, config, remoteUser, password);
199
- case 2:
200
- token = _context3.v;
201
- if (token) {
202
- _context3.n = 3;
203
- break;
204
- }
205
- return _context3.a(2, next(_core.errorUtils.getUnauthorized()));
206
- case 3:
207
- // Replace login session with token (to be picked up by the "done" endpoint)
208
- debug('saving token for sessionId %o', sessionId);
209
- _context3.n = 4;
210
- return storage.deleteToken(sessionId, WEB_LOGIN_SESSION_ID);
211
- case 4:
212
- _context3.n = 5;
213
- return storage.saveToken({
214
- user: sessionId,
215
- token: token,
216
- key: WEB_LOGIN_SESSION_ID,
217
- readonly: false,
218
- created: new Date().getTime()
219
- });
220
- case 5:
221
- message = _core.authUtils.getAuthenticatedMessage((_remoteUser$name = remoteUser.name) !== null && _remoteUser$name !== void 0 ? _remoteUser$name : '');
222
- res.status(_core.HTTP_STATUS.CREATED);
223
- res.set(_core.HEADERS.CACHE_CONTROL, 'no-cache, no-store');
224
- res.json({
225
- ok: message,
226
- token: token
227
- });
228
- case 6:
229
- return _context3.a(2);
230
- }
231
- }, _callee3);
232
- }));
233
- function callbackAuthenticate(_x9, _x0) {
234
- return _callbackAuthenticate.apply(this, arguments);
235
- }
236
- return callbackAuthenticate;
237
- }());
238
- case 3:
239
- return _context4.a(2);
240
- }
241
- }, _callee4);
242
- }));
243
- return function (_x6, _x7, _x8) {
244
- return _ref3.apply(this, arguments);
245
- };
246
- }());
1
+ const require_runtime = require("../_virtual/_rolldown/runtime.js");
2
+ let debug = require("debug");
3
+ debug = require_runtime.__toESM(debug);
4
+ let _verdaccio_middleware = require("@verdaccio/middleware");
5
+ let _verdaccio_core = require("@verdaccio/core");
6
+ let _verdaccio_auth = require("@verdaccio/auth");
7
+ let _verdaccio_config = require("@verdaccio/config");
8
+ let node_crypto = require("node:crypto");
9
+ //#region src/v1/login.ts
10
+ var debug$1 = (0, debug.default)("verdaccio:api:login");
11
+ var WEB_LOGIN_SESSION_ID = "web-login-sessionId";
12
+ function login_default(route, auth, storage, config, logger) {
13
+ route.post(_verdaccio_middleware.LOGIN_API_ENDPOINTS.login, (0, _verdaccio_middleware.rateLimit)(config?.userRateLimit), async function(req, res) {
14
+ const sessionId = (0, node_crypto.randomUUID)();
15
+ debug$1("creating login session %o", sessionId);
16
+ await storage.saveToken({
17
+ user: sessionId,
18
+ token: "",
19
+ key: WEB_LOGIN_SESSION_ID,
20
+ readonly: false,
21
+ created: (/* @__PURE__ */ new Date()).getTime()
22
+ });
23
+ res.status(_verdaccio_core.HTTP_STATUS.OK);
24
+ const protocol = req.protocol;
25
+ const host = req.hostname;
26
+ const port = req.socket.localPort;
27
+ const loginUrl = `${protocol}://${host}:${port}/-/web/login?next=${_verdaccio_middleware.LOGIN_API_ENDPOINTS.login_cli}/${sessionId}`;
28
+ const doneUrl = `${protocol}://${host}:${port}${_verdaccio_middleware.LOGIN_API_ENDPOINTS.login_done}/${sessionId}`;
29
+ debug$1("loginUrl: %o", loginUrl);
30
+ debug$1("doneUrl: %o", doneUrl);
31
+ res.json({
32
+ loginUrl,
33
+ doneUrl
34
+ });
35
+ });
36
+ route.get(_verdaccio_middleware.LOGIN_API_ENDPOINTS.login_done_session, (0, _verdaccio_middleware.rateLimit)(config?.userRateLimit), async function(req, res, next) {
37
+ debug$1("polling login session %o", req.params.sessionId);
38
+ if (!req.params.sessionId) {
39
+ debug$1("sessionId is missing");
40
+ return next(_verdaccio_core.errorUtils.getCode(_verdaccio_core.HTTP_STATUS.BAD_REQUEST, _verdaccio_core.API_ERROR.SESSION_ID_REQUIRED));
41
+ }
42
+ const sessionId = req.params.sessionId;
43
+ if (sessionId.length !== 36) {
44
+ debug$1("sessionId is invalid length: %o", sessionId.length);
45
+ return next(_verdaccio_core.errorUtils.getCode(_verdaccio_core.HTTP_STATUS.BAD_REQUEST, _verdaccio_core.API_ERROR.SESSION_ID_INVALID));
46
+ }
47
+ try {
48
+ const tokens = await storage.readTokens({ user: sessionId });
49
+ debug$1("tokens found for sessionId %o: %o", sessionId, tokens.length);
50
+ if (tokens && tokens.length === 1 && tokens[0].key === WEB_LOGIN_SESSION_ID) if (tokens[0].token.length === 0) {
51
+ debug$1("waiting for authentication");
52
+ res.status(_verdaccio_core.HTTP_STATUS.ACCEPTED);
53
+ res.set(_verdaccio_core.HEADERS.RETRY_AFTER, "5");
54
+ res.json({});
55
+ } else {
56
+ debug$1("deleting session token");
57
+ await storage.deleteToken(sessionId, tokens[0].key);
58
+ if (new Date(tokens[0].created) < /* @__PURE__ */ new Date(Date.now() - 120 * 1e3)) {
59
+ debug$1("session token expired");
60
+ return next(_verdaccio_core.errorUtils.getUnauthorized(_verdaccio_core.API_ERROR.SESSION_TOKEN_EXPIRED));
61
+ }
62
+ debug$1("session token is valid, login successful");
63
+ res.status(_verdaccio_core.HTTP_STATUS.OK);
64
+ res.json({ token: tokens[0].token });
65
+ }
66
+ else return next(_verdaccio_core.errorUtils.getCode(_verdaccio_core.HTTP_STATUS.BAD_REQUEST, _verdaccio_core.API_ERROR.SESSION_ID_INVALID));
67
+ } catch (error) {
68
+ logger.error({ error: error.msg }, "token list has failed: @{error}");
69
+ return next(_verdaccio_core.errorUtils.getCode(_verdaccio_core.HTTP_STATUS.INTERNAL_ERROR, error.message));
70
+ }
71
+ });
72
+ route.post(_verdaccio_middleware.LOGIN_API_ENDPOINTS.login_cli_session, (0, _verdaccio_middleware.rateLimit)(config?.userRateLimit), async function(req, res, next) {
73
+ const { username, password } = req.body;
74
+ debug$1("authenticating login session %o for user %o", req.params.sessionId, username);
75
+ if (!req.params.sessionId) {
76
+ debug$1("sessionId is missing");
77
+ return next(_verdaccio_core.errorUtils.getCode(_verdaccio_core.HTTP_STATUS.BAD_REQUEST, _verdaccio_core.API_ERROR.SESSION_ID_REQUIRED));
78
+ }
79
+ const sessionId = req.params.sessionId;
80
+ if (sessionId.length !== 36) {
81
+ debug$1("sessionId is invalid length: %o", sessionId.length);
82
+ return next(_verdaccio_core.errorUtils.getCode(_verdaccio_core.HTTP_STATUS.BAD_REQUEST, _verdaccio_core.API_ERROR.SESSION_ID_INVALID));
83
+ }
84
+ auth.authenticate(username, password, async function callbackAuthenticate(err, user) {
85
+ if (err) {
86
+ logger.trace({
87
+ username,
88
+ err
89
+ }, "authenticating for user @{username} failed. Error: @{err.message}");
90
+ return next(_verdaccio_core.errorUtils.getCode(_verdaccio_core.HTTP_STATUS.UNAUTHORIZED, err.message));
91
+ }
92
+ const remoteUser = (0, _verdaccio_config.createRemoteUser)(username, user?.groups || []);
93
+ const token = await (0, _verdaccio_auth.getApiToken)(auth, config, remoteUser, password);
94
+ if (!token) return next(_verdaccio_core.errorUtils.getUnauthorized());
95
+ debug$1("saving token for sessionId %o", sessionId);
96
+ await storage.deleteToken(sessionId, WEB_LOGIN_SESSION_ID);
97
+ await storage.saveToken({
98
+ user: sessionId,
99
+ token,
100
+ key: WEB_LOGIN_SESSION_ID,
101
+ readonly: false,
102
+ created: (/* @__PURE__ */ new Date()).getTime()
103
+ });
104
+ const message = _verdaccio_core.authUtils.getAuthenticatedMessage(remoteUser.name ?? "");
105
+ res.status(_verdaccio_core.HTTP_STATUS.CREATED);
106
+ res.set(_verdaccio_core.HEADERS.CACHE_CONTROL, "no-cache, no-store");
107
+ res.json({
108
+ ok: message,
109
+ token
110
+ });
111
+ });
112
+ });
247
113
  }
114
+ //#endregion
115
+ exports.default = login_default;
116
+
248
117
  //# sourceMappingURL=login.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","names":["_debug","_interopRequireDefault","require","_nodeCrypto","_auth","_config","_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","_default","route","auth","storage","config","logger","post","LOGIN_API_ENDPOINTS","login","rateLimit","userRateLimit","_ref","_callee","req","res","sessionId","protocol","host","port","loginUrl","doneUrl","_context","randomUUID","saveToken","user","token","key","readonly","created","Date","getTime","status","HTTP_STATUS","OK","hostname","socket","localPort","concat","login_cli","login_done","json","_x","_x2","get","login_done_session","_ref2","_callee2","next","tokens","tokenCreatedDate","minutesAgo","_t","_context2","params","errorUtils","getCode","BAD_REQUEST","API_ERROR","SESSION_ID_REQUIRED","SESSION_ID_INVALID","readTokens","ACCEPTED","set","HEADERS","RETRY_AFTER","deleteToken","now","getUnauthorized","SESSION_TOKEN_EXPIRED","error","msg","INTERNAL_ERROR","message","_x3","_x4","_x5","login_cli_session","_ref3","_callee4","_req$body","username","password","_context4","body","authenticate","_callbackAuthenticate","_callee3","err","_remoteUser$name","remoteUser","_context3","trace","UNAUTHORIZED","createRemoteUser","groups","getApiToken","authUtils","getAuthenticatedMessage","name","CREATED","CACHE_CONTROL","ok","callbackAuthenticate","_x9","_x0","_x6","_x7","_x8"],"sources":["../../src/v1/login.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport type { Response, Router } from 'express';\nimport { randomUUID } from 'node:crypto';\n\nimport type { Auth } from '@verdaccio/auth';\nimport { getApiToken } from '@verdaccio/auth';\nimport { createRemoteUser } from '@verdaccio/config';\nimport { API_ERROR, HEADERS, HTTP_STATUS, authUtils, errorUtils } from '@verdaccio/core';\nimport { LOGIN_API_ENDPOINTS, rateLimit } from '@verdaccio/middleware';\nimport type { Storage } from '@verdaccio/store';\nimport type { Config, Logger } from '@verdaccio/types';\n\nimport type { $NextFunctionVer, $RequestExtend } from '../../types/custom';\n\nconst debug = buildDebug('verdaccio:api:login');\n\nconst WEB_LOGIN_SESSION_ID = 'web-login-sessionId';\n\n// https://github.com/npm/npm-profile/blob/main/lib/index.js\nexport default function (\n route: Router,\n auth: Auth,\n storage: Storage,\n config: Config,\n logger: Logger\n): void {\n route.post(\n LOGIN_API_ENDPOINTS.login,\n rateLimit(config?.userRateLimit),\n async function (req: $RequestExtend, res: Response): Promise<void> {\n // create new login session (without token)\n const sessionId = randomUUID();\n debug('creating login session %o', sessionId);\n\n await storage.saveToken({\n user: sessionId,\n token: '',\n key: WEB_LOGIN_SESSION_ID,\n readonly: false,\n created: new Date().getTime(),\n });\n\n res.status(HTTP_STATUS.OK);\n\n // Assuming Web UI is running on the same address as API\n const protocol = req.protocol;\n const host = req.hostname;\n const port = req.socket.localPort;\n\n const loginUrl = `${protocol}://${host}:${port}/-/web/login?next=${LOGIN_API_ENDPOINTS.login_cli}/${sessionId}`;\n const doneUrl = `${protocol}://${host}:${port}${LOGIN_API_ENDPOINTS.login_done}/${sessionId}`;\n debug('loginUrl: %o', loginUrl);\n debug('doneUrl: %o', doneUrl);\n\n res.json({\n loginUrl,\n doneUrl,\n });\n }\n );\n\n route.get(\n LOGIN_API_ENDPOINTS.login_done_session,\n rateLimit(config?.userRateLimit),\n async function (req: $RequestExtend, res: Response, next: $NextFunctionVer): Promise<void> {\n debug('polling login session %o', req.params.sessionId);\n\n if (!req.params.sessionId) {\n debug('sessionId is missing');\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.SESSION_ID_REQUIRED));\n }\n const sessionId = req.params.sessionId;\n if (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 try {\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 } else {\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\n res.status(HTTP_STATUS.OK);\n res.json({ token: tokens[0].token });\n }\n } else {\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.SESSION_ID_INVALID));\n }\n } catch (error: any) {\n logger.error({ error: error.msg }, 'token list has failed: @{error}');\n return next(errorUtils.getCode(HTTP_STATUS.INTERNAL_ERROR, error.message));\n }\n }\n );\n\n route.post(\n LOGIN_API_ENDPOINTS.login_cli_session,\n rateLimit(config?.userRateLimit),\n async function (req: $RequestExtend, res: Response, next: $NextFunctionVer): Promise<void> {\n const { username, password } = req.body;\n debug('authenticating login session %o for user %o', req.params.sessionId, username);\n\n if (!req.params.sessionId) {\n debug('sessionId is missing');\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.SESSION_ID_REQUIRED));\n }\n const sessionId = req.params.sessionId;\n if (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 auth.authenticate(\n username,\n password,\n async function callbackAuthenticate(err, user): Promise<void> {\n if (err) {\n logger.trace(\n { username, err },\n 'authenticating for user @{username} failed. Error: @{err.message}'\n );\n return next(errorUtils.getCode(HTTP_STATUS.UNAUTHORIZED, err.message));\n }\n\n const remoteUser = createRemoteUser(username, user?.groups || []);\n const token = await getApiToken(auth, config, remoteUser, password);\n\n if (!token) {\n return next(errorUtils.getUnauthorized());\n }\n\n // Replace login session with token (to be picked up by the \"done\" endpoint)\n debug('saving token for sessionId %o', sessionId);\n await storage.deleteToken(sessionId, WEB_LOGIN_SESSION_ID);\n await storage.saveToken({\n user: sessionId,\n token,\n key: WEB_LOGIN_SESSION_ID,\n readonly: false,\n created: new Date().getTime(),\n });\n\n const message = authUtils.getAuthenticatedMessage(remoteUser.name ?? '');\n\n res.status(HTTP_STATUS.CREATED);\n res.set(HEADERS.CACHE_CONTROL, 'no-cache, no-store');\n res.json({ ok: message, token });\n }\n );\n }\n );\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"login.js","names":[],"sources":["../../src/v1/login.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport type { Response, Router } from 'express';\nimport { randomUUID } from 'node:crypto';\n\nimport type { Auth } from '@verdaccio/auth';\nimport { getApiToken } from '@verdaccio/auth';\nimport { createRemoteUser } from '@verdaccio/config';\nimport { API_ERROR, HEADERS, HTTP_STATUS, authUtils, errorUtils } from '@verdaccio/core';\nimport { LOGIN_API_ENDPOINTS, rateLimit } from '@verdaccio/middleware';\nimport type { Storage } from '@verdaccio/store';\nimport type { Config, Logger } from '@verdaccio/types';\n\nimport type { $NextFunctionVer, $RequestExtend } from '../../types/custom';\n\nconst debug = buildDebug('verdaccio:api:login');\n\nconst WEB_LOGIN_SESSION_ID = 'web-login-sessionId';\n\n// https://github.com/npm/npm-profile/blob/main/lib/index.js\nexport default function (\n route: Router,\n auth: Auth,\n storage: Storage,\n config: Config,\n logger: Logger\n): void {\n route.post(\n LOGIN_API_ENDPOINTS.login,\n rateLimit(config?.userRateLimit),\n async function (req: $RequestExtend, res: Response): Promise<void> {\n // create new login session (without token)\n const sessionId = randomUUID();\n debug('creating login session %o', sessionId);\n\n await storage.saveToken({\n user: sessionId,\n token: '',\n key: WEB_LOGIN_SESSION_ID,\n readonly: false,\n created: new Date().getTime(),\n });\n\n res.status(HTTP_STATUS.OK);\n\n // Assuming Web UI is running on the same address as API\n const protocol = req.protocol;\n const host = req.hostname;\n const port = req.socket.localPort;\n\n const loginUrl = `${protocol}://${host}:${port}/-/web/login?next=${LOGIN_API_ENDPOINTS.login_cli}/${sessionId}`;\n const doneUrl = `${protocol}://${host}:${port}${LOGIN_API_ENDPOINTS.login_done}/${sessionId}`;\n debug('loginUrl: %o', loginUrl);\n debug('doneUrl: %o', doneUrl);\n\n res.json({\n loginUrl,\n doneUrl,\n });\n }\n );\n\n route.get(\n LOGIN_API_ENDPOINTS.login_done_session,\n rateLimit(config?.userRateLimit),\n async function (req: $RequestExtend, res: Response, next: $NextFunctionVer): Promise<void> {\n debug('polling login session %o', req.params.sessionId);\n\n if (!req.params.sessionId) {\n debug('sessionId is missing');\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.SESSION_ID_REQUIRED));\n }\n const sessionId = req.params.sessionId;\n if (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 try {\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 } else {\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\n res.status(HTTP_STATUS.OK);\n res.json({ token: tokens[0].token });\n }\n } else {\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.SESSION_ID_INVALID));\n }\n } catch (error: any) {\n logger.error({ error: error.msg }, 'token list has failed: @{error}');\n return next(errorUtils.getCode(HTTP_STATUS.INTERNAL_ERROR, error.message));\n }\n }\n );\n\n route.post(\n LOGIN_API_ENDPOINTS.login_cli_session,\n rateLimit(config?.userRateLimit),\n async function (req: $RequestExtend, res: Response, next: $NextFunctionVer): Promise<void> {\n const { username, password } = req.body;\n debug('authenticating login session %o for user %o', req.params.sessionId, username);\n\n if (!req.params.sessionId) {\n debug('sessionId is missing');\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.SESSION_ID_REQUIRED));\n }\n const sessionId = req.params.sessionId;\n if (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 auth.authenticate(\n username,\n password,\n async function callbackAuthenticate(err, user): Promise<void> {\n if (err) {\n logger.trace(\n { username, err },\n 'authenticating for user @{username} failed. Error: @{err.message}'\n );\n return next(errorUtils.getCode(HTTP_STATUS.UNAUTHORIZED, err.message));\n }\n\n const remoteUser = createRemoteUser(username, user?.groups || []);\n const token = await getApiToken(auth, config, remoteUser, password);\n\n if (!token) {\n return next(errorUtils.getUnauthorized());\n }\n\n // Replace login session with token (to be picked up by the \"done\" endpoint)\n debug('saving token for sessionId %o', sessionId);\n await storage.deleteToken(sessionId, WEB_LOGIN_SESSION_ID);\n await storage.saveToken({\n user: sessionId,\n token,\n key: WEB_LOGIN_SESSION_ID,\n readonly: false,\n created: new Date().getTime(),\n });\n\n const message = authUtils.getAuthenticatedMessage(remoteUser.name ?? '');\n\n res.status(HTTP_STATUS.CREATED);\n res.set(HEADERS.CACHE_CONTROL, 'no-cache, no-store');\n res.json({ ok: message, token });\n }\n );\n }\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ import buildDebug from "debug";
2
+ import { LOGIN_API_ENDPOINTS, rateLimit } from "@verdaccio/middleware";
3
+ import { API_ERROR, HEADERS, HTTP_STATUS, authUtils, errorUtils } from "@verdaccio/core";
4
+ import { getApiToken } from "@verdaccio/auth";
5
+ import { createRemoteUser } from "@verdaccio/config";
6
+ import { randomUUID } from "node:crypto";
7
+ //#region src/v1/login.ts
8
+ var debug = buildDebug("verdaccio:api:login");
9
+ var WEB_LOGIN_SESSION_ID = "web-login-sessionId";
10
+ function login_default(route, auth, storage, config, logger) {
11
+ route.post(LOGIN_API_ENDPOINTS.login, rateLimit(config?.userRateLimit), async function(req, res) {
12
+ const sessionId = randomUUID();
13
+ debug("creating login session %o", sessionId);
14
+ await storage.saveToken({
15
+ user: sessionId,
16
+ token: "",
17
+ key: WEB_LOGIN_SESSION_ID,
18
+ readonly: false,
19
+ created: (/* @__PURE__ */ new Date()).getTime()
20
+ });
21
+ res.status(HTTP_STATUS.OK);
22
+ const protocol = req.protocol;
23
+ const host = req.hostname;
24
+ const port = req.socket.localPort;
25
+ const loginUrl = `${protocol}://${host}:${port}/-/web/login?next=${LOGIN_API_ENDPOINTS.login_cli}/${sessionId}`;
26
+ const doneUrl = `${protocol}://${host}:${port}${LOGIN_API_ENDPOINTS.login_done}/${sessionId}`;
27
+ debug("loginUrl: %o", loginUrl);
28
+ debug("doneUrl: %o", doneUrl);
29
+ res.json({
30
+ loginUrl,
31
+ doneUrl
32
+ });
33
+ });
34
+ route.get(LOGIN_API_ENDPOINTS.login_done_session, rateLimit(config?.userRateLimit), async function(req, res, next) {
35
+ debug("polling login session %o", req.params.sessionId);
36
+ if (!req.params.sessionId) {
37
+ debug("sessionId is missing");
38
+ return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.SESSION_ID_REQUIRED));
39
+ }
40
+ const sessionId = req.params.sessionId;
41
+ if (sessionId.length !== 36) {
42
+ debug("sessionId is invalid length: %o", sessionId.length);
43
+ return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.SESSION_ID_INVALID));
44
+ }
45
+ try {
46
+ const tokens = await storage.readTokens({ user: sessionId });
47
+ debug("tokens found for sessionId %o: %o", sessionId, tokens.length);
48
+ if (tokens && tokens.length === 1 && tokens[0].key === WEB_LOGIN_SESSION_ID) if (tokens[0].token.length === 0) {
49
+ debug("waiting for authentication");
50
+ res.status(HTTP_STATUS.ACCEPTED);
51
+ res.set(HEADERS.RETRY_AFTER, "5");
52
+ res.json({});
53
+ } else {
54
+ debug("deleting session token");
55
+ await storage.deleteToken(sessionId, tokens[0].key);
56
+ if (new Date(tokens[0].created) < /* @__PURE__ */ new Date(Date.now() - 120 * 1e3)) {
57
+ debug("session token expired");
58
+ return next(errorUtils.getUnauthorized(API_ERROR.SESSION_TOKEN_EXPIRED));
59
+ }
60
+ debug("session token is valid, login successful");
61
+ res.status(HTTP_STATUS.OK);
62
+ res.json({ token: tokens[0].token });
63
+ }
64
+ else return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.SESSION_ID_INVALID));
65
+ } catch (error) {
66
+ logger.error({ error: error.msg }, "token list has failed: @{error}");
67
+ return next(errorUtils.getCode(HTTP_STATUS.INTERNAL_ERROR, error.message));
68
+ }
69
+ });
70
+ route.post(LOGIN_API_ENDPOINTS.login_cli_session, rateLimit(config?.userRateLimit), async function(req, res, next) {
71
+ const { username, password } = req.body;
72
+ debug("authenticating login session %o for user %o", req.params.sessionId, username);
73
+ if (!req.params.sessionId) {
74
+ debug("sessionId is missing");
75
+ return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.SESSION_ID_REQUIRED));
76
+ }
77
+ const sessionId = req.params.sessionId;
78
+ if (sessionId.length !== 36) {
79
+ debug("sessionId is invalid length: %o", sessionId.length);
80
+ return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.SESSION_ID_INVALID));
81
+ }
82
+ auth.authenticate(username, password, async function callbackAuthenticate(err, user) {
83
+ if (err) {
84
+ logger.trace({
85
+ username,
86
+ err
87
+ }, "authenticating for user @{username} failed. Error: @{err.message}");
88
+ return next(errorUtils.getCode(HTTP_STATUS.UNAUTHORIZED, err.message));
89
+ }
90
+ const remoteUser = createRemoteUser(username, user?.groups || []);
91
+ const token = await getApiToken(auth, config, remoteUser, password);
92
+ if (!token) return next(errorUtils.getUnauthorized());
93
+ debug("saving token for sessionId %o", sessionId);
94
+ await storage.deleteToken(sessionId, WEB_LOGIN_SESSION_ID);
95
+ await storage.saveToken({
96
+ user: sessionId,
97
+ token,
98
+ key: WEB_LOGIN_SESSION_ID,
99
+ readonly: false,
100
+ created: (/* @__PURE__ */ new Date()).getTime()
101
+ });
102
+ const message = authUtils.getAuthenticatedMessage(remoteUser.name ?? "");
103
+ res.status(HTTP_STATUS.CREATED);
104
+ res.set(HEADERS.CACHE_CONTROL, "no-cache, no-store");
105
+ res.json({
106
+ ok: message,
107
+ token
108
+ });
109
+ });
110
+ });
111
+ }
112
+ //#endregion
113
+ export { login_default as default };
114
+
115
+ //# sourceMappingURL=login.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.mjs","names":[],"sources":["../../src/v1/login.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport type { Response, Router } from 'express';\nimport { randomUUID } from 'node:crypto';\n\nimport type { Auth } from '@verdaccio/auth';\nimport { getApiToken } from '@verdaccio/auth';\nimport { createRemoteUser } from '@verdaccio/config';\nimport { API_ERROR, HEADERS, HTTP_STATUS, authUtils, errorUtils } from '@verdaccio/core';\nimport { LOGIN_API_ENDPOINTS, rateLimit } from '@verdaccio/middleware';\nimport type { Storage } from '@verdaccio/store';\nimport type { Config, Logger } from '@verdaccio/types';\n\nimport type { $NextFunctionVer, $RequestExtend } from '../../types/custom';\n\nconst debug = buildDebug('verdaccio:api:login');\n\nconst WEB_LOGIN_SESSION_ID = 'web-login-sessionId';\n\n// https://github.com/npm/npm-profile/blob/main/lib/index.js\nexport default function (\n route: Router,\n auth: Auth,\n storage: Storage,\n config: Config,\n logger: Logger\n): void {\n route.post(\n LOGIN_API_ENDPOINTS.login,\n rateLimit(config?.userRateLimit),\n async function (req: $RequestExtend, res: Response): Promise<void> {\n // create new login session (without token)\n const sessionId = randomUUID();\n debug('creating login session %o', sessionId);\n\n await storage.saveToken({\n user: sessionId,\n token: '',\n key: WEB_LOGIN_SESSION_ID,\n readonly: false,\n created: new Date().getTime(),\n });\n\n res.status(HTTP_STATUS.OK);\n\n // Assuming Web UI is running on the same address as API\n const protocol = req.protocol;\n const host = req.hostname;\n const port = req.socket.localPort;\n\n const loginUrl = `${protocol}://${host}:${port}/-/web/login?next=${LOGIN_API_ENDPOINTS.login_cli}/${sessionId}`;\n const doneUrl = `${protocol}://${host}:${port}${LOGIN_API_ENDPOINTS.login_done}/${sessionId}`;\n debug('loginUrl: %o', loginUrl);\n debug('doneUrl: %o', doneUrl);\n\n res.json({\n loginUrl,\n doneUrl,\n });\n }\n );\n\n route.get(\n LOGIN_API_ENDPOINTS.login_done_session,\n rateLimit(config?.userRateLimit),\n async function (req: $RequestExtend, res: Response, next: $NextFunctionVer): Promise<void> {\n debug('polling login session %o', req.params.sessionId);\n\n if (!req.params.sessionId) {\n debug('sessionId is missing');\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.SESSION_ID_REQUIRED));\n }\n const sessionId = req.params.sessionId;\n if (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 try {\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 } else {\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\n res.status(HTTP_STATUS.OK);\n res.json({ token: tokens[0].token });\n }\n } else {\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.SESSION_ID_INVALID));\n }\n } catch (error: any) {\n logger.error({ error: error.msg }, 'token list has failed: @{error}');\n return next(errorUtils.getCode(HTTP_STATUS.INTERNAL_ERROR, error.message));\n }\n }\n );\n\n route.post(\n LOGIN_API_ENDPOINTS.login_cli_session,\n rateLimit(config?.userRateLimit),\n async function (req: $RequestExtend, res: Response, next: $NextFunctionVer): Promise<void> {\n const { username, password } = req.body;\n debug('authenticating login session %o for user %o', req.params.sessionId, username);\n\n if (!req.params.sessionId) {\n debug('sessionId is missing');\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.SESSION_ID_REQUIRED));\n }\n const sessionId = req.params.sessionId;\n if (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 auth.authenticate(\n username,\n password,\n async function callbackAuthenticate(err, user): Promise<void> {\n if (err) {\n logger.trace(\n { username, err },\n 'authenticating for user @{username} failed. Error: @{err.message}'\n );\n return next(errorUtils.getCode(HTTP_STATUS.UNAUTHORIZED, err.message));\n }\n\n const remoteUser = createRemoteUser(username, user?.groups || []);\n const token = await getApiToken(auth, config, remoteUser, password);\n\n if (!token) {\n return next(errorUtils.getUnauthorized());\n }\n\n // Replace login session with token (to be picked up by the \"done\" endpoint)\n debug('saving token for sessionId %o', sessionId);\n await storage.deleteToken(sessionId, WEB_LOGIN_SESSION_ID);\n await storage.saveToken({\n user: sessionId,\n token,\n key: WEB_LOGIN_SESSION_ID,\n readonly: false,\n created: new Date().getTime(),\n });\n\n const message = authUtils.getAuthenticatedMessage(remoteUser.name ?? '');\n\n res.status(HTTP_STATUS.CREATED);\n res.set(HEADERS.CACHE_CONTROL, 'no-cache, no-store');\n res.json({ ok: message, token });\n }\n );\n }\n );\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import type { Router } from 'express';
2
- import type { Auth } from '@verdaccio/auth';
3
- import type { Config } from '@verdaccio/types';
1
+ import { Router } from 'express';
2
+ import { Auth } from '@verdaccio/auth';
3
+ import { Config } from '@verdaccio/types';
4
4
  export interface Profile {
5
5
  tfa: boolean;
6
6
  name: string;