userfront로 리펙토링 완료

This commit is contained in:
Lectom C Han committed 2026-01-28 08:28:25 +09:00
1 parent 6d88c81217
commit 1aaa772907
154 files changed
+338 -313

No files matched your search

+2 -2
View File
@@ -11,7 +11,7 @@ DB_PORT=5432
CLICKHOUSE_PORT_HTTP=8123 CLICKHOUSE_PORT_HTTP=8123
CLICKHOUSE_PORT_NATIVE=9000 CLICKHOUSE_PORT_NATIVE=9000
BACKEND_PORT=3000 BACKEND_PORT=3000
FRONTEND_PORT=5000 USERFRONT_PORT=5000
# --- Database Credentials (PostgreSQL) --- # --- Database Credentials (PostgreSQL) ---
DB_USER=baron DB_USER=baron
@@ -47,7 +47,7 @@ ADMIN_EMAIL=admin@baron.co.kr
ADMIN_PASSWORD=adminPasswordIsNotSimple ADMIN_PASSWORD=adminPasswordIsNotSimple
# --- URLs for Proxy/Handoff --- # --- URLs for Proxy/Handoff ---
FRONTEND_URL=https://sso.hmac.kr # 프론트엔드 접속 주소 (이메일/SMS 링크 생성 시 사용) USERFRONT_URL=https://sso.hmac.kr # 프론트엔드 접속 주소 (이메일/SMS 링크 생성 시 사용)
BACKEND_URL=https://sso.hmac.kr # 프론트엔드에서 참조할 백엔드 API 주소 BACKEND_URL=https://sso.hmac.kr # 프론트엔드에서 참조할 백엔드 API 주소
# IDP_PROVIDER는 우선순위 순으로 콤마 구분 (예: Kratos/Hydra 우선, Descope 백업) # IDP_PROVIDER는 우선순위 순으로 콤마 구분 (예: Kratos/Hydra 우선, Descope 백업)
+7 -7
View File
@@ -86,17 +86,17 @@ jobs:
provenance: false provenance: false
sbom: false sbom: false
- name: Temporarily update frontend nginx port - name: Temporarily update userfront nginx port
run: | run: |
sed -i 's/listen 5000;/listen 80;/g' frontend/nginx.conf sed -i 's/listen 5000;/listen 80;/g' userfront/nginx.conf
sed -i 's/proxy_pass http:\/\/baron_backend:3000;/proxy_pass http:\/\/baron_backend:3010;/g' frontend/nginx.conf sed -i 's/proxy_pass http:\/\/baron_backend:3000;/proxy_pass http:\/\/baron_backend:3010;/g' userfront/nginx.conf
- name: Build and push frontend RC image - name: Build and push userfront RC image
uses: docker/build-push-action@v5 uses: docker/build-push-action@v5
with: with:
context: ./frontend context: ./userfront
file: ./frontend/Dockerfile file: ./userfront/Dockerfile
push: true push: true
tags: ${{ vars.HARBOR_HOSTNAME }}/baron_sso/frontend:${{ steps.rc_calculator.outputs.new_rc_tag }} tags: ${{ vars.HARBOR_HOSTNAME }}/baron_sso/userfront:${{ steps.rc_calculator.outputs.new_rc_tag }}
provenance: false provenance: false
sbom: false sbom: false
+9 -9
View File
@@ -13,8 +13,8 @@ on:
required: true required: true
type: boolean type: boolean
default: true default: true
run_frontend_tests: run_userfront_tests:
description: "Run frontend Flutter tests" description: "Run userfront Flutter tests"
required: true required: true
type: boolean type: boolean
default: true default: true
@@ -46,9 +46,9 @@ jobs:
working-directory: backend working-directory: backend
args: --enable-only=gofmt,gofumpt args: --enable-only=gofmt,gofumpt
- name: Analyze Flutter frontend - name: Analyze Flutter userfront
run: | run: |
cd frontend cd userfront
flutter analyze --no-fatal-warnings --no-fatal-infos flutter analyze --no-fatal-warnings --no-fatal-infos
backend-tests: backend-tests:
@@ -85,9 +85,9 @@ jobs:
cd backend cd backend
go test -v ./... go test -v ./...
frontend-tests: userfront-tests:
needs: lint needs: lint
if: ${{ inputs.run_frontend_tests == true }} if: ${{ inputs.run_userfront_tests == true }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
@@ -99,11 +99,11 @@ jobs:
channel: "stable" channel: "stable"
cache: true cache: true
- name: Run frontend tests - name: Run userfront tests
run: | run: |
cd frontend cd userfront
if [ -d test ]; then if [ -d test ]; then
flutter test flutter test
else else
echo "No frontend tests: skipping (test/ directory not found)." echo "No userfront tests: skipping (test/ directory not found)."
fi fi
+7 -7
View File
@@ -49,12 +49,12 @@ jobs:
--src-tls-verify=false --dest-tls-verify=false \ --src-tls-verify=false --dest-tls-verify=false \
"docker://${HARBOR_HOSTNAME}/baron_sso/backend:${BASE_TAG}" "docker://${HARBOR_HOSTNAME}/baron_sso/backend:${RE_TAG}" "docker://${HARBOR_HOSTNAME}/baron_sso/backend:${BASE_TAG}" "docker://${HARBOR_HOSTNAME}/baron_sso/backend:${RE_TAG}"
# Re-tag frontend image # Re-tag userfront image
echo "Re-tagging frontend image..." echo "Re-tagging userfront image..."
skopeo copy --preserve-digests \ skopeo copy --preserve-digests \
--src-creds "${HARBOR_USER}:${HARBOR_PASSWORD}" --dest-creds "${HARBOR_USER}:${HARBOR_PASSWORD}" \ --src-creds "${HARBOR_USER}:${HARBOR_PASSWORD}" --dest-creds "${HARBOR_USER}:${HARBOR_PASSWORD}" \
--src-tls-verify=false --dest-tls-verify=false \ --src-tls-verify=false --dest-tls-verify=false \
"docker://${HARBOR_HOSTNAME}/baron_sso/frontend:${BASE_TAG}" "docker://${HARBOR_HOSTNAME}/baron_sso/frontend:${RE_TAG}" "docker://${HARBOR_HOSTNAME}/baron_sso/userfront:${BASE_TAG}" "docker://${HARBOR_HOSTNAME}/baron_sso/userfront:${RE_TAG}"
echo "final_image_tag=${RE_TAG}" >> "$GITHUB_OUTPUT" echo "final_image_tag=${RE_TAG}" >> "$GITHUB_OUTPUT"
@@ -67,7 +67,7 @@ jobs:
env: env:
IMAGE_TAG: ${{ steps.retag.outputs.final_image_tag }} IMAGE_TAG: ${{ steps.retag.outputs.final_image_tag }}
BACKEND_IMAGE_NAME: ${{ vars.HARBOR_HOSTNAME }}/baron_sso/backend BACKEND_IMAGE_NAME: ${{ vars.HARBOR_HOSTNAME }}/baron_sso/backend
FRONTEND_IMAGE_NAME: ${{ vars.HARBOR_HOSTNAME }}/baron_sso/frontend USERFRONT_IMAGE_NAME: ${{ vars.HARBOR_HOSTNAME }}/baron_sso/userfront
DEPLOY_PATH: ${{ vars.PROD_DEPLOY_PATH }} DEPLOY_PATH: ${{ vars.PROD_DEPLOY_PATH }}
PROD_HOST: ${{ vars.PROD_HOST }} PROD_HOST: ${{ vars.PROD_HOST }}
PROD_USER: ${{ vars.PROD_USER }} PROD_USER: ${{ vars.PROD_USER }}
@@ -102,7 +102,7 @@ jobs:
"CLICKHOUSE_USER=${{ vars.PROD_CLICKHOUSE_USER }}" \ "CLICKHOUSE_USER=${{ vars.PROD_CLICKHOUSE_USER }}" \
"CLICKHOUSE_PASSWORD=${{ secrets.PROD_CLICKHOUSE_PASSWORD }}" \ "CLICKHOUSE_PASSWORD=${{ secrets.PROD_CLICKHOUSE_PASSWORD }}" \
"BACKEND_PORT=${{ vars.PROD_BACKEND_PORT }}" \ "BACKEND_PORT=${{ vars.PROD_BACKEND_PORT }}" \
"FRONTEND_PORT=${{ vars.PROD_FRONTEND_PORT }}" \ "USERFRONT_PORT=${{ vars.PROD_USERFRONT_PORT }}" \
"DB_USER=${{ vars.PROD_DB_USER }}" \ "DB_USER=${{ vars.PROD_DB_USER }}" \
"DB_PASSWORD=${{ secrets.PROD_DB_PASSWORD }}" \ "DB_PASSWORD=${{ secrets.PROD_DB_PASSWORD }}" \
"DB_NAME=${{ vars.PROD_DB_NAME }}" \ "DB_NAME=${{ vars.PROD_DB_NAME }}" \
@@ -119,7 +119,7 @@ jobs:
"AWS_ACCESS_KEY_ID=${{ vars.AWS_ACCESS_KEY_ID }}" \ "AWS_ACCESS_KEY_ID=${{ vars.AWS_ACCESS_KEY_ID }}" \
"AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }}" \ "AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }}" \
"AWS_SES_SENDER=${{ vars.AWS_SES_SENDER }}" \ "AWS_SES_SENDER=${{ vars.AWS_SES_SENDER }}" \
"FRONTEND_URL=${{ vars.PROD_FRONTEND_URL }}" \ "USERFRONT_URL=${{ vars.PROD_USERFRONT_URL }}" \
"BACKEND_URL=${{ vars.PROD_BACKEND_URL }}" \ "BACKEND_URL=${{ vars.PROD_BACKEND_URL }}" \
> .env > .env
@@ -131,7 +131,7 @@ jobs:
echo "${HARBOR_ROBOT_KEY}" | ssh "${PROD_USER}@${PROD_HOST}" \ echo "${HARBOR_ROBOT_KEY}" | ssh "${PROD_USER}@${PROD_HOST}" \
"export DEPLOY_PATH='${DEPLOY_PATH}'; \ "export DEPLOY_PATH='${DEPLOY_PATH}'; \
export BACKEND_IMAGE_NAME='${BACKEND_IMAGE_NAME}'; \ export BACKEND_IMAGE_NAME='${BACKEND_IMAGE_NAME}'; \
export FRONTEND_IMAGE_NAME='${FRONTEND_IMAGE_NAME}'; \ export USERFRONT_IMAGE_NAME='${USERFRONT_IMAGE_NAME}'; \
export IMAGE_TAG='${IMAGE_TAG}'; \ export IMAGE_TAG='${IMAGE_TAG}'; \
export HARBOR_ENDPOINT='${HARBOR_ENDPOINT}'; \ export HARBOR_ENDPOINT='${HARBOR_ENDPOINT}'; \
export HARBOR_ROBOT_ACCOUNT='${HARBOR_ROBOT_ACCOUNT}'; \ export HARBOR_ROBOT_ACCOUNT='${HARBOR_ROBOT_ACCOUNT}'; \
+7 -7
View File
@@ -17,10 +17,10 @@ backend/vendor/
backend/tmp/ backend/tmp/
backend/.env backend/.env
# Frontend (Flutter) # userfront (Flutter)
# Note: Frontend might have its own .gitignore, but adding here just in case # Note: userfront might have its own .gitignore, but adding here just in case
frontend/build/ userfront/build/
frontend/.dart_tool/ userfront/.dart_tool/
frontend/.packages userfront/.packages
frontend/.pub/ userfront/.pub/
frontend/.env userfront/.env
+16 -16
View File
@@ -21,22 +21,22 @@
- **Features**: - **Features**:
- 인증용 SMS 발송 등 Ory-Stack으로 구현 어려운 부분 직접 구현 - 인증용 SMS 발송 등 Ory-Stack으로 구현 어려운 부분 직접 구현
- `POST /api/v1/audit`: 감사 로그 수집 API - `POST /api/v1/audit`: 감사 로그 수집 API
- User-Front가 바라보는 backend - userfront가 바라보는 backend
### 2. User-Front(Flutter Web/App) ### 2. userfront(Flutter Web/App)
- **Framework**: Flutter 3.32+ - **Framework**: Flutter 3.32+
- **Key Packages**: `flutter_riverpod`, `go_router` - **Key Packages**: `flutter_riverpod`, `go_router`
- **Features**: - **Features**:
- 탭 기반 로그인 UI (비밀번호 기반 / 링크 기반 / QR 기반 등) - 탭 기반 로그인 UI (비밀번호 기반 / 링크 기반 / QR 기반 등)
### 3. Admin-Front(Web) ### 3. adminfront(Web)
- **Framework**: Vite, React 19+, Shadcn/ui 등 - **Framework**: Vite, React 19+, Shadcn/ui 등
- **Features**: - **Features**:
- 사용자 관리, 권한 부여 등 관리자 기능 - 사용자 관리, 권한 부여 등 관리자 기능
- 앱 별 사용량(호출량) 등 통계 - 앱 별 사용량(호출량) 등 통계
- 핵심 Audit 대상 - 핵심 Audit 대상
### 4. Dev-Front(Web) - 향후 분리 예정 ### 4. devfront(Web) - 향후 분리 예정
- **Framework**: Vite, React 19+, Shadcn/ui 등 - **Framework**: Vite, React 19+, Shadcn/ui 등
- **Features**: - **Features**:
- RP 등록 및 관리 - RP 등록 및 관리
@@ -55,9 +55,9 @@
```mermaid ```mermaid
flowchart LR flowchart LR
AF[Admin Front] -->|"OIDC authorize/token (PKCE)"| HY["Hydra (OIDC 엔진)"] AF[adminfront] -->|"OIDC authorize/token (PKCE)"| HY["Hydra (OIDC 엔진)"]
DF[Dev Front] -->|"OIDC authorize/token (PKCE)"| HY DF[devfront] -->|"OIDC authorize/token (PKCE)"| HY
UF["User Front (Login/Consent UI)"] <-->|Hydra login/consent redirect| HY UF["userfront (Login/Consent UI)"] <-->|Hydra login/consent redirect| HY
UF -->|Kratos Browser Flow| KR["Kratos (SoT: identities/traits)"] UF -->|Kratos Browser Flow| KR["Kratos (SoT: identities/traits)"]
KR -->|subject=identity.id| HY KR -->|subject=identity.id| HY
HY -->|ID/Access Token| RP[Relying Party Apps] HY -->|ID/Access Token| RP[Relying Party Apps]
@@ -111,14 +111,14 @@ docker compose -f compose.infra.yaml -f compose.ory.yaml up -d
``` ```
#### 3. 애플리케이션 실행 #### 3. 애플리케이션 실행
Frontend와 Backend 서비스를 실행합니다. userfront와 backend 서비스를 실행합니다.
```bash ```bash
docker compose -f docker-compose.yaml up -d docker compose -f docker-compose.yaml up -d
``` ```
(또는 한번에 실행: `docker compose -f compose.infra.yaml -f compose.ory.yaml -f docker-compose.yaml up -d`) (또는 한번에 실행: `docker compose -f compose.infra.yaml -f compose.ory.yaml -f docker-compose.yaml up -d`)
- **Frontend**: http://localhost:5000 접속 - **userfront**: http://localhost:5000 접속
- **Backend**: http://localhost:3000 (API) - **backend**: http://localhost:3000 (API)
- **ClickHouse**: http://localhost:8123 - **ClickHouse**: http://localhost:8123
- **Kratos Public**: http://localhost:4433 - **Kratos Public**: http://localhost:4433
- **Hydra Public**: http://localhost:4444 - **Hydra Public**: http://localhost:4444
@@ -134,9 +134,9 @@ go mod tidy
go run cmd/server/main.go go run cmd/server/main.go
``` ```
**Frontend:** **userfront:**
```bash ```bash
cd frontend cd userfront
flutter pub get flutter pub get
flutter run -d chrome flutter run -d chrome
``` ```
@@ -151,10 +151,10 @@ baron_sso/
│ ├── cmd/server/ # 진입점 (Entry point) │ ├── cmd/server/ # 진입점 (Entry point)
│ ├── internal/ # 도메인, 핸들러, 저장소(Repository) │ ├── internal/ # 도메인, 핸들러, 저장소(Repository)
│ └── Dockerfile │ └── Dockerfile
├── user-front/ # Flutter 애플리케이션 ├── userfront/ # Flutter 애플리케이션
│ ├── src/ # UI 및 로직 │ ├── src/ # UI 및 로직
│ └── pubspec.yaml │ └── pubspec.yaml
├── admin-front/ # React 기반 관리 ├── adminfront/ # React 기반 관리
│ ├── src/ # UI 및 로직 │ ├── src/ # UI 및 로직
│ └── pubspec.yaml │ └── pubspec.yaml
├── compose.ory-stack.yaml # DB 서비스 (Postgres, ClickHouse) ├── compose.ory-stack.yaml # DB 서비스 (Postgres, ClickHouse)
@@ -167,6 +167,6 @@ baron_sso/
## 📝 상태 및 로드맵 (Status & Roadmap) ## 📝 상태 및 로드맵 (Status & Roadmap)
- [x] **Phase 1**: 초기 설정 및 아키텍처 설계 (완료) - [x] **Phase 1**: 초기 설정 및 아키텍처 설계 (완료)
- [x] **Phase 2**: Backend Audit API 구현 (일부 완료) - [x] **Phase 2**: Backend Audit API 구현 (일부 완료)
- [x] **Phase 3**: User Front 로그인 UI 인증 로직 (완료) - [x] **Phase 3**: userfront 로그인 UI 인증 로직 (완료)
- [ ] **Phase 4**: Admin Front 기능 추가 (예정) - [ ] **Phase 4**: adminfront 기능 추가 (예정)
- [ ] **Phase 5**: 대시보드 및 통합 런처 구현 (예정) - [ ] **Phase 5**: 대시보드 및 통합 런처 구현 (예정)
+7 -7
View File
@@ -24,7 +24,7 @@ It leverages **Descope** for secure, passwordless authentication (Enchanted Link
### 3. Infrastructure (Docker) ### 3. Infrastructure (Docker)
- **Services**: `postgres`, `clickhouse` (defined in `compose.infra.yaml`) - **Services**: `postgres`, `clickhouse` (defined in `compose.infra.yaml`)
- **App**: `frontend`, `backend` (defined in `docker-compose.yaml`) - **App**: `userfront`, `backend` (defined in `docker-compose.yaml`)
--- ---
@@ -60,13 +60,13 @@ docker compose -f compose.infra.yaml up -d
``` ```
#### 2. Start Applications #### 2. Start Applications
Start the Frontend and Backend services. Start the userfront and backend services.
```bash ```bash
docker compose up docker compose up
``` ```
- **Frontend**: Accessible at http://localhost:5000 - **userfront**: Accessible at http://localhost:5000
- **Backend**: API active at http://localhost:3000 - **backend**: API active at http://localhost:3000
- **ClickHouse**: http://localhost:8123 - **ClickHouse**: http://localhost:8123
### Local Development (Manual) ### Local Development (Manual)
@@ -79,9 +79,9 @@ go mod tidy
go run cmd/server/main.go go run cmd/server/main.go
``` ```
**Frontend:** **userfront:**
```bash ```bash
cd frontend cd userfront
flutter pub get flutter pub get
flutter run -d chrome flutter run -d chrome
``` ```
@@ -96,7 +96,7 @@ baron_sso/
│ ├── cmd/server/ # Entry point │ ├── cmd/server/ # Entry point
│ ├── internal/ # Domain, Handlers, Repository │ ├── internal/ # Domain, Handlers, Repository
│ └── Dockerfile │ └── Dockerfile
├── frontend/ # Flutter Application ├── userfront/ # Flutter Application
│ ├── lib/ # UI & Logic │ ├── lib/ # UI & Logic
│ └── pubspec.yaml │ └── pubspec.yaml
├── compose.infra.yaml # DB Services (Postgres, ClickHouse) ├── compose.infra.yaml # DB Services (Postgres, ClickHouse)
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -4,7 +4,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>admin-front</title> <title>adminfront</title>
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
@@ -1,11 +1,11 @@
{ {
"name": "admin-front", "name": "adminfront",
"version": "0.0.0", "version": "0.0.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "admin-front", "name": "adminfront",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@radix-ui/react-avatar": "^1.1.4", "@radix-ui/react-avatar": "^1.1.4",
@@ -1,5 +1,5 @@
{ {
"name": "admin-front", "name": "adminfront",
"private": true, "private": true,
"version": "0.0.0", "version": "0.0.0",
"type": "module", "type": "module",
File renamed without changes.
File renamed without changes.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

File renamed without changes.
File renamed without changes.
File renamed without changes.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

File renamed without changes.
@@ -54,7 +54,7 @@ function DashboardPage() {
<div className="space-y-3 max-w-2xl"> <div className="space-y-3 max-w-2xl">
<div className="inline-flex items-center gap-2 rounded-full border border-[var(--color-border)] px-3 py-1 text-xs uppercase tracking-[0.2em] text-[var(--color-muted)]"> <div className="inline-flex items-center gap-2 rounded-full border border-[var(--color-border)] px-3 py-1 text-xs uppercase tracking-[0.2em] text-[var(--color-muted)]">
<Sparkles size={14} /> <Sparkles size={14} />
admin-front ready adminfront ready
</div> </div>
<h2 className="text-3xl font-semibold leading-tight"> <h2 className="text-3xl font-semibold leading-tight">
Build the admin plane with{" "} Build the admin plane with{" "}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+2 -2
View File
@@ -74,8 +74,8 @@ func main() {
"app_env", getEnv("APP_ENV", "dev"), "app_env", getEnv("APP_ENV", "dev"),
"db_port", getEnv("DB_PORT", "5532"), "db_port", getEnv("DB_PORT", "5532"),
"backend_port", getEnv("BACKEND_PORT", "3000"), "backend_port", getEnv("BACKEND_PORT", "3000"),
"frontend_port", getEnv("FRONTEND_PORT", "5000"), "userfront_port", getEnv("USERFRONT_PORT", "5000"),
"frontend_url", getEnv("FRONTEND_URL", "http://sso.hmac.kr"), "userfront_url", getEnv("USERFRONT_URL", "http://sso.hmac.kr"),
"redis_addr", getEnv("REDIS_ADDR", "redis:6379"), "redis_addr", getEnv("REDIS_ADDR", "redis:6379"),
) )
+20 -20
View File
@@ -418,7 +418,7 @@ func (h *AuthHandler) saveSignupState(key string, state *signupState, ttl time.D
return h.RedisService.Set(key, string(data), ttl) return h.RedisService.Set(key, string(data), ttl)
} }
// GetPasswordPolicy exposes the current Descope password policy to the frontend for dynamic validation. // GetPasswordPolicy exposes the current Descope password policy to the userfront for dynamic validation.
func (h *AuthHandler) GetPasswordPolicy(c *fiber.Ctx) error { func (h *AuthHandler) GetPasswordPolicy(c *fiber.Ctx) error {
if h.DescopeClient == nil { if h.DescopeClient == nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Descope client not configured"}) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Descope client not configured"})
@@ -531,12 +531,12 @@ func (h *AuthHandler) InitEnchantedLink(c *fiber.Ctx) error {
h.RedisService.Set(prefixToken+token, fmt.Sprintf(`{"pendingRef":"%s","loginId":"%s"}`, pendingRef, loginID), defaultExpiration) h.RedisService.Set(prefixToken+token, fmt.Sprintf(`{"pendingRef":"%s","loginId":"%s"}`, pendingRef, loginID), defaultExpiration)
// Generate Link // Generate Link
frontendURL := os.Getenv("FRONTEND_URL") userfrontURL := os.Getenv("USERFRONT_URL")
slog.Info("[Enchanted] Read FRONTEND_URL", "url", frontendURL) slog.Info("[Enchanted] Read USERFRONT_URL", "url", userfrontURL)
if frontendURL == "" { if userfrontURL == "" {
frontendURL = "http://sso.hmac.kr" userfrontURL = "http://sso.hmac.kr"
} }
link := fmt.Sprintf("%s/verify/%s", frontendURL, token) link := fmt.Sprintf("%s/verify/%s", userfrontURL, token)
// Route based on LoginID type // Route based on LoginID type
if strings.Contains(loginID, "@") { if strings.Contains(loginID, "@") {
@@ -801,16 +801,16 @@ func (h *AuthHandler) InitiatePasswordReset(c *fiber.Ctx) error {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Authentication service not configured"}) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Authentication service not configured"})
} }
frontendURL := os.Getenv("FRONTEND_URL") userfrontURL := os.Getenv("USERFRONT_URL")
if frontendURL == "" { if userfrontURL == "" {
ale.Status = fiber.StatusInternalServerError ale.Status = fiber.StatusInternalServerError
ale.LatencyMs = time.Since(startTime) ale.LatencyMs = time.Since(startTime)
ale.DescopeError = "FRONTEND_URL is not set" ale.DescopeError = "USERFRONT_URL is not set"
ale.Log(slog.LevelError, "FRONTEND_URL is not set") ale.Log(slog.LevelError, "USERFRONT_URL is not set")
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "FRONTEND_URL environment variable is not set"}) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "USERFRONT_URL environment variable is not set"})
} }
// [Changed] Point to Backend API for verification (which then redirects to Frontend) // [Changed] Point to Backend API for verification (which then redirects to Frontend)
redirectURL := fmt.Sprintf("%s/api/v1/auth/password/reset/verify", frontendURL) redirectURL := fmt.Sprintf("%s/api/v1/auth/password/reset/verify", userfrontURL)
ale.RedirectTo = redirectURL ale.RedirectTo = redirectURL
// 내부 토큰 발급 + 우리 채널로 전송 // 내부 토큰 발급 + 우리 채널로 전송
@@ -831,7 +831,7 @@ func (h *AuthHandler) InitiatePasswordReset(c *fiber.Ctx) error {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to store reset token"}) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to store reset token"})
} }
resetLink := fmt.Sprintf("%s/reset-password?token=%s", frontendURL, resetToken) resetLink := fmt.Sprintf("%s/reset-password?token=%s", userfrontURL, resetToken)
ale.RedirectTo = resetLink ale.RedirectTo = resetLink
ale.Operation = "SendPasswordReset" ale.Operation = "SendPasswordReset"
ale.Log(slog.LevelInfo, "Initiating password reset via internal token") ale.Log(slog.LevelInfo, "Initiating password reset via internal token")
@@ -923,7 +923,7 @@ func (h *AuthHandler) VerifyPasswordResetPage(c *fiber.Ctx) error {
} }
// ProcessPasswordResetToken - Handles the POST request from the interstitial page. // ProcessPasswordResetToken - Handles the POST request from the interstitial page.
// Verifies the token, sets the refresh token cookie, and redirects to the frontend. // Verifies the token, sets the refresh token cookie, and redirects to the userfront.
func (h *AuthHandler) ProcessPasswordResetToken(c *fiber.Ctx) error { func (h *AuthHandler) ProcessPasswordResetToken(c *fiber.Ctx) error {
startTime := time.Now() startTime := time.Now()
ale := logger.NewAuditLogEntry(c, "verify") ale := logger.NewAuditLogEntry(c, "verify")
@@ -960,7 +960,7 @@ func (h *AuthHandler) ProcessPasswordResetToken(c *fiber.Ctx) error {
ale.LoginIDs["loginId_normalized"] = loginID ale.LoginIDs["loginId_normalized"] = loginID
redirectURL := fmt.Sprintf("%s/reset-password?loginId=%s&token=%s", redirectURL := fmt.Sprintf("%s/reset-password?loginId=%s&token=%s",
os.Getenv("FRONTEND_URL"), os.Getenv("USERFRONT_URL"),
loginID, loginID,
token, token,
) )
@@ -968,7 +968,7 @@ func (h *AuthHandler) ProcessPasswordResetToken(c *fiber.Ctx) error {
ale.RedirectTo = redirectURL ale.RedirectTo = redirectURL
ale.Status = fiber.StatusFound ale.Status = fiber.StatusFound
ale.LatencyMs = time.Since(startTime) ale.LatencyMs = time.Since(startTime)
ale.Log(slog.LevelInfo, "Token verified, redirecting to frontend") ale.Log(slog.LevelInfo, "Token verified, redirecting to userfront")
return c.Redirect(redirectURL) return c.Redirect(redirectURL)
} }
@@ -1127,11 +1127,11 @@ func (h *AuthHandler) InitQRLogin(c *fiber.Ctx) error {
pendingRef := GenerateSecureToken(16) pendingRef := GenerateSecureToken(16)
// QR 코드 페이로드를 실제 접속 가능한 URL로 변경합니다. // QR 코드 페이로드를 실제 접속 가능한 URL로 변경합니다.
frontendURL := os.Getenv("FRONTEND_URL") userfrontURL := os.Getenv("USERFRONT_URL")
if frontendURL == "" { if userfrontURL == "" {
frontendURL = "https://sso.hmac.kr" userfrontURL = "https://sso.hmac.kr"
} }
qrPayload := fmt.Sprintf("%s/approve?ref=%s", frontendURL, pendingRef) qrPayload := fmt.Sprintf("%s/approve?ref=%s", userfrontURL, pendingRef)
slog.Info("[QR] Init", "pendingRef", pendingRef, "url", qrPayload) slog.Info("[QR] Init", "pendingRef", pendingRef, "url", qrPayload)
+1 -1
View File
@@ -44,7 +44,7 @@ func NewDescopeProvider(projectID, managementKey string) *DescopeProvider {
return &DescopeProvider{ return &DescopeProvider{
Client: descopeClient, Client: descopeClient,
FrontendURL: os.Getenv("FRONTEND_URL"), FrontendURL: os.Getenv("USERFRONT_URL"),
fieldMapping: mapping, fieldMapping: mapping,
} }
} }
+2 -1
View File
@@ -52,5 +52,6 @@ volumes:
networks: networks:
baron_net: baron_net:
name: baron_network name: baron_net
external: true
driver: bridge driver: bridge
+1 -1
View File
@@ -173,7 +173,7 @@ services:
command: > command: >
clients create clients create
--endpoint http://hydra:4445 --endpoint http://hydra:4445
--id admin-front --id adminfront
--secret admin-secret --secret admin-secret
--grant-types authorization_code,refresh_token --grant-types authorization_code,refresh_token
--response-types code --response-types code
+85 -85
View File
@@ -1,91 +1,91 @@
services: services:
backend: backend:
build: build:
context: ./backend context: ./backend
dockerfile: Dockerfile dockerfile: Dockerfile
container_name: baron_backend container_name: baron_backend
env_file: env_file:
- .env - .env
environment: environment:
- APP_ENV=${APP_ENV:-development} - APP_ENV=${APP_ENV:-development}
- GO_ENV=${APP_ENV:-development} - GO_ENV=${APP_ENV:-development}
- COOKIE_SECRET=${COOKIE_SECRET} - COOKIE_SECRET=${COOKIE_SECRET}
- JWT_SECRET=${JWT_SECRET} - JWT_SECRET=${JWT_SECRET}
- DESCOPE_PROJECT_ID=${DESCOPE_PROJECT_ID} - DESCOPE_PROJECT_ID=${DESCOPE_PROJECT_ID}
- DESCOPE_MANAGEMENT_KEY=${DESCOPE_MANAGEMENT_KEY} - DESCOPE_MANAGEMENT_KEY=${DESCOPE_MANAGEMENT_KEY}
- NAVER_CLOUD_ACCESS_KEY=${NAVER_CLOUD_ACCESS_KEY} - NAVER_CLOUD_ACCESS_KEY=${NAVER_CLOUD_ACCESS_KEY}
- NAVER_CLOUD_SECRET_KEY=${NAVER_CLOUD_SECRET_KEY} - NAVER_CLOUD_SECRET_KEY=${NAVER_CLOUD_SECRET_KEY}
- NAVER_CLOUD_SERVICE_ID=${NAVER_CLOUD_SERVICE_ID} - NAVER_CLOUD_SERVICE_ID=${NAVER_CLOUD_SERVICE_ID}
- NAVER_SENDER_PHONE_NUMBER=${NAVER_SENDER_PHONE_NUMBER} - NAVER_SENDER_PHONE_NUMBER=${NAVER_SENDER_PHONE_NUMBER}
- FRONTEND_URL=${FRONTEND_URL} - USERFRONT_URL=${USERFRONT_URL}
- IDP_PROVIDER=${IDP_PROVIDER:-ory,descope} - IDP_PROVIDER=${IDP_PROVIDER:-ory,descope}
- KRATOS_ADMIN_URL=${KRATOS_ADMIN_URL:-http://kratos:4434} - KRATOS_ADMIN_URL=${KRATOS_ADMIN_URL:-http://kratos:4434}
- HYDRA_ADMIN_URL=${HYDRA_ADMIN_URL:-http://hydra:4445} - HYDRA_ADMIN_URL=${HYDRA_ADMIN_URL:-http://hydra:4445}
- DB_HOST=postgres - DB_HOST=postgres
- CLICKHOUSE_HOST=clickhouse - CLICKHOUSE_HOST=clickhouse
- CLICKHOUSE_PORT=${CLICKHOUSE_PORT_NATIVE:-9000} - CLICKHOUSE_PORT=${CLICKHOUSE_PORT_NATIVE:-9000}
- CLICKHOUSE_USER=${CLICKHOUSE_USER:-baron} - CLICKHOUSE_USER=${CLICKHOUSE_USER:-baron}
- CLICKHOUSE_PASSWORD=${CLICKHOUSE_PASSWORD:-password} - CLICKHOUSE_PASSWORD=${CLICKHOUSE_PASSWORD:-password}
ports: ports:
- "${BACKEND_PORT:-3000}:3000" - "${BACKEND_PORT:-3000}:3000"
depends_on: depends_on:
- infra_check - infra_check
networks: networks:
- baron_net - baron_net
- ory-net - ory-net
volumes: volumes:
- ./backend:/app - ./backend:/app
command: ["go", "run", "./cmd/server/main.go"] command: ["go", "run", "./cmd/server/main.go"]
healthcheck: healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3000/health"] test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3000/health"]
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 3 retries: 3
start_period: 10s start_period: 10s
frontend: userfront:
build: build:
context: ./frontend context: ./userfront
dockerfile: Dockerfile dockerfile: Dockerfile
container_name: baron_frontend container_name: baron_userfront
env_file: env_file:
- .env - .env
environment: environment:
- DESCOPE_PROJECT_ID=${DESCOPE_PROJECT_ID} - DESCOPE_PROJECT_ID=${DESCOPE_PROJECT_ID}
- BACKEND_URL=${BACKEND_URL} - BACKEND_URL=${BACKEND_URL}
- FRONTEND_URL=${FRONTEND_URL} - USERFRONT_URL=${USERFRONT_URL}
- APP_ENV=${APP_ENV} - APP_ENV=${APP_ENV}
ports: ports:
- "${FRONTEND_PORT:-5000}:5000" - "${USERFRONT_PORT:-5000}:5000"
networks: networks:
- baron_net - baron_net
depends_on: depends_on:
backend: backend:
condition: service_healthy condition: service_healthy
command: > command: >
/bin/sh -c "mkdir -p /usr/share/nginx/html/assets && /bin/sh -c "mkdir -p /usr/share/nginx/html/assets &&
echo \"DESCOPE_PROJECT_ID=$${DESCOPE_PROJECT_ID}\" > /usr/share/nginx/html/assets/.env && echo \"DESCOPE_PROJECT_ID=$${DESCOPE_PROJECT_ID}\" > /usr/share/nginx/html/assets/.env &&
echo \"BACKEND_URL=$${BACKEND_URL}\" >> /usr/share/nginx/html/assets/.env && echo \"BACKEND_URL=$${BACKEND_URL}\" >> /usr/share/nginx/html/assets/.env &&
echo \"FRONTEND_URL=$${FRONTEND_URL}\" >> /usr/share/nginx/html/assets/.env && echo \"USERFRONT_URL=$${USERFRONT_URL}\" >> /usr/share/nginx/html/assets/.env &&
echo \"APP_ENV=$${APP_ENV}\" >> /usr/share/nginx/html/assets/.env && echo \"APP_ENV=$${APP_ENV}\" >> /usr/share/nginx/html/assets/.env &&
cp /usr/share/nginx/html/assets/.env /usr/share/nginx/html/.env && cp /usr/share/nginx/html/assets/.env /usr/share/nginx/html/.env &&
nginx -g 'daemon off;'" nginx -g 'daemon off;'"
# Dummy service to wait for infra network if needed, # Dummy service to wait for infra network if needed,
# but essentially we assume infra is running. # but essentially we assume infra is running.
# In a real unified stack, we might include infra here or use external links. # In a real unified stack, we might include infra here or use external links.
# Here we attach to the same network. # Here we attach to the same network.
infra_check: infra_check:
image: alpine image: alpine
command: ["echo", "Infrastructure assumed running"] command: ["echo", "Infrastructure assumed running"]
networks: networks:
- baron_net - baron_net
networks: networks:
baron_net: baron_net:
external: true external: true
name: baron_network name: baron_net
ory-net: ory-net:
external: true external: true
name: ory-net name: ory-net
+3 -3
View File
@@ -13,10 +13,10 @@ Backend와 Frontend 애플리케이션을 각각의 Dockerfile을 사용하여
```bash ```bash
# Backend 이미지 빌드 # Backend 이미지 빌드
# v1.2601.1-RC1 부분은 실제 배포 버전에 맞게 수정하세요. # v1.2601.1-RC1 부분은 실제 배포 버전에 맞게 수정하세요.
docker build -t reg.hmac.kr/baron_sso/backend:v1.2601.1-RC1 -f docker/Dockerfile.backend . docker build -t reg.hmac.kr/baron_sso/backend:v1.2601.1-RC1 -f backend/Dockerfile .
# Frontend 이미지 빌드 # Frontend 이미지 빌드
docker build -t reg.hmac.kr/baron_sso/frontend:v1.2601.1-RC1 -f docker/Dockerfile.frontend . docker build -t reg.hmac.kr/baron_sso/userfront:v1.2601.1-RC1 -f userfront/Dockerfile .
``` ```
--- ---
@@ -42,7 +42,7 @@ docker login reg.hmac.kr
docker push reg.hmac.kr/baron_sso/backend:v1.2601.1-RC1 docker push reg.hmac.kr/baron_sso/backend:v1.2601.1-RC1
# Frontend 이미지 푸시 # Frontend 이미지 푸시
docker push reg.hmac.kr/baron_sso/frontend:v1.2601.1-RC1 docker push reg.hmac.kr/baron_sso/userfront:v1.2601.1-RC1
``` ```
--- ---
+7 -7
View File
@@ -16,7 +16,7 @@ services:
- CLICKHOUSE_PORT=${CLICKHOUSE_PORT_NATIVE:-9000} - CLICKHOUSE_PORT=${CLICKHOUSE_PORT_NATIVE:-9000}
- CLICKHOUSE_USER=${CLICKHOUSE_USER:-baron} - CLICKHOUSE_USER=${CLICKHOUSE_USER:-baron}
- CLICKHOUSE_PASSWORD=${CLICKHOUSE_PASSWORD:-password} - CLICKHOUSE_PASSWORD=${CLICKHOUSE_PASSWORD:-password}
- FRONTEND_URL=${FRONTEND_URL:-https://sso.hmac.kr} - USERFRONT_URL=${USERFRONT_URL:-https://sso.hmac.kr}
ports: ports:
- "${BACKEND_PORT:-3010}:3010" - "${BACKEND_PORT:-3010}:3010"
depends_on: depends_on:
@@ -30,15 +30,15 @@ services:
networks: networks:
- baron_net - baron_net
frontend: userfront:
image: ${FRONTEND_IMAGE_NAME}:${IMAGE_TAG} image: ${USERFRONT_IMAGE_NAME}:${IMAGE_TAG}
container_name: baron_frontend container_name: baron_userfront
restart: unless-stopped restart: unless-stopped
environment: environment:
- FRONTEND_URL=${FRONTEND_URL:-https://sso.hmac.kr} - USERFRONT_URL=${USERFRONT_URL:-https://sso.hmac.kr}
- BACKEND_URL=${FRONTEND_URL:-https://sso.hmac.kr} - BACKEND_URL=${USERFRONT_URL:-https://sso.hmac.kr}
ports: ports:
- "${FRONTEND_PORT:-80}:80" - "${USERFRONT_PORT:-80}:80"
depends_on: depends_on:
backend: backend:
condition: service_healthy condition: service_healthy
+1 -1
View File
@@ -35,7 +35,7 @@
## Workspace Structure ## Workspace Structure
Root: `/home/lectom/.gemini/antigravity/scratch/baron_sso` Root: `/home/lectom/.gemini/antigravity/scratch/baron_sso`
- `/backend`: Go Fiber Application - `/backend`: Go Fiber Application
- `/frontend`: Flutter Application - `/userfront`: Flutter Application
- `/docs`: Documentation (PRD, API Specs) - `/docs`: Documentation (PRD, API Specs)
## Current Status ## Current Status
-98
View File
@@ -1,98 +0,0 @@
name: frontend
description: "A new Flutter project."
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: "none" # Remove this line if you wish to publish to pub.dev
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.0+1
environment:
sdk: ^3.10.4
# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
# consider running `flutter pub upgrade --major-versions`. Alternatively,
# dependencies can be manually updated by changing the version numbers below to
# the latest version available on pub.dev. To see which dependencies have newer
# versions available, run `flutter pub outdated`.
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.8
flutter_riverpod: ^3.0.3
go_router: ^17.0.1
descope: ^0.9.11
http: ^1.6.0
google_fonts: ^6.3.3
flutter_dotenv: ^5.1.0
url_launcher: ^6.3.2
logging: ^1.2.0
logger: ^2.0.0
qr_flutter: ^4.1.0
mobile_scanner: ^6.0.0
dev_dependencies:
flutter_test:
sdk: flutter
# The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is
# activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^6.0.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter packages.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - .env
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/to/resolution-aware-images
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/to/asset-from-package
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/to/font-from-package
@@ -11,7 +11,7 @@ DB_PORT=5432
CLICKHOUSE_PORT_HTTP=8123 CLICKHOUSE_PORT_HTTP=8123
CLICKHOUSE_PORT_NATIVE=9000 CLICKHOUSE_PORT_NATIVE=9000
BACKEND_PORT=3000 BACKEND_PORT=3000
FRONTEND_PORT=5000 USERFRONT_PORT=5000
# --- Database Credentials (PostgreSQL) --- # --- Database Credentials (PostgreSQL) ---
DB_USER=baron DB_USER=baron
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -6,7 +6,7 @@ plugins {
} }
android { android {
namespace = "kr.co.baroncs.frontend" namespace = "kr.co.baroncs.userfront"
compileSdk = flutter.compileSdkVersion compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion ndkVersion = flutter.ndkVersion
@@ -21,7 +21,7 @@ android {
defaultConfig { defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "kr.co.baroncs.frontend" applicationId = "kr.co.baroncs.userfront"
// You can update the following values to match your application needs. // You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config. // For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion minSdk = flutter.minSdkVersion
@@ -1,7 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.CAMERA"/>
<application <application
android:label="frontend" android:label="userfront"
android:name="${applicationName}" android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/ic_launcher">
<activity <activity
@@ -1,4 +1,4 @@
package kr.co.baroncs.frontend package kr.co.baroncs.userfront
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.FlutterActivity
File renamed without changes.

Before

Width:  |  Height:  |  Size: 544 B

After

Width:  |  Height:  |  Size: 544 B

File renamed without changes.

Before

Width:  |  Height:  |  Size: 442 B

After

Width:  |  Height:  |  Size: 442 B

File renamed without changes.

Before

Width:  |  Height:  |  Size: 721 B

After

Width:  |  Height:  |  Size: 721 B

File renamed without changes.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

File renamed without changes.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -368,7 +368,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = kr.co.baroncs.frontend; PRODUCT_BUNDLE_IDENTIFIER = kr.co.baroncs.userfront;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@@ -384,7 +384,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = kr.co.baroncs.frontend.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = kr.co.baroncs.userfront.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -401,7 +401,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = kr.co.baroncs.frontend.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = kr.co.baroncs.userfront.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@@ -416,7 +416,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = kr.co.baroncs.frontend.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = kr.co.baroncs.userfront.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@@ -547,7 +547,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = kr.co.baroncs.frontend; PRODUCT_BUNDLE_IDENTIFIER = kr.co.baroncs.userfront;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -569,7 +569,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = kr.co.baroncs.frontend; PRODUCT_BUNDLE_IDENTIFIER = kr.co.baroncs.userfront;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
File renamed without changes.
File renamed without changes.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

File renamed without changes.

Before

Width:  |  Height:  |  Size: 295 B

After

Width:  |  Height:  |  Size: 295 B

File renamed without changes.

Before

Width:  |  Height:  |  Size: 406 B

After

Width:  |  Height:  |  Size: 406 B

File renamed without changes.

Before

Width:  |  Height:  |  Size: 450 B

After

Width:  |  Height:  |  Size: 450 B

File renamed without changes.

Before

Width:  |  Height:  |  Size: 282 B

After

Width:  |  Height:  |  Size: 282 B

File renamed without changes.

Before

Width:  |  Height:  |  Size: 462 B

After

Width:  |  Height:  |  Size: 462 B

Loaded 100 of 154 files, more files were not shown because too many files have changed in this diff. Show more