fix: Windows syslog兼容 + API设计文档
This commit is contained in:
@@ -198,79 +198,91 @@ FILE_UPLOAD_MAX_MEMORY_SIZE = 524288000
|
|||||||
CELERY_BROKER_URL = 'redis://:xjjq1234!@localhost:6379/0'
|
CELERY_BROKER_URL = 'redis://:xjjq1234!@localhost:6379/0'
|
||||||
CELERY_RESULT_BACKEND = 'redis://:xjjq1234!@localhost:6379/0'
|
CELERY_RESULT_BACKEND = 'redis://:xjjq1234!@localhost:6379/0'
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
_is_linux = sys.platform == 'linux'
|
||||||
|
|
||||||
|
_syslog_handler = {
|
||||||
|
'level': 'WARNING',
|
||||||
|
'class': 'logging.handlers.SysLogHandler',
|
||||||
|
'address': '/dev/log',
|
||||||
|
'facility': 'local0',
|
||||||
|
'formatter': 'syslog',
|
||||||
|
} if _is_linux else {
|
||||||
|
'level': 'WARNING',
|
||||||
|
'class': 'logging.handlers.RotatingFileHandler',
|
||||||
|
'filename': str(LOG_DIR / 'syslog.log'),
|
||||||
|
'maxBytes': 1024 * 1024 * 50,
|
||||||
|
'backupCount': 5,
|
||||||
|
'formatter': 'standard',
|
||||||
|
'encoding': 'utf-8',
|
||||||
|
}
|
||||||
|
|
||||||
LOGGING = {
|
LOGGING = {
|
||||||
'version': 1,
|
'version': 1,
|
||||||
'disable_existing_loggers': False, # 不关闭已存在的日志器
|
'disable_existing_loggers': False,
|
||||||
'formatters': {
|
'formatters': {
|
||||||
'standard': { # 统一的标准日志格式
|
'standard': {
|
||||||
'format': '[%(asctime)s] [%(levelname)s] [%(process)d] [%(module)s] %(message)s',
|
'format': '[%(asctime)s] [%(levelname)s] [%(process)d] [%(module)s] %(message)s',
|
||||||
'datefmt': '%Y-%m-%d %H:%M:%S'
|
'datefmt': '%Y-%m-%d %H:%M:%S'
|
||||||
},
|
},
|
||||||
'syslog': { # syslog格式(用于fail2ban检测)
|
'syslog': {
|
||||||
'format': '%(name)s: %(levelname)s %(message)s'
|
'format': '%(name)s: %(levelname)s %(message)s'
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'handlers': {
|
'handlers': {
|
||||||
'file': { # 日志写入文件的处理器
|
'file': {
|
||||||
'level': 'INFO', # 日志级别:INFO及以上都记录(ERROR/WARNING/INFO)
|
'level': 'INFO',
|
||||||
'class': 'logging.handlers.RotatingFileHandler', # 日志轮转,防止文件过大
|
'class': 'logging.handlers.RotatingFileHandler',
|
||||||
# ✅ 核心:pathlib对象转字符串,logging只接收字符串路径,必转!
|
|
||||||
'filename': str(LOG_DIR / 'all_in_one.log'),
|
'filename': str(LOG_DIR / 'all_in_one.log'),
|
||||||
'maxBytes': 1024 * 1024 * 100, # 单个日志文件最大100MB
|
'maxBytes': 1024 * 1024 * 100,
|
||||||
'backupCount': 10, # 最多保留10个日志备份
|
'backupCount': 10,
|
||||||
'formatter': 'standard', # 使用上面定义的统一格式
|
'formatter': 'standard',
|
||||||
'encoding': 'utf-8', # 编码,防止中文乱码
|
'encoding': 'utf-8',
|
||||||
},
|
},
|
||||||
'console': { # 兼容控制台输出(开发调试用,不影响生产)
|
'console': {
|
||||||
'level': 'INFO',
|
'level': 'INFO',
|
||||||
'class': 'logging.StreamHandler',
|
'class': 'logging.StreamHandler',
|
||||||
'formatter': 'standard'
|
'formatter': 'standard'
|
||||||
},
|
},
|
||||||
'syslog': { # syslog处理器(用于fail2ban检测登录失败)
|
'syslog': _syslog_handler,
|
||||||
'level': 'WARNING',
|
'auth_file': {
|
||||||
'class': 'logging.handlers.SysLogHandler',
|
|
||||||
'address': '/dev/log', # Linux系统日志socket
|
|
||||||
'facility': 'local0',
|
|
||||||
'formatter': 'syslog',
|
|
||||||
},
|
|
||||||
'auth_file': { # 认证日志文件处理器(备选方案)
|
|
||||||
'level': 'WARNING',
|
'level': 'WARNING',
|
||||||
'class': 'logging.handlers.RotatingFileHandler',
|
'class': 'logging.handlers.RotatingFileHandler',
|
||||||
'filename': str(LOG_DIR / 'auth.log'),
|
'filename': str(LOG_DIR / 'auth.log'),
|
||||||
'maxBytes': 1024 * 1024 * 50, # 50MB
|
'maxBytes': 1024 * 1024 * 50,
|
||||||
'backupCount': 5,
|
'backupCount': 5,
|
||||||
'formatter': 'standard',
|
'formatter': 'standard',
|
||||||
'encoding': 'utf-8',
|
'encoding': 'utf-8',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
# 所有日志器配置和原配置完全一致,无需任何修改
|
|
||||||
'loggers': {
|
'loggers': {
|
||||||
'django': { # Django核心日志
|
'django': {
|
||||||
'handlers': ['file'],
|
'handlers': ['file'],
|
||||||
'level': 'INFO',
|
'level': 'INFO',
|
||||||
'propagate': True,
|
'propagate': True,
|
||||||
},
|
},
|
||||||
'django.request': { # Django的请求日志
|
'django.request': {
|
||||||
'handlers': ['file'],
|
'handlers': ['file'],
|
||||||
'level': 'INFO',
|
'level': 'INFO',
|
||||||
'propagate': True,
|
'propagate': True,
|
||||||
},
|
},
|
||||||
'django.security.login': { # 登录安全日志(用于fail2ban)
|
'django.security.login': {
|
||||||
'handlers': ['syslog', 'auth_file'],
|
'handlers': ['syslog', 'auth_file'],
|
||||||
'level': 'WARNING',
|
'level': 'WARNING',
|
||||||
'propagate': False,
|
'propagate': False,
|
||||||
},
|
},
|
||||||
'celery': { # Celery客户端日志(Django中提交任务的日志)
|
'celery': {
|
||||||
'handlers': ['file'],
|
'handlers': ['file'],
|
||||||
'level': 'INFO',
|
'level': 'INFO',
|
||||||
'propagate': True,
|
'propagate': True,
|
||||||
},
|
},
|
||||||
'utils.tasks': { # Celery邮件任务模块
|
'utils.tasks': {
|
||||||
'handlers': ['file'],
|
'handlers': ['file'],
|
||||||
'level': 'INFO',
|
'level': 'INFO',
|
||||||
'propagate': True,
|
'propagate': True,
|
||||||
},
|
},
|
||||||
'utils.email_utils': { # 邮件配置模块
|
'utils.email_utils': {
|
||||||
'handlers': ['file'],
|
'handlers': ['file'],
|
||||||
'level': 'INFO',
|
'level': 'INFO',
|
||||||
'propagate': True,
|
'propagate': True,
|
||||||
|
|||||||
73
docs/superpowers/specs/2026-06-07-api-token-auth-design.md
Normal file
73
docs/superpowers/specs/2026-06-07-api-token-auth-design.md
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
# API Token 鉴权与数据写入接口设计
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
为家庭日报系统增加 Token 鉴权机制,并通过 API 支持外部写入阅读记录、感悟记录、今日计划。
|
||||||
|
|
||||||
|
## Token 鉴权
|
||||||
|
|
||||||
|
- Token 存储在 `settings.py` 的 `API_TOKEN` 配置项中
|
||||||
|
- 请求需携带 `Authorization: Bearer <token>` 头
|
||||||
|
- 新建 `@require_api_token` 装饰器统一校验,校验失败返回 401
|
||||||
|
- 已有 API(`api_submit_summary`、`api_temp_upload`)同步加上鉴权(破坏性变更,需评估影响)
|
||||||
|
|
||||||
|
## 新增 API 端点
|
||||||
|
|
||||||
|
所有端点均为 POST,支持 `application/json` 和 `multipart/form-data`(文件上传场景)。统一返回格式:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"success": true/false, "message": "...", "id": ...}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1. POST /api/v1/insight/submit/ - 写入感悟记录
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| content | string | 是 | 感悟内容 |
|
||||||
|
| speaker | string | 是 | 发言人姓名,匹配 FamilyMember.name |
|
||||||
|
| date | string | 否 | 日期 YYYY-MM-DD,默认今天 |
|
||||||
|
| file | file | 否 | 附件 |
|
||||||
|
|
||||||
|
### 2. POST /api/v1/reading/submit/ - 写入阅读记录
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| type | string | 是 | 阅读类型,匹配 ReadingType.name |
|
||||||
|
| title | string | 是 | 标题 |
|
||||||
|
| source | string | 否 | 来源 |
|
||||||
|
| progress | string | 否 | 进度 |
|
||||||
|
| note | string | 否 | 阅读笔记 |
|
||||||
|
| date | string | 否 | 日期 YYYY-MM-DD,默认今天 |
|
||||||
|
| file | file | 否 | 附件 |
|
||||||
|
|
||||||
|
### 3. POST /api/v1/plan/submit/ - 写入今日计划
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| content | string | 是 | 计划内容 |
|
||||||
|
| speaker | string | 否 | 发言人,默认"机器人" |
|
||||||
|
| priority | string | 否 | 优先级,匹配 Priority.name,默认"中" |
|
||||||
|
| type | string | 否 | 类型,匹配 PlanType.name,默认"其他" |
|
||||||
|
| status | string | 否 | 状态,匹配 Status.name,默认"未开始" |
|
||||||
|
| date | string | 否 | 日期 YYYY-MM-DD,默认今天 |
|
||||||
|
|
||||||
|
## 实现范围
|
||||||
|
|
||||||
|
- `diary_family/settings.py`:新增 `API_TOKEN` 配置
|
||||||
|
- `core/views.py`:新增 `require_api_token` 装饰器、3 个 API 视图函数
|
||||||
|
- `core/urls.py`:新增 3 条路由
|
||||||
|
- 不引入 DRF,沿用项目现有 JsonResponse + 函数视图模式
|
||||||
|
- 不涉及数据库迁移
|
||||||
|
|
||||||
|
## 错误处理
|
||||||
|
|
||||||
|
- 401:Token 缺失或错误
|
||||||
|
- 400:必填字段缺失、外键匹配失败
|
||||||
|
- 405:非 POST 请求
|
||||||
|
- 500:服务器内部错误
|
||||||
|
- 所有错误统一返回 `{"success": false, "message": "错误描述"}`
|
||||||
|
|
||||||
|
## 向后兼容
|
||||||
|
|
||||||
|
- 已有 Web 页面功能不受影响
|
||||||
|
- 已有 API 端点加上 Token 鉴权(需同步更新调用方)
|
||||||
Reference in New Issue
Block a user