mirror of
https://github.com/verdaccio/verdaccio.git
synced 2024-12-16 21:56:25 -05:00
fix: error E409 "username is already registered" (adduser) (#4957)
* fix: E409 username is already registered (adduser) * update tests
This commit is contained in:
parent
ba71932523
commit
eca62597e8
5 changed files with 51 additions and 27 deletions
6
.changeset/green-eagles-boil.md
Normal file
6
.changeset/green-eagles-boil.md
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
'@verdaccio/auth': patch
|
||||||
|
'@verdaccio/api': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: E409 username is already registered (adduser)
|
|
@ -28,7 +28,11 @@ export default function (route: Router, auth: Auth, config: Config, logger: Logg
|
||||||
function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void {
|
function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void {
|
||||||
debug('verifying user');
|
debug('verifying user');
|
||||||
|
|
||||||
if (typeof req.remote_user.name !== 'string' || req.remote_user.name === '') {
|
if (
|
||||||
|
!req.remote_user ||
|
||||||
|
typeof req.remote_user.name !== 'string' ||
|
||||||
|
req.remote_user.name === ''
|
||||||
|
) {
|
||||||
debug('user not logged in');
|
debug('user not logged in');
|
||||||
res.status(HTTP_STATUS.OK);
|
res.status(HTTP_STATUS.OK);
|
||||||
return next({ ok: false });
|
return next({ ok: false });
|
||||||
|
|
|
@ -166,7 +166,9 @@ export function getDefaultPlugins(logger: Logger): pluginUtils.Auth<Config> {
|
||||||
|
|
||||||
adduser(_user: string, _password: string, cb: pluginUtils.AuthUserCallback): void {
|
adduser(_user: string, _password: string, cb: pluginUtils.AuthUserCallback): void {
|
||||||
debug('triggered default adduser method');
|
debug('triggered default adduser method');
|
||||||
return cb(errorUtils.getConflict(API_ERROR.BAD_USERNAME_PASSWORD));
|
// since adduser is not implemented but optional, continue without error
|
||||||
|
// this assumes that the user is added by an external system
|
||||||
|
cb(null, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|
|
@ -123,11 +123,12 @@ describe('Auth utilities', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('add user should fail by default (default)', () => {
|
test('add user should not fail by default (default)', () => {
|
||||||
const plugin = getDefaultPlugins({ trace: vi.fn() });
|
const plugin = getDefaultPlugins({ trace: vi.fn() });
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
plugin.adduser('foo', 'bar', (error: any) => {
|
plugin.adduser('foo', 'bar', (error: any, access: any) => {
|
||||||
expect(error).toEqual(errorUtils.getForbidden(API_ERROR.BAD_USERNAME_PASSWORD));
|
expect(error).toEqual(null);
|
||||||
|
expect(access).toEqual(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,14 +4,7 @@ import supertest from 'supertest';
|
||||||
import { describe, expect, test, vi } from 'vitest';
|
import { describe, expect, test, vi } from 'vitest';
|
||||||
|
|
||||||
import { Config as AppConfig, ROLES, createRemoteUser, getDefaultConfig } from '@verdaccio/config';
|
import { Config as AppConfig, ROLES, createRemoteUser, getDefaultConfig } from '@verdaccio/config';
|
||||||
import {
|
import { HEADERS, HTTP_STATUS, SUPPORT_ERRORS, TOKEN_BEARER, errorUtils } from '@verdaccio/core';
|
||||||
API_ERROR,
|
|
||||||
HEADERS,
|
|
||||||
HTTP_STATUS,
|
|
||||||
SUPPORT_ERRORS,
|
|
||||||
TOKEN_BEARER,
|
|
||||||
errorUtils,
|
|
||||||
} from '@verdaccio/core';
|
|
||||||
import { logger, setup } from '@verdaccio/logger';
|
import { logger, setup } from '@verdaccio/logger';
|
||||||
import { errorReportingMiddleware, final, handleError } from '@verdaccio/middleware';
|
import { errorReportingMiddleware, final, handleError } from '@verdaccio/middleware';
|
||||||
import { Config } from '@verdaccio/types';
|
import { Config } from '@verdaccio/types';
|
||||||
|
@ -259,7 +252,7 @@ describe('AuthTest', () => {
|
||||||
describe('no custom allow_access implementation provided', () => {
|
describe('no custom allow_access implementation provided', () => {
|
||||||
// when allow_access is not implemented, the groups must match
|
// when allow_access is not implemented, the groups must match
|
||||||
// exactly with the packages access group
|
// exactly with the packages access group
|
||||||
test('should fails if groups do not match exactly', async () => {
|
test('should fail if groups do not match exactly', async () => {
|
||||||
const config: Config = new AppConfig({ ...authProfileConf });
|
const config: Config = new AppConfig({ ...authProfileConf });
|
||||||
config.checkSecretKey('12345');
|
config.checkSecretKey('12345');
|
||||||
const auth: Auth = new Auth(config, logger);
|
const auth: Auth = new Auth(config, logger);
|
||||||
|
@ -308,7 +301,7 @@ describe('AuthTest', () => {
|
||||||
describe('no custom allow_publish implementation provided', () => {
|
describe('no custom allow_publish implementation provided', () => {
|
||||||
// when allow_access is not implemented, the groups must match
|
// when allow_access is not implemented, the groups must match
|
||||||
// exactly with the packages access group
|
// exactly with the packages access group
|
||||||
test('should fails if groups do not match exactly', async () => {
|
test('should fail if groups do not match exactly', async () => {
|
||||||
const config: Config = new AppConfig({ ...authProfileConf });
|
const config: Config = new AppConfig({ ...authProfileConf });
|
||||||
config.checkSecretKey('12345');
|
config.checkSecretKey('12345');
|
||||||
const auth: Auth = new Auth(config, logger);
|
const auth: Auth = new Auth(config, logger);
|
||||||
|
@ -354,7 +347,7 @@ describe('AuthTest', () => {
|
||||||
});
|
});
|
||||||
describe('allow_unpublish', () => {
|
describe('allow_unpublish', () => {
|
||||||
describe('no custom allow_unpublish implementation provided', () => {
|
describe('no custom allow_unpublish implementation provided', () => {
|
||||||
test('should fails if groups do not match exactly', async () => {
|
test('should fail if groups do not match exactly', async () => {
|
||||||
const config: Config = new AppConfig({ ...authProfileConf });
|
const config: Config = new AppConfig({ ...authProfileConf });
|
||||||
config.checkSecretKey('12345');
|
config.checkSecretKey('12345');
|
||||||
|
|
||||||
|
@ -439,7 +432,7 @@ describe('AuthTest', () => {
|
||||||
describe('error handling', () => {
|
describe('error handling', () => {
|
||||||
// when allow_access is not implemented, the groups must match
|
// when allow_access is not implemented, the groups must match
|
||||||
// exactly with the packages access group
|
// exactly with the packages access group
|
||||||
test('should fails with bad password if adduser is not implemented', async () => {
|
test('should not fail if adduser is not implemented', async () => {
|
||||||
const config: Config = new AppConfig({ ...authProfileConf });
|
const config: Config = new AppConfig({ ...authProfileConf });
|
||||||
config.checkSecretKey('12345');
|
config.checkSecretKey('12345');
|
||||||
const auth: Auth = new Auth(config, logger);
|
const auth: Auth = new Auth(config, logger);
|
||||||
|
@ -451,12 +444,21 @@ describe('AuthTest', () => {
|
||||||
auth.add_user('juan', 'password', callback);
|
auth.add_user('juan', 'password', callback);
|
||||||
|
|
||||||
expect(callback).toHaveBeenCalledTimes(1);
|
expect(callback).toHaveBeenCalledTimes(1);
|
||||||
expect(callback).toHaveBeenCalledWith(
|
expect(callback).toHaveBeenCalledWith(null, {
|
||||||
errorUtils.getConflict(API_ERROR.BAD_USERNAME_PASSWORD)
|
groups: [
|
||||||
);
|
'test',
|
||||||
|
ROLES.$ALL,
|
||||||
|
ROLES.$AUTH,
|
||||||
|
ROLES.DEPRECATED_ALL,
|
||||||
|
ROLES.DEPRECATED_AUTH,
|
||||||
|
ROLES.ALL,
|
||||||
|
],
|
||||||
|
name: 'juan',
|
||||||
|
real_groups: ['test'],
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should fails if adduser fails internally (exception)', async () => {
|
test('should fail if adduser fails internally (exception)', async () => {
|
||||||
const config: Config = new AppConfig({
|
const config: Config = new AppConfig({
|
||||||
...getDefaultConfig(),
|
...getDefaultConfig(),
|
||||||
plugins: path.join(__dirname, './partials/plugin'),
|
plugins: path.join(__dirname, './partials/plugin'),
|
||||||
|
@ -471,14 +473,14 @@ describe('AuthTest', () => {
|
||||||
|
|
||||||
const callback = vi.fn();
|
const callback = vi.fn();
|
||||||
|
|
||||||
// note: fail uas username make plugin fails
|
// note: username to make plugin fail
|
||||||
auth.add_user('fail', 'password', callback);
|
auth.add_user('fail', 'password', callback);
|
||||||
|
|
||||||
expect(callback).toHaveBeenCalledTimes(1);
|
expect(callback).toHaveBeenCalledTimes(1);
|
||||||
expect(callback).toHaveBeenCalledWith(new Error('bad username'));
|
expect(callback).toHaveBeenCalledWith(new Error('bad username'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should skip to the next plugin and fails', async () => {
|
test('should skip to the next plugin and fail', async () => {
|
||||||
const config: Config = new AppConfig({
|
const config: Config = new AppConfig({
|
||||||
...getDefaultConfig(),
|
...getDefaultConfig(),
|
||||||
plugins: path.join(__dirname, './partials/plugin'),
|
plugins: path.join(__dirname, './partials/plugin'),
|
||||||
|
@ -495,13 +497,22 @@ describe('AuthTest', () => {
|
||||||
|
|
||||||
const callback = vi.fn();
|
const callback = vi.fn();
|
||||||
|
|
||||||
// note: fail uas username make plugin fails
|
// note: username to make plugin fail
|
||||||
auth.add_user('skip', 'password', callback);
|
auth.add_user('skip', 'password', callback);
|
||||||
|
|
||||||
expect(callback).toHaveBeenCalledTimes(1);
|
expect(callback).toHaveBeenCalledTimes(1);
|
||||||
expect(callback).toHaveBeenCalledWith(
|
expect(callback).toHaveBeenCalledWith(null, {
|
||||||
errorUtils.getConflict(API_ERROR.BAD_USERNAME_PASSWORD)
|
groups: [
|
||||||
);
|
'test',
|
||||||
|
ROLES.$ALL,
|
||||||
|
ROLES.$AUTH,
|
||||||
|
ROLES.DEPRECATED_ALL,
|
||||||
|
ROLES.DEPRECATED_AUTH,
|
||||||
|
ROLES.ALL,
|
||||||
|
],
|
||||||
|
name: 'skip',
|
||||||
|
real_groups: ['test'],
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
test('should success if adduser', async () => {
|
test('should success if adduser', async () => {
|
||||||
|
|
Loading…
Reference in a new issue