mirror of
https://github.com/papra-hq/papra.git
synced 2026-05-02 19:39:34 -05:00
refactor(documents): mutualized organization and document validation logic (#18)
This commit is contained in:
committed by
GitHub
parent
c00b2b5bbd
commit
60d4028aa8
@@ -0,0 +1,7 @@
|
||||
import { createErrorFactory } from '../shared/errors/errors';
|
||||
|
||||
export const createDocumentNotFoundError = createErrorFactory({
|
||||
message: 'Document not found.',
|
||||
code: 'document.not_found',
|
||||
statusCode: 404,
|
||||
});
|
||||
@@ -6,10 +6,11 @@ import { getDb } from '../app/database/database.models';
|
||||
import { getConfig } from '../config/config.models';
|
||||
import { organizationIdRegex } from '../organizations/organizations.constants';
|
||||
import { createOrganizationsRepository } from '../organizations/organizations.repository';
|
||||
import { ensureUserIsInOrganization } from '../organizations/organizations.usecases';
|
||||
import { createError } from '../shared/errors/errors';
|
||||
import { validateFormData, validateParams, validateQuery } from '../shared/validation/validation';
|
||||
import { createDocumentsRepository } from './documents.repository';
|
||||
import { createDocument } from './documents.usecases';
|
||||
import { createDocument, ensureDocumentExists, getDocumentOrThrow } from './documents.usecases';
|
||||
import { createDocumentStorageService } from './storage/documents.storage.services';
|
||||
|
||||
export function registerDocumentsPrivateRoutes({ app }: { app: ServerInstance }) {
|
||||
@@ -113,15 +114,7 @@ function setupGetDocumentsRoute({ app }: { app: ServerInstance }) {
|
||||
const documentsRepository = createDocumentsRepository({ db });
|
||||
const organizationsRepository = createOrganizationsRepository({ db });
|
||||
|
||||
const { isInOrganization } = await organizationsRepository.isUserInOrganization({ userId, organizationId });
|
||||
|
||||
if (!isInOrganization) {
|
||||
throw createError({
|
||||
message: 'You are not part of this organization.',
|
||||
code: 'user.not_in_organization',
|
||||
statusCode: 403,
|
||||
});
|
||||
}
|
||||
await ensureUserIsInOrganization({ userId, organizationId, organizationsRepository });
|
||||
|
||||
const [
|
||||
{ documents },
|
||||
@@ -155,17 +148,9 @@ function setupGetDocumentRoute({ app }: { app: ServerInstance }) {
|
||||
const documentsRepository = createDocumentsRepository({ db });
|
||||
const organizationsRepository = createOrganizationsRepository({ db });
|
||||
|
||||
const { isInOrganization } = await organizationsRepository.isUserInOrganization({ userId, organizationId });
|
||||
await ensureUserIsInOrganization({ userId, organizationId, organizationsRepository });
|
||||
|
||||
if (!isInOrganization) {
|
||||
throw createError({
|
||||
message: 'You are not part of this organization.',
|
||||
code: 'user.not_in_organization',
|
||||
statusCode: 403,
|
||||
});
|
||||
}
|
||||
|
||||
const { document } = await documentsRepository.getDocumentById({ documentId });
|
||||
const { document } = await getDocumentOrThrow({ documentId, documentsRepository });
|
||||
|
||||
return context.json({
|
||||
document,
|
||||
@@ -190,15 +175,8 @@ function setupDeleteDocumentRoute({ app }: { app: ServerInstance }) {
|
||||
const documentsRepository = createDocumentsRepository({ db });
|
||||
const organizationsRepository = createOrganizationsRepository({ db });
|
||||
|
||||
const { isInOrganization } = await organizationsRepository.isUserInOrganization({ userId, organizationId });
|
||||
|
||||
if (!isInOrganization) {
|
||||
throw createError({
|
||||
message: 'You are not part of this organization.',
|
||||
code: 'user.not_in_organization',
|
||||
statusCode: 403,
|
||||
});
|
||||
}
|
||||
await ensureUserIsInOrganization({ userId, organizationId, organizationsRepository });
|
||||
await ensureDocumentExists({ documentId, documentsRepository });
|
||||
|
||||
await documentsRepository.softDeleteDocument({ documentId, userId });
|
||||
|
||||
@@ -226,25 +204,9 @@ function setupGetDocumentFileRoute({ app }: { app: ServerInstance }) {
|
||||
const documentsRepository = createDocumentsRepository({ db });
|
||||
const organizationsRepository = createOrganizationsRepository({ db });
|
||||
|
||||
const { isInOrganization } = await organizationsRepository.isUserInOrganization({ userId, organizationId });
|
||||
await ensureUserIsInOrganization({ userId, organizationId, organizationsRepository });
|
||||
|
||||
if (!isInOrganization) {
|
||||
throw createError({
|
||||
message: 'You are not part of this organization.',
|
||||
code: 'user.not_in_organization',
|
||||
statusCode: 403,
|
||||
});
|
||||
}
|
||||
|
||||
const { document } = await documentsRepository.getDocumentById({ documentId });
|
||||
|
||||
if (!document) {
|
||||
throw createError({
|
||||
message: 'Document not found.',
|
||||
code: 'document.not_found',
|
||||
statusCode: 404,
|
||||
});
|
||||
}
|
||||
const { document } = await getDocumentOrThrow({ documentId, documentsRepository });
|
||||
|
||||
const documentsStorageService = await createDocumentStorageService({ config });
|
||||
|
||||
@@ -285,15 +247,7 @@ function setupSearchDocumentsRoute({ app }: { app: ServerInstance }) {
|
||||
const documentsRepository = createDocumentsRepository({ db });
|
||||
const organizationsRepository = createOrganizationsRepository({ db });
|
||||
|
||||
const { isInOrganization } = await organizationsRepository.isUserInOrganization({ userId, organizationId });
|
||||
|
||||
if (!isInOrganization) {
|
||||
throw createError({
|
||||
message: 'You are not part of this organization.',
|
||||
code: 'user.not_in_organization',
|
||||
statusCode: 403,
|
||||
});
|
||||
}
|
||||
await ensureUserIsInOrganization({ userId, organizationId, organizationsRepository });
|
||||
|
||||
const { documents } = await documentsRepository.searchOrganizationDocuments({ organizationId, searchQuery, pageIndex, pageSize });
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { DocumentsRepository } from './documents.repository';
|
||||
import type { DocumentStorageService } from './storage/documents.storage.services';
|
||||
import { createDocumentNotFoundError } from './documents.errors';
|
||||
import { buildOriginalDocumentKey, generateDocumentId as generateDocumentIdImpl } from './documents.models';
|
||||
|
||||
export async function createDocument({
|
||||
@@ -49,3 +50,29 @@ export async function createDocument({
|
||||
|
||||
return { document };
|
||||
}
|
||||
|
||||
export async function getDocumentOrThrow({
|
||||
documentId,
|
||||
documentsRepository,
|
||||
}: {
|
||||
documentId: string;
|
||||
documentsRepository: DocumentsRepository;
|
||||
}) {
|
||||
const { document } = await documentsRepository.getDocumentById({ documentId });
|
||||
|
||||
if (!document) {
|
||||
throw createDocumentNotFoundError();
|
||||
}
|
||||
|
||||
return { document };
|
||||
}
|
||||
|
||||
export async function ensureDocumentExists({
|
||||
documentId,
|
||||
documentsRepository,
|
||||
}: {
|
||||
documentId: string;
|
||||
documentsRepository: DocumentsRepository;
|
||||
}) {
|
||||
await getDocumentOrThrow({ documentId, documentsRepository });
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { createErrorFactory } from '../shared/errors/errors';
|
||||
|
||||
export const createUserNotInOrganizationError = createErrorFactory({
|
||||
message: 'You are not part of this organization.',
|
||||
code: 'user.not_in_organization',
|
||||
statusCode: 403,
|
||||
});
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { OrganizationsRepository } from './organizations.repository';
|
||||
import { ORGANIZATION_ROLE_OWNER } from './organizations.constants';
|
||||
import { createUserNotInOrganizationError } from './organizations.errors';
|
||||
|
||||
export async function createOrganization({ name, userId, organizationsRepository }: { name: string; userId: string; organizationsRepository: OrganizationsRepository }) {
|
||||
const { organization } = await organizationsRepository.saveOrganization({ organization: { name } });
|
||||
@@ -8,3 +9,19 @@ export async function createOrganization({ name, userId, organizationsRepository
|
||||
|
||||
return { organization };
|
||||
}
|
||||
|
||||
export async function ensureUserIsInOrganization({
|
||||
userId,
|
||||
organizationId,
|
||||
organizationsRepository,
|
||||
}: {
|
||||
userId: string;
|
||||
organizationId: string;
|
||||
organizationsRepository: OrganizationsRepository;
|
||||
}) {
|
||||
const { isInOrganization } = await organizationsRepository.isUserInOrganization({ userId, organizationId });
|
||||
|
||||
if (!isInOrganization) {
|
||||
throw createUserNotInOrganizationError();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user