/api/plugins/frontuser/ext/**;本页所有接口均为一次同步请求-响应,由平台代执行。{code,data,message} 壳:
list → {items,limit,offset}、get → {id,data,created_at,updated_at}、
create/update → {id,data}、delete → {deleted:1};出错是 {"error":"..."}。POST /api/plugins/frontuser/users/login 返回的 ppk_ 令牌(7 天,仅本插件有效),
放在 Authorization: Bearer <token>;管理端用平台令牌。plugin = 全插件共享;caller = 每人一份数据岛(管理员跨岛可读全部)。phone / mobile / tel / email / mail / id_card 强制脱敏,返回值带星号,请勿把脱敏值原样写回。limit(默认 20,上限 200)、offset;q 对整条 data 做模糊匹配。| 集合 | 作用域 | 读 / 写层级 | 用途 |
|---|---|---|---|
| profiles | caller | L1 / L1 | 用户自助资料:名称、性别、用户模式、头像、生日、地区、语言、时区、联系方式、简介、标签、社交、分类、邀请码 |
| account_requests | caller | L1 / L1 | 改用户名 / 改密码 / 绑定 / 注销等账户变更申请单 |
| my_invites | caller | L1 / L1 | 我的邀请码与邀请记录 |
| login_logs | caller | L1 / L1 | 我的登录记录 |
| members | plugin | L2 / L2 | 用户扩展档案:分组、等级、分类、特权、角色、状态、积分、余额、VIP 到期、标签、来源、推荐人、备注 |
| member_cards | plugin | L1 / L2 | 管理员下发的前台可读权益卡(按 user_id 过滤) |
| groups | plugin | L1 / L2 | 用户分组 |
| levels | plugin | L1 / L2 | 用户等级(经验阈值、权益、自动升级) |
| categories | plugin | L1 / L2 | 用户分类 |
| privileges | plugin | L1 / L2 | 用户特权 |
| modes | plugin | L1 / L2 | 用户模式字典 |
| announcements | plugin | L1 / L2 | 公告消息 |
| handlings | plugin | L1 / L2 | 账户申请单处理记录(按 request_id 关联) |
| invites | plugin | L2 / L2 | 官方邀请码 |
| settings | plugin | L1 / L2 | 插件键值配置(前台读 site_notice 等公开配置) |
| audit_logs | plugin | L2 / L2 | 管理动作审计日志 |
| shared | plugin | L2 / L2 | 插件级共享数据(示例遗留集合,已补齐读改删) |
安全设计(平台 1.11.59+):写保护由平台按 op + scope 强制校验 ——
scope:plugin 的 create / update / delete 仅归属人与后台管理员可调用,与 level 无关;
L1 只降低读的门槛。普通用户写自己的数据请用 scope:caller。
隐私提示:member_cards / handlings / settings 是 L1 读的共享集合,
平台会返回全量记录。本插件前台用 q=user_id 做服务端过滤;
切勿在这些集合存放密码、密钥、身份证号等高敏信息。
| 方法 | 路径 | 层级 | 动作 | 集合 | 说明 |
|---|
401 需要登录 或 404。curl、Postman、或代码里的 fetch / requests 调用,并带对 HTTP 方法与请求头。ppk_... = 登录返回的令牌;<id> = 先 list 拿到的记录 id;<管理员令牌> / <平台令牌> = 你的 rap_ API Key 或后台 JWT。整段保存为 try.py 后 python try.py;会依次跑完 6 步并打印每步的 HTTP 状态。已实测 6 步全部 200。
import json, urllib.request, urllib.error, random, string
BASE = "https://cfapi.aog.cc"
P = "/api/plugins/frontuser"
ADMIN = "<管理员令牌>" # ← 只改这一行:换成你的 rap_ API Key
def call(method, path, body=None, token=None):
data = json.dumps(body, ensure_ascii=False).encode() if body is not None else None
h = {"Content-Type": "application/json"}
if token: h["Authorization"] = "Bearer " + token
req = urllib.request.Request(BASE + path, data=data, headers=h, method=method)
try:
with urllib.request.urlopen(req, timeout=20) as r:
return r.status, json.loads(r.read().decode())
except urllib.error.HTTPError as e:
return e.code, json.loads(e.read().decode())
u = "demo_" + "".join(random.choices(string.ascii_lowercase, k=5))
pw = "Demo123456"
print("1 注册 ", call("POST", P + "/users/register", {"username": u, "password": pw})[0])
s, d = call("POST", P + "/users/login", {"username": u, "password": pw})
ppk = d["data"]["token"]
print("2 登录 ", s, "ppk_ 长度", len(ppk))
print("3 读资料 ", call("GET", P + "/ext/profiles?limit=1", token=ppk))
s, d = call("POST", P + "/ext/profiles", {"user_id": 1, "username": u, "nick": "初始化"}, ppk)
rid = d["id"]
body = {"user_id": 1, "username": u, "nick": "小明", "gender": "male", "mode": "focus",
"phone": "", "email": "", "tags": [], "social": {}, "bio": "", "updated_at": 0}
print("4 整条覆盖 ", call("PUT", P + "/ext/profiles/" + rid, body, ppk)[0])
print("5 建等级 ", call("POST", P + "/ext/levels",
{"key": "lv6", "name": "至尊", "value": 6, "min_points": 50000,
"benefits": ["全部权益"], "sort": 6}, ADMIN)[0])
print("6 提 BUG ", call("POST", "/api/bugs",
{"title": "连通性自检", "description": "来自一键脚本", "severity": "low",
"plugin_code": "frontuser", "category": "文档"}, ADMIN)[0])
# 1) 注册
curl -X POST https://cfapi.aog.cc/api/plugins/frontuser/users/register \
-H 'Content-Type: application/json' \
-d '{"username":"demo","password":"Demo123456"}'
# 2) 登录,取 ppk_ 令牌(把返回值里的 data.token 填到下面 ppk_... 处)
curl -X POST https://cfapi.aog.cc/api/plugins/frontuser/users/login \
-H 'Content-Type: application/json' \
-d '{"username":"demo","password":"Demo123456"}'
# 3) 读我的资料(裸 JSON,注意没有 data 壳)
curl 'https://cfapi.aog.cc/api/plugins/frontuser/ext/profiles?limit=1' \
-H 'Authorization: Bearer ppk_...'
# 4) 幂等保存:先 list 拿自己的 id 替换 <id>,再 PUT 整条覆盖(不要每次 POST)
curl -X PUT 'https://cfapi.aog.cc/api/plugins/frontuser/ext/profiles/<id>' \
-H 'Authorization: Bearer ppk_...' -H 'Content-Type: application/json' \
-d '{"user_id":1,"username":"demo","nick":"小明","gender":"male","mode":"focus","phone":"","email":"","tags":[],"social":{},"bio":"","updated_at":0}'
# 5) 管理端:创建用户等级(需管理员令牌)
curl -X POST 'https://cfapi.aog.cc/api/plugins/frontuser/ext/levels' \
-H 'Authorization: Bearer <管理员令牌>' -H 'Content-Type: application/json' \
-d '{"key":"lv6","name":"至尊","value":6,"min_points":50000,"benefits":["全部权益"],"sort":6}'
# 6) 提交 BUG 反馈到平台 BUG 仓库
curl -X POST 'https://cfapi.aog.cc/api/bugs' \
-H 'Authorization: Bearer <平台令牌>' -H 'Content-Type: application/json' \
-d '{"title":"问题描述","description":"复现步骤","severity":"high","plugin_code":"frontuser","category":"服务端"}'
已修复并实测通过:L1 写越权(现按 op + scope 强制校验)、重复注册 500→409、 插件用户自助接口、管理端用户接口、用户列表分页/搜索/注册时间。
| 平台新增接口 | 用途 |
|---|---|
| GET / PATCH /users/me | 查看 / 修改自己的显示名、用户名、邮箱 |
| POST /users/me/password | 自助改密(返回新 ppk_ 令牌,旧令牌失效) |
| DELETE /users/me | 自助注销(软删,数据保留,管理员可恢复) |
| POST /users | 管理端建号 |
| GET / PATCH / DELETE /users/{id} | 单条查询、停用/启用、重置密码、删除 |
| GET /users?page=&page_size=&q=&status= | 分页返回 {items,total,page,page_size};不带参数仍返回数组 |
caller_sub(平台声明已加,线上未见);插件继续在资料里写 user_id 关联,并兼容 caller_sub。plugin 集合读返回全量 → 个人信息放 caller 或按 q 服务端过滤;
update 整条覆盖 → 读→改→整条写回;记录 ID 不可自定义、无 upsert → 用业务唯一键 + q 查询。PATCH /users/{id} 只接受固定字段(username / display_name / email / password / status),
不持久化任意扩展字段;分组、等级、特权等业务属性仍由插件 members 集合承载。bug.manage。前台用户 v2.3.2 · 全部功能开放 API · 由平台代执行