법인 회원 초대 방법 개선

This commit is contained in:
Rinjae
2025-11-25 14:29:22 +09:00
parent d7a32e1dcf
commit 39ca5837ef
8 changed files with 245 additions and 96 deletions
+62 -56
View File
@@ -1,99 +1,105 @@
flowchart TD
Start([법인 관리자가 사용자 초대]) --> GenerateToken[8글자 토큰 생성<br/>예: K7MNPQ2R<br/>UserInvitation 저장]
Start([법인 관리자가 사용자 초대]) --> GenerateToken[8글자 토큰 생성<br/>예: K7MNPQ2R<br/>UserInvitation 저장<br/>상태: PENDING]
GenerateToken --> SendEmail[이메일 발송<br/>- 링크 포함<br/>- 8글자 토큰 표시]
SendEmail --> UserType{사용자 유형}
%% ========================================
%% 신규 회원 플로우
%% ========================================
UserType -->|신규 회원<br/>미가입자| NewUserPath{초대 확인 방법}
NewUserPath -->|폐쇄망 환경| LoginPage1[로그인 페이지 접근]
LoginPage1 --> InviteLink1["초대를 받으셨나요?" 링크 클릭]
InviteLink1 --> InputCodePage1[초대코드 입력 페이지]
InputCodePage1 --> InputCode1[8자리 코드 입력<br/>예: K7MNPQ2R]
InputCode1 --> ValidateCode1{코드 유효성 검증}
ValidateCode1 -->|유효하지 않음| Error1[에러: 유효하지 않은 초대코드]
ValidateCode1 -->|유효| SignupPage1[회원가입 페이지<br/>/signup/portalUser?invitation=CODE]
NewUserPath -->|이메일 링크| EmailLink1[이메일 링크 클릭<br/>/signup/portalUser?invitation=CODE]
EmailLink1 --> SignupPage1
NewUserPath -->|일반 회원가입| DirectSignup[일반 회원가입 진행<br/>ROLE_USER로 생성]
SignupPage1 --> RegisterForm[가입 정보 입력<br/>- 이메일 자동 입력됨<br/>- 법인명 표시<br/>- 약관 동의]
RegisterForm --> RegisterComplete[회원가입 완료<br/>ROLE_CORP_USER로 생성]
EmailLink1 --> SignupPage1[회원가입 페이지<br/>- 이메일 자동 입력됨<br/>- 법인명 표시]
SignupPage1 --> RegisterForm[가입 정보 입력<br/>약관 동의]
RegisterForm --> RegisterComplete[회원가입 완료<br/>ROLE_CORP_USER로 생성<br/>상태: COMPLETED]
RegisterComplete --> NewUserEnd([가입 완료 안내])
DirectSignup --> Login4[로그인]
Login4 --> AfterLogin4[로그인 성공]
AfterLogin4 --> CheckInvitation
%% ========================================
%% 기존 회원 플로우
%% ========================================
UserType -->|기존 회원<br/>ROLE_USER| ExistingUserPath{초대 확인 방법}
ExistingUserPath -->|폐쇄망 환경| LoginPage2[로그인 페이지 접근]
LoginPage2 --> InviteLink2["초대를 받으셨나요?" 링크 클릭]
InviteLink2 --> InputCodePage2[초대코드 입력 페이지]
InputCodePage2 --> CheckLogin1{로그인 여부}
ExistingUserPath -->|이메일 링크<br/>비로그인 상태| EmailLink2[이메일 링크 클릭<br/>/signup/decision?invitation=CODE]
ExistingUserPath -->|이메일 링크<br/>로그인 상태| EmailLinkLoggedIn[이메일 링크 클릭<br/>/signup/decision?invitation=CODE]
ExistingUserPath -->|직접 로그인| DirectLogin[로그인 페이지에서 로그인]
CheckLogin1 -->|미로그인| RedirectLogin1[로그인 페이지로 리다이렉트<br/>코드 저장]
RedirectLogin1 --> Login1[로그인]
Login1 --> AfterLogin1[로그인 성공]
CheckLogin1 -->|로그인됨| InputCode2[8자리 코드 입력]
InputCode2 --> ValidateCode2{코드 유효성 검증}
ValidateCode2 -->|유효하지 않음| Error2[에러: 유효하지 않은 초대코드]
ValidateCode2 -->|유효| DecisionPage1[초대 수락 페이지<br/>/signup/decision_process]
ExistingUserPath -->|이메일 링크| EmailLink2[이메일 링크 클릭<br/>/signup/decision?invitation=CODE]
%% 비로그인 상태에서 이메일 링크 클릭
EmailLink2 --> DecisionPagePublic[초대 수락 페이지<br/>비로그인 상태]
DecisionPagePublic --> RedirectLogin2[로그인 유도]
RedirectLogin2 --> Login2[로그인]
Login2 --> AfterLogin2[로그인 성공]
ExistingUserPath -->|직접 로그인| DirectLogin[로그인 페이지에서 로그인]
%% 로그인 상태에서 이메일 링크 클릭 → 바로 수락 페이지
EmailLinkLoggedIn --> DecisionPageDirect[초대 수락 페이지<br/>/signup/decision_process<br/>약관 동의]
DecisionPageDirect --> UserDecision
%% 직접 로그인
DirectLogin --> Login3[로그인]
Login3 --> AfterLogin3[로그인 성공]
%% 로그인 후 자동 초대 확인
AfterLogin1 --> CheckInvitation[초대 코드 자동 확인<br/>findFirstByInvitationEmailAndStatus]
AfterLogin2 --> CheckInvitation
%% ========================================
%% 로그인 후 초대 확인 (PortalAuthenticationSuccessHandler)
%% ========================================
AfterLogin2 --> CheckInvitation[PortalAuthenticationSuccessHandler<br/>PENDING 초대 확인<br/>findFirstByInvitationEmailAndStatus]
AfterLogin3 --> CheckInvitation
CheckInvitation --> HasInvitation{초대 코드 존재?}
CheckInvitation --> HasInvitation{PENDING 초대 존재?}
HasInvitation -->|없음| NormalHome[일반 홈페이지]
HasInvitation -->|있음| AutoRedirect[자동으로 초대 수락 페이지로 이동<br/>/signup/decision_process]
HasInvitation -->|없음| NormalHome[메인 페이지 이동]
HasInvitation -->|있음| SaveToSession[세션에 초대 정보 저장<br/>pendingInvitation=true<br/>pendingInvitationToken<br/>pendingInvitationOrgName]
AutoRedirect --> DecisionPage1
DecisionPage1 --> UserDecision{사용자 선택}
SaveToSession --> RedirectHome[메인 페이지로 이동]
UserDecision -->|수락| AcceptProcess[초대 수락 처리<br/>1. PortalOrg 변경<br/>2. ROLE_CORP_USER 전환<br/>3. 약관 재동의]
UserDecision -->|거절| RejectProcess[초대 거절 처리<br/>Invitation.status = REJECTED]
%% ========================================
%% 메인 페이지 팝업 (index.html)
%% ========================================
RedirectHome --> ShowPopup[팝업 표시<br/>OOO에서 초대가 도착했습니다<br/>초대를 확인하시겠습니까?]
AcceptProcess --> CompleteInvitation[Invitation.status = COMPLETED]
CompleteInvitation --> LogoutPrompt[로그아웃 후 재로그인 안내]
ShowPopup --> PopupChoice{사용자 선택}
PopupChoice -->|확인| GoDecisionPage[초대 수락 페이지 이동<br/>/signup/decision?invitation=TOKEN]
PopupChoice -->|취소| StayHome[메인 페이지 유지<br/>다음 로그인 시 팝업 재표시]
StayHome --> NextLogin[다음 로그인]
NextLogin --> CheckInvitation
GoDecisionPage --> DecisionPage[초대 수락 페이지<br/>/signup/decision_process<br/>약관 동의]
DecisionPage --> UserDecision{사용자 선택}
UserDecision -->|수락| AcceptProcess[초대 수락 처리<br/>1. PortalOrg 변경<br/>2. ROLE_CORP_USER 전환<br/>3. 약관 재동의<br/>상태: COMPLETED]
UserDecision -->|거절| RejectProcess[초대 거절 처리<br/>상태: REJECTED]
AcceptProcess --> LogoutPrompt[로그아웃 후 재로그인 안내]
LogoutPrompt --> ExistingUserEnd([초대 수락 완료])
RejectProcess --> RejectEnd([초대 거절 완료])
%% 에러 처리
Error1 --> ErrorEnd([처리 종료])
Error2 --> ErrorEnd
RejectProcess --> RejectEnd([초대 거절 완료<br/>다음 로그인 시 팝업 안 뜸])
%% ========================================
%% 스타일링
%% ========================================
style Start fill:#e1f5e1
style NewUserEnd fill:#c8e6c9
style ExistingUserEnd fill:#c8e6c9
style RejectEnd fill:#fff9c4
style ErrorEnd fill:#ffcdd2
style Error1 fill:#ffcdd2
style Error2 fill:#ffcdd2
style NormalHome fill:#e3f2fd
style GenerateToken fill:#bbdefb
style AcceptProcess fill:#c5cae9
style CheckInvitation fill:#ffe0b2
style AutoRedirect fill:#ffe0b2
style RejectProcess fill:#ffecb3
style LoginPage1 fill:#e1bee7
style LoginPage2 fill:#e1bee7
style InviteLink1 fill:#f8bbd0
style InviteLink2 fill:#f8bbd0
style InputCodePage1 fill:#f8bbd0
style InputCodePage2 fill:#f8bbd0
style CheckInvitation fill:#ffe0b2
style SaveToSession fill:#ffe0b2
style ShowPopup fill:#f8bbd0
style PopupChoice fill:#f8bbd0
style StayHome fill:#e1bee7
style NextLogin fill:#e1bee7