forked from baron/baron-sso
chore: consolidate local integration changes
This commit is contained in:
@@ -18,7 +18,7 @@ COPY . .
|
||||
RUN /bin/sh ./scripts/sync_userfront_locales.sh
|
||||
WORKDIR /app/userfront
|
||||
RUN flutter pub get
|
||||
RUN flutter build web --release --wasm
|
||||
RUN rm -rf build/web && flutter build web --release --wasm
|
||||
|
||||
FROM node:24-alpine AS optimize
|
||||
WORKDIR /work
|
||||
|
||||
@@ -1446,7 +1446,7 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
||||
color: Colors.redAccent,
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
: _singleLineText(
|
||||
item.isRevoked
|
||||
? tr('ui.userfront.dashboard.status.revoked')
|
||||
: tr('ui.userfront.dashboard.revoke.title'),
|
||||
|
||||
@@ -2151,7 +2151,7 @@ const Map<String, String> koStrings = {
|
||||
"ui.userfront.dashboard.last_auth_label": "최근 인증",
|
||||
"ui.userfront.dashboard.link_status_label": "연동 상태",
|
||||
"ui.userfront.dashboard.revoke.confirm_button": "해지하기",
|
||||
"ui.userfront.dashboard.revoke.title": "연동 해지",
|
||||
"ui.userfront.dashboard.revoke.title": "연동해지",
|
||||
"ui.userfront.dashboard.scopes.title": "동의 범위",
|
||||
"ui.userfront.dashboard.sessions.active_badge": "활성화",
|
||||
"ui.userfront.dashboard.sessions.current_badge": "접속중",
|
||||
|
||||
@@ -11,6 +11,14 @@ USERFRONT_BOOT_WARMUP_ATTEMPTS="${USERFRONT_BOOT_WARMUP_ATTEMPTS:-120}"
|
||||
USERFRONT_BOOT_WARMUP_INTERVAL_SECONDS="${USERFRONT_BOOT_WARMUP_INTERVAL_SECONDS:-0.5}"
|
||||
USERFRONT_BOOT_WARMUP_LOCALES="${USERFRONT_BOOT_WARMUP_LOCALES:-ko en}"
|
||||
USERFRONT_BOOT_WARMUP_VIEWPORTS="${USERFRONT_BOOT_WARMUP_VIEWPORTS:-mobile:390 desktop:1440}"
|
||||
USERFRONT_BOOT_BUILD_MARKER="${USERFRONT_BOOT_BUILD_MARKER:-build/.userfront-boot-build-start}"
|
||||
USERFRONT_BOOT_LOG="${USERFRONT_BOOT_LOG:-build/userfront-boot-flutter.log}"
|
||||
USERFRONT_BOOT_LOG_PIPE="${USERFRONT_BOOT_LOG_PIPE:-build/userfront-boot-flutter.pipe}"
|
||||
|
||||
echo "[userfront-boot] removing stale build/web before flutter run" >&2
|
||||
rm -rf build/web
|
||||
mkdir -p "$(dirname "$USERFRONT_BOOT_BUILD_MARKER")"
|
||||
: > "$USERFRONT_BOOT_BUILD_MARKER"
|
||||
|
||||
warm_get() {
|
||||
path="$1"
|
||||
@@ -32,7 +40,7 @@ wait_for_userfront_build() {
|
||||
attempt=1
|
||||
|
||||
while [ "$attempt" -le "$USERFRONT_BOOT_WARMUP_ATTEMPTS" ]; do
|
||||
if [ -f "build/web/index.html" ]; then
|
||||
if [ -f "build/web/index.html" ] && [ "build/web/index.html" -nt "$USERFRONT_BOOT_BUILD_MARKER" ]; then
|
||||
return 0
|
||||
fi
|
||||
if ! kill -0 "$flutter_pid" 2>/dev/null; then
|
||||
@@ -47,50 +55,63 @@ wait_for_userfront_build() {
|
||||
return 1
|
||||
}
|
||||
|
||||
reset_userfront_service_worker() {
|
||||
wait_for_userfront_serve_log() {
|
||||
flutter_pid="$1"
|
||||
attempt=1
|
||||
|
||||
while [ "$attempt" -le "$USERFRONT_BOOT_WARMUP_ATTEMPTS" ]; do
|
||||
if [ -f "$USERFRONT_BOOT_LOG" ] && grep -Fq "lib/main.dart is being served at" "$USERFRONT_BOOT_LOG"; then
|
||||
return 0
|
||||
fi
|
||||
if ! kill -0 "$flutter_pid" 2>/dev/null; then
|
||||
echo "[userfront-boot] warmup skipped because flutter exited before serve log was ready" >&2
|
||||
return 1
|
||||
fi
|
||||
attempt=$((attempt + 1))
|
||||
sleep "$USERFRONT_BOOT_WARMUP_INTERVAL_SECONDS"
|
||||
done
|
||||
|
||||
echo "[userfront-boot] warmup skipped after ${USERFRONT_BOOT_WARMUP_ATTEMPTS} serve readiness attempts" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
disable_userfront_dev_service_worker() {
|
||||
cat > build/web/flutter_service_worker.js <<'EOF'
|
||||
self.addEventListener("install", (event) => {
|
||||
self.skipWaiting();
|
||||
});
|
||||
|
||||
self.addEventListener("activate", (event) => {
|
||||
event.waitUntil(
|
||||
(async () => {
|
||||
if (self.caches) {
|
||||
const keys = await self.caches.keys();
|
||||
await Promise.all(
|
||||
keys
|
||||
.filter(
|
||||
(key) =>
|
||||
key.indexOf("baron-userfront-") === 0 ||
|
||||
key.indexOf("flutter-app-cache") === 0,
|
||||
)
|
||||
.map((key) => self.caches.delete(key)),
|
||||
);
|
||||
}
|
||||
|
||||
await self.registration.unregister();
|
||||
|
||||
const clients = await self.clients.matchAll({
|
||||
type: "window",
|
||||
includeUncontrolled: true,
|
||||
});
|
||||
await Promise.all(clients.map((client) => client.navigate(client.url)));
|
||||
})(),
|
||||
);
|
||||
event.waitUntil(self.registration.unregister());
|
||||
});
|
||||
EOF
|
||||
}
|
||||
|
||||
warm_flutter_bootstrap_assets() {
|
||||
if [ ! -f build/web/flutter_bootstrap.js ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
grep -Eo 'main\.dart\.[^"]+\.(js|mjs|wasm)' build/web/flutter_bootstrap.js \
|
||||
| sort -u \
|
||||
| while IFS= read -r asset; do
|
||||
[ -n "$asset" ] || continue
|
||||
wget -qO- "http://127.0.0.1:${USERFRONT_INTERNAL_PORT}/${asset}" >/dev/null 2>&1 || \
|
||||
echo "[userfront-boot] warmup warning: failed to load /${asset}" >&2
|
||||
done
|
||||
}
|
||||
|
||||
warm_userfront_once() {
|
||||
flutter_pid="$1"
|
||||
attempt=1
|
||||
started_at="$(date +%s)"
|
||||
|
||||
if ! wait_for_userfront_serve_log "$flutter_pid"; then
|
||||
return 0
|
||||
fi
|
||||
if ! wait_for_userfront_build "$flutter_pid"; then
|
||||
return 0
|
||||
fi
|
||||
reset_userfront_service_worker
|
||||
disable_userfront_dev_service_worker
|
||||
|
||||
while [ "$attempt" -le "$USERFRONT_BOOT_WARMUP_ATTEMPTS" ]; do
|
||||
if wget -qO- "http://127.0.0.1:${USERFRONT_INTERNAL_PORT}/flutter_bootstrap.js" >/dev/null 2>&1; then
|
||||
@@ -109,6 +130,7 @@ warm_userfront_once() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
started_at="$(date +%s)"
|
||||
echo "[userfront-boot] one-shot warmup starting locales=\"${USERFRONT_BOOT_WARMUP_LOCALES}\" viewports=\"${USERFRONT_BOOT_WARMUP_VIEWPORTS}\"" >&2
|
||||
|
||||
for locale in $USERFRONT_BOOT_WARMUP_LOCALES; do
|
||||
@@ -120,8 +142,6 @@ warm_userfront_once() {
|
||||
for asset in \
|
||||
/ \
|
||||
/flutter_bootstrap.js \
|
||||
/main.dart.mjs \
|
||||
/main.dart.wasm \
|
||||
/canvaskit/skwasm.js \
|
||||
/canvaskit/skwasm.wasm \
|
||||
/canvaskit/skwasm_heavy.js \
|
||||
@@ -131,6 +151,7 @@ warm_userfront_once() {
|
||||
do
|
||||
wget -qO- "http://127.0.0.1:${USERFRONT_INTERNAL_PORT}${asset}" >/dev/null 2>&1 || true
|
||||
done
|
||||
warm_flutter_bootstrap_assets
|
||||
|
||||
finished_at="$(date +%s)"
|
||||
elapsed_seconds=$((finished_at - started_at))
|
||||
@@ -149,14 +170,28 @@ set -- flutter run \
|
||||
${USERFRONT_FLUTTER_RUN_FLAGS} \
|
||||
--no-web-resources-cdn
|
||||
|
||||
"$@" &
|
||||
mkdir -p "$(dirname "$USERFRONT_BOOT_LOG")"
|
||||
rm -f "$USERFRONT_BOOT_LOG" "$USERFRONT_BOOT_LOG_PIPE"
|
||||
mkfifo "$USERFRONT_BOOT_LOG_PIPE"
|
||||
tee "$USERFRONT_BOOT_LOG" < "$USERFRONT_BOOT_LOG_PIPE" &
|
||||
tee_pid="$!"
|
||||
|
||||
"$@" > "$USERFRONT_BOOT_LOG_PIPE" 2>&1 &
|
||||
flutter_pid="$!"
|
||||
|
||||
terminate() {
|
||||
kill "$flutter_pid" 2>/dev/null || true
|
||||
kill "$tee_pid" 2>/dev/null || true
|
||||
wait "$flutter_pid" 2>/dev/null || true
|
||||
wait "$tee_pid" 2>/dev/null || true
|
||||
rm -f "$USERFRONT_BOOT_LOG_PIPE"
|
||||
}
|
||||
|
||||
trap terminate INT TERM
|
||||
warm_userfront_once "$flutter_pid"
|
||||
set +e
|
||||
wait "$flutter_pid"
|
||||
flutter_status="$?"
|
||||
wait "$tee_pid" 2>/dev/null || true
|
||||
rm -f "$USERFRONT_BOOT_LOG_PIPE"
|
||||
exit "$flutter_status"
|
||||
|
||||
@@ -13,4 +13,23 @@ void main() {
|
||||
expect(source.contains('_loadAuditLogs('), isFalse);
|
||||
expect(source.contains('/api/v1/audit/auth/timeline'), isFalse);
|
||||
});
|
||||
|
||||
test('나의 App 현황 연동해지 버튼은 단일 라인 텍스트로 렌더링한다', () async {
|
||||
final screenFile = File(
|
||||
'lib/features/dashboard/presentation/dashboard_screen.dart',
|
||||
);
|
||||
final source = await screenFile.readAsString();
|
||||
final revokeLabelIndex = source.lastIndexOf(
|
||||
"tr('ui.userfront.dashboard.revoke.title')",
|
||||
);
|
||||
|
||||
expect(revokeLabelIndex, isNonNegative);
|
||||
final snippetStart = revokeLabelIndex > 500 ? revokeLabelIndex - 500 : 0;
|
||||
final snippetEnd = revokeLabelIndex + 300 < source.length
|
||||
? revokeLabelIndex + 300
|
||||
: source.length;
|
||||
final revokeButtonSource = source.substring(snippetStart, snippetEnd);
|
||||
|
||||
expect(revokeButtonSource, contains('_singleLineText('));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -31,6 +31,10 @@ void main() {
|
||||
}
|
||||
});
|
||||
|
||||
test('Korean linked app revoke action label stays unbreakable', () {
|
||||
expect(koStrings['ui.userfront.dashboard.revoke.title'], '연동해지');
|
||||
});
|
||||
|
||||
test(
|
||||
'TomlAssetLoader excludes non-userfront dictionaries at startup',
|
||||
() async {
|
||||
|
||||
Reference in New Issue
Block a user