docs.membloc.com

membloc docs

제품, 플랫폼, 운영 문서를 한곳에서 읽는 Membloc 공식 문서 포털입니다.

homb RBAC (Role-Based Access Control) 설계

homb 플랫폼 전체에 걸친 권한 모델을 정의한다. 플랫폼 수준, 가족 수준, 모듈 수준의 3계층 RBAC과 관리자 인터페이스 방향을 설계한다.


1. 현재 상태 (As-Is)

영역현재문제
플랫폼없음시스템 관리자 구분 불가, 퍼블리셔도 일반 유저와 동일
가족owner/member (DB), UI에 admin/viewer label만 존재실제 권한 분기 없음 (canRunActivityBackfill 정도)
모듈ModuleInstall.permissions 필드만 존재누가 설치/설정 변경할 수 있는지 강제 안 됨
관리자없음Firestore 콘솔에서 수동 관리

2. RBAC 3계층 모델

┌─────────────────────────────────────────────────────┐
│ Layer 1: Platform Role (시스템 전체)                  │
│                                                      │
│  super_admin ─ admin ─ support ─ publisher ─ user    │
│                                                      │
├─────────────────────────────────────────────────────┤
│ Layer 2: Family Role (가족 내)                        │
│                                                      │
│  owner ─ admin ─ member ─ viewer                     │
│                                                      │
├─────────────────────────────────────────────────────┤
│ Layer 3: Module Permission (모듈별)                   │
│                                                      │
│  module.install ─ module.configure ─ module.use      │
│                                                      │
└─────────────────────────────────────────────────────┘

2.1 Layer 1: Platform Role

시스템 전체에 걸친 역할. 모든 사용자는 정확히 하나의 platform role을 가진다.

Role설명권한
super_admin최고 관리자 (1~2명)모든 권한 + admin 역할 부여/해제
admin플랫폼 관리자사용자 관리, 모듈 심사, 퍼블리셔 승인, 통계
support고객 지원사용자 조회, 가족 조회, 신고 처리 (읽기 + 제한된 쓰기)
publisher모듈 퍼블리셔자기 모듈 관리, API 키 발급, 분석
user일반 사용자앱 기본 기능, 모듈 사용

Platform Role 권한 매트릭스:

                          super_admin  admin  support  publisher  user
─────────────────────────────────────────────────────────────────────
사용자 목록/조회              ✅         ✅     ✅        ❌       ❌
사용자 역할 변경              ✅         ✅     ❌        ❌       ❌
사용자 정지/해제              ✅         ✅     ❌        ❌       ❌
admin 역할 부여               ✅         ❌     ❌        ❌       ❌

가족 목록/조회                ✅         ✅     ✅        ❌       ❌
가족 강제 삭제                ✅         ✅     ❌        ❌       ❌

모듈 심사 (승인/반려)         ✅         ✅     ❌        ❌       ❌
모듈 강제 정지                ✅         ✅     ❌        ❌       ❌
모듈 등록/수정 (자기 것)      ✅         ✅     ❌        ✅       ❌

퍼블리셔 승인/반려            ✅         ✅     ❌        ❌       ❌
퍼블리셔 등록                 ✅         ✅     ❌        ✅(자기) ❌

플랫폼 통계 조회              ✅         ✅     ✅        ❌       ❌
시스템 설정 변경              ✅         ❌     ❌        ❌       ❌

신고 목록/처리                ✅         ✅     ✅        ❌       ❌
신고 접수                     ✅         ✅     ✅        ✅       ✅

2.2 Layer 2: Family Role

가족(그룹) 내 역할. 사용자는 가족마다 다른 역할을 가질 수 있다.

Role설명권한
owner가족 생성자/관리자모든 권한 + 가족 삭제 + 역할 변경 + 초대 코드 관리
admin운영진모듈 설치/제거, 멤버 초대, 채널 관리, 설정 변경
member일반 구성원모듈 사용, 채널 참여, 콘텐츠 생성
viewer보기 전용콘텐츠 조회만 가능 (어린 자녀, 게스트 등)

Family Role 권한 매트릭스:

                          owner  admin  member  viewer
──────────────────────────────────────────────────────
가족 정보 수정               ✅     ✅     ❌      ❌
가족 삭제                    ✅     ❌     ❌      ❌
초대 코드 관리               ✅     ✅     ❌      ❌
멤버 초대                    ✅     ✅     ❌      ❌
멤버 역할 변경               ✅     ❌     ❌      ❌
멤버 강퇴                    ✅     ✅*    ❌      ❌

