feat: add Node ACS admin workflows

This commit is contained in:
unknown
2026-07-16 11:00:09 +09:00
parent a25872394a
commit c6f342a861
24 changed files with 3442 additions and 266 deletions

View File

@@ -384,6 +384,159 @@
- `GET /db`는 현재 Windows 로컬에 `DATABASE_URL`이 없어 500과 명확한 오류 메시지를 반환. AI DEV/Coder에서 `.project-env` 로드 후 재검증 필요.
- `docker build -t acs-node-guide-check .`는 Docker daemon 미기동(`dockerDesktopLinuxEngine` pipe 없음)으로 실행 전 실패. Docker Desktop 또는 AI DEV/Coder 배포 환경에서 재검증 필요.
### Coder / Gitea / Coolify 배포 검증
- Coder 접속:
- `https://coder.bokdev.in/workspaces`에서 `ws-aidev-0420301` 워크스페이스 확인.
- 최초 VS Code Web 접속 시 `Agent state is "disconnected"` 404가 발생했으나, 잠시 대기 후 VS Code Web 아이콘이 활성화되어 접속 성공.
- VS Code Web 작업 위치: `/home/coder/projects`.
- Gitea 장애:
- 초기에는 Gitea 루트는 200이었으나 저장소 URL은 500 오류:
- `https://gitea.bokdev.in/playground/MANUAL`
- `https://gitea.bokdev.in/playground/acs`
- `https://gitea.bokdev.in/0420301/acs`
- `git ls-remote https://gitea.bokdev.in/playground/acs.git`
- 인프라 확인 후 Gitea가 정상화되어 clone 가능해짐.
- AI DEV 표준 프로젝트 생성:
- 단순 `git clone https://gitea.bokdev.in/playground/acs.git`만 수행하면 `.project-env`가 생성되지 않아 `DATABASE_URL`이 없음.
- `docs/AIdev.md`의 6번 절차에 따라 아래 순서로 표준 프로젝트 재생성:
- `mv acs acs-from-git`
- `new-project acs`
- `cd ~/projects/acs`
- `.project-env` 생성 확인.
- 이후 원격 소스 반영:
- `git init -b main`
- `git remote add origin https://gitea.bokdev.in/playground/acs.git`
- `git fetch origin`
- `git reset --hard origin/main`
- `.project-env`가 유지되었고 `DATABASE_URL` 환경변수 로드 확인.
- Coder 로컬 검증:
- `npm install` 성공.
- `npm --prefix frontend install` 성공.
- `npm run typecheck` 성공.
- `npm run db:check` 성공:
- `DB OK: Mon Jul 13 2026 10:53:51 GMT+0900 (한국 표준시)`
- `npm run minio:check`는 ACS S3 미사용으로 정상 skip:
- `S3 SKIPPED: ACS does not currently use S3/MinIO storage.`
- `npm run build` 성공.
- `npm run migrate` 성공:
- `Applied migration 001_init.sql`
- `Applied migration 002_audit_log.sql`
- `Applied migration 003_pass_delivery.sql`
- `Applied migration 004_visit_request_contact_fields.sql`
- `npm start` 성공:
- `ACS Node app listening on port 3000`
- Coder 로컬 endpoint 확인:
- `curl 127.0.0.1:3000/healthz` -> `{"ok":true}`
- `curl 127.0.0.1:3000/db` -> `{"ok":true,"now":"..."}`
- `curl 127.0.0.1:3000/s3` -> ACS S3 미사용 skip 응답.
- Coder 내 Docker/Podman build 성공:
- `docker build -t acs-node-local .`
- `Successfully tagged localhost/acs-node-local:latest`
- Coolify 리소스 생성:
- Coolify 팀/프로젝트: `aidev / production`.
- Resource type: `Public Repository`.
- Repository URL: `https://gitea.bokdev.in/playground/acs.git`.
- Branch: `main`.
- Build Pack: `Dockerfile`.
- Base Directory: `/`.
- Port: `3000`.
- Static site: 비활성.
- 최초 자동 생성 resource 이름:
- `obedient-ocelot-w6wzpkzzv8qua4uzejznirp`
- 최초 자동 생성 domain:
- `https://hridawfl9pktjtzq1vj92zbb.apps.bokdev.in`
- Coolify 환경변수 등록:
- `.project-env`에서 제공된 값 중 아래 DB 관련 변수를 등록:
- `DATABASE_URL`
- `PGHOST`
- `PGPORT`
- `PGDATABASE`
- `PGUSER`
- `PGPASSWORD`
- `PGOPTIONS`
- `PORT`
- 추가 ACS 변수:
- `SESSION_SECRET`
- `ACS_PUBLIC_BASE_URL=https://hridawfl9pktjtzq1vj92zbb.apps.bokdev.in`
- `ACS_SMS_PROVIDER=dev`
- S3 관련 변수는 ACS 현재 범위에서는 사용하지 않으므로 필수 등록 대상에서 제외.
- Coolify healthcheck 설정:
- Type: `HTTP`
- Method: `GET`
- Scheme: `http`
- Host: `localhost`
- Port: `3000`
- Path: `/healthz`
- Return Code: `200`
- Healthcheck enabled.
- 1차 Coolify 배포 결과:
- Docker image build와 container start는 성공.
- 컨테이너 로그에 `ACS Node app listening on port 3000` 확인.
- 그러나 Coolify healthcheck 실패:
- `/bin/sh: 1: curl: not found`
- `/bin/sh: 1: wget: not found`
- 원인:
- `node:22-bookworm-slim` runtime image에 Coolify가 healthcheck에 사용하는 `curl`/`wget`이 없음.
- healthcheck 실패 조치:
- `Dockerfile` runtime stage에 `curl``ca-certificates` 설치 추가:
- `apt-get update`
- `apt-get install -y --no-install-recommends curl ca-certificates`
- `rm -rf /var/lib/apt/lists/*`
- Coder에서 커밋:
- `Install curl for Coolify healthcheck`
- Coder에서 최초 `git push`는 upstream 미설정으로 실패.
- `git push --set-upstream origin main`은 인증 실패.
- Gitea `Settings > Applications`에서 repository read/write 권한 토큰 생성 후 토큰 URL 방식으로 push 성공.
- 2차 Coolify 배포 결과:
- commit `44a4bc1086ab9d57dd9815e519c2d2c3c2d0d9c4` 기준 배포.
- Docker image build 성공.
- New container started.
- Healthcheck URL:
- `GET http://localhost:3000/healthz`
- Healthcheck passed:
- `Healthcheck status: "healthy"`
- `Return code: 0`
- Rolling update completed.
- Coolify 상태:
- `Running (healthy)`
- 외부 배포 URL 검증:
- `https://hridawfl9pktjtzq1vj92zbb.apps.bokdev.in/healthz`
- `{"ok":true}`
- `https://hridawfl9pktjtzq1vj92zbb.apps.bokdev.in/db`
- `{"ok":true,"now":"2026-07-13T05:12:54.842Z"}` 등 정상 응답.
- `https://hridawfl9pktjtzq1vj92zbb.apps.bokdev.in/login`
- React 로그인 화면 표시 정상.
- 현재 배포 상태:
- AI DEV 표준 Node.js + Dockerfile + `.project-env`/`DATABASE_URL` 기반 배포 파이프라인 성공.
- 현재 Node 서버는 health/db/static frontend 기반까지만 구현됨.
- 기존 ACS 업무 기능은 아직 Spring Boot 백엔드에서 Node API로 이관 전.
- 로그인 화면은 표시되지만 `/api/auth/login` 등 Node Auth API 구현 전이므로 실제 로그인은 다음 단계에서 구현 필요.
- 도메인 정리 및 고정 도메인 전환:
- 최초 Coolify 자동 생성 임시 도메인:
- `https://hridawfl9pktjtzq1vj92zbb.apps.bokdev.in`
- 인프라팀에 고정 도메인 사용 가능 여부 확인 요청:
- 희망: `https://acs.apps.bokdev.in`
- 또는 AI DEV 표준: `https://acs.playground.bokdev.in`
- 팀장 확인 결과, Coolify에서 사용자가 직접 고정 도메인으로 변경하면 되는 것으로 판단.
- Coolify `Configuration > General`에서 `Domains` 값을 아래로 변경:
- `https://acs.apps.bokdev.in`
- `Set Direction`은 기존 direction 확인/적용용이며, domain 자체 저장은 `General` 제목 옆 `Save` 버튼으로 처리.
- 도메인 저장 직후 `/healthz`에서 일시적으로 `no available server`가 표시되었으나, 재배포/라우팅 반영 후 정상화.
- Coolify `Configuration > Environment Variables`에서 `ACS_PUBLIC_BASE_URL` 값 변경:
- 변경 전: `https://hridawfl9pktjtzq1vj92zbb.apps.bokdev.in`
- 변경 후: `https://acs.apps.bokdev.in`
- 변경 후 재배포 및 최종 확인 완료:
- `https://acs.apps.bokdev.in/healthz` -> `{"ok":true}`
- `https://acs.apps.bokdev.in/db` -> `{"ok":true,"now":"..."}`
- `https://acs.apps.bokdev.in/login` -> React 로그인 화면 표시 정상.
- AI DEV 포털 프로젝트의 배포 URL도 `https://acs.apps.bokdev.in`로 맞추는 방향으로 정리.
- 다음 작업:
- Node Auth/session/role middleware 구현.
- PostgreSQL session store 구성.
- 사용자 seed 또는 기존 사용자 적재 방식 확정.
- `/api/auth/login`, `/api/auth/logout`, `/api/auth/me`, `/api/auth/change-password` 구현.
- 이후 방문신청/승인/출입/리포트 API를 순차 이관.
## 2026-07-14
### ACS 테스트 준비 및 문서 산출물
@@ -492,3 +645,102 @@
- 한 화면 표시 여부.
- 레이블/placeholder/그룹 박스/연락처 자동 포맷 확인.
- 방문 신청 저장 API가 아직 Node로 이관되지 않은 경우, 다음 테스트 단계에서 `/api/visit-requests` 구현 필요.
## 2026-07-16
### 출입신청 날짜 검증 및 QR 유효기간 정책
- 출입신청 화면에서 퇴장일이 출입일 다음날 이후인 경우 2건 분리 신청 안내 후 제출 차단.
- 출입일시가 현재 시스템 일시 이전이어도 입력 가능하도록 과거일자 차단 제거.
- 출입일시가 퇴장일시보다 늦은 경우 안내 메시지 후 제출 차단.
- 백엔드 신청 생성 API에도 동일한 역전/익일 퇴장 검증 추가.
- 방문자 QR은 `visitFrom`의 일자 동안만 유효하도록 입장 판정 기준을 `visitTo`가 아닌 `visitFrom.toLocalDate()`로 변경.
- 지난 출입일 QR을 스캔하면 입장을 차단하고 해당 신청을 `EXPIRED`로 전이하도록 조정.
- 매일 00:10 만료 배치도 `visitFrom` 기준으로 지난 승인 건을 만료 처리하도록 변경.
- 검증:
- `npm.cmd run build` 성공.
- `mvn.cmd test` 성공.
### 개인정보 동의 문구 조정
- `[개인정보 수집·이용 동의 확인]``[방문자에 대한 개인정보 수집·이용 동의 확인]`으로 변경.
- 보유·이용 기간 문구를 `전산실 퇴장 등록시 입력된 방문자 이름, 연락처, 이메일, 차량번호는 바로 삭제`로 변경.
- 해당 보유·이용 기간 한 줄만 red 색상으로 표시.
- 검증:
- `npm.cmd run build` 성공.
### 시스템 관리 및 출입목적 코드화
- 관리자 전용 `시스템관리` 메뉴 추가.
- 관리 탭:
- 현장감시자1 정보 수정.
- 출입목적 코드/표시명/사용 여부/기타 입력 허용 관리.
- 사용자별 ADMIN/SECURITY/HOST 권한 관리.
- 출입신청 화면의 출입목적 목록을 고정 상수에서 서버 코드 목록 기반으로 변경.
- 방문신청 저장 시 `purposeCode`, `purposeDetail`을 함께 저장하도록 확장.
- 기타 목적 입력값이 기존 출입목적 코드/표시명과 일치하면 해당 코드로 자동 정규화.
- Flyway `V5__admin_config.sql` 추가:
- `purpose_codes`
- `system_settings`
- `visit_requests.purpose_code`
- `visit_requests.purpose_detail`
- 검증:
- `mvn.cmd test` 성공.
- `npm.cmd run build` 성공.
- 로컬 새 API 확인: `/api/purpose-codes`, `/api/admin/purpose-codes`, `/api/settings/watcher1`, `/api/admin/users` 모두 200.
### 팀 기반 권한관리 개선
- 개발1팀 등 조직 변경이 잦은 운영을 고려해 사용자별 권한 직접 수정만 두지 않고, 팀 기준 권한 템플릿을 추가.
- `시스템관리 > 팀 관리` 탭 추가:
- 팀 코드, 팀명, 사용 여부, 기본권한 관리.
- 기본권한은 ADMIN/SECURITY/HOST 다중 선택 가능.
- 팀별 기본권한을 해당 팀 소속 전체 사용자에게 일괄 적용 가능.
- `시스템관리 > 권한관리` 탭 개선:
- 사용자 검색, 팀 필터 추가.
- 사용자별 소속 팀 변경 가능.
- 팀 변경 시 팀 기본권한을 즉시 적용할지 선택 가능.
- 특정 사용자에게 팀 기본권한만 별도 재적용 가능.
- 기존 `users.department`는 호환성을 위해 유지하되, 신규 `teams` 마스터와 `users.team_id`를 기준으로 운영하도록 확장.
- Flyway `V6__teams.sql` 추가:
- `teams`
- `team_default_roles`
- `users.team_id`
- 기존 IT운영팀/개발1팀/보안팀 및 기본권한 seed.
- 검증:
- `mvn.cmd test` 성공.
- `npm.cmd run build` 성공.
- 로컬 서버 재기동 후 `/api/admin/teams`, `/api/admin/users` 모두 200.
### 팀/권한 엑셀 업로드
- `시스템관리 > 팀 관리`에 엑셀 업로드 기능 추가.
- 컬럼: `팀 코드`, `팀명`, `기본권한`.
- 팀 코드를 기준으로 신규/수정 구분.
- 기본권한은 업로드 값으로 교체.
- 양식 다운로드 제공.
- `시스템관리 > 권한관리`에 엑셀 업로드 기능 추가.
- 컬럼: `아이디`, `이름`, `팀명`, `권한`.
- 기존 사용자만 수정하며 신규 사용자 생성은 제외.
- 아이디 기준으로 사용자 확인, 이름 불일치/없는 팀/잘못된 권한/중복 행은 오류 처리.
- 양식 다운로드 제공.
- 업로드는 즉시 반영하지 않고 `검증`으로 미리보기 결과를 확인한 뒤, 오류가 0건일 때만 `적용` 가능하도록 구성.
- 백엔드에서 Apache POI로 `.xlsx`를 파싱하고 적용 시 `ADMIN_CONFIG_UPDATE` 감사로그 기록.
- 검증:
- `mvn.cmd test` 성공.
- `npm.cmd run build` 성공.
- 로컬 서버 재기동 후 팀 양식 다운로드 및 `/api/admin/teams/upload?dryRun=true` 200 확인.
- 권한 양식 다운로드 및 `/api/admin/users/roles/upload?dryRun=true` 200 확인.
### 권한관리 운영 방식 일원화
- `시스템관리 > 권한관리` 하단 목록의 사용자별 `기본권한 적용` 버튼 제거.
- 사용자별 권한 변경은 팀 선택/권한 체크박스 수정 후 `저장` 버튼으로 반영하도록 변경.
- 팀 변경 시에도 팀 기본권한을 자동 적용하지 않고, 관리자가 화면에서 확인한 권한 체크 상태 그대로 저장.
- 팀 기본권한 적용 기능은 `팀 관리`의 팀원 일괄 적용 또는 권한 엑셀 업로드 방식으로만 유지.
- `/api/admin/**`는 기존 보안 설정상 ADMIN 권한자만 접근 가능함을 확인.
- 검증:
- `npm.cmd run build` 성공.
- `mvn.cmd test` 성공.
- 2026-07-16 배포 준비:
- 서버 배포 구조가 루트 Node Dockerfile 기준임을 확인하고, Spring Boot 변경사항 중 서버에서 필요한 기능을 Node API로 이관.
- 원격 최신 `playground/acs` 기준의 클린 클론(`acs-deploy`)에 Node/프론트/마이그레이션 변경만 적용.
- 클린 클론 검증:
- `npm.cmd run typecheck` 성공.
- `npm.cmd run build` 성공.
- `npm.cmd test` 성공.
- 로컬 DB 접속 정보(`DATABASE_URL`)가 없어 신규 마이그레이션은 서버 기동 시 적용되는 방식으로 확인 예정.