@verdaccio/api 9.0.0-next-9.5 → 9.0.0-next-9.7

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/README.md CHANGED
@@ -29,16 +29,16 @@ If you want to report a security vulnerability, please follow the steps which we
29
29
 
30
30
  Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/verdaccio/contribute)]
31
31
 
32
- [![sponsor](https://opencollective.com/verdaccio/sponsor/0/avatar.svg)](https://opencollective.com/verdaccio/sponsor/0/website)
33
- [![sponsor](https://opencollective.com/verdaccio/sponsor/1/avatar.svg)](https://opencollective.com/verdaccio/sponsor/1/website)
34
- [![sponsor](https://opencollective.com/verdaccio/sponsor/2/avatar.svg)](https://opencollective.com/verdaccio/sponsor/2/website)
35
- [![sponsor](https://opencollective.com/verdaccio/sponsor/3/avatar.svg)](https://opencollective.com/verdaccio/sponsor/3/website)
36
- [![sponsor](https://opencollective.com/verdaccio/sponsor/4/avatar.svg)](https://opencollective.com/verdaccio/sponsor/4/website)
37
- [![sponsor](https://opencollective.com/verdaccio/sponsor/5/avatar.svg)](https://opencollective.com/verdaccio/sponsor/5/website)
38
- [![sponsor](https://opencollective.com/verdaccio/sponsor/6/avatar.svg)](https://opencollective.com/verdaccio/sponsor/6/website)
39
- [![sponsor](https://opencollective.com/verdaccio/sponsor/7/avatar.svg)](https://opencollective.com/verdaccio/sponsor/7/website)
40
- [![sponsor](https://opencollective.com/verdaccio/sponsor/8/avatar.svg)](https://opencollective.com/verdaccio/sponsor/8/website)
41
- [![sponsor](https://opencollective.com/verdaccio/sponsor/9/avatar.svg)](https://opencollective.com/verdaccio/sponsor/9/website)
32
+ [![sponsor](https://opencollective.com/verdaccio/sponsor/0/avatar.png)](https://opencollective.com/verdaccio/sponsor/0/website)
33
+ [![sponsor](https://opencollective.com/verdaccio/sponsor/1/avatar.png)](https://opencollective.com/verdaccio/sponsor/1/website)
34
+ [![sponsor](https://opencollective.com/verdaccio/sponsor/2/avatar.png)](https://opencollective.com/verdaccio/sponsor/2/website)
35
+ [![sponsor](https://opencollective.com/verdaccio/sponsor/3/avatar.png)](https://opencollective.com/verdaccio/sponsor/3/website)
36
+ [![sponsor](https://opencollective.com/verdaccio/sponsor/4/avatar.png)](https://opencollective.com/verdaccio/sponsor/4/website)
37
+ [![sponsor](https://opencollective.com/verdaccio/sponsor/5/avatar.png)](https://opencollective.com/verdaccio/sponsor/5/website)
38
+ [![sponsor](https://opencollective.com/verdaccio/sponsor/6/avatar.png)](https://opencollective.com/verdaccio/sponsor/6/website)
39
+ [![sponsor](https://opencollective.com/verdaccio/sponsor/7/avatar.png)](https://opencollective.com/verdaccio/sponsor/7/website)
40
+ [![sponsor](https://opencollective.com/verdaccio/sponsor/8/avatar.png)](https://opencollective.com/verdaccio/sponsor/8/website)
41
+ [![sponsor](https://opencollective.com/verdaccio/sponsor/9/avatar.png)](https://opencollective.com/verdaccio/sponsor/9/website)
42
42
 
43
43
  ## Open Collective Backers
44
44
 
package/build/user.js CHANGED
@@ -61,7 +61,7 @@ function user_default(route, auth, config, logger) {
61
61
  debug$1("login: new token");
62
62
  if (!token) return next(_verdaccio_core.errorUtils.getUnauthorized());
63
63
  res.status(_verdaccio_core.HTTP_STATUS.CREATED);
64
- res.set(_verdaccio_core.HEADERS.CACHE_CONTROL, "no-cache, no-store");
64
+ res.set(_verdaccio_core.HEADERS.CACHE_CONTROL, _verdaccio_core.HEADERS.NO_CACHE);
65
65
  const message = _verdaccio_core.authUtils.getAuthenticatedMessage(req.remote_user.name);
66
66
  debug$1("login: created user message %o", message);
67
67
  return next({
@@ -88,7 +88,7 @@ function user_default(route, auth, config, logger) {
88
88
  if (!token) return next(_verdaccio_core.errorUtils.getUnauthorized());
89
89
  req.remote_user = user;
90
90
  res.status(_verdaccio_core.HTTP_STATUS.CREATED);
91
- res.set(_verdaccio_core.HEADERS.CACHE_CONTROL, "no-cache, no-store");
91
+ res.set(_verdaccio_core.HEADERS.CACHE_CONTROL, _verdaccio_core.HEADERS.NO_CACHE);
92
92
  debug$1("adduser: user has been created");
93
93
  return next({
94
94
  ok: `user '${req.body.name}' created`,
package/build/user.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"user.js","names":[],"sources":["../src/user.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport type { Response, Router } from 'express';\n\nimport type { Auth } from '@verdaccio/auth';\nimport { getApiToken } from '@verdaccio/auth';\nimport { createRemoteUser } from '@verdaccio/config';\nimport {\n API_ERROR,\n API_MESSAGE,\n HEADERS,\n HTTP_STATUS,\n authUtils,\n cryptoUtils,\n errorUtils,\n validationUtils,\n} from '@verdaccio/core';\nimport { USER_API_ENDPOINTS, rateLimit } from '@verdaccio/middleware';\nimport type { Config, Logger, RemoteUser } from '@verdaccio/types';\n\nimport type { $NextFunctionVer, $RequestExtend } from '../types/custom';\n\nconst debug = buildDebug('verdaccio:api:user');\n\nexport default function (route: Router, auth: Auth, config: Config, logger: Logger): void {\n route.get(\n USER_API_ENDPOINTS.get_user,\n rateLimit(config?.userRateLimit),\n function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void {\n debug('verifying user');\n\n if (\n !req.remote_user ||\n typeof req.remote_user.name !== 'string' ||\n req.remote_user.name === ''\n ) {\n debug('user not logged in');\n res.status(HTTP_STATUS.OK);\n return next({ ok: false });\n }\n\n const username = req.params.org_couchdb_user.split(':')[1];\n const message = authUtils.getAuthenticatedMessage(req.remote_user.name);\n debug('user authenticated message %o', message);\n res.status(HTTP_STATUS.OK);\n next({\n // 'npm owner' requires user info\n // TODO: we don't have the email\n name: username,\n email: '',\n ok: message,\n });\n }\n );\n\n /**\n * \n * body example\n * req.body = {\n _id: \"org.couchdb.user:jjjj\",\n name: \"jjjj\",\n password: \"jjjj\",\n type: \"user\",\n roles: [],\n date: \"2022-07-08T15:51:04.002Z\",\n }\n * \n * @export\n * @param {Router} route\n * @param {Auth} auth\n * @param {Config} config\n */\n route.put(\n USER_API_ENDPOINTS.add_user,\n rateLimit(config?.userRateLimit),\n function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void {\n const { name, password } = req.body;\n debug('login or adduser');\n const remoteName = req?.remote_user?.name;\n\n if (!validationUtils.validateUserName(req.params.org_couchdb_user, name)) {\n return next(errorUtils.getBadRequest(API_ERROR.USERNAME_MISMATCH));\n }\n\n if (typeof remoteName !== 'undefined' && typeof name === 'string' && remoteName === name) {\n debug('login: no remote user detected');\n auth.authenticate(\n name,\n password,\n async function callbackAuthenticate(err, user): Promise<void> {\n if (err) {\n logger.trace(\n { name, err },\n 'authenticating for user @{username} failed. Error: @{err.message}'\n );\n return next(\n errorUtils.getCode(HTTP_STATUS.UNAUTHORIZED, API_ERROR.BAD_USERNAME_PASSWORD)\n );\n }\n\n const restoredRemoteUser: RemoteUser = createRemoteUser(name, user?.groups || []);\n const token = await getApiToken(auth, config, restoredRemoteUser, password);\n debug('login: new token');\n if (!token) {\n return next(errorUtils.getUnauthorized());\n }\n\n res.status(HTTP_STATUS.CREATED);\n res.set(HEADERS.CACHE_CONTROL, 'no-cache, no-store');\n\n const message = authUtils.getAuthenticatedMessage(req.remote_user.name);\n debug('login: created user message %o', message);\n\n return next({\n ok: message,\n token,\n });\n }\n );\n } else {\n debug('adduser: %o', name);\n if (\n validationUtils.validatePassword(password, config?.server?.passwordValidationRegex) ===\n false\n ) {\n debug('adduser: invalid password');\n\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.PASSWORD_SHORT));\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 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 }\n if (!token) {\n return next(errorUtils.getUnauthorized());\n }\n\n req.remote_user = user;\n res.status(HTTP_STATUS.CREATED);\n res.set(HEADERS.CACHE_CONTROL, 'no-cache, no-store');\n debug('adduser: user has been created');\n return next({\n ok: `user '${req.body.name}' created`,\n token,\n });\n });\n }\n }\n );\n\n route.delete(\n USER_API_ENDPOINTS.user_token,\n function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void {\n res.status(HTTP_STATUS.OK);\n next({\n ok: API_MESSAGE.LOGGED_OUT,\n });\n }\n );\n}\n"],"mappings":";;;;;;;;AAqBA,IAAM,WAAA,GAAA,MAAA,SAAmB,qBAAqB;AAE9C,SAAA,aAAyB,OAAe,MAAY,QAAgB,QAAsB;AACxF,OAAM,IACJ,sBAAA,mBAAmB,WAAA,GAAA,sBAAA,WACT,QAAQ,cAAc,EAChC,SAAU,KAAqB,KAAe,MAA8B;AAC1E,UAAM,iBAAiB;AAEvB,MACE,CAAC,IAAI,eACL,OAAO,IAAI,YAAY,SAAS,YAChC,IAAI,YAAY,SAAS,IACzB;AACA,WAAM,qBAAqB;AAC3B,OAAI,OAAO,gBAAA,YAAY,GAAG;AAC1B,UAAO,KAAK,EAAE,IAAI,OAAO,CAAC;;EAG5B,MAAM,WAAW,IAAI,OAAO,iBAAiB,MAAM,IAAI,CAAC;EACxD,MAAM,UAAU,gBAAA,UAAU,wBAAwB,IAAI,YAAY,KAAK;AACvE,UAAM,iCAAiC,QAAQ;AAC/C,MAAI,OAAO,gBAAA,YAAY,GAAG;AAC1B,OAAK;GAGH,MAAM;GACN,OAAO;GACP,IAAI;GACL,CAAC;GAEL;;;;;;;;;;;;;;;;;;AAmBD,OAAM,IACJ,sBAAA,mBAAmB,WAAA,GAAA,sBAAA,WACT,QAAQ,cAAc,EAChC,SAAU,KAAqB,KAAe,MAA8B;EAC1E,MAAM,EAAE,MAAM,aAAa,IAAI;AAC/B,UAAM,mBAAmB;EACzB,MAAM,aAAa,KAAK,aAAa;AAErC,MAAI,CAAC,gBAAA,gBAAgB,iBAAiB,IAAI,OAAO,kBAAkB,KAAK,CACtE,QAAO,KAAK,gBAAA,WAAW,cAAc,gBAAA,UAAU,kBAAkB,CAAC;AAGpE,MAAI,OAAO,eAAe,eAAe,OAAO,SAAS,YAAY,eAAe,MAAM;AACxF,WAAM,iCAAiC;AACvC,QAAK,aACH,MACA,UACA,eAAe,qBAAqB,KAAK,MAAqB;AAC5D,QAAI,KAAK;AACP,YAAO,MACL;MAAE;MAAM;MAAK,EACb,oEACD;AACD,YAAO,KACL,gBAAA,WAAW,QAAQ,gBAAA,YAAY,cAAc,gBAAA,UAAU,sBAAsB,CAC9E;;IAIH,MAAM,QAAQ,OAAA,GAAA,gBAAA,aAAkB,MAAM,SAAA,GAAA,kBAAA,kBADkB,MAAM,MAAM,UAAU,EAAE,CAAC,EACf,SAAS;AAC3E,YAAM,mBAAmB;AACzB,QAAI,CAAC,MACH,QAAO,KAAK,gBAAA,WAAW,iBAAiB,CAAC;AAG3C,QAAI,OAAO,gBAAA,YAAY,QAAQ;AAC/B,QAAI,IAAI,gBAAA,QAAQ,eAAe,qBAAqB;IAEpD,MAAM,UAAU,gBAAA,UAAU,wBAAwB,IAAI,YAAY,KAAK;AACvE,YAAM,kCAAkC,QAAQ;AAEhD,WAAO,KAAK;KACV,IAAI;KACJ;KACD,CAAC;KAEL;SACI;AACL,WAAM,eAAe,KAAK;AAC1B,OACE,gBAAA,gBAAgB,iBAAiB,UAAU,QAAQ,QAAQ,wBAAwB,KACnF,OACA;AACA,YAAM,4BAA4B;AAElC,WAAO,KAAK,gBAAA,WAAW,QAAQ,gBAAA,YAAY,aAAa,gBAAA,UAAU,eAAe,CAAC;;AAGpF,QAAK,SAAS,MAAM,UAAU,eAAgB,KAAK,MAAqB;AACtE,QAAI,KAAK;AACP,SAAI,IAAI,UAAU,gBAAA,YAAY,eAAe,IAAI,SAAS,gBAAA,YAAY,gBAAgB;AACpF,cAAM,gCAAgC;AAItC,aAAO,KACL,gBAAA,WAAW,QAAQ,IAAI,QAAQ,IAAI,QAAQ,IAAI,gBAAA,WAAW,YAAY,IAAI,QAAQ,CACnF;;AAEH,YAAO,KAAK,IAAI;;IAGlB,MAAM,QACJ,QAAQ,WACJ,OAAA,GAAA,gBAAA,aAAkB,MAAM,QAAQ,MAAoB,SAAS,GAC7D,KAAA;AACN,QAAI,MACF,SAAM,yBAAyB,gBAAA,YAAY,KAAK,OAAiB,EAAE,CAAC;AAEtE,QAAI,CAAC,MACH,QAAO,KAAK,gBAAA,WAAW,iBAAiB,CAAC;AAG3C,QAAI,cAAc;AAClB,QAAI,OAAO,gBAAA,YAAY,QAAQ;AAC/B,QAAI,IAAI,gBAAA,QAAQ,eAAe,qBAAqB;AACpD,YAAM,iCAAiC;AACvC,WAAO,KAAK;KACV,IAAI,SAAS,IAAI,KAAK,KAAK;KAC3B;KACD,CAAC;KACF;;GAGP;AAED,OAAM,OACJ,sBAAA,mBAAmB,YACnB,SAAU,KAAqB,KAAe,MAA8B;AAC1E,MAAI,OAAO,gBAAA,YAAY,GAAG;AAC1B,OAAK,EACH,IAAI,gBAAA,YAAY,YACjB,CAAC;GAEL"}
1
+ {"version":3,"file":"user.js","names":[],"sources":["../src/user.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport type { Response, Router } from 'express';\n\nimport type { Auth } from '@verdaccio/auth';\nimport { getApiToken } from '@verdaccio/auth';\nimport { createRemoteUser } from '@verdaccio/config';\nimport {\n API_ERROR,\n API_MESSAGE,\n HEADERS,\n HTTP_STATUS,\n authUtils,\n cryptoUtils,\n errorUtils,\n validationUtils,\n} from '@verdaccio/core';\nimport { USER_API_ENDPOINTS, rateLimit } from '@verdaccio/middleware';\nimport type { Config, Logger, RemoteUser } from '@verdaccio/types';\n\nimport type { $NextFunctionVer, $RequestExtend } from '../types/custom';\n\nconst debug = buildDebug('verdaccio:api:user');\n\nexport default function (route: Router, auth: Auth, config: Config, logger: Logger): void {\n route.get(\n USER_API_ENDPOINTS.get_user,\n rateLimit(config?.userRateLimit),\n function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void {\n debug('verifying user');\n\n if (\n !req.remote_user ||\n typeof req.remote_user.name !== 'string' ||\n req.remote_user.name === ''\n ) {\n debug('user not logged in');\n res.status(HTTP_STATUS.OK);\n return next({ ok: false });\n }\n\n const username = req.params.org_couchdb_user.split(':')[1];\n const message = authUtils.getAuthenticatedMessage(req.remote_user.name);\n debug('user authenticated message %o', message);\n res.status(HTTP_STATUS.OK);\n next({\n // 'npm owner' requires user info\n // TODO: we don't have the email\n name: username,\n email: '',\n ok: message,\n });\n }\n );\n\n /**\n * \n * body example\n * req.body = {\n _id: \"org.couchdb.user:jjjj\",\n name: \"jjjj\",\n password: \"jjjj\",\n type: \"user\",\n roles: [],\n date: \"2022-07-08T15:51:04.002Z\",\n }\n * \n * @export\n * @param {Router} route\n * @param {Auth} auth\n * @param {Config} config\n */\n route.put(\n USER_API_ENDPOINTS.add_user,\n rateLimit(config?.userRateLimit),\n function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void {\n const { name, password } = req.body;\n debug('login or adduser');\n const remoteName = req?.remote_user?.name;\n\n if (!validationUtils.validateUserName(req.params.org_couchdb_user, name)) {\n return next(errorUtils.getBadRequest(API_ERROR.USERNAME_MISMATCH));\n }\n\n if (typeof remoteName !== 'undefined' && typeof name === 'string' && remoteName === name) {\n debug('login: no remote user detected');\n auth.authenticate(\n name,\n password,\n async function callbackAuthenticate(err, user): Promise<void> {\n if (err) {\n logger.trace(\n { name, err },\n 'authenticating for user @{username} failed. Error: @{err.message}'\n );\n return next(\n errorUtils.getCode(HTTP_STATUS.UNAUTHORIZED, API_ERROR.BAD_USERNAME_PASSWORD)\n );\n }\n\n const restoredRemoteUser: RemoteUser = createRemoteUser(name, user?.groups || []);\n const token = await getApiToken(auth, config, restoredRemoteUser, password);\n debug('login: new token');\n if (!token) {\n return next(errorUtils.getUnauthorized());\n }\n\n res.status(HTTP_STATUS.CREATED);\n res.set(HEADERS.CACHE_CONTROL, HEADERS.NO_CACHE);\n\n const message = authUtils.getAuthenticatedMessage(req.remote_user.name);\n debug('login: created user message %o', message);\n\n return next({\n ok: message,\n token,\n });\n }\n );\n } else {\n debug('adduser: %o', name);\n if (\n validationUtils.validatePassword(password, config?.server?.passwordValidationRegex) ===\n false\n ) {\n debug('adduser: invalid password');\n\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.PASSWORD_SHORT));\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 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 }\n if (!token) {\n return next(errorUtils.getUnauthorized());\n }\n\n req.remote_user = user;\n res.status(HTTP_STATUS.CREATED);\n res.set(HEADERS.CACHE_CONTROL, HEADERS.NO_CACHE);\n debug('adduser: user has been created');\n return next({\n ok: `user '${req.body.name}' created`,\n token,\n });\n });\n }\n }\n );\n\n route.delete(\n USER_API_ENDPOINTS.user_token,\n function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void {\n res.status(HTTP_STATUS.OK);\n next({\n ok: API_MESSAGE.LOGGED_OUT,\n });\n }\n );\n}\n"],"mappings":"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"}
package/build/user.mjs CHANGED
@@ -59,7 +59,7 @@ function user_default(route, auth, config, logger) {
59
59
  debug("login: new token");
60
60
  if (!token) return next(errorUtils.getUnauthorized());
61
61
  res.status(HTTP_STATUS.CREATED);
62
- res.set(HEADERS.CACHE_CONTROL, "no-cache, no-store");
62
+ res.set(HEADERS.CACHE_CONTROL, HEADERS.NO_CACHE);
63
63
  const message = authUtils.getAuthenticatedMessage(req.remote_user.name);
64
64
  debug("login: created user message %o", message);
65
65
  return next({
@@ -86,7 +86,7 @@ function user_default(route, auth, config, logger) {
86
86
  if (!token) return next(errorUtils.getUnauthorized());
87
87
  req.remote_user = user;
88
88
  res.status(HTTP_STATUS.CREATED);
89
- res.set(HEADERS.CACHE_CONTROL, "no-cache, no-store");
89
+ res.set(HEADERS.CACHE_CONTROL, HEADERS.NO_CACHE);
90
90
  debug("adduser: user has been created");
91
91
  return next({
92
92
  ok: `user '${req.body.name}' created`,
@@ -1 +1 @@
1
- {"version":3,"file":"user.mjs","names":[],"sources":["../src/user.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport type { Response, Router } from 'express';\n\nimport type { Auth } from '@verdaccio/auth';\nimport { getApiToken } from '@verdaccio/auth';\nimport { createRemoteUser } from '@verdaccio/config';\nimport {\n API_ERROR,\n API_MESSAGE,\n HEADERS,\n HTTP_STATUS,\n authUtils,\n cryptoUtils,\n errorUtils,\n validationUtils,\n} from '@verdaccio/core';\nimport { USER_API_ENDPOINTS, rateLimit } from '@verdaccio/middleware';\nimport type { Config, Logger, RemoteUser } from '@verdaccio/types';\n\nimport type { $NextFunctionVer, $RequestExtend } from '../types/custom';\n\nconst debug = buildDebug('verdaccio:api:user');\n\nexport default function (route: Router, auth: Auth, config: Config, logger: Logger): void {\n route.get(\n USER_API_ENDPOINTS.get_user,\n rateLimit(config?.userRateLimit),\n function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void {\n debug('verifying user');\n\n if (\n !req.remote_user ||\n typeof req.remote_user.name !== 'string' ||\n req.remote_user.name === ''\n ) {\n debug('user not logged in');\n res.status(HTTP_STATUS.OK);\n return next({ ok: false });\n }\n\n const username = req.params.org_couchdb_user.split(':')[1];\n const message = authUtils.getAuthenticatedMessage(req.remote_user.name);\n debug('user authenticated message %o', message);\n res.status(HTTP_STATUS.OK);\n next({\n // 'npm owner' requires user info\n // TODO: we don't have the email\n name: username,\n email: '',\n ok: message,\n });\n }\n );\n\n /**\n * \n * body example\n * req.body = {\n _id: \"org.couchdb.user:jjjj\",\n name: \"jjjj\",\n password: \"jjjj\",\n type: \"user\",\n roles: [],\n date: \"2022-07-08T15:51:04.002Z\",\n }\n * \n * @export\n * @param {Router} route\n * @param {Auth} auth\n * @param {Config} config\n */\n route.put(\n USER_API_ENDPOINTS.add_user,\n rateLimit(config?.userRateLimit),\n function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void {\n const { name, password } = req.body;\n debug('login or adduser');\n const remoteName = req?.remote_user?.name;\n\n if (!validationUtils.validateUserName(req.params.org_couchdb_user, name)) {\n return next(errorUtils.getBadRequest(API_ERROR.USERNAME_MISMATCH));\n }\n\n if (typeof remoteName !== 'undefined' && typeof name === 'string' && remoteName === name) {\n debug('login: no remote user detected');\n auth.authenticate(\n name,\n password,\n async function callbackAuthenticate(err, user): Promise<void> {\n if (err) {\n logger.trace(\n { name, err },\n 'authenticating for user @{username} failed. Error: @{err.message}'\n );\n return next(\n errorUtils.getCode(HTTP_STATUS.UNAUTHORIZED, API_ERROR.BAD_USERNAME_PASSWORD)\n );\n }\n\n const restoredRemoteUser: RemoteUser = createRemoteUser(name, user?.groups || []);\n const token = await getApiToken(auth, config, restoredRemoteUser, password);\n debug('login: new token');\n if (!token) {\n return next(errorUtils.getUnauthorized());\n }\n\n res.status(HTTP_STATUS.CREATED);\n res.set(HEADERS.CACHE_CONTROL, 'no-cache, no-store');\n\n const message = authUtils.getAuthenticatedMessage(req.remote_user.name);\n debug('login: created user message %o', message);\n\n return next({\n ok: message,\n token,\n });\n }\n );\n } else {\n debug('adduser: %o', name);\n if (\n validationUtils.validatePassword(password, config?.server?.passwordValidationRegex) ===\n false\n ) {\n debug('adduser: invalid password');\n\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.PASSWORD_SHORT));\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 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 }\n if (!token) {\n return next(errorUtils.getUnauthorized());\n }\n\n req.remote_user = user;\n res.status(HTTP_STATUS.CREATED);\n res.set(HEADERS.CACHE_CONTROL, 'no-cache, no-store');\n debug('adduser: user has been created');\n return next({\n ok: `user '${req.body.name}' created`,\n token,\n });\n });\n }\n }\n );\n\n route.delete(\n USER_API_ENDPOINTS.user_token,\n function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void {\n res.status(HTTP_STATUS.OK);\n next({\n ok: API_MESSAGE.LOGGED_OUT,\n });\n }\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"user.mjs","names":[],"sources":["../src/user.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport type { Response, Router } from 'express';\n\nimport type { Auth } from '@verdaccio/auth';\nimport { getApiToken } from '@verdaccio/auth';\nimport { createRemoteUser } from '@verdaccio/config';\nimport {\n API_ERROR,\n API_MESSAGE,\n HEADERS,\n HTTP_STATUS,\n authUtils,\n cryptoUtils,\n errorUtils,\n validationUtils,\n} from '@verdaccio/core';\nimport { USER_API_ENDPOINTS, rateLimit } from '@verdaccio/middleware';\nimport type { Config, Logger, RemoteUser } from '@verdaccio/types';\n\nimport type { $NextFunctionVer, $RequestExtend } from '../types/custom';\n\nconst debug = buildDebug('verdaccio:api:user');\n\nexport default function (route: Router, auth: Auth, config: Config, logger: Logger): void {\n route.get(\n USER_API_ENDPOINTS.get_user,\n rateLimit(config?.userRateLimit),\n function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void {\n debug('verifying user');\n\n if (\n !req.remote_user ||\n typeof req.remote_user.name !== 'string' ||\n req.remote_user.name === ''\n ) {\n debug('user not logged in');\n res.status(HTTP_STATUS.OK);\n return next({ ok: false });\n }\n\n const username = req.params.org_couchdb_user.split(':')[1];\n const message = authUtils.getAuthenticatedMessage(req.remote_user.name);\n debug('user authenticated message %o', message);\n res.status(HTTP_STATUS.OK);\n next({\n // 'npm owner' requires user info\n // TODO: we don't have the email\n name: username,\n email: '',\n ok: message,\n });\n }\n );\n\n /**\n * \n * body example\n * req.body = {\n _id: \"org.couchdb.user:jjjj\",\n name: \"jjjj\",\n password: \"jjjj\",\n type: \"user\",\n roles: [],\n date: \"2022-07-08T15:51:04.002Z\",\n }\n * \n * @export\n * @param {Router} route\n * @param {Auth} auth\n * @param {Config} config\n */\n route.put(\n USER_API_ENDPOINTS.add_user,\n rateLimit(config?.userRateLimit),\n function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void {\n const { name, password } = req.body;\n debug('login or adduser');\n const remoteName = req?.remote_user?.name;\n\n if (!validationUtils.validateUserName(req.params.org_couchdb_user, name)) {\n return next(errorUtils.getBadRequest(API_ERROR.USERNAME_MISMATCH));\n }\n\n if (typeof remoteName !== 'undefined' && typeof name === 'string' && remoteName === name) {\n debug('login: no remote user detected');\n auth.authenticate(\n name,\n password,\n async function callbackAuthenticate(err, user): Promise<void> {\n if (err) {\n logger.trace(\n { name, err },\n 'authenticating for user @{username} failed. Error: @{err.message}'\n );\n return next(\n errorUtils.getCode(HTTP_STATUS.UNAUTHORIZED, API_ERROR.BAD_USERNAME_PASSWORD)\n );\n }\n\n const restoredRemoteUser: RemoteUser = createRemoteUser(name, user?.groups || []);\n const token = await getApiToken(auth, config, restoredRemoteUser, password);\n debug('login: new token');\n if (!token) {\n return next(errorUtils.getUnauthorized());\n }\n\n res.status(HTTP_STATUS.CREATED);\n res.set(HEADERS.CACHE_CONTROL, HEADERS.NO_CACHE);\n\n const message = authUtils.getAuthenticatedMessage(req.remote_user.name);\n debug('login: created user message %o', message);\n\n return next({\n ok: message,\n token,\n });\n }\n );\n } else {\n debug('adduser: %o', name);\n if (\n validationUtils.validatePassword(password, config?.server?.passwordValidationRegex) ===\n false\n ) {\n debug('adduser: invalid password');\n\n return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.PASSWORD_SHORT));\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 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 }\n if (!token) {\n return next(errorUtils.getUnauthorized());\n }\n\n req.remote_user = user;\n res.status(HTTP_STATUS.CREATED);\n res.set(HEADERS.CACHE_CONTROL, HEADERS.NO_CACHE);\n debug('adduser: user has been created');\n return next({\n ok: `user '${req.body.name}' created`,\n token,\n });\n });\n }\n }\n );\n\n route.delete(\n USER_API_ENDPOINTS.user_token,\n function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void {\n res.status(HTTP_STATUS.OK);\n next({\n ok: API_MESSAGE.LOGGED_OUT,\n });\n }\n );\n}\n"],"mappings":"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"}
package/build/v1/login.js CHANGED
@@ -103,7 +103,7 @@ function login_default(route, auth, storage, config, logger) {
103
103
  });
104
104
  const message = _verdaccio_core.authUtils.getAuthenticatedMessage(remoteUser.name ?? "");
105
105
  res.status(_verdaccio_core.HTTP_STATUS.CREATED);
106
- res.set(_verdaccio_core.HEADERS.CACHE_CONTROL, "no-cache, no-store");
106
+ res.set(_verdaccio_core.HEADERS.CACHE_CONTROL, _verdaccio_core.HEADERS.NO_CACHE);
107
107
  res.json({
108
108
  ok: message,
109
109
  token
@@ -1 +1 @@
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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"}
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, HEADERS.NO_CACHE);\n res.json({ ok: message, token });\n }\n );\n }\n );\n}\n"],"mappings":"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"}
@@ -101,7 +101,7 @@ function login_default(route, auth, storage, config, logger) {
101
101
  });
102
102
  const message = authUtils.getAuthenticatedMessage(remoteUser.name ?? "");
103
103
  res.status(HTTP_STATUS.CREATED);
104
- res.set(HEADERS.CACHE_CONTROL, "no-cache, no-store");
104
+ res.set(HEADERS.CACHE_CONTROL, HEADERS.NO_CACHE);
105
105
  res.json({
106
106
  ok: message,
107
107
  token
@@ -1 +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
+ {"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, HEADERS.NO_CACHE);\n res.json({ ok: message, token });\n }\n );\n }\n );\n}\n"],"mappings":"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"}
package/build/v1/token.js CHANGED
@@ -63,7 +63,7 @@ function token_default(route, auth, storage, config, logger) {
63
63
  key,
64
64
  name
65
65
  }, "token @{key} was created for user @{name}");
66
- res.set(_verdaccio_core.HEADERS.CACHE_CONTROL, "no-cache, no-store");
66
+ res.set(_verdaccio_core.HEADERS.CACHE_CONTROL, _verdaccio_core.HEADERS.NO_CACHE);
67
67
  return next(normalizeToken({
68
68
  token,
69
69
  user: name,
@@ -1 +1 @@
1
- {"version":3,"file":"token.js","names":[],"sources":["../../src/v1/token.ts"],"sourcesContent":["import type { Response, Router } from 'express';\nimport _ from 'lodash';\n\nimport type { Auth } from '@verdaccio/auth';\nimport { getApiToken } from '@verdaccio/auth';\nimport { HEADERS, HTTP_STATUS, SUPPORT_ERRORS, cryptoUtils, errorUtils } from '@verdaccio/core';\nimport { TOKEN_API_ENDPOINTS, rateLimit } from '@verdaccio/middleware';\nimport type { Storage } from '@verdaccio/store';\nimport type { Config, Logger, RemoteUser, Token } from '@verdaccio/types';\n\nimport type { $NextFunctionVer, $RequestExtend } from '../../types/custom';\n\nexport type NormalizeToken = Token & {\n cidr_whitelist: string[];\n created: string;\n};\n\n// npm expects \"cidr_whitelist\" for token list\nfunction normalizeToken(token: Token): NormalizeToken {\n return {\n ...token,\n cidr_whitelist: token.cidr || [],\n created: new Date(token.created).toISOString(),\n };\n}\n\n// https://github.com/npm/npm-profile/blob/latest/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.get(\n TOKEN_API_ENDPOINTS.get_tokens,\n rateLimit(config?.userRateLimit),\n async function (req: $RequestExtend, res: Response, next: $NextFunctionVer) {\n const { name } = req.remote_user;\n\n if (_.isNil(name) === false) {\n try {\n const tokens = await storage.readTokens({ user: name });\n const totalTokens = tokens.length;\n logger.debug({ totalTokens }, 'token list retrieved: @{totalTokens}');\n\n res.status(HTTP_STATUS.OK);\n return next({\n objects: tokens.map(normalizeToken),\n urls: {\n next: '', // TODO: pagination?\n },\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 return next(errorUtils.getUnauthorized());\n }\n );\n\n route.post(\n TOKEN_API_ENDPOINTS.get_tokens,\n rateLimit(config?.userRateLimit),\n function (req: $RequestExtend, res: Response, next: $NextFunctionVer) {\n const { password, readonly, cidr_whitelist } = req.body;\n const { name } = req.remote_user;\n\n if (!_.isBoolean(readonly) || !_.isArray(cidr_whitelist)) {\n return next(errorUtils.getCode(HTTP_STATUS.BAD_DATA, SUPPORT_ERRORS.PARAMETERS_NOT_VALID));\n }\n\n auth.authenticate(name, password, async (err, user?: RemoteUser) => {\n if (err) {\n const errorCode = err.message ? HTTP_STATUS.UNAUTHORIZED : HTTP_STATUS.INTERNAL_ERROR;\n return next(errorUtils.getCode(errorCode, err.message));\n }\n\n req.remote_user = user;\n\n if (!_.isFunction(storage.saveToken)) {\n return next(\n errorUtils.getCode(HTTP_STATUS.NOT_IMPLEMENTED, SUPPORT_ERRORS.STORAGE_NOT_IMPLEMENT)\n );\n }\n\n try {\n const token = await getApiToken(auth, config, user as RemoteUser, password);\n if (!token) {\n throw errorUtils.getInternalError();\n }\n\n const key = cryptoUtils.stringToMD5(token);\n // TODO: use a utility here\n const maskedToken = cryptoUtils.mask(token, 5);\n const created = new Date().getTime();\n\n /**\n * cidr_whitelist: is not being used, we pass it through\n * token: we do not store the real token (it is generated once and retrieved\n * to the user), just a mask of it.\n */\n const saveToken: Token = {\n user: name,\n token: maskedToken,\n key,\n cidr: cidr_whitelist,\n readonly,\n created,\n };\n\n await storage.saveToken(saveToken);\n logger.debug({ key, name }, 'token @{key} was created for user @{name}');\n res.set(HEADERS.CACHE_CONTROL, 'no-cache, no-store');\n return next(\n normalizeToken({\n token,\n user: name,\n key: saveToken.key,\n cidr: cidr_whitelist,\n readonly,\n created: saveToken.created,\n })\n );\n } catch (error: any) {\n logger.error({ error: error.msg }, 'token creation has failed: @{error}');\n return next(errorUtils.getInternalError(error.message));\n }\n });\n }\n );\n\n route.delete(\n TOKEN_API_ENDPOINTS.delete_token,\n rateLimit(config?.userRateLimit),\n async (req: $RequestExtend, res: Response, next: $NextFunctionVer) => {\n const {\n params: { tokenKey },\n } = req;\n const { name } = req.remote_user;\n\n if (_.isNil(name) === false) {\n logger.debug({ name }, '@{name} has requested remove a token');\n try {\n await storage.deleteToken(name, tokenKey);\n logger.info({ tokenKey, name }, 'token id @{tokenKey} was revoked for user @{name}');\n return next({});\n } catch (error: any) {\n logger.error({ error: error.msg }, 'token creation has failed: @{error}');\n return next(errorUtils.getCode(HTTP_STATUS.INTERNAL_ERROR, error.message));\n }\n }\n return next(errorUtils.getUnauthorized());\n }\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"token.js","names":[],"sources":["../../src/v1/token.ts"],"sourcesContent":["import type { Response, Router } from 'express';\nimport _ from 'lodash';\n\nimport type { Auth } from '@verdaccio/auth';\nimport { getApiToken } from '@verdaccio/auth';\nimport { HEADERS, HTTP_STATUS, SUPPORT_ERRORS, cryptoUtils, errorUtils } from '@verdaccio/core';\nimport { TOKEN_API_ENDPOINTS, rateLimit } from '@verdaccio/middleware';\nimport type { Storage } from '@verdaccio/store';\nimport type { Config, Logger, RemoteUser, Token } from '@verdaccio/types';\n\nimport type { $NextFunctionVer, $RequestExtend } from '../../types/custom';\n\nexport type NormalizeToken = Token & {\n cidr_whitelist: string[];\n created: string;\n};\n\n// npm expects \"cidr_whitelist\" for token list\nfunction normalizeToken(token: Token): NormalizeToken {\n return {\n ...token,\n cidr_whitelist: token.cidr || [],\n created: new Date(token.created).toISOString(),\n };\n}\n\n// https://github.com/npm/npm-profile/blob/latest/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.get(\n TOKEN_API_ENDPOINTS.get_tokens,\n rateLimit(config?.userRateLimit),\n async function (req: $RequestExtend, res: Response, next: $NextFunctionVer) {\n const { name } = req.remote_user;\n\n if (_.isNil(name) === false) {\n try {\n const tokens = await storage.readTokens({ user: name });\n const totalTokens = tokens.length;\n logger.debug({ totalTokens }, 'token list retrieved: @{totalTokens}');\n\n res.status(HTTP_STATUS.OK);\n return next({\n objects: tokens.map(normalizeToken),\n urls: {\n next: '', // TODO: pagination?\n },\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 return next(errorUtils.getUnauthorized());\n }\n );\n\n route.post(\n TOKEN_API_ENDPOINTS.get_tokens,\n rateLimit(config?.userRateLimit),\n function (req: $RequestExtend, res: Response, next: $NextFunctionVer) {\n const { password, readonly, cidr_whitelist } = req.body;\n const { name } = req.remote_user;\n\n if (!_.isBoolean(readonly) || !_.isArray(cidr_whitelist)) {\n return next(errorUtils.getCode(HTTP_STATUS.BAD_DATA, SUPPORT_ERRORS.PARAMETERS_NOT_VALID));\n }\n\n auth.authenticate(name, password, async (err, user?: RemoteUser) => {\n if (err) {\n const errorCode = err.message ? HTTP_STATUS.UNAUTHORIZED : HTTP_STATUS.INTERNAL_ERROR;\n return next(errorUtils.getCode(errorCode, err.message));\n }\n\n req.remote_user = user;\n\n if (!_.isFunction(storage.saveToken)) {\n return next(\n errorUtils.getCode(HTTP_STATUS.NOT_IMPLEMENTED, SUPPORT_ERRORS.STORAGE_NOT_IMPLEMENT)\n );\n }\n\n try {\n const token = await getApiToken(auth, config, user as RemoteUser, password);\n if (!token) {\n throw errorUtils.getInternalError();\n }\n\n const key = cryptoUtils.stringToMD5(token);\n // TODO: use a utility here\n const maskedToken = cryptoUtils.mask(token, 5);\n const created = new Date().getTime();\n\n /**\n * cidr_whitelist: is not being used, we pass it through\n * token: we do not store the real token (it is generated once and retrieved\n * to the user), just a mask of it.\n */\n const saveToken: Token = {\n user: name,\n token: maskedToken,\n key,\n cidr: cidr_whitelist,\n readonly,\n created,\n };\n\n await storage.saveToken(saveToken);\n logger.debug({ key, name }, 'token @{key} was created for user @{name}');\n res.set(HEADERS.CACHE_CONTROL, HEADERS.NO_CACHE);\n return next(\n normalizeToken({\n token,\n user: name,\n key: saveToken.key,\n cidr: cidr_whitelist,\n readonly,\n created: saveToken.created,\n })\n );\n } catch (error: any) {\n logger.error({ error: error.msg }, 'token creation has failed: @{error}');\n return next(errorUtils.getInternalError(error.message));\n }\n });\n }\n );\n\n route.delete(\n TOKEN_API_ENDPOINTS.delete_token,\n rateLimit(config?.userRateLimit),\n async (req: $RequestExtend, res: Response, next: $NextFunctionVer) => {\n const {\n params: { tokenKey },\n } = req;\n const { name } = req.remote_user;\n\n if (_.isNil(name) === false) {\n logger.debug({ name }, '@{name} has requested remove a token');\n try {\n await storage.deleteToken(name, tokenKey);\n logger.info({ tokenKey, name }, 'token id @{tokenKey} was revoked for user @{name}');\n return next({});\n } catch (error: any) {\n logger.error({ error: error.msg }, 'token creation has failed: @{error}');\n return next(errorUtils.getCode(HTTP_STATUS.INTERNAL_ERROR, error.message));\n }\n }\n return next(errorUtils.getUnauthorized());\n }\n );\n}\n"],"mappings":"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"}
@@ -61,7 +61,7 @@ function token_default(route, auth, storage, config, logger) {
61
61
  key,
62
62
  name
63
63
  }, "token @{key} was created for user @{name}");
64
- res.set(HEADERS.CACHE_CONTROL, "no-cache, no-store");
64
+ res.set(HEADERS.CACHE_CONTROL, HEADERS.NO_CACHE);
65
65
  return next(normalizeToken({
66
66
  token,
67
67
  user: name,
@@ -1 +1 @@
1
- {"version":3,"file":"token.mjs","names":[],"sources":["../../src/v1/token.ts"],"sourcesContent":["import type { Response, Router } from 'express';\nimport _ from 'lodash';\n\nimport type { Auth } from '@verdaccio/auth';\nimport { getApiToken } from '@verdaccio/auth';\nimport { HEADERS, HTTP_STATUS, SUPPORT_ERRORS, cryptoUtils, errorUtils } from '@verdaccio/core';\nimport { TOKEN_API_ENDPOINTS, rateLimit } from '@verdaccio/middleware';\nimport type { Storage } from '@verdaccio/store';\nimport type { Config, Logger, RemoteUser, Token } from '@verdaccio/types';\n\nimport type { $NextFunctionVer, $RequestExtend } from '../../types/custom';\n\nexport type NormalizeToken = Token & {\n cidr_whitelist: string[];\n created: string;\n};\n\n// npm expects \"cidr_whitelist\" for token list\nfunction normalizeToken(token: Token): NormalizeToken {\n return {\n ...token,\n cidr_whitelist: token.cidr || [],\n created: new Date(token.created).toISOString(),\n };\n}\n\n// https://github.com/npm/npm-profile/blob/latest/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.get(\n TOKEN_API_ENDPOINTS.get_tokens,\n rateLimit(config?.userRateLimit),\n async function (req: $RequestExtend, res: Response, next: $NextFunctionVer) {\n const { name } = req.remote_user;\n\n if (_.isNil(name) === false) {\n try {\n const tokens = await storage.readTokens({ user: name });\n const totalTokens = tokens.length;\n logger.debug({ totalTokens }, 'token list retrieved: @{totalTokens}');\n\n res.status(HTTP_STATUS.OK);\n return next({\n objects: tokens.map(normalizeToken),\n urls: {\n next: '', // TODO: pagination?\n },\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 return next(errorUtils.getUnauthorized());\n }\n );\n\n route.post(\n TOKEN_API_ENDPOINTS.get_tokens,\n rateLimit(config?.userRateLimit),\n function (req: $RequestExtend, res: Response, next: $NextFunctionVer) {\n const { password, readonly, cidr_whitelist } = req.body;\n const { name } = req.remote_user;\n\n if (!_.isBoolean(readonly) || !_.isArray(cidr_whitelist)) {\n return next(errorUtils.getCode(HTTP_STATUS.BAD_DATA, SUPPORT_ERRORS.PARAMETERS_NOT_VALID));\n }\n\n auth.authenticate(name, password, async (err, user?: RemoteUser) => {\n if (err) {\n const errorCode = err.message ? HTTP_STATUS.UNAUTHORIZED : HTTP_STATUS.INTERNAL_ERROR;\n return next(errorUtils.getCode(errorCode, err.message));\n }\n\n req.remote_user = user;\n\n if (!_.isFunction(storage.saveToken)) {\n return next(\n errorUtils.getCode(HTTP_STATUS.NOT_IMPLEMENTED, SUPPORT_ERRORS.STORAGE_NOT_IMPLEMENT)\n );\n }\n\n try {\n const token = await getApiToken(auth, config, user as RemoteUser, password);\n if (!token) {\n throw errorUtils.getInternalError();\n }\n\n const key = cryptoUtils.stringToMD5(token);\n // TODO: use a utility here\n const maskedToken = cryptoUtils.mask(token, 5);\n const created = new Date().getTime();\n\n /**\n * cidr_whitelist: is not being used, we pass it through\n * token: we do not store the real token (it is generated once and retrieved\n * to the user), just a mask of it.\n */\n const saveToken: Token = {\n user: name,\n token: maskedToken,\n key,\n cidr: cidr_whitelist,\n readonly,\n created,\n };\n\n await storage.saveToken(saveToken);\n logger.debug({ key, name }, 'token @{key} was created for user @{name}');\n res.set(HEADERS.CACHE_CONTROL, 'no-cache, no-store');\n return next(\n normalizeToken({\n token,\n user: name,\n key: saveToken.key,\n cidr: cidr_whitelist,\n readonly,\n created: saveToken.created,\n })\n );\n } catch (error: any) {\n logger.error({ error: error.msg }, 'token creation has failed: @{error}');\n return next(errorUtils.getInternalError(error.message));\n }\n });\n }\n );\n\n route.delete(\n TOKEN_API_ENDPOINTS.delete_token,\n rateLimit(config?.userRateLimit),\n async (req: $RequestExtend, res: Response, next: $NextFunctionVer) => {\n const {\n params: { tokenKey },\n } = req;\n const { name } = req.remote_user;\n\n if (_.isNil(name) === false) {\n logger.debug({ name }, '@{name} has requested remove a token');\n try {\n await storage.deleteToken(name, tokenKey);\n logger.info({ tokenKey, name }, 'token id @{tokenKey} was revoked for user @{name}');\n return next({});\n } catch (error: any) {\n logger.error({ error: error.msg }, 'token creation has failed: @{error}');\n return next(errorUtils.getCode(HTTP_STATUS.INTERNAL_ERROR, error.message));\n }\n }\n return next(errorUtils.getUnauthorized());\n }\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"token.mjs","names":[],"sources":["../../src/v1/token.ts"],"sourcesContent":["import type { Response, Router } from 'express';\nimport _ from 'lodash';\n\nimport type { Auth } from '@verdaccio/auth';\nimport { getApiToken } from '@verdaccio/auth';\nimport { HEADERS, HTTP_STATUS, SUPPORT_ERRORS, cryptoUtils, errorUtils } from '@verdaccio/core';\nimport { TOKEN_API_ENDPOINTS, rateLimit } from '@verdaccio/middleware';\nimport type { Storage } from '@verdaccio/store';\nimport type { Config, Logger, RemoteUser, Token } from '@verdaccio/types';\n\nimport type { $NextFunctionVer, $RequestExtend } from '../../types/custom';\n\nexport type NormalizeToken = Token & {\n cidr_whitelist: string[];\n created: string;\n};\n\n// npm expects \"cidr_whitelist\" for token list\nfunction normalizeToken(token: Token): NormalizeToken {\n return {\n ...token,\n cidr_whitelist: token.cidr || [],\n created: new Date(token.created).toISOString(),\n };\n}\n\n// https://github.com/npm/npm-profile/blob/latest/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.get(\n TOKEN_API_ENDPOINTS.get_tokens,\n rateLimit(config?.userRateLimit),\n async function (req: $RequestExtend, res: Response, next: $NextFunctionVer) {\n const { name } = req.remote_user;\n\n if (_.isNil(name) === false) {\n try {\n const tokens = await storage.readTokens({ user: name });\n const totalTokens = tokens.length;\n logger.debug({ totalTokens }, 'token list retrieved: @{totalTokens}');\n\n res.status(HTTP_STATUS.OK);\n return next({\n objects: tokens.map(normalizeToken),\n urls: {\n next: '', // TODO: pagination?\n },\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 return next(errorUtils.getUnauthorized());\n }\n );\n\n route.post(\n TOKEN_API_ENDPOINTS.get_tokens,\n rateLimit(config?.userRateLimit),\n function (req: $RequestExtend, res: Response, next: $NextFunctionVer) {\n const { password, readonly, cidr_whitelist } = req.body;\n const { name } = req.remote_user;\n\n if (!_.isBoolean(readonly) || !_.isArray(cidr_whitelist)) {\n return next(errorUtils.getCode(HTTP_STATUS.BAD_DATA, SUPPORT_ERRORS.PARAMETERS_NOT_VALID));\n }\n\n auth.authenticate(name, password, async (err, user?: RemoteUser) => {\n if (err) {\n const errorCode = err.message ? HTTP_STATUS.UNAUTHORIZED : HTTP_STATUS.INTERNAL_ERROR;\n return next(errorUtils.getCode(errorCode, err.message));\n }\n\n req.remote_user = user;\n\n if (!_.isFunction(storage.saveToken)) {\n return next(\n errorUtils.getCode(HTTP_STATUS.NOT_IMPLEMENTED, SUPPORT_ERRORS.STORAGE_NOT_IMPLEMENT)\n );\n }\n\n try {\n const token = await getApiToken(auth, config, user as RemoteUser, password);\n if (!token) {\n throw errorUtils.getInternalError();\n }\n\n const key = cryptoUtils.stringToMD5(token);\n // TODO: use a utility here\n const maskedToken = cryptoUtils.mask(token, 5);\n const created = new Date().getTime();\n\n /**\n * cidr_whitelist: is not being used, we pass it through\n * token: we do not store the real token (it is generated once and retrieved\n * to the user), just a mask of it.\n */\n const saveToken: Token = {\n user: name,\n token: maskedToken,\n key,\n cidr: cidr_whitelist,\n readonly,\n created,\n };\n\n await storage.saveToken(saveToken);\n logger.debug({ key, name }, 'token @{key} was created for user @{name}');\n res.set(HEADERS.CACHE_CONTROL, HEADERS.NO_CACHE);\n return next(\n normalizeToken({\n token,\n user: name,\n key: saveToken.key,\n cidr: cidr_whitelist,\n readonly,\n created: saveToken.created,\n })\n );\n } catch (error: any) {\n logger.error({ error: error.msg }, 'token creation has failed: @{error}');\n return next(errorUtils.getInternalError(error.message));\n }\n });\n }\n );\n\n route.delete(\n TOKEN_API_ENDPOINTS.delete_token,\n rateLimit(config?.userRateLimit),\n async (req: $RequestExtend, res: Response, next: $NextFunctionVer) => {\n const {\n params: { tokenKey },\n } = req;\n const { name } = req.remote_user;\n\n if (_.isNil(name) === false) {\n logger.debug({ name }, '@{name} has requested remove a token');\n try {\n await storage.deleteToken(name, tokenKey);\n logger.info({ tokenKey, name }, 'token id @{tokenKey} was revoked for user @{name}');\n return next({});\n } catch (error: any) {\n logger.error({ error: error.msg }, 'token creation has failed: @{error}');\n return next(errorUtils.getCode(HTTP_STATUS.INTERNAL_ERROR, error.message));\n }\n }\n return next(errorUtils.getUnauthorized());\n }\n );\n}\n"],"mappings":";;;;;AAkBA,SAAS,eAAe,OAA8B;AACpD,QAAO;EACL,GAAG;EACH,gBAAgB,MAAM,QAAQ,EAAE;EAChC,SAAS,IAAI,KAAK,MAAM,QAAQ,CAAC,aAAa;EAC/C;;AAIH,SAAA,cACE,OACA,MACA,SACA,QACA,QACM;AACN,OAAM,IACJ,oBAAoB,YACpB,UAAU,QAAQ,cAAc,EAChC,eAAgB,KAAqB,KAAe,MAAwB;EAC1E,MAAM,EAAE,SAAS,IAAI;AAErB,MAAI,EAAE,MAAM,KAAK,KAAK,MACpB,KAAI;GACF,MAAM,SAAS,MAAM,QAAQ,WAAW,EAAE,MAAM,MAAM,CAAC;GACvD,MAAM,cAAc,OAAO;AAC3B,UAAO,MAAM,EAAE,aAAa,EAAE,uCAAuC;AAErE,OAAI,OAAO,YAAY,GAAG;AAC1B,UAAO,KAAK;IACV,SAAS,OAAO,IAAI,eAAe;IACnC,MAAM,EACJ,MAAM,IACP;IACF,CAAC;WACK,OAAY;AACnB,UAAO,MAAM,EAAE,OAAO,MAAM,KAAK,EAAE,kCAAkC;AACrE,UAAO,KAAK,WAAW,QAAQ,YAAY,gBAAgB,MAAM,QAAQ,CAAC;;AAG9E,SAAO,KAAK,WAAW,iBAAiB,CAAC;GAE5C;AAED,OAAM,KACJ,oBAAoB,YACpB,UAAU,QAAQ,cAAc,EAChC,SAAU,KAAqB,KAAe,MAAwB;EACpE,MAAM,EAAE,UAAU,UAAU,mBAAmB,IAAI;EACnD,MAAM,EAAE,SAAS,IAAI;AAErB,MAAI,CAAC,EAAE,UAAU,SAAS,IAAI,CAAC,EAAE,QAAQ,eAAe,CACtD,QAAO,KAAK,WAAW,QAAQ,YAAY,UAAU,eAAe,qBAAqB,CAAC;AAG5F,OAAK,aAAa,MAAM,UAAU,OAAO,KAAK,SAAsB;AAClE,OAAI,KAAK;IACP,MAAM,YAAY,IAAI,UAAU,YAAY,eAAe,YAAY;AACvE,WAAO,KAAK,WAAW,QAAQ,WAAW,IAAI,QAAQ,CAAC;;AAGzD,OAAI,cAAc;AAElB,OAAI,CAAC,EAAE,WAAW,QAAQ,UAAU,CAClC,QAAO,KACL,WAAW,QAAQ,YAAY,iBAAiB,eAAe,sBAAsB,CACtF;AAGH,OAAI;IACF,MAAM,QAAQ,MAAM,YAAY,MAAM,QAAQ,MAAoB,SAAS;AAC3E,QAAI,CAAC,MACH,OAAM,WAAW,kBAAkB;IAGrC,MAAM,MAAM,YAAY,YAAY,MAAM;;;;;;IAU1C,MAAM,YAAmB;KACvB,MAAM;KACN,OAVkB,YAAY,KAAK,OAAO,EAAE;KAW5C;KACA,MAAM;KACN;KACA,0BAbc,IAAI,MAAM,EAAC,SAAS;KAcnC;AAED,UAAM,QAAQ,UAAU,UAAU;AAClC,WAAO,MAAM;KAAE;KAAK;KAAM,EAAE,4CAA4C;AACxE,QAAI,IAAI,QAAQ,eAAe,QAAQ,SAAS;AAChD,WAAO,KACL,eAAe;KACb;KACA,MAAM;KACN,KAAK,UAAU;KACf,MAAM;KACN;KACA,SAAS,UAAU;KACpB,CAAC,CACH;YACM,OAAY;AACnB,WAAO,MAAM,EAAE,OAAO,MAAM,KAAK,EAAE,sCAAsC;AACzE,WAAO,KAAK,WAAW,iBAAiB,MAAM,QAAQ,CAAC;;IAEzD;GAEL;AAED,OAAM,OACJ,oBAAoB,cACpB,UAAU,QAAQ,cAAc,EAChC,OAAO,KAAqB,KAAe,SAA2B;EACpE,MAAM,EACJ,QAAQ,EAAE,eACR;EACJ,MAAM,EAAE,SAAS,IAAI;AAErB,MAAI,EAAE,MAAM,KAAK,KAAK,OAAO;AAC3B,UAAO,MAAM,EAAE,MAAM,EAAE,uCAAuC;AAC9D,OAAI;AACF,UAAM,QAAQ,YAAY,MAAM,SAAS;AACzC,WAAO,KAAK;KAAE;KAAU;KAAM,EAAE,oDAAoD;AACpF,WAAO,KAAK,EAAE,CAAC;YACR,OAAY;AACnB,WAAO,MAAM,EAAE,OAAO,MAAM,KAAK,EAAE,sCAAsC;AACzE,WAAO,KAAK,WAAW,QAAQ,YAAY,gBAAgB,MAAM,QAAQ,CAAC;;;AAG9E,SAAO,KAAK,WAAW,iBAAiB,CAAC;GAE5C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@verdaccio/api",
3
- "version": "9.0.0-next-9.5",
3
+ "version": "9.0.0-next-9.7",
4
4
  "description": "Verdaccio Registry API",
5
5
  "main": "./build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -33,19 +33,19 @@
33
33
  },
34
34
  "license": "MIT",
35
35
  "dependencies": {
36
- "@verdaccio/auth": "9.0.0-next-9.5",
37
- "@verdaccio/config": "9.0.0-next-9.5",
38
- "@verdaccio/core": "9.0.0-next-9.5",
39
- "@verdaccio/logger": "9.0.0-next-9.5",
40
- "@verdaccio/middleware": "9.0.0-next-9.5",
41
- "@verdaccio/store": "9.0.0-next-9.5",
36
+ "@verdaccio/auth": "9.0.0-next-9.7",
37
+ "@verdaccio/config": "9.0.0-next-9.7",
38
+ "@verdaccio/core": "9.0.0-next-9.7",
39
+ "@verdaccio/logger": "9.0.0-next-9.7",
40
+ "@verdaccio/middleware": "9.0.0-next-9.7",
41
+ "@verdaccio/store": "9.0.0-next-9.7",
42
42
  "debug": "4.4.3",
43
43
  "express": "5.2.1",
44
44
  "lodash": "4.17.23"
45
45
  },
46
46
  "devDependencies": {
47
- "@verdaccio/test-helper": "5.0.0-next-9.5",
48
- "@verdaccio/types": "14.0.0-next-9.2",
47
+ "@verdaccio/test-helper": "5.0.0-next-9.7",
48
+ "@verdaccio/types": "14.0.0-next-9.4",
49
49
  "mockdate": "3.0.5",
50
50
  "nock": "13.5.6",
51
51
  "supertest": "7.1.4",