모듈 설치/제거               ✅     ✅     ❌      ❌
모듈 설정 변경               ✅     ✅     ❌      ❌
모듈 사용                    ✅     ✅     ✅      ❌
모듈 데이터 조회             ✅     ✅     ✅      ✅

채널 생성/삭제               ✅     ✅     ❌      ❌
채널 메시지 전송             ✅     ✅     ✅      ❌
채널 메시지 조회             ✅     ✅     ✅      ✅

추억/아카이브 생성           ✅     ✅     ✅      ❌
추억/아카이브 조회           ✅     ✅     ✅      ✅
추억/아카이브 삭제           ✅     ✅     자기것   ❌

캘린더 이벤트 생성           ✅     ✅     ✅      ❌
캘린더 이벤트 조회           ✅     ✅     ✅      ✅

*admin은 member/viewer만 강퇴 가능 (다른 admin 불가)

2.3 Layer 3: Module Permission

모듈이 요청하는 권한. 설치 시 가족 admin 이상이 동의.

Permission설명체크 주체
family.read가족 기본 정보Runtime API 미들웨어
members.read멤버 목록Runtime API 미들웨어
storage.write파일 업로드Runtime API 미들웨어
notifications.send알림 전송Runtime API 미들웨어
activity.write피드 게시Runtime API 미들웨어
calendar.read/write캘린더 접근Runtime API 미들웨어
channel.share채널 공유Runtime API 미들웨어

이 권한은 모듈 설치 시점에 결정되며, 가족의 admin+ 역할만 승인할 수 있다.


3. 데이터 모델

3.1 DB 스키마

-- ============================================
-- Platform Role (시스템 수준)
-- ============================================

-- 플랫폼 역할 정의
CREATE TABLE platform_roles (
    role        TEXT PRIMARY KEY,  -- super_admin, admin, support, publisher, user
    description TEXT NOT NULL,
    sort_order  INTEGER NOT NULL DEFAULT 0
);

INSERT INTO platform_roles (role, description, sort_order) VALUES
    ('super_admin', '최고 관리자', 1),
    ('admin',       '플랫폼 관리자', 2),
    ('support',     '고객 지원', 3),
    ('publisher',   '모듈 퍼블리셔', 4),
    ('user',        '일반 사용자', 5);

-- 플랫폼 역할에 부여된 권한
CREATE TABLE platform_role_permissions (
    role        TEXT NOT NULL REFERENCES platform_roles(role),
    permission  TEXT NOT NULL,
    PRIMARY KEY (role, permission)
);

-- 권한 목록 시드
INSERT INTO platform_role_permissions (role, permission) VALUES
    -- super_admin: 모든 권한
    ('super_admin', 'users.list'),
    ('super_admin', 'users.read'),
    ('super_admin', 'users.update_role'),
    ('super_admin', 'users.suspend'),
    ('super_admin', 'users.grant_admin'),
    ('super_admin', 'families.list'),
    ('super_admin', 'families.read'),
    ('super_admin', 'families.delete'),
    ('super_admin', 'modules.review'),
    ('super_admin', 'modules.suspend'),
    ('super_admin', 'publishers.approve'),
    ('super_admin', 'platform.stats'),
    ('super_admin', 'platform.settings'),
    ('super_admin', 'reports.manage'),

    -- admin: super_admin에서 grant_admin, platform.settings 제외
    ('admin', 'users.list'),
    ('admin', 'users.read'),
    ('admin', 'users.update_role'),
    ('admin', 'users.suspend'),
    ('admin', 'families.list'),
    ('admin', 'families.read'),
    ('admin', 'families.delete'),
    ('admin', 'modules.review'),
    ('admin', 'modules.suspend'),
    ('admin', 'publishers.approve'),
    ('admin', 'platform.stats'),
    ('admin', 'reports.manage'),

    -- support
    ('support', 'users.list'),
    ('support', 'users.read'),
    ('support', 'families.list'),
    ('support', 'families.read'),
    ('support', 'platform.stats'),
    ('support', 'reports.manage'),

    -- publisher
    ('publisher', 'modules.own.manage'),
    ('publisher', 'publisher.own.manage'),
    ('publisher', 'reports.submit'),

    -- user
    ('user', 'reports.submit');

-- 사용자-플랫폼 역할 매핑 (users 테이블 확장)
ALTER TABLE users ADD COLUMN platform_role TEXT NOT NULL DEFAULT 'user'
    REFERENCES platform_roles(role);

