법인 회원 초대 대응
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
flowchart TD
|
||||
Start([법인 관리자가 사용자 초대]) --> GenerateToken[8글자 토큰 생성<br/>예: K7MNPQ2R<br/>UserInvitation 저장]
|
||||
|
||||
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
|
||||
|
||||
SignupPage1 --> RegisterForm[가입 정보 입력<br/>- 이메일 자동 입력됨<br/>- 법인명 표시<br/>- 약관 동의]
|
||||
RegisterForm --> RegisterComplete[회원가입 완료<br/>ROLE_CORP_USER로 생성]
|
||||
RegisterComplete --> NewUserEnd([가입 완료 안내])
|
||||
|
||||
%% 기존 회원 플로우
|
||||
UserType -->|기존 회원<br/>ROLE_USER| ExistingUserPath{초대 확인 방법}
|
||||
|
||||
ExistingUserPath -->|폐쇄망 환경| LoginPage2[로그인 페이지 접근]
|
||||
LoginPage2 --> InviteLink2["초대를 받으셨나요?" 링크 클릭]
|
||||
InviteLink2 --> InputCodePage2[초대코드 입력 페이지]
|
||||
InputCodePage2 --> CheckLogin1{로그인 여부}
|
||||
|
||||
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[로그인 페이지에서 로그인]
|
||||
DirectLogin --> Login3[로그인]
|
||||
Login3 --> AfterLogin3[로그인 성공]
|
||||
|
||||
%% 로그인 후 자동 초대 확인
|
||||
AfterLogin1 --> CheckInvitation[초대 코드 자동 확인<br/>findFirstByInvitationEmailAndStatus]
|
||||
AfterLogin2 --> CheckInvitation
|
||||
AfterLogin3 --> CheckInvitation
|
||||
|
||||
CheckInvitation --> HasInvitation{초대 코드 존재?}
|
||||
|
||||
HasInvitation -->|없음| NormalHome[일반 홈페이지]
|
||||
HasInvitation -->|있음| AutoRedirect[자동으로 초대 수락 페이지로 이동<br/>/signup/decision_process]
|
||||
|
||||
AutoRedirect --> DecisionPage1
|
||||
DecisionPage1 --> UserDecision{사용자 선택}
|
||||
|
||||
UserDecision -->|수락| AcceptProcess[초대 수락 처리<br/>1. PortalOrg 변경<br/>2. ROLE_CORP_USER 전환<br/>3. 약관 재동의]
|
||||
UserDecision -->|거절| RejectProcess[초대 거절 처리<br/>Invitation.status = REJECTED]
|
||||
|
||||
AcceptProcess --> CompleteInvitation[Invitation.status = COMPLETED]
|
||||
CompleteInvitation --> LogoutPrompt[로그아웃 후 재로그인 안내]
|
||||
LogoutPrompt --> ExistingUserEnd([초대 수락 완료])
|
||||
|
||||
RejectProcess --> RejectEnd([초대 거절 완료])
|
||||
|
||||
%% 에러 처리
|
||||
Error1 --> ErrorEnd([처리 종료])
|
||||
Error2 --> ErrorEnd
|
||||
|
||||
%% 스타일링
|
||||
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 GenerateToken fill:#bbdefb
|
||||
style AcceptProcess fill:#c5cae9
|
||||
style CheckInvitation fill:#ffe0b2
|
||||
style AutoRedirect fill:#ffe0b2
|
||||
|
||||
style LoginPage1 fill:#e1bee7
|
||||
style LoginPage2 fill:#e1bee7
|
||||
style InviteLink1 fill:#f8bbd0
|
||||
style InviteLink2 fill:#f8bbd0
|
||||
style InputCodePage1 fill:#f8bbd0
|
||||
style InputCodePage2 fill:#f8bbd0
|
||||
@@ -0,0 +1,44 @@
|
||||
flowchart TD
|
||||
Start([법인 관리자가 사용자 초대 시작]) --> CheckUser{가입된 사용자인가?}
|
||||
|
||||
CheckUser -->|아니오| Error1[에러: 가입된 사용자만 초대 가능]
|
||||
CheckUser -->|예| CheckRole{이미 법인 사용자인가?}
|
||||
|
||||
CheckRole -->|예| Error2[에러: 이미 기관에 등록된 사용자]
|
||||
CheckRole -->|아니오 ROLE_USER| CreateInvitation[8글자 토큰 생성<br/>UserInvitation 저장<br/>상태: PENDING]
|
||||
|
||||
CreateInvitation --> SendEmail[이메일 발송<br/>UserInvitationEvent]
|
||||
|
||||
SendEmail --> UserReceive{사용자가 토큰 받음}
|
||||
|
||||
UserReceive -->|폐쇄망| ManualInput[8글자 토큰 직접 입력<br/>예: K7MNPQ2R]
|
||||
UserReceive -->|이메일 링크| EmailLink[Base64 인코딩된<br/>링크 클릭]
|
||||
|
||||
ManualInput --> DecodeToken[토큰 디코딩<br/>decodeInvitationToken]
|
||||
EmailLink --> DecodeToken
|
||||
|
||||
DecodeToken --> ValidateToken{토큰 유효성 검증}
|
||||
|
||||
ValidateToken -->|무효| Error3[에러: 유효하지 않은 초대]
|
||||
ValidateToken -->|유효 & PENDING| ShowDecision[약관 동의 페이지<br/>/signup/decision]
|
||||
|
||||
ShowDecision --> UserDecision{사용자 선택}
|
||||
|
||||
UserDecision -->|수락| ProcessAccept[processInvitation: accept]
|
||||
UserDecision -->|거절| ProcessReject[processInvitation: reject]
|
||||
|
||||
ProcessAccept --> UpdateUser[1. PortalOrg 변경<br/>2. ROLE_CORP_USER로 전환<br/>3. 약관 재동의 PRIVACY_COLLECT_ORG]
|
||||
UpdateUser --> CompleteInvitation[Invitation 상태:<br/>COMPLETED + completeDate]
|
||||
CompleteInvitation --> Success([초대 수락 완료<br/>로그아웃 후 재로그인])
|
||||
|
||||
ProcessReject --> RejectInvitation[Invitation 상태:<br/>REJECTED + completeDate]
|
||||
RejectInvitation --> End([초대 거절 완료])
|
||||
|
||||
style Start fill:#e1f5e1
|
||||
style Success fill:#c8e6c9
|
||||
style End fill:#fff9c4
|
||||
style Error1 fill:#ffcdd2
|
||||
style Error2 fill:#ffcdd2
|
||||
style Error3 fill:#ffcdd2
|
||||
style CreateInvitation fill:#bbdefb
|
||||
style UpdateUser fill:#c5cae9
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
sequenceDiagram
|
||||
actor 법인관리자
|
||||
participant Portal as Portal UI
|
||||
participant UserManFacade
|
||||
participant UserInvitationRepo as UserInvitation Repository
|
||||
participant MessageService as Message Handler
|
||||
participant Email as Email System
|
||||
actor 초대받은사용자
|
||||
participant UserRegisterController
|
||||
participant UserRegisterFacade
|
||||
participant PortalUserRepo as PortalUser Repository
|
||||
|
||||
법인관리자->>Portal: 사용자 이메일 입력<br/>초대 요청
|
||||
Portal->>UserManFacade: sendInvitation(sender, emailAddr)
|
||||
|
||||
UserManFacade->>PortalUserRepo: findByEmailAddr(emailAddr)
|
||||
alt 사용자가 없거나 이미 법인 사용자
|
||||
UserManFacade-->>Portal: 에러 반환
|
||||
Portal-->>법인관리자: 초대 불가 알림
|
||||
else 일반 사용자 ROLE_USER
|
||||
UserManFacade->>UserManFacade: generateEightCharToken()<br/>예: K7MNPQ2R
|
||||
UserManFacade->>UserInvitationRepo: save(UserInvitation)<br/>status: PENDING<br/>expiresOn: 7일 후
|
||||
UserManFacade->>MessageService: publishEvent(UserInvitationEvent)
|
||||
MessageService->>Email: 초대 이메일 발송<br/>(법인명, 관리자명, 토큰)
|
||||
UserManFacade-->>Portal: 초대 완료
|
||||
Portal-->>법인관리자: 초대 성공 알림
|
||||
end
|
||||
|
||||
Email->>초대받은사용자: 초대 이메일 수신
|
||||
|
||||
alt 폐쇄망 환경
|
||||
초대받은사용자->>Portal: 8글자 토큰 직접 입력<br/>/signup/decision?invitation=K7MNPQ2R
|
||||
else 이메일 링크
|
||||
초대받은사용자->>Portal: 링크 클릭<br/>/signup/decision?invitation=BASE64TOKEN
|
||||
end
|
||||
|
||||
Portal->>UserRegisterController: showDecisionPage(invitationToken)
|
||||
UserRegisterController->>UserRegisterController: decodeInvitationToken()<br/>(Base64 or 직접입력 처리)
|
||||
UserRegisterController->>UserInvitationRepo: findByToken(decodedToken)
|
||||
|
||||
alt 토큰 무효 or 상태가 PENDING 아님
|
||||
UserRegisterController-->>Portal: 에러: 유효하지 않은 초대
|
||||
Portal-->>초대받은사용자: 에러 페이지
|
||||
else 토큰 유효
|
||||
UserRegisterController->>PortalUserRepo: findByEmailAddr()
|
||||
UserRegisterController-->>Portal: 약관 동의 페이지<br/>(법인명, 사용자명 표시)
|
||||
Portal-->>초대받은사용자: 수락/거절 선택 화면
|
||||
end
|
||||
|
||||
초대받은사용자->>Portal: 수락 or 거절 선택
|
||||
Portal->>UserRegisterController: processInvitation(action)
|
||||
UserRegisterController->>UserRegisterFacade: processInvitation(action, invitation)
|
||||
|
||||
alt 수락
|
||||
UserRegisterFacade->>PortalUserRepo: findByEmailAddr()
|
||||
UserRegisterFacade->>PortalUserRepo: updateUserToCorpUser()<br/>(PortalOrg 변경<br/>ROLE_CORP_USER 전환)
|
||||
UserRegisterFacade->>UserInvitationRepo: save(invitation)<br/>status: COMPLETED<br/>completeDate: now()
|
||||
UserRegisterFacade-->>Portal: 수락 성공
|
||||
Portal-->>초대받은사용자: 성공 메시지<br/>로그아웃 후 재로그인 안내
|
||||
else 거절
|
||||
UserRegisterFacade->>UserInvitationRepo: save(invitation)<br/>status: REJECTED<br/>completeDate: now()
|
||||
UserRegisterFacade-->>Portal: 거절 처리 완료
|
||||
Portal-->>초대받은사용자: 거절 완료 메시지
|
||||
end
|
||||
@@ -0,0 +1,20 @@
|
||||
stateDiagram-v2
|
||||
[*] --> 초대생성: 법인관리자가 초대 시작
|
||||
|
||||
초대생성 --> PENDING: 8글자 토큰 생성<br/>UserInvitation 저장
|
||||
|
||||
PENDING --> 토큰전달: 이메일 발송
|
||||
|
||||
토큰전달 --> 사용자접근: 폐쇄망 직접입력 or<br/>이메일 링크 클릭
|
||||
|
||||
사용자접근 --> 약관동의: 토큰 유효성 검증 성공
|
||||
사용자접근 --> 에러: 토큰 무효
|
||||
|
||||
약관동의 --> COMPLETED: 사용자 수락<br/>ROLE_CORP_USER 전환<br/>PortalOrg 변경
|
||||
약관동의 --> REJECTED: 사용자 거절
|
||||
|
||||
COMPLETED --> [*]: 초대 완료
|
||||
REJECTED --> [*]: 초대 거절
|
||||
PENDING --> CANCELED: 관리자가 초대 취소
|
||||
CANCELED --> [*]: 초대 취소
|
||||
에러 --> [*]: 처리 종료
|
||||
Reference in New Issue
Block a user