forked from baron/baron-sso
make dev/dev-debug 구분.
This commit is contained in:
8
Makefile
8
Makefile
@@ -29,7 +29,7 @@ ifneq (,$(wildcard ./.env))
|
|||||||
COMPOSE_DROP_ENV_ARGS += --env-file .env
|
COMPOSE_DROP_ENV_ARGS += --env-file .env
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: build-auth-config validate-auth-config verify-auth-config render-ory-config up up-all up-infra up-ory up-app up-backend ensure-networks ensure-infra ensure-ory up-dev up-front-dev dev down drop down-app down-backend down-infra down-ory check-infra ps logs-infra logs-ory logs-app
|
.PHONY: build-auth-config validate-auth-config verify-auth-config render-ory-config up up-all up-infra up-ory up-app up-backend ensure-networks ensure-infra ensure-ory up-dev up-front-dev dev dev-debug down drop down-app down-backend down-infra down-ory check-infra ps logs-infra logs-ory logs-app
|
||||||
|
|
||||||
# --- 인증 설정 빌드/검증 ---
|
# --- 인증 설정 빌드/검증 ---
|
||||||
build-auth-config:
|
build-auth-config:
|
||||||
@@ -128,7 +128,11 @@ up-front-dev: up-infra up-ory up-backend
|
|||||||
|
|
||||||
dev: up-dev
|
dev: up-dev
|
||||||
@echo "Starting development app containers in foreground attach mode..."
|
@echo "Starting development app containers in foreground attach mode..."
|
||||||
docker compose $(COMPOSE_CLI_ENV_ARGS) -f $(COMPOSE_APP) up --build $(DEV_SERVICES)
|
BACKEND_LOG_LEVEL=info CLIENT_LOG_DEBUG=false VITE_CLIENT_LOG_DEBUG=false docker compose $(COMPOSE_CLI_ENV_ARGS) -f $(COMPOSE_APP) up --build $(DEV_SERVICES)
|
||||||
|
|
||||||
|
dev-debug: up-dev
|
||||||
|
@echo "Starting development app containers in foreground attach debug mode..."
|
||||||
|
BACKEND_LOG_LEVEL=debug CLIENT_LOG_DEBUG=true VITE_CLIENT_LOG_DEBUG=true USERFRONT_FLUTTER_RUN_FLAGS=--debug docker compose $(COMPOSE_CLI_ENV_ARGS) -f $(COMPOSE_APP) up --build $(DEV_SERVICES)
|
||||||
|
|
||||||
# --- 종료 (Down) ---
|
# --- 종료 (Down) ---
|
||||||
down:
|
down:
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import {
|
|||||||
} from "../../../../common/shell";
|
} from "../../../../common/shell";
|
||||||
import { buildAuthenticatedOrgChartUrl } from "../../features/users/orgChartPicker";
|
import { buildAuthenticatedOrgChartUrl } from "../../features/users/orgChartPicker";
|
||||||
import { fetchMe } from "../../lib/adminApi";
|
import { fetchMe } from "../../lib/adminApi";
|
||||||
|
import { debugLog } from "../../lib/debugLog";
|
||||||
import { t } from "../../lib/i18n";
|
import { t } from "../../lib/i18n";
|
||||||
import { isSuperAdminRole } from "../../lib/roles";
|
import { isSuperAdminRole } from "../../lib/roles";
|
||||||
import {
|
import {
|
||||||
@@ -154,10 +155,10 @@ function AppLayout() {
|
|||||||
} = useQuery({
|
} = useQuery({
|
||||||
queryKey: ["me"],
|
queryKey: ["me"],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
console.debug("[AppLayout] Fetching profile...");
|
debugLog("[AppLayout] Fetching profile...");
|
||||||
try {
|
try {
|
||||||
const data = await fetchMe();
|
const data = await fetchMe();
|
||||||
console.debug("[AppLayout] Profile fetched successfully:", data.email);
|
debugLog("[AppLayout] Profile fetched successfully:", data.email);
|
||||||
return data;
|
return data;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("[AppLayout] Failed to fetch profile:", err);
|
console.error("[AppLayout] Failed to fetch profile:", err);
|
||||||
@@ -273,7 +274,7 @@ function AppLayout() {
|
|||||||
(window as Window & typeof globalThis & { _IS_TEST_MODE?: boolean })
|
(window as Window & typeof globalThis & { _IS_TEST_MODE?: boolean })
|
||||||
._IS_TEST_MODE === true;
|
._IS_TEST_MODE === true;
|
||||||
|
|
||||||
console.debug("[AppLayout] Auth state check:", {
|
debugLog("[AppLayout] Auth state check:", {
|
||||||
isLoading: auth.isLoading,
|
isLoading: auth.isLoading,
|
||||||
isAuthenticated: auth.isAuthenticated,
|
isAuthenticated: auth.isAuthenticated,
|
||||||
isTest,
|
isTest,
|
||||||
|
|||||||
@@ -2,13 +2,14 @@ import { ShieldHalf } from "lucide-react";
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useAuth } from "react-oidc-context";
|
import { useAuth } from "react-oidc-context";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { debugLog } from "../../lib/debugLog";
|
||||||
|
|
||||||
function AuthCallbackPage() {
|
function AuthCallbackPage() {
|
||||||
const auth = useAuth();
|
const auth = useAuth();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.debug("[AuthCallbackPage] State:", {
|
debugLog("[AuthCallbackPage] State:", {
|
||||||
isAuthenticated: auth.isAuthenticated,
|
isAuthenticated: auth.isAuthenticated,
|
||||||
isLoading: auth.isLoading,
|
isLoading: auth.isLoading,
|
||||||
error: auth.error,
|
error: auth.error,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "../../components/ui/card";
|
} from "../../components/ui/card";
|
||||||
|
import { debugLog } from "../../lib/debugLog";
|
||||||
|
|
||||||
function LoginPage() {
|
function LoginPage() {
|
||||||
const auth = useAuth();
|
const auth = useAuth();
|
||||||
@@ -20,7 +21,7 @@ function LoginPage() {
|
|||||||
const shouldAutoLogin = searchParams.get("auto") === "1";
|
const shouldAutoLogin = searchParams.get("auto") === "1";
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.debug("[LoginPage] Auth state check:", {
|
debugLog("[LoginPage] Auth state check:", {
|
||||||
isAuthenticated: auth.isAuthenticated,
|
isAuthenticated: auth.isAuthenticated,
|
||||||
isLoading: auth.isLoading,
|
isLoading: auth.isLoading,
|
||||||
returnTo,
|
returnTo,
|
||||||
|
|||||||
8
adminfront/src/lib/debugLog.ts
Normal file
8
adminfront/src/lib/debugLog.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
const CLIENT_DEBUG_LOG_ENABLED = new Set(["1", "true", "yes", "y", "on"]).has(
|
||||||
|
String(import.meta.env.VITE_CLIENT_LOG_DEBUG ?? "").trim().toLowerCase(),
|
||||||
|
);
|
||||||
|
|
||||||
|
export function debugLog(...args: Parameters<typeof console.debug>) {
|
||||||
|
if (!CLIENT_DEBUG_LOG_ENABLED) return;
|
||||||
|
console.debug(...args);
|
||||||
|
}
|
||||||
@@ -37,20 +37,25 @@ func IsProductionEnv(appEnv string) bool {
|
|||||||
return IsProductionLikeEnv(appEnv)
|
return IsProductionLikeEnv(appEnv)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseBoolFlag(raw string) bool {
|
func parseOptionalBoolFlag(raw string) (bool, bool) {
|
||||||
switch strings.ToLower(strings.TrimSpace(raw)) {
|
switch strings.ToLower(strings.TrimSpace(raw)) {
|
||||||
case "1", "true", "yes", "y", "on":
|
case "1", "true", "yes", "y", "on":
|
||||||
return true
|
return true, true
|
||||||
|
case "0", "false", "no", "n", "off":
|
||||||
|
return false, true
|
||||||
default:
|
default:
|
||||||
return false
|
return false, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ClientDebugEnabled(appEnv, productionDebugFlag string) bool {
|
func ClientDebugEnabled(appEnv, debugFlag string) bool {
|
||||||
|
if enabled, ok := parseOptionalBoolFlag(debugFlag); ok {
|
||||||
|
return enabled
|
||||||
|
}
|
||||||
if !IsProductionEnv(appEnv) {
|
if !IsProductionEnv(appEnv) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return parseBoolFlag(productionDebugFlag)
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func NormalizeClientLogLevel(level string) slog.Level {
|
func NormalizeClientLogLevel(level string) slog.Level {
|
||||||
|
|||||||
@@ -9,7 +9,14 @@ import (
|
|||||||
func TestClientDebugEnabled(t *testing.T) {
|
func TestClientDebugEnabled(t *testing.T) {
|
||||||
t.Run("non production enables debug by default", func(t *testing.T) {
|
t.Run("non production enables debug by default", func(t *testing.T) {
|
||||||
assert.True(t, ClientDebugEnabled("dev", ""))
|
assert.True(t, ClientDebugEnabled("dev", ""))
|
||||||
assert.True(t, ClientDebugEnabled("local", "false"))
|
assert.True(t, ClientDebugEnabled("local", ""))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("explicit debug flag applies in non production", func(t *testing.T) {
|
||||||
|
assert.True(t, ClientDebugEnabled("dev", "true"))
|
||||||
|
assert.True(t, ClientDebugEnabled("local", "1"))
|
||||||
|
assert.False(t, ClientDebugEnabled("dev", "false"))
|
||||||
|
assert.False(t, ClientDebugEnabled("local", "0"))
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("production disables debug by default", func(t *testing.T) {
|
t.Run("production disables debug by default", func(t *testing.T) {
|
||||||
@@ -37,6 +44,8 @@ func TestShouldAcceptClientLog(t *testing.T) {
|
|||||||
assert.True(t, ShouldAcceptClientLog("stage", "", "ERROR"))
|
assert.True(t, ShouldAcceptClientLog("stage", "", "ERROR"))
|
||||||
assert.True(t, ShouldAcceptClientLog("production", "true", "INFO"))
|
assert.True(t, ShouldAcceptClientLog("production", "true", "INFO"))
|
||||||
assert.True(t, ShouldAcceptClientLog("dev", "", "INFO"))
|
assert.True(t, ShouldAcceptClientLog("dev", "", "INFO"))
|
||||||
|
assert.False(t, ShouldAcceptClientLog("dev", "false", "INFO"))
|
||||||
|
assert.True(t, ShouldAcceptClientLog("dev", "false", "WARN"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShouldFilterNoisyClientInfo(t *testing.T) {
|
func TestShouldFilterNoisyClientInfo(t *testing.T) {
|
||||||
@@ -44,6 +53,7 @@ func TestShouldFilterNoisyClientInfo(t *testing.T) {
|
|||||||
assert.True(t, ShouldFilterNoisyClientInfo("stage", "", "Navigating to /ko/signin"))
|
assert.True(t, ShouldFilterNoisyClientInfo("stage", "", "Navigating to /ko/signin"))
|
||||||
assert.False(t, ShouldFilterNoisyClientInfo("production", "true", "Navigating to /ko/signin"))
|
assert.False(t, ShouldFilterNoisyClientInfo("production", "true", "Navigating to /ko/signin"))
|
||||||
assert.False(t, ShouldFilterNoisyClientInfo("dev", "", "Navigating to /ko/signin"))
|
assert.False(t, ShouldFilterNoisyClientInfo("dev", "", "Navigating to /ko/signin"))
|
||||||
|
assert.True(t, ShouldFilterNoisyClientInfo("dev", "false", "Navigating to /ko/signin"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSanitizeClientLogData(t *testing.T) {
|
func TestSanitizeClientLogData(t *testing.T) {
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- APP_ENV=${APP_ENV:-development}
|
- APP_ENV=${APP_ENV:-development}
|
||||||
- GO_ENV=${APP_ENV:-development}
|
- GO_ENV=${APP_ENV:-development}
|
||||||
|
- BACKEND_LOG_LEVEL=${BACKEND_LOG_LEVEL:-info}
|
||||||
|
- CLIENT_LOG_DEBUG=${CLIENT_LOG_DEBUG:-false}
|
||||||
- COOKIE_SECRET=${COOKIE_SECRET}
|
- COOKIE_SECRET=${COOKIE_SECRET}
|
||||||
- JWT_SECRET=${JWT_SECRET}
|
- JWT_SECRET=${JWT_SECRET}
|
||||||
- NAVER_CLOUD_ACCESS_KEY=${NAVER_CLOUD_ACCESS_KEY}
|
- NAVER_CLOUD_ACCESS_KEY=${NAVER_CLOUD_ACCESS_KEY}
|
||||||
@@ -58,6 +60,7 @@ services:
|
|||||||
- APP_ENV=${APP_ENV:-development}
|
- APP_ENV=${APP_ENV:-development}
|
||||||
- API_PROXY_TARGET=http://baron_backend:3000
|
- API_PROXY_TARGET=http://baron_backend:3000
|
||||||
- USERFRONT_URL=${USERFRONT_URL}
|
- USERFRONT_URL=${USERFRONT_URL}
|
||||||
|
- VITE_CLIENT_LOG_DEBUG=${VITE_CLIENT_LOG_DEBUG:-false}
|
||||||
ports:
|
ports:
|
||||||
- "${ADMINFRONT_PORT:-5173}:5173"
|
- "${ADMINFRONT_PORT:-5173}:5173"
|
||||||
volumes:
|
volumes:
|
||||||
@@ -82,6 +85,7 @@ services:
|
|||||||
- APP_ENV=${APP_ENV:-development}
|
- APP_ENV=${APP_ENV:-development}
|
||||||
- API_PROXY_TARGET=http://baron_backend:3000
|
- API_PROXY_TARGET=http://baron_backend:3000
|
||||||
- USERFRONT_URL=${USERFRONT_URL}
|
- USERFRONT_URL=${USERFRONT_URL}
|
||||||
|
- VITE_CLIENT_LOG_DEBUG=${VITE_CLIENT_LOG_DEBUG:-false}
|
||||||
ports:
|
ports:
|
||||||
- "${DEVFRONT_PORT:-5174}:5173"
|
- "${DEVFRONT_PORT:-5174}:5173"
|
||||||
volumes:
|
volumes:
|
||||||
@@ -106,6 +110,7 @@ services:
|
|||||||
- APP_ENV=${APP_ENV:-development}
|
- APP_ENV=${APP_ENV:-development}
|
||||||
- API_PROXY_TARGET=http://baron_backend:3000
|
- API_PROXY_TARGET=http://baron_backend:3000
|
||||||
- USERFRONT_URL=${USERFRONT_URL}
|
- USERFRONT_URL=${USERFRONT_URL}
|
||||||
|
- VITE_CLIENT_LOG_DEBUG=${VITE_CLIENT_LOG_DEBUG:-false}
|
||||||
ports:
|
ports:
|
||||||
- "${ORGFRONT_PORT:-5175}:5175"
|
- "${ORGFRONT_PORT:-5175}:5175"
|
||||||
volumes:
|
volumes:
|
||||||
@@ -132,7 +137,9 @@ services:
|
|||||||
- BACKEND_URL=${BACKEND_URL:-}
|
- BACKEND_URL=${BACKEND_URL:-}
|
||||||
- USERFRONT_URL=${USERFRONT_URL}
|
- USERFRONT_URL=${USERFRONT_URL}
|
||||||
- APP_ENV=${APP_ENV}
|
- APP_ENV=${APP_ENV}
|
||||||
|
- CLIENT_LOG_DEBUG=${CLIENT_LOG_DEBUG:-false}
|
||||||
- USERFRONT_INTERNAL_PORT=5000
|
- USERFRONT_INTERNAL_PORT=5000
|
||||||
|
- USERFRONT_FLUTTER_RUN_FLAGS=${USERFRONT_FLUTTER_RUN_FLAGS:-}
|
||||||
volumes:
|
volumes:
|
||||||
- ./userfront/lib:/workspace/userfront/lib
|
- ./userfront/lib:/workspace/userfront/lib
|
||||||
- ./userfront/assets:/workspace/userfront/assets
|
- ./userfront/assets:/workspace/userfront/assets
|
||||||
|
|||||||
@@ -40,7 +40,14 @@ grep -Fq -- "AS dev" "$USERFRONT_DOCKERFILE" || fail "userfront Dockerfile must
|
|||||||
grep -Fq -- "AS production" "$USERFRONT_DOCKERFILE" || fail "userfront Dockerfile must keep an explicit production target"
|
grep -Fq -- "AS production" "$USERFRONT_DOCKERFILE" || fail "userfront Dockerfile must keep an explicit production target"
|
||||||
grep -Fq -- "flutter run" "$USERFRONT_DEV_SERVER" || fail "userfront dev server must use flutter run"
|
grep -Fq -- "flutter run" "$USERFRONT_DEV_SERVER" || fail "userfront dev server must use flutter run"
|
||||||
grep -Fq -- "--wasm" "$USERFRONT_DEV_SERVER" || fail "userfront dev server must keep WebAssembly enabled"
|
grep -Fq -- "--wasm" "$USERFRONT_DEV_SERVER" || fail "userfront dev server must keep WebAssembly enabled"
|
||||||
grep -Fq -- "--debug" "$USERFRONT_DEV_SERVER" || fail "userfront dev server must run in debug mode"
|
grep -Fq -- "--dart-define=CLIENT_LOG_DEBUG=" "$USERFRONT_DEV_SERVER" || fail "userfront dev server must pass client log debug mode through dart-define"
|
||||||
|
grep -Fq -- "--dart-define=APP_ENV=" "$USERFRONT_DEV_SERVER" || fail "userfront dev server must pass app env through dart-define"
|
||||||
|
grep -Fq -- 'USERFRONT_FLUTTER_RUN_FLAGS' "$USERFRONT_DEV_SERVER" || fail "userfront dev server must accept optional Flutter run flags"
|
||||||
|
assert_contains 'CLIENT_LOG_DEBUG=${CLIENT_LOG_DEBUG:-false}'
|
||||||
|
assert_contains 'USERFRONT_FLUTTER_RUN_FLAGS=${USERFRONT_FLUTTER_RUN_FLAGS:-}'
|
||||||
|
if grep -Fq -- "--debug" "$USERFRONT_DEV_SERVER"; then
|
||||||
|
fail "make dev must not hard-code Flutter debug mode in the userfront dev server"
|
||||||
|
fi
|
||||||
if grep -Fq -- "--release" "$USERFRONT_DEV_SERVER"; then
|
if grep -Fq -- "--release" "$USERFRONT_DEV_SERVER"; then
|
||||||
fail "userfront dev server must not run Flutter in release mode"
|
fail "userfront dev server must not run Flutter in release mode"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -54,6 +54,54 @@ if ! grep -q -- " --build" <<<"$app_up_line"; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if ! grep -q -- "BACKEND_LOG_LEVEL=info" <<<"$app_up_line"; then
|
||||||
|
echo "make dev must run backend at info log level." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! grep -q -- "CLIENT_LOG_DEBUG=false" <<<"$app_up_line"; then
|
||||||
|
echo "make dev must disable verbose client debug log ingestion." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! grep -q -- "VITE_CLIENT_LOG_DEBUG=false" <<<"$app_up_line"; then
|
||||||
|
echo "make dev must disable React client debug console logs." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -q -- "BACKEND_LOG_LEVEL=debug" <<<"$app_up_line"; then
|
||||||
|
echo "make dev must not run backend at debug log level." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -q -- "USERFRONT_FLUTTER_RUN_FLAGS=--debug" <<<"$app_up_line"; then
|
||||||
|
echo "make dev must not run userfront with explicit Flutter debug flags." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
dry_run_dev_debug="$(
|
||||||
|
make --dry-run --always-make -C "$repo_root" dev-debug DEV_SERVICES="backend userfront" 2>&1
|
||||||
|
)"
|
||||||
|
|
||||||
|
if ! grep -q "Ensuring Infra stack" <<<"$dry_run_dev_debug"; then
|
||||||
|
echo "make dev-debug must ensure the infra stack first." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! grep -q "Ensuring Ory stack" <<<"$dry_run_dev_debug"; then
|
||||||
|
echo "make dev-debug must ensure the Ory stack first." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
dev_debug_app_up_line="$(
|
||||||
|
grep -E "BACKEND_LOG_LEVEL=debug CLIENT_LOG_DEBUG=true VITE_CLIENT_LOG_DEBUG=true USERFRONT_FLUTTER_RUN_FLAGS=--debug docker compose .* -f docker-compose.yaml up .*backend.*userfront" <<<"$dry_run_dev_debug" | tail -1
|
||||||
|
)"
|
||||||
|
|
||||||
|
if [[ -z "$dev_debug_app_up_line" ]]; then
|
||||||
|
echo "make dev-debug must run app services with explicit backend, client log, and userfront debug flags." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
dry_run_up_dev="$(
|
dry_run_up_dev="$(
|
||||||
make --dry-run --always-make -C "$repo_root" up-dev 2>&1
|
make --dry-run --always-make -C "$repo_root" up-dev 2>&1
|
||||||
)"
|
)"
|
||||||
|
|||||||
@@ -29,23 +29,37 @@ class LogPolicy {
|
|||||||
env == 'staging';
|
env == 'staging';
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool parseBoolFlag(String? raw) {
|
static ({bool enabled, bool specified}) parseOptionalBoolFlag(String? raw) {
|
||||||
final value = (raw ?? '').trim().toLowerCase();
|
final value = (raw ?? '').trim().toLowerCase();
|
||||||
return value == '1' ||
|
if (value == '1' ||
|
||||||
value == 'true' ||
|
value == 'true' ||
|
||||||
value == 'yes' ||
|
value == 'yes' ||
|
||||||
value == 'y' ||
|
value == 'y' ||
|
||||||
value == 'on';
|
value == 'on') {
|
||||||
|
return (enabled: true, specified: true);
|
||||||
|
}
|
||||||
|
if (value == '0' ||
|
||||||
|
value == 'false' ||
|
||||||
|
value == 'no' ||
|
||||||
|
value == 'n' ||
|
||||||
|
value == 'off') {
|
||||||
|
return (enabled: false, specified: true);
|
||||||
|
}
|
||||||
|
return (enabled: false, specified: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool debugEnabled({
|
static bool debugEnabled({
|
||||||
required String? appEnv,
|
required String? appEnv,
|
||||||
required String? productionDebugFlag,
|
required String? productionDebugFlag,
|
||||||
}) {
|
}) {
|
||||||
|
final flag = parseOptionalBoolFlag(productionDebugFlag);
|
||||||
|
if (flag.specified) {
|
||||||
|
return flag.enabled;
|
||||||
|
}
|
||||||
if (!isProductionEnv(appEnv)) {
|
if (!isProductionEnv(appEnv)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return parseBoolFlag(productionDebugFlag);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool shouldRelayClientLog({
|
static bool shouldRelayClientLog({
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
|
||||||
import 'package:logging/logging.dart' as std_log;
|
import 'package:logging/logging.dart' as std_log;
|
||||||
import 'package:logger/logger.dart' as pretty_log;
|
import 'package:logger/logger.dart' as pretty_log;
|
||||||
import 'auth_proxy_service.dart';
|
import 'auth_proxy_service.dart';
|
||||||
import 'log_policy.dart';
|
import 'log_policy.dart';
|
||||||
|
import 'runtime_env.dart';
|
||||||
|
|
||||||
/// Global Logger Service for Baron SSO Frontend
|
/// Global Logger Service for Baron SSO Frontend
|
||||||
class LoggerService {
|
class LoggerService {
|
||||||
@@ -16,10 +16,10 @@ class LoggerService {
|
|||||||
late final String _productionDebugFlag;
|
late final String _productionDebugFlag;
|
||||||
|
|
||||||
LoggerService._internal() {
|
LoggerService._internal() {
|
||||||
_appEnv = _envOrDefault('APP_ENV', 'dev');
|
_appEnv = envOrDefault('APP_ENV', 'dev');
|
||||||
_productionDebugFlag = _envOrDefault(
|
_productionDebugFlag = envOrDefault(
|
||||||
'CLIENT_LOG_DEBUG',
|
'CLIENT_LOG_DEBUG',
|
||||||
_envOrDefault('USERFRONT_DEBUG_LOG', ''),
|
envOrDefault('USERFRONT_DEBUG_LOG', ''),
|
||||||
);
|
);
|
||||||
final debugEnabled = LogPolicy.debugEnabled(
|
final debugEnabled = LogPolicy.debugEnabled(
|
||||||
appEnv: _appEnv,
|
appEnv: _appEnv,
|
||||||
@@ -54,17 +54,6 @@ class LoggerService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static String _envOrDefault(String key, String fallback) {
|
|
||||||
if (!dotenv.isInitialized) {
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
final value = dotenv.env[key];
|
|
||||||
if (value == null || value.trim().isEmpty) {
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Initialize the logger. Call this in main.dart
|
/// Initialize the logger. Call this in main.dart
|
||||||
static void init() {
|
static void init() {
|
||||||
// Accessing the instance triggers the constructor
|
// Accessing the instance triggers the constructor
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||||
|
|
||||||
|
const _compileTimeEnv = {
|
||||||
|
'APP_ENV': String.fromEnvironment('APP_ENV'),
|
||||||
|
'CLIENT_LOG_DEBUG': String.fromEnvironment('CLIENT_LOG_DEBUG'),
|
||||||
|
'USERFRONT_DEBUG_LOG': String.fromEnvironment('USERFRONT_DEBUG_LOG'),
|
||||||
|
};
|
||||||
|
|
||||||
String runtimeOriginFallback() {
|
String runtimeOriginFallback() {
|
||||||
try {
|
try {
|
||||||
final origin = Uri.base.origin;
|
final origin = Uri.base.origin;
|
||||||
@@ -11,14 +17,18 @@ String runtimeOriginFallback() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String envOrDefault(String key, String fallback) {
|
String envOrDefault(String key, String fallback) {
|
||||||
if (!dotenv.isInitialized) {
|
if (dotenv.isInitialized) {
|
||||||
return fallback;
|
final value = dotenv.env[key];
|
||||||
|
if (value != null && value.trim().isNotEmpty) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
final value = dotenv.env[key];
|
|
||||||
if (value == null || value.trim().isEmpty) {
|
final compileTimeValue = _compileTimeEnv[key];
|
||||||
return fallback;
|
if (compileTimeValue != null && compileTimeValue.trim().isNotEmpty) {
|
||||||
|
return compileTimeValue;
|
||||||
}
|
}
|
||||||
return value;
|
return fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
String sanitizedUrl(String value) {
|
String sanitizedUrl(String value) {
|
||||||
|
|||||||
@@ -5,10 +5,14 @@ cd /workspace
|
|||||||
/bin/sh ./scripts/sync_userfront_locales.sh
|
/bin/sh ./scripts/sync_userfront_locales.sh
|
||||||
|
|
||||||
cd /workspace/userfront
|
cd /workspace/userfront
|
||||||
exec flutter run \
|
set -- flutter run \
|
||||||
-d web-server \
|
-d web-server \
|
||||||
--web-hostname 0.0.0.0 \
|
--web-hostname 0.0.0.0 \
|
||||||
--web-port "${USERFRONT_INTERNAL_PORT:-5000}" \
|
--web-port "${USERFRONT_INTERNAL_PORT:-5000}" \
|
||||||
--wasm \
|
--wasm \
|
||||||
--debug \
|
--dart-define=CLIENT_LOG_DEBUG="${CLIENT_LOG_DEBUG:-false}" \
|
||||||
|
--dart-define=APP_ENV="${APP_ENV:-dev}" \
|
||||||
|
${USERFRONT_FLUTTER_RUN_FLAGS:-} \
|
||||||
--no-web-resources-cdn
|
--no-web-resources-cdn
|
||||||
|
|
||||||
|
exec "$@"
|
||||||
|
|||||||
@@ -9,14 +9,30 @@ void main() {
|
|||||||
isTrue,
|
isTrue,
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
LogPolicy.debugEnabled(
|
LogPolicy.debugEnabled(appEnv: 'development', productionDebugFlag: ''),
|
||||||
appEnv: 'development',
|
|
||||||
productionDebugFlag: 'false',
|
|
||||||
),
|
|
||||||
isTrue,
|
isTrue,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('explicit debug flag applies in development-like environment', () {
|
||||||
|
expect(
|
||||||
|
LogPolicy.debugEnabled(appEnv: 'dev', productionDebugFlag: 'true'),
|
||||||
|
isTrue,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
LogPolicy.debugEnabled(appEnv: 'development', productionDebugFlag: '1'),
|
||||||
|
isTrue,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
LogPolicy.debugEnabled(appEnv: 'dev', productionDebugFlag: 'false'),
|
||||||
|
isFalse,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
LogPolicy.debugEnabled(appEnv: 'development', productionDebugFlag: '0'),
|
||||||
|
isFalse,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test('production disables debug unless explicitly enabled', () {
|
test('production disables debug unless explicitly enabled', () {
|
||||||
expect(
|
expect(
|
||||||
LogPolicy.debugEnabled(appEnv: 'production', productionDebugFlag: ''),
|
LogPolicy.debugEnabled(appEnv: 'production', productionDebugFlag: ''),
|
||||||
@@ -94,6 +110,28 @@ void main() {
|
|||||||
isTrue,
|
isTrue,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'explicit development debug false forwards only warning or higher',
|
||||||
|
() {
|
||||||
|
expect(
|
||||||
|
LogPolicy.shouldRelayClientLog(
|
||||||
|
level: 'INFO',
|
||||||
|
appEnv: 'dev',
|
||||||
|
productionDebugFlag: 'false',
|
||||||
|
),
|
||||||
|
isFalse,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
LogPolicy.shouldRelayClientLog(
|
||||||
|
level: 'WARN',
|
||||||
|
appEnv: 'dev',
|
||||||
|
productionDebugFlag: 'false',
|
||||||
|
),
|
||||||
|
isTrue,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
group('LogPolicy.sanitize', () {
|
group('LogPolicy.sanitize', () {
|
||||||
|
|||||||
Reference in New Issue
Block a user