CREATE INDEX idx_users_platform_role ON users(platform_role);

-- ============================================
-- Family Role (가족 수준) — 기존 family_members 확장
-- ============================================

-- family_members.role 이미 존재하지만 CHECK 제약조건 추가
-- (마이그레이션 시 기존 데이터 호환 확인 필요)
-- ALTER TABLE family_members
--     ADD CONSTRAINT chk_family_member_role
--     CHECK (role IN ('owner', 'admin', 'member', 'viewer'));

-- 가족 역할별 권한
CREATE TABLE family_role_permissions (
    role        TEXT NOT NULL,  -- owner, admin, member, viewer
    permission  TEXT NOT NULL,
    PRIMARY KEY (role, permission)
);

INSERT INTO family_role_permissions (role, permission) VALUES
    -- owner
    ('owner', 'family.update'),
    ('owner', 'family.delete'),
    ('owner', 'family.invite'),
    ('owner', 'family.manage_invite'),
    ('owner', 'family.kick_member'),
    ('owner', 'family.change_role'),
    ('owner', 'module.install'),
    ('owner', 'module.uninstall'),
    ('owner', 'module.configure'),
    ('owner', 'module.use'),
    ('owner', 'channel.create'),
    ('owner', 'channel.delete'),
    ('owner', 'channel.write'),
    ('owner', 'channel.read'),
    ('owner', 'content.create'),
    ('owner', 'content.read'),
    ('owner', 'content.delete_any'),
    ('owner', 'calendar.write'),
    ('owner', 'calendar.read'),

    -- admin
    ('admin', 'family.update'),
    ('admin', 'family.invite'),
    ('admin', 'family.manage_invite'),
    ('admin', 'family.kick_member'),
    ('admin', 'module.install'),
    ('admin', 'module.uninstall'),
    ('admin', 'module.configure'),
    ('admin', 'module.use'),
    ('admin', 'channel.create'),
    ('admin', 'channel.delete'),
    ('admin', 'channel.write'),
    ('admin', 'channel.read'),
    ('admin', 'content.create'),
    ('admin', 'content.read'),
    ('admin', 'content.delete_own'),
    ('admin', 'calendar.write'),
    ('admin', 'calendar.read'),

    -- member
    ('member', 'module.use'),
    ('member', 'channel.write'),
    ('member', 'channel.read'),
    ('member', 'content.create'),
    ('member', 'content.read'),
    ('member', 'content.delete_own'),
    ('member', 'calendar.write'),
    ('member', 'calendar.read'),

    -- viewer
    ('viewer', 'channel.read'),
    ('viewer', 'content.read'),
    ('viewer', 'calendar.read');

-- ============================================
-- 감사 로그
-- ============================================
CREATE TABLE audit_logs (
    id          TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
    actor_uid   TEXT NOT NULL,
    action      TEXT NOT NULL,       -- e.g. 'user.role_changed', 'module.approved'
    target_type TEXT NOT NULL,       -- e.g. 'user', 'family', 'module'
    target_id   TEXT NOT NULL,
    details     JSONB DEFAULT '{}',  -- 변경 전/후 데이터
    ip_address  TEXT,
    created_at  TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX idx_audit_logs_actor ON audit_logs(actor_uid);
CREATE INDEX idx_audit_logs_target ON audit_logs(target_type, target_id);
CREATE INDEX idx_audit_logs_action ON audit_logs(action);
CREATE INDEX idx_audit_logs_created ON audit_logs(created_at);

3.2 권한 체크 흐름

요청 수신
  │
  ▼
[1] Firebase Auth 토큰 검증 → UID 추출
  │
  ▼
[2] Platform Role 조회 (users.platform_role)
  │
  ├── platform 수준 API? ─▶ platform_role_permissions 확인
  │
  ▼
[3] Family Role 조회 (family_members WHERE uid = :uid AND family_id = :fid)
  │
  ├── family 수준 API? ─▶ family_role_permissions 확인
  │
  ▼
[4] Module Permission 확인 (module_installations.settings.permissions)
  │
  └── module runtime API? ─▶ 설치 시 승인된 permissions 확인

4. 백엔드 구현

4.1 RBAC 미들웨어

// internal/auth/rbac.go

// RequirePlatformPermission — 플랫폼 권한 체크 미들웨어
func RequirePlatformPermission(db *pgxpool.Pool, permission string) echo.MiddlewareFunc

// RequireFamilyPermission — 가족 권한 체크 미들웨어
func RequireFamilyPermission(db *pgxpool.Pool, permission string) echo.MiddlewareFunc

// 사용 예시:
// admin.GET("/users", userHandler.List,
//     auth.RequirePlatformPermission(pool, "users.list"))
//
// api.POST("/families/:familyId/modules/:key/install", moduleInstallHandler.Install,
//     auth.RequireFamilyPermission(pool, "module.install"))

4.2 적용 예시

// cmd/server/main.go

// Public
e.GET("/health", healthHandler.Check)
e.GET("/api/marketplace/modules", marketplaceHandler.ListModules)
e.GET("/api/marketplace/modules/:key", marketplaceHandler.GetModule)
e.GET("/api/marketplace/categories", marketplaceHandler.ListCategories)

// Authenticated (모든 로그인 사용자)
api := e.Group("/api", auth.Middleware(fbAuth))
api.POST("/families", familyHandler.Create)
api.POST("/families/join", familyHandler.Join)
api.GET("/families/:id", familyHandler.Get)

// Family-scoped (가족 역할 필요)
api.POST("/families/:familyId/modules/:key/install", moduleInstallHandler.Install,
    auth.RequireFamilyPermission(pool, "module.install"))
api.POST("/families/:familyId/modules/:key/uninstall", moduleInstallHandler.Uninstall,
    auth.RequireFamilyPermission(pool, "module.uninstall"))
api.GET("/families/:familyId/modules", moduleInstallHandler.ListInstalled)

// Admin (플랫폼 관리자)
admin := api.Group("/admin")
admin.Use(auth.RequirePlatformRole(pool, "admin", "super_admin"))
admin.GET("/users", adminHandler.ListUsers)
admin.PUT("/users/:uid/role", adminHandler.UpdateUserRole)
admin.GET("/modules/pending", adminHandler.ListPendingModules)
admin.POST("/modules/:key/approve", adminHandler.ApproveModule)
admin.POST("/modules/:key/reject", adminHandler.RejectModule)
admin.GET("/stats", adminHandler.GetPlatformStats)

5. 관리자 인터페이스 — 어디에 만들 것인가?

5.1 선택지 비교

선택지장점단점
A. membloc-app 내 관리자 섹션별도 앱 불필요, 공유 코드앱 번들 크기 증가, 일반 사용자에게 노출 위험, 관리 기능은 데스크톱이 편함
B. 별도 관리자 Flutter 앱모바일에서 긴급 대응 가능두 개 앱 유지보수, Flutter 웹으로도 가능하지만 관리 도구에는 과한 스택
C. 별도 웹 관리자 대시보드데스크톱 UX 최적, Phase 3 Publisher Portal과 통합 가능웹 프로젝트 하나 더 필요
D. Publisher Portal에 Admin 섹션 통합하나의 웹 프로젝트로 관리, 역할에 따라 다른 화면퍼블리셔와 관리자 관심사 혼재 가능

5.2 권장: D안 — Publisher Portal에 Admin 통합

developer.membloc.com
├── / ────────────────── 랜딩 (문서 + 시작하기)
├── /login ───────────── Firebase Auth 로그인
│
├── [platform_role = publisher 이상]
│   ├── /dashboard ───── 퍼블리셔 대시보드
│   ├── /modules ──────── 내 모듈 관리
│   └── /settings ─────── 퍼블리셔 설정
│
├── [platform_role = support 이상]
│   ├── /admin ──────────── 관리자 대시보드
│   ├── /admin/users ────── 사용자 관리
│   ├── /admin/families ─── 가족 관리
│   └── /admin/reports ──── 신고 관리
│
├── [platform_role = admin 이상]
│   ├── /admin/modules ──── 모듈 심사
│   ├── /admin/publishers ─ 퍼블리셔 관리
│   └── /admin/stats ────── 플랫폼 통계
│
└── [platform_role = super_admin]
    ├── /admin/roles ──────── 역할 관리
    └── /admin/system ─────── 시스템 설정

이유:

  1. 하나의 웹 프로젝트 — Phase 3에서 어차피 developer.membloc.com을 만들어야 함
  2. 역할 기반 라우팅 — 로그인한 사용자의 platform_role에 따라 메뉴가 달라짐
  3. 코드 공유 — 모듈 관리 UI는 퍼블리셔와 관리자가 거의 동일 (권한만 다름)
  4. 긴급 모바일 대응 — 반응형 웹이면 모바일 브라우저에서도 사용 가능

5.3 그래도 관리자 앱이 필요한 경우

membloc-app 내에 경량 관리자 모드를 추가:

// platform_role이 admin 이상이면 설정에 "관리자 모드" 토글 표시
// 활성화 시 → 간단한 관리 기능 노출:
//   - 신고 알림 + 즉시 처리 (모듈 정지)
//   - 긴급 사용자 정지
//   - push 알림으로 심사 요청 수신

// 별도 앱은 불필요 — 웹 대시보드 + 앱 내 경량 모드로 충분

6. Flutter 앱 변경

6.1 현재 코드 영향 분석

파일변경 내용
group_membership.dart변경 없음 (이미 role 필드 있음)
settings_dialogs.dartroleLabel() — 이미 owner/admin/viewer 처리, 변경 불필요
settings_screen.dartcanRunActivityBackfill() 같은 권한 체크를 RBAC 기반으로 전환
family_service.dart역할 변경 API 호출 추가
module_hub_screen.dart설치 버튼에 module.install 권한 체크 추가
신규 rbac_service.dart백엔드에서 권한 캐시 + 체크 유틸

6.2 RBAC Service (Flutter)

// core/services/rbac_service.dart

class RbacService {
  // 현재 사용자의 platform_role (로그인 시 fetch + 캐시)
  String get platformRole => _platformRole;

  // 특정 가족에서의 역할
  String getFamilyRole(String familyId) => _familyRoles[familyId] ?? 'member';

  // 가족 내 권한 체크
  bool hasFamilyPermission(String familyId, String permission);

  // 플랫폼 권한 체크
  bool hasPlatformPermission(String permission);

  // 관리자인지 확인
  bool get isAdmin => ['super_admin', 'admin'].contains(_platformRole);
  bool get isSupport => ['super_admin', 'admin', 'support'].contains(_platformRole);
}

// 사용 예시:
// if (rbacService.hasFamilyPermission(groupId, 'module.install')) {
//   showInstallButton();
// }

7. 구현 로드맵

7.1 Phase 1.5 (현재 시점에 추가)

Platform Role + Family Role 강제를 백엔드에 구현. 기존 Phase 1 (마켓플레이스)과 병행 가능.

#작업예상
1DB 마이그레이션 (004_rbac.up.sql)0.5d
2users.platform_role 컬럼 추가 + 기존 사용자 'user'로 초기화0.5d
3internal/auth/rbac.go — 미들웨어 구현1d
4internal/handler/admin.go — 관리자 API (사용자/모듈/통계)2d
5internal/service/admin.go — 관리자 비즈니스 로직1d
6main.go admin 라우트 등록0.5d
7기존 모듈 설치 API에 family role 체크 적용0.5d
8감사 로그 기록1d
9Flutter RbacService 구현1d
10Flutter UI 권한 분기 (설치 버튼, 설정 등)1d

7.2 Phase 3에 통합

Publisher Portal 웹 개발 시 Admin 섹션을 함께 구현.

#작업예상
1Next.js 프로젝트에 admin 라우트 그룹 추가0.5d
2역할 기반 사이드바/메뉴0.5d
3사용자 관리 페이지1d
4가족 관리 페이지1d
5모듈 심사 페이지1d
6플랫폼 통계 대시보드1d
7신고 관리 페이지1d
8감사 로그 뷰어0.5d

8. 보안 고려사항

항목대책
역할 상승 공격super_admin만 admin 부여 가능, API에서 이중 체크
토큰 변조Firebase Auth 토큰의 UID로 DB 조회, 토큰 자체에 역할 넣지 않음
감사 추적모든 역할 변경/관리 행위를 audit_logs에 기록
Rate Limitingadmin API도 rate limit 적용 (DDoS 방지)
IP 제한super_admin API는 IP 화이트리스트 적용 가능 (향후)
세션 관리역할 변경 즉시 반영 (토큰 캐시가 아닌 DB 실시간 조회)

9. 결론

결정내용
RBAC 모델3계층 (Platform → Family → Module)
Platform Rolesuper_admin, admin, support, publisher, user
Family Roleowner, admin, member, viewer (기존 확장)
관리자 앱별도 앱 불필요developer.membloc.com 웹에 Admin 섹션 통합
긴급 대응membloc-app 설정에 경량 관리자 모드 (platform_role 기반 노출)
구현 시점Phase 1.5로 백엔드 RBAC 즉시 구현, Phase 3에서 Admin UI 구축