fix: use workbench service name for manager config
This commit is contained in:
+1
-1
@@ -13,7 +13,7 @@ ENV IM_WORKBENCH_CONFIG=/app/configs/workbench.test.json
|
|||||||
ENV IM_WORKBENCH_INTERNAL_SERVICE_NAME=hotgo-admin
|
ENV IM_WORKBENCH_INTERNAL_SERVICE_NAME=hotgo-admin
|
||||||
ENV IM_WORKBENCH_INTERNAL_SECRET=hotgo-workbench-internal
|
ENV IM_WORKBENCH_INTERNAL_SECRET=hotgo-workbench-internal
|
||||||
ENV IM_WORKBENCH_MANAGER_BASE_URL=https://admin.118im.com
|
ENV IM_WORKBENCH_MANAGER_BASE_URL=https://admin.118im.com
|
||||||
ENV IM_WORKBENCH_MANAGER_SERVICE_NAME=im-server
|
ENV IM_WORKBENCH_MANAGER_SERVICE_NAME=im-workbench
|
||||||
ENV IM_CONFIG_API_SECRET=
|
ENV IM_CONFIG_API_SECRET=
|
||||||
ENV IM_INTERNAL_API_SECRET=
|
ENV IM_INTERNAL_API_SECRET=
|
||||||
COPY --from=builder /out/im_workbench /app/im_workbench
|
COPY --from=builder /out/im_workbench /app/im_workbench
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ X-Request-ID: {uuid}
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
IM_WORKBENCH_MANAGER_BASE_URL=https://admin.118im.com
|
IM_WORKBENCH_MANAGER_BASE_URL=https://admin.118im.com
|
||||||
IM_WORKBENCH_MANAGER_SERVICE_NAME=im-server
|
IM_WORKBENCH_MANAGER_SERVICE_NAME=im-workbench
|
||||||
IM_WORKBENCH_MANAGER_SECRET={IM_CONFIG_API_SECRET}
|
IM_WORKBENCH_MANAGER_SECRET={IM_CONFIG_API_SECRET}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
},
|
},
|
||||||
"manager": {
|
"manager": {
|
||||||
"base_url": "",
|
"base_url": "",
|
||||||
"service_name": "im-server",
|
"service_name": "im-workbench",
|
||||||
"secret": "",
|
"secret": "",
|
||||||
"uid_key_group": "im",
|
"uid_key_group": "im",
|
||||||
"uid_key_keys": [
|
"uid_key_keys": [
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
},
|
},
|
||||||
"manager": {
|
"manager": {
|
||||||
"base_url": "https://admin.118im.com",
|
"base_url": "https://admin.118im.com",
|
||||||
"service_name": "im-server",
|
"service_name": "im-workbench",
|
||||||
"secret": "",
|
"secret": "",
|
||||||
"uid_key_group": "im",
|
"uid_key_group": "im",
|
||||||
"uid_key_keys": [
|
"uid_key_keys": [
|
||||||
|
|||||||
@@ -0,0 +1,442 @@
|
|||||||
|
# 工作台与 Manager 内部配置运维说明
|
||||||
|
|
||||||
|
更新时间:2026-09-17
|
||||||
|
|
||||||
|
## 1. 背景
|
||||||
|
|
||||||
|
`im_workbench` 需要从 `im_manager` 读取系统配置,例如:
|
||||||
|
|
||||||
|
- `im.uid_encryption_key`
|
||||||
|
|
||||||
|
读取链路如下:
|
||||||
|
|
||||||
|
```text
|
||||||
|
im_workbench
|
||||||
|
-> GET https://admin.118im.com/internal/im-config/third-party/im?keys=uid_encryption_key,UID_ENCRYPTION_KEY,uid_key
|
||||||
|
-> im_manager 校验 HMAC 签名
|
||||||
|
-> 返回系统配置
|
||||||
|
```
|
||||||
|
|
||||||
|
这个接口是服务间内部接口,不是普通前端接口。调用方必须带 HMAC 请求头:
|
||||||
|
|
||||||
|
```http
|
||||||
|
X-Service-Name: im-workbench
|
||||||
|
X-Timestamp: <unix seconds>
|
||||||
|
X-Nonce: <random nonce>
|
||||||
|
X-Signature: <hmac-sha256 hex>
|
||||||
|
```
|
||||||
|
|
||||||
|
签名使用的密钥来自 `im_manager` 测试环境 Secret 中的:
|
||||||
|
|
||||||
|
```text
|
||||||
|
manager-system / im-manager-secrets / IM_CONFIG_API_SECRET
|
||||||
|
```
|
||||||
|
|
||||||
|
注意:不要把真实密钥写进 Git 文档或代码。
|
||||||
|
|
||||||
|
## 2. 为什么 .env 不生效
|
||||||
|
|
||||||
|
测试环境运行在 Kubernetes Pod 中,服务启动时不会自动读取仓库里的 `.env` 文件。
|
||||||
|
|
||||||
|
当前代码和启动方式是:
|
||||||
|
|
||||||
|
- `im_workbench` 只读取进程环境变量和 `IM_WORKBENCH_CONFIG` 指向的 JSON 配置文件。
|
||||||
|
- `im_manager` 的 entrypoint 使用 Pod 环境变量做 `envsubst` 生成 `config.yaml`。
|
||||||
|
- 两个服务都没有 `godotenv.Load()`、`source .env` 或 docker compose `env_file` 逻辑。
|
||||||
|
|
||||||
|
所以测试环境真正生效的是:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Kubernetes Secret / Deployment 环境变量
|
||||||
|
```
|
||||||
|
|
||||||
|
不是仓库中的 `.env`。
|
||||||
|
|
||||||
|
## 3. 当前 Kubernetes 配置关系
|
||||||
|
|
||||||
|
### im_workbench
|
||||||
|
|
||||||
|
命名空间:
|
||||||
|
|
||||||
|
```text
|
||||||
|
workbench-system
|
||||||
|
```
|
||||||
|
|
||||||
|
Deployment:
|
||||||
|
|
||||||
|
```text
|
||||||
|
im-workbench
|
||||||
|
```
|
||||||
|
|
||||||
|
当前 Pod 里只显式注入:
|
||||||
|
|
||||||
|
```text
|
||||||
|
IM_WORKBENCH_CONFIG=/etc/im-workbench/workbench.json
|
||||||
|
```
|
||||||
|
|
||||||
|
`/etc/im-workbench/workbench.json` 来自:
|
||||||
|
|
||||||
|
```text
|
||||||
|
workbench-system / im-workbench-secrets / workbench.json
|
||||||
|
```
|
||||||
|
|
||||||
|
因此 workbench 的运行时配置要改这个 Secret 里的 `workbench.json`,或在 Deployment 里显式加环境变量。
|
||||||
|
|
||||||
|
### im_manager
|
||||||
|
|
||||||
|
命名空间:
|
||||||
|
|
||||||
|
```text
|
||||||
|
manager-system
|
||||||
|
```
|
||||||
|
|
||||||
|
Deployment:
|
||||||
|
|
||||||
|
```text
|
||||||
|
im-manager
|
||||||
|
```
|
||||||
|
|
||||||
|
Secret:
|
||||||
|
|
||||||
|
```text
|
||||||
|
manager-system / im-manager-secrets
|
||||||
|
```
|
||||||
|
|
||||||
|
其中和内部配置接口相关的 key:
|
||||||
|
|
||||||
|
```text
|
||||||
|
IM_CONFIG_API_SERVICE_NAME
|
||||||
|
IM_CONFIG_API_SECRET
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. 必须配置什么
|
||||||
|
|
||||||
|
### 4.1 im_manager 需要允许 im_workbench 调配置接口
|
||||||
|
|
||||||
|
`im_manager` 的 `IM_CONFIG_API_SERVICE_NAME` 需要支持两个调用方:
|
||||||
|
|
||||||
|
```text
|
||||||
|
im-server,im-workbench
|
||||||
|
```
|
||||||
|
|
||||||
|
原因:
|
||||||
|
|
||||||
|
- `im_server` 也需要读取 manager 配置。
|
||||||
|
- `im_workbench` 也需要读取 manager 配置。
|
||||||
|
- 如果只配置 `im-workbench`,会影响 `im_server`。
|
||||||
|
- 如果只配置 `im-server`,`im_workbench` 用正确 service name 调用会 401。
|
||||||
|
|
||||||
|
目标配置:
|
||||||
|
|
||||||
|
```text
|
||||||
|
IM_CONFIG_API_SERVICE_NAME=im-server,im-workbench
|
||||||
|
```
|
||||||
|
|
||||||
|
`IM_CONFIG_API_SECRET` 保持现有值,不要改成空,也不要泄露到日志或文档。
|
||||||
|
|
||||||
|
### 4.2 im_workbench 需要配置 manager 连接信息
|
||||||
|
|
||||||
|
`workbench.json` 中需要有:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"manager": {
|
||||||
|
"base_url": "https://admin.118im.com",
|
||||||
|
"service_name": "im-workbench",
|
||||||
|
"secret": "<填 manager-system/im-manager-secrets 中的 IM_CONFIG_API_SECRET>",
|
||||||
|
"uid_key_group": "im",
|
||||||
|
"uid_key_keys": [
|
||||||
|
"uid_encryption_key",
|
||||||
|
"UID_ENCRYPTION_KEY",
|
||||||
|
"uid_key"
|
||||||
|
],
|
||||||
|
"timeout_ms": 3000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
也可以不用改 JSON,改成 Deployment 环境变量:
|
||||||
|
|
||||||
|
```text
|
||||||
|
IM_WORKBENCH_MANAGER_BASE_URL=https://admin.118im.com
|
||||||
|
IM_WORKBENCH_MANAGER_SERVICE_NAME=im-workbench
|
||||||
|
IM_WORKBENCH_MANAGER_SECRET=<填 manager-system/im-manager-secrets 中的 IM_CONFIG_API_SECRET>
|
||||||
|
```
|
||||||
|
|
||||||
|
建议优先统一放到 `workbench.json`,因为当前 workbench 已经通过 Secret 挂载 JSON 配置。
|
||||||
|
|
||||||
|
## 5. 推荐操作流程
|
||||||
|
|
||||||
|
### 步骤 1:更新 manager Secret
|
||||||
|
|
||||||
|
将:
|
||||||
|
|
||||||
|
```text
|
||||||
|
manager-system / im-manager-secrets / IM_CONFIG_API_SERVICE_NAME
|
||||||
|
```
|
||||||
|
|
||||||
|
改为:
|
||||||
|
|
||||||
|
```text
|
||||||
|
im-server,im-workbench
|
||||||
|
```
|
||||||
|
|
||||||
|
`IM_CONFIG_API_SECRET` 保持现有值。
|
||||||
|
|
||||||
|
### 步骤 2:更新 workbench Secret
|
||||||
|
|
||||||
|
从:
|
||||||
|
|
||||||
|
```text
|
||||||
|
manager-system / im-manager-secrets / IM_CONFIG_API_SECRET
|
||||||
|
```
|
||||||
|
|
||||||
|
取值,写入:
|
||||||
|
|
||||||
|
```text
|
||||||
|
workbench-system / im-workbench-secrets / workbench.json
|
||||||
|
```
|
||||||
|
|
||||||
|
目标字段:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"manager": {
|
||||||
|
"base_url": "https://admin.118im.com",
|
||||||
|
"service_name": "im-workbench",
|
||||||
|
"secret": "<IM_CONFIG_API_SECRET>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤 3:重启服务
|
||||||
|
|
||||||
|
更新 Secret 后需要重启 Pod,确保进程重新读取配置。
|
||||||
|
|
||||||
|
建议顺序:
|
||||||
|
|
||||||
|
```text
|
||||||
|
1. 重启 im-manager
|
||||||
|
2. 重启 im-workbench
|
||||||
|
```
|
||||||
|
|
||||||
|
原因:
|
||||||
|
|
||||||
|
- 先让 manager 支持 `im-workbench` service name。
|
||||||
|
- 再让 workbench 使用 `im-workbench` service name 去调用 manager。
|
||||||
|
|
||||||
|
## 6. 验证方法
|
||||||
|
|
||||||
|
### 6.1 验证 manager 是否接受 im-workbench
|
||||||
|
|
||||||
|
用 `IM_CONFIG_API_SECRET` 对请求签名,请求:
|
||||||
|
|
||||||
|
```text
|
||||||
|
GET https://admin.118im.com/internal/im-config/third-party/im?keys=uid_encryption_key,UID_ENCRYPTION_KEY,uid_key
|
||||||
|
X-Service-Name: im-workbench
|
||||||
|
```
|
||||||
|
|
||||||
|
期望结果:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 0,
|
||||||
|
"data": {
|
||||||
|
"values": {
|
||||||
|
"uid_encryption_key": "..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
如果返回 401,重点检查:
|
||||||
|
|
||||||
|
- `IM_CONFIG_API_SERVICE_NAME` 是否包含 `im-workbench`
|
||||||
|
- 请求里的 `X-Service-Name` 是否是 `im-workbench`
|
||||||
|
- `IM_CONFIG_API_SECRET` 是否和 manager 当前 Secret 一致
|
||||||
|
- 签名文本是否为:
|
||||||
|
|
||||||
|
```text
|
||||||
|
METHOD
|
||||||
|
RequestURI
|
||||||
|
BodySHA256
|
||||||
|
Timestamp
|
||||||
|
Nonce
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.2 验证 workbench 是否加载到 manager 配置
|
||||||
|
|
||||||
|
进入 workbench Pod 看环境和配置摘要,注意不要打印真实 secret:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl -n workbench-system exec <im-workbench-pod> -- sh -c 'env | grep IM_WORKBENCH_MANAGER'
|
||||||
|
```
|
||||||
|
|
||||||
|
或查看挂载配置:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl -n workbench-system exec <im-workbench-pod> -- sh -c 'cat /etc/im-workbench/workbench.json'
|
||||||
|
```
|
||||||
|
|
||||||
|
检查:
|
||||||
|
|
||||||
|
```text
|
||||||
|
manager.base_url = https://admin.118im.com
|
||||||
|
manager.service_name = im-workbench
|
||||||
|
manager.secret 非空
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.3 验证业务接口
|
||||||
|
|
||||||
|
从 IM 登录获取 token 后,请求 workbench 接口:
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET https://api.118im.com/v1/workbench
|
||||||
|
Authorization: Bearer <IM token>
|
||||||
|
X-MeetingIM-APIKey: <api key>
|
||||||
|
X-IM-Schema: 1
|
||||||
|
X-Tenant-Code: <tenant code>
|
||||||
|
```
|
||||||
|
|
||||||
|
期望:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
再创建会议,确认 user id 编解码和展示名正常:
|
||||||
|
|
||||||
|
```http
|
||||||
|
POST https://api.118im.com/v1/workbench/meetings
|
||||||
|
Idempotency-Key: <unique id>
|
||||||
|
Authorization: Bearer <IM token>
|
||||||
|
X-MeetingIM-APIKey: <api key>
|
||||||
|
X-IM-Schema: 1
|
||||||
|
X-Tenant-Code: <tenant code>
|
||||||
|
Content-Type: application/json
|
||||||
|
```
|
||||||
|
|
||||||
|
请求体示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"title": "运维验证会议",
|
||||||
|
"start_at": "2026-09-18T08:00:00Z",
|
||||||
|
"end_at": "2026-09-18T09:00:00Z",
|
||||||
|
"location": "",
|
||||||
|
"recorder_user_id": "usr...",
|
||||||
|
"attendee_user_ids": ["usr..."],
|
||||||
|
"reminder_minutes": []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
期望:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 0,
|
||||||
|
"data": {
|
||||||
|
"state": "scheduled",
|
||||||
|
"organizer": {
|
||||||
|
"user_id": "usr...",
|
||||||
|
"display_name": "..."
|
||||||
|
},
|
||||||
|
"participant_names": ["..."]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 7. 常见问题
|
||||||
|
|
||||||
|
### 7.1 为什么不能从 manager 读取 manager secret
|
||||||
|
|
||||||
|
因为 `IM_CONFIG_API_SECRET` 是调用 manager 配置接口的 HMAC 引导凭证。
|
||||||
|
|
||||||
|
如果要读取 manager 配置接口,必须先有这个 secret 才能签名。
|
||||||
|
所以它不能从同一个 manager 配置接口中获取,只能来自部署环境,例如 Kubernetes Secret。
|
||||||
|
|
||||||
|
### 7.2 为什么 service name 不是 im-server
|
||||||
|
|
||||||
|
`X-Service-Name` 表示调用方服务名。
|
||||||
|
|
||||||
|
- `im_server` 调 manager 时,应使用 `im-server`
|
||||||
|
- `im_workbench` 调 manager 时,应使用 `im-workbench`
|
||||||
|
|
||||||
|
manager 侧应该允许多个合法调用方:
|
||||||
|
|
||||||
|
```text
|
||||||
|
im-server,im-workbench
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.3 为什么配置了 .env 还是没用
|
||||||
|
|
||||||
|
因为 Kubernetes 不会自动读取仓库 `.env`。
|
||||||
|
|
||||||
|
`.env` 只有在以下情况才会生效:
|
||||||
|
|
||||||
|
- 程序代码主动 `godotenv.Load()`
|
||||||
|
- 启动脚本 `source .env`
|
||||||
|
- docker compose 配了 `env_file`
|
||||||
|
- CI/CD 将 `.env` 内容写进 Deployment 或 Secret
|
||||||
|
|
||||||
|
当前测试环境都不是这些方式。
|
||||||
|
|
||||||
|
### 7.4 只改 workbench 会怎样
|
||||||
|
|
||||||
|
如果只把 workbench 改成:
|
||||||
|
|
||||||
|
```text
|
||||||
|
X-Service-Name: im-workbench
|
||||||
|
```
|
||||||
|
|
||||||
|
但 manager 仍然只允许:
|
||||||
|
|
||||||
|
```text
|
||||||
|
IM_CONFIG_API_SERVICE_NAME=im-server
|
||||||
|
```
|
||||||
|
|
||||||
|
那么 workbench 调 manager 会返回 401。
|
||||||
|
|
||||||
|
所以需要 manager 和 workbench 一起配置。
|
||||||
|
|
||||||
|
## 8. 最终配置清单
|
||||||
|
|
||||||
|
manager:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Namespace: manager-system
|
||||||
|
Secret: im-manager-secrets
|
||||||
|
|
||||||
|
IM_CONFIG_API_SERVICE_NAME=im-server,im-workbench
|
||||||
|
IM_CONFIG_API_SECRET=<保持现有值>
|
||||||
|
```
|
||||||
|
|
||||||
|
workbench:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Namespace: workbench-system
|
||||||
|
Secret: im-workbench-secrets
|
||||||
|
Key: workbench.json
|
||||||
|
```
|
||||||
|
|
||||||
|
`workbench.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"manager": {
|
||||||
|
"base_url": "https://admin.118im.com",
|
||||||
|
"service_name": "im-workbench",
|
||||||
|
"secret": "<manager 的 IM_CONFIG_API_SECRET>",
|
||||||
|
"uid_key_group": "im",
|
||||||
|
"uid_key_keys": [
|
||||||
|
"uid_encryption_key",
|
||||||
|
"UID_ENCRYPTION_KEY",
|
||||||
|
"uid_key"
|
||||||
|
],
|
||||||
|
"timeout_ms": 3000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ func defaultConfig() *Config {
|
|||||||
RequiredAPIKey: true,
|
RequiredAPIKey: true,
|
||||||
},
|
},
|
||||||
Manager: ManagerConfig{
|
Manager: ManagerConfig{
|
||||||
ServiceName: "im-server",
|
ServiceName: "im-workbench",
|
||||||
UIDKeyGroup: "im",
|
UIDKeyGroup: "im",
|
||||||
UIDKeyKeys: []string{"uid_encryption_key", "UID_ENCRYPTION_KEY", "uid_key"},
|
UIDKeyKeys: []string{"uid_encryption_key", "UID_ENCRYPTION_KEY", "uid_key"},
|
||||||
TimeoutMS: 3000,
|
TimeoutMS: 3000,
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ func (c *Client) newRequest(ctx context.Context, method string, rawURL string, b
|
|||||||
_, _ = mac.Write([]byte(signingText))
|
_, _ = mac.Write([]byte(signingText))
|
||||||
serviceName := strings.TrimSpace(c.cfg.ServiceName)
|
serviceName := strings.TrimSpace(c.cfg.ServiceName)
|
||||||
if serviceName == "" {
|
if serviceName == "" {
|
||||||
serviceName = "im-server"
|
serviceName = "im-workbench"
|
||||||
}
|
}
|
||||||
req.Header.Set("Accept", "application/json")
|
req.Header.Set("Accept", "application/json")
|
||||||
req.Header.Set("X-Service-Name", serviceName)
|
req.Header.Set("X-Service-Name", serviceName)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ func TestResolveUIDKeyPrefersManager(t *testing.T) {
|
|||||||
if r.URL.Query().Get("keys") != "uid_encryption_key,UID_ENCRYPTION_KEY,uid_key" {
|
if r.URL.Query().Get("keys") != "uid_encryption_key,UID_ENCRYPTION_KEY,uid_key" {
|
||||||
t.Fatalf("unexpected keys %s", r.URL.Query().Get("keys"))
|
t.Fatalf("unexpected keys %s", r.URL.Query().Get("keys"))
|
||||||
}
|
}
|
||||||
if r.Header.Get("X-Service-Name") != "im-server" {
|
if r.Header.Get("X-Service-Name") != "im-workbench" {
|
||||||
t.Fatalf("unexpected service %s", r.Header.Get("X-Service-Name"))
|
t.Fatalf("unexpected service %s", r.Header.Get("X-Service-Name"))
|
||||||
}
|
}
|
||||||
if !validSignature(t, r, secret) {
|
if !validSignature(t, r, secret) {
|
||||||
@@ -36,7 +36,7 @@ func TestResolveUIDKeyPrefersManager(t *testing.T) {
|
|||||||
|
|
||||||
got := ResolveUIDKey(context.Background(), config.ManagerConfig{
|
got := ResolveUIDKey(context.Background(), config.ManagerConfig{
|
||||||
BaseURL: server.URL,
|
BaseURL: server.URL,
|
||||||
ServiceName: "im-server",
|
ServiceName: "im-workbench",
|
||||||
Secret: secret,
|
Secret: secret,
|
||||||
UIDKeyGroup: "im",
|
UIDKeyGroup: "im",
|
||||||
UIDKeyKeys: []string{"uid_encryption_key", "UID_ENCRYPTION_KEY", "uid_key"},
|
UIDKeyKeys: []string{"uid_encryption_key", "UID_ENCRYPTION_KEY", "uid_key"},
|
||||||
|
|||||||
Reference in New Issue
Block a user