mirror of
https://github.com/verdaccio/verdaccio.git
synced 2024-12-24 21:15:51 +01:00
feat: migrate web login endpoint to fastify (#2624)
* feat: migrate login to fastify * Update package.json * Update server.ts * fix authentication tests * fix test
This commit is contained in:
parent
b7d319c5be
commit
18dc5f1f2f
@ -94,6 +94,9 @@ class Auth implements IAuth {
|
||||
this.config = config;
|
||||
this.logger = LoggerApi.logger.child({ sub: 'auth' });
|
||||
this.secret = config.secret;
|
||||
if (!this.secret) {
|
||||
throw new TypeError('secret it is required value on initialize the auth class');
|
||||
}
|
||||
|
||||
this.plugins =
|
||||
_.isNil(config?.auth) === false ? this._loadPlugin(config) : this.loadDefaultPlugin(config);
|
||||
|
@ -14,6 +14,8 @@ setup([]);
|
||||
describe('AuthTest', () => {
|
||||
test('should be defined', () => {
|
||||
const config: Config = new AppConfig(_.cloneDeep(authProfileConf));
|
||||
config.checkSecretKey('12345');
|
||||
|
||||
const auth: IAuth = new Auth(config);
|
||||
|
||||
expect(auth).toBeDefined();
|
||||
@ -23,6 +25,7 @@ describe('AuthTest', () => {
|
||||
describe('test authenticate states', () => {
|
||||
test('should be a success login', () => {
|
||||
const config: Config = new AppConfig(_.cloneDeep(authProfileConf));
|
||||
config.checkSecretKey('12345');
|
||||
const auth: IAuth = new Auth(config);
|
||||
|
||||
expect(auth).toBeDefined();
|
||||
@ -49,6 +52,7 @@ describe('AuthTest', () => {
|
||||
|
||||
test('should be a fail on login', () => {
|
||||
const config: Config = new AppConfig(_.cloneDeep(authPluginFailureConf));
|
||||
config.checkSecretKey('12345');
|
||||
const auth: IAuth = new Auth(config);
|
||||
|
||||
expect(auth).toBeDefined();
|
||||
@ -67,6 +71,7 @@ describe('AuthTest', () => {
|
||||
describe('test authenticate out of control inputs from plugins', () => {
|
||||
test('should skip falsy values', () => {
|
||||
const config: Config = new AppConfig(_.cloneDeep(authPluginPassThrougConf));
|
||||
config.checkSecretKey('12345');
|
||||
const auth: IAuth = new Auth(config);
|
||||
|
||||
expect(auth).toBeDefined();
|
||||
@ -86,6 +91,7 @@ describe('AuthTest', () => {
|
||||
|
||||
test('should error truthy non-array', () => {
|
||||
const config: Config = new AppConfig(_.cloneDeep(authPluginPassThrougConf));
|
||||
config.checkSecretKey('12345');
|
||||
const auth: IAuth = new Auth(config);
|
||||
|
||||
expect(auth).toBeDefined();
|
||||
@ -103,6 +109,7 @@ describe('AuthTest', () => {
|
||||
|
||||
test('should skip empty array', () => {
|
||||
const config: Config = new AppConfig(_.cloneDeep(authPluginPassThrougConf));
|
||||
config.checkSecretKey('12345');
|
||||
const auth: IAuth = new Auth(config);
|
||||
|
||||
expect(auth).toBeDefined();
|
||||
@ -119,6 +126,7 @@ describe('AuthTest', () => {
|
||||
|
||||
test('should accept valid array', () => {
|
||||
const config: Config = new AppConfig(_.cloneDeep(authPluginPassThrougConf));
|
||||
config.checkSecretKey('12345');
|
||||
const auth: IAuth = new Auth(config);
|
||||
|
||||
expect(auth).toBeDefined();
|
||||
|
75
packages/core/server/src/routes/web/api/login.ts
Normal file
75
packages/core/server/src/routes/web/api/login.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import buildDebug from 'debug';
|
||||
import { FastifyInstance } from 'fastify';
|
||||
import _ from 'lodash';
|
||||
|
||||
import { JWTSignOptions } from '@verdaccio/types';
|
||||
import { validatePassword } from '@verdaccio/utils';
|
||||
|
||||
const debug = buildDebug('verdaccio:api:login');
|
||||
|
||||
async function loginRoute(fastify: FastifyInstance) {
|
||||
fastify.post('/login', async (request, reply) => {
|
||||
// @ts-expect-error
|
||||
const { username, password } = request.body;
|
||||
debug('authenticate %o', username);
|
||||
fastify.auth.authenticate(
|
||||
username,
|
||||
password,
|
||||
async function callbackAuthenticate(err, user): Promise<void> {
|
||||
if (err) {
|
||||
const errorCode = err.message
|
||||
? fastify.statusCode.UNAUTHORIZED
|
||||
: fastify.statusCode.INTERNAL_ERROR;
|
||||
reply.send(fastify.errorUtils.getCode(errorCode, err.message));
|
||||
} else {
|
||||
const jWTSignOptions: JWTSignOptions = fastify.configInstance.security.web.sign;
|
||||
debug('jwtSignOptions: %o', jWTSignOptions);
|
||||
const token = await fastify.auth.jwtEncrypt(user, jWTSignOptions);
|
||||
reply.code(fastify.statusCode.OK).send({ token, username });
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
fastify.put('/reset_password', async (request, reply) => {
|
||||
if (_.isNil(request.userRemote.name)) {
|
||||
reply.send(
|
||||
fastify.errorUtils.getCode(
|
||||
fastify.statusCode.UNAUTHORIZED,
|
||||
fastify.errorUtils.API_ERROR.MUST_BE_LOGGED
|
||||
)
|
||||
);
|
||||
}
|
||||
// @ts-ignore
|
||||
const { password } = request.body;
|
||||
const { name } = request.userRemote;
|
||||
|
||||
if (validatePassword(password.new) === false) {
|
||||
fastify.auth.changePassword(
|
||||
name as string,
|
||||
password.old,
|
||||
password.new,
|
||||
(err, isUpdated): void => {
|
||||
if (_.isNil(err) && isUpdated) {
|
||||
reply.code(fastify.statusCode.OK);
|
||||
} else {
|
||||
reply.send(
|
||||
fastify.errorUtils.getInternalError(
|
||||
fastify.errorUtils.API_ERROR.INTERNAL_SERVER_ERROR
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
reply.send(
|
||||
fastify.errorUtils.getCode(
|
||||
fastify.statusCode.BAD_REQUEST,
|
||||
fastify.errorUtils.APP_ERROR.PASSWORD_VALIDATION
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
// });
|
||||
}
|
||||
export default loginRoute;
|
@ -13,6 +13,7 @@ import authPlugin from './plugins/auth';
|
||||
import configPlugin from './plugins/config';
|
||||
import coreUtils from './plugins/coreUtils';
|
||||
import storagePlugin from './plugins/storage';
|
||||
import login from './routes/web/api/login';
|
||||
import readme from './routes/web/api/readme';
|
||||
import sidebar from './routes/web/api/sidebar';
|
||||
|
||||
@ -24,10 +25,10 @@ async function startServer({ logger, config }) {
|
||||
debug('start server');
|
||||
const fastifyInstance = fastify({ logger });
|
||||
fastifyInstance.decorateRequest<RemoteUser>('userRemote', createAnonymousRemoteUser());
|
||||
fastifyInstance.register(configPlugin, { config });
|
||||
fastifyInstance.register(coreUtils);
|
||||
fastifyInstance.register(authPlugin, { config: configInstance });
|
||||
fastifyInstance.register(configPlugin, { config });
|
||||
fastifyInstance.register(storagePlugin, { config: configInstance });
|
||||
fastifyInstance.register(authPlugin, { config: configInstance });
|
||||
|
||||
// api
|
||||
fastifyInstance.register((instance, opts, done) => {
|
||||
@ -38,6 +39,8 @@ async function startServer({ logger, config }) {
|
||||
instance.register(tarball);
|
||||
instance.register(readme, { prefix: '/-/verdaccio' });
|
||||
instance.register(sidebar, { prefix: '/-/verdaccio' });
|
||||
instance.register(login, { prefix: '/-/verdaccio' });
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
|
@ -21,6 +21,7 @@ const getConf = (configName: string) => {
|
||||
export async function initializeServer(configName: string): Promise<Application> {
|
||||
const app = express();
|
||||
const config = new Config(getConf(configName));
|
||||
config.checkSecretKey('12345');
|
||||
const storage = new Storage(config);
|
||||
await storage.init(config, []);
|
||||
const auth: IAuth = new Auth(config);
|
||||
|
Loading…
Reference in New Issue
Block a user