Conversation
- NFCリーダーのコードを整理し、定数名を大文字に変更 - データベース接続のプール設定を追加し、エラーハンドリングを強化 - ユーザーの入退室ログをトランザクションで管理し、エラーメッセージを詳細化 - APIハンドラーでのリクエストボディの解析を改善し、エラーハンドリングを統一 - cronジョブの設定を更新し、毎日の強制退室と月次ログ送信を追加 - Slack APIとの連携を強化し、エラーメッセージを明確化
- go.mod: golang.org/x/netの依存関係をv0.47.0からv0.48.0に変更 - go.sum: golang.org/x/net v0.48.0のハッシュを追加
- DISPLAY環境変数を設定 - Chromiumブラウザを無対話モード、キオスク、シークレットモードで起動するコマンドを追加
- nfc_reader.pyを新規作成し、学生IDおよび大学カードの読み取り機能を実装 - requirements.txtにnfcpyの依存関係を追加
database.dbを.gitignoreからserver/test/ディレクトリに移動しました。
- elsystemd.service: ユーザーとグループをrootからgeekに変更、PIDFileを削除 - elsystemf.service: ユーザーをpiからgeekに変更
- log.go: "encoding/json" と "io" のインポートを削除 - socket.go: Writeメソッドのエラーハンドリングを修正 - user.go: 不要なインポートを削除
- Goodbyeコンポーネントを追加し、3秒後にトップページに遷移する機能を実装 - Questionコンポーネントを追加し、ユーザーからの入力を受け付ける機能を実装 - Registerコンポーネントを追加し、学生番号の入力を受け付ける機能を実装 - Topコンポーネントを追加し、カードリーダーとのWebSocket接続を管理 - Welcomeコンポーネントを追加し、ユーザーを歓迎するメッセージを表示 - CSSモジュールを使用してスタイルを適用 - VueからReactへの移行に伴い、Vue関連のファイルを削除 - API呼び出しを行うユーティリティ関数を新たに作成 - TypeScriptを導入し、型定義を追加 - Viteを使用してビルド設定を行う - データベース初期化SQLから不要なデータを削除
Forgotコンポーネントの入力フィールドのプレースホルダーを"s12xxxxx"から"s13xxxxx"に変更しました。
Question.module.cssのh2セレクタから重複したfont-weightプロパティを削除しました。
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Top.tsxの「Forgot card?」リンクのクラス名を「forgotLink」から「forgotPos」に変更しました。
h3セレクタから重複していたfont-weightプロパティを削除しました。
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
README.mdから特定の環境向けのビルド手順を削除しました。
Top.tsxの50行目で、カードリーダーが停止した際にconnectCardReader()を呼び出すのではなく、window.location.reload()を実行するように変更しました。
…kDojo/EnterLeaveSystem into refactor-frontend-202512
Top.tsxの「Forgot card?」リンクのクラス名を「forgotPos」から「forgetPos」に変更しました。
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Top.tsxファイルで、react-routerからreact-router-domへのインポートを変更しました。
Top.tsxでconnectCardReader関数をuseCallbackでラップし、再接続時の処理を改善しました。また、WebSocketのoncloseイベントでの再接続処理を修正しました。
eslint.config.jsからdefineConfigのインポートを削除し、エクスポートを簡素化しました。
…kDojo/EnterLeaveSystem into refactor-frontend-202512
- go.modにgithub.com/gorilla/websocket v1.5.3とgithub.com/slack-go/slack v0.17.3を追加しました。 - go.sumに対応するハッシュを追加しました。
- WebHookおよびAttachment構造体を削除し、slack-goライブラリのWebhookMessageを直接使用するように変更 - SlackNotify関数内の変数名を小文字に統一し、可読性を向上 - エラーハンドリングのメッセージを改善
- .gitignoreに.envファイルを追加 - go.modから依存関係を整理し、Slackの依存関係を直接追加 - SlackのSocket Modeクライアントを初期化する機能を追加 - Slackの設定構造体を更新し、必要なトークンを環境変数から取得 - Slack通知機能を改善し、Socket Modeを使用するように変更
Vue2をReactに置き換え
- Forgot.tsx: useLocationを追加し、エラーメッセージを表示する機能を実装 - Top.tsx: カードリーダー通信エラー時のナビゲーション先を'/forgot'に変更
- App.module.cssのフォントファミリーをverdanaから"Noto Sans"に変更しました。 - フォントのインポート文を追加しました。
Welcomeコンポーネントの挨拶文を「Welcome to {room},<br/>{username}!」に変更し、改行を追加しました。
- HTTP POSTリクエストによるファイルアップロードを、SlackクライアントのUploadFileV2メソッドを使用する形式に変更 - 不要なインポート文を削除 - エラーハンドリングを簡素化
Top.tsxにおいて、カードリーダーのエラー処理をcardReaderError関数として抽出し、エラーハンドリングを一元化しました。これにより、コードの可読性と保守性が向上しました。
socket.goファイルのReaderErrorRetryDelayを60秒から5秒に変更しました。これにより、NFCリーダーエラー発生時の再試行が迅速になります。
- Welcome.tsx: ユーザー名がある場合とない場合で表示内容を分岐させるロジックを追加 - api.ts: 不要な204ステータスの処理を削除 - log.go: 不要なエラーハンドリングを削除 - user.go: ユーザー作成ハンドラーを削除し、GETメソッドの処理に統一 - slack.go: 未登録ユーザーの通知メッセージを追加
- update_app.sh: アプリケーションの再ビルドを行うスクリプトを追加 - update_user.sh: ユーザー情報をデータベースにインポートするスクリプトを追加
'scripts/update_app.sh'ファイル内のgit pullコマンドのブランチ名を'main'から'master'に修正しました。
- nfc_reader.pyのファイルモードを100644から100755に変更し、実行可能にしました。
- 新規ファイル: scripts/frontstart.shを追加 - elsystemf.serviceのExecStartを/home/geek/EnterLeaveSystem/scripts/frontstart.shに変更
elsystemf.serviceファイルを削除しました。このファイルはもはや必要なくなったため、コードベースから除去しました。
update_app.shからelsystemf.serviceの停止および開始のコマンドを削除しました。これにより、サービスの管理がelsystemd.serviceのみに統一されました。
log.goファイルのAddLog関数において、ユーザーが未登録の場合にプレースホルダーを作成する処理を追加しました。これにより、ユーザーの入退室ステータスを更新する際のエラーハンドリングが強化されました。
There was a problem hiding this comment.
Pull request overview
This pull request represents a major refactoring of the Enter Leave System, modernizing both the backend and frontend infrastructure. The changes include migrating from Vue.js to React 19 with TypeScript, updating the Slack integration from webhooks to the official slack-go SDK with socket mode support, improving database schema with constraints and indexes, adding graceful shutdown to the server, and updating the NFC reader from Python 2.7 to Python 3.
Changes:
- Backend: Migrated Slack integration to slack-go SDK, added database constraints and transactions, implemented graceful shutdown, updated cron library, and improved error handling
- Frontend: Complete migration from Vue.js 2 to React 19 with TypeScript, replaced Vue Router with React Router v7, modernized build tooling from Vue CLI to Vite
- Infrastructure: Updated NFC reader to Python 3, revised deployment scripts, updated GitHub Actions workflow, and improved systemd service configuration
Reviewed changes
Copilot reviewed 74 out of 86 changed files in this pull request and generated 28 comments.
Show a summary per file
| File | Description |
|---|---|
go.mod |
Updated Go version and dependencies (critical: invalid version specified) |
server/utils/slack.go |
Refactored to use slack-go SDK with socket mode instead of webhooks |
server/utils/csvexport.go |
Updated to use slack-go client for file uploads |
server/utils/cron.go |
Updated cron library to v3 with improved comments |
server/utils/config.go |
Restructured Slack configuration for new SDK |
server/main.go |
Added graceful shutdown, structured logging, and improved initialization |
server/handler/user.go |
Removed POST endpoint, added validation (breaking change) |
server/handler/socket.go |
Added mutex protection, improved error handling, updated NFC reader path |
server/handler/log.go |
Refactored request parsing, removed user existence validation |
server/handler/handler.go |
Added common utility functions for validation and error handling |
server/db/db.go |
Added PRIMARY KEY, FOREIGN KEY constraints, connection pooling, and indexes |
server/db/user.go |
Improved error messages, added transaction support for ForceLeave |
server/db/log.go |
Added transaction support, auto-creates placeholder users |
server/nfc/nfc_reader.py |
Migrated from Python 2.7 to Python 3 with improved code structure |
server/test/init.sql |
Removed test data (schema mismatch with production) |
scripts/*.sh |
Updated deployment and utility scripts |
scripts/elsystemd.service |
Updated systemd service configuration |
front/src/**/*.tsx |
Complete frontend rewrite in React 19 with TypeScript |
front/package.json |
Updated to Vite, React 19, and modern tooling |
.github/workflows/main.yml |
Updated GitHub Actions to use newer action versions |
Comments suppressed due to low confidence (2)
scripts/update_user.sh:10
- The database path is relative ("database.db") in line 10 of scripts/update_user.sh, but the script doesn't ensure it's running from the correct directory. If run from the scripts directory, it will create/modify a database file in the wrong location. Consider using an absolute path or changing directory to the project root first.
server/handler/log.go:76 - The removal of the username check (previously lines 61-65) means that unregistered users can now create logs. This is a significant behavior change. While the AddLog function in db/log.go creates placeholder users (lines 50-54), this bypasses the previous validation that required users to be registered first. This could lead to database pollution with auto-created user entries. Consider whether this is intentional or if the validation should be restored.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
server/db/db.go
Outdated
| }, | ||
| { | ||
| name: "idcard", | ||
| schema: `CREATE TABLE IF NOT EXISTS "idcard" (idm TEXT PRIMARY KEY, sid TEXT NOT NULL, FOREIGN KEY(sid) REFERENCES users(sid))`, |
There was a problem hiding this comment.
The idcard table has a FOREIGN KEY constraint referencing users(sid), but there's no ON DELETE or ON UPDATE clause specified. If a user is deleted, orphaned card records would remain. Consider adding ON DELETE CASCADE or ON DELETE SET NULL depending on the desired behavior.
| except Exception as e: | ||
| # General card - use IDm as identifier | ||
| idm_hex = "".join([f"{s:02x}" for s in tag.idm]) | ||
| print(f"general {idm_hex}") |
There was a problem hiding this comment.
The exception handler on line 30 catches all exceptions but doesn't log or report what the actual error was. This makes debugging difficult when legitimate errors occur (not just general cards). Consider logging the exception details before falling back to using the IDm.
| CREATE TABLE IF NOT EXISTS "users" (sid TEXT,name TEXT,isenter INTEGER); | ||
| INSERT INTO users VALUES('s1240095','Yusuke Namiki',0); | ||
| CREATE TABLE IF NOT EXISTS "idcard" (idm TEXT,sid TEXT); | ||
| CREATE TABLE IF NOT EXISTS "log" (sid TEXT,isenter INTEGER,time INTEGER,ext TEXT); |
There was a problem hiding this comment.
The test database schema (lines 3-5) doesn't match the production schema defined in server/db/db.go (lines 56-67). The production schema has PRIMARY KEY constraints, FOREIGN KEY constraints, DEFAULT values, and an autoincrement ID column in the log table, while the test schema lacks all of these. This mismatch could cause tests to pass while production fails, or vice versa. The schemas should be synchronized.
| def main(): | ||
| """Main function to initialize NFC reader and wait for cards.""" | ||
| clf = nfc.ContactlessFrontend('usb') | ||
| try: | ||
| clf.connect(rdwr={'on-connect': on_connect}) | ||
| finally: | ||
| clf.close() |
There was a problem hiding this comment.
The main function doesn't handle exceptions that might occur during NFC reader initialization or connection (lines 38-42). If the USB device is not found or initialization fails, the script will crash with an unhandled exception. Consider adding try-except error handling with a meaningful error message.
| switch r.Method { | ||
| case "GET": | ||
| getUserHandler(w, r, h.DB) | ||
| case "POST": | ||
| createUserHandler(w, r, h.DB) | ||
| default: | ||
| w.WriteHeader(http.StatusMethodNotAllowed) | ||
| fmt.Fprintf(w, "Unexpected method") |
There was a problem hiding this comment.
In the POST handler for registCardInfo (lines 20-38), the API endpoint still exists in the frontend code (front/src/utils/api.ts), but the corresponding POST handler was removed from server/handler/user.go (previously at lines 52-99). This means card registration will fail with a 405 Method Not Allowed error. Either restore the POST handler or remove the frontend registration functionality.
server/nfc/nfc_reader.py
Outdated
| #!/usr/bin/env python3 | ||
| """NFC card reader for student ID and university cards.""" | ||
|
|
||
| import sys |
There was a problem hiding this comment.
Import of 'sys' is not used.
- `EnvironmentFile`, `WorkingDirectory`, `ExecStart`のパスをユーザーのホームディレクトリから相対パスに変更しました。
- db.go: idcardテーブルの作成を削除 - user.go: GetUIDByCardIDおよびRegisterCard関数を削除 - init.sql: 初期化SQLファイルを削除
This reverts commit a1b7754.
- App.tsx: 時計の更新間隔を500msから1000msに変更 - Forgot.tsx: SIDをAINSIDに変更し、関連する処理を更新 - Question.tsx: SIDをAINSIDに変更し、ログ追加処理を修正 - Register.module.css: クラス名をstudentNUMからainsIDに変更 - Register.tsx: SIDをAINSIDに変更し、関連する処理を更新 - Top.tsx: SIDをAINSIDに変更し、ユーザー情報取得処理を修正 - Welcome.tsx: SIDをAINSIDに変更し、ログ追加処理を修正 - index.ts: UserInfoインターフェースのSIDをAINSIDに変更 - api.ts: getUserInfoとregistCardInfoの引数をSIDからAINSIDに変更 - update_user.sh: ユーザー情報取得スクリプトを修正 - db.go: usersテーブルのSIDをAINSIDに変更 - idcard.go: 新規ファイル作成、AINSIDを使用したカード登録処理を追加 - log.go: ログ処理でのUIDをAINSIDに変更 - user.go: ユーザー情報取得関数をAINSIDに基づくものに変更 - socket.go: IDCardInfo構造体のSIDをAINSIDに変更 - handler.go: SID検証関数をAINSID用に変更 - log.go: ログ処理でのUIDをAINSIDに変更
- ERdiagram.png, api.md, seq.pu, sequence.png, state.png, state.pu, react.svg のファイルを削除しました。
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 78 out of 92 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| usage := extMap["Use"] | ||
| mess := extMap["message"] |
There was a problem hiding this comment.
Removed type assertions without error checking. Lines 94-95 access extMap["Use"] and extMap["message"] without checking if the keys exist or if the values are the expected types. This could cause a panic if the JSON structure is unexpected. The old code had type assertions with explicit error handling.
| resp, err := client.PostForm( | ||
| IncomingURL, | ||
| url.Values{"payload": {string(params)}}, | ||
| log.Println(cfg.ChannelID) |
There was a problem hiding this comment.
Debug log statement that should be removed before production deployment.
| except Exception as e: | ||
| # General card - use IDm as identifier | ||
| idm_hex = "".join([f"{s:02x}" for s in tag.idm]) | ||
| print(f"general {idm_hex}") |
There was a problem hiding this comment.
The except block on line 29 catches all exceptions and treats them as general cards. This means genuine errors (like NFC communication failures, decode errors, or IndexError from accessing data[0:4]) will be silently treated as a general card. Consider logging the exception details or handling specific expected exceptions separately from unexpected errors.
| import type { UserInfo, RegistResponse } from '../types'; | ||
|
|
||
| export const getUserInfo = async (ainsID: string): Promise<UserInfo> => { | ||
| const response = await fetch(`http://localhost:3000/api/user?AINSID=${ainsID}`, { |
There was a problem hiding this comment.
Hardcoded localhost URL. The API URL should be configurable via environment variable to support different deployment environments (development, staging, production). Consider using import.meta.env.VITE_API_URL or a similar approach.
| func ForceLeave(d *sql.DB) error { | ||
| rows, err := d.Query(`SELECT * FROM users where isenter=1`) | ||
| // Select all users who are currently in the room | ||
| rows, err := tx.Query(`SELECT ainsID FROM log WHERE isEnter=1 AND time<?`, yesterdayStartTime) |
There was a problem hiding this comment.
The ForceLeave function has a logic issue. It queries SELECT ainsID FROM log WHERE isEnter=1 AND time<? which will select ALL historical enter logs before yesterday, not just users currently in the room. The function should query for the latest log entry per user and check if that entry is an enter (isEnter=1). The current implementation could create duplicate leave logs for users who aren't actually in the room.
| } | ||
|
|
||
| err = db.RegisterCard(userdat.CardID, userdat.UID, d) | ||
| err := db.RegisterCard(userdat.CardID, userdat.AINSID, d) |
There was a problem hiding this comment.
The CardID from the request is not validated before being passed to db.RegisterCard. The validateCardID function exists in handler.go but is never used. This could allow empty or excessively long CardID values to be stored in the database. Add validation for userdat.CardID before line 119.
- user.go: SQLクエリを修正し、ユーザー名と入室状況を取得するロジックを改善しました。 - nfc_reader.py: 出力される学生IDをs1300071に変更しました。
This pull request migrates the frontend application from Vue.js to React, updates the build and development tooling to use Vite and TypeScript, and modernizes the CI/CD pipeline and configuration files. The changes include a complete rewrite of the frontend codebase, updates to environment variables and dependencies, and improvements to project documentation and workflow automation.
Frontend migration and modernization:
App.vue,.eslintrc.js,babel.config.js,postcss.config.js, etc.) with React equivalents (App.tsx,App.module.css,eslint.config.js, etc.) and updating the project structure and main entry point (index.html,main.tsx). [1] [2] [3] [4] [5] [6] [7]VITE_ROOMNAME,VITE_SHOWQUESTION) and removed legacy Vue environment files. [1] [2] [3]Dependency and configuration updates:
package.json, and updated linting and formatting configurations for the new stack. [1] [2] [3] [4] [5].gitignoreto better support Node.js and Vite projects, including logs and editor configuration files.Documentation improvements:
README.mdto reflect the new React/TypeScript/Vite stack, including development setup, project structure, key components, and API integration details.CI/CD and workflow updates:
.github/workflows/main.ymlto use the latest versions of actions (actions/checkout@v4,actions/cache@v4, etc.), added Node.js 20 setup, and improved caching and artifact handling for the new frontend build process. [1] [2] [3] [4]Cleanup and removal of legacy files: