使用 Google 帳號登入的線上投票系統。資料儲存於 PostgreSQL + Prisma。
若已安裝 Docker,在專案根目錄執行:
docker compose up -d這會啟動本機 Postgres(帳密 postgres / postgres,資料庫 evote,埠 5432)。
若你使用自己的 PostgreSQL,請自行建立資料庫 evote。
複製範例並填入:
cp .env.example .env
cp .env.example .env.local至少確認這兩個檔都有:
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/evote?schema=public"
AUTH_SECRET=...
AUTH_GOOGLE_ID=...
AUTH_GOOGLE_SECRET=...
AUTH_URL=http://localhost:3000
ADMIN_EMAILS=你的管理員@gmail.comPrisma CLI 讀
.env;Next.js 讀.env.local。兩邊的DATABASE_URL請保持一致。
npm install
npx prisma generate
npx prisma migrate dev --name init_evotenpm run dev| 指令 | 說明 |
|---|---|
npm run db:up |
啟動 Docker PostgreSQL |
npm run db:generate |
產生 Prisma Client |
npm run db:migrate |
建立/套用 migration |
npm run db:studio |
開啟 Prisma Studio 看資料 |
npm run smoke |
端到端煙霧測試(需 DB) |
- Google Cloud Console 建立 OAuth 用戶端
- 重新導向 URI:
http://localhost:3000/api/auth/callback/google - 填入
AUTH_GOOGLE_ID/AUTH_GOOGLE_SECRET
投票權人:登入 → /vote 選擇投票 → 送出 → /confirm 確認 → /results 看結果
投票管理(任何登入使用者):/admin
- 建立新投票(建立者即為該場投票管理者)
- 可新增共同管理者
- 查看並管理自己建立/被授權的投票
系統管理者(ADMIN_EMAILS):可在 /admin 查看並管理全部投票
- 背景仍使用盲簽、ElGamal、ZKP、Mix-Net
- 私鑰目前存於資料庫 JSON(示範用);正式環境建議改放 KMS/HSM
- 選項圖片存在
public/uploads(Vercel 等無狀態主機上無法持久保存;正式環境建議改接物件儲存)
- 到 Neon Console 建立專案
- 複製連線字串為
DATABASE_URL
本機可先驗證遷移:
# 暫時把 DATABASE_URL 設成 Neon 連線字串後執行
npx prisma migrate deploy- 把專案推上 GitHub
- 到 Vercel Import 該儲存庫
- 設定環境變數(Production):
DATABASE_URL=(Neon 連線字串;應用程式可用 pooled)
DIRECT_URL=(選填,Neon 非 pooler 直連;遷移建議使用,未設時會自動去掉 -pooler)
AUTH_SECRET=(隨機字串,可用 openssl rand -base64 32)
AUTH_GOOGLE_ID=...
AUTH_GOOGLE_SECRET=...
AUTH_URL=https://你的專案.vercel.app
AUTH_TRUST_HOST=true
ADMIN_EMAILS=你的管理員@gmail.com
prisma migrate deploy需要能取得 Postgres advisory lock。若DATABASE_URL是 Neon-pooler位址,建置可能出現P1002逾時;請改設DIRECT_URL為不含-pooler的直連,或沿用本專案自動轉換。
- Build Command 使用專案預設:
prisma generate && node scripts/migrate-deploy.mjs && next build(遷移失敗會自動重試,以應付 Neon 冷啟動/lock) - Deploy 完成後取得公開網址
在 Google Cloud Console 的 OAuth 用戶端新增:
- 授權的 JavaScript 來源:
https://你的專案.vercel.app - 授權重新導向 URI:
https://你的專案.vercel.app/api/auth/callback/google
並確認 Vercel 的 AUTH_URL 與此網域一致。