Skip to content
AS-ITSPublic

About

MIT 授權的 Yii2 電子投票平台,支援表決投票與匿名投票。

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

27 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

電子投票系統 (voting)

通用電子投票平台(原院士選舉參考實作)。

English · 繁體中文

English

Electronic voting platform (general-purpose; originally a reference implementation for academician elections).

Requirements: PHP 8.2+, MariaDB 10.6+, Composer, Apache/Nginx. See SETUP.md for required PHP extensions.

Quick start:

  1. Clone main (has install.sh): git clone --branch main --depth 1 https://github.com/AS-ITS/evoting.git
    After a release that includes the installer (e.g. v1.0.1+), you may use that tag. Do not use v1.0.0 for fresh install (no install script). Do not use composer create-project.
  2. Recommended (fresh install): one-liner in SETUP.md (git clone … && cd … && sudo bash scripts/install.sh). For upgrades — do not re-run init_db.sql.
  3. Or manually: composer install --prefer-dist, then bash scripts/ensure-writable-dirs.sh, copy .env.example → .env, import docs/init_db.sql, php yii admin/create, point Document Root to web/

Full install, Web Server samples, and production checklist: SETUP.md (Traditional Chinese).
Architecture notes: docs/ARCHITECTURE.md. Security reporting: SECURITY.md.

Vote types: open ballot (no auth) and anonymous (one-time passwords). Maintenance status: see GOVERNANCE.md. Licensed under MIT (LICENSE). Report vulnerabilities via SECURITY.md.


繁體中文

維護狀態

專案目前由中央研究院資訊服務處人員維護,不構成服務等級或永久維護承諾。詳見 GOVERNANCE.md。

快速開始

  1. 請 clone main(含 install.sh):git clone --branch main --depth 1 https://github.com/AS-ITS/evoting.git
    待有含安裝精靈的 release(如 v1.0.1+)再改用該 tag。勿用 v1.0.0 新裝。不要使用 composer create-project
  2. 建議新裝:見 SETUP.md 一行指令(git clone … && cd … && sudo bash scripts/install.sh)。升級勿再跑 init_db
  3. 或手動:composer install --prefer-dist → bash scripts/ensure-writable-dirs.sh → 設定 .env → 匯入 docs/init_db.sql → php yii admin/create → Document Root 指向 web/

完整安裝、Web Server 設定與正式環境檢查表見 SETUP.md。
系統架構與開發指引見 docs/ARCHITECTURE.md。

系統功能

管理員認證

  • 登入: /auth/login 或 /admin
  • 登出: /auth/logout
  • 修改密碼: /auth/change-password
  • 忘記密碼: /auth/forgot-password(帳號須先設定信箱;非正式環境信件寫入 runtime/mail)

密碼修改功能

管理員可透過「修改密碼」功能更新自己的登入密碼。

密碼要求:

  • 長度至少 8 個字元
  • 必須包含至少一個字母和一個數字
  • 不可與帳號相同
  • 不可與目前密碼相同

安全特性:

  • 驗證舊密碼正確性
  • 密碼強度檢查
  • 防止密碼重用
  • 操作日誌記錄(LOG 418)
  • 修改成功後自動登出,要求重新登入

忘記密碼(/auth/forgot-password):帳號須先設定信箱。連結 30 分鐘、單次;不關閉 TOTP。正式環境經 SMTP 寄出(LOG 425/426);其他環境寫入 runtime/mail/。升級既有資料庫須執行 docs/migrations/20261021_password_reset.sql。詳見 SETUP.md。

二次驗證(TOTP)與敏感操作

  • TOTP 綁定:登入後台 → 使用者管理 → 雙因素驗證(/users/totp)
  • 敏感操作(密碼 CSV 匯出、RBAC 同步):需輸入管理員密碼;已啟用 TOTP 者另需 6 碼
  • 詳見 SECURITY.md、SETUP.md §二次驗證與 TOTP

開源釋出前

bash scripts/open-source-prep.sh

測試

單元測試(Unit Tests)

單元測試直接呼叫 Model 方法,不需要測試伺服器。Fixture 由各測試自動管理。

# 步驟 1:清除舊測試資料(確保乾淨起始狀態)
echo "yes" | php yii fixture/unload "*" --appconfig=config/console-test.php

# 步驟 2:執行所有單元測試
php vendor/bin/codecept run unit

# 執行特定測試檔案
php vendor/bin/codecept run unit models/FormPartiesTest

# 顯示詳細輸出
php vendor/bin/codecept run unit --debug

注意:單元測試執行後會清除 Config、Users、Rbac 等資料表,若需接著執行驗收或功能測試,需重新載入所有 Fixture。


功能測試(Functional Tests)

