集体台
集体台(Club)
目录
集体台(Club)资源管理集体台的成员以及每名成员所持有的权限级别。读取列表相当于 v1 的 list_clubmembers 端点;写操作则是 Web 界面中集体台权限页面的 API 对应物。
- 基础路径:
/api/v2/club - 作用域:
club:read、club:write、club:delete - 起始版本: 3.1.0
注意
请先阅读 API v2 概览,了解认证、响应封装与错误码。
警告:仅在启用集体台的实例上
整个资源仅当管理员开启了集体台功能(
special_callsign)时才存在。未开启时,下文每条路径都会返回404 not_found——与访问未知资源完全一样——并且创建令牌时也不会提供club:*作用域。
端点
路径中的 id 用于定位成员,使用的是其 user_id。
| 动词 | 路径 | 作用域 | 用途 | 起始版本 |
|---|---|---|---|---|
GET |
/api/v2/club |
club:read |
列出集体台的成员——或者,对于未指定集体台的管理员,列出各集体台 | 3.1.0 |
GET |
/api/v2/club/{user_id} |
club:read |
获取单个成员 | 3.1.0 |
POST |
/api/v2/club |
club:write |
向集体台添加成员 | 3.1.0 |
PATCH |
/api/v2/club/{user_id} |
club:write |
更改成员的权限级别 | 3.1.0 |
DELETE |
/api/v2/club/{user_id} |
club:delete |
从集体台移除成员 | 3.1.0 |
注意(没有
PUT)
谁可以调用
与能够打开 Web 界面中集体台权限页面的两种角色相同:
| 令牌 | 哪个集体台 | ?club_id= |
|---|---|---|
| 创建者为干事(级别 9)的集体台令牌 | 令牌所有者 | 可选,且只能是同一个集体台 |
| Wavelog 管理员的个人令牌 | club_id 指定的那个 |
必填 |
集体台令牌属于该集体台(所有者),但由代表其行事的成员创建(创建者),因此集体台在那里是隐含的。管理员管理所有集体台,没有隐含的集体台——他们总是需要指定。
其他任何情况都会以 403 forbidden 拒绝:
{
"error": {
"code": "forbidden",
"message": "Token is neither a club officer nor an admin"
}
}
这涵盖了普通用户的个人令牌、低于干事级别的集体台令牌,以及成员资格此后已被撤销的令牌。消息会指出所缺少的那个角色——低于干事级别的集体台令牌会以 Token is not a club officer 被拒,因为它缺少的并不是管理员权限。请根据 code 判断,而不是消息。权限级别见 集体台。
注意(只有在可用处才提供这些作用域)
两种角色都不匹配的会话在创建令牌时不会看到
club:*复选框——集体台之外的普通用户,或集体台内低于干事级别的成员,都没有可操作的集体台。
选择集体台
?club_id= 在所有动词上的作用方式相同,包括 POST、PATCH 和 DELETE——它用于选择集体台,因此不放进请求体。
# Administrator: name the club
curl "https://<WAVELOG_URL>/index.php/api/v2/club?club_id=5" \
-H "Authorization: Bearer wl2_admin_token"
# Officer: the club token already knows
curl "https://<WAVELOG_URL>/index.php/api/v2/club" \
-H "Authorization: Bearer wl2_club_token"
| 情形 | 响应 |
|---|---|
管理员未提供 club_id,请求 GET /api/v2/club |
集体台列表 |
管理员未提供 club_id,请求其他任何端点 |
400 validation_error |
提供了 club_id 但不是数字 |
400 validation_error |
club_id 不是集体台,或不存在 |
404 not_found |
集体台令牌,club_id 指向其他集体台 |
403 forbidden |
集体台令牌,club_id 指向自己的集体台 |
接受 |
有哪些集体台
以管理员身份不带 club_id 调用 GET /api/v2/club:得到用于挑选 club_id 的集体台目录。其他所有调用都需要它,因此若用 400 拒绝这一请求,就无处可查了。
curl "https://<WAVELOG_URL>/index.php/api/v2/club" \
-H "Authorization: Bearer wl2_admin_token"
{
"data": [
{ "club_id": 5, "callsign": "N0CLUB", "member_count": 4 },
{ "club_id": 8, "callsign": "N0DX", "member_count": 0 }
],
"meta": { "count": 2 }
}
member_count 统计任意权限级别的成员。集体台令牌永远看不到这个列表——它只有一个集体台,因此 GET /api/v2/club 返回该集体台的成员。
警告
默认情况下,响应会包含每名成员的电子邮箱地址,同时还有其姓名与网格定位,而
club:write允许令牌授予干事权限。这两个作用域都不应轻易授予第三方工具。作为实例所有者,你可以隐藏个人字段——见 隐藏的用户数据。
成员对象
{
"user_id": 42,
"user_firstname": "Alex",
"user_lastname": "Example",
"user_locator": "JN47",
"callsign": "N0CALL",
"user_name": "alex",
"user_email": "alex@example.org",
"permission_level": 9,
"user_language": "english"
}
| 字段 | 说明 |
|---|---|
user_id |
成员的 user id——本资源路径中的 id |
user_firstname / user_lastname |
成员的真实姓名 |
user_locator |
梅登黑德网格定位 |
callsign |
成员本人的呼号,而非集体台的呼号 |
user_name |
登录名/用户名 |
user_email |
成员的电子邮箱地址 |
permission_level |
集体台权限级别:3、6 或 9 |
user_language |
成员的界面语言 |
警告:字段可能缺失
实例所有者可以隐藏个人字段(除
user_id、callsign和permission_level之外的全部字段),以符合其须遵守的隐私规定。被隐藏的字段在对象中是缺失的,而不是空值。使用前请先确认字段是否存在;见 隐藏的用户数据。
列出成员
在已选定集体台的情况下调用 GET /api/v2/club——集体台令牌隐含选定,管理员则通过 ?club_id= 显式指定。未指定时,管理员得到的是集体台列表。
curl "https://<WAVELOG_URL>/index.php/api/v2/club" \
-H "Authorization: Bearer wl2_club_token"
{
"data": [
{
"user_id": 42,
"user_firstname": "Alex",
"user_lastname": "Example",
"user_locator": "JN47",
"callsign": "N0CALL",
"user_name": "alex",
"user_email": "alex@example.org",
"permission_level": 9,
"user_language": "english"
}
],
"meta": { "count": 1 }
}
GET /api/v2/club/{user_id} 返回其中单个对象,若该用户不是该集体台的成员则返回 404 not_found。
添加成员
POST /api/v2/club
必填字段: user_id、permission_level。
curl -X POST https://<WAVELOG_URL>/index.php/api/v2/club \
-H "Authorization: Bearer wl2_your_token_here" \
-H "Content-Type: application/json" \
-d '{ "user_id": 42, "permission_level": 6, "notify": true }'
- 成功时 API 返回
201 Created、一个Location响应头,以及data中新创建的成员对象。 - 用户已是成员时返回
409 conflict——请用PATCH更改其级别。 permission_level必须为3、6或9;其他值返回400 validation_error,并在details.allowed中给出可接受的值。
可写字段
| 字段 | 说明 |
|---|---|
user_id |
要添加的用户(仅 POST) |
permission_level |
3 = 集体台成员,6 = 集体台成员 ADIF,9 = 集体台干事 |
notify |
可选,见通知成员 |
更改权限级别
PATCH /api/v2/club/{user_id}
curl -X PATCH https://<WAVELOG_URL>/index.php/api/v2/club/42 \
-H "Authorization: Bearer wl2_your_token_here" \
-H "Content-Type: application/json" \
-d '{ "permission_level": 9 }'
data 中返回更新后的成员对象。与 Web 界面不同,这里绝不会创建成员资格:尚不是成员的用户会返回 404 not_found。添加成员请用 POST。
移除成员
DELETE /api/v2/club/{user_id}
curl -X DELETE https://<WAVELOG_URL>/index.php/api/v2/club/42 \
-H "Authorization: Bearer wl2_your_token_here"
- 成功时 API 返回
204 No Content。 - 不是成员的用户返回
404 not_found。
警告
移除成员还会删除他们为此集体台创建的 API 密钥、API 令牌和电台控制会话,与 Web 界面完全一样。以此方式删除的令牌将永久失效:重新添加该成员会恢复其权限,但他们必须创建新令牌。见 集体台。
他们的个人账户、个人令牌和自己的 QSO 不受影响——但他们以集体台呼号记录的 QSO 会留在集体台。
通知成员
POST 和 PATCH 接受可选的 notify 标志。当其为 true 时,Wavelog 会向该成员发送与 Web 界面相同的邮件——POST 时为「已加入集体台」,PATCH 时为「权限已更改」,并使用该成员自己的语言。
结果在响应的 meta 中给出:
{
"data": { "user_id": 42, "permission_level": 9, "…": "…" },
"meta": { "notified": true }
}
邮件发送失败不会导致请求失败:权限无论如何都已授予,而 meta.notified 为 false。未请求 notify 时,该字段完全省略。
注意
这需要实例上配置了可用的邮件设置。没有时
meta.notified始终为false。
防护规则
除访问检查之外,API 还会拒绝少数 Web 界面允许的操作:
| 情形 | 干事 | 管理员 |
|---|---|---|
| 操作自己的成员资格 | 403 forbidden |
允许 |
以集体台自身的 user_id 作为目标 |
400 validation_error |
400 validation_error |
| 目标用户本身就是一个集体台 | 400 validation_error |
400 validation_error |
| 目标用户不存在 | 404 not_found |
404 not_found |
| 集体台由身份提供方管理 | 每次写入均 409 conflict |
每次写入均 409 conflict |
注意(为什么干事不能更改自己的成员资格)
通过 API 将自己降级或移除,会使该集体台失去对自己的权限管理能力,只有 Wavelog 管理员才能撤销。Web 界面仍然允许这样做,因为那里的后果是可见的——而且管理员本就可达每个集体台,这条规则只会妨碍他们。
注意(SSO 管理的集体台)
当成员资格来自身份提供方(
auth_header_clubstation_direct)时,它们在登录时被授予和撤销。通过 API 的写入会被静默撤销,因此以409 conflict拒绝——这也是 Web 界面禁用该表单的原因。
Wavelog 管理员
管理员(user_type 为 99)可以管理所有集体台,与 Web 界面完全一致。有两种方式:
- 个人令牌加
?club_id=——常见方式。从你平常的会话创建令牌;由于你是管理员,会提供club:*作用域。此后每个请求都要指定集体台。 - 在切换到某个集体台时创建的集体台令牌。集体台是隐含的,即使该集体台的权限页面上没有条目也能工作:API 会像 Web 界面一样让管理员通过成员资格检查。
注意
确实在某集体台上持有明确权限级别的管理员,会按该级别对待,而不是按管理员对待——低于 9 的级别会被拒绝。把自己设为集体台成员是一个有意的选择,API 尊重这一选择。如果你想要管理员路径,请改用带
?club_id=的个人令牌。