@restnfeel/agentc-starter-kit
Version:
한국어 기업용 CMS 모듈 - Task Master AI와 함께 빠르게 웹사이트를 구현할 수 있는 재사용 가능한 컴포넌트 시스템
212 lines (188 loc) • 6.05 kB
text/typescript
import { NextRequest, NextResponse } from "next/server";
import { getServerSession } from "next-auth";
import { authOptions } from "../../../../lib/auth";
import {
UserRole,
Permission,
PermissionChecker,
getUserPermissions,
} from "../../../../lib/auth/roles";
import { sendInvitationEmail } from "../../../../lib/email/invitation";
import { generateInviteToken } from "../../../../lib/auth/tokens";
interface InviteUserRequest {
email: string;
role: UserRole;
siteIds?: string[];
message?: string;
}
export async function POST(request: NextRequest) {
try {
const session = await getServerSession(authOptions);
if (!session?.user) {
return NextResponse.json(
{ error: "인증이 필요합니다." },
{ status: 401 }
);
}
// Check if user has permission to invite users
const userPermissions = getUserPermissions(
(session.user as any).role as UserRole,
(session.user as any).siteIds
);
const permissionChecker = new PermissionChecker(userPermissions);
if (!permissionChecker.hasPermission(Permission.INVITE_USER)) {
return NextResponse.json(
{ error: "사용자 초대 권한이 없습니다." },
{ status: 403 }
);
}
const body: InviteUserRequest = await request.json();
const { email, role, siteIds, message } = body;
// Validate required fields
if (!email || !role) {
return NextResponse.json(
{ error: "이메일과 역할은 필수입니다." },
{ status: 400 }
);
}
// Validate email format
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
return NextResponse.json(
{ error: "유효한 이메일 주소를 입력해주세요." },
{ status: 400 }
);
}
// Validate role
if (!Object.values(UserRole).includes(role)) {
return NextResponse.json(
{ error: "유효하지 않은 역할입니다." },
{ status: 400 }
);
}
// Check if user can assign this role
if (
role === UserRole.SUPER_ADMIN &&
(session.user as any).role !== UserRole.SUPER_ADMIN
) {
return NextResponse.json(
{ error: "슈퍼 관리자 역할은 슈퍼 관리자만 할당할 수 있습니다." },
{ status: 403 }
);
}
// Validate site access for site-specific roles
if (siteIds && siteIds.length > 0) {
const accessibleSites = permissionChecker.getAccessibleSites();
if (accessibleSites.length > 0) {
// If not super admin
const invalidSites = siteIds.filter(
(siteId) => !accessibleSites.includes(siteId)
);
if (invalidSites.length > 0) {
return NextResponse.json(
{
error: `다음 사이트에 대한 접근 권한이 없습니다: ${invalidSites.join(
", "
)}`,
},
{ status: 403 }
);
}
}
}
// Check if user already exists
// This would typically check your user database
// For now, we'll assume the user doesn't exist
// Generate invitation token
const inviteToken = generateInviteToken({
email,
role,
siteIds,
invitedBy: (session.user as any).id,
expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days
});
// Store invitation in database
// This would typically save to your database
// For now, we'll simulate this
// Send invitation email
try {
await sendInvitationEmail({
to: email,
inviteToken,
invitedBy: session.user.name || session.user.email || "관리자",
role,
siteIds,
message,
});
} catch (emailError) {
console.error("Failed to send invitation email:", emailError);
return NextResponse.json(
{ error: "초대 이메일 발송에 실패했습니다." },
{ status: 500 }
);
}
return NextResponse.json({
message: "사용자 초대가 성공적으로 발송되었습니다.",
invitation: {
email,
role,
siteIds,
invitedBy: session.user.name || session.user.email,
invitedAt: new Date().toISOString(),
},
});
} catch (error) {
console.error("User invitation error:", error);
return NextResponse.json(
{ error: "사용자 초대 중 오류가 발생했습니다." },
{ status: 500 }
);
}
}
export async function GET(_request: NextRequest) {
try {
const session = await getServerSession(authOptions);
if (!session?.user) {
return NextResponse.json(
{ error: "인증이 필요합니다." },
{ status: 401 }
);
}
// Check if user has permission to view users
const userPermissions = getUserPermissions(
(session.user as any).role as UserRole,
(session.user as any).siteIds
);
const permissionChecker = new PermissionChecker(userPermissions);
if (!permissionChecker.hasPermission(Permission.VIEW_USERS)) {
return NextResponse.json(
{ error: "사용자 조회 권한이 없습니다." },
{ status: 403 }
);
}
// Get pending invitations
// This would typically query your database for pending invitations
// For now, we'll return a mock response
const pendingInvitations = [
{
id: "1",
email: "user@example.com",
role: UserRole.EDITOR,
siteIds: ["site1", "site2"],
invitedBy: session.user.name || session.user.email,
invitedAt: new Date().toISOString(),
expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
status: "pending",
},
];
return NextResponse.json({
invitations: pendingInvitations,
});
} catch (error) {
console.error("Get invitations error:", error);
return NextResponse.json(
{ error: "초대 목록 조회 중 오류가 발생했습니다." },
{ status: 500 }
);
}
}