功能測試透過 Codeception Yii2 模組模擬 HTTP 請求,直接測試 Controller 行為,不需要啟動測試伺服器。Fixture 由各 Cest 類別的 _fixtures() 方法自動管理,每個測試方法執行前會自動載入。

共 190 個測試,涵蓋 19 個 Controller/場景(詳見 tests/TEST_STATUS.md):

Cest 檔案 測試範圍
AuthControllerCest 登入、登出、修改密碼
BallotControllerCest 選票管理
BallotWorkControllerCest 投票工作管理
CandiControllerCest 候選人設定
CountControllerCest 開票作業
ElectControllerCest 投票場次管理
GroupControllerCest 群組管理
GroupMemberControllerCest 群組成員管理
ManageControllerCest 系統管理
PasswdControllerCest 匿名投票密碼管理
PermissionDenialCest 權限控制驗證(各角色存取)
QuestionControllerCest 投票問題管理
ResultControllerCest 開票結果
RoundControllerCest 輪次管理
SiteControllerCest 網站首頁
UsersControllerCest 使用者管理
VoteControllerCest 投票操作
VoteListCest 投票列表
VoteResultCest 投票結果頁

執行方式:

# 執行所有功能測試
php vendor/bin/codecept run functional

# 執行特定 Cest 檔案
php vendor/bin/codecept run functional ElectControllerCest

# 執行特定測試方法
php vendor/bin/codecept run functional ElectControllerCest:testCreateVotePageDisplay

# 顯示詳細輸出
php vendor/bin/codecept run functional --debug

首次執行前:先以測試設定載入必要 fixture;測試失敗不應以重跑掩蓋,請保留輸出並排查根因。

echo "yes" | php yii fixture/load "Votes,Parties,Round,Questions,CandiData,Passwords,CandiConfig,Config,Users,Rbac,Group,GroupMember,Ballots,BallotsSelected,ResultsConfig" --appconfig=config/console-test.php
php vendor/bin/codecept run functional

驗收測試(Acceptance Tests)

驗收測試透過瀏覽器模擬完整操作流程,需先啟動測試伺服器並載入所有 Fixture。

# 步驟 1:啟動測試伺服器(在獨立終端機中執行,保持執行)
# 測試入口僅在 APP_ENV=testing 時啟用;.env 為 development/production 時須如下指定,否則一律回 404
APP_ENV=testing php -S localhost:8080 -t web web/router-test.php

# 步驟 2:載入所有 Fixture(必須包含 Config、Users、Rbac)
echo "yes" | php yii fixture/load "Votes,Parties,Round,Questions,CandiData,Passwords,CandiConfig,Config,Users,Rbac,Group,GroupMember,Ballots,BallotsSelected,ResultsConfig" --appconfig=config/console-test.php

# 步驟 3:執行所有驗收測試
php vendor/bin/codecept run acceptance

# 執行特定測試
php vendor/bin/codecept run acceptance AnonVoteCest

# 步驟 4:重複測試前,重新執行步驟 2 即可將測試資料還原為初始狀態

注意:fixture/unload 會連同相依的 Fixture 一起清除。例如 fixture/unload "Ballots,BallotsSelected" 也會清空 CandiData、Questions、Votes(BallotsSelected 相依 CandiData/Questions,CandiData 相依 Votes),之後的測試會因缺少投票資料而失敗。重設資料請用 fixture/load。

⚠️ 重要: 務必使用 --appconfig=config/console-test.php 參數,確保操作測試資料庫而非正式資料庫。

瀏覽器 E2E 測試

以 Headless Chrome 實際操作畫面(全畫面巡檢、對話框、附件與照片、投票流程),不需安裝 Node.js。測試伺服器須以 APP_ENV=testing 啟動並已載入 fixture:

APP_ENV=testing php -S localhost:8080 -t web web/router-test.php
php tests/e2e/run.php

詳見 tests/e2e/README.md。

產生測試數據

# 產生預期的測試資料: 從 /tests/fixtures/data 修改
php yii fixture/load "*" --appconfig=config/console-test.php

# 透過 template 產生測試資料
php yii fixture/generate <fixtures> --count=<number> --appconfig=config/console-test.php

清除測試資料

# 清除所有測試資料
php yii fixture/unload "*" --appconfig=config/console-test.php

# 清除特定測試資料(會連同相依的 Fixture 一起清除,見上方注意事項)
php yii fixture/unload "Ballots,BallotsSelected" --appconfig=config/console-test.php

簡易壓力測試

php ./vendor/bin/codecept run acceptance AnonVoteCest.php

只執行tryAnonVoteCandidates,其他@skip;然後開n個cmd,更改anonProvider()中的密碼清單(limit、offset),同時執行php ./vendor/bin/codecept run acceptance AnonVoteCest.php,觀察結果。

ex:

cmd1: offset(0),執行php ./vendor/bin/codecept run acceptance AnonVoteCest.php

