@restnfeel/agentc-starter-kit
Version:
한국어 기업용 CMS 모듈 - Task Master AI와 함께 빠르게 웹사이트를 구현할 수 있는 재사용 가능한 컴포넌트 시스템
310 lines (280 loc) • 7.4 kB
text/typescript
export enum MediaPermission {
VIEW = "view",
UPLOAD = "upload",
EDIT = "edit",
DELETE = "delete",
MANAGE_PERMISSIONS = "manage_permissions",
DOWNLOAD = "download",
SHARE = "share",
}
export enum MediaRole {
ADMIN = "admin",
EDITOR = "editor",
AUTHOR = "author",
CONTRIBUTOR = "contributor",
SUBSCRIBER = "subscriber",
GUEST = "guest",
}
export interface MediaUser {
id: string;
role: MediaRole;
permissions?: MediaPermission[];
folders?: string[]; // 접근 가능한 폴더 ID 목록
}
export interface MediaFolder {
id: string;
name: string;
parentId?: string;
ownerId: string;
permissions: MediaFolderPermission[];
inheritParentPermissions: boolean;
isPublic: boolean;
createdAt: Date;
updatedAt: Date;
}
export interface MediaFolderPermission {
id: string;
folderId: string;
userId?: string;
roleId?: MediaRole;
permissions: MediaPermission[];
allowInheritance: boolean;
createdAt: Date;
}
export interface MediaCollection {
id: string;
name: string;
description?: string;
ownerId: string;
permissions: MediaCollectionPermission[];
isPublic: boolean;
tags: string[];
createdAt: Date;
updatedAt: Date;
}
export interface MediaCollectionPermission {
id: string;
collectionId: string;
userId?: string;
roleId?: MediaRole;
permissions: MediaPermission[];
createdAt: Date;
}
// 기본 역할별 권한 매핑
export const DEFAULT_ROLE_PERMISSIONS: Record<MediaRole, MediaPermission[]> = {
[MediaRole.ADMIN]: [
MediaPermission.VIEW,
MediaPermission.UPLOAD,
MediaPermission.EDIT,
MediaPermission.DELETE,
MediaPermission.MANAGE_PERMISSIONS,
MediaPermission.DOWNLOAD,
MediaPermission.SHARE,
],
[MediaRole.EDITOR]: [
MediaPermission.VIEW,
MediaPermission.UPLOAD,
MediaPermission.EDIT,
MediaPermission.DELETE,
MediaPermission.DOWNLOAD,
MediaPermission.SHARE,
],
[MediaRole.AUTHOR]: [
MediaPermission.VIEW,
MediaPermission.UPLOAD,
MediaPermission.EDIT,
MediaPermission.DOWNLOAD,
MediaPermission.SHARE,
],
[MediaRole.CONTRIBUTOR]: [
MediaPermission.VIEW,
MediaPermission.UPLOAD,
MediaPermission.DOWNLOAD,
],
[MediaRole.SUBSCRIBER]: [MediaPermission.VIEW, MediaPermission.DOWNLOAD],
[MediaRole.GUEST]: [MediaPermission.VIEW],
};
export class MediaPermissionService {
/**
* 사용자가 특정 작업을 수행할 권한이 있는지 확인
*/
hasPermission(
user: MediaUser,
permission: MediaPermission,
context?: {
folderId?: string;
collectionId?: string;
fileId?: string;
ownerId?: string;
}
): boolean {
// 관리자는 모든 권한 보유
if (user.role === MediaRole.ADMIN) {
return true;
}
// 소유자는 MANAGE_PERMISSIONS를 제외한 모든 권한 보유
if (
context?.ownerId === user.id &&
permission !== MediaPermission.MANAGE_PERMISSIONS
) {
return true;
}
// 사용자별 직접 권한 확인
if (user.permissions?.includes(permission)) {
return true;
}
// 역할 기반 기본 권한 확인
const rolePermissions = DEFAULT_ROLE_PERMISSIONS[user.role];
if (rolePermissions.includes(permission)) {
return true;
}
// 폴더별 권한 확인
if (context?.folderId) {
return this.hasFolderPermission(user, permission, context.folderId);
}
// 컬렉션별 권한 확인
if (context?.collectionId) {
return this.hasCollectionPermission(
user,
permission,
context.collectionId
);
}
return false;
}
/**
* 폴더별 권한 확인 (상속 포함)
*/
private hasFolderPermission(
_user: MediaUser,
_permission: MediaPermission,
_folderId: string
): boolean {
// 실제 구현에서는 데이터베이스에서 폴더 권한 조회
// 여기서는 Mock 구현
return true;
}
/**
* 컬렉션별 권한 확인
*/
private hasCollectionPermission(
_user: MediaUser,
_permission: MediaPermission,
_collectionId: string
): boolean {
// 실제 구현에서는 데이터베이스에서 컬렉션 권한 조회
// 여기서는 Mock 구현
return true;
}
/**
* 사용자가 접근 가능한 폴더 목록 반환
*/
async getAccessibleFolders(_user: MediaUser): Promise<MediaFolder[]> {
// 실제 구현에서는 데이터베이스에서 조회
return [];
}
/**
* 사용자가 접근 가능한 컬렉션 목록 반환
*/
async getAccessibleCollections(_user: MediaUser): Promise<MediaCollection[]> {
// 실제 구현에서는 데이터베이스에서 조회
return [];
}
/**
* 폴더에 사용자 권한 추가
*/
async addFolderPermission(
folderId: string,
userId: string,
permissions: MediaPermission[],
grantedBy: string
): Promise<MediaFolderPermission> {
// 실제 구현에서는 데이터베이스에 저장
const permission: MediaFolderPermission = {
id: `perm_${Date.now()}`,
folderId,
userId,
permissions,
allowInheritance: true,
createdAt: new Date(),
};
// 감사 로그 기록
await this.logPermissionChange({
action: "add_folder_permission",
resourceType: "folder",
resourceId: folderId,
targetUserId: userId,
permissions,
grantedBy,
});
return permission;
}
/**
* 컬렉션에 사용자 권한 추가
*/
async addCollectionPermission(
collectionId: string,
userId: string,
permissions: MediaPermission[],
grantedBy: string
): Promise<MediaCollectionPermission> {
// 실제 구현에서는 데이터베이스에 저장
const permission: MediaCollectionPermission = {
id: `perm_${Date.now()}`,
collectionId,
userId,
permissions,
createdAt: new Date(),
};
// 감사 로그 기록
await this.logPermissionChange({
action: "add_collection_permission",
resourceType: "collection",
resourceId: collectionId,
targetUserId: userId,
permissions,
grantedBy,
});
return permission;
}
/**
* 권한 변경 사항 로깅
*/
private async logPermissionChange(data: {
action: string;
resourceType: string;
resourceId: string;
targetUserId: string;
permissions: MediaPermission[];
grantedBy: string;
}): Promise<void> {
// 감사 로그 서비스에 기록
console.log("Permission change logged:", data);
}
/**
* 폴더 권한 상속 처리
*/
async inheritFolderPermissions(
_parentFolderId: string,
_childFolderId: string
): Promise<void> {
// 부모 폴더의 권한을 자식 폴더에 상속
// 실제 구현에서는 데이터베이스 작업
}
/**
* 사용자 권한 검증 미들웨어
*/
createPermissionMiddleware(requiredPermission: MediaPermission) {
return (user: MediaUser, context?: Record<string, unknown>) => {
return this.hasPermission(user, requiredPermission, context);
};
}
}
// 싱글톤 인스턴스
let permissionServiceInstance: MediaPermissionService | null = null;
export function getMediaPermissionService(): MediaPermissionService {
if (!permissionServiceInstance) {
permissionServiceInstance = new MediaPermissionService();
}
return permissionServiceInstance;
}