chore: implemented feedback
This commit is contained in:
@@ -1,12 +1,10 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
|
||||||
|
|
||||||
import { upsertDocumentMeta } from '@documenso/lib/server-only/document-meta/upsert-document-meta';
|
import { upsertDocumentMeta } from '@documenso/lib/server-only/document-meta/upsert-document-meta';
|
||||||
import { deleteDocument } from '@documenso/lib/server-only/document/delete-document';
|
import { deleteDocument } from '@documenso/lib/server-only/document/delete-document';
|
||||||
import { findDocuments } from '@documenso/lib/server-only/document/find-documents';
|
import { findDocuments } from '@documenso/lib/server-only/document/find-documents';
|
||||||
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 { sendDocument } from '@documenso/lib/server-only/document/send-document';
|
import { sendDocument } from '@documenso/lib/server-only/document/send-document';
|
||||||
import { setFieldsForDocument } from '@documenso/lib/server-only/field/set-fields-for-document';
|
import { setFieldsForDocument } from '@documenso/lib/server-only/field/set-fields-for-document';
|
||||||
import { checkUserFromToken } from '@documenso/lib/server-only/public-api/get-user-by-token';
|
import { getUserByApiToken } from '@documenso/lib/server-only/public-api/get-user-by-token';
|
||||||
import { setRecipientsForDocument } from '@documenso/lib/server-only/recipient/set-recipients-for-document';
|
import { setRecipientsForDocument } from '@documenso/lib/server-only/recipient/set-recipients-for-document';
|
||||||
import { getPresignPostUrl } from '@documenso/lib/universal/upload/server-actions';
|
import { getPresignPostUrl } from '@documenso/lib/universal/upload/server-actions';
|
||||||
import { contract } from '@documenso/trpc/api-contract/contract';
|
import { contract } from '@documenso/trpc/api-contract/contract';
|
||||||
@@ -20,7 +18,7 @@ const router = createNextRoute(contract, {
|
|||||||
let user;
|
let user;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
user = await checkUserFromToken({ token: authorization });
|
user = await getUserByApiToken({ token: authorization });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return {
|
return {
|
||||||
status: 401,
|
status: 401,
|
||||||
@@ -46,7 +44,7 @@ const router = createNextRoute(contract, {
|
|||||||
let user;
|
let user;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
user = await checkUserFromToken({ token: authorization });
|
user = await getUserByApiToken({ token: authorization });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return {
|
return {
|
||||||
status: 401,
|
status: 401,
|
||||||
@@ -79,7 +77,7 @@ const router = createNextRoute(contract, {
|
|||||||
let user;
|
let user;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
user = await checkUserFromToken({ token: authorization });
|
user = await getUserByApiToken({ token: authorization });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return {
|
return {
|
||||||
status: 401,
|
status: 401,
|
||||||
@@ -140,7 +138,7 @@ const router = createNextRoute(contract, {
|
|||||||
let user;
|
let user;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
user = await checkUserFromToken({ token: authorization });
|
user = await getUserByApiToken({ token: authorization });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return {
|
return {
|
||||||
status: 401,
|
status: 401,
|
||||||
@@ -226,8 +224,4 @@ const router = createNextRoute(contract, {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const nextRouter = createNextRouter(contract, router);
|
export default createNextRouter(contract, router);
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
||||||
await nextRouter(req, res);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { compareSync as bcryptCompareSync, hashSync as bcryptHashSync } from 'bcrypt';
|
import { compareSync as bcryptCompareSync, hashSync as bcryptHashSync } from 'bcrypt';
|
||||||
|
import crypto from 'crypto';
|
||||||
|
|
||||||
import { SALT_ROUNDS } from '../../constants/auth';
|
import { SALT_ROUNDS } from '../../constants/auth';
|
||||||
|
|
||||||
@@ -12,3 +13,7 @@ export const hashSync = (password: string) => {
|
|||||||
export const compareSync = (password: string, hash: string) => {
|
export const compareSync = (password: string, hash: string) => {
|
||||||
return bcryptCompareSync(password, hash);
|
return bcryptCompareSync(password, hash);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const hashString = (input: string) => {
|
||||||
|
return crypto.createHash('sha512').update(input).digest('hex');
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import crypto from 'crypto';
|
|
||||||
|
|
||||||
import { prisma } from '@documenso/prisma';
|
import { prisma } from '@documenso/prisma';
|
||||||
|
|
||||||
// temporary choice for testing only
|
// temporary choice for testing only
|
||||||
import { ONE_YEAR } from '../../constants/time';
|
import { ONE_YEAR } from '../../constants/time';
|
||||||
|
import { alphaid } from '../../universal/id';
|
||||||
|
import { hashString } from '../auth/hash';
|
||||||
|
|
||||||
type CreateApiTokenInput = {
|
type CreateApiTokenInput = {
|
||||||
userId: number;
|
userId: number;
|
||||||
@@ -11,24 +11,25 @@ type CreateApiTokenInput = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const createApiToken = async ({ userId, tokenName }: CreateApiTokenInput) => {
|
export const createApiToken = async ({ userId, tokenName }: CreateApiTokenInput) => {
|
||||||
// quick implementation for testing; it needs double checking
|
const apiToken = `api_${alphaid(16)}`;
|
||||||
const tokenHash = crypto
|
|
||||||
.createHash('sha512')
|
|
||||||
.update(crypto.randomBytes(32).toString('hex'))
|
|
||||||
.digest('hex');
|
|
||||||
|
|
||||||
const token = await prisma.apiToken.create({
|
const hashedToken = hashString(apiToken);
|
||||||
|
|
||||||
|
const dbToken = await prisma.apiToken.create({
|
||||||
data: {
|
data: {
|
||||||
token: tokenHash,
|
token: hashedToken,
|
||||||
name: tokenName,
|
name: tokenName,
|
||||||
userId,
|
userId,
|
||||||
expires: new Date(Date.now() + ONE_YEAR),
|
expires: new Date(Date.now() + ONE_YEAR),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!token) {
|
if (!dbToken) {
|
||||||
throw new Error(`Failed to create the API token`);
|
throw new Error(`Failed to create the API token`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return token;
|
return {
|
||||||
|
id: dbToken.id,
|
||||||
|
token: apiToken,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
import { prisma } from '@documenso/prisma';
|
import { prisma } from '@documenso/prisma';
|
||||||
|
|
||||||
export const checkUserFromToken = async ({ token }: { token: string }) => {
|
import { hashString } from '../auth/hash';
|
||||||
|
|
||||||
|
export const getUserByApiToken = async ({ token }: { token: string }) => {
|
||||||
|
const hashedToken = hashString(token);
|
||||||
|
|
||||||
const user = await prisma.user.findFirst({
|
const user = await prisma.user.findFirst({
|
||||||
where: {
|
where: {
|
||||||
ApiToken: {
|
ApiToken: {
|
||||||
some: {
|
some: {
|
||||||
token: token,
|
token: hashedToken,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -18,7 +22,7 @@ export const checkUserFromToken = async ({ token }: { token: string }) => {
|
|||||||
throw new Error('Invalid token');
|
throw new Error('Invalid token');
|
||||||
}
|
}
|
||||||
|
|
||||||
const tokenObject = user.ApiToken.find((apiToken) => apiToken.token === token);
|
const tokenObject = user.ApiToken.find((apiToken) => apiToken.token === hashedToken);
|
||||||
|
|
||||||
if (!tokenObject || new Date(tokenObject.expires) < new Date()) {
|
if (!tokenObject || new Date(tokenObject.expires) < new Date()) {
|
||||||
throw new Error('Expired token');
|
throw new Error('Expired token');
|
||||||
|
|||||||
Reference in New Issue
Block a user