멤버
`members.list`, `list_all`, `iterate`, `get`, `add`, `update`, `remove`, `grant_address`, `revoke_address`, 그리고 옆의 초대 메서드.
모든 메서드
support_role_id = "role_8b1f4c2e9a7d3b60e5f1a2c4"viewer_role_id = "role_2c7e9a1f4b8d3e60c5a7f1b9" invitation = client.members.add( email: "[email protected]", roleId: support_role_id, addressIds: ["2b81de07-9c3f-4a61-b8e2-5d07f4c19a36"], access: "member")puts invitation[:id], invitation[:expiresAt] people = client.members.list_allputs people.map { |person| "#{person[:email]} #{person[:userId]}" } sam_id = "q7Vd3kX9mT2pLw8RzN4bYc6HfJ1sGa5E"member = client.members.get(sam_id)puts member.dig(:role, :name), member[:implied] client.members.update(sam_id, roleId: viewer_role_id) address_id = "c40a95f2-1e7b-4d38-a6c9-82f05b3d7e14"client.members.grant_address(sam_id, addressId: address_id, access: "viewer")client.members.revoke_address(sam_id, address_id) removed = client.members.remove(sam_id)puts removed[:addressesRevoked]한 사람에게는 두 가지 권한이 주어지며, 이 둘을 하나로 합쳐서는 안 됩니다. role은 무엇을 해도 되는지이고, addresses는 그것을 어떤 대상에 할 수 있는지입니다. 둘 다 허용해야 합니다: emails:send를 가진 역할을 갖고 있으면서 invoices@에 대해서는 access: "viewer"인 사람은, 메일을 보낼 수는 있지만 그 주소에서는 보낼 수 없는 사람입니다. 예외는 addresses:all을 가진 역할로, addresses에 무엇이 나열되든 모든 주소에 닿는데, 그 Array에는 직접 받은 부여만 들어 있기 때문입니다. 그러므로 addresses를 그 사람이 닿는 범위 전체로 읽기 전에 permissions를 확인하세요.
한 사람에 관한 모든 호출은 이메일이 아니라 그 사람의 userId를 첫 번째 인자로 받으므로, 예제처럼 list나 list_all에서 읽어 오세요. 유일한 예외는 add로, 주소를 초대하기 때문입니다: 그 사람은 초대를 수락한 뒤에야 userId를 가지며, 그때까지는 list_invitations로 초대를 추적합니다. 요청 본문의 필드는 API의 camelCase 이름(roleId:, addressIds:, addressId:)을 그대로 쓰며, 키워드 인자나 Hash 하나로 전달합니다.
list는 OpenEmail::Page 하나를 반환하고, list_all은 모든 멤버를 하나의 Array로 반환하며, iterate는 각 멤버를 블록에 yield하거나 블록이 없으면 Enumerator를 반환합니다. 멤버는 Symbol 키를 가진 Hash로 돌아오고 role은 그 안의 Hash이므로, member.dig(:role, :name)으로 역할의 이름을 읽습니다.
implied: true는 아무도 역할을 고르지 않았다는 뜻입니다. 주소 권한만 있고 역할 행은 없어서, 가진 권한 중 가장 넓은 것에서 역할을 추론한 것입니다. “아직 정해지지 않음”으로 취급하십시오. 추론을 결정으로 바꾸는 것은 update입니다. 그전까지는 주소 접근 권한을 넓히면 그 사람이 할 수 있는 일도 조용히 함께 넓어집니다.
워크스페이스 소유자는 첫 번째 행이며 isOwner: true로 표시되고, add, update, remove는 여전히 member_is_owner로 소유자를 거부합니다. 이는 OpenEmail::ValidationError로 발생하는 422입니다. 공유되지 않은 워크스페이스도 멤버가 없다고 보고하지 않고 한 명으로 보고하므로, 좌석 수를 셀 때는 isOwner를 제외하세요: client.members.list_all.count { |member| !member[:isOwner] }.
remove는 두 축을 모두 가져갑니다: 역할과 이 워크스페이스의 모든 주소 권한을 함께 회수하고 addressesRevoked를 보고합니다. revoke_address는 좁은 쪽으로, 회사를 떠난 사람이 아니라 팀을 옮긴 사람을 위한 호출입니다.
매개변수
emailString필수- 초대할 대상이며, 앞뒤 공백을 제거하고 소문자로 변환합니다. 아직 계정이 없어도 됩니다. 누구든 초대할 수 있고, 역할과 권한은 초대를 수락할 때 적용됩니다. 이미 워크스페이스에 있는 사람은 `member_is_owner`(422)입니다.
roleIdString필수- 그 사람이 가질 역할이며 1자에서 128자이고, 이 워크스페이스에 존재하는 역할이어야 합니다: 알 수 없는 id는 `OpenEmail::NotFoundError`로 발생하는 `role_not_found`(404)입니다. 소유자 역할은 넘겨줄 수 없어 `role_immutable`(409)로 돌아옵니다. 누군가를 소유자로 만드는 것은 워크스페이스 양도이고, 여기에는 그런 호출이 없기 때문입니다.
addressIdsArray<String>- 초대에 담기는 주소이며, 각각 1자에서 128자인 id를 최대 64개까지 지정할 수 있고, 초대가 수락될 때 부여됩니다. 무엇이든 기록되기 전에 모든 id를 검사하므로, 이 워크스페이스의 주소가 아닌 id가 하나라도 있으면 호출 전체가 422 `member_not_found`로 거부되고 아무것도 발송되지 않습니다. 같은 주소를 10분 안에 다시 초대하면 409 `invitation_too_soon`입니다.
accessString- `addressIds`에 담긴 모든 id에 대해 무엇을 할 수 있는지입니다: `member`는 주소를 읽고 그 주소로 보낼 수 있으며, `viewer`는 읽기만 합니다. 기본값은 `member`로, 콘솔과 기존 공유 경로가 늘 사용해 온 수준입니다. 덕분에 스크립트에서든 화면에서든 같은 호출이 같은 의미를 갖습니다. 서로 다른 수준을 섞으려면 예외로 둘 주소에 대해 나중에 `grant_address`를 호출하세요.
응답
objectString- 항상 `member`입니다. 삭제 호출도 같은 값과 함께 해당 사용자의 `userId`, `deleted: true`, `addressesRevoked`만 돌려주고, 아래의 다른 필드는 돌려주지 않습니다.
userIdString- 그 사람의 계정 id이며, 다른 모든 멤버 호출이 첫 번째 인자로 받는 핸들입니다: `get`, `update`, `remove`와 두 주소 호출이 모두 이 값을 씁니다. 사람을 추가하는 호출만 대신 이메일로 동작하는데, 동료를 추가하는 사람은 상대의 주소는 알아도 id는 모르기 때문입니다.
emailString- 그 사람 계정에 등록된 이메일이며, 해당 행에 저장된 그대로 돌려줍니다. 이 리소스는 이 값을 기록하지 않으며, `add`에서의 소문자 변환은 조회를 위해 보낸 주소에 적용될 뿐 돌아오는 값에 적용되는 것이 아닙니다. 멤버 목록은 소유자 다음부터 가입 시점이 아니라 이 값을 기준으로 정렬됩니다. 이 목록은 무엇이 바뀌었는지 보려고가 아니라 특정 한 사람을 찾으려고 읽기 때문입니다.
nameString or nil- 그 사람 계정에서 가져온 표시 이름이며, 해당 컬럼에는 항상 값이 있습니다. 타입에 있는 nil은 방어적인 것일 뿐 이 API에서 실제로 관측된 상태는 아닙니다. 이 값은 워크스페이스가 아니라 그 사람에게 속하므로, 이 리소스로는 아무것도 설정할 수 없습니다.
imageString or nil- 그 사람 계정에서 가져온 아바타이며, 설정하지 않았으면 nil입니다.
role.idString or nil- 그 사람이 가진 역할의 id로, `member.dig(:role, :id)`로 읽으며, 아무도 고르지 않았으면 nil입니다. `implied`를 참고하세요. 여기가 nil인 경우가, `role`이 누군가의 결정이 아니라 추론을 보고하는 유일한 경우입니다.
role.nameString- 역할의 이름입니다. 추론된 멤버의 경우 이 워크스페이스의 행이 아니라, 그 사람의 접근 권한이 대응하는 내장 템플릿의 이름입니다.
role.builtinString or nil- 이 역할이 어떤 내장 역할(`owner`, `admin`, `member`, `viewer`, `developer`, `billing`)인지이며, 사용자 정의 역할이면 nil입니다. `owner`는 소유자 본인의 행에만 `isOwner: true`와 함께 나타납니다. 그 역할을 누군가에게 부여하려 하면 `role_immutable`(409)로 거부됩니다.
isOwnerBoolean- 정확히 한 행에서만 true이며, 워크스페이스가 귀속된 계정입니다. 역할 행이 무엇이라고 하든 모든 권한을 가지며, 정렬 시 가장 앞에 오고, `add`, `update`, `remove`는 모두 `member_is_owner`로 거부합니다. 좌석 수를 셀 때는 제외하십시오.
impliedBoolean- 주소 권한은 있는데 멤버 행이 없어 역할이 선택된 것이 아니라 추론된 경우 true입니다: `member` 권한이 하나라도 있으면 내장 Member로, 그렇지 않으면 Viewer가 됩니다. 소유자에게는 절대 true가 되지 않습니다. “접근 권한에서 추론됨”으로 표시하세요. `update`로 추론을 결정으로 바꾸기 전까지는, 주소 접근 권한을 넓히면 그 사람이 할 수 있는 일도 조용히 함께 넓어집니다.
permissionsArray<String>- 역할의 권한을 멤버에 펼쳐 놓은 것으로, 역할을 따로 조회하지 않고도 한 번의 읽기로 “이 사람이 해도 되는가?”에 답할 수 있습니다. 추론된 멤버의 경우 이 워크스페이스의 역할 행이 아니라 내장 템플릿에서 가져오므로, 내장 Member 역할을 수정해도 추론된 멤버가 가진 권한은 달라지지 않습니다.
addressesArray<Hash>- 그 사람에게 부여된 주소이며 주소 기준으로 정렬되고, 각각 자체 접근 수준을 갖습니다. 역할만 있고 권한이 없는 사람은 비어 있습니다. 주소가 부여되기 전의 새 멤버가 바로 그 모습이며, 무엇을 보여 줄지 아직 정하는 중이라면 그것이 올바른 상태입니다.
addresses[].addressIdString- 주소의 id이며, `grant_address`와 `revoke_address`가 받는 값입니다. 이 워크스페이스의 주소가 아닌 id는 두 호출 모두에서 거부되며, 일어나지도 않은 회수를 보고하는 일은 없습니다.
addresses[].addressString- 로컬 파트와 도메인을 다시 조합한 전체 주소이며, 소문자로 표기됩니다.
addresses[].accessString- 이 주소 하나에 대해 무엇을 할 수 있는지입니다: `member`는 읽고 그 주소로 보낼 수 있으며, `viewer`는 읽기만 합니다. 발송이 일어나려면 이 값과 역할이 모두 허용해야 하므로, `emails:send`를 가진 역할이라도 `viewer` 권한 위에서는 어떤 주소로도 보내지 못합니다. 저장된 컬럼 이름은 `role`이지만, 한 Hash가 서로 다른 어휘에서 온 `role` 키를 두 개 들고 있지 않도록 여기서는 이름을 바꿨습니다.
createdAtString or nil- 멤버 행이 기록된 시각이며 ISO 8601 String입니다. 멤버 행이 아예 없으면 nil입니다. 이 nil은 `implied: true`와 같은 집단을 가리킵니다: 역할 제도가 생기기 전부터 주소 권한을 갖고 있었고 그 뒤로 아무도 역할을 주지 않은 사람들입니다.
초대
waiting = client.members.list_all_invitations waiting.each do |invitation| client.members.resend_invitation(invitation[:id]) if invitation[:expired]end client.members.revoke_invitation("winv_6bb640f5b99e47deb758f1f5")add는 초대로 답하며, 이어지는 호출은 다음과 같습니다. list_invitations는 아직 아무도 수락하지 않은 초대의 OpenEmail::Page 하나를 반환하고, list_all_invitations는 전부를 하나의 Array로 반환하며, iterate_invitations는 각각을 블록에 yield하거나 Enumerator를 반환합니다. resend_invitation은 새 링크와 14일의 추가 기간으로 다시 보내고, revoke_invitation은 철회합니다. 대기 중인 초대는 수락될 때까지 아무것도 부여하지 않습니다.
resend_invitation은 같은 주소를 10분 안에 두 번째로 보내려 하면 409 invitation_too_soon으로 거부하고, revoke_invitation은 먼저 수락된 초대를 409 invitation_accepted로 거부합니다. 둘 다 OpenEmail::ConflictError로 발생하므로 conflict?가 true이며, code로 구분할 수 있습니다.