- database/schema/ 14개 DDL 파일 신규 생성 (운영 DB pg_dump 기반) - database/seed/ 14개 초기 데이터 파일 분리 - database/_deprecated/로 구 init.sql, auth_init.sql 이동 - database/README.md 신규 작성 (DB 아키텍처, 설치 절차) - docs/ 6개 가이드 문서 wing_auth→auth 스키마 구조로 수정 - README.md, CLAUDE.md wing 단일 DB 구조 반영 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
253 lines
10 KiB
SQL
253 lines
10 KiB
SQL
-- WING-OPS Database Schema: Auth Tables
|
|
-- auth 스키마 9개 테이블 (인증/인가/감사)
|
|
|
|
-- ============================================================
|
|
-- 1. auth_role — 역할 (FK 없음, 최상위)
|
|
-- ============================================================
|
|
CREATE TABLE auth.auth_role (
|
|
role_sn integer NOT NULL,
|
|
role_cd character varying(20) NOT NULL,
|
|
role_nm character varying(50) NOT NULL,
|
|
role_dc character varying(200),
|
|
dflt_yn character(1) DEFAULT 'N'::bpchar NOT NULL,
|
|
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
|
|
CONSTRAINT pk_auth_role PRIMARY KEY (role_sn),
|
|
CONSTRAINT uk_auth_role_cd UNIQUE (role_cd),
|
|
CONSTRAINT ck_auth_role_dflt CHECK ((dflt_yn = ANY (ARRAY['Y'::bpchar, 'N'::bpchar])))
|
|
);
|
|
|
|
CREATE SEQUENCE auth.auth_role_role_sn_seq
|
|
AS integer
|
|
START WITH 1
|
|
INCREMENT BY 1
|
|
NO MINVALUE
|
|
NO MAXVALUE
|
|
CACHE 1;
|
|
|
|
ALTER SEQUENCE auth.auth_role_role_sn_seq OWNED BY auth.auth_role.role_sn;
|
|
ALTER TABLE ONLY auth.auth_role ALTER COLUMN role_sn SET DEFAULT nextval('auth.auth_role_role_sn_seq'::regclass);
|
|
|
|
|
|
-- ============================================================
|
|
-- 2. auth_org — 조직 (자기참조 FK)
|
|
-- ============================================================
|
|
CREATE TABLE auth.auth_org (
|
|
org_sn integer NOT NULL,
|
|
org_nm character varying(100) NOT NULL,
|
|
org_abbr_nm character varying(20) NOT NULL,
|
|
org_tp_cd character varying(20) NOT NULL,
|
|
upper_org_sn integer,
|
|
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
|
|
CONSTRAINT pk_auth_org PRIMARY KEY (org_sn)
|
|
);
|
|
|
|
CREATE SEQUENCE auth.auth_org_org_sn_seq
|
|
AS integer
|
|
START WITH 1
|
|
INCREMENT BY 1
|
|
NO MINVALUE
|
|
NO MAXVALUE
|
|
CACHE 1;
|
|
|
|
ALTER SEQUENCE auth.auth_org_org_sn_seq OWNED BY auth.auth_org.org_sn;
|
|
ALTER TABLE ONLY auth.auth_org ALTER COLUMN org_sn SET DEFAULT nextval('auth.auth_org_org_sn_seq'::regclass);
|
|
|
|
|
|
-- ============================================================
|
|
-- 3. auth_user — 사용자 (FK: auth_org)
|
|
-- ============================================================
|
|
CREATE TABLE auth.auth_user (
|
|
user_id uuid DEFAULT public.uuid_generate_v4() NOT NULL,
|
|
user_acnt character varying(50) NOT NULL,
|
|
pswd_hash character varying(255),
|
|
user_nm character varying(50) NOT NULL,
|
|
rnkp_nm character varying(30),
|
|
org_sn integer,
|
|
user_stts_cd character varying(20) DEFAULT 'ACTIVE'::character varying NOT NULL,
|
|
fail_cnt integer DEFAULT 0 NOT NULL,
|
|
last_login_dtm timestamp with time zone,
|
|
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
|
|
mdfcn_dtm timestamp with time zone DEFAULT now() NOT NULL,
|
|
oauth_provider character varying(20),
|
|
oauth_sub character varying(255),
|
|
email character varying(255),
|
|
CONSTRAINT pk_auth_user PRIMARY KEY (user_id),
|
|
CONSTRAINT uk_auth_user_acnt UNIQUE (user_acnt),
|
|
CONSTRAINT ck_auth_user_stts CHECK (((user_stts_cd)::text = ANY (ARRAY[('ACTIVE'::character varying)::text, ('LOCKED'::character varying)::text, ('INACTIVE'::character varying)::text])))
|
|
);
|
|
|
|
-- 조건부 유니크 인덱스 (NULL 값 제외)
|
|
CREATE UNIQUE INDEX uk_auth_user_email ON auth.auth_user USING btree (email) WHERE (email IS NOT NULL);
|
|
CREATE UNIQUE INDEX uk_auth_user_oauth ON auth.auth_user USING btree (oauth_provider, oauth_sub) WHERE (oauth_provider IS NOT NULL);
|
|
|
|
|
|
-- ============================================================
|
|
-- 4. auth_user_role — 사용자-역할 매핑 (FK: auth_user, auth_role)
|
|
-- ============================================================
|
|
CREATE TABLE auth.auth_user_role (
|
|
user_id uuid NOT NULL,
|
|
role_sn integer NOT NULL,
|
|
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
|
|
CONSTRAINT pk_auth_user_role PRIMARY KEY (user_id, role_sn)
|
|
);
|
|
|
|
|
|
-- ============================================================
|
|
-- 5. auth_perm_tree — 권한 트리 (자기참조 FK)
|
|
-- ============================================================
|
|
CREATE TABLE auth.auth_perm_tree (
|
|
rsrc_cd character varying(50) NOT NULL,
|
|
parent_cd character varying(50),
|
|
rsrc_nm character varying(100) NOT NULL,
|
|
rsrc_desc character varying(200),
|
|
icon character varying(20),
|
|
rsrc_level smallint DEFAULT 0 NOT NULL,
|
|
sort_ord smallint DEFAULT 0 NOT NULL,
|
|
use_yn character(1) DEFAULT 'Y'::bpchar NOT NULL,
|
|
CONSTRAINT pk_perm_tree PRIMARY KEY (rsrc_cd)
|
|
);
|
|
|
|
|
|
-- ============================================================
|
|
-- 6. auth_perm — 역할별 권한 (FK: auth_role)
|
|
-- ============================================================
|
|
CREATE TABLE auth.auth_perm (
|
|
perm_sn integer NOT NULL,
|
|
role_sn integer NOT NULL,
|
|
rsrc_cd character varying(50) NOT NULL,
|
|
grant_yn character(1) DEFAULT 'Y'::bpchar NOT NULL,
|
|
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
|
|
oper_cd character varying(20) NOT NULL,
|
|
CONSTRAINT pk_auth_perm PRIMARY KEY (perm_sn),
|
|
CONSTRAINT uk_auth_perm UNIQUE (role_sn, rsrc_cd, oper_cd),
|
|
CONSTRAINT ck_auth_perm_grant CHECK ((grant_yn = ANY (ARRAY['Y'::bpchar, 'N'::bpchar]))),
|
|
CONSTRAINT ck_auth_perm_oper CHECK (((oper_cd)::text = ANY (ARRAY[('READ'::character varying)::text, ('CREATE'::character varying)::text, ('UPDATE'::character varying)::text, ('DELETE'::character varying)::text, ('MANAGE'::character varying)::text, ('EXPORT'::character varying)::text])))
|
|
);
|
|
|
|
CREATE SEQUENCE auth.auth_perm_perm_sn_seq
|
|
AS integer
|
|
START WITH 1
|
|
INCREMENT BY 1
|
|
NO MINVALUE
|
|
NO MAXVALUE
|
|
CACHE 1;
|
|
|
|
ALTER SEQUENCE auth.auth_perm_perm_sn_seq OWNED BY auth.auth_perm.perm_sn;
|
|
ALTER TABLE ONLY auth.auth_perm ALTER COLUMN perm_sn SET DEFAULT nextval('auth.auth_perm_perm_sn_seq'::regclass);
|
|
|
|
|
|
-- ============================================================
|
|
-- 7. auth_setting — 시스템 설정
|
|
-- ============================================================
|
|
CREATE TABLE auth.auth_setting (
|
|
setting_key character varying(100) NOT NULL,
|
|
setting_val text NOT NULL,
|
|
setting_dc character varying(500),
|
|
mdfcn_dtm timestamp without time zone DEFAULT now(),
|
|
CONSTRAINT auth_setting_pkey PRIMARY KEY (setting_key)
|
|
);
|
|
|
|
|
|
-- ============================================================
|
|
-- 8. auth_login_hist — 로그인 이력 (FK: auth_user)
|
|
-- ============================================================
|
|
CREATE TABLE auth.auth_login_hist (
|
|
hist_sn integer NOT NULL,
|
|
user_id uuid NOT NULL,
|
|
login_dtm timestamp with time zone DEFAULT now() NOT NULL,
|
|
ip_addr character varying(45),
|
|
user_agent character varying(500),
|
|
success_yn character(1) DEFAULT 'Y'::bpchar NOT NULL,
|
|
CONSTRAINT pk_auth_login_hist PRIMARY KEY (hist_sn),
|
|
CONSTRAINT ck_alh_success CHECK ((success_yn = ANY (ARRAY['Y'::bpchar, 'N'::bpchar])))
|
|
);
|
|
|
|
CREATE SEQUENCE auth.auth_login_hist_hist_sn_seq
|
|
AS integer
|
|
START WITH 1
|
|
INCREMENT BY 1
|
|
NO MINVALUE
|
|
NO MAXVALUE
|
|
CACHE 1;
|
|
|
|
ALTER SEQUENCE auth.auth_login_hist_hist_sn_seq OWNED BY auth.auth_login_hist.hist_sn;
|
|
ALTER TABLE ONLY auth.auth_login_hist ALTER COLUMN hist_sn SET DEFAULT nextval('auth.auth_login_hist_hist_sn_seq'::regclass);
|
|
|
|
|
|
-- ============================================================
|
|
-- 9. auth_audit_log — 감사 로그
|
|
-- ============================================================
|
|
CREATE TABLE auth.auth_audit_log (
|
|
log_sn integer NOT NULL,
|
|
user_id uuid,
|
|
action_cd character varying(30) NOT NULL,
|
|
action_dtl character varying(100),
|
|
http_method character varying(10),
|
|
crud_type character varying(10),
|
|
req_url character varying(500),
|
|
req_dtm timestamp with time zone DEFAULT now() NOT NULL,
|
|
res_dtm timestamp with time zone,
|
|
res_status smallint,
|
|
res_size integer,
|
|
ip_addr character varying(45),
|
|
user_agent character varying(500),
|
|
extra jsonb,
|
|
CONSTRAINT pk_auth_audit_log PRIMARY KEY (log_sn)
|
|
);
|
|
|
|
CREATE SEQUENCE auth.auth_audit_log_log_sn_seq
|
|
AS integer
|
|
START WITH 1
|
|
INCREMENT BY 1
|
|
NO MINVALUE
|
|
NO MAXVALUE
|
|
CACHE 1;
|
|
|
|
ALTER SEQUENCE auth.auth_audit_log_log_sn_seq OWNED BY auth.auth_audit_log.log_sn;
|
|
ALTER TABLE ONLY auth.auth_audit_log ALTER COLUMN log_sn SET DEFAULT nextval('auth.auth_audit_log_log_sn_seq'::regclass);
|
|
|
|
|
|
-- ============================================================
|
|
-- FK 제약조건
|
|
-- ============================================================
|
|
ALTER TABLE ONLY auth.auth_org
|
|
ADD CONSTRAINT fk_auth_org_upper FOREIGN KEY (upper_org_sn) REFERENCES auth.auth_org(org_sn);
|
|
|
|
ALTER TABLE ONLY auth.auth_user
|
|
ADD CONSTRAINT fk_auth_user_org FOREIGN KEY (org_sn) REFERENCES auth.auth_org(org_sn);
|
|
|
|
ALTER TABLE ONLY auth.auth_user_role
|
|
ADD CONSTRAINT fk_aur_user FOREIGN KEY (user_id) REFERENCES auth.auth_user(user_id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE ONLY auth.auth_user_role
|
|
ADD CONSTRAINT fk_aur_role FOREIGN KEY (role_sn) REFERENCES auth.auth_role(role_sn) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE ONLY auth.auth_perm_tree
|
|
ADD CONSTRAINT fk_perm_tree_parent FOREIGN KEY (parent_cd) REFERENCES auth.auth_perm_tree(rsrc_cd);
|
|
|
|
ALTER TABLE ONLY auth.auth_perm
|
|
ADD CONSTRAINT fk_ap_role FOREIGN KEY (role_sn) REFERENCES auth.auth_role(role_sn) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE ONLY auth.auth_login_hist
|
|
ADD CONSTRAINT fk_alh_user FOREIGN KEY (user_id) REFERENCES auth.auth_user(user_id) ON DELETE CASCADE;
|
|
|
|
|
|
-- ============================================================
|
|
-- 인덱스
|
|
-- ============================================================
|
|
CREATE INDEX idx_auth_user_org ON auth.auth_user USING btree (org_sn);
|
|
CREATE INDEX idx_auth_user_stts ON auth.auth_user USING btree (user_stts_cd);
|
|
|
|
CREATE INDEX idx_auth_perm_role ON auth.auth_perm USING btree (role_sn);
|
|
CREATE INDEX idx_auth_perm_rsrc ON auth.auth_perm USING btree (rsrc_cd);
|
|
CREATE INDEX idx_auth_perm_oper ON auth.auth_perm USING btree (oper_cd);
|
|
|
|
CREATE INDEX idx_perm_tree_parent ON auth.auth_perm_tree USING btree (parent_cd);
|
|
|
|
CREATE INDEX idx_auth_login_user ON auth.auth_login_hist USING btree (user_id);
|
|
CREATE INDEX idx_auth_login_dtm ON auth.auth_login_hist USING btree (login_dtm);
|
|
|
|
CREATE INDEX idx_audit_log_user ON auth.auth_audit_log USING btree (user_id);
|
|
CREATE INDEX idx_audit_log_action ON auth.auth_audit_log USING btree (action_cd);
|
|
CREATE INDEX idx_audit_log_dtm ON auth.auth_audit_log USING btree (req_dtm);
|