agr3012/epochzero-learn

GitHub: agr3012/epochzero-learn

一个基于 Next.js 和 Supabase 构建的逆向工程与恶意软件分析在线学习中心,提供文章、视频、在线测试及可验证证书颁发功能。

Stars: 0 | Forks: 0

# REMA Club — 学习门户 一个基于 Next.js 14 + Supabase + Resend 的逆向工程与恶意软件分析学习中心。提供公开文章、视频演示、带有可验证证书的 MCQ 测试,以及电子书和题库下载。 ## 技术栈 - **Next.js 14** (App Router, TypeScript) - **Tailwind CSS** + 自定义主题 - **Supabase** — Postgres, Auth, Storage, RLS - **Resend** — 事务性邮件 - **@react-pdf/renderer** — 证书 PDF - **next-mdx-remote** — 文章渲染 - **Vercel** — 托管 (Hobby 计划) ## 项目结构 ``` rema-club/ ├── app/ # App Router pages │ ├── (api) │ │ ├── auth/register, login/ # account auth — no email-domain restriction │ │ ├── enrollment/redeem/ # POST: redeem a batch enrollment code │ │ ├── admin/batches/ # GET/POST: generate & list enrollment codes │ │ ├── tests/start/ # POST: login-gated, enrollment-checked attempt start │ │ ├── tests/submit/ # POST: score test, trigger cert │ │ └── certificates/generate/# POST: render PDF, upload, email │ ├── articles/[slug]/ # Article reader (MDX) │ ├── videos/[slug]/ # Video + step-by-step sidebar │ ├── tests/[slug]/ # Test detail + engine │ ├── verify/[uid]/ # Public certificate verification │ ├── resources/ # Downloadable PDFs │ ├── podcast/ # Audio episodes │ ├── reels/ # Instagram reel grid │ ├── about/ │ ├── page.tsx # Landing │ └── layout.tsx ├── components/ │ ├── navbar.tsx │ ├── footer.tsx │ ├── test-engine.tsx # Multi-step MCQ engine (client) │ ├── certificate-pdf.tsx # PDF document │ └── video-player.tsx # YouTube embed wrapper ├── lib/ │ ├── supabase/ # client / server / admin clients │ ├── resend.ts │ ├── env.ts # Zod-validated env vars │ └── utils.ts # formatters, slugify ├── supabase/migrations/ │ ├── 001_initial_schema.sql │ └── 002_rls_policies.sql ├── public/ │ └── logo.png # REMA Club shield ├── scripts/ │ └── bootstrap-admin.mjs # promote a user to admin ├── middleware.ts # Supabase session refresh ├── tailwind.config.ts ├── next.config.js └── .env.local.example ``` ## 部署清单 请按以下顺序操作。跳过任何步骤都会导致后续步骤出错。 ### 1. Supabase 项目 1. 在 创建一个新项目。 2. **SQL Editor → New query** → 粘贴 `supabase/migrations/001_initial_schema.sql` → Run。 3. **SQL Editor → New query** → 粘贴 `supabase/migrations/002_rls_policies.sql` → Run。 4. **Project Settings → API** — 复制以下内容: - `Project URL` → `NEXT_PUBLIC_SUPABASE_URL` - `anon public key` → `NEXT_PUBLIC_SUPABASE_ANON_KEY` - `service_role key` → `SUPABASE_SERVICE_ROLE_KEY` (注意保密) ### 2. Resend 账户(电子邮件) 1. 在 注册。 2. **API Keys → Create API Key** → 复制并记为 `RESEND_API_KEY`。 3. **Domains → Add Domain** → 输入你要用于发送邮件的域名(例如 `epochzero.net`)。添加 Resend 提供给你的 DNS 记录 (SPF, DKIM, DMARC)。等待验证完成。 4. 将 `RESEND_FROM_EMAIL` 设置为已验证的发件人 — 例如 `REMA Club `。 - 如果在初始测试时没有已验证的域名,你可以使用 `onboarding@resend.dev`。 ### 3. 本地开发 ``` git clone cd rema-club cp .env.local.example .env.local # 填写 .env.local 中的所有值 npm install npm run dev ``` 访问 。 ### 4. Vercel 部署 1. 将代码仓库推送到 GitHub。 2. 进入 → **Add New → Project** → 导入该仓库。 3. **Environment Variables** → 添加 `.env.local.example` 中的所有变量。将 `NEXT_PUBLIC_SITE_URL` 设置为你的 Vercel URL(例如 `https://rema-club.vercel.app`)。 4. **Deploy。** 5. 部署完成后,如果你的 Resend 域名在首次部署时还未通过验证,请更新 `RESEND_FROM_EMAIL`,然后点击 **Redeploy**。 ### 5. 引导创建管理员用户 管理面板受到 `admin_users` 上的 RLS 保护。要创建第一个管理员: 1. **Supabase Dashboard → Authentication → Add user** → 使用你的邮箱,并勾选启用 *Auto Confirm User*。 2. 运行: node scripts/bootstrap-admin.mjs you@example.com super_admin 3. 现在前往 `/admin/login` 使用该邮箱登录应用(管理后台 UI 将在第 6 阶段构建)。 ### 6. 添加内容 在管理后台 UI 上线之前,请直接通过 Supabase 的 **Table Editor** 或 SQL 插入内容: - `articles` — 设置 `mdx_content`,`is_published = true`,`published_at = now()` - `videos` — 设置 `youtube_id`,`steps` 可选设置为 JSON 数组 - `tests` + `test_questions` — 批量插入问题;确保设置了 `correct_index` - `resources` — 将 PDF 上传到 Supabase Storage 的 `resources` bucket,并将公开的 URL 粘贴到 `file_url` 中 ### 7. 端到端验证测试 → 证书流程 1. 通过 SQL Editor 插入一行测试数据 + 5 个问题。 2. 访问 `/tests/`。 3. 提交你的真实邮箱 → 检查收件箱获取 OTP → 参加测试 → 验证带有 PDF 附件的证书邮件是否成功发送。 4. 访问 `/verify/REMA-2026-XXXXXX` 以确认公开验证功能正常运行。 ## 安全模型 - **正确答案绝不会离开服务器。** 测试引擎仅接收问题文本 + 选项。评分过程在 API 路由中使用 service role key 进行。 - **选项乱序通过完整性校验**:客户端回传 `option_permutation` 数组,服务端在评分前会重新应用该数组。 - **OTP 频率限制:** 每个邮箱每个测试每小时 5 个验证码。静态存储时使用 SHA-256 哈希加密。 - **仅限首次通过颁发证书。** 重复通过不会颁发新证书。 - 每个表都启用了 **RLS**。anon key 无法读取 `test_questions`、`attempts`、`email_otps` 或 `admin_users`。 - **Service role key** 仅在 API 路由和引导脚本中使用。绝不能将其导入到 Client Component 中。 - **可选的 Cloudflare Turnstile**:可通过设置 `TURNSTILE_SECRET_KEY` 和 `NEXT_PUBLIC_TURNSTILE_SITE_KEY` 来启用。 ## 路线图 | 阶段 | 状态 | 描述 | |-------|--------|-------------| | 1. 基础架构 | ✓ 完成 | 脚手架、落地页、布局、Supabase、设计系统 | | 2. 内容阅读 | ✓ 完成 | 文章 (MDX)、资源、播客、短视频 | | 3. 视频学习 | ✓ 完成 | YouTube 网格布局、分步侧边栏 | | 4. 测试引擎 + 证书 | ✓ 完成 | OTP、MCQ 流程、PDF 证书、邮件、公开验证 | | 5. 学生仪表盘 | ◯ 待处理 | 无密码登录、历史尝试记录、可下载证书 | | 6. 管理面板 | ◯ 待处理 | 文章/视频/测试的 CRUD 操作、批量导入 MCQ | ## 许可证 教育项目。内容许可按标记区分各个文章/视频。代码:MIT。
标签:DAST, Supabase, 云资产清单, 在线教育, 恶意软件分析, 测试用例, 自动化攻击, 逆向工程