增加注册登录与鉴权,并按功能拆分 internal 模块

- 新增 /api/auth/register、/api/auth/login,JWT 签发与 Bearer 鉴权中间件
- notes 需登录,users/user-groups 仅管理员;auth 配置项随版本 1→2 自动补全
- internal/api 仅保留路由装配,拆分为 auth/user/usergroup/note/httpx/testutil
- 同步更新 Swagger 文档与前端注册接口路径
This commit is contained in:
2026-09-20 02:03:06 +08:00
parent c17fa0dba2
commit b683fb293e
24 files changed
+3002 -1116

No files matched your search

+646 -213
View File
File diff suppressed because it is too large. Load diff
+646 -213
View File
File diff suppressed because it is too large. Load diff
+442 -168
View File
@@ -1,11 +1,5 @@
basePath: /api
definitions:
api.ErrorResponse:
properties:
error:
example: 记录不存在
type: string
type: object
api.HealthResponse:
properties:
error:
@@ -15,146 +9,55 @@ definitions:
example: ok
type: string
type: object
api.NoteListResponse:
auth.LoginRequest:
properties:
items:
items:
$ref: '#/definitions/model.Note'
type: array
page:
example: 1
type: integer
page_size:
example: 20
type: integer
total:
example: 42
type: integer
type: object
api.NoteRequest:
properties:
content:
example: 牛奶、鸡蛋
account:
example: alice
type: string
title:
example: 购物清单
maxLength: 200
password:
example: secret123
type: string
required:
- title
- account
- password
type: object
api.UserCreateRequest:
auth.LoginResponse:
properties:
avatar:
example: https://example.com/avatar.png
maxLength: 255
expires_at:
example: "2026-09-21T10:00:00+08:00"
type: string
token:
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
type: string
user:
$ref: '#/definitions/model.User'
type: object
auth.RegisterRequest:
properties:
email:
example: alice@example.com
maxLength: 255
type: string
group_ids:
example:
- 1
items:
type: integer
type: array
nickname:
example: Alice
maxLength: 50
type: string
password:
example: secret123
maxLength: 72
minLength: 6
type: string
status:
enum:
- 0
- 1
example: 1
type: integer
username:
example: alice
maxLength: 50
minLength: 3
type: string
required:
- email
- password
- username
type: object
api.UserGroupListResponse:
httpx.ErrorResponse:
properties:
items:
items:
$ref: '#/definitions/model.UserGroup'
type: array
page:
example: 1
type: integer
page_size:
example: 20
type: integer
total:
example: 42
type: integer
type: object
api.UserGroupRequest:
properties:
description:
example: 负责日常运营
maxLength: 255
error:
example: 记录不存在
type: string
name:
example: 运营组
maxLength: 50
type: string
required:
- name
type: object
api.UserListResponse:
properties:
items:
items:
$ref: '#/definitions/model.User'
type: array
page:
example: 1
type: integer
page_size:
example: 20
type: integer
total:
example: 42
type: integer
type: object
api.UserUpdateRequest:
properties:
avatar:
example: https://example.com/avatar.png
maxLength: 255
type: string
group_ids:
example:
- 1
items:
type: integer
type: array
nickname:
example: Alice
maxLength: 50
type: string
password:
example: secret123
maxLength: 72
minLength: 6
type: string
status:
enum:
- 0
- 1
example: 1
type: integer
type: object
model.Note:
properties:
@@ -207,14 +110,229 @@ definitions:
updated_at:
type: string
type: object
note.ListResponse:
properties:
items:
items:
$ref: '#/definitions/model.Note'
type: array
page:
example: 1
type: integer
page_size:
example: 20
type: integer
total:
example: 42
type: integer
type: object
note.Request:
properties:
content:
example: 牛奶、鸡蛋
type: string
title:
example: 购物清单
maxLength: 200
type: string
required:
- title
type: object
user.CreateRequest:
properties:
avatar:
example: https://example.com/avatar.png
maxLength: 255
type: string
email:
example: alice@example.com
maxLength: 255
type: string
group_ids:
example:
- 1
items:
type: integer
type: array
nickname:
example: Alice
maxLength: 50
type: string
password:
example: secret123
maxLength: 72
minLength: 6
type: string
status:
enum:
- 0
- 1
example: 1
type: integer
username:
example: alice
maxLength: 50
type: string
required:
- email
- password
- username
type: object
user.ListResponse:
properties:
items:
items:
$ref: '#/definitions/model.User'
type: array
page:
example: 1
type: integer
page_size:
example: 20
type: integer
total:
example: 42
type: integer
type: object
user.UpdateRequest:
properties:
avatar:
example: https://example.com/avatar.png
maxLength: 255
type: string
group_ids:
example:
- 1
items:
type: integer
type: array
nickname:
example: Alice
maxLength: 50
type: string
password:
example: secret123
maxLength: 72
minLength: 6
type: string
status:
enum:
- 0
- 1
example: 1
type: integer
type: object
usergroup.ListResponse:
properties:
items:
items:
$ref: '#/definitions/model.UserGroup'
type: array
page:
example: 1
type: integer
page_size:
example: 20
type: integer
total:
example: 42
type: integer
type: object
usergroup.Request:
properties:
description:
example: 负责日常运营
maxLength: 255
type: string
name:
example: 运营组
maxLength: 50
type: string
required:
- name
type: object
info:
contact: {}
description: |-
Rill 服务端 HTTP API 文档,所有接口以配置项 api.prefix(默认 /api)为前缀,请求与响应均为 JSON。
Swagger 页面:{prefix}/swagger/index.htmlOpenAPI JSON{prefix}/swagger/doc.json。
除 health、swagger、auth 外,其余接口需要 Bearer JWT:先调用 /auth/login 获取 token,再在请求头携带 Authorization: Bearer {token}。
title: Rill API
version: "1.0"
paths:
/auth/login:
post:
consumes:
- application/json
description: 使用用户名或邮箱登录,成功返回 JWT(有效期见 auth.token_ttl)与用户信息。
parameters:
- description: 登录凭证
in: body
name: credentials
required: true
schema:
$ref: '#/definitions/auth.LoginRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/auth.LoginResponse'
"400":
description: 参数无效
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"401":
description: 账号或密码错误
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"403":
description: 账号已被禁用
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/httpx.ErrorResponse'
summary: Login
tags:
- auth
/auth/register:
post:
consumes:
- application/json
description: 公开注册,创建普通用户并默认加入普通用户组(id 1)。username 长度 3-50 且唯一,email 唯一,password
长度 6-72。
parameters:
- description: 注册信息
in: body
name: user
required: true
schema:
$ref: '#/definitions/auth.RegisterRequest'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/model.User'
"400":
description: 参数无效
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"409":
description: 用户名或邮箱已存在
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/httpx.ErrorResponse'
summary: Register
tags:
- auth
/health:
get:
description: 检查服务与数据库连接状态;数据库不可用时返回 503。
@@ -252,11 +370,21 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/api.NoteListResponse'
$ref: '#/definitions/note.ListResponse'
"401":
description: 未登录或登录已过期
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"403":
description: 账号已被禁用
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
security:
- BearerAuth: []
summary: List notes
tags:
- notes
@@ -270,7 +398,7 @@ paths:
name: note
required: true
schema:
$ref: '#/definitions/api.NoteRequest'
$ref: '#/definitions/note.Request'
produces:
- application/json
responses:
@@ -281,11 +409,21 @@ paths:
"400":
description: 参数无效
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"401":
description: 未登录或登录已过期
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"403":
description: 账号已被禁用
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
security:
- BearerAuth: []
summary: Create a note
tags:
- notes
@@ -307,15 +445,25 @@ paths:
"400":
description: id 无效
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"401":
description: 未登录或登录已过期
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"403":
description: 账号已被禁用
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"404":
description: 记录不存在
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
security:
- BearerAuth: []
summary: Delete a note
tags:
- notes
@@ -338,15 +486,25 @@ paths:
"400":
description: id 无效
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"401":
description: 未登录或登录已过期
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"403":
description: 账号已被禁用
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"404":
description: 记录不存在
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
security:
- BearerAuth: []
summary: Get a note
tags:
- notes
@@ -366,7 +524,7 @@ paths:
name: note
required: true
schema:
$ref: '#/definitions/api.NoteRequest'
$ref: '#/definitions/note.Request'
produces:
- application/json
responses:
@@ -377,15 +535,25 @@ paths:
"400":
description: 参数无效或 id 无效
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"401":
description: 未登录或登录已过期
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"403":
description: 账号已被禁用
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"404":
description: 记录不存在
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
security:
- BearerAuth: []
summary: Update a note
tags:
- notes
@@ -409,11 +577,21 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/api.UserGroupListResponse'
$ref: '#/definitions/usergroup.ListResponse'
"401":
description: 未登录或登录已过期
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"403":
description: 需要管理员权限或账号已被禁用
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
security:
- BearerAuth: []
summary: List user groups
tags:
- user-groups
@@ -427,7 +605,7 @@ paths:
name: group
required: true
schema:
$ref: '#/definitions/api.UserGroupRequest'
$ref: '#/definitions/usergroup.Request'
produces:
- application/json
responses:
@@ -438,15 +616,25 @@ paths:
"400":
description: 参数无效
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"401":
description: 未登录或登录已过期
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"403":
description: 需要管理员权限或账号已被禁用
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"409":
description: 用户组名称已存在
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
security:
- BearerAuth: []
summary: Create a user group
tags:
- user-groups
@@ -468,19 +656,29 @@ paths:
"400":
description: id 无效
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"401":
description: 未登录或登录已过期
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"403":
description: 需要管理员权限或账号已被禁用
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"404":
description: 记录不存在
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"409":
description: 系统内置组不可删除或用户组内仍有用户
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
security:
- BearerAuth: []
summary: Delete a user group
tags:
- user-groups
@@ -503,15 +701,25 @@ paths:
"400":
description: id 无效
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"401":
description: 未登录或登录已过期
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"403":
description: 需要管理员权限或账号已被禁用
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"404":
description: 记录不存在
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
security:
- BearerAuth: []
summary: Get a user group
tags:
- user-groups
@@ -531,7 +739,7 @@ paths:
name: group
required: true
schema:
$ref: '#/definitions/api.UserGroupRequest'
$ref: '#/definitions/usergroup.Request'
produces:
- application/json
responses:
@@ -542,19 +750,29 @@ paths:
"400":
description: 参数无效或 id 无效
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"401":
description: 未登录或登录已过期
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"403":
description: 需要管理员权限或账号已被禁用
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"404":
description: 记录不存在
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"409":
description: 用户组名称已存在
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
security:
- BearerAuth: []
summary: Update a user group
tags:
- user-groups
@@ -578,11 +796,21 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/api.UserListResponse'
$ref: '#/definitions/user.ListResponse'
"401":
description: 未登录或登录已过期
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"403":
description: 需要管理员权限或账号已被禁用
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
security:
- BearerAuth: []
summary: List users
tags:
- users
@@ -597,7 +825,7 @@ paths:
name: user
required: true
schema:
$ref: '#/definitions/api.UserCreateRequest'
$ref: '#/definitions/user.CreateRequest'
produces:
- application/json
responses:
@@ -608,15 +836,25 @@ paths:
"400":
description: 参数无效或用户组不存在
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"401":
description: 未登录或登录已过期
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"403":
description: 需要管理员权限或账号已被禁用
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"409":
description: 用户名或邮箱已存在
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
security:
- BearerAuth: []
summary: Create a user
tags:
- users
@@ -638,15 +876,25 @@ paths:
"400":
description: id 无效
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"401":
description: 未登录或登录已过期
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"403":
description: 需要管理员权限或账号已被禁用
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"404":
description: 记录不存在
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
security:
- BearerAuth: []
summary: Delete a user
tags:
- users
@@ -669,15 +917,25 @@ paths:
"400":
description: id 无效
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"401":
description: 未登录或登录已过期
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"403":
description: 需要管理员权限或账号已被禁用
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"404":
description: 记录不存在
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
security:
- BearerAuth: []
summary: Get a user
tags:
- users
@@ -697,7 +955,7 @@ paths:
name: user
required: true
schema:
$ref: '#/definitions/api.UserUpdateRequest'
$ref: '#/definitions/user.UpdateRequest'
produces:
- application/json
responses:
@@ -708,16 +966,32 @@ paths:
"400":
description: 参数无效、id 无效或用户组不存在
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"401":
description: 未登录或登录已过期
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"403":
description: 需要管理员权限或账号已被禁用
schema:
$ref: '#/definitions/httpx.ErrorResponse'
"404":
description: 记录不存在
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/api.ErrorResponse'
$ref: '#/definitions/httpx.ErrorResponse'
security:
- BearerAuth: []
summary: Update a user
tags:
- users
securityDefinitions:
BearerAuth:
description: Bearer JWT,格式:Bearer {token},通过 /auth/login 获取
in: header
name: Authorization
type: apiKey
swagger: "2.0"