diff --git a/src/backend/database/db/index.ts b/src/backend/database/db/index.ts index dff125c8..b919c931 100644 --- a/src/backend/database/db/index.ts +++ b/src/backend/database/db/index.ts @@ -210,6 +210,8 @@ async function initializeCompleteDatabase(): Promise { stats_config TEXT, docker_config TEXT, terminal_config TEXT, + notes TEXT, + expiration_date TEXT, use_socks5 INTEGER, socks5_host TEXT, socks5_port INTEGER, @@ -575,6 +577,9 @@ const migrateSchema = () => { ); addColumnIfNotExists("ssh_data", "docker_config", "TEXT"); + addColumnIfNotExists("ssh_data", "notes", "TEXT"); + addColumnIfNotExists("ssh_data", "expiration_date", "TEXT"); + // SOCKS5 Proxy columns addColumnIfNotExists("ssh_data", "use_socks5", "INTEGER"); addColumnIfNotExists("ssh_data", "socks5_host", "TEXT"); diff --git a/src/backend/database/db/schema.ts b/src/backend/database/db/schema.ts index 39c091e6..52dfcc45 100644 --- a/src/backend/database/db/schema.ts +++ b/src/backend/database/db/schema.ts @@ -93,6 +93,8 @@ export const sshData = sqliteTable("ssh_data", { statsConfig: text("stats_config"), terminalConfig: text("terminal_config"), quickActions: text("quick_actions"), + notes: text("notes"), + expirationDate: text("expiration_date"), useSocks5: integer("use_socks5", { mode: "boolean" }), socks5Host: text("socks5_host"), diff --git a/src/backend/database/routes/ssh.ts b/src/backend/database/routes/ssh.ts index c3e5510c..9d299aa8 100644 --- a/src/backend/database/routes/ssh.ts +++ b/src/backend/database/routes/ssh.ts @@ -14,7 +14,17 @@ import { hostAccess, userRoles, } from "../db/schema.js"; -import { eq, and, desc, isNotNull, or, isNull, gte, sql, inArray } from "drizzle-orm"; +import { + eq, + and, + desc, + isNotNull, + or, + isNull, + gte, + sql, + inArray, +} from "drizzle-orm"; import type { Request, Response } from "express"; import multer from "multer"; import { sshLogger } from "../../utils/logger.js"; @@ -245,12 +255,15 @@ router.post( statsConfig, terminalConfig, forceKeyboardInteractive, + notes, + expirationDate, useSocks5, socks5Host, socks5Port, socks5Username, socks5Password, socks5ProxyChain, + overrideCredentialUsername, } = hostData; console.log("POST /db/ssh - Received SOCKS5 data:", { @@ -285,6 +298,7 @@ router.post( username, authType: effectiveAuthType, credentialId: credentialId || null, + overrideCredentialUsername: overrideCredentialUsername ? 1 : 0, pin: pin ? 1 : 0, enableTerminal: enableTerminal ? 1 : 0, enableTunnel: enableTunnel ? 1 : 0, @@ -301,12 +315,16 @@ router.post( statsConfig: statsConfig ? JSON.stringify(statsConfig) : null, terminalConfig: terminalConfig ? JSON.stringify(terminalConfig) : null, forceKeyboardInteractive: forceKeyboardInteractive ? "true" : "false", + notes: notes || null, + expirationDate: expirationDate || null, useSocks5: useSocks5 ? 1 : 0, socks5Host: socks5Host || null, socks5Port: socks5Port || null, socks5Username: socks5Username || null, socks5Password: socks5Password || null, - socks5ProxyChain: socks5ProxyChain ? JSON.stringify(socks5ProxyChain) : null, + socks5ProxyChain: socks5ProxyChain + ? JSON.stringify(socks5ProxyChain) + : null, }; if (effectiveAuthType === "password") { @@ -489,13 +507,20 @@ router.put( statsConfig, terminalConfig, forceKeyboardInteractive, + notes, + expirationDate, useSocks5, socks5Host, socks5Port, socks5Username, socks5Password, socks5ProxyChain, + overrideCredentialUsername, } = hostData; + + // Temporary logging to debug notes and expirationDate + console.log("DEBUG - Update host data:", { notes, expirationDate }); + if ( !isNonEmptyString(userId) || !isNonEmptyString(ip) || @@ -523,6 +548,7 @@ router.put( username, authType: effectiveAuthType, credentialId: credentialId || null, + overrideCredentialUsername: overrideCredentialUsername ? 1 : 0, pin: pin ? 1 : 0, enableTerminal: enableTerminal ? 1 : 0, enableTunnel: enableTunnel ? 1 : 0, @@ -539,12 +565,16 @@ router.put( statsConfig: statsConfig ? JSON.stringify(statsConfig) : null, terminalConfig: terminalConfig ? JSON.stringify(terminalConfig) : null, forceKeyboardInteractive: forceKeyboardInteractive ? "true" : "false", + notes: notes || null, + expirationDate: expirationDate || null, useSocks5: useSocks5 ? 1 : 0, socks5Host: socks5Host || null, socks5Port: socks5Port || null, socks5Username: socks5Username || null, socks5Password: socks5Password || null, - socks5ProxyChain: socks5ProxyChain ? JSON.stringify(socks5ProxyChain) : null, + socks5ProxyChain: socks5ProxyChain + ? JSON.stringify(socks5ProxyChain) + : null, }; if (effectiveAuthType === "password") { @@ -742,6 +772,8 @@ router.get( credentialId: sshData.credentialId, overrideCredentialUsername: sshData.overrideCredentialUsername, quickActions: sshData.quickActions, + notes: sshData.notes, + expirationDate: sshData.expirationDate, // Shared access info isShared: sql`${hostAccess.id} IS NOT NULL`, @@ -755,12 +787,11 @@ router.get( eq(hostAccess.hostId, sshData.id), or( eq(hostAccess.userId, userId), - roleIds.length > 0 ? inArray(hostAccess.roleId, roleIds) : sql`false`, - ), - or( - isNull(hostAccess.expiresAt), - gte(hostAccess.expiresAt, now), + roleIds.length > 0 + ? inArray(hostAccess.roleId, roleIds) + : sql`false`, ), + or(isNull(hostAccess.expiresAt), gte(hostAccess.expiresAt, now)), ), ) .where( @@ -769,10 +800,7 @@ router.get( and( // Shared to user directly (not expired) eq(hostAccess.userId, userId), - or( - isNull(hostAccess.expiresAt), - gte(hostAccess.expiresAt, now), - ), + or(isNull(hostAccess.expiresAt), gte(hostAccess.expiresAt, now)), ), roleIds.length > 0 ? and( diff --git a/src/components/ui/textarea.tsx b/src/components/ui/textarea.tsx index 6c816b16..a5c84926 100644 --- a/src/components/ui/textarea.tsx +++ b/src/components/ui/textarea.tsx @@ -9,7 +9,7 @@ const Textarea = React.forwardRef( return (