mirror of
https://github.com/larksuite/cli.git
synced 2026-08-03 08:32:46 +08:00
fix(vc): align meeting query scopes by identity
This commit is contained in:
@@ -52,7 +52,8 @@ var VCMeetingEvents = common.Shortcut{
|
||||
Command: "+meeting-events",
|
||||
Description: "List meeting events by meeting ID",
|
||||
Risk: "read",
|
||||
Scopes: []string{"vc:meeting.meetingevent:read"},
|
||||
UserScopes: []string{"vc:meeting.meetingevent:read"},
|
||||
BotScopes: []string{"vc:meeting.bot.join:write"},
|
||||
AuthTypes: []string{"user", "bot"},
|
||||
HasFormat: true,
|
||||
Flags: []common.Flag{
|
||||
|
||||
@@ -418,6 +418,24 @@ func TestMeetingEvents_Validation_PageAllIgnoresInvalidPageSize(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMeetingEvents_ScopesMatchIdentityPermissions(t *testing.T) {
|
||||
userScopes := []string{"vc:meeting.meetingevent:read"}
|
||||
botScopes := []string{"vc:meeting.bot.join:write"}
|
||||
|
||||
if got := VCMeetingEvents.ScopesForIdentity("user"); !reflect.DeepEqual(got, userScopes) {
|
||||
t.Fatalf("ScopesForIdentity(user) = %v, want %v", got, userScopes)
|
||||
}
|
||||
if got := VCMeetingEvents.ScopesForIdentity("bot"); !reflect.DeepEqual(got, botScopes) {
|
||||
t.Fatalf("ScopesForIdentity(bot) = %v, want %v", got, botScopes)
|
||||
}
|
||||
if got := VCMeetingEvents.DeclaredScopesForIdentity("user"); !reflect.DeepEqual(got, userScopes) {
|
||||
t.Fatalf("DeclaredScopesForIdentity(user) = %v, want %v", got, userScopes)
|
||||
}
|
||||
if got := VCMeetingEvents.DeclaredScopesForIdentity("bot"); !reflect.DeepEqual(got, botScopes) {
|
||||
t.Fatalf("DeclaredScopesForIdentity(bot) = %v, want %v", got, botScopes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMeetingEvents_Validation_InvalidPageSizeReturnsFlagError(t *testing.T) {
|
||||
runtime := newMeetingEventsRuntime()
|
||||
mustSetMeetingEventsFlag(t, runtime, "meeting-id", "7628568141510692381")
|
||||
|
||||
@@ -23,7 +23,8 @@ var VCMeetingListActive = common.Shortcut{
|
||||
Command: "+meeting-list-active",
|
||||
Description: "List active meetings for the current identity or target user",
|
||||
Risk: "read",
|
||||
Scopes: []string{"vc:meeting.meetingevent:read"},
|
||||
UserScopes: []string{"vc:meeting.meetingevent:read"},
|
||||
BotScopes: []string{"vc:meeting.bot.join:write"},
|
||||
AuthTypes: []string{"user", "bot"},
|
||||
HasFormat: true,
|
||||
Flags: []common.Flag{
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -608,9 +609,21 @@ func TestMeetingListActive_DryRun_UserIdentity(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMeetingListActive_ScopeMatchesEventReadPermission(t *testing.T) {
|
||||
if len(VCMeetingListActive.Scopes) != 1 || VCMeetingListActive.Scopes[0] != "vc:meeting.meetingevent:read" {
|
||||
t.Fatalf("scopes = %#v, want [vc:meeting.meetingevent:read]", VCMeetingListActive.Scopes)
|
||||
func TestMeetingListActive_ScopesMatchIdentityPermissions(t *testing.T) {
|
||||
userScopes := []string{"vc:meeting.meetingevent:read"}
|
||||
botScopes := []string{"vc:meeting.bot.join:write"}
|
||||
|
||||
if got := VCMeetingListActive.ScopesForIdentity("user"); !reflect.DeepEqual(got, userScopes) {
|
||||
t.Fatalf("ScopesForIdentity(user) = %v, want %v", got, userScopes)
|
||||
}
|
||||
if got := VCMeetingListActive.ScopesForIdentity("bot"); !reflect.DeepEqual(got, botScopes) {
|
||||
t.Fatalf("ScopesForIdentity(bot) = %v, want %v", got, botScopes)
|
||||
}
|
||||
if got := VCMeetingListActive.DeclaredScopesForIdentity("user"); !reflect.DeepEqual(got, userScopes) {
|
||||
t.Fatalf("DeclaredScopesForIdentity(user) = %v, want %v", got, userScopes)
|
||||
}
|
||||
if got := VCMeetingListActive.DeclaredScopesForIdentity("bot"); !reflect.DeepEqual(got, botScopes) {
|
||||
t.Fatalf("DeclaredScopesForIdentity(bot) = %v, want %v", got, botScopes)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,21 @@
|
||||
- `meeting_id` 来自 `+meeting-list-active --as bot --user-id <user_open_id>` 或 `+meeting-join --as bot`:后续读取事件继续 `--as bot`。
|
||||
- 应用身份下,应用机器人必须在该会中或参会过;应用身份 active meeting 返回的是“目标用户在会中且应用机器人也在会中”的会议,不表示可以读取任意 `meeting_id`。
|
||||
|
||||
## 权限建议
|
||||
|
||||
本命令当前按身份声明不同权限:
|
||||
|
||||
| 场景 | 推荐权限 |
|
||||
|------|----------|
|
||||
| UAT / 用户身份 `--as user` | `vc:meeting.meetingevent:read` |
|
||||
| TAT / 应用身份 `--as bot` | `vc:meeting.bot.join:write` |
|
||||
|
||||
注意:
|
||||
|
||||
- 这里的 TAT 建议只说明 CLI 当前为应用身份声明了 `vc:meeting.bot.join:write` 这条窄版权限路径,不代表服务端已经把会中事件读取降成“无数据范围风险”的纯读点位。
|
||||
- 应用身份是否能真正读到事件,仍取决于应用机器人是否在会中或曾在会中、租户安装、权限可访问的数据范围,以及后端对该会议的可见性判断。
|
||||
- 如果你的目标是最小化读权限,优先使用用户身份并开通 `vc:meeting.meetingevent:read`。
|
||||
|
||||
## 命令
|
||||
|
||||
```bash
|
||||
|
||||
@@ -4,6 +4,21 @@
|
||||
|
||||
本 skill 对应 shortcut:`lark-cli vc +meeting-list-active`(调用 `GET /open-apis/vc/v1/bots/user_active_meeting`)。
|
||||
|
||||
## 权限建议
|
||||
|
||||
本命令当前按身份声明不同权限:
|
||||
|
||||
| 场景 | 推荐权限 |
|
||||
|------|----------|
|
||||
| UAT / 用户身份 `--as user` | `vc:meeting.meetingevent:read` |
|
||||
| TAT / 应用身份 `--as bot` | `vc:meeting.bot.join:write` |
|
||||
|
||||
注意:
|
||||
|
||||
- TAT 这里的 `vc:meeting.bot.join:write` 是窄版 CLI 权限点位支持,不表示服务端已经把 active meeting 可见性变成纯读无数据范围风险模型。
|
||||
- 应用身份依然只返回“目标用户在会中且应用机器人也在会中”的会议;如果机器人没进会、数据范围没放开、应用没安装,结果仍可能为空。
|
||||
- 如果只是查询当前登录用户自己正在参加的会议,优先用用户身份和 `vc:meeting.meetingevent:read`。
|
||||
|
||||
## 命令
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user