341 lines
9.1 KiB
Markdown
341 lines
9.1 KiB
Markdown
# 회원 관리 및 인증 시스템 구축 완료 ✅
|
|
|
|
## 📝 작업 요약
|
|
|
|
부산교통공사 1호선 고장코드 시스템에 회원 관리 및 인증 기능을 성공적으로 추가했습니다.
|
|
|
|
---
|
|
|
|
## 🎯 구현된 기능
|
|
|
|
### 1. **이메일 인증 시스템**
|
|
- ✅ Supabase Auth를 활용한 이메일 기반 회원가입 및 로그인
|
|
- ✅ **humetro.busan.kr** 도메인만 허용하는 이메일 검증
|
|
- ✅ 비밀번호 암호화 및 안전한 인증 처리
|
|
|
|
### 2. **회원가입 기능**
|
|
- ✅ 사번, 이름, 소속부서, 이메일 정보 수집
|
|
- ✅ 부서 선택은 미리 정의된 부서 목록에서만 가능
|
|
- ✅ 이메일 도메인 자동 검증
|
|
- ✅ 비밀번호 확인 및 유효성 검사
|
|
|
|
### 3. **부서별 권한 관리 기반 구축**
|
|
- ✅ 부서 테이블 및 권한 테이블 설계
|
|
- ✅ 향후 부서별 조회/수정/삭제 권한 제어 가능
|
|
- ✅ RLS(Row Level Security) 정책 설정
|
|
|
|
---
|
|
|
|
## 📂 생성된 파일
|
|
|
|
### 1. **auth.py** - 인증 모듈
|
|
회원 관리 및 인증 로직을 담당하는 별도 모듈
|
|
|
|
**주요 클래스: AuthManager**
|
|
- `validate_email()`: 이메일 도메인 검증 (humetro.busan.kr)
|
|
- `get_departments()`: 가입 가능한 부서 목록 조회
|
|
- `signup_user()`: 회원가입 처리 (Supabase Auth + users 테이블)
|
|
- `login_user()`: 로그인 처리 및 세션 데이터 생성
|
|
- `logout_user()`: 로그아웃 처리
|
|
- `check_email_exists()`: 이메일 중복 체크
|
|
- `check_employee_id_exists()`: 사번 중복 체크
|
|
|
|
### 2. **database_schema.sql** - 데이터베이스 DDL
|
|
Supabase에서 실행할 데이터베이스 스키마 정의
|
|
|
|
**생성되는 테이블:**
|
|
|
|
#### 📋 departments (부서)
|
|
```sql
|
|
- id (SERIAL PRIMARY KEY)
|
|
- code (VARCHAR, UNIQUE) - 부서 코드
|
|
- name (VARCHAR) - 부서명
|
|
- description (TEXT) - 부서 설명
|
|
- is_active (BOOLEAN) - 활성화 여부
|
|
- created_at, updated_at (TIMESTAMPTZ)
|
|
```
|
|
|
|
**초기 부서 데이터:**
|
|
- SPC: 신평차량
|
|
- NPC: 노포차량
|
|
- VHD: 차량처
|
|
|
|
> **참고**: 부서 목록은 Supabase의 `public.departments` 테이블에서 동적으로 관리됩니다.
|
|
|
|
#### 👤 users (사용자)
|
|
```sql
|
|
- id (SERIAL PRIMARY KEY)
|
|
- auth_id (UUID, UNIQUE) - Supabase Auth ID
|
|
- email (VARCHAR, UNIQUE) - 이메일
|
|
- employee_id (VARCHAR, UNIQUE) - 사번
|
|
- name (VARCHAR) - 이름
|
|
- department_id (INTEGER, FK) - 부서 ID
|
|
- is_active (BOOLEAN) - 계정 활성화 여부
|
|
- last_login_at (TIMESTAMPTZ) - 마지막 로그인
|
|
- created_at, updated_at (TIMESTAMPTZ)
|
|
```
|
|
|
|
#### 🔐 department_permissions (부서별 권한)
|
|
```sql
|
|
- id (SERIAL PRIMARY KEY)
|
|
- department_id (INTEGER, FK)
|
|
- resource_type (VARCHAR) - 'fault_code', 'signal', 'mmi_code'
|
|
- can_read (BOOLEAN) - 조회 권한
|
|
- can_write (BOOLEAN) - 수정 권한
|
|
- can_delete (BOOLEAN) - 삭제 권한
|
|
- created_at, updated_at (TIMESTAMPTZ)
|
|
```
|
|
|
|
#### 📊 audit_logs (감사 로그)
|
|
```sql
|
|
- id (SERIAL PRIMARY KEY)
|
|
- user_id (INTEGER, FK)
|
|
- action (VARCHAR) - 'login', 'logout', 'create', 'update', 'delete'
|
|
- resource_type (VARCHAR)
|
|
- resource_id (VARCHAR)
|
|
- details (JSONB)
|
|
- ip_address (VARCHAR)
|
|
- created_at (TIMESTAMPTZ)
|
|
```
|
|
|
|
**추가 기능:**
|
|
- ✅ RLS(Row Level Security) 정책 적용
|
|
- ✅ 트리거를 통한 updated_at 자동 업데이트
|
|
- ✅ 인덱스 최적화
|
|
- ✅ 뷰(users_with_department) 생성
|
|
|
|
### 3. **templates/login.html** - 로그인 페이지
|
|
- 이메일/비밀번호 입력 폼
|
|
- 회원가입 페이지 링크
|
|
- 에러/성공 메시지 표시
|
|
- 반응형 디자인 (Pico CSS)
|
|
|
|
### 4. **templates/signup.html** - 회원가입 페이지
|
|
- 사번, 이름, 부서, 이메일, 비밀번호 입력 폼
|
|
- 부서 선택 드롭다운 (Supabase에서 동적으로 로드)
|
|
- 이메일 도메인 검증 (humetro.busan.kr)
|
|
- 비밀번호 확인 검증
|
|
- 에러 메시지 표시
|
|
|
|
### 5. **app.py** - 수정된 메인 애플리케이션
|
|
**추가된 기능:**
|
|
- Flask 세션 설정 (SECRET_KEY, 쿠키 보안)
|
|
- 인증 라우트 추가:
|
|
- `/auth/login` (GET, POST): 로그인
|
|
- `/auth/signup` (GET, POST): 회원가입
|
|
- `/auth/logout`: 로그아웃
|
|
- `@login_required` 데코레이터: 로그인 필요 페이지 보호
|
|
- `get_current_user()` 함수: 현재 로그인 사용자 정보 조회
|
|
|
|
### 6. **templates/index.html** - 수정된 메인 페이지
|
|
- 헤더에 사용자 정보 표시 (이름, 사번)
|
|
- 로그아웃 버튼 추가
|
|
- 로그인된 사용자만 접근 가능
|
|
|
|
### 7. **AUTH_SETUP.md** - 설정 가이드
|
|
상세한 설정 및 사용 방법 문서
|
|
|
|
---
|
|
|
|
## 🚀 설정 방법 (빠른 시작)
|
|
|
|
### 1단계: 데이터베이스 스키마 적용
|
|
|
|
Supabase SQL 에디터에서 실행:
|
|
```bash
|
|
# database_schema.sql 파일 내용 복사 후 실행
|
|
```
|
|
|
|
### 2단계: 환경 변수 설정
|
|
|
|
`.env` 파일에 추가:
|
|
```bash
|
|
# Supabase 설정
|
|
SUPABASE_URL=http://localhost:8000
|
|
SUPABASE_ANON_KEY=your-anon-key-here
|
|
|
|
# Flask 세션 보안 키 (반드시 변경!)
|
|
SECRET_KEY=your-secret-key-here
|
|
```
|
|
|
|
### 3단계: 서버 실행
|
|
|
|
```bash
|
|
python app.py
|
|
```
|
|
|
|
### 4단계: 회원가입 및 로그인
|
|
|
|
1. 브라우저에서 `http://localhost:5000` 접속
|
|
2. 자동으로 로그인 페이지로 리다이렉트
|
|
3. "회원가입" 클릭하여 계정 생성
|
|
4. humetro.busan.kr 도메인 이메일로 가입
|
|
|
|
---
|
|
|
|
## 🔑 주요 보안 기능
|
|
|
|
### 1. 이메일 도메인 제한 (애플리케이션 레벨)
|
|
|
|
> ⚠️ **Docker 기반 Supabase 환경**: 대시보드 Authentication 설정이 제한적이므로, **애플리케이션 레벨에서만** 도메인 검증을 수행합니다.
|
|
|
|
- **검증 위치**: `auth.py`의 `validate_email()` 함수
|
|
- **검증 패턴**: `@humetro.busan.kr`로 끝나는 이메일만 허용
|
|
|
|
```python
|
|
def validate_email(self, email: str) -> tuple[bool, str]:
|
|
domain = email.split('@')[1]
|
|
if domain != self.ALLOWED_EMAIL_DOMAIN:
|
|
return False, f"{self.ALLOWED_EMAIL_DOMAIN} 도메인의 이메일만 사용 가능합니다."
|
|
return True, "OK"
|
|
```
|
|
|
|
### 2. 중복 검사
|
|
- 이메일 중복 체크
|
|
- 사번 중복 체크
|
|
|
|
### 3. 세션 보안
|
|
- HTTPOnly 쿠키
|
|
- SameSite 설정
|
|
- SECRET_KEY 암호화
|
|
|
|
### 4. Row Level Security (RLS)
|
|
- 사용자는 본인 정보만 조회/수정 가능
|
|
- 부서 정보는 모든 인증된 사용자가 조회 가능
|
|
|
|
---
|
|
|
|
## 📊 데이터베이스 관계도
|
|
|
|
```
|
|
departments (부서)
|
|
↓ (1:N)
|
|
users (사용자) ← auth_id → Supabase Auth
|
|
↓
|
|
department_permissions (부서별 권한)
|
|
↓
|
|
audit_logs (감사 로그)
|
|
```
|
|
|
|
---
|
|
|
|
## 🎨 사용자 흐름
|
|
|
|
### 회원가입 플로우
|
|
```
|
|
1. /auth/signup 접속
|
|
2. 부서 목록 로드 (Supabase departments 테이블)
|
|
3. 정보 입력 (사번, 이름, 부서, 이메일, 비밀번호)
|
|
4. 이메일 도메인 검증 (humetro.busan.kr)
|
|
5. Supabase Auth에 사용자 생성
|
|
6. users 테이블에 정보 저장
|
|
7. 로그인 페이지로 리다이렉트
|
|
```
|
|
|
|
### 로그인 플로우
|
|
```
|
|
1. /auth/login 접속
|
|
2. 이메일/비밀번호 입력
|
|
3. Supabase Auth 인증
|
|
4. users 테이블에서 사용자 정보 조회
|
|
5. 세션에 사용자 정보 저장
|
|
6. 메인 페이지로 리다이렉트
|
|
```
|
|
|
|
### 로그아웃 플로우
|
|
```
|
|
1. /auth/logout 접속
|
|
2. Supabase Auth 로그아웃
|
|
3. 세션 클리어
|
|
4. 로그인 페이지로 리다이렉트
|
|
```
|
|
|
|
---
|
|
|
|
## 🔍 API 엔드포인트
|
|
|
|
### 인증 관련
|
|
- `GET /auth/login` - 로그인 페이지
|
|
- `POST /auth/login` - 로그인 처리
|
|
- `GET /auth/signup` - 회원가입 페이지
|
|
- `POST /auth/signup` - 회원가입 처리
|
|
- `GET /auth/logout` - 로그아웃
|
|
|
|
### 메인
|
|
- `GET /` - 메인 페이지 (로그인 필요)
|
|
|
|
---
|
|
|
|
## 🛠️ 향후 확장 가능 사항
|
|
|
|
### 1. 부서별 권한 적용
|
|
`department_permissions` 테이블을 활용하여:
|
|
- 고장코드 조회/수정 권한 제어
|
|
- TCMS 신호 조회/수정 권한 제어
|
|
- MMI 코드 조회/수정 권한 제어
|
|
|
|
### 2. 감사 로그 활용
|
|
`audit_logs` 테이블을 활용하여:
|
|
- 사용자 활동 추적
|
|
- 데이터 수정 이력 관리
|
|
- 보안 모니터링
|
|
|
|
### 3. 비밀번호 정책 강화
|
|
- 대문자, 숫자, 특수문자 포함 필수
|
|
- 비밀번호 변경 주기 설정
|
|
- 비밀번호 재사용 방지
|
|
|
|
### 4. 2단계 인증 (2FA)
|
|
- OTP 인증 추가
|
|
- SMS 인증 추가
|
|
|
|
### 5. 관리자 페이지
|
|
- 사용자 관리 (활성화/비활성화)
|
|
- 부서 관리
|
|
- 권한 관리
|
|
|
|
---
|
|
|
|
## 📋 체크리스트
|
|
|
|
### 설정 완료 확인
|
|
- [ ] `database_schema.sql` 실행
|
|
- [ ] `.env` 파일에 `SECRET_KEY` 설정
|
|
- [ ] Supabase Auth 이메일 인증 활성화
|
|
- [ ] 부서 데이터 확인 (`SELECT * FROM departments`)
|
|
- [ ] 테스트 회원가입 수행
|
|
- [ ] 테스트 로그인 수행
|
|
|
|
### 프로덕션 배포 전
|
|
- [ ] `SECRET_KEY` 변경 (강력한 랜덤 키)
|
|
- [ ] HTTPS 활성화
|
|
- [ ] CORS 설정 검토
|
|
- [ ] Supabase 프로덕션 환경 설정
|
|
- [ ] 이메일 템플릿 커스터마이징
|
|
- [ ] 로그 모니터링 설정
|
|
|
|
---
|
|
|
|
## 📚 관련 문서
|
|
|
|
- **AUTH_SETUP.md**: 상세 설정 가이드 및 트러블슈팅
|
|
- **database_schema.sql**: 데이터베이스 스키마 전체
|
|
- **auth.py**: 인증 모듈 소스 코드
|
|
|
|
---
|
|
|
|
## 🤝 기술 스택
|
|
|
|
- **Backend**: Flask (Python)
|
|
- **Authentication**: Supabase Auth
|
|
- **Database**: Supabase (PostgreSQL)
|
|
- **Frontend**: Pico CSS, HTMX
|
|
- **Session**: Flask Session (서버 사이드)
|
|
|
|
---
|
|
|
|
**작성일**: 2024년 10월
|
|
**부산교통공사 차량처**
|
|
**1호선 고장코드 시스템 v2.0**
|
|
|