KJBank 흔적 삭제
This commit is contained in:
@@ -69,10 +69,17 @@ eapim-portal
|
|||||||
|
|
||||||
### 사전 요구사항
|
### 사전 요구사항
|
||||||
|
|
||||||
- JDK 8 이상
|
아래 도구 설치 및 검증 절차는 별도 문서로 분리되어 있습니다. 신규 개발자는 먼저 이 문서를 끝까지 진행하세요.
|
||||||
- Gradle 8.7
|
|
||||||
|
📄 **[개발환경 준비 사항](djb-docs/개발환경-준비-사항.md)** — JDK 8 · Gradle 8.7 · Git · Oracle 19c · Node.js & SASS · direnv · IDE 설정
|
||||||
|
|
||||||
|
요약:
|
||||||
|
|
||||||
|
- JDK 8 (Zulu 권장)
|
||||||
|
- Gradle 8.7 (gradlew 사용 금지)
|
||||||
- Git
|
- Git
|
||||||
- Oracle 19c (또는 개발 환경에 따라 접근 가능한 DB)
|
- Oracle 19c 접근 (개발: `192.168.240.177:1599`)
|
||||||
|
- Node.js 18 LTS 이상 (SCSS 컴파일용)
|
||||||
|
|
||||||
### Git Bash에서 초기 세팅
|
### Git Bash에서 초기 세팅
|
||||||
|
|
||||||
@@ -306,8 +313,11 @@ src/main/java/com/eactive/apim/portal/
|
|||||||
|
|
||||||
### 설치
|
### 설치
|
||||||
|
|
||||||
|
Node.js 및 SASS 설치 절차는 [개발환경 준비 사항 § 6. Node.js & SASS 빌드 환경](djb-docs/개발환경-준비-사항.md#6-nodejs--sass-빌드-환경) 을 참고하세요.
|
||||||
|
|
||||||
|
Node.js가 이미 설치되어 있다면 프로젝트 의존성만 설치하면 됩니다:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Node.js가 설치된 상태에서
|
|
||||||
npm install
|
npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -510,6 +520,7 @@ ls -lh src/main/resources/static/css/main.min.css # minified
|
|||||||
|
|
||||||
## 문서
|
## 문서
|
||||||
|
|
||||||
|
- **개발환경 준비 사항**: [`djb-docs/개발환경-준비-사항.md`](djb-docs/개발환경-준비-사항.md) — JDK·Gradle·Node.js·SASS 설치 가이드
|
||||||
- **프로젝트 상세 지침**: `CLAUDE.md` (한글)
|
- **프로젝트 상세 지침**: `CLAUDE.md` (한글)
|
||||||
- **사용자 가이드**: `개발자포탈.md` (한글)
|
- **사용자 가이드**: `개발자포탈.md` (한글)
|
||||||
- **빌드 스크립트**: `build-gf63.sh`, `deploy_portal.sh`
|
- **빌드 스크립트**: `build-gf63.sh`, `deploy_portal.sh`
|
||||||
|
|||||||
@@ -0,0 +1,273 @@
|
|||||||
|
# 개발환경 준비 사항
|
||||||
|
|
||||||
|
EAPIM Portal 개발에 필요한 도구와 런타임을 설치하고 검증하는 절차입니다.
|
||||||
|
처음 환경을 세팅하는 신규 개발자는 이 문서를 끝까지 따라 진행한 뒤 [README.md](../README.md)의 "초기 세팅 가이드" 단계를 이어서 수행하세요.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 0. 한눈에 보는 요구사항
|
||||||
|
|
||||||
|
| 구분 | 도구 | 권장 버전 | 비고 |
|
||||||
|
|------|------|-----------|----------------------------------|
|
||||||
|
| 백엔드 | JDK | 1.8 (Zulu 8 권장) | `sourceCompatibility=1.8` |
|
||||||
|
| 빌드 | Gradle | 8.7 | gradlew 사용 금지 — 시스템 gradle 직접 사용 |
|
||||||
|
| 형상관리 | Git | 2.30 이상 | SSH 키 등록 권장 |
|
||||||
|
| DB | Oracle Client/접근 | 19c | 개발은 `192.168.240.177:1598` |
|
||||||
|
| 프론트엔드 빌드 | Node.js | 18 LTS 이상 | SCSS 컴파일 전용 |
|
||||||
|
| 프론트엔드 빌드 | npm | Node.js 함께 설치 | `sass` 패키지 사용 |
|
||||||
|
| (선택) 환경 변수 | direnv | 최신 | `.envrc` 자동 로드 |
|
||||||
|
| (선택) IDE | IntelliJ IDEA | 2023.x 이상 | Lombok / MapStruct 플러그인 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. JDK 8 설치
|
||||||
|
|
||||||
|
Java 8 (1.8) 호환이 필요합니다. Azul Zulu JDK 8 사용을 권장합니다.
|
||||||
|
|
||||||
|
### macOS (Homebrew)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew install --cask zulu@8
|
||||||
|
# 설치 후 경로 확인
|
||||||
|
/usr/libexec/java_home -v 1.8
|
||||||
|
```
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
1. [Azul Zulu JDK 8 다운로드](https://www.azul.com/downloads/?version=java-8-lts&package=jdk)
|
||||||
|
2. MSI 설치 후 `JAVA_HOME` 환경변수 등록
|
||||||
|
3. `PATH`에 `%JAVA_HOME%\bin` 추가
|
||||||
|
|
||||||
|
### 검증
|
||||||
|
|
||||||
|
```bash
|
||||||
|
java -version # 1.8.x
|
||||||
|
javac -version # 1.8.x
|
||||||
|
echo $JAVA_HOME # macOS/Linux
|
||||||
|
echo %JAVA_HOME% # Windows
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Gradle 8.7 설치
|
||||||
|
|
||||||
|
이 프로젝트는 **gradlew 사용을 금지**합니다. 시스템에 설치된 gradle 8.7을 직접 사용합니다.
|
||||||
|
|
||||||
|
### macOS (Homebrew + SDKMAN 권장)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# SDKMAN 설치 (이미 있으면 생략)
|
||||||
|
curl -s "https://get.sdkman.io" | bash
|
||||||
|
source "$HOME/.sdkman/bin/sdkman-init.sh"
|
||||||
|
|
||||||
|
# Gradle 8.7 설치
|
||||||
|
sdk install gradle 8.7
|
||||||
|
sdk default gradle 8.7
|
||||||
|
```
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
1. [Gradle 8.7 Binary-only 다운로드](https://gradle.org/releases/)
|
||||||
|
2. `C:\gradle\gradle-8.7` 경로에 압축 해제
|
||||||
|
3. `GRADLE_HOME=C:\gradle\gradle-8.7` 환경변수 등록
|
||||||
|
4. `PATH`에 `%GRADLE_HOME%\bin` 추가
|
||||||
|
|
||||||
|
### 검증
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gradle -v
|
||||||
|
# Gradle 8.7
|
||||||
|
# JVM: 1.8.x
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. (권장) direnv 사용
|
||||||
|
|
||||||
|
저장소 루트의 `.envrc` 가 `JAVA_HOME`, `GRADLE_USER_HOME` 등을 자동 주입합니다.
|
||||||
|
디렉터리 진입만으로 환경이 격리되므로 다른 프로젝트와 JDK가 섞이지 않습니다.
|
||||||
|
|
||||||
|
### 설치
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# macOS
|
||||||
|
brew install direnv
|
||||||
|
|
||||||
|
# Windows (scoop)
|
||||||
|
scoop install direnv
|
||||||
|
```
|
||||||
|
|
||||||
|
### 셸 훅 등록 (한 번만)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# zsh
|
||||||
|
echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc
|
||||||
|
|
||||||
|
# bash
|
||||||
|
echo 'eval "$(direnv hook bash)"' >> ~/.bashrc
|
||||||
|
```
|
||||||
|
|
||||||
|
### 프로젝트에서 허용
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /path/to/eapim-portal
|
||||||
|
direnv allow
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Git 설치
|
||||||
|
|
||||||
|
### macOS
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew install git
|
||||||
|
```
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
[Git for Windows](https://git-scm.com/download/win) 설치. Git Bash가 함께 설치되어 README의 Bash 스니펫을 그대로 사용할 수 있습니다.
|
||||||
|
|
||||||
|
### SSH 키 등록 (사내 Git 서버용)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh-keygen -t ed25519 -C "your.email@djbank.co.kr"
|
||||||
|
cat ~/.ssh/id_ed25519.pub
|
||||||
|
# 출력된 공개키를 사내 Git 서버(192.168.240.178:18081)에 등록
|
||||||
|
```
|
||||||
|
|
||||||
|
### 검증
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git --version
|
||||||
|
ssh -T git@192.168.240.178 -p 18081
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Oracle 19c 접근 정보
|
||||||
|
|
||||||
|
개발 환경에서는 별도 Oracle 설치 없이 사내 개발 DB에 접속합니다.
|
||||||
|
|
||||||
|
- **Host**: `192.168.240.177`
|
||||||
|
- **Port**: `1599`
|
||||||
|
- **Schemas**: `EMSADM` (Portal), `AGWADM` (Gateway)
|
||||||
|
- 상세 계정/패스워드는 사내 비밀번호 관리자에게 문의
|
||||||
|
|
||||||
|
스테이징/운영은 JNDI를 통해 접근합니다 — `jdbc/dsOBP_EMS`, `jdbc/dsOBP_AGW`.
|
||||||
|
|
||||||
|
DB 클라이언트 도구는 자유 선택 (DBeaver, DataGrip, SQL Developer 등).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Node.js & SASS 빌드 환경
|
||||||
|
|
||||||
|
SCSS 파일을 CSS로 컴파일하기 위해 Node.js 환경이 필요합니다.
|
||||||
|
`src/main/resources/static/css/main.css` 는 SASS 컴파일 결과물이므로 **반드시 SCSS 파일을 수정한 뒤 컴파일**해야 합니다.
|
||||||
|
|
||||||
|
### 6.1 Node.js 설치 (LTS 18 이상)
|
||||||
|
|
||||||
|
#### macOS (Homebrew)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew install node
|
||||||
|
```
|
||||||
|
|
||||||
|
#### macOS / Linux (nvm 권장 — 버전 관리 용이)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# nvm 설치
|
||||||
|
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
|
||||||
|
exec $SHELL -l
|
||||||
|
|
||||||
|
# Node.js LTS 설치
|
||||||
|
nvm install --lts
|
||||||
|
nvm use --lts
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Windows
|
||||||
|
|
||||||
|
1. [Node.js LTS 다운로드](https://nodejs.org/en/download) 후 MSI 설치
|
||||||
|
2. 또는 [nvm-windows](https://github.com/coreybutler/nvm-windows/releases) 사용
|
||||||
|
|
||||||
|
#### 검증
|
||||||
|
|
||||||
|
```bash
|
||||||
|
node -v # v18.x 이상
|
||||||
|
npm -v # 9.x 이상
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.2 프로젝트 SASS 의존성 설치
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /path/to/eapim-portal
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
`package.json` 의 `devDependencies.sass` (Dart Sass) 가 `node_modules/` 에 설치됩니다.
|
||||||
|
|
||||||
|
### 6.3 SASS 빌드 명령어
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1회 컴파일 (개발용, 들여쓰기 유지)
|
||||||
|
npm run sass:build
|
||||||
|
|
||||||
|
# 1회 컴파일 (배포용, minified)
|
||||||
|
npm run sass:build:minified
|
||||||
|
|
||||||
|
# 파일 변경 감지 후 자동 컴파일 (개발 중 권장)
|
||||||
|
npm run sass:watch
|
||||||
|
|
||||||
|
# 빌드 + minified 동시 생성
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.4 SASS 컴파일 검증
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ls -lh src/main/resources/static/css/main.css
|
||||||
|
ls -lh src/main/resources/static/css/main.min.css
|
||||||
|
```
|
||||||
|
|
||||||
|
파일이 갱신되었고 브라우저에서 스타일이 정상 적용되면 성공입니다.
|
||||||
|
|
||||||
|
### 6.5 SASS 작업 시 주의사항
|
||||||
|
|
||||||
|
- `src/main/resources/static/css/main.css` **직접 수정 금지** — 재컴파일 시 덮어씌워짐
|
||||||
|
- SCSS 파일은 `src/main/resources/static/sass/` 하위에서만 작성
|
||||||
|
- 새 파일 추가 시 파일명 앞에 언더스코어(`_`) 필수 (`_filename.scss`)
|
||||||
|
- `@import` 대신 `@use` 사용 (Dart Sass 3.0 호환)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. (선택) IDE 설정
|
||||||
|
|
||||||
|
### IntelliJ IDEA
|
||||||
|
|
||||||
|
1. **Lombok 플러그인** 설치 → `Settings → Plugins → Lombok`
|
||||||
|
2. **Annotation Processing 활성화** → `Settings → Build → Compiler → Annotation Processors → Enable annotation processing`
|
||||||
|
3. **Gradle JVM** 설정 → `Settings → Build → Build Tools → Gradle → Gradle JVM` 을 JDK 1.8 (Zulu) 로 지정
|
||||||
|
4. **MapStruct** 는 별도 플러그인 불필요 (annotation processor 만 활성화되어 있으면 됨)
|
||||||
|
|
||||||
|
### VS Code
|
||||||
|
|
||||||
|
- `Extension Pack for Java`
|
||||||
|
- `Lombok Annotations Support`
|
||||||
|
- `Sass` (Syler) — SCSS 문법 하이라이팅
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 최종 체크리스트
|
||||||
|
|
||||||
|
아래 명령이 모두 정상 동작하면 개발환경 준비가 완료된 것입니다.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
java -version # 1.8.x
|
||||||
|
gradle -v # 8.7 / JVM 1.8
|
||||||
|
git --version
|
||||||
|
node -v # v18 이상
|
||||||
|
npm -v
|
||||||
|
direnv version # (선택)
|
||||||
|
```
|
||||||
|
|
||||||
|
이후 [README.md](../README.md) 의 "초기 세팅 가이드" 로 이동해 프로젝트 클론과 의존 모듈 설치를 진행하세요.
|
||||||
Vendored
-91
@@ -1,91 +0,0 @@
|
|||||||
pipeline {
|
|
||||||
// 25.10.01 : 기본 브랜치 staging -> jenkins_with_weblogic 로 변경
|
|
||||||
|
|
||||||
agent { label 'apipod01' }
|
|
||||||
|
|
||||||
triggers {
|
|
||||||
pollSCM('H/5 * * * *')
|
|
||||||
}
|
|
||||||
|
|
||||||
environment {
|
|
||||||
// Java 환경 설정
|
|
||||||
JAVA_HOME = '/App/jenkins/jdks/jdk1.8.0_441'
|
|
||||||
PATH = "${JAVA_HOME}/bin:${env.PATH}"
|
|
||||||
|
|
||||||
// Gradle 환경 설정
|
|
||||||
GRADLE_HOME = '/App/jenkins/gradle-8.7'
|
|
||||||
GRADLE_USER_HOME = '/App/jenkins/gradle-home'
|
|
||||||
// GRADLE_OPTS = '--offline'
|
|
||||||
|
|
||||||
// Git 저장소 정보
|
|
||||||
GIT_SERVER = '192.168.240.178:18081'
|
|
||||||
GIT_CREDENTIALS_ID = 'git-ssh-credentials'
|
|
||||||
|
|
||||||
// 프로젝트 디렉토리 구조
|
|
||||||
PROJECT_HOME = '/Data/jenkins/eapim'
|
|
||||||
|
|
||||||
BRANCH = 'jenkins_with_weblogic'
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
stages {
|
|
||||||
stage('Git pull') {
|
|
||||||
steps {
|
|
||||||
echo "[portal] Git pull from branch: ${BRANCH}"
|
|
||||||
dir("${PROJECT_HOME}/eapim-portal") {
|
|
||||||
git url: "ssh://git@${GIT_SERVER}/eapim/eapim-portal", branch: "${BRANCH}", credentialsId: "${GIT_CREDENTIALS_ID}"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
echo "[online-core-jpa] Git pull from branch: ${BRANCH}"
|
|
||||||
dir("${PROJECT_HOME}/eapim-online/elink-online-core-jpa") {
|
|
||||||
git url: "ssh://git@${GIT_SERVER}/eapim/elink-online-core-jpa", branch: "${BRANCH}", credentialsId: "${GIT_CREDENTIALS_ID}"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
echo "[portal-common] Git pull from branch: ${BRANCH}"
|
|
||||||
dir("${PROJECT_HOME}/elink-portal-common") {
|
|
||||||
git url: "ssh://git@${GIT_SERVER}/eapim/elink-portal-common", branch: "${BRANCH}", credentialsId: "${GIT_CREDENTIALS_ID}"
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "[kjb-safedb] Git pull from branch: ${BRANCH}"
|
|
||||||
dir("${PROJECT_HOME}/kjb-safedb") {
|
|
||||||
git url: "ssh://git@${GIT_SERVER}/eapim/kjb-safedb", branch: "${BRANCH}", credentialsId: "${GIT_CREDENTIALS_ID}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
stage('Build') {
|
|
||||||
steps {
|
|
||||||
tool name: 'Oracle-JDK-1.8', type: 'hudson.model.JDK'
|
|
||||||
// tool name: 'Gradle-8.7', type: 'hudson.tasks.Gradle'
|
|
||||||
|
|
||||||
// echo "[online-core-jpa] Build project"
|
|
||||||
// dir("${PROJECT_HOME}/elink-online-multi/elink-online-core-jpa") {
|
|
||||||
// sh '${GRADLE_HOME}/bin/gradle clean build -x test'
|
|
||||||
// }
|
|
||||||
|
|
||||||
// echo "[portal-common] Build project"
|
|
||||||
// dir("${PROJECT_HOME}/elink-portal-common") {
|
|
||||||
// sh '${GRADLE_HOME}/bin/gradle clean build -x test'
|
|
||||||
// }
|
|
||||||
|
|
||||||
echo "[portal] Build project"
|
|
||||||
dir("${PROJECT_HOME}/eapim-portal") {
|
|
||||||
sh '${GRADLE_HOME}/bin/gradle clean build -x test'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
stage('Archive WAR') {
|
|
||||||
steps {
|
|
||||||
echo "[portal] Archive WAR file"
|
|
||||||
dir("${PROJECT_HOME}/eapim-portal/build/libs") {
|
|
||||||
archiveArtifacts artifacts: '*.war', fingerprint: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
# 광주은행 eAPIM
|
|
||||||
|
|
||||||
## 커스텀 항목
|
|
||||||
### 포탈 Property (EMS 프로퍼티)
|
|
||||||
- `disable_features.user_email_verify' == true
|
|
||||||
이메일 인증 기능 비활성화(회원 가입시 이메일 인증은 한걸로 처리)
|
|
||||||
|
|
||||||
### 디비 접속 방법 Direct -> JNDI 로 변경
|
|
||||||
- 은행 내부 환경에선 모두 JNDI 사용하기 때문에 서버환경에서 동작하는 profile 내 application.yaml 에서 디비 접속 정보 삭제
|
|
||||||
|
|
||||||
## 서버 운영 중 긴급 로깅이 필요할 경우 JVM 파라미터 추가 하여 재기동
|
|
||||||
- DEBUG 레벨 root 로그 / debug.log 로 파일 작성
|
|
||||||
```
|
|
||||||
-Dlogging.config=classpath:logback-debug.xml
|
|
||||||
```
|
|
||||||
|
|
||||||
## 참고자료
|
|
||||||
### 개발용 파라미터
|
|
||||||
```
|
|
||||||
-Dlogging.config=classpath:logback-rinjae.xml
|
|
||||||
-Dinst.Name=devSvr98
|
|
||||||
-Duser.language=en
|
|
||||||
-Duser.country=US
|
|
||||||
-Dkjb_safedb.mode=fake
|
|
||||||
```
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
# 사업자등록번호 중복 체크 구현 작업 계획서
|
|
||||||
|
|
||||||
## 1. 현황 분석
|
|
||||||
|
|
||||||
### 문제점
|
|
||||||
- 법인 등록 시 사업자등록번호(compRegNo) 중복 검증이 없음
|
|
||||||
- `PortalOrgRepository.findByCompRegNo()` 메서드는 존재하나 사용되지 않음
|
|
||||||
- 동일한 사업자등록번호로 여러 법인이 등록될 수 있는 상태
|
|
||||||
|
|
||||||
### 검증 시점
|
|
||||||
1. **실시간 검증**: 사용자가 사업자등록번호 입력 시 `/check-business-number` API 호출
|
|
||||||
2. **등록 시 검증**: 실제 법인 생성 시점 (`registerOrgFromDTOWithFile`)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. 수정 대상 파일
|
|
||||||
|
|
||||||
| 파일 경로 | 수정 내용 |
|
|
||||||
|-----------|-----------|
|
|
||||||
| `src/main/java/.../apps/user/service/PortalOrgService.java` | 사업자등록번호 중복 체크 메서드 추가 |
|
|
||||||
| `src/main/java/.../apps/user/facade/OrgRegisterFacadeImpl.java` | `checkBusinessNumber()` 중복 체크 로직 추가, 등록 전 중복 체크 추가 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. 구현 상세
|
|
||||||
|
|
||||||
### 3.1 PortalOrgService.java
|
|
||||||
|
|
||||||
```java
|
|
||||||
// 추가할 메서드
|
|
||||||
public boolean existsByCompRegNo(String compRegNo) {
|
|
||||||
return portalOrgRepository.findByCompRegNo(compRegNo).isPresent();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.2 OrgRegisterFacadeImpl.java
|
|
||||||
|
|
||||||
#### checkBusinessNumber 메서드 수정
|
|
||||||
- 형식 검증 + 중복 검증 동시 수행
|
|
||||||
- 중복 시 "이미 등록된 사업자등록번호입니다." 메시지 반환
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Override
|
|
||||||
public ResponseEntity<ValidationResponse> checkBusinessNumber(String compRegNo) {
|
|
||||||
// 1. 형식 검증
|
|
||||||
boolean isValidFormat = validationService.isValidBusinessNumber(compRegNo);
|
|
||||||
if (!isValidFormat) {
|
|
||||||
return ResponseEntity.ok(new ValidationResponse(false, "유효하지 않은 사업자 등록번호입니다."));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 중복 검증
|
|
||||||
boolean isDuplicate = portalOrgService.existsByCompRegNo(compRegNo);
|
|
||||||
if (isDuplicate) {
|
|
||||||
return ResponseEntity.ok(new ValidationResponse(false, "이미 등록된 사업자등록번호입니다."));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ResponseEntity.ok(new ValidationResponse(true, "사용 가능한 사업자 등록번호입니다."));
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 법인 생성 메서드들에 중복 체크 추가
|
|
||||||
- `registerNewCorporateUser()`
|
|
||||||
- `convertExistingUserToCorporate()`
|
|
||||||
- `registerNewCorporateUserWithExistingData()`
|
|
||||||
|
|
||||||
각 메서드에서 `portalOrgService.registerOrgFromDTOWithFile()` 호출 전 중복 체크 수행
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. 검증 흐름
|
|
||||||
|
|
||||||
```
|
|
||||||
[사용자 입력]
|
|
||||||
↓
|
|
||||||
[실시간 검증] /check-business-number API
|
|
||||||
├── 형식 검증 (10자리 숫자)
|
|
||||||
└── 중복 검증 (DB 조회)
|
|
||||||
↓
|
|
||||||
[등록 요청]
|
|
||||||
↓
|
|
||||||
[등록 시 검증] registerOrgFromDTOWithFile 호출 전
|
|
||||||
└── 중복 체크 (이중 방어)
|
|
||||||
↓
|
|
||||||
[법인 생성]
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. 기존 중복 데이터 처리
|
|
||||||
|
|
||||||
- 기존에 중복 등록된 데이터는 그대로 유지
|
|
||||||
- 신규 등록 시에만 중복 체크 적용
|
|
||||||
- 필요시 관리자 화면에서 중복 데이터 조회/정리 기능 별도 개발 가능
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6. 테스트 시나리오
|
|
||||||
|
|
||||||
| 시나리오 | 예상 결과 |
|
|
||||||
|----------|-----------|
|
|
||||||
| 형식이 잘못된 사업자등록번호 입력 | "유효하지 않은 사업자 등록번호입니다." |
|
|
||||||
| 이미 등록된 사업자등록번호 입력 | "이미 등록된 사업자등록번호입니다." |
|
|
||||||
| 사용 가능한 사업자등록번호 입력 | "사용 가능한 사업자 등록번호입니다." |
|
|
||||||
| 중복된 번호로 법인 등록 시도 | 등록 실패, 에러 메시지 표시 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7. 작업 완료
|
|
||||||
|
|
||||||
- [x] PortalOrgService에 existsByCompRegNo 메서드 추가
|
|
||||||
- [x] OrgRegisterFacadeImpl.checkBusinessNumber 수정
|
|
||||||
- [x] 법인 등록 메서드들에 중복 체크 로직 추가
|
|
||||||
- [x] 빌드 검증 완료
|
|
||||||
@@ -1,165 +0,0 @@
|
|||||||
# 네비게이션 바 디자인 Survey 기능 가이드
|
|
||||||
|
|
||||||
## 개요
|
|
||||||
|
|
||||||
직원 대상 네비게이션 바 디자인 선호도 조사를 위한 UI 기능입니다.
|
|
||||||
사용자가 A, B, C 등의 버튼을 클릭하면 실시간으로 네비게이션 바 디자인이 변경됩니다.
|
|
||||||
|
|
||||||
## 기능 활성화/비활성화
|
|
||||||
|
|
||||||
### PortalProperty 설정
|
|
||||||
|
|
||||||
DB의 `ptl_property` 테이블에서 `ui.design-survey` 값을 설정합니다.
|
|
||||||
|
|
||||||
```sql
|
|
||||||
-- 활성화
|
|
||||||
UPDATE ptl_property
|
|
||||||
SET property_value = 'true'
|
|
||||||
WHERE property_group_name = 'Portal' AND property_name = 'ui.design-survey';
|
|
||||||
|
|
||||||
-- 비활성화
|
|
||||||
UPDATE ptl_property
|
|
||||||
SET property_value = 'false'
|
|
||||||
WHERE property_group_name = 'Portal' AND property_name = 'ui.design-survey';
|
|
||||||
```
|
|
||||||
|
|
||||||
> 최초 페이지 로드 시 속성이 자동 생성됩니다 (기본값: `false`)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 디자인 옵션 추가/수정 방법
|
|
||||||
|
|
||||||
### 파일 위치
|
|
||||||
`src/main/resources/templates/views/fragment/kjbank/header_container.html`
|
|
||||||
|
|
||||||
### DESIGN_OPTIONS 배열
|
|
||||||
|
|
||||||
디자인 옵션은 JavaScript의 `DESIGN_OPTIONS` 배열에서 관리됩니다:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const DESIGN_OPTIONS = [
|
|
||||||
{
|
|
||||||
id: 'A', // 고유 식별자 (필수)
|
|
||||||
label: 'A (현재)', // 버튼에 표시될 텍스트 (필수)
|
|
||||||
isDefault: true, // 기본 선택 옵션 (선택, 하나만 true)
|
|
||||||
styles: {} // 적용할 CSS 스타일 (필수)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'B',
|
|
||||||
label: 'B',
|
|
||||||
styles: {
|
|
||||||
'.logo-text': { 'font-size': '18px' },
|
|
||||||
'.nav-link': { 'margin': '0 20px' }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'C',
|
|
||||||
label: 'C',
|
|
||||||
styles: {
|
|
||||||
'.nav-link': { 'margin': '0 20px', 'font-weight': 'bold' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
```
|
|
||||||
|
|
||||||
### 새 디자인 옵션 추가 예시
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// D 옵션 추가
|
|
||||||
{
|
|
||||||
id: 'D',
|
|
||||||
label: 'D',
|
|
||||||
styles: {
|
|
||||||
'.logo-text': {
|
|
||||||
'font-size': '16px',
|
|
||||||
'color': '#333333'
|
|
||||||
},
|
|
||||||
'.nav-link': {
|
|
||||||
'padding': '10px 24px',
|
|
||||||
'font-weight': '600'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### styles 객체 구조
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
styles: {
|
|
||||||
'CSS 셀렉터': {
|
|
||||||
'CSS 속성': '값',
|
|
||||||
'CSS 속성2': '값2'
|
|
||||||
},
|
|
||||||
'다른 셀렉터': {
|
|
||||||
'CSS 속성': '값'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 자주 사용되는 CSS 셀렉터
|
|
||||||
|
|
||||||
| 셀렉터 | 설명 |
|
|
||||||
|--------|------|
|
|
||||||
| `.logo-text` | 로고 텍스트 "API Portal" |
|
|
||||||
| `.nav-link` | 네비게이션 메뉴 링크 |
|
|
||||||
| `.nav-menu` | 네비게이션 메뉴 컨테이너 |
|
|
||||||
| `.header-content` | 헤더 콘텐츠 영역 |
|
|
||||||
| `.global-header` | 전체 헤더 |
|
|
||||||
| `.logo-wrapper` | 로고 래퍼 (이미지 + 텍스트) |
|
|
||||||
|
|
||||||
## 자주 사용되는 CSS 속성
|
|
||||||
|
|
||||||
| 속성 | 예시 값 | 설명 |
|
|
||||||
|------|---------|------|
|
|
||||||
| `font-size` | `18px`, `1.2rem` | 글자 크기 |
|
|
||||||
| `font-weight` | `400`, `500`, `600`, `bold` | 글자 두께 |
|
|
||||||
| `margin` | `0 20px`, `10px 15px` | 바깥 여백 |
|
|
||||||
| `padding` | `8px 16px` | 안쪽 여백 |
|
|
||||||
| `color` | `#333333`, `#0049b4` | 글자 색상 |
|
|
||||||
| `background` | `#ffffff`, `#f5f5f5` | 배경 색상 |
|
|
||||||
| `gap` | `12px`, `20px` | flex 아이템 간격 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 사용자 선택 저장
|
|
||||||
|
|
||||||
사용자의 디자인 선택은 브라우저의 `localStorage`에 저장됩니다.
|
|
||||||
|
|
||||||
- Key: `design-survey-selection`
|
|
||||||
- Value: 선택한 디자인 ID (예: `A`, `B`, `C`)
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// 저장된 선택 확인 (개발자 도구 콘솔)
|
|
||||||
localStorage.getItem('design-survey-selection')
|
|
||||||
|
|
||||||
// 선택 초기화
|
|
||||||
localStorage.removeItem('design-survey-selection')
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 관련 파일
|
|
||||||
|
|
||||||
| 파일 | 역할 |
|
|
||||||
|------|------|
|
|
||||||
| `GlobalControllerAdvice.java` | `designSurveyEnabled` ModelAttribute 제공 |
|
|
||||||
| `header_container.html` | Survey 바 HTML 및 DESIGN_OPTIONS 설정 |
|
|
||||||
| `_header.scss` | Survey 바 스타일 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 주의사항
|
|
||||||
|
|
||||||
1. **디자인 옵션 ID는 고유해야 합니다** - 중복 ID 사용 시 오동작
|
|
||||||
2. **isDefault는 하나의 옵션에만 설정** - 여러 개 설정 시 첫 번째만 적용
|
|
||||||
3. **CSS 속성명은 kebab-case 사용** - `fontSize` (X) → `font-size` (O)
|
|
||||||
4. **스타일 적용 시 `!important` 자동 추가** - 기존 스타일 덮어씀
|
|
||||||
5. **Survey 기능 종료 후** - `ui.design-survey`를 `false`로 설정하여 비활성화
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 문의
|
|
||||||
|
|
||||||
기능 관련 문의는 개발팀에 연락해주세요.
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,105 +0,0 @@
|
|||||||
flowchart TD
|
|
||||||
Start([법인 관리자가 사용자 초대]) --> GenerateToken[8글자 토큰 생성<br/>예: K7MNPQ2R<br/>UserInvitation 저장<br/>상태: PENDING]
|
|
||||||
|
|
||||||
GenerateToken --> SendEmail[이메일 발송<br/>- 링크 포함<br/>- 8글자 토큰 표시]
|
|
||||||
|
|
||||||
SendEmail --> UserType{사용자 유형}
|
|
||||||
|
|
||||||
%% ========================================
|
|
||||||
%% 신규 회원 플로우
|
|
||||||
%% ========================================
|
|
||||||
UserType -->|신규 회원<br/>미가입자| NewUserPath{초대 확인 방법}
|
|
||||||
|
|
||||||
NewUserPath -->|이메일 링크| EmailLink1[이메일 링크 클릭<br/>/signup/portalUser?invitation=CODE]
|
|
||||||
NewUserPath -->|일반 회원가입| DirectSignup[일반 회원가입 진행<br/>ROLE_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 -->|이메일 링크<br/>비로그인 상태| EmailLink2[이메일 링크 클릭<br/>/signup/decision?invitation=CODE]
|
|
||||||
ExistingUserPath -->|이메일 링크<br/>로그인 상태| EmailLinkLoggedIn[이메일 링크 클릭<br/>/signup/decision?invitation=CODE]
|
|
||||||
ExistingUserPath -->|직접 로그인| DirectLogin[로그인 페이지에서 로그인]
|
|
||||||
|
|
||||||
%% 비로그인 상태에서 이메일 링크 클릭
|
|
||||||
EmailLink2 --> DecisionPagePublic[초대 수락 페이지<br/>비로그인 상태]
|
|
||||||
DecisionPagePublic --> RedirectLogin2[로그인 유도]
|
|
||||||
RedirectLogin2 --> Login2[로그인]
|
|
||||||
Login2 --> AfterLogin2[로그인 성공]
|
|
||||||
|
|
||||||
%% 로그인 상태에서 이메일 링크 클릭 → 바로 수락 페이지
|
|
||||||
EmailLinkLoggedIn --> DecisionPageDirect[초대 수락 페이지<br/>/signup/decision_process<br/>초대 수락]
|
|
||||||
DecisionPageDirect --> UserDecision
|
|
||||||
|
|
||||||
%% 직접 로그인
|
|
||||||
DirectLogin --> Login3[로그인]
|
|
||||||
Login3 --> AfterLogin3[로그인 성공]
|
|
||||||
|
|
||||||
%% ========================================
|
|
||||||
%% 로그인 후 초대 확인 (PortalAuthenticationSuccessHandler)
|
|
||||||
%% ========================================
|
|
||||||
AfterLogin2 --> CheckInvitation[PortalAuthenticationSuccessHandler<br/>PENDING 초대 확인<br/>findFirstByInvitationEmailAndStatus]
|
|
||||||
AfterLogin3 --> CheckInvitation
|
|
||||||
|
|
||||||
CheckInvitation --> HasInvitation{PENDING 초대 존재?}
|
|
||||||
|
|
||||||
HasInvitation -->|없음| NormalHome[메인 페이지 이동]
|
|
||||||
HasInvitation -->|있음| SaveToSession[세션에 초대 정보 저장<br/>pendingInvitation=true<br/>pendingInvitationToken<br/>pendingInvitationOrgName]
|
|
||||||
|
|
||||||
SaveToSession --> RedirectHome[메인 페이지로 이동]
|
|
||||||
|
|
||||||
%% ========================================
|
|
||||||
%% 메인 페이지 팝업 (index.html)
|
|
||||||
%% ========================================
|
|
||||||
RedirectHome --> ShowPopup[팝업 표시<br/>OOO에서 초대가 도착했습니다<br/>초대를 확인하시겠습니까?]
|
|
||||||
|
|
||||||
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([초대 거절 완료<br/>다음 로그인 시 팝업 안 뜸])
|
|
||||||
|
|
||||||
%% ========================================
|
|
||||||
%% 스타일링
|
|
||||||
%% ========================================
|
|
||||||
style Start fill:#e1f5e1
|
|
||||||
style NewUserEnd fill:#c8e6c9
|
|
||||||
style ExistingUserEnd fill:#c8e6c9
|
|
||||||
style RejectEnd fill:#fff9c4
|
|
||||||
style NormalHome fill:#e3f2fd
|
|
||||||
|
|
||||||
style GenerateToken fill:#bbdefb
|
|
||||||
style AcceptProcess fill:#c5cae9
|
|
||||||
style RejectProcess fill:#ffecb3
|
|
||||||
|
|
||||||
style CheckInvitation fill:#ffe0b2
|
|
||||||
style SaveToSession fill:#ffe0b2
|
|
||||||
style ShowPopup fill:#f8bbd0
|
|
||||||
style PopupChoice fill:#f8bbd0
|
|
||||||
|
|
||||||
style StayHome fill:#e1bee7
|
|
||||||
style NextLogin fill:#e1bee7
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
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 AuthHandler as PortalAuthenticationSuccessHandler
|
|
||||||
participant IndexController
|
|
||||||
participant MainPage as 메인 페이지 (index.html)
|
|
||||||
participant UserRegisterController
|
|
||||||
participant UserRegisterFacade
|
|
||||||
participant PortalUserRepo as PortalUser Repository
|
|
||||||
participant PortalOrgRepo as PortalOrg Repository
|
|
||||||
|
|
||||||
%% ========================================
|
|
||||||
%% 1. 초대 발송
|
|
||||||
%% ========================================
|
|
||||||
법인관리자->>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->>초대받은사용자: 초대 이메일 수신
|
|
||||||
|
|
||||||
%% ========================================
|
|
||||||
%% 2-A. 로그인 상태에서 이메일 링크 클릭 (바로 수락 페이지)
|
|
||||||
%% ========================================
|
|
||||||
alt 로그인 상태에서 이메일 링크 클릭
|
|
||||||
초대받은사용자->>Portal: 이메일 링크 클릭<br/>/signup/decision?invitation=TOKEN
|
|
||||||
Portal->>UserRegisterController: showDecisionPage(invitationToken)
|
|
||||||
UserRegisterController->>UserInvitationRepo: findByToken(decodedToken)
|
|
||||||
UserRegisterController-->>Portal: 약관 동의 페이지
|
|
||||||
Portal-->>초대받은사용자: 초대 수락/거절 화면<br/>(바로 표시, 팝업 없음)
|
|
||||||
Note over 초대받은사용자: 6. 초대 수락/거절 처리로 이동
|
|
||||||
end
|
|
||||||
|
|
||||||
%% ========================================
|
|
||||||
%% 2-B. 로그인 (기존 회원 또는 신규 가입 후)
|
|
||||||
%% ========================================
|
|
||||||
alt 기존 회원 (비로그인 상태)
|
|
||||||
초대받은사용자->>Portal: 로그인
|
|
||||||
else 비회원이 일반 회원가입 후
|
|
||||||
초대받은사용자->>Portal: 회원가입 (ROLE_USER)
|
|
||||||
초대받은사용자->>Portal: 로그인
|
|
||||||
end
|
|
||||||
|
|
||||||
%% ========================================
|
|
||||||
%% 3. 로그인 성공 처리 (AuthenticationSuccessHandler)
|
|
||||||
%% ========================================
|
|
||||||
Portal->>AuthHandler: onAuthenticationSuccess()
|
|
||||||
AuthHandler->>AuthHandler: 이메일 인증, 휴면계정,<br/>비밀번호 만료 체크
|
|
||||||
|
|
||||||
AuthHandler->>UserInvitationRepo: findFirstByInvitationEmailAndStatus<br/>(loginId, PENDING)
|
|
||||||
|
|
||||||
alt PENDING 초대 없음
|
|
||||||
AuthHandler->>Portal: redirect to /
|
|
||||||
Portal-->>초대받은사용자: 메인 페이지 (팝업 없음)
|
|
||||||
else PENDING 초대 있음 & 만료 안됨
|
|
||||||
AuthHandler->>PortalOrgRepo: findById(invitation.orgId)
|
|
||||||
PortalOrgRepo-->>AuthHandler: PortalOrg (기관명)
|
|
||||||
AuthHandler->>AuthHandler: session.setAttribute<br/>("pendingInvitation", true)<br/>("pendingInvitationToken", token)<br/>("pendingInvitationOrgName", orgName)
|
|
||||||
AuthHandler->>Portal: redirect to /
|
|
||||||
end
|
|
||||||
|
|
||||||
%% ========================================
|
|
||||||
%% 4. 메인 페이지 팝업 표시
|
|
||||||
%% ========================================
|
|
||||||
Portal->>IndexController: GET /
|
|
||||||
IndexController->>MainPage: render index.html
|
|
||||||
|
|
||||||
MainPage->>MainPage: 세션에서 pendingInvitation 확인
|
|
||||||
|
|
||||||
alt pendingInvitation == true
|
|
||||||
MainPage-->>초대받은사용자: 팝업 표시<br/>"[기관명]에서 초대가 도착했습니다.<br/>초대를 확인하시겠습니까?"
|
|
||||||
end
|
|
||||||
|
|
||||||
%% ========================================
|
|
||||||
%% 5. 사용자 팝업 선택
|
|
||||||
%% ========================================
|
|
||||||
alt 팝업에서 "확인" 클릭
|
|
||||||
초대받은사용자->>Portal: /signup/decision?invitation=TOKEN
|
|
||||||
Portal->>UserRegisterController: showDecisionPage(invitationToken)
|
|
||||||
UserRegisterController->>UserInvitationRepo: findByToken(decodedToken)
|
|
||||||
UserRegisterController-->>Portal: 약관 동의 페이지
|
|
||||||
Portal-->>초대받은사용자: 초대 수락/거절 화면
|
|
||||||
else 팝업에서 "취소" 클릭
|
|
||||||
Note over 초대받은사용자,MainPage: 메인 페이지 유지<br/>다음 로그인 시 팝업 재표시
|
|
||||||
end
|
|
||||||
|
|
||||||
%% ========================================
|
|
||||||
%% 6. 초대 수락/거절 처리
|
|
||||||
%% ========================================
|
|
||||||
초대받은사용자->>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/>로그아웃 후 재로그인 안내
|
|
||||||
Note over 초대받은사용자: 다음 로그인 시<br/>PENDING 초대 없음 → 팝업 안 뜸
|
|
||||||
else 거절
|
|
||||||
UserRegisterFacade->>UserInvitationRepo: save(invitation)<br/>status: REJECTED<br/>completeDate: now()
|
|
||||||
UserRegisterFacade-->>Portal: 거절 처리 완료
|
|
||||||
Portal-->>초대받은사용자: 거절 완료 메시지
|
|
||||||
Note over 초대받은사용자: 다음 로그인 시<br/>REJECTED 상태 → 팝업 안 뜸
|
|
||||||
end
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
stateDiagram-v2
|
|
||||||
[*] --> 초대생성: 법인관리자가 초대 시작
|
|
||||||
|
|
||||||
초대생성 --> PENDING: 토큰 생성 및 저장
|
|
||||||
|
|
||||||
PENDING --> 이메일발송: 초대 이메일 발송
|
|
||||||
|
|
||||||
state 로그인후팝업 {
|
|
||||||
이메일발송 --> 로그인: 사용자 로그인
|
|
||||||
로그인 --> 초대확인: AuthSuccessHandler
|
|
||||||
초대확인 --> 세션저장: 세션에 초대 정보 저장
|
|
||||||
세션저장 --> 팝업표시: 메인 페이지 팝업
|
|
||||||
팝업표시 --> 팝업확인: 확인 클릭
|
|
||||||
팝업표시 --> 팝업취소: 취소 클릭
|
|
||||||
팝업취소 --> 로그인: 다음 로그인 시 재표시
|
|
||||||
}
|
|
||||||
|
|
||||||
팝업확인 --> 초대수락: 수락 페이지 이동
|
|
||||||
|
|
||||||
초대수락 --> COMPLETED: 수락
|
|
||||||
초대수락 --> REJECTED: 거절
|
|
||||||
|
|
||||||
COMPLETED --> [*]: 초대 완료
|
|
||||||
REJECTED --> [*]: 초대 거절
|
|
||||||
PENDING --> CANCELED: 관리자 취소
|
|
||||||
PENDING --> EXPIRED: 만료일 경과
|
|
||||||
CANCELED --> [*]: 초대 취소
|
|
||||||
EXPIRED --> [*]: 초대 만료
|
|
||||||
|
|
||||||
note right of PENDING
|
|
||||||
PENDING 상태일 때만
|
|
||||||
로그인 시 팝업 표시
|
|
||||||
end note
|
|
||||||
|
|
||||||
note right of REJECTED
|
|
||||||
REJECTED 상태가 되면
|
|
||||||
더 이상 팝업 표시 안 함
|
|
||||||
end note
|
|
||||||
|
|
||||||
note right of COMPLETED
|
|
||||||
COMPLETED 상태가 되면
|
|
||||||
더 이상 팝업 표시 안 함
|
|
||||||
ROLE_CORP_USER로 전환됨
|
|
||||||
end note
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.7 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 574 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Generated
+84
-466
@@ -1,33 +1,30 @@
|
|||||||
{
|
{
|
||||||
"name": "eapim-portal",
|
"name": "eapim-portal",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "eapim-portal",
|
"name": "eapim-portal",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
|
||||||
"playwright": "^1.57.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"sass": "^1.69.5"
|
"sass": "^1.69.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher": {
|
"node_modules/@parcel/watcher": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz",
|
||||||
"integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==",
|
"integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"detect-libc": "^1.0.3",
|
"detect-libc": "^2.0.3",
|
||||||
"is-glob": "^4.0.3",
|
"is-glob": "^4.0.3",
|
||||||
"micromatch": "^4.0.5",
|
"node-addon-api": "^7.0.0",
|
||||||
"node-addon-api": "^7.0.0"
|
"picomatch": "^4.0.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10.0.0"
|
"node": ">= 10.0.0"
|
||||||
@@ -37,25 +34,25 @@
|
|||||||
"url": "https://opencollective.com/parcel"
|
"url": "https://opencollective.com/parcel"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@parcel/watcher-android-arm64": "2.5.1",
|
"@parcel/watcher-android-arm64": "2.5.6",
|
||||||
"@parcel/watcher-darwin-arm64": "2.5.1",
|
"@parcel/watcher-darwin-arm64": "2.5.6",
|
||||||
"@parcel/watcher-darwin-x64": "2.5.1",
|
"@parcel/watcher-darwin-x64": "2.5.6",
|
||||||
"@parcel/watcher-freebsd-x64": "2.5.1",
|
"@parcel/watcher-freebsd-x64": "2.5.6",
|
||||||
"@parcel/watcher-linux-arm-glibc": "2.5.1",
|
"@parcel/watcher-linux-arm-glibc": "2.5.6",
|
||||||
"@parcel/watcher-linux-arm-musl": "2.5.1",
|
"@parcel/watcher-linux-arm-musl": "2.5.6",
|
||||||
"@parcel/watcher-linux-arm64-glibc": "2.5.1",
|
"@parcel/watcher-linux-arm64-glibc": "2.5.6",
|
||||||
"@parcel/watcher-linux-arm64-musl": "2.5.1",
|
"@parcel/watcher-linux-arm64-musl": "2.5.6",
|
||||||
"@parcel/watcher-linux-x64-glibc": "2.5.1",
|
"@parcel/watcher-linux-x64-glibc": "2.5.6",
|
||||||
"@parcel/watcher-linux-x64-musl": "2.5.1",
|
"@parcel/watcher-linux-x64-musl": "2.5.6",
|
||||||
"@parcel/watcher-win32-arm64": "2.5.1",
|
"@parcel/watcher-win32-arm64": "2.5.6",
|
||||||
"@parcel/watcher-win32-ia32": "2.5.1",
|
"@parcel/watcher-win32-ia32": "2.5.6",
|
||||||
"@parcel/watcher-win32-x64": "2.5.1"
|
"@parcel/watcher-win32-x64": "2.5.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-android-arm64": {
|
"node_modules/@parcel/watcher-android-arm64": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz",
|
||||||
"integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==",
|
"integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -74,9 +71,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-darwin-arm64": {
|
"node_modules/@parcel/watcher-darwin-arm64": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz",
|
||||||
"integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==",
|
"integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -95,9 +92,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-darwin-x64": {
|
"node_modules/@parcel/watcher-darwin-x64": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz",
|
||||||
"integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==",
|
"integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -116,9 +113,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-freebsd-x64": {
|
"node_modules/@parcel/watcher-freebsd-x64": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz",
|
||||||
"integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==",
|
"integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -137,9 +134,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-linux-arm-glibc": {
|
"node_modules/@parcel/watcher-linux-arm-glibc": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz",
|
||||||
"integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==",
|
"integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -158,9 +155,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-linux-arm-musl": {
|
"node_modules/@parcel/watcher-linux-arm-musl": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz",
|
||||||
"integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==",
|
"integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -179,9 +176,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-linux-arm64-glibc": {
|
"node_modules/@parcel/watcher-linux-arm64-glibc": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz",
|
||||||
"integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==",
|
"integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -200,9 +197,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-linux-arm64-musl": {
|
"node_modules/@parcel/watcher-linux-arm64-musl": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz",
|
||||||
"integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==",
|
"integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -221,9 +218,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-linux-x64-glibc": {
|
"node_modules/@parcel/watcher-linux-x64-glibc": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz",
|
||||||
"integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==",
|
"integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -242,9 +239,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-linux-x64-musl": {
|
"node_modules/@parcel/watcher-linux-x64-musl": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz",
|
||||||
"integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==",
|
"integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -263,9 +260,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-win32-arm64": {
|
"node_modules/@parcel/watcher-win32-arm64": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz",
|
||||||
"integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==",
|
"integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -284,9 +281,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-win32-ia32": {
|
"node_modules/@parcel/watcher-win32-ia32": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz",
|
||||||
"integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==",
|
"integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@@ -305,9 +302,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-win32-x64": {
|
"node_modules/@parcel/watcher-win32-x64": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz",
|
||||||
"integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==",
|
"integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -325,82 +322,37 @@
|
|||||||
"url": "https://opencollective.com/parcel"
|
"url": "https://opencollective.com/parcel"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/braces": {
|
|
||||||
"version": "3.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
|
||||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"fill-range": "^7.1.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/chokidar": {
|
"node_modules/chokidar": {
|
||||||
"version": "4.0.3",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz",
|
||||||
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
|
"integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"readdirp": "^4.0.1"
|
"readdirp": "^5.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 14.16.0"
|
"node": ">= 20.19.0"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://paulmillr.com/funding/"
|
"url": "https://paulmillr.com/funding/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/detect-libc": {
|
"node_modules/detect-libc": {
|
||||||
"version": "1.0.3",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
||||||
"integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
|
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"bin": {
|
|
||||||
"detect-libc": "bin/detect-libc.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/fill-range": {
|
|
||||||
"version": "7.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
|
||||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"to-regex-range": "^5.0.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fsevents": {
|
|
||||||
"version": "2.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
|
||||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
|
||||||
"hasInstallScript": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/immutable": {
|
"node_modules/immutable": {
|
||||||
"version": "5.1.4",
|
"version": "5.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz",
|
||||||
"integrity": "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==",
|
"integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
@@ -429,32 +381,6 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/is-number": {
|
|
||||||
"version": "7.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
|
||||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.12.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/micromatch": {
|
|
||||||
"version": "4.0.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
|
||||||
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"braces": "^3.0.3",
|
|
||||||
"picomatch": "^2.3.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/node-addon-api": {
|
"node_modules/node-addon-api": {
|
||||||
"version": "7.1.1",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
|
||||||
@@ -464,57 +390,27 @@
|
|||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"node_modules/picomatch": {
|
"node_modules/picomatch": {
|
||||||
"version": "2.3.1",
|
"version": "4.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
|
||||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.6"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/playwright": {
|
|
||||||
"version": "1.57.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.57.0.tgz",
|
|
||||||
"integrity": "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"playwright-core": "1.57.0"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"playwright": "cli.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
},
|
|
||||||
"optionalDependencies": {
|
|
||||||
"fsevents": "2.3.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/playwright-core": {
|
|
||||||
"version": "1.57.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.57.0.tgz",
|
|
||||||
"integrity": "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"bin": {
|
|
||||||
"playwright-core": "cli.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/readdirp": {
|
"node_modules/readdirp": {
|
||||||
"version": "4.1.2",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz",
|
||||||
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
|
"integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 14.18.0"
|
"node": ">= 20.19.0"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@@ -522,21 +418,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/sass": {
|
"node_modules/sass": {
|
||||||
"version": "1.97.1",
|
"version": "1.100.0",
|
||||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.97.1.tgz",
|
"resolved": "https://registry.npmjs.org/sass/-/sass-1.100.0.tgz",
|
||||||
"integrity": "sha512-uf6HoO8fy6ClsrShvMgaKUn14f2EHQLQRtpsZZLeU/Mv0Q1K5P0+x2uvH6Cub39TVVbWNSrraUhDAoFph6vh0A==",
|
"integrity": "sha512-B5j0rYMlinhhOo9tjQebMVVn0TfyXAF+wB3b2ggZUuJ/is/Y+7+JGjirAMxHZ9Z3hIP98NPfamlAkBHa1lAaXQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chokidar": "^4.0.0",
|
"chokidar": "^5.0.0",
|
||||||
"immutable": "^5.0.2",
|
"immutable": "^5.1.5",
|
||||||
"source-map-js": ">=0.6.2 <2.0.0"
|
"source-map-js": ">=0.6.2 <2.0.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"sass": "sass.js"
|
"sass": "sass.js"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=20.19.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@parcel/watcher": "^2.4.1"
|
"@parcel/watcher": "^2.4.1"
|
||||||
@@ -551,284 +447,6 @@
|
|||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"node_modules/to-regex-range": {
|
|
||||||
"version": "5.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
|
||||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"is-number": "^7.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@parcel/watcher": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"@parcel/watcher-android-arm64": "2.5.1",
|
|
||||||
"@parcel/watcher-darwin-arm64": "2.5.1",
|
|
||||||
"@parcel/watcher-darwin-x64": "2.5.1",
|
|
||||||
"@parcel/watcher-freebsd-x64": "2.5.1",
|
|
||||||
"@parcel/watcher-linux-arm-glibc": "2.5.1",
|
|
||||||
"@parcel/watcher-linux-arm-musl": "2.5.1",
|
|
||||||
"@parcel/watcher-linux-arm64-glibc": "2.5.1",
|
|
||||||
"@parcel/watcher-linux-arm64-musl": "2.5.1",
|
|
||||||
"@parcel/watcher-linux-x64-glibc": "2.5.1",
|
|
||||||
"@parcel/watcher-linux-x64-musl": "2.5.1",
|
|
||||||
"@parcel/watcher-win32-arm64": "2.5.1",
|
|
||||||
"@parcel/watcher-win32-ia32": "2.5.1",
|
|
||||||
"@parcel/watcher-win32-x64": "2.5.1",
|
|
||||||
"detect-libc": "^1.0.3",
|
|
||||||
"is-glob": "^4.0.3",
|
|
||||||
"micromatch": "^4.0.5",
|
|
||||||
"node-addon-api": "^7.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@parcel/watcher-android-arm64": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@parcel/watcher-darwin-arm64": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@parcel/watcher-darwin-x64": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@parcel/watcher-freebsd-x64": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@parcel/watcher-linux-arm-glibc": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@parcel/watcher-linux-arm-musl": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@parcel/watcher-linux-arm64-glibc": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@parcel/watcher-linux-arm64-musl": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@parcel/watcher-linux-x64-glibc": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@parcel/watcher-linux-x64-musl": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@parcel/watcher-win32-arm64": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@parcel/watcher-win32-ia32": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@parcel/watcher-win32-x64": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"braces": {
|
|
||||||
"version": "3.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
|
||||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"fill-range": "^7.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"chokidar": {
|
|
||||||
"version": "4.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
|
|
||||||
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"readdirp": "^4.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"detect-libc": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"fill-range": {
|
|
||||||
"version": "7.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
|
||||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"to-regex-range": "^5.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"fsevents": {
|
|
||||||
"version": "2.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
|
||||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"immutable": {
|
|
||||||
"version": "5.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz",
|
|
||||||
"integrity": "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"is-extglob": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
|
||||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"is-glob": {
|
|
||||||
"version": "4.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
|
||||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"is-extglob": "^2.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"is-number": {
|
|
||||||
"version": "7.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
|
||||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"micromatch": {
|
|
||||||
"version": "4.0.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
|
||||||
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"braces": "^3.0.3",
|
|
||||||
"picomatch": "^2.3.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node-addon-api": {
|
|
||||||
"version": "7.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
|
|
||||||
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"picomatch": {
|
|
||||||
"version": "2.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
|
||||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"playwright": {
|
|
||||||
"version": "1.57.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.57.0.tgz",
|
|
||||||
"integrity": "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==",
|
|
||||||
"requires": {
|
|
||||||
"fsevents": "2.3.2",
|
|
||||||
"playwright-core": "1.57.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"playwright-core": {
|
|
||||||
"version": "1.57.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.57.0.tgz",
|
|
||||||
"integrity": "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ=="
|
|
||||||
},
|
|
||||||
"readdirp": {
|
|
||||||
"version": "4.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
|
||||||
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"sass": {
|
|
||||||
"version": "1.97.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.97.1.tgz",
|
|
||||||
"integrity": "sha512-uf6HoO8fy6ClsrShvMgaKUn14f2EHQLQRtpsZZLeU/Mv0Q1K5P0+x2uvH6Cub39TVVbWNSrraUhDAoFph6vh0A==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"@parcel/watcher": "^2.4.1",
|
|
||||||
"chokidar": "^4.0.0",
|
|
||||||
"immutable": "^5.0.2",
|
|
||||||
"source-map-js": ">=0.6.2 <2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"source-map-js": {
|
|
||||||
"version": "1.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
|
||||||
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"to-regex-range": {
|
|
||||||
"version": "5.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
|
||||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"is-number": "^7.0.0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-4
@@ -13,8 +13,5 @@
|
|||||||
"sass": "^1.69.5"
|
"sass": "^1.69.5"
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC"
|
||||||
"dependencies": {
|
|
||||||
"playwright": "^1.57.0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package com.eactive.apim.portal.apps.user.dto;
|
|||||||
import com.eactive.apim.portal.common.validator.AuthNumberMatch;
|
import com.eactive.apim.portal.common.validator.AuthNumberMatch;
|
||||||
import com.eactive.apim.portal.common.validator.CellPhone;
|
import com.eactive.apim.portal.common.validator.CellPhone;
|
||||||
import com.eactive.apim.portal.common.validator.PasswordMatch;
|
import com.eactive.apim.portal.common.validator.PasswordMatch;
|
||||||
import com.eactive.apim.portal.common.validator.PasswordRuleForKjbank;
|
import com.eactive.apim.portal.common.validator.PasswordRuleForDjbank;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.hibernate.validator.constraints.Length;
|
import org.hibernate.validator.constraints.Length;
|
||||||
import org.hibernate.validator.constraints.NotEmpty;
|
import org.hibernate.validator.constraints.NotEmpty;
|
||||||
@@ -12,7 +12,7 @@ import org.hibernate.validator.constraints.NotEmpty;
|
|||||||
@AuthNumberMatch(recipient = "loginId", authField = "authNumber")
|
@AuthNumberMatch(recipient = "loginId", authField = "authNumber")
|
||||||
@PasswordMatch(input = "password", confirm = "password2")
|
@PasswordMatch(input = "password", confirm = "password2")
|
||||||
@Data
|
@Data
|
||||||
@PasswordRuleForKjbank(password = "password", loginId = "loginId", mobile = "mobileNumber")
|
@PasswordRuleForDjbank(password = "password", loginId = "loginId", mobile = "mobileNumber")
|
||||||
public class PortalUserRegistrationDTO {
|
public class PortalUserRegistrationDTO {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.eactive.apim.portal.apps.user.dto;
|
package com.eactive.apim.portal.apps.user.dto;
|
||||||
|
|
||||||
import com.eactive.apim.portal.common.validator.PasswordMatch;
|
import com.eactive.apim.portal.common.validator.PasswordMatch;
|
||||||
import com.eactive.apim.portal.common.validator.PasswordRuleForKjbank;
|
import com.eactive.apim.portal.common.validator.PasswordRuleForDjbank;
|
||||||
import com.eactive.apim.portal.common.validator.UniqueId;
|
import com.eactive.apim.portal.common.validator.UniqueId;
|
||||||
import com.eactive.apim.portal.portaluser.entity.UserStatus;
|
import com.eactive.apim.portal.portaluser.entity.UserStatus;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -13,7 +13,7 @@ import java.io.Serializable;
|
|||||||
|
|
||||||
@PasswordMatch(input = "password", confirm = "password2")
|
@PasswordMatch(input = "password", confirm = "password2")
|
||||||
@Data
|
@Data
|
||||||
@PasswordRuleForKjbank(loginId = "userId", password = "password", mobile = "mobilePhone")
|
@PasswordRuleForDjbank(loginId = "userId", password = "password", mobile = "mobilePhone")
|
||||||
public class UserRegisterDTO implements Serializable {
|
public class UserRegisterDTO implements Serializable {
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.eactive.apim.portal.apps.user.validator;
|
package com.eactive.apim.portal.apps.user.validator;
|
||||||
|
|
||||||
import com.eactive.apim.portal.common.validator.PasswordRuleForKbankValidator;
|
import com.eactive.apim.portal.common.validator.PasswordRuleForKbankValidator;
|
||||||
import com.eactive.apim.portal.common.validator.PasswordRuleForKjbankValidator;
|
import com.eactive.apim.portal.common.validator.PasswordRuleForDjbankValidator;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@@ -17,7 +17,7 @@ public class PasswordValidator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isValidPassword(String password, String loginId, String mobileNumber) {
|
public boolean isValidPassword(String password, String loginId, String mobileNumber) {
|
||||||
PasswordRuleForKjbankValidator validator = new PasswordRuleForKjbankValidator();
|
PasswordRuleForDjbankValidator validator = new PasswordRuleForDjbankValidator();
|
||||||
return validator.isValid(password, loginId, mobileNumber);
|
return validator.isValid(password, loginId, mobileNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -4,11 +4,11 @@ import javax.validation.Constraint;
|
|||||||
import javax.validation.Payload;
|
import javax.validation.Payload;
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
@Constraint(validatedBy = PasswordRuleForKjbankValidator.class)
|
@Constraint(validatedBy = PasswordRuleForDjbankValidator.class)
|
||||||
@Target({ElementType.TYPE})
|
@Target({ElementType.TYPE})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Documented
|
@Documented
|
||||||
public @interface PasswordRuleForKjbank {
|
public @interface PasswordRuleForDjbank {
|
||||||
String message() default "비밀 번호 규칙에 부합하지 않습니다.(영문/숫자/특수문자 포함 8~20자, 아이디, 휴대전화, 3자리 이상 연속,반복 문자 불가)";
|
String message() default "비밀 번호 규칙에 부합하지 않습니다.(영문/숫자/특수문자 포함 8~20자, 아이디, 휴대전화, 3자리 이상 연속,반복 문자 불가)";
|
||||||
|
|
||||||
Class<?>[] groups() default {};
|
Class<?>[] groups() default {};
|
||||||
+144
@@ -0,0 +1,144 @@
|
|||||||
|
package com.eactive.apim.portal.common.validator;
|
||||||
|
|
||||||
|
import org.apache.commons.beanutils.PropertyUtils;
|
||||||
|
|
||||||
|
import javax.validation.ConstraintValidator;
|
||||||
|
import javax.validation.ConstraintValidatorContext;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Sungpil Hyun
|
||||||
|
*/
|
||||||
|
public class PasswordRuleForDjbankValidator implements ConstraintValidator<PasswordRuleForDjbank, Object> {
|
||||||
|
|
||||||
|
// 최소 8자, 최대 20자 상수 선언
|
||||||
|
private static final int MIN = 8;
|
||||||
|
private static final int MAX = 20;
|
||||||
|
|
||||||
|
private String password;
|
||||||
|
private String loginId;
|
||||||
|
private String mobileNumber;
|
||||||
|
|
||||||
|
// 3자리 연속 문자 정규식
|
||||||
|
private static final String SAMEPT = "(\\w)\\1\\1";
|
||||||
|
// 공백 문자 정규식
|
||||||
|
private static final String BLANKPT = "(\\s)";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(PasswordRuleForDjbank constraintAnnotation) {
|
||||||
|
this.password = constraintAnnotation.password();
|
||||||
|
this.loginId = constraintAnnotation.loginId();
|
||||||
|
this.mobileNumber = constraintAnnotation.mobile();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
|
||||||
|
|
||||||
|
String passwordValue = null;
|
||||||
|
String loginIdValue = null;
|
||||||
|
String mobileNumberValue = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
passwordValue = (String) PropertyUtils.getProperty(value, this.password);
|
||||||
|
loginIdValue = (String) PropertyUtils.getProperty(value, this.loginId);
|
||||||
|
mobileNumberValue = (String) PropertyUtils.getProperty(value, this.mobileNumber);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isValid(passwordValue, loginIdValue, mobileNumberValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValid(String password, String loginId, String mobileNumber) {
|
||||||
|
// 영어, 숫자, 특수문자 포함한 MIN to MAX 글자 정규식
|
||||||
|
String REGEX = "^((?=.*\\d)(?=.*[a-zA-Z])(?=.*[\\W]).{" + MIN + "," + MAX + "})$";
|
||||||
|
|
||||||
|
// 정규식 검사객체
|
||||||
|
Matcher matcher;
|
||||||
|
|
||||||
|
// 공백 체크
|
||||||
|
if (password == null || "".equals(password)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ASCII 문자 비교를 위한 UpperCase
|
||||||
|
String tmpPw = password.toUpperCase();
|
||||||
|
// 문자열 길이
|
||||||
|
int strLen = tmpPw.length();
|
||||||
|
|
||||||
|
// 글자 길이 체크
|
||||||
|
if (strLen > 20 || strLen < 8) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loginId != null && !loginId.isEmpty()) {
|
||||||
|
String[] loginParts = loginId.split("@");
|
||||||
|
if (loginParts.length > 0) {
|
||||||
|
String username = loginParts[0].toUpperCase();
|
||||||
|
if (tmpPw.contains(username)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mobile number validation
|
||||||
|
if (mobileNumber != null && !mobileNumber.isEmpty()) {
|
||||||
|
String[] mobileParts = mobileNumber.split("-");
|
||||||
|
for (String part : mobileParts) {
|
||||||
|
if (!part.isEmpty() && tmpPw.contains(part)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 공백 체크
|
||||||
|
matcher = Pattern.compile(BLANKPT).matcher(tmpPw);
|
||||||
|
if (matcher.find()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 비밀번호 정규식 체크
|
||||||
|
matcher = Pattern.compile(REGEX).matcher(tmpPw);
|
||||||
|
if (!matcher.find()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 동일한 문자 3개 이상 체크
|
||||||
|
matcher = Pattern.compile(SAMEPT).matcher(tmpPw);
|
||||||
|
if (matcher.find()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 연속된 문자 / 숫자 3개 이상 체크
|
||||||
|
// ASCII Char를 담을 배열 선언
|
||||||
|
int[] tmpArray = new int[strLen];
|
||||||
|
|
||||||
|
// Make Array
|
||||||
|
for (int i = 0; i < strLen; i++) {
|
||||||
|
tmpArray[i] = tmpPw.charAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validation Array
|
||||||
|
for (int i = 0; i < strLen - 2; i++) {
|
||||||
|
if (isContinuous(tmpArray[i], tmpArray[i + 2]) && isContinuous(tmpArray[i], tmpArray[i + 1], tmpArray[i + 2])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Validation Complete
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static boolean isContinuous(int first, int third) {
|
||||||
|
// 첫 글자 A-Z / 0-9
|
||||||
|
return (first > 47 && third < 58) || (first > 64 && third < 91);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isContinuous(int first, int second, int third) {
|
||||||
|
// 배열의 연속된 수 검사
|
||||||
|
// 3번째 글자 - 2번째 글자 = 1, 3번째 글자 - 1번째 글자 = 2
|
||||||
|
return Math.abs(third - second) == 1 && Math.abs(third - first) == 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.eactive.apim.portal.config;
|
package com.eactive.apim.portal.config;
|
||||||
|
|
||||||
import com.eactive.apim.portal.custom.config.KjbPasswordEncoder;
|
import com.eactive.apim.portal.custom.config.DjbPasswordEncoder;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
@@ -11,6 +11,6 @@ public class PasswordEncoderConfig {
|
|||||||
@Bean
|
@Bean
|
||||||
public PasswordEncoder passwordEncoder() {
|
public PasswordEncoder passwordEncoder() {
|
||||||
// return new StandardPasswordEncoder();
|
// return new StandardPasswordEncoder();
|
||||||
return new KjbPasswordEncoder();
|
return new DjbPasswordEncoder();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.eactive.apim.portal.custom.config;
|
||||||
|
|
||||||
|
//import com.eactive.ext.djb.safedb.DjbSafedbWrapper;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
|
||||||
|
public class DjbPasswordEncoder implements PasswordEncoder {
|
||||||
|
|
||||||
|
private final BCryptPasswordEncoder bcryptEncoder = new BCryptPasswordEncoder();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String encode(CharSequence rawPassword) {
|
||||||
|
String bcryptHash = bcryptEncoder.encode(rawPassword);
|
||||||
|
return bcryptHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matches(CharSequence rawPassword, String encodedPassword) {
|
||||||
|
return bcryptEncoder.matches(rawPassword, encodedPassword);
|
||||||
|
// DjbSafedbWrapper safedb = DjbSafedbWrapper.getInstance();
|
||||||
|
// String bcryptHash = safedb.decryptNotRnno(encodedPassword);
|
||||||
|
// return bcryptEncoder.matches(rawPassword, bcryptHash);
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
|
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
|
||||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/kbank_base_layout}">
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/DJBank_base_layout}">
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<section layout:fragment="contentFragment" class="content">
|
<section layout:fragment="contentFragment" class="content">
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
<div class="inner i_cs h_inner8 h_inner10">
|
<div class="inner i_cs h_inner8 h_inner10">
|
||||||
<div class="swagger_title m-only">
|
<div class="swagger_title m-only">
|
||||||
<p class="title">API 테스트 베드</p>
|
<p class="title">API 테스트 베드</p>
|
||||||
<p class="text">Kbank API Portal은 Swagger를 이용해 API를 테스트 할 수 있습니다.</p>
|
<p class="text">DJBank API Portal은 Swagger를 이용해 API를 테스트 할 수 있습니다.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="custom_select select_w h_inp" id="apiList">
|
<div class="custom_select select_w h_inp" id="apiList">
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="swagger_infor">
|
<div class="swagger_infor">
|
||||||
<p class="text">인증키가 없는 경우 입력란에 "Kbank"라고 입력하시면 API요청 테스트를 할 수 있습니다.</p>
|
<p class="text">인증키가 없는 경우 API요청 테스트를 할 수 없습니다.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="swagger-ui"></div>
|
<div id="swagger-ui"></div>
|
||||||
|
|||||||
Reference in New Issue
Block a user