cmd2: offset(100),執行php ./vendor/bin/codecept run acceptance AnonVoteCest.php

以此類推....


S-BOM (Software Bill of Materials)

本專案提供符合 CycloneDX 1.5 標準的 S-BOM 資料,用於軟體供應鏈安全與依賴管理。

S-BOM 檔案

產生與更新 S-BOM

專案內含一個獨立的 PHP 腳本,無需安裝任何額外套件即可讀取專案狀態並產生最新的 S-BOM。

執行方式:

# 產生所有 S-BOM (後端與前端)
php docs/generate_sbom.php all

# 僅產生後端 S-BOM
php docs/generate_sbom.php vendor

# 僅產生前端 S-BOM
php docs/generate_sbom.php frontend

開發文檔

系統架構

配置文檔

測試文檔

測試檔案位置

tests/
├── unit/
│   └── controllers/
│       └── AuthControllerTest.php        # 管理員認證單元測試(含密碼修改)
└── acceptance/
    └── ChangePasswordCest.php            # 密碼修改功能測試(9 個場景)

重要提醒

Fixture 載入注意事項

  • 正式環境:php yii fixture/load → 使用 config/console.php → 操作正式資料庫 voting
  • 測試環境:php yii fixture/load --appconfig=config/console-test.php → 使用 config/console-test.php → 操作測試資料庫 voting_test

務必使用測試配置避免影響正式資料!

密碼修改實作重點

Users 模型使用雙欄位設計:

  • password - 資料庫欄位(以 password_hash() 單向雜湊儲存,不可還原)
  • password_plain - 虛擬屬性(表單輸入/驗證用)

正確的密碼更新方式:

// ✅ 正確
$user->password_plain = '新密碼';
$user->save();  // beforeSave() 自動雜湊

// ❌ 錯誤
$user->password = $user->hashPassword('新密碼');
$user->save(false);  // beforeSave() 可能用舊 password_plain 覆蓋

漸進式遷移:validatePassword() 會先以 password_verify() 驗證; 若資料庫仍是舊制 AES 可逆密文,驗證成功後會自動轉為雜湊寫回,無須一次性重設全部帳號。

詳見 models/Users.php 的 beforeSave() 方法。

部署安全注意事項

  1. 執行環境:web/index.php 由環境變數 YII_DEBUG / YII_ENV 控制,未設定時預設為正式環境(prod、除錯關閉)。開發環境請在 .env 設定 YII_DEBUG=true、YII_ENV=dev。
  2. 測試入口:web/index-test.php、web/router-test.php 僅在明確的 APP_ENV=testing/test 下啟用。正式部署仍建議由 Web Server 拒絕這兩個路徑,或在部署包排除。
  3. 初始管理員:匯入 docs/init_db.sql 後執行 php yii admin/create 建立 admin(sa)帳號;密碼由安裝時互動設定,不寫入文件。
  4. 上傳目錄:檔案上傳目錄(APP_PATH_UPLOADS,預設 /var/www/filepool)必須位於網站根目錄之外;若因故置於網站根目錄下,請停用該目錄的 PHP 執行:
# Apache(上傳目錄的 .htaccess)
<FilesMatch "\.ph(p[3457]?|t|tml)$">
    Require all denied
</FilesMatch>
# nginx
location ~* ^/uploads/.*\.php$ {
    deny all;
}

文件與支援

文件 用途
CHANGELOG.md 版本變更紀錄(Keep a Changelog)
SETUP.md 安裝、部署、測試環境、部署最佳實踐
SECURITY.md 資安政策、TOTP、開源釋出前檢查
CONTRIBUTING.md Issue/PR 與測試流程
CODE_OF_CONDUCT.md 行為準則
GOVERNANCE.md 維護狀態與決策
docs/ARCHITECTURE.md 系統架構與開發指引
docs/RELEASING.md 公開版本發布指南
docs/threat-model/README.md 威脅建模(STRIDE/匿名性)
docs/CONFIGURATION.md 環境變數與配置詳解
LICENSE / NOTICE MIT 授權與第三方聲明
docs/授權合規評估檢核表.md 授權合規檢核表
OPENSOURCE_MIGRATION.md 通用化遷移摘要

回報問題:一般問題開 GitHub Issue(見模板);提交前請先查 SETUP.md 常見問題與 runtime/logs/,並附上 PHP、MariaDB、APP_ENV。安全漏洞請勿在公開 Issue 揭露,見 SECURITY.md。

程式碼貢獻:見 CONTRIBUTING.md。

授權

本專案原始碼以 MIT License 釋出。第三方套件見 NOTICE 與 docs/授權合規評估檢核表.md。

About

MIT 授權的 Yii2 電子投票平台,支援表決投票與匿名投票。

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages