2025-10-08 23:04:12 +09:00
const { PrismaClient } = require ( "@prisma/client" ) ;
const prisma = new PrismaClient ( ) ;
2025-10-09 11:23:27 +09:00
async function upsertRoles ( ) {
const roles = [
{ name : "admin" , description : "관리자" } ,
{ name : "editor" , description : "운영진" } ,
{ name : "user" , description : "일반 사용자" }
] ;
for ( const r of roles ) {
await prisma . role . upsert ( {
where : { name : r . name } ,
update : { description : r . description } ,
create : r ,
} ) ;
}
2025-10-09 14:37:42 +09:00
// 기본 권한 매핑
const roleMap = {
admin : [
[ "ADMIN" , "ADMINISTER" ] ,
[ "BOARD" , "MODERATE" ] ,
[ "POST" , "CREATE" ] ,
[ "POST" , "UPDATE" ] ,
[ "POST" , "DELETE" ] ,
[ "COMMENT" , "DELETE" ] ,
[ "USER" , "UPDATE" ] ,
] ,
editor : [
[ "BOARD" , "MODERATE" ] ,
[ "POST" , "UPDATE" ] ,
[ "POST" , "DELETE" ] ,
[ "COMMENT" , "DELETE" ] ,
] ,
user : [
[ "POST" , "CREATE" ] ,
[ "COMMENT" , "CREATE" ] ,
[ "POST" , "READ" ] ,
[ "COMMENT" , "READ" ] ,
] ,
} ;
for ( const [ roleName , perms ] of Object . entries ( roleMap ) ) {
const role = await prisma . role . findUnique ( { where : { name : roleName } } ) ;
if ( ! role ) continue ;
for ( const [ resource , action ] of perms ) {
await prisma . rolePermission . upsert ( {
where : {
roleId _resource _action : {
roleId : role . roleId ,
resource ,
action ,
} ,
} ,
update : { allowed : true } ,
create : { roleId : role . roleId , resource , action , allowed : true } ,
} ) ;
}
}
2025-10-09 11:23:27 +09:00
}
async function upsertAdmin ( ) {
const admin = await prisma . user . upsert ( {
where : { nickname : "admin" } ,
2025-10-08 23:04:12 +09:00
update : { } ,
create : {
2025-10-09 11:23:27 +09:00
nickname : "admin" ,
name : "Administrator" ,
2025-10-08 23:44:21 +09:00
birth : new Date ( "1990-01-01" ) ,
2025-10-09 11:23:27 +09:00
phone : "010-0000-0001" ,
agreementTermsAt : new Date ( ) ,
authLevel : "ADMIN" ,
} ,
2025-10-08 23:04:12 +09:00
} ) ;
2025-10-08 23:44:21 +09:00
2025-10-09 11:23:27 +09:00
const adminRole = await prisma . role . findUnique ( { where : { name : "admin" } } ) ;
if ( adminRole ) {
await prisma . userRole . upsert ( {
where : {
userId _roleId : { userId : admin . userId , roleId : adminRole . roleId } ,
} ,
update : { } ,
create : { userId : admin . userId , roleId : adminRole . roleId } ,
} ) ;
}
return admin ;
}
async function upsertBoards ( admin ) {
const boards = [
// 일반
2025-10-09 17:13:54 +09:00
{ name : "공지사항" , slug : "notice" , description : "공지" , type : "general" , sortOrder : 1 , writeLevel : "moderator" } ,
2025-10-09 11:23:27 +09:00
{ name : "가입인사" , slug : "greetings" , description : "가입인사" , type : "general" , sortOrder : 2 } ,
{ name : "버그건의" , slug : "bug-report" , description : "버그/건의" , type : "general" , sortOrder : 3 } ,
2025-10-09 17:13:54 +09:00
{ name : "이벤트" , slug : "event" , description : "이벤트" , type : "general" , sortOrder : 4 , requiredTags : { required : [ "이벤트" ] } } ,
2025-10-09 11:23:27 +09:00
{ name : "자유게시판" , slug : "free" , description : "자유" , type : "general" , sortOrder : 5 } ,
{ name : "무엇이든" , slug : "qna" , description : "무엇이든 물어보세요" , type : "general" , sortOrder : 6 } ,
{ name : "마사지꿀팁" , slug : "tips" , description : "팁" , type : "general" , sortOrder : 7 } ,
2025-10-09 17:13:54 +09:00
{ name : "익명게시판" , slug : "anonymous" , description : "익명" , type : "general" , sortOrder : 8 , allowAnonymousPost : true , allowSecretComment : true } ,
2025-10-09 11:23:27 +09:00
{ name : "관리사찾아요" , slug : "find-therapist" , description : "구인/구직" , type : "general" , sortOrder : 9 } ,
{ name : "청와대" , slug : "blue-house" , description : "레벨 제한" , type : "general" , sortOrder : 10 , readLevel : "member" } ,
2025-10-09 17:13:54 +09:00
{ name : "방문후기" , slug : "reviews" , description : "운영자 승인 후 공개" , type : "general" , sortOrder : 11 , requiresApproval : true , requiredTags : { anyOf : [ "업체명" , "지역" ] } } ,
2025-10-09 11:23:27 +09:00
// 특수
{ name : "출석부" , slug : "attendance" , description : "데일리 체크인" , type : "special" , sortOrder : 12 } ,
{ name : "주변 제휴업체" , slug : "nearby-partners" , description : "위치 기반" , type : "special" , sortOrder : 13 } ,
{ name : "회원랭킹" , slug : "ranking" , description : "랭킹" , type : "special" , sortOrder : 14 } ,
{ name : "무료쿠폰" , slug : "free-coupons" , description : "쿠폰" , type : "special" , sortOrder : 15 } ,
{ name : "월간집계" , slug : "monthly-stats" , description : "월간 통계" , type : "special" , sortOrder : 16 } ,
2025-10-09 17:16:27 +09:00
// 제휴업소 일반(사진)
{ name : "제휴업소 일반(사진)" , slug : "partners-photos" , description : "사진 전용 게시판" , type : "general" , sortOrder : 17 , requiredFields : { imageOnly : true , minImages : 1 , maxImages : 10 } } ,
2025-10-09 11:23:27 +09:00
] ;
const created = [ ] ;
for ( const b of boards ) {
const board = await prisma . board . upsert ( {
where : { slug : b . slug } ,
update : {
description : b . description ,
sortOrder : b . sortOrder ,
type : b . type ,
requiresApproval : ! ! b . requiresApproval ,
allowAnonymousPost : ! ! b . allowAnonymousPost ,
readLevel : b . readLevel || undefined ,
} ,
create : {
name : b . name ,
slug : b . slug ,
description : b . description ,
sortOrder : b . sortOrder ,
type : b . type ,
requiresApproval : ! ! b . requiresApproval ,
allowAnonymousPost : ! ! b . allowAnonymousPost ,
readLevel : b . readLevel || undefined ,
} ,
} ) ;
created . push ( board ) ;
// 공지/운영 보드는 관리자 모더레이터 지정
if ( [ "notice" , "bug-report" ] . includes ( board . slug ) ) {
await prisma . boardModerator . upsert ( {
where : {
boardId _userId : { boardId : board . id , userId : admin . userId } ,
} ,
update : { } ,
create : { boardId : board . id , userId : admin . userId , role : "MANAGER" } ,
} ) ;
2025-10-08 23:44:21 +09:00
}
2025-10-09 11:23:27 +09:00
}
return created ;
}
2025-10-08 23:44:21 +09:00
2025-10-09 11:23:27 +09:00
async function seedPolicies ( ) {
// 금칙어 예시
const banned = [
{ pattern : "광고" , appliesTo : "POST" , severity : 1 } ,
{ pattern : "욕설" , appliesTo : "COMMENT" , severity : 2 } ,
{ pattern : "스팸" , appliesTo : "POST" , severity : 2 } ,
] ;
for ( const k of banned ) {
await prisma . bannedKeyword . upsert ( {
where : { pattern : k . pattern } ,
update : { appliesTo : k . appliesTo , severity : k . severity , active : true } ,
create : k ,
} ) ;
}
// 레벨 임계 예시
const levels = [
{ level : 1 , minPoints : 0 } ,
{ level : 2 , minPoints : 100 } ,
{ level : 3 , minPoints : 300 } ,
] ;
for ( const l of levels ) {
await prisma . levelThreshold . upsert ( {
where : { level : l . level } ,
update : { minPoints : l . minPoints } ,
create : l ,
} ) ;
}
}
async function main ( ) {
await upsertRoles ( ) ;
const admin = await upsertAdmin ( ) ;
const boards = await upsertBoards ( admin ) ;
// 샘플 글 하나
const free = boards . find ( ( b ) => b . slug === "free" ) || boards [ 0 ] ;
2025-10-08 23:44:21 +09:00
const post = await prisma . post . create ( {
data : {
2025-10-09 11:23:27 +09:00
boardId : free . id ,
authorId : admin . userId ,
2025-10-08 23:44:21 +09:00
title : "첫 글" ,
2025-10-09 11:23:27 +09:00
content : "메시지 앱 초기 설정 완료" ,
status : "published" ,
} ,
2025-10-08 23:44:21 +09:00
} ) ;
await prisma . comment . createMany ( {
data : [
2025-10-09 11:23:27 +09:00
{ postId : post . id , authorId : admin . userId , content : "환영합니다!" } ,
{ postId : post . id , authorId : admin . userId , content : "댓글 테스트" } ,
] ,
2025-10-08 23:44:21 +09:00
} ) ;
2025-10-09 11:23:27 +09:00
await seedPolicies ( ) ;
2025-10-08 23:04:12 +09:00
}
main ( )
. catch ( ( e ) => {
console . error ( e ) ;
process . exit ( 1 ) ;
} )
. finally ( async ( ) => {
await prisma . $disconnect ( ) ;
} ) ;