diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-08-06 04:23:40 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-08-06 04:23:40 +0000 |
| commit | de2ac5a2860bc25180971e7a11f852d9d44675b7 (patch) | |
| tree | b931c363f2cb19e177a0a7b17190d5de2a82d709 /db/schema/consent.ts | |
| parent | 6c549b0f264e9be4d60af38f9efc05b189d6849f (diff) | |
(대표님) 정기평가, 법적검토, 정책, 가입관련 처리 및 관련 컴포넌트 추가, 메뉴 변경
Diffstat (limited to 'db/schema/consent.ts')
| -rw-r--r-- | db/schema/consent.ts | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/db/schema/consent.ts b/db/schema/consent.ts new file mode 100644 index 00000000..a02d5575 --- /dev/null +++ b/db/schema/consent.ts @@ -0,0 +1,138 @@ +// schema/consent.ts +import { + pgTable, + integer, + varchar, + boolean, + timestamp, + text, + json, + pgEnum, + uniqueIndex, + index, + } from "drizzle-orm/pg-core"; +import { users } from "./users"; + + // 동의 타입 enum + export const consentTypeEnum = pgEnum("consent_type", [ + "privacy_policy", + "terms_of_service", + "marketing", + "optional" + ]); + + // 동의 액션 enum + export const consentActionEnum = pgEnum("consent_action", [ + "consent", + "revoke", + "update" + ]); + + // 정책 타입 enum + export const policyTypeEnum = pgEnum("policy_type", [ + "privacy_policy", + "terms_of_service" + ]); + + // 1. 정책 버전 관리 테이블 + export const policyVersions = pgTable("policy_versions", { + id: integer("id").primaryKey().generatedAlwaysAsIdentity(), + policyType: policyTypeEnum("policy_type").notNull(), + version: varchar("version", { length: 20 }).notNull(), + content: text("content").notNull(), + effectiveDate: timestamp("effective_date", { withTimezone: true }).notNull(), + isCurrent: boolean("is_current").default(false).notNull(), + createdAt: timestamp("created_at", { withTimezone: true }) + .defaultNow() + .notNull(), + }, (table) => { + return { + // 정책 타입과 버전의 유니크 조합 + policyVersionUniqueIdx: uniqueIndex("policy_versions_type_version_idx") + .on(table.policyType, table.version), + // 현재 버전 조회용 인덱스 + currentPolicyIdx: index("policy_versions_current_idx") + .on(table.isCurrent), + // 효력 발생일 인덱스 + effectiveDateIdx: index("policy_versions_effective_date_idx") + .on(table.effectiveDate), + }; + }); + + // 2. 사용자 동의 내역 테이블 + export const userConsents = pgTable("user_consents", { + id: integer("id").primaryKey().generatedAlwaysAsIdentity(), + userId: integer("user_id") + .references(() => users.id, { onDelete: "cascade" }) + .notNull(), + consentType: consentTypeEnum("consent_type").notNull(), + consentStatus: boolean("consent_status").default(false).notNull(), + policyVersion: varchar("policy_version", { length: 20 }).notNull(), + consentedAt: timestamp("consented_at", { withTimezone: true }) + .defaultNow() + .notNull(), + ipAddress: varchar("ip_address", { length: 45 }), // IPv6 지원 + userAgent: text("user_agent"), + revokedAt: timestamp("revoked_at", { withTimezone: true }), + revokeReason: text("revoke_reason"), + createdAt: timestamp("created_at", { withTimezone: true }) + .defaultNow() + .notNull(), + updatedAt: timestamp("updated_at", { withTimezone: true }) + .defaultNow() + .notNull(), + }, (table) => { + return { + // 사용자별 동의 타입 조회용 인덱스 + userConsentTypeIdx: index("user_consents_user_type_idx") + .on(table.userId, table.consentType), + // 동의 시점 인덱스 + consentedAtIdx: index("user_consents_consented_at_idx") + .on(table.consentedAt), + // 정책 버전별 인덱스 + policyVersionIdx: index("user_consents_policy_version_idx") + .on(table.policyVersion), + }; + }); + + // 3. 동의 로그 테이블 (모든 동의/철회 이력 보관) + export const consentLogs = pgTable("consent_logs", { + id: integer("id").primaryKey().generatedAlwaysAsIdentity(), + userId: integer("user_id") + .references(() => users.id, { onDelete: "cascade" }) + .notNull(), + consentType: consentTypeEnum("consent_type").notNull(), + action: consentActionEnum("action").notNull(), + oldStatus: boolean("old_status"), + newStatus: boolean("new_status").notNull(), + policyVersion: varchar("policy_version", { length: 20 }).notNull(), + ipAddress: varchar("ip_address", { length: 45 }), + userAgent: text("user_agent"), + actionTimestamp: timestamp("action_timestamp", { withTimezone: true }) + .defaultNow() + .notNull(), + additionalData: json("additional_data"), // 추가 메타데이터 + }, (table) => { + return { + // 사용자별 액션 시간 순 조회용 인덱스 + userActionTimestampIdx: index("consent_logs_user_action_timestamp_idx") + .on(table.userId, table.actionTimestamp), + // 동의 타입별 인덱스 + consentTypeIdx: index("consent_logs_consent_type_idx") + .on(table.consentType), + // 액션 타입별 인덱스 + actionIdx: index("consent_logs_action_idx") + .on(table.action), + }; + }); + + + export type PolicyVersion = typeof policyVersions.$inferSelect; + export type NewPolicyVersion = typeof policyVersions.$inferInsert; + + export type UserConsent = typeof userConsents.$inferSelect; + export type NewUserConsent = typeof userConsents.$inferInsert; + + export type ConsentLog = typeof consentLogs.$inferSelect; + export type NewConsentLog = typeof consentLogs.$inferInsert; +
\ No newline at end of file |
