Merge branch 'main' into feat/webhook-implementation

This commit is contained in:
Lucas Smith
2024-02-26 12:47:21 +11:00
committed by GitHub
196 changed files with 10026 additions and 1102 deletions

View File

@ -0,0 +1,67 @@
import type { Duration } from 'luxon';
import { DateTime } from 'luxon';
import { prisma } from '@documenso/prisma';
import { TeamMemberRole } from '@documenso/prisma/client';
// temporary choice for testing only
import * as timeConstants from '../../constants/time';
import { alphaid } from '../../universal/id';
import { hashString } from '../auth/hash';
type TimeConstants = typeof timeConstants & {
[key: string]: number | Duration;
};
type CreateApiTokenInput = {
userId: number;
teamId?: number;
tokenName: string;
expiresIn: string | null;
};
export const createApiToken = async ({
userId,
teamId,
tokenName,
expiresIn,
}: CreateApiTokenInput) => {
const apiToken = `api_${alphaid(16)}`;
const hashedToken = hashString(apiToken);
const timeConstantsRecords: TimeConstants = timeConstants;
if (teamId) {
const member = await prisma.teamMember.findFirst({
where: {
userId,
teamId,
role: TeamMemberRole.ADMIN,
},
});
if (!member) {
throw new Error('You do not have permission to create a token for this team');
}
}
const storedToken = await prisma.apiToken.create({
data: {
name: tokenName,
token: hashedToken,
expires: expiresIn ? DateTime.now().plus(timeConstantsRecords[expiresIn]).toJSDate() : null,
userId: teamId ? null : userId,
teamId,
},
});
if (!storedToken) {
throw new Error('Failed to create the API token');
}
return {
id: storedToken.id,
token: apiToken,
};
};

View File

@ -0,0 +1,32 @@
import { prisma } from '@documenso/prisma';
import { TeamMemberRole } from '@documenso/prisma/client';
export type DeleteTokenByIdOptions = {
id: number;
userId: number;
teamId?: number;
};
export const deleteTokenById = async ({ id, userId, teamId }: DeleteTokenByIdOptions) => {
if (teamId) {
const member = await prisma.teamMember.findFirst({
where: {
userId,
teamId,
role: TeamMemberRole.ADMIN,
},
});
if (!member) {
throw new Error('You do not have permission to delete this token');
}
}
return await prisma.apiToken.delete({
where: {
id,
userId: teamId ? null : userId,
teamId,
},
});
};

View File

@ -0,0 +1,36 @@
import { prisma } from '@documenso/prisma';
import { TeamMemberRole } from '@documenso/prisma/client';
export type GetUserTokensOptions = {
userId: number;
teamId: number;
};
export const getTeamTokens = async ({ userId, teamId }: GetUserTokensOptions) => {
const teamMember = await prisma.teamMember.findFirst({
where: {
userId,
teamId,
},
});
if (teamMember?.role !== TeamMemberRole.ADMIN) {
throw new Error('You do not have permission to view tokens for this team');
}
return await prisma.apiToken.findMany({
where: {
teamId,
},
select: {
id: true,
name: true,
algorithm: true,
createdAt: true,
expires: true,
},
orderBy: {
createdAt: 'desc',
},
});
};

View File

@ -0,0 +1,23 @@
import { prisma } from '@documenso/prisma';
export type GetUserTokensOptions = {
userId: number;
};
export const getUserTokens = async ({ userId }: GetUserTokensOptions) => {
return await prisma.apiToken.findMany({
where: {
userId,
},
select: {
id: true,
name: true,
algorithm: true,
createdAt: true,
expires: true,
},
orderBy: {
createdAt: 'desc',
},
});
};

View File

@ -0,0 +1,15 @@
import { prisma } from '@documenso/prisma';
export type GetApiTokenByIdOptions = {
id: number;
userId: number;
};
export const getApiTokenById = async ({ id, userId }: GetApiTokenByIdOptions) => {
return await prisma.apiToken.findFirstOrThrow({
where: {
id,
userId,
},
});
};

View File

@ -0,0 +1,41 @@
import { prisma } from '@documenso/prisma';
import { hashString } from '../auth/hash';
export const getApiTokenByToken = async ({ token }: { token: string }) => {
const hashedToken = hashString(token);
const apiToken = await prisma.apiToken.findFirst({
where: {
token: hashedToken,
},
include: {
team: true,
user: true,
},
});
if (!apiToken) {
throw new Error('Invalid token');
}
if (apiToken.expires && apiToken.expires < new Date()) {
throw new Error('Expired token');
}
if (apiToken.team) {
apiToken.user = await prisma.user.findFirst({
where: {
id: apiToken.team.ownerUserId,
},
});
}
const { user } = apiToken;
if (!user) {
throw new Error('Invalid token');
}
return { ...apiToken, user };
};