feat: add authorization for api calls
This commit is contained in:
@@ -1,16 +1,38 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||||
|
|
||||||
|
import { deleteDraftDocument } from '@documenso/lib/server-only/document/delete-draft-document';
|
||||||
import { getDocumentById } from '@documenso/lib/server-only/document/get-document-by-id';
|
import { getDocumentById } from '@documenso/lib/server-only/document/get-document-by-id';
|
||||||
import { getDocuments } from '@documenso/lib/server-only/public-api/get-documents';
|
import { getDocuments } from '@documenso/lib/server-only/public-api/get-documents';
|
||||||
|
import { checkUserFromToken } from '@documenso/lib/server-only/public-api/get-user-by-token';
|
||||||
import { contract } from '@documenso/trpc/api-contract/contract';
|
import { contract } from '@documenso/trpc/api-contract/contract';
|
||||||
import { createNextRoute, createNextRouter } from '@documenso/trpc/server/public-api/ts-rest';
|
import { createNextRoute, createNextRouter } from '@documenso/trpc/server/public-api/ts-rest';
|
||||||
|
|
||||||
|
const validateUserToken = async (token: string) => {
|
||||||
|
try {
|
||||||
|
return await checkUserFromToken({ token });
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const router = createNextRoute(contract, {
|
const router = createNextRoute(contract, {
|
||||||
getDocuments: async (args) => {
|
getDocuments: async (args) => {
|
||||||
const page = Number(args.query.page) || 1;
|
const page = Number(args.query.page) || 1;
|
||||||
const perPage = Number(args.query.perPage) || 10;
|
const perPage = Number(args.query.perPage) || 10;
|
||||||
|
const { authorization } = args.headers;
|
||||||
|
|
||||||
const { documents, totalPages } = await getDocuments({ page, perPage });
|
const user = await validateUserToken(authorization);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return {
|
||||||
|
status: 401,
|
||||||
|
body: {
|
||||||
|
message: 'Unauthorized',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const { documents, totalPages } = await getDocuments({ page, perPage, userId: user.id });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status: 200,
|
status: 200,
|
||||||
@@ -21,12 +43,66 @@ const router = createNextRoute(contract, {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
getDocument: async (args) => {
|
getDocument: async (args) => {
|
||||||
const document = await getDocumentById(args.params.id);
|
const { id: documentId } = args.params;
|
||||||
|
const { authorization } = args.headers;
|
||||||
|
|
||||||
return {
|
const user = await validateUserToken(authorization);
|
||||||
status: 200,
|
|
||||||
body: document,
|
if (!user) {
|
||||||
};
|
return {
|
||||||
|
status: 401,
|
||||||
|
body: {
|
||||||
|
message: 'Unauthorized',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const document = await getDocumentById({ id: Number(documentId), userId: user.id });
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 200,
|
||||||
|
body: document,
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
return {
|
||||||
|
status: 404,
|
||||||
|
body: {
|
||||||
|
message: 'Document not found',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteDocument: async (args) => {
|
||||||
|
const { id: documentId } = args.params;
|
||||||
|
const { authorization } = args.headers;
|
||||||
|
|
||||||
|
const user = await validateUserToken(authorization);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return {
|
||||||
|
status: 401,
|
||||||
|
body: {
|
||||||
|
message: 'Unauthorized',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const document = await deleteDraftDocument({ id: Number(documentId), userId: user.id });
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 200,
|
||||||
|
body: document,
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
return {
|
||||||
|
status: 404,
|
||||||
|
body: {
|
||||||
|
message: 'Document not found',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,15 @@ import { prisma } from '@documenso/prisma';
|
|||||||
type GetDocumentsProps = {
|
type GetDocumentsProps = {
|
||||||
page: number;
|
page: number;
|
||||||
perPage: number;
|
perPage: number;
|
||||||
|
userId: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getDocuments = async ({ page = 1, perPage = 10 }: GetDocumentsProps) => {
|
export const getDocuments = async ({ page = 1, perPage = 10, userId }: GetDocumentsProps) => {
|
||||||
const [documents, count] = await Promise.all([
|
const [documents, count] = await Promise.all([
|
||||||
await prisma.document.findMany({
|
await prisma.document.findMany({
|
||||||
|
where: {
|
||||||
|
userId,
|
||||||
|
},
|
||||||
take: perPage,
|
take: perPage,
|
||||||
skip: Math.max(page - 1, 0) * perPage,
|
skip: Math.max(page - 1, 0) * perPage,
|
||||||
}),
|
}),
|
||||||
|
|||||||
15
packages/lib/server-only/public-api/get-user-by-token.ts
Normal file
15
packages/lib/server-only/public-api/get-user-by-token.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { prisma } from '@documenso/prisma';
|
||||||
|
|
||||||
|
export const checkUserFromToken = async ({ token }: { token: string }) => {
|
||||||
|
const user = await prisma.user.findFirstOrThrow({
|
||||||
|
where: {
|
||||||
|
ApiToken: {
|
||||||
|
some: {
|
||||||
|
token: token,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return user;
|
||||||
|
};
|
||||||
@@ -40,6 +40,8 @@ export const contract = c.router(
|
|||||||
query: GetDocumentsQuerySchema,
|
query: GetDocumentsQuerySchema,
|
||||||
responses: {
|
responses: {
|
||||||
200: SuccessfulResponseSchema,
|
200: SuccessfulResponseSchema,
|
||||||
|
401: UnsuccessfulResponseSchema,
|
||||||
|
404: UnsuccessfulResponseSchema,
|
||||||
},
|
},
|
||||||
summary: 'Get all documents',
|
summary: 'Get all documents',
|
||||||
},
|
},
|
||||||
@@ -48,6 +50,8 @@ export const contract = c.router(
|
|||||||
path: `/documents/:id`,
|
path: `/documents/:id`,
|
||||||
responses: {
|
responses: {
|
||||||
200: DocumentSchema,
|
200: DocumentSchema,
|
||||||
|
401: UnsuccessfulResponseSchema,
|
||||||
|
404: UnsuccessfulResponseSchema,
|
||||||
},
|
},
|
||||||
summary: 'Get a single document',
|
summary: 'Get a single document',
|
||||||
},
|
},
|
||||||
@@ -57,6 +61,7 @@ export const contract = c.router(
|
|||||||
body: z.string(),
|
body: z.string(),
|
||||||
responses: {
|
responses: {
|
||||||
200: DocumentSchema,
|
200: DocumentSchema,
|
||||||
|
401: UnsuccessfulResponseSchema,
|
||||||
404: UnsuccessfulResponseSchema,
|
404: UnsuccessfulResponseSchema,
|
||||||
},
|
},
|
||||||
summary: 'Delete a document',
|
summary: 'Delete a document',
|
||||||
|
|||||||
Reference in New Issue
Block a user