Files
tk-factory-services/system3-nonconformance/api/migrations/011_add_permission_system.sql
Hyungi Ahn 550633b89d feat: 3-System 분리 프로젝트 초기 코드 작성
TK-FB(공장관리+신고)와 M-Project(부적합관리)를 3개 독립 시스템으로
분리하기 위한 전체 코드 구조 작성.
- SSO 인증 서비스 (bcrypt + pbkdf2 이중 해시 지원)
- System 1: 공장관리 (TK-FB 기반, 신고 코드 제거)
- System 2: 신고 (TK-FB에서 workIssue 코드 추출)
- System 3: 부적합관리 (M-Project 기반)
- Gateway 포털 (path-based 라우팅)
- 통합 docker-compose.yml 및 배포 스크립트

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 14:40:11 +09:00

138 lines
4.4 KiB
PL/PgSQL

-- 권한 시스템 개선 마이그레이션
-- 새로운 사용자 역할 추가 및 개별 권한 테이블 생성
-- 1. 새로운 사용자 역할 추가
ALTER TYPE userrole ADD VALUE 'super_admin';
ALTER TYPE userrole ADD VALUE 'manager';
-- 2. 사용자별 개별 권한 테이블 생성
CREATE TABLE IF NOT EXISTS user_permissions (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
permission VARCHAR(50) NOT NULL,
granted BOOLEAN DEFAULT TRUE,
granted_by_id INTEGER REFERENCES users(id),
granted_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
revoked_at TIMESTAMP WITH TIME ZONE,
notes TEXT,
UNIQUE(user_id, permission)
);
-- 3. 인덱스 생성
CREATE INDEX IF NOT EXISTS idx_user_permissions_user_id ON user_permissions(user_id);
CREATE INDEX IF NOT EXISTS idx_user_permissions_permission ON user_permissions(permission);
CREATE INDEX IF NOT EXISTS idx_user_permissions_granted ON user_permissions(granted);
-- 4. 기본 권한 설정 (기존 관리자에게 super_admin 권한 부여)
UPDATE users SET role = 'super_admin' WHERE username = 'hyungi';
-- 5. 권한 확인 함수 생성
CREATE OR REPLACE FUNCTION check_user_permission(p_user_id INTEGER, p_permission VARCHAR)
RETURNS BOOLEAN AS $$
DECLARE
user_role userrole;
has_permission BOOLEAN := FALSE;
BEGIN
-- 사용자 역할 가져오기
SELECT role INTO user_role FROM users WHERE id = p_user_id AND is_active = TRUE;
IF user_role IS NULL THEN
RETURN FALSE;
END IF;
-- super_admin은 모든 권한 보유
IF user_role = 'super_admin' THEN
RETURN TRUE;
END IF;
-- 개별 권한 확인
SELECT granted INTO has_permission
FROM user_permissions
WHERE user_id = p_user_id
AND permission = p_permission
AND granted = TRUE
AND revoked_at IS NULL;
-- 개별 권한이 없으면 역할 기반 기본 권한 확인
IF has_permission IS NULL THEN
-- 기본 권한 매트릭스
CASE
WHEN p_permission IN ('issues.create', 'issues.view') THEN
has_permission := TRUE; -- 모든 사용자
WHEN p_permission IN ('issues.edit', 'issues.review', 'daily_work.create', 'daily_work.view', 'daily_work.edit') THEN
has_permission := user_role IN ('admin', 'manager'); -- 관리자, 매니저
WHEN p_permission IN ('projects.create', 'projects.edit', 'issues.delete', 'daily_work.delete') THEN
has_permission := user_role = 'admin'; -- 관리자만
WHEN p_permission IN ('projects.delete', 'users.create', 'users.edit', 'users.delete', 'users.change_role') THEN
has_permission := user_role = 'super_admin'; -- 최고 관리자만
ELSE
has_permission := FALSE;
END CASE;
END IF;
RETURN COALESCE(has_permission, FALSE);
END;
$$ LANGUAGE plpgsql;
-- 6. 권한 부여 함수 생성
CREATE OR REPLACE FUNCTION grant_user_permission(
p_user_id INTEGER,
p_permission VARCHAR,
p_granted_by_id INTEGER,
p_notes TEXT DEFAULT NULL
)
RETURNS BOOLEAN AS $$
BEGIN
INSERT INTO user_permissions (user_id, permission, granted, granted_by_id, notes)
VALUES (p_user_id, p_permission, TRUE, p_granted_by_id, p_notes)
ON CONFLICT (user_id, permission)
DO UPDATE SET
granted = TRUE,
granted_by_id = p_granted_by_id,
granted_at = NOW(),
revoked_at = NULL,
notes = p_notes;
RETURN TRUE;
END;
$$ LANGUAGE plpgsql;
-- 7. 권한 취소 함수 생성
CREATE OR REPLACE FUNCTION revoke_user_permission(
p_user_id INTEGER,
p_permission VARCHAR,
p_revoked_by_id INTEGER,
p_notes TEXT DEFAULT NULL
)
RETURNS BOOLEAN AS $$
BEGIN
UPDATE user_permissions
SET granted = FALSE,
revoked_at = NOW(),
notes = p_notes
WHERE user_id = p_user_id
AND permission = p_permission;
RETURN TRUE;
END;
$$ LANGUAGE plpgsql;
-- 8. 사용자 권한 목록 조회 뷰 생성
CREATE OR REPLACE VIEW user_permissions_view AS
SELECT
u.id as user_id,
u.username,
u.full_name,
u.role,
up.permission,
up.granted,
up.granted_at,
up.revoked_at,
granted_by.username as granted_by_username,
up.notes
FROM users u
LEFT JOIN user_permissions up ON u.id = up.user_id
LEFT JOIN users granted_by ON up.granted_by_id = granted_by.id
WHERE u.is_active = TRUE
ORDER BY u.username, up.permission;