feat: 프로젝트 문서 첨부(생성/편집/상세)
프로젝트에 문서 파일을 첨부할 수 있도록 추가(업무 첨부 인프라·업로드 설정 재사용). 백엔드: - ProjectAttachment 엔티티 + 마이그레이션(project_attachments) - 업로드(관리자)/삭제(관리자)/다운로드(멤버) 엔드포인트, 멀터 디스크 저장 - 프로젝트 상세 응답에 attachments 포함 프론트: - 생성 화면: 파일 staged 후 생성 직후 업로드 - 편집(설정) 화면: 기존 문서 목록 + 추가/삭제(즉시), 폼 미저장 보존 - 프로젝트 상세: 문서 목록(다운로드 전용) - useProject.uploadFile/removeFile, ApiProjectAttachment 타입 권한: 업로드/삭제=관리자, 조회/다운로드=멤버. 형식/용량은 업무 첨부와 동일(25MB). 런타임 검증: 업로드·목록·다운로드·삭제 + 비관리자 403 확인. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
// 프로젝트 문서 첨부 — project_attachments 테이블 추가.
|
||||
// (업무 첨부 attachments 와 동일 구조, project_id FK)
|
||||
export class AddProjectAttachments1782500000000 implements MigrationInterface {
|
||||
name = 'AddProjectAttachments1782500000000';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "project_attachments" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "name" character varying NOT NULL, "stored_name" character varying NOT NULL, "size" integer NOT NULL, "mime" character varying NOT NULL, "kind" character varying NOT NULL, "created_at" TIMESTAMP NOT NULL DEFAULT now(), "project_id" uuid, "uploader_id" uuid, CONSTRAINT "PK_project_attachments" PRIMARY KEY ("id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_project_attachments_project" ON "project_attachments" ("project_id")`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "project_attachments" ADD CONSTRAINT "FK_project_attachments_project" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "project_attachments" ADD CONSTRAINT "FK_project_attachments_uploader" FOREIGN KEY ("uploader_id") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "project_attachments" DROP CONSTRAINT "FK_project_attachments_uploader"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "project_attachments" DROP CONSTRAINT "FK_project_attachments_project"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "project_attachments"`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user