1043 timebox prepare zapier integration (#1967)

* Add create api-key route

* Import module

* Remove required mutation parameter

* Fix Authentication

* Generate random key

* Update Read ApiKeyAbility handler

* Add findMany apiKey route

* Remove useless attribute

* Use signed token for apiKeys

* Authenticate with api keys

* Fix typo

* Add a test for apiKey module

* Revoke token when api key does not exist

* Handler expiresAt parameter

* Fix user passport

* Code review returns: Add API_TOKEN_SECRET

* Code review returns: Rename variable

* Code review returns: Update code style

* Update apiKey schema

* Update create token route

* Update delete token route

* Filter revoked api keys from listApiKeys

* Rename endpoint

* Set default expiry to 2 years

* Code review returns: Update comment

* Generate token after create apiKey

* Code review returns: Update env variable

* Code review returns: Move method to proper service

---------

Co-authored-by: martmull <martmull@hotmail.com>
This commit is contained in:
martmull
2023-10-12 18:07:44 +02:00
committed by GitHub
parent 6b990c8501
commit 8fbad7d3ba
20 changed files with 430 additions and 42 deletions

View File

@ -1,14 +1,19 @@
import { PassportStrategy } from '@nestjs/passport';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import {
ForbiddenException,
Injectable,
UnauthorizedException,
} from '@nestjs/common';
import { Strategy, ExtractJwt } from 'passport-jwt';
import { User, Workspace } from '@prisma/client';
import { PrismaService } from 'src/database/prisma.service';
import { EnvironmentService } from 'src/integrations/environment/environment.service';
import { assert } from 'src/utils/assert';
export type JwtPayload = { sub: string; workspaceId: string };
export type PassportUser = { user: User; workspace: Workspace };
export type JwtPayload = { sub: string; workspaceId: string; jti?: string };
export type PassportUser = { user?: User; workspace: Workspace };
@Injectable()
export class JwtAuthStrategy extends PassportStrategy(Strategy, 'jwt') {
@ -24,22 +29,25 @@ export class JwtAuthStrategy extends PassportStrategy(Strategy, 'jwt') {
}
async validate(payload: JwtPayload): Promise<PassportUser> {
const user = await this.prismaService.client.user.findUniqueOrThrow({
where: { id: payload.sub },
const workspace = await this.prismaService.client.workspace.findUnique({
where: { id: payload.workspaceId ?? payload.sub },
});
if (!user) {
throw new UnauthorizedException();
}
const workspace =
await this.prismaService.client.workspace.findUniqueOrThrow({
where: { id: payload.workspaceId },
});
if (!workspace) {
throw new UnauthorizedException();
}
if (payload.jti) {
// If apiKey has been deleted or revoked, we throw an error
const apiKey = await this.prismaService.client.apiKey.findUniqueOrThrow({
where: { id: payload.jti },
});
assert(!apiKey.revokedAt, 'This API Key is revoked', ForbiddenException);
}
const user = payload.workspaceId
? await this.prismaService.client.user.findUniqueOrThrow({
where: { id: payload.sub },
})
: undefined;
return { user, workspace };
}