From aaaecbfab4cd25895738793607839cdf84ac2cd2 Mon Sep 17 00:00:00 2001 From: furu04 Date: Wed, 25 Mar 2026 10:37:06 +0900 Subject: [PATCH] =?UTF-8?q?README=E3=80=81=E3=83=89=E3=82=AD=E3=83=A5?= =?UTF-8?q?=E3=83=A1=E3=83=B3=E3=83=88=E3=82=92=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 155 +++++++-------- docs/API.md | 424 +++++++++++++++++++++++++++--------------- docs/SPECIFICATION.md | 68 +++++-- 3 files changed, 401 insertions(+), 246 deletions(-) diff --git a/README.md b/README.md index f157458..2f40717 100644 --- a/README.md +++ b/README.md @@ -1,102 +1,105 @@ -# Homework Manager +
-シンプルな課題管理アプリケーションです。学生の課題管理を効率化するために設計されています。 +# Super Homework Manager + +シンプルで高機能な課題管理アプリケーション + +[![Go](https://img.shields.io/badge/Go-1.24+-00ADD8?logo=go&logoColor=white)](https://go.dev/) +[![License](https://img.shields.io/badge/License-AGPLv3-blue.svg)](LICENSE.md) +[![Docker](https://img.shields.io/badge/Docker-Compose-2496ED?logo=docker&logoColor=white)](#docker-での実行) + +
+ +--- + +## 概要 + +学生の課題管理を効率化するために設計されたWebアプリケーションです。 +繰り返し課題の自動生成やダッシュボードによる期限管理など、日々の課題管理をサポートします。 + +## スクリーンショット + +| ダッシュボード | 課題一覧 | API | +|:---:|:---:|:---:| +| ![ダッシュボード](./docs/images/dashboard.png) | ![課題一覧](./docs/images/list.png) | ![API](./docs/images/api.png) | ## 特徴 -- **課題管理**: 課題の登録、編集、削除、完了状況の管理 -- **繰り返し課題**: 日次・週次・月次の繰り返し課題を自動生成・管理 -- **ダッシュボード**: 期限切れ、本日期限、今週期限の課題をひと目で確認 -- **API対応**: 外部連携用のRESTful API (APIキー認証) -- **セキュリティ**: - - CSRF対策 - - レート制限 (Rate Limiting) - - セキュアなセッション管理 -- **ポータビリティ**: Pure Go SQLiteドライバー使用により、CGO不要でどこでも動作 +| 機能 | 説明 | +|---|---| +| **課題管理** | 課題の登録・編集・削除・完了状況の管理 | +| **繰り返し課題** | 日次・週次・月次の繰り返し課題を自動生成 | +| **ダッシュボード** | 期限切れ・本日期限・今週期限の課題をひと目で確認 | +| **REST API** | 外部連携用のAPIキー認証付きRESTful API | +| **セキュリティ** | CSRF対策 / レート制限 / セキュアなセッション管理 / 2FA対応 | +| **ポータビリティ** | Pure Go SQLiteドライバー使用でCGO不要 | -![ダッシュボード](./docs/images/dashboard.png) -![課題一覧](./docs/images/list.png) -![API](./docs/images/api.png) +## クイックスタート +### 前提条件 -## TODO +- **Go 1.24 以上** (ローカルビルドの場合) +- **Docker / Docker Compose** (コンテナ実行の場合) -- 取り組み目安時間の登録 -- SNS連携(もしかしたらやるかも) +### ローカルで実行 -## ドキュメント +```bash +# 1. リポジトリのクローン +git clone +cd Homework-Manager -詳細な仕様やAPIドキュメントは `docs/` ディレクトリを参照してください。 +# 2. 依存関係のダウンロード +go mod download -- [仕様書](docs/SPECIFICATION.md): 機能詳細、データモデル、設定項目 -- [APIドキュメント](docs/API.md): APIのエンドポイント、リクエスト/レスポンス形式 +# 3. ビルド +go build -o homework-manager cmd/server/main.go -## 前提条件 +# 4. 設定ファイルの準備 +cp config.ini.example config.ini -- Go 1.24 以上 +# 5. 実行 +./homework-manager +``` -## インストール方法 +> **Windows (PowerShell)** の場合: +> `Copy-Item config.ini.example config.ini` → `.\homework-manager.exe` -1. **リポジトリのクローン** - ```bash - git clone - cd Homework-Manager - ``` +ブラウザで **http://localhost:8080** にアクセスしてください。 -2. **依存関係のダウンロード** - ```bash - go mod download - ``` +### Docker での実行 -3. **アプリケーションのビルド** - ```bash - go build -o homework-manager cmd/server/main.go - ``` +```bash +# 1. 設定ファイルの準備 (必須 ※これを行わないとDockerがディレクトリとして作成し起動に失敗します) +cp config.ini.example config.ini -4. **設定ファイルの準備** - サンプル設定ファイルをコピーして、`config.ini` を作成します。 - - ```bash - cp config.ini.example config.ini - ``` - ※ Windows (PowerShell): `Copy-Item config.ini.example config.ini` +# 2. コンテナの起動 +docker-compose up -d --build +``` - **重要**: 本番環境で使用する場合は、必ず `[session] secret` と `[security] csrf_secret` を変更してください。 - -5. **アプリケーションの実行** - ```bash - ./homework-manager - ``` - ※ Windows (PowerShell): `.\homework-manager.exe` - - ブラウザで `http://localhost:8080` にアクセスしてください。 - -## Dockerでの実行 - -DockerおよびDocker Composeがインストールされている環境では、以下の手順で簡単に起動できます。 - -1. **設定ファイルの準備** - ```bash - cp config.ini.example config.ini - ``` - ※ 必須です。これを行わないとDockerがディレクトリとして作成してしまい起動に失敗します。 - -2. **コンテナの起動** - ```bash - docker-compose up -d --build - ``` - -3. **アクセスの確認** - ブラウザで `http://localhost:8080` にアクセスしてください。 +ブラウザで **http://localhost:8080** にアクセスしてください。 +> **注意**: 本番環境で使用する場合は、`config.ini` の `[session] secret` と `[security] csrf_secret` を必ず変更してください。 ## 更新方法 -1. `git pull` で最新コードを取得 -2. `go build -o homework-manager cmd/server/main.go` で再ビルド -3. アプリケーションを再起動 +```bash +git pull +go build -o homework-manager cmd/server/main.go +# アプリケーションを再起動 +``` + +## ドキュメント + +| ドキュメント | 内容 | +|---|---| +| [仕様書](docs/SPECIFICATION.md) | 機能詳細・データモデル・設定項目 | +| [APIドキュメント](docs/API.md) | エンドポイント・リクエスト/レスポンス形式 | + +## TODO + +- [ ] 取り組み目安時間の登録 +- [ ] SNS連携 ## ライセンス -本ソフトウェアのライセンスはAGPLv3 (GNU Affero General Public License v3)です。 -詳しくはLICENSEファイルをご覧ください。 \ No newline at end of file +[AGPLv3 (GNU Affero General Public License v3)](LICENSE.md) diff --git a/docs/API.md b/docs/API.md index 0ffc114..ac4420e 100644 --- a/docs/API.md +++ b/docs/API.md @@ -40,7 +40,12 @@ Authorization: Bearer hm_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | メソッド | パス | 説明 | |----------|------|------| -| GET | `/api/v1/assignments` | 課題一覧取得 | +| GET | `/api/v1/assignments` | 課題一覧取得(フィルタ・ページネーション対応) | +| GET | `/api/v1/assignments/pending` | 未完了課題一覧取得 | +| GET | `/api/v1/assignments/completed` | 完了済み課題一覧取得 | +| GET | `/api/v1/assignments/overdue` | 期限切れ課題一覧取得 | +| GET | `/api/v1/assignments/due-today` | 本日期限の課題一覧取得 | +| GET | `/api/v1/assignments/due-this-week` | 今週期限の課題一覧取得 | | GET | `/api/v1/assignments/:id` | 課題詳細取得 | | POST | `/api/v1/assignments` | 課題作成 | | PUT | `/api/v1/assignments/:id` | 課題更新 | @@ -64,7 +69,9 @@ GET /api/v1/assignments | パラメータ | 型 | 説明 | |------------|------|------| -| `filter` | string | フィルタ: `pending`, `completed`, `overdue` (省略時: 全件) | +| `filter` | string | フィルタ: `pending`, `completed`, `overdue`(省略時: 全件) | +| `page` | integer | ページ番号(デフォルト: `1`) | +| `page_size` | integer | 1ページあたりの件数(デフォルト: `20`、最大: `100`) | ### レスポンス @@ -79,13 +86,18 @@ GET /api/v1/assignments "title": "数学レポート", "description": "第5章の練習問題", "subject": "数学", + "priority": "medium", "due_date": "2025-01-15T23:59:00+09:00", "is_completed": false, "created_at": "2025-01-10T10:00:00+09:00", "updated_at": "2025-01-10T10:00:00+09:00" } ], - "count": 1 + "count": 1, + "total_count": 15, + "total_pages": 1, + "current_page": 1, + "page_size": 20 } ``` @@ -95,11 +107,43 @@ GET /api/v1/assignments # 全件取得 curl -H "Authorization: Bearer hm_xxx" http://localhost:8080/api/v1/assignments -# 未完了のみ取得 -curl -H "Authorization: Bearer hm_xxx" http://localhost:8080/api/v1/assignments?filter=pending +# 未完了のみ(ページネーション付き) +curl -H "Authorization: Bearer hm_xxx" "http://localhost:8080/api/v1/assignments?filter=pending&page=1&page_size=10" -# 期限切れのみ取得 -curl -H "Authorization: Bearer hm_xxx" http://localhost:8080/api/v1/assignments?filter=overdue +# 期限切れのみ +curl -H "Authorization: Bearer hm_xxx" "http://localhost:8080/api/v1/assignments?filter=overdue" +``` + +--- + +## 絞り込み済み課題一覧取得 + +専用エンドポイントでも同等の絞り込みができます(`pending` / `completed` / `overdue` はページネーション対応)。 + +``` +GET /api/v1/assignments/pending +GET /api/v1/assignments/completed +GET /api/v1/assignments/overdue +GET /api/v1/assignments/due-today +GET /api/v1/assignments/due-this-week +``` + +### クエリパラメータ(pending / completed / overdue のみ) + +| パラメータ | 型 | 説明 | +|------------|------|------| +| `page` | integer | ページ番号(デフォルト: `1`) | +| `page_size` | integer | 1ページあたりの件数(デフォルト: `20`、最大: `100`) | + +### レスポンス + +`due-today` / `due-this-week` は `count` のみ返します(ページネーションなし)。その他は `GET /api/v1/assignments` と同形式です。 + +### 例 + +```bash +curl -H "Authorization: Bearer hm_xxx" http://localhost:8080/api/v1/assignments/due-today +curl -H "Authorization: Bearer hm_xxx" http://localhost:8080/api/v1/assignments/due-this-week ``` --- @@ -127,6 +171,7 @@ GET /api/v1/assignments/:id "title": "数学レポート", "description": "第5章の練習問題", "subject": "数学", + "priority": "medium", "due_date": "2025-01-15T23:59:00+09:00", "is_completed": false, "created_at": "2025-01-10T10:00:00+09:00", @@ -163,29 +208,30 @@ POST /api/v1/assignments | `title` | string | ✅ | 課題タイトル | | `description` | string | | 説明 | | `subject` | string | | 教科・科目 | +| `priority` | string | | 重要度: `low`, `medium`, `high`(デフォルト: `medium`) | | `due_date` | string | ✅ | 提出期限(RFC3339 または `YYYY-MM-DDTHH:MM` または `YYYY-MM-DD`) | -| `reminder_enabled` | boolean | | リマインダーを有効にするか(省略時: false) | -| `reminder_at` | string | | リマインダー設定時刻(形式はdue_dateと同じ) | -| `urgent_reminder_enabled` | boolean | | 期限切れ時の督促リマインダーを有効にするか(省略時: true) | -| `recurrence` | object | | 繰り返し設定(以下参照) | +| `reminder_enabled` | boolean | | リマインダーを有効にするか(デフォルト: `false`) | +| `reminder_at` | string | | リマインダー設定時刻(形式は `due_date` と同じ) | +| `urgent_reminder_enabled` | boolean | | 督促リマインダーを有効にするか(デフォルト: `true`) | +| `recurrence` | object | | 繰り返し設定(下記参照) | ### Recurrence オブジェクト | フィールド | 型 | 説明 | |------------|------|------| -| `type` | string | 繰り返しタイプ (`daily`, `weekly`, `monthly`, または空文字で無効) | -| `interval` | integer | 間隔 (例: 1 = 毎週, 2 = 隔週) | -| `weekday` | integer | 週次の曜日 (0=日, 1=月, ..., 6=土) | -| `day` | integer | 月次の日付 (1-31) | +| `type` | string | 繰り返しタイプ: `daily`, `weekly`, `monthly`(空文字で繰り返しなし) | +| `interval` | integer | 繰り返し間隔(例: `1` = 毎週、`2` = 隔週) | +| `weekday` | integer | 週次の曜日(`0`=日, `1`=月, ..., `6`=土) | +| `day` | integer | 月次の日付(1-31) | | `until` | object | 終了条件 | #### Recurrence.Until オブジェクト | フィールド | 型 | 説明 | |------------|------|------| -| `type` | string | 終了タイプ (`never`, `count`, `date`) | -| `count` | integer | 回数指定時の終了回数 | -| `date` | string | 日付指定時の終了日 | +| `type` | string | 終了タイプ: `never`, `count`, `date` | +| `count` | integer | 終了回数(`count` 指定時) | +| `date` | string | 終了日(`date` 指定時) | ### リクエスト例 @@ -194,6 +240,7 @@ POST /api/v1/assignments "title": "英語エッセイ", "description": "テーマ自由、1000語以上", "subject": "英語", + "priority": "high", "due_date": "2025-01-20T17:00" } ``` @@ -209,6 +256,7 @@ POST /api/v1/assignments "title": "英語エッセイ", "description": "テーマ自由、1000語以上", "subject": "英語", + "priority": "high", "due_date": "2025-01-20T17:00:00+09:00", "is_completed": false, "created_at": "2025-01-10T11:00:00+09:00", @@ -216,11 +264,20 @@ POST /api/v1/assignments } ``` +繰り返し設定を含む場合は `recurring_assignment` を返します: + +```json +{ + "message": "Recurring assignment created", + "recurring_assignment": { ... } +} +``` + **400 Bad Request** ```json { - "error": "Invalid input: title and due_date are required" + "error": "Invalid input: Key: 'title' Error:Field validation for 'title' failed on the 'required' tag" } ``` @@ -230,7 +287,7 @@ POST /api/v1/assignments curl -X POST \ -H "Authorization: Bearer hm_xxx" \ -H "Content-Type: application/json" \ - -d '{"title":"英語エッセイ","due_date":"2025-01-20"}' \ + -d '{"title":"英語エッセイ","subject":"英語","due_date":"2025-01-20"}' \ http://localhost:8080/api/v1/assignments ``` @@ -257,6 +314,7 @@ PUT /api/v1/assignments/:id | `title` | string | 課題タイトル | | `description` | string | 説明 | | `subject` | string | 教科・科目 | +| `priority` | string | 重要度: `low`, `medium`, `high` | | `due_date` | string | 提出期限 | | `reminder_enabled` | boolean | リマインダー有効/無効 | | `reminder_at` | string | リマインダー時刻 | @@ -273,21 +331,7 @@ PUT /api/v1/assignments/:id ### レスポンス -**200 OK** - -```json -{ - "id": 2, - "user_id": 1, - "title": "英語エッセイ(修正版)", - "description": "テーマ自由、1000語以上", - "subject": "英語", - "due_date": "2025-01-25T17:00:00+09:00", - "is_completed": false, - "created_at": "2025-01-10T11:00:00+09:00", - "updated_at": "2025-01-10T12:00:00+09:00" -} -``` +**200 OK** — 更新後の課題オブジェクト **404 Not Found** @@ -332,25 +376,33 @@ DELETE /api/v1/assignments/:id **200 OK** ```json -{ - "message": "Assignment deleted" -} +{ "message": "Assignment deleted" } +``` + +繰り返し設定も削除した場合: + +```json +{ "message": "Assignment and recurring settings deleted" } ``` **404 Not Found** ```json -{ - "error": "Assignment not found" -} +{ "error": "Assignment not found" } ``` ### 例 ```bash +# 課題のみ削除 curl -X DELETE \ -H "Authorization: Bearer hm_xxx" \ http://localhost:8080/api/v1/assignments/2 + +# 課題と繰り返し設定をまとめて削除 +curl -X DELETE \ + -H "Authorization: Bearer hm_xxx" \ + "http://localhost:8080/api/v1/assignments/2?delete_recurring=true" ``` --- @@ -380,6 +432,7 @@ PATCH /api/v1/assignments/:id/toggle "title": "数学レポート", "description": "第5章の練習問題", "subject": "数学", + "priority": "medium", "due_date": "2025-01-15T23:59:00+09:00", "is_completed": true, "completed_at": "2025-01-12T14:30:00+09:00", @@ -391,9 +444,7 @@ PATCH /api/v1/assignments/:id/toggle **404 Not Found** ```json -{ - "error": "Assignment not found" -} +{ "error": "Assignment not found" } ``` ### 例 @@ -408,7 +459,7 @@ curl -X PATCH \ ## 統計情報取得 -ユーザーの課題統計を取得します。科目、日付範囲でフィルタリング可能です。 +ユーザーの課題統計を取得します。 ``` GET /api/v1/statistics @@ -419,8 +470,9 @@ GET /api/v1/statistics | パラメータ | 型 | 説明 | |------------|------|------| | `subject` | string | 科目で絞り込み(省略時: 全科目) | -| `from` | string | 課題登録日の開始日(YYYY-MM-DD形式) | -| `to` | string | 課題登録日の終了日(YYYY-MM-DD形式) | +| `from` | string | 課題登録日の開始日(`YYYY-MM-DD`) | +| `to` | string | 課題登録日の終了日(`YYYY-MM-DD`) | +| `include_archived` | boolean | アーカイブ済み課題を含む(デフォルト: `false`) | ### レスポンス @@ -446,36 +498,11 @@ GET /api/v1/statistics "pending": 2, "overdue": 1, "on_time_completion_rate": 91.7 - }, - { - "subject": "英語", - "total": 10, - "completed": 8, - "pending": 2, - "overdue": 0, - "on_time_completion_rate": 87.5 } ] } ``` -### 科目別統計 (特定科目のみ) - -```json -{ - "total_assignments": 15, - "completed_assignments": 12, - "pending_assignments": 2, - "overdue_assignments": 1, - "on_time_completion_rate": 91.7, - "filter": { - "subject": "数学", - "from": null, - "to": null - } -} -``` - ### 例 ```bash @@ -487,9 +514,175 @@ curl -H "Authorization: Bearer hm_xxx" "http://localhost:8080/api/v1/statistics? # 日付範囲で絞り込み curl -H "Authorization: Bearer hm_xxx" "http://localhost:8080/api/v1/statistics?from=2025-01-01&to=2025-03-31" +``` -# 科目と日付範囲の組み合わせ -curl -H "Authorization: Bearer hm_xxx" "http://localhost:8080/api/v1/statistics?subject=数学&from=2025-01-01&to=2025-03-31" +--- + +## 繰り返し設定一覧取得 + +``` +GET /api/v1/recurring +``` + +### レスポンス + +**200 OK** + +```json +{ + "recurring_assignments": [ + { + "id": 1, + "user_id": 1, + "title": "週次ミーティング", + "subject": "その他", + "priority": "medium", + "recurrence_type": "weekly", + "recurrence_interval": 1, + "recurrence_weekday": 1, + "due_time": "23:59", + "end_type": "never", + "is_active": true, + "created_at": "2025-01-01T00:00:00+09:00", + "updated_at": "2025-01-01T00:00:00+09:00" + } + ], + "count": 1 +} +``` + +--- + +## 繰り返し設定詳細取得 + +``` +GET /api/v1/recurring/:id +``` + +### パスパラメータ + +| パラメータ | 型 | 説明 | +|------------|------|------| +| `id` | integer | 繰り返し設定ID | + +### レスポンス + +**200 OK** — 繰り返し設定オブジェクト(一覧と同形式) + +**404 Not Found** + +```json +{ "error": "Recurring assignment not found" } +``` + +--- + +## 繰り返し設定更新 + +``` +PUT /api/v1/recurring/:id +``` + +### パスパラメータ + +| パラメータ | 型 | 説明 | +|------------|------|------| +| `id` | integer | 繰り返し設定ID | + +### リクエストボディ + +すべてのフィールドはオプションです。省略されたフィールドは既存の値を維持します。 + +| フィールド | 型 | 説明 | +|------------|------|------| +| `title` | string | タイトル | +| `description` | string | 説明 | +| `subject` | string | 教科・科目 | +| `priority` | string | 重要度: `low`, `medium`, `high` | +| `recurrence_type` | string | 繰り返しタイプ: `daily`, `weekly`, `monthly` | +| `recurrence_interval` | integer | 繰り返し間隔 | +| `recurrence_weekday` | integer | 週次の曜日(0-6) | +| `recurrence_day` | integer | 月次の日付(1-31) | +| `due_time` | string | 締切時刻(`HH:MM`) | +| `end_type` | string | 終了タイプ: `never`, `count`, `date` | +| `end_count` | integer | 終了回数 | +| `end_date` | string | 終了日(`YYYY-MM-DD`) | +| `is_active` | boolean | `false` で停止、`true` で再開 | +| `reminder_enabled` | boolean | リマインダー有効/無効 | +| `reminder_offset` | integer | リマインダーのオフセット(分) | +| `urgent_reminder_enabled` | boolean | 督促リマインダー有効/無効 | +| `edit_behavior` | string | 編集範囲: `this_only`, `this_and_future`, `all`(デフォルト: `this_only`) | + +### リクエスト例(一時停止) + +```json +{ + "is_active": false +} +``` + +### レスポンス + +**200 OK** — 更新後の繰り返し設定オブジェクト + +**404 Not Found** + +```json +{ "error": "Recurring assignment not found" } +``` + +### 例 + +```bash +# 一時停止 +curl -X PUT \ + -H "Authorization: Bearer hm_xxx" \ + -H "Content-Type: application/json" \ + -d '{"is_active": false}' \ + http://localhost:8080/api/v1/recurring/1 + +# タイトルと締切時刻を変更 +curl -X PUT \ + -H "Authorization: Bearer hm_xxx" \ + -H "Content-Type: application/json" \ + -d '{"title":"更新済みタスク","due_time":"22:00"}' \ + http://localhost:8080/api/v1/recurring/1 +``` + +--- + +## 繰り返し設定削除 + +``` +DELETE /api/v1/recurring/:id +``` + +### パスパラメータ + +| パラメータ | 型 | 説明 | +|------------|------|------| +| `id` | integer | 繰り返し設定ID | + +### レスポンス + +**200 OK** + +```json +{ "message": "Recurring assignment deleted" } +``` + +**404 Not Found** + +```json +{ "error": "Recurring assignment not found or failed to delete" } +``` + +### 例 + +```bash +curl -X DELETE \ + -H "Authorization: Bearer hm_xxx" \ + http://localhost:8080/api/v1/recurring/1 ``` --- @@ -511,6 +704,7 @@ curl -H "Authorization: Bearer hm_xxx" "http://localhost:8080/api/v1/statistics? | 400 Bad Request | リクエストの形式が不正 | | 401 Unauthorized | 認証エラー | | 404 Not Found | リソースが見つからない | +| 429 Too Many Requests | レート制限超過 | | 500 Internal Server Error | サーバー内部エラー | --- @@ -521,7 +715,7 @@ APIは以下の日付形式を受け付けます(優先度順): 1. **RFC3339**: `2025-01-15T23:59:00+09:00` 2. **日時形式**: `2025-01-15T23:59` -3. **日付のみ**: `2025-01-15`(時刻は23:59に設定) +3. **日付のみ**: `2025-01-15`(時刻は `23:59` に設定) レスポンスの日付はすべてRFC3339形式で返されます。 @@ -542,83 +736,3 @@ APIは以下の日付形式を受け付けます(優先度順): ``` 設定ファイル (`config.ini`) または環境変数で制限値を変更可能です。 - ---- - -## 繰り返し設定一覧取得 - -``` -GET /api/v1/recurring -``` - -### レスポンス - -**200 OK** - -```json -{ - "recurring_assignments": [ - { - "id": 1, - "user_id": 1, - "title": "週次ミーティング", - "recurrence_type": "weekly", - "interval": 1, - "weekday": 1, - "is_active": true - } - ], - "count": 1 -} -``` - ---- - -## 繰り返し設定詳細取得 - -``` -GET /api/v1/recurring/:id -``` - -### レスポンス - -**200 OK** - ---- - -## 繰り返し設定更新 - -``` -PUT /api/v1/recurring/:id -``` - -### リクエストボディ - -各フィールドはオプション。省略時は更新なし。 - -| フィールド | 型 | 説明 | -|------------|------|------| -| `title` | string | タイトル | -| `is_active` | boolean | `false` で停止、`true` で再開 | -| `recurrence_type` | string | `daily`, `weekly`, `monthly` | -| ... | ... | その他の設定フィールド | - -### リクエスト例(停止) - -```json -{ - "is_active": false -} -``` - ---- - -## 繰り返し設定削除 - -``` -DELETE /api/v1/recurring/:id -``` - -### レスポンス - -**200 OK** diff --git a/docs/SPECIFICATION.md b/docs/SPECIFICATION.md index 5ddc7bd..b975538 100644 --- a/docs/SPECIFICATION.md +++ b/docs/SPECIFICATION.md @@ -8,9 +8,9 @@ Super Homework Managerは、学生の課題管理を支援するWebアプリケ | 項目 | 技術 | |------|------| -| 言語 | Go | +| 言語 | Go 1.24+ | | Webフレームワーク | Gin | -| データベース | SQLite (GORM with Pure Go driver - glebarez/sqlite) | +| データベース | SQLite / MySQL / PostgreSQL (GORM、Pure Go SQLiteドライバー使用) | | セッション管理 | gin-contrib/sessions (Cookie store) | | テンプレートエンジン | Go html/template | | コンテナ | Docker対応 | @@ -27,7 +27,8 @@ homework-manager/ │ ├── middleware/ # ミドルウェア │ ├── models/ # データモデル │ ├── repository/ # データアクセス層 -│ └── service/ # ビジネスロジック +│ ├── service/ # ビジネスロジック +│ └── validation/ # 入力バリデーション ├── web/ │ ├── static/ # 静的ファイル (CSS, JS) │ └── templates/ # HTMLテンプレート @@ -50,6 +51,8 @@ homework-manager/ | PasswordHash | string | パスワードハッシュ | Not Null | | Name | string | 表示名 | Not Null | | Role | string | 権限 (`user` or `admin`) | Default: `user` | +| TOTPSecret | string | TOTP秘密鍵 | - | +| TOTPEnabled | bool | 2FA有効フラグ | Default: false | | CreatedAt | time.Time | 作成日時 | 自動設定 | | UpdatedAt | time.Time | 更新日時 | 自動更新 | | DeletedAt | gorm.DeletedAt | 論理削除日時 | ソフトデリート | @@ -145,6 +148,7 @@ REST API認証用のAPIキーを管理するモデル。 - **パスワード要件**: 8文字以上 - **パスワードハッシュ**: bcryptを使用 - **CSRF対策**: 全フォームでのトークン検証 +- **2段階認証 (TOTP)**: プロフィール画面からGoogle Authenticator等で設定可能。有効化後はログイン時にワンタイムパスワードの入力が必要 ### 3.2 API認証 @@ -158,6 +162,7 @@ REST API認証用のAPIキーを管理するモデル。 |--------|------| | `user` | 自分の課題のCRUD操作、プロフィール管理 | | `admin` | 全ユーザー管理、APIキー管理、ユーザー権限の変更 | + ※ 最初に登録されたユーザーには自動的に `admin` 権限が付与されます。2人目以降は `user` として登録されます。 --- @@ -169,8 +174,9 @@ REST API認証用のAPIキーを管理するモデル。 | 機能 | 説明 | |------|------| | 新規登録 | メールアドレス、パスワード、名前で登録 | -| ログイン | メールアドレスとパスワードでログイン | +| ログイン | メールアドレスとパスワードでログイン。2FA有効時は続けてTOTPコードを入力 | | ログアウト | セッションをクリアしてログアウト | +| CAPTCHA | ログイン・登録フォームへのbot対策(画像認証またはCloudflare Turnstile) | ### 4.2 課題管理機能 @@ -233,7 +239,9 @@ REST API認証用のAPIキーを管理するモデル。 | プロフィール表示 | ユーザー情報を表示 | | プロフィール更新 | 表示名を変更 | | パスワード変更 | 現在のパスワードを確認後、新しいパスワードに変更 | -| 通知設定 | Telegram通知の有効化とトークン設定 | +| 通知設定 | Telegram通知の有効化とChat ID設定 | +| 2FA設定 | TOTPアプリ(Google Authenticator等)でQRコードをスキャンし2FAを有効化 | +| 2FA無効化 | 有効中の2FAを無効化 | ### 4.6 管理者機能 @@ -277,7 +285,14 @@ rate_limit_requests = 100 rate_limit_window = 60 [notification] - telegram_bot_token = your-telegram-bot-token +telegram_bot_token = your-telegram-bot-token + +[captcha] +enabled = false +type = image +# type = turnstile の場合は以下も設定 +# turnstile_site_key = your-site-key +# turnstile_secret_key = your-secret-key ``` ### 5.2 設定項目 @@ -286,16 +301,26 @@ rate_limit_window = 60 |------------|------|------|--------------| | `server` | `port` | サーバーポート | `8080` | | `server` | `debug` | デバッグモード | `true` | -| `database` | `driver` | DBドライバー (sqlite, mysql, postgres) | `sqlite` | +| `database` | `driver` | DBドライバー (`sqlite`, `mysql`, `postgres`) | `sqlite` | | `database` | `path` | SQLiteファイルパス | `homework.db` | -| `session` | `secret` | セッション暗号化キー | (必須) | +| `database` | `host` | DBホスト (MySQL/PostgreSQL) | `localhost` | +| `database` | `port` | DBポート (MySQL/PostgreSQL) | `3306` | +| `database` | `user` | DBユーザー (MySQL/PostgreSQL) | `root` | +| `database` | `password` | DBパスワード (MySQL/PostgreSQL) | - | +| `database` | `name` | DB名 (MySQL/PostgreSQL) | `homework_manager` | +| `session` | `secret` | セッション暗号化キー | **(必須)** | | `auth` | `allow_registration` | 新規登録許可 | `true` | -| `security` | `https` | HTTPS設定(Secure Cookie) | `false` | -| `security` | `csrf_secret` | CSRFトークン秘密鍵 | (必須) | +| `security` | `https` | HTTPS設定 (Secure Cookie) | `false` | +| `security` | `csrf_secret` | CSRFトークン秘密鍵 | **(必須)** | | `security` | `rate_limit_enabled` | レート制限有効化 | `true` | | `security` | `rate_limit_requests` | 期間あたりの最大リクエスト数 | `100` | | `security` | `rate_limit_window` | 期間(秒) | `60` | +| `security` | `trusted_proxies` | 信頼するプロキシ | - | | `notification` | `telegram_bot_token` | Telegram Bot Token | - | +| `captcha` | `enabled` | CAPTCHA有効化 | `false` | +| `captcha` | `type` | CAPTCHAタイプ (`image` or `turnstile`) | `image` | +| `captcha` | `turnstile_site_key` | Cloudflare Turnstile サイトキー | - | +| `captcha` | `turnstile_secret_key` | Cloudflare Turnstile シークレットキー | - | ### 5.3 環境変数 @@ -306,13 +331,22 @@ rate_limit_window = 60 | `PORT` | サーバーポート | | `DATABASE_DRIVER` | データベースドライバー | | `DATABASE_PATH` | SQLiteデータベースファイルパス | +| `DATABASE_HOST` | DBホスト | +| `DATABASE_PORT` | DBポート | +| `DATABASE_USER` | DBユーザー | +| `DATABASE_PASSWORD` | DBパスワード | +| `DATABASE_NAME` | DB名 | | `SESSION_SECRET` | セッション暗号化キー | | `CSRF_SECRET` | CSRFトークン秘密鍵 | -| `GIN_MODE` | `release` でリリースモード(debug=false) | -| `ALLOW_REGISTRATION` | 新規登録許可 (true/false) | -| `HTTPS` | HTTPSモード (true/false) | -| `TRUSTED_PROXIES` | 信頼するプロキシのリスト | +| `GIN_MODE` | `release` でリリースモード | +| `ALLOW_REGISTRATION` | 新規登録許可 (`true`/`false`) | +| `HTTPS` | HTTPSモード (`true`/`false`) | +| `TRUSTED_PROXIES` | 信頼するプロキシ | | `TELEGRAM_BOT_TOKEN` | Telegram Bot Token | +| `CAPTCHA_ENABLED` | CAPTCHA有効化 (`true`/`false`) | +| `CAPTCHA_TYPE` | CAPTCHAタイプ (`image`/`turnstile`) | +| `TURNSTILE_SITE_KEY` | Cloudflare Turnstile サイトキー | +| `TURNSTILE_SECRET_KEY` | Cloudflare Turnstile シークレットキー | ### 5.4 設定の優先順位 @@ -327,13 +361,16 @@ rate_limit_window = 60 ### 6.1 実装済みセキュリティ機能 - **パスワードハッシュ化**: bcryptによるソルト付きハッシュ +- **2段階認証 (TOTP)**: RFC 6238準拠のTOTPによる2FA +- **CAPTCHA**: ログイン・登録時のbot対策(画像認証またはCloudflare Turnstile) - **セッションセキュリティ**: HttpOnly Cookie - **入力バリデーション**: 各ハンドラで基本的な入力検証 -- **CSFR対策**: Double Submit Cookieパターンまたは同期トークンによるCSRF保護 +- **CSRF対策**: Double Submit Cookieパターンによる全フォーム保護 - **レート制限**: IPベースのリクエスト制限によるDoS対策 - **論理削除**: データの完全削除を防ぐソフトデリート - **権限チェック**: ミドルウェアによるロールベースアクセス制御 - **Secure Cookie**: HTTPS設定時のSecure属性付与 +- **セキュリティヘッダー**: X-Content-Type-Options, X-Frame-Options等の設定 ### 6.2 推奨される本番環境設定 @@ -341,6 +378,7 @@ rate_limit_window = 60 - HTTPSを有効化し、`HTTPS=true` を設定 - `GIN_MODE=release` を設定 - 必要に応じて `TRUSTED_PROXIES` を設定 +- `CAPTCHA_ENABLED=true` を設定してbot対策を強化 ---