ServiceUserRole

ServiceUserRole은 제품에 가입한 end-user, 곧 ServiceUser에게 주는 권한 묶음입니다. Content Type·Content·Media에 대해 무엇을(읽기·생성·편집·삭제·발행) 할 수 있는지, Script를 실행할 수 있는지, 그리고 어떤 Content Type만, 자기가 만든 것만 등으로 범위를 좁히는 필터를 한 리소스에 담습니다. 이 권한은 ServiceUser가 호출하는 ACMA/ACDA에 적용됩니다.

ServiceUserRoleSpaceRole과 쓰이는 자리가 다릅니다. SpaceRole은 Weegloo User(콘텐츠 스튜디오 사용자)의 권한 묶음으로 CMA/CDA에 적용되고, ServiceUserRole은 제품에 가입한 ServiceUser의 권한 묶음으로 ACMA/ACDA에 적용됩니다. 만든 ServiceUserRole은 그 자체로는 아무에게도 적용되지 않습니다. ServiceLogin의 기본 역할(defaultRole)에 지정하거나 ServiceUserroleOverride에 바인딩해 부여합니다.

리소스 구조

다음은 ServiceUserRole "구매자"의 단일 조회 응답입니다. sys(시스템 속성)와 함께, 권한을 정하는 본문 속성 contentType·content·media·script를 가집니다.

{
  "sys": {
    "id": "3trmXRLXeZN2RTHvVj3hFDN5546vbp",
    "type": "ServiceUserRole",
    "space": { "sys": { "id": "HnQ32YiH", "type": "Refer", "targetType": "Space" } },
    "createdBy": { "sys": { "id": "3p4tcFbQRwz503VXdtHXNI5dZH5TVB", "type": "Refer", "targetType": "User" } },
    "createdAt": "2026-06-18T12:40:36.944Z",
    "updatedBy": { "sys": { "id": "3p4tcFbQRwz503VXdtHXNI5dZH5TVB", "type": "Refer", "targetType": "User" } },
    "updatedAt": "2026-06-18T12:40:36.944Z",
    "version": 1
  },
  "name": "구매자",
  "description": "발행된 상품을 읽을 수 있는 회원",
  "contentType": { "All": { "Allow": [] } },
  "content": {
    "Read": {
      "Allow": [
        { "contentType": { "sys": { "id": "3trmXRLdJF4GBlAjtcuoZ7Pnxj8dlA", "type": "Refer", "targetType": "ContentType" } } }
      ]
    }
  },
  "media": { "All": { "Allow": [] } },
  "script": {}
}

주요 키:

  • contentType: Content Type 자체(스키마)에 대한 권한 맵입니다. Content Type을 읽고, 만들고, 고치고, 삭제하고, 발행하는 권한을 액션별로 정합니다.
  • content: Content(콘텐츠 데이터)에 대한 권한 맵입니다. 위 예시는 특정 Content TypeContent만 읽도록 한정한 모습입니다.
  • media: Media(파일·이미지)에 대한 권한 맵입니다.
  • script: Script(선언형 백엔드 엔드포인트)에 대한 권한 맵입니다. ServiceUserScript를 실행(Execute)만 하므로 보통 Execute만 둡니다.

SpaceRole과 달리 ServiceUserRole에는 Space 설정 접근을 담는 settings가 없습니다. ServiceUserSpace 설정을 다루지 않기 때문입니다. 또 기본 제공 여부를 나타내는 sys.isLocked도 없습니다.

시스템 속성 (sys)

모든 ServiceUserRole은 공통 시스템 속성을 sys 객체에 담습니다. space·createdBy·updatedByRefer 모양({ "sys": { "id", "type": "Refer", "targetType" } })으로 들어갑니다.

속성타입설명
idstring리소스 고유 식별자.
typestring리소스 종류. ServiceUserRole은 항상 "ServiceUserRole".
spaceRefer<Space>ServiceUserRole이 속한 Space.
createdByRefer<User>생성한 사용자.
createdAtstring (date-time)생성 시각.
updatedByRefer<User>마지막으로 수정한 사용자.
updatedAtstring (date-time)마지막 수정 시각.
versioninteger (≥1)리소스 버전. 수정할 때마다 1씩 올라갑니다.

ServiceUserRole은 발행 개념이 없는 설정 리소스입니다. 그래서 Content·Media와 달리 syspublish·archive·status가 없고, version만 가집니다. versionServiceUserRole을 수정할 때마다 오릅니다. SpaceRole과 달리 sys.isLocked도 없습니다.

권한 맵: contentType·content·media

contentType·content·media는 각각 액션을 키로 갖는 맵입니다. 쓸 수 있는 액션은 Create(생성)·Read(읽기)·Edit(편집)·Delete(삭제)·Publish(발행)·Unpublish(발행취소)·Archive(보관)·Unarchive(보관해제)이며, 모든 액션을 한꺼번에 가리키는 All도 있습니다. SaveEdit과 같은 뜻입니다. 각 액션의 값은 Allow(허용)와 Deny(거부) 규칙 배열을 담은 객체입니다. 이 권한 맵 구조는 SpaceRole과 같습니다.

"content": {
  "Read":   { "Allow": [ /* 규칙 */ ], "Deny": [ /* 규칙 */ ] },
  "Edit":   { "Allow": [ /* 규칙 */ ] }
}

각 규칙(rule) 객체는 권한 범위를 좁히는 선택적 필터를 가집니다.

  • self: 그 규칙이 적용되는 대상을 리소스 자신 하나로 한정합니다. contentType 맵에서는 특정 Content Type 하나, script 맵에서는 특정 Script 하나를 뜻합니다.
  • contentType: 그 Content속한 Content Type으로 한정합니다. Content Type을 가리키는 Refer를 넣습니다.
  • createdBy: 특정 사용자가 만든 리소스만으로 한정합니다. sys.id에 특정 id를 넣으면 그 사람이 만든 것만, 예약값 :self를 넣으면 "지금 호출한 ServiceUser가 만든 것만"으로 한정됩니다.
  • tag: 특정 Tag가 달린 리소스만으로 한정합니다.

어느 필터가 어느 권한 맵에서 유효한지는 SpaceRole과 같고(contentType 맵은 self, content 맵은 contentType으로 대상을 지정합니다), 맞지 않는 필터를 넣으면 역할 저장이 거부됩니다. 맵별 표는 SpaceRole의 권한 맵에 있습니다.

createdBy 필터(:self 포함)를 ACDA에서 걸 때는 대상 Content TypepublishWithAuthortrue여야 합니다. ACDA는 발행 스냅샷의 sys.createdBy로 이 필터를 판정하는데, publishWithAuthor가 기본값 false면 스냅샷에 작성자가 없어 Allow 규칙은 아무것도 매칭하지 않고(회원이 자기 리소스를 빈 결과로 받습니다), Deny 규칙은 아무도 걸러내지 못합니다. 반면 ACMA(관리)는 초안의 sys.createdBy로 판정하므로 이 설정과 무관해, 같은 규칙이 ACMA에서는 동작해도 ACDA에서 어긋날 수 있습니다. publishWithAuthor는 회원이 글을 올리기 전에 켜야 하고 소급되지 않습니다. Content TypepublishWithAuthor 설명을 참고하세요.

Allow 배열 []는 그 종류 전체에 액션을 허용한다는 뜻입니다. 필터가 비어 있으니 거를 것이 없어, 모든 리소스에 그 액션이 열립니다.

SpaceRole과 달리 ServiceUserRole에는 settings가 없습니다. 권한 맵은 contentType·content·media·script 네 가지입니다. 액션 목록과 필터 키, :self의 의미를 비롯한 권한 맵 작성 방법은 같은 구조를 쓰는 SpaceRole의 설명도 함께 참고하세요. :self를 써서 본인이 만든 Content만 편집하도록 좁히는 예시는 아래 수정 블록에서 보여 줍니다.

액션 목록(Create·Read·Edit·Save·Delete·Publish·Unpublish·Archive·Unarchive·All)과 필터 키(self·contentType·createdBy·tag:self 의미는 SpaceRole의 권한 규칙 정의를 기준으로 합니다. ServiceUserRole:self는 현재 ServiceUser가 만든 것만으로 풀립니다.

script (Script 권한)

scriptScript에 대한 권한 맵으로, 구조는 content·media와 같습니다. 다만 ServiceUserScript에 할 수 있는 일은 실행뿐입니다(저작, 곧 생성·수정·삭제는 CMA의 Weegloo User 전용입니다). 그래서 ServiceUserRolescript에서 실질적으로 쓰는 액션은 Execute 하나입니다.

가입 회원이 Script를 실행할 수 있게 하려면 이렇게 씁니다.

"script": {
  "Execute": { "Allow": [] }
}

규칙 필터로 쓸 수 있는 것은 self(특정 Script 하나)와 createdBy 둘입니다. contentType·tagScript에 붙지 않는 축이라 넣으면 역할 저장이 거부됩니다. 회원에게 특정 Script 하나만 실행하도록 허용하려면 ExecuteAllow에 그 Script를 가리키는 self 규칙을 둡니다.

"script": {
  "Execute": {
    "Allow": [
      { "self": { "sys": { "id": "3trmXRMZcTAjDnphewjj1AaxYcaxlK", "type": "Refer", "targetType": "Script" } } }
    ]
  }
}

Script 자체의 구조와 실행 엔드포인트는 Script 리소스와 엔드포인트에서, 액션 전체 목록은 SpaceRole의 script 권한에서 다룹니다.

오류

ServiceUserRole을 다룰 때 만나는 코드입니다. 모든 리소스에 공통인 코드는 공통 오류를 참조하세요.

코드조건
WGL400020권한 맵에 그 맵에서 쓸 수 없는 필터를 넣어 ServiceUserRole 저장이 거부되었습니다. script 맵에 contentType·tag를 넣은 경우가 여기에 해당합니다.

API

아래 모든 엔드포인트의 기준 URL은 https://cma.weegloo.com/v1이며, Authorization 헤더에 CMA를 인증하는 Bearer 토큰이 필요합니다. 역할 수정(PUT·PATCH)에는 낙관적 동시성 제어를 위해 X-Weegloo-Version 헤더(현재 리소스의 sys.version)를 함께 보내야 합니다. 생성과 삭제에는 이 헤더가 없습니다.

  • ServiceUser: 이 역할을 받는 가입 회원(roleOverride).
  • ServiceLogin: 기본 역할(defaultRole)로 ServiceUserRole을 지정.
  • SpaceRole: Weegloo User용 권한 묶음(같은 권한 맵 구조).