feat: access token (#1320)

Co-authored-by: sealday <sealday@gmail.com>
Reviewed-on: daoyoucloud/tachybase#1320
This commit is contained in:
sealday 2024-07-15 18:45:45 +08:00
parent 3a1e3d92e6
commit 90a09dfa40
3 changed files with 38 additions and 2 deletions

View File

@ -92,5 +92,10 @@ export default {
type: 'string', type: 'string',
hidden: true, hidden: true,
}, },
{
name: 'accessToken',
type: 'string',
hidden: true,
},
], ],
} as CollectionOptions; } as CollectionOptions;

View File

@ -1,3 +1,4 @@
import { createHash } from 'crypto';
import actions, { Context, Next } from '@tachybase/actions'; import actions, { Context, Next } from '@tachybase/actions';
import { Repository } from '@tachybase/database'; import { Repository } from '@tachybase/database';
@ -18,13 +19,19 @@ export async function create(ctx: Context, next: Next) {
throw ctx.throw(400, ctx.t('Role not found')); throw ctx.throw(400, ctx.t('Role not found'));
} }
const token = ctx.app.authManager.jwt.sign( const hash = createHash('sha256');
const jwtToken = ctx.app.authManager.jwt.sign(
{ userId: ctx.auth.user.id, roleName: role.name }, { userId: ctx.auth.user.id, roleName: role.name },
{ expiresIn: values.expiresIn }, { expiresIn: values.expiresIn },
); );
hash.update(jwtToken);
const token = hash.digest('hex');
ctx.action.mergeParams({ ctx.action.mergeParams({
values: { values: {
token, token: jwtToken,
accessToken: token,
}, },
}); });
return actions.create(ctx, async () => { return actions.create(ctx, async () => {

View File

@ -22,6 +22,30 @@ export class PluginAPIKeysServer extends Plugin {
} }
async load() { async load() {
const repo = this.db.getRepository('apiKeys');
this.app.resourcer.use(
async (ctx, next) => {
const token = ctx.getBearerToken();
// TODO 固定长度判断来优化性能
if (token && token.length !== 64) {
return await next();
}
const key = await repo.findOne({
filter: {
accessToken: token,
},
});
ctx.getBearerToken = () => {
if (key) {
return key.token;
}
return token;
};
await next();
},
{ tag: 'api-access-token', before: 'auth' },
);
this.app.resourcer.use(async (ctx, next) => { this.app.resourcer.use(async (ctx, next) => {
const { resourceName, actionName } = ctx.action; const { resourceName, actionName } = ctx.action;
if (resourceName === this.resourceName && ['list', 'destroy'].includes(actionName)) { if (resourceName === this.resourceName && ['list', 'destroy'].includes(actionName)) {