diff --git a/.dockerignore b/.dockerignore index 139605bf..986e896c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -51,9 +51,6 @@ repo-images/ # Uploads directory uploads/ -# Fonts (Electron-only, not needed for Docker) -public/fonts/ - # Logs logs *.log diff --git a/docker/Dockerfile b/docker/Dockerfile index c90afc49..6f2b9afe 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -67,6 +67,7 @@ COPY docker/nginx.conf /etc/nginx/nginx.conf COPY docker/nginx-https.conf /etc/nginx/nginx-https.conf COPY --from=frontend-builder /app/dist /usr/share/nginx/html COPY --from=frontend-builder /app/src/locales /usr/share/nginx/html/locales +COPY --from=frontend-builder /app/public/fonts /usr/share/nginx/html/fonts RUN chown -R nginx:nginx /usr/share/nginx/html COPY --from=production-deps /app/node_modules /app/node_modules diff --git a/src/backend/database/db/index.ts b/src/backend/database/db/index.ts index 47512e3e..9a52e4f4 100644 --- a/src/backend/database/db/index.ts +++ b/src/backend/database/db/index.ts @@ -422,11 +422,6 @@ const migrateSchema = () => { addColumnIfNotExists("users", "totp_enabled", "INTEGER NOT NULL DEFAULT 0"); addColumnIfNotExists("users", "totp_backup_codes", "TEXT"); - // Password recovery fields (UX compromise - breaks zero-trust for usability) - addColumnIfNotExists("users", "recovery_dek", "TEXT"); - addColumnIfNotExists("users", "backup_encrypted_dek", "TEXT"); - addColumnIfNotExists("users", "zero_trust_mode", "INTEGER NOT NULL DEFAULT 0"); - addColumnIfNotExists("ssh_data", "name", "TEXT"); addColumnIfNotExists("ssh_data", "folder", "TEXT"); addColumnIfNotExists("ssh_data", "tags", "TEXT"); diff --git a/src/backend/database/db/schema.ts b/src/backend/database/db/schema.ts index 16cdac05..8e0f8e79 100644 --- a/src/backend/database/db/schema.ts +++ b/src/backend/database/db/schema.ts @@ -23,13 +23,6 @@ export const users = sqliteTable("users", { .notNull() .default(false), totp_backup_codes: text("totp_backup_codes"), - - // Password recovery fields (breaks zero-trust for UX) - recovery_dek: text("recovery_dek"), // Recovery DEK stored in plaintext - backup_encrypted_dek: text("backup_encrypted_dek"), // DEK encrypted with recovery DEK - zero_trust_mode: integer("zero_trust_mode", { mode: "boolean" }) - .notNull() - .default(false), // false=compromise mode, true=zero-trust mode }); export const settings = sqliteTable("settings", { diff --git a/src/ui/Desktop/Apps/Terminal/Terminal.tsx b/src/ui/Desktop/Apps/Terminal/Terminal.tsx index 65b65542..d6a61d57 100644 --- a/src/ui/Desktop/Apps/Terminal/Terminal.tsx +++ b/src/ui/Desktop/Apps/Terminal/Terminal.tsx @@ -558,7 +558,7 @@ export const Terminal = forwardRef(function SSHTerminal( scrollback: 10000, fontSize: 14, fontFamily: - '"JetBrains Mono Nerd Font", "MesloLGS NF", "FiraCode Nerd Font", "Cascadia Code", "JetBrains Mono", Consolas, "Courier New", monospace', + '"JetBrains Mono Nerd Font", "MesloLGS NF", "FiraCode Nerd Font", "Cascadia Code", "JetBrains Mono", "SF Mono", Monaco, Consolas, "Liberation Mono", "Courier New", monospace', theme: { background: "#18181b", foreground: "#f7f7f7" }, allowTransparency: true, convertEol: true, @@ -791,7 +791,7 @@ const style = document.createElement("style"); style.innerHTML = ` @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap'); -/* Load NerdFonts locally */ +/* Load NerdFonts locally with fallback handling */ @font-face { font-family: 'JetBrains Mono Nerd Font'; src: url('./fonts/JetBrainsMonoNerdFont-Regular.ttf') format('truetype'); @@ -816,6 +816,15 @@ style.innerHTML = ` font-display: swap; } +/* Fallback fonts for when custom fonts fail to load */ +@font-face { + font-family: 'Terminal Fallback'; + src: local('SF Mono'), local('Monaco'), local('Consolas'), local('Liberation Mono'), local('Courier New'); + font-weight: normal; + font-style: normal; + font-display: swap; +} + .xterm .xterm-viewport::-webkit-scrollbar { width: 8px; background: transparent; @@ -840,7 +849,7 @@ style.innerHTML = ` } .xterm .xterm-screen { - font-family: 'JetBrains Mono Nerd Font', 'MesloLGS NF', 'FiraCode Nerd Font', 'Cascadia Code', 'JetBrains Mono', Consolas, "Courier New", monospace !important; + font-family: 'JetBrains Mono Nerd Font', 'MesloLGS NF', 'FiraCode Nerd Font', 'Cascadia Code', 'JetBrains Mono', 'SF Mono', Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace !important; font-variant-ligatures: contextual; } diff --git a/src/ui/Mobile/Apps/Terminal/Terminal.tsx b/src/ui/Mobile/Apps/Terminal/Terminal.tsx index 2c1a59a3..b4184fa7 100644 --- a/src/ui/Mobile/Apps/Terminal/Terminal.tsx +++ b/src/ui/Mobile/Apps/Terminal/Terminal.tsx @@ -226,7 +226,7 @@ export const Terminal = forwardRef(function SSHTerminal( scrollback: 10000, fontSize: 14, fontFamily: - '"JetBrains Mono Nerd Font", "MesloLGS NF", "FiraCode Nerd Font", "Cascadia Code", "JetBrains Mono", Consolas, "Courier New", monospace', + '"JetBrains Mono Nerd Font", "MesloLGS NF", "FiraCode Nerd Font", "Cascadia Code", "JetBrains Mono", "SF Mono", Monaco, Consolas, "Liberation Mono", "Courier New", monospace', theme: { background: "#09090b", foreground: "#f7f7f7" }, allowTransparency: true, convertEol: true, @@ -402,7 +402,7 @@ const style = document.createElement("style"); style.innerHTML = ` @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap'); -/* Load NerdFonts locally */ +/* Load NerdFonts locally with fallback handling */ @font-face { font-family: 'JetBrains Mono Nerd Font'; src: url('./fonts/JetBrainsMonoNerdFont-Regular.ttf') format('truetype'); @@ -427,6 +427,15 @@ style.innerHTML = ` font-display: swap; } +/* Fallback fonts for when custom fonts fail to load */ +@font-face { + font-family: 'Terminal Fallback'; + src: local('SF Mono'), local('Monaco'), local('Consolas'), local('Liberation Mono'), local('Courier New'); + font-weight: normal; + font-style: normal; + font-display: swap; +} + .xterm .xterm-viewport::-webkit-scrollbar { width: 8px; background: transparent; @@ -451,7 +460,7 @@ style.innerHTML = ` } .xterm .xterm-screen { - font-family: 'JetBrains Mono Nerd Font', 'MesloLGS NF', 'FiraCode Nerd Font', 'Cascadia Code', 'JetBrains Mono', Consolas, "Courier New", monospace !important; + font-family: 'JetBrains Mono Nerd Font', 'MesloLGS NF', 'FiraCode Nerd Font', 'Cascadia Code', 'JetBrains Mono', 'SF Mono', Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace !important; font-variant-ligatures: contextual; } diff --git a/src/ui/main-axios.ts b/src/ui/main-axios.ts index 8904164b..9908bba5 100644 --- a/src/ui/main-axios.ts +++ b/src/ui/main-axios.ts @@ -1604,49 +1604,6 @@ export async function getUserCount(): Promise { } } -// ===== New Recovery API functions (UX compromise) ===== - -export async function requestRecoveryCode(username: string): Promise { - try { - const response = await authApi.post("/users/recovery/request", { username }); - return response.data; - } catch (error) { - handleApiError(error, "request recovery code"); - } -} - -export async function verifyRecoveryCode( - username: string, - code: string, -): Promise { - try { - const response = await authApi.post("/users/recovery/verify", { - username, - code, - }); - return response.data; - } catch (error) { - handleApiError(error, "verify recovery code"); - } -} - -export async function loginWithRecovery( - username: string, - tempToken: string, -): Promise { - try { - const response = await authApi.post("/users/recovery/login", { - username, - tempToken, - }); - return response.data; - } catch (error) { - handleApiError(error, "recovery login"); - } -} - -// ===== Legacy password reset functions (deprecated) ===== - export async function initiatePasswordReset(username: string): Promise { try { const response = await authApi.post("/users/initiate-reset", { username });