@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.
- package/build/_virtual/_rolldown/runtime.js +23 -0
- package/build/dist-tags.d.ts +4 -4
- package/build/dist-tags.js +52 -124
- package/build/dist-tags.js.map +1 -1
- package/build/dist-tags.mjs +52 -0
- package/build/dist-tags.mjs.map +1 -0
- package/build/index.d.ts +4 -4
- package/build/index.js +61 -78
- package/build/index.js.map +1 -1
- package/build/index.mjs +59 -0
- package/build/index.mjs.map +1 -0
- package/build/package.d.ts +3 -3
- package/build/package.js +69 -120
- package/build/package.js.map +1 -1
- package/build/package.mjs +69 -0
- package/build/package.mjs.map +1 -0
- package/build/ping.d.ts +1 -1
- package/build/ping.js +10 -11
- package/build/ping.js.map +1 -1
- package/build/ping.mjs +11 -0
- package/build/ping.mjs.map +1 -0
- package/build/publish.d.ts +4 -4
- package/build/publish.js +192 -268
- package/build/publish.js.map +1 -1
- package/build/publish.mjs +196 -0
- package/build/publish.mjs.map +1 -0
- package/build/search.d.ts +1 -1
- package/build/search.js +13 -17
- package/build/search.js.map +1 -1
- package/build/search.mjs +14 -0
- package/build/search.mjs.map +1 -0
- package/build/stars.d.ts +2 -2
- package/build/stars.js +21 -59
- package/build/stars.js.map +1 -1
- package/build/stars.mjs +21 -0
- package/build/stars.mjs.map +1 -0
- package/build/user.d.ts +3 -3
- package/build/user.js +106 -188
- package/build/user.js.map +1 -1
- package/build/user.mjs +106 -0
- package/build/user.mjs.map +1 -0
- package/build/v1/login.d.ts +4 -4
- package/build/v1/login.js +115 -246
- package/build/v1/login.js.map +1 -1
- package/build/v1/login.mjs +115 -0
- package/build/v1/login.mjs.map +1 -0
- package/build/v1/profile.d.ts +3 -3
- package/build/v1/profile.js +45 -67
- package/build/v1/profile.js.map +1 -1
- package/build/v1/profile.mjs +45 -0
- package/build/v1/profile.mjs.map +1 -0
- package/build/v1/search.d.ts +3 -3
- package/build/v1/search.js +64 -113
- package/build/v1/search.js.map +1 -1
- package/build/v1/search.mjs +64 -0
- package/build/v1/search.mjs.map +1 -0
- package/build/v1/token.d.ts +4 -4
- package/build/v1/token.js +100 -201
- package/build/v1/token.js.map +1 -1
- package/build/v1/token.mjs +102 -0
- package/build/v1/token.mjs.map +1 -0
- package/build/whoami.d.ts +1 -1
- package/build/whoami.js +20 -25
- package/build/whoami.js.map +1 -1
- package/build/whoami.mjs +20 -0
- package/build/whoami.mjs.map +1 -0
- package/package.json +25 -14
package/build/v1/login.js
CHANGED
|
@@ -1,248 +1,117 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
var
|
|
11
|
-
var
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
package/build/v1/login.js.map
CHANGED
|
@@ -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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"}
|
package/build/v1/profile.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
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;
|