memi-board 0.37.2 → 0.38.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -440,11 +440,12 @@ const router = useRouter()
440
440
 
441
441
  | 동작 | 조건 |
442
442
  |------|------|
443
- | 글/댓글 읽기 | 공개 |
444
- | 글 작성 | 로그인 + 카테고리 `writeRole` 충족 + `moderationStatus == 'approved'` |
445
- | 댓글 작성 | 로그인 + `moderationStatus == 'approved'` (클라가 항상 approved 로 씀 — 검열 통과 후에만 write) |
446
- | 글 수정·삭제 | 작성자 또는 `memiBoardUsers/{uid}.role in ['admin', 'staff']` |
447
- | 댓글 삭제 | 댓글 작성자 · 글 작성자 · admin · staff |
443
+ | 글 읽기 | 공개(`listed`·게시됨) 또는 작성자·관리자·담당 스태프. 숨김 보드는 작성자·관리자·담당 스태프만 |
444
+ | 댓글 읽기 | 공개(`listed`) 또는 작성자·관리자·담당 스태프·부모 글을 읽을 수 있는 사람 |
445
+ | 글 작성 | 로그인 + 보드 `writeRole` 충족 + `moderationStatus == 'approved'` |
446
+ | 댓글 작성 | 로그인 + 보드 `commentWriteRole` 충족. **숨김 보드는 담당 스태프만** (`commentWriteRole` 무시) |
447
+ | 글 수정·삭제 | 작성자 또는 해당 보드 관리자·담당 스태프 |
448
+ | 댓글 삭제 | 댓글 작성자 · 글 작성자 · 해당 보드 관리자·담당 스태프 |
448
449
  | 역할 관리 | `MemiBoardUsers`에서 admin이 `admin`·`staff`·`user` 변경 |
449
450
 
450
451
  **알려진 한계:** AI 검열은 클라이언트 전용. SDK로 직접 write 하면 우회 가능. 중요 서비스면 Cloud Functions 검증을 호스트가 추가(패키지 범위 밖).
@@ -547,6 +548,22 @@ App Check 토큰, `appId` 일치, 모델명(3.x), AI Logic 활성화, 네트워
547
548
  3. 호스트 `storage.rules`에 `docs/storage.rules.example`의 `memiBoardPosts/{postId}/images` 규칙이 있는지 확인. 쓰기는 `image/*` 이어야 한다(붙여넣기 PNG).
548
549
  4. `firebase deploy --only storage` 후 다시 올려 본다.
549
550
 
551
+ ### 글 삭제 `storage/unauthorized`
552
+
553
+ 작성자 본인 글 삭제가 `User does not have permission to access 'memiBoardPosts/{postId}'` 로 실패하면, 파일 삭제가 아니라 **폴더 목록(`listAll`)** 이 막힌 것이다.
554
+
555
+ 요청은 `prefix=memiBoardPosts/{postId}/`(끝 슬래시)다. `match /memiBoardPosts/{postId} { allow list }` 만 있으면 이 접두사와 안 맞는다. 호스트 `storage.rules`에 예시와 같은 블록이 있어야 한다.
556
+
557
+ ```
558
+ match /memiBoardPosts/{postId}/{allPaths=**} {
559
+ allow list, get: if true;
560
+ allow delete: if isSignedIn()
561
+ && (!postExists(postId) || isPostOwner(postId) || isBoardStaff());
562
+ }
563
+ ```
564
+
565
+ `write` 는 이 블록에 넣지 않는다(용량·`image/*` 제한은 `images`/`attachments` match 가 담당). `firebase deploy --only storage` 후 다시 삭제한다. 0.38.1+ 패키지는 `images/`·`attachments/`만 목록으로 비운다.
566
+
550
567
  ### monorepo `link:` / `file:` 로 개발할 때
551
568
 
552
569
  링크하기 전에 패키지 의존성과 `dist`를 준비한다.
@@ -2,7 +2,8 @@ import { MaybeRefOrGetter } from 'vue';
2
2
  import { CommentModel } from '../types';
3
3
  export type CommentFeedSort = 'latest' | 'likes';
4
4
  /**
5
- * 보드를 가로질러 댓글을 모은다. 최신순은 createdAt, 좋아요순은 likeCount.
5
+ * 보드를 가로질러 공개(listed) 댓글만 모은다. 숨김 보드 댓글은 제외.
6
+ * 최신순은 createdAt, 좋아요순은 likeCount.
6
7
  * likeCount 가 없는 예전 댓글은 좋아요순 쿼리에 나오지 않는다(표시 시 0).
7
8
  */
8
9
  export declare function useMemiBoardCommentFeed(sort?: MaybeRefOrGetter<CommentFeedSort>, options?: {
@@ -34,6 +34,7 @@ export declare function useMemiBoardReplies(boardId: string, postId: string, roo
34
34
  id?: string | undefined;
35
35
  postId: string;
36
36
  boardId: string;
37
+ listed?: boolean | undefined;
37
38
  body: string;
38
39
  authorUid: string;
39
40
  authorName: string | null;
@@ -95,6 +96,7 @@ export declare function useMemiBoardReplies(boardId: string, postId: string, roo
95
96
  id?: string | undefined;
96
97
  postId: string;
97
98
  boardId: string;
99
+ listed?: boolean | undefined;
98
100
  body: string;
99
101
  authorUid: string;
100
102
  authorName: string | null;
@@ -1,11 +1,8 @@
1
1
  import { MaybeRefOrGetter } from 'vue';
2
2
  import { CommentModel } from '../types';
3
3
  /**
4
- * 작성자 uid로 모든 보드를 가로질러 댓글을 모은다. memiBoardComments 읽기 규칙이
5
- * 더 이상 부모 글을 get()하지 않고 항상 허용이라(누구나 볼 수 있어야 하는 요구사항),
6
- * useMemiBoardUserPosts와 동일하게 authorUid 동등 필터만으로 충분하다 — 부모 글이
7
- * 비공개·삭제·블라인드 상태여도 댓글 자체는 여기서 그대로 보이고, 실제 글로
8
- * 이동했을 때 그 글의 접근 상태에 따라 표현하는 건 호스트(클릭 시 이동하는 페이지)의 몫이다.
4
+ * 작성자 uid로 모든 보드를 가로질러 공개(listed) 댓글만 모은다.
5
+ * 숨김 보드 댓글은 글 상세에서 글 읽기 권한이 있는 사람만 본다.
9
6
  */
10
7
  export declare function useMemiBoardUserComments(uid: MaybeRefOrGetter<string>, options?: {
11
8
  pageSize?: number;
package/dist/index.d.ts CHANGED
@@ -24,7 +24,7 @@ export { REPORT_DETAIL_MAX_LENGTH, REPORT_REASONS, reportReasonLabel, useMemiBoa
24
24
  export { useMemiBoardViews } from './composables/useMemiBoardViews';
25
25
  export { useMemiBoardModeration } from './composables/useMemiBoardModeration';
26
26
  export { useMemiBoardSettings, DEFAULT_CATEGORIES, DEFAULT_BOARDS } from './composables/useMemiBoardSettings';
27
- export { canManageBoardByRole, isAssignedStaff } from './utils/boardAccess';
27
+ export { canManageBoardByRole, canWriteCommentByRole, isAssignedStaff } from './utils/boardAccess';
28
28
  export { useMemiBoardUsers, BOARD_USER_ROLES } from './composables/useMemiBoardUsers';
29
29
  export { useMemiBoardUserProfile } from './composables/useMemiBoardUserProfile';
30
30
  export { useMemiBoardSections, normalizeBoardSection } from './composables/useMemiBoardSections';