mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-10-24 02:07:00 +08:00
feat: depromisify fastify-jwt-authz (#49550)
This commit is contained in:
@@ -218,4 +218,75 @@ describe('fastify-jwt-authz', { only: true }, () => {
|
||||
assert.strictEqual(res.statusCode, 200);
|
||||
assert.strictEqual(resData.foo, 'bar');
|
||||
});
|
||||
|
||||
it('should throw an error when there is no callback', async () => {
|
||||
const fastify = Fastify();
|
||||
await fastify.register(jwtAuthz);
|
||||
|
||||
fastify.get(
|
||||
'/test7',
|
||||
{
|
||||
preHandler: function (request, _reply, done) {
|
||||
request.user = {
|
||||
name: 'sample',
|
||||
scope: 123
|
||||
};
|
||||
|
||||
request.jwtAuthz(['baz']);
|
||||
done();
|
||||
}
|
||||
},
|
||||
function () {
|
||||
return { foo: 'bar' };
|
||||
}
|
||||
);
|
||||
|
||||
fastify.listen({ port: 0 }, function () {
|
||||
fastify.server.unref();
|
||||
});
|
||||
|
||||
const res = await fastify.inject({
|
||||
method: 'GET',
|
||||
url: '/test7'
|
||||
});
|
||||
const resData: ErrorResponse = res.json();
|
||||
|
||||
assert.strictEqual(res.statusCode, 500);
|
||||
assert.strictEqual(resData.message, 'request.user.scope must be a string');
|
||||
});
|
||||
|
||||
it('should verify user scope when there is no callback', async () => {
|
||||
const fastify = Fastify();
|
||||
await fastify.register(jwtAuthz);
|
||||
|
||||
fastify.get(
|
||||
'/test8',
|
||||
{
|
||||
preHandler: function (request, _reply, done) {
|
||||
request.user = {
|
||||
name: 'sample',
|
||||
scope: 'user manager'
|
||||
};
|
||||
request.jwtAuthz(['user']);
|
||||
done();
|
||||
}
|
||||
},
|
||||
function () {
|
||||
return { foo: 'bar' };
|
||||
}
|
||||
);
|
||||
|
||||
fastify.listen({ port: 0 }, function () {
|
||||
fastify.server.unref();
|
||||
});
|
||||
|
||||
const res = await fastify.inject({
|
||||
method: 'GET',
|
||||
url: '/test8'
|
||||
});
|
||||
const resData: { foo: string } = res.json();
|
||||
|
||||
assert.strictEqual(res.statusCode, 200);
|
||||
assert.strictEqual(resData.foo, 'bar');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -26,49 +26,41 @@ import { FastifyPluginCallback, FastifyRequest } from 'fastify';
|
||||
import fp from 'fastify-plugin';
|
||||
|
||||
interface UserObject {
|
||||
scope: string;
|
||||
scope?: string;
|
||||
}
|
||||
|
||||
export interface JwtAuthz {
|
||||
(scopes: string[], callback: (err?: Error) => void): Promise<void>;
|
||||
interface JwtAuthz {
|
||||
(scopes: string[], callback?: (err?: Error) => void): void;
|
||||
}
|
||||
|
||||
const fastifyJwtAuthz: FastifyPluginCallback = (fastify, _opts, done) => {
|
||||
fastify.decorateRequest('jwtAuthz', checkScopes);
|
||||
fastify.decorateRequest('jwtAuthz', jwtAuthz);
|
||||
|
||||
done();
|
||||
function checkScopes(user: UserObject, scopes: string[]) {
|
||||
if (scopes.length === 0) return Error('Scopes cannot be empty');
|
||||
|
||||
function checkScopes(
|
||||
this: FastifyRequest,
|
||||
scopes: string[],
|
||||
callback: (err?: Error) => void
|
||||
) {
|
||||
if (callback === undefined) {
|
||||
return new Promise((resolve, reject) => {
|
||||
void this.jwtAuthz(scopes, function (err) {
|
||||
return err ? reject(err) : resolve(null);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (!user) return Error('request.user does not exist');
|
||||
|
||||
if (scopes.length === 0) {
|
||||
return callback(new Error('Scopes cannot be empty'));
|
||||
}
|
||||
const user = this.user as UserObject;
|
||||
if (!user) {
|
||||
return callback(new Error('request.user does not exist'));
|
||||
}
|
||||
if (typeof user.scope !== 'string') {
|
||||
return callback(new Error('request.user.scope must be a string'));
|
||||
}
|
||||
if (typeof user.scope !== 'string')
|
||||
return Error('request.user.scope must be a string');
|
||||
|
||||
const userScopes = user.scope.split(' ');
|
||||
const allowed = scopes.some(scope => {
|
||||
return userScopes.indexOf(scope) !== -1;
|
||||
});
|
||||
const sufficientScope = scopes.some(scope => userScopes.includes(scope));
|
||||
|
||||
return callback(allowed ? undefined : new Error('Insufficient scope'));
|
||||
if (!sufficientScope) return Error('Insufficient scope');
|
||||
}
|
||||
|
||||
function jwtAuthz(
|
||||
this: FastifyRequest,
|
||||
scopes: string[],
|
||||
callback?: (err?: Error) => void
|
||||
) {
|
||||
const err = checkScopes(this.user as UserObject, scopes);
|
||||
if (callback) return callback(err);
|
||||
if (err) throw err;
|
||||
}
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
declare module 'fastify' {
|
||||
|
||||
Reference in New Issue
Block a user