mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-28 22:25:24 +00:00
feat: convert file manager into a plugin
This commit is contained in:
1 parent
b76da9ab52
commit
c85c1fdb86
259 files changed
+54155
-16791
No files matched your search
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Moves the three file-manager host columns into the file-manager plugin's
|
||||
* host-scope settings, before those columns are dropped from ssh_data.
|
||||
*
|
||||
* Idempotent: skips a host that already has a file-manager settings row, so
|
||||
* it is safe to run on every boot. Lossless: reads straight off the
|
||||
* still-present ssh_data columns, so it must run and finish before those
|
||||
* columns are ever dropped from schema.ts.
|
||||
*/
|
||||
|
||||
import { sql } from "drizzle-orm";
|
||||
import { databaseLogger } from "../logger.js";
|
||||
import { getDb } from "../../database/db/index.js";
|
||||
import { createCurrentPluginSettingsRepository } from "../../database/repositories/factory.js";
|
||||
|
||||
export interface FileManagerSettingsMigrationResult {
|
||||
moved: number;
|
||||
skipped: number;
|
||||
}
|
||||
|
||||
interface LegacyFileManagerRow {
|
||||
id: number;
|
||||
enable_file_manager: number | boolean | null;
|
||||
default_path: string | null;
|
||||
scp_legacy: number | boolean | null;
|
||||
}
|
||||
|
||||
export async function runFileManagerSettingsMigration(): Promise<FileManagerSettingsMigrationResult> {
|
||||
const result: FileManagerSettingsMigrationResult = { moved: 0, skipped: 0 };
|
||||
|
||||
try {
|
||||
const drizzleDb = getDb();
|
||||
// Raw SQL, not the typed schema: this runs once schema.ts has already
|
||||
// dropped these columns, so the query is the only thing left that still
|
||||
// knows they used to exist.
|
||||
const rows = await drizzleDb.all<LegacyFileManagerRow>(sql`
|
||||
SELECT id, enable_file_manager, default_path, scp_legacy
|
||||
FROM ssh_data
|
||||
WHERE enable_file_manager = false OR default_path IS NOT NULL
|
||||
OR scp_legacy = true
|
||||
`);
|
||||
|
||||
if (rows.length === 0) return result;
|
||||
|
||||
const pluginSettingsRepository = createCurrentPluginSettingsRepository();
|
||||
|
||||
for (const row of rows) {
|
||||
const scopeId = String(row.id);
|
||||
const existing = await pluginSettingsRepository.get(
|
||||
"file-manager",
|
||||
"host",
|
||||
scopeId,
|
||||
"enableFileManager",
|
||||
);
|
||||
if (existing && existing.value !== null) {
|
||||
result.skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
await pluginSettingsRepository.set(
|
||||
"file-manager",
|
||||
"host",
|
||||
scopeId,
|
||||
"enableFileManager",
|
||||
JSON.stringify(row.enable_file_manager !== false),
|
||||
);
|
||||
await pluginSettingsRepository.set(
|
||||
"file-manager",
|
||||
"host",
|
||||
scopeId,
|
||||
"defaultPath",
|
||||
JSON.stringify(row.default_path ?? null),
|
||||
);
|
||||
await pluginSettingsRepository.set(
|
||||
"file-manager",
|
||||
"host",
|
||||
scopeId,
|
||||
"scpLegacy",
|
||||
JSON.stringify(!!row.scp_legacy),
|
||||
);
|
||||
result.moved++;
|
||||
}
|
||||
|
||||
if (result.moved > 0) {
|
||||
databaseLogger.info(
|
||||
`Moved file manager settings for ${result.moved} host(s) into plugin settings`,
|
||||
{ operation: "file_manager_settings_migration", moved: result.moved },
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
// A failed migration must not stop the backend. Hosts simply keep
|
||||
// whatever file-manager settings they already had (none, on a fresh run).
|
||||
databaseLogger.warn("File manager settings migration failed", {
|
||||
operation: "file_manager_settings_migration",
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1,13 +1,35 @@
|
||||
import { sql } from "drizzle-orm";
|
||||
import {
|
||||
createCurrentDismissedAlertRepository,
|
||||
createCurrentFileManagerBookmarkRepository,
|
||||
createCurrentTransferRecentRepository,
|
||||
createCurrentUserDataExportRepository,
|
||||
createCurrentUserRepository,
|
||||
} from "../database/repositories/factory.js";
|
||||
import { getDb } from "../database/db/index.js";
|
||||
import { DataCrypto } from "./data-crypto.js";
|
||||
import { databaseLogger } from "./logger.js";
|
||||
|
||||
// The file manager plugin owns these tables now (p_file_manager_*); read by
|
||||
// raw SQL rather than importing plugin code into core.
|
||||
async function listFileManagerExportData(userId: string): Promise<{
|
||||
recent: unknown[];
|
||||
pinned: unknown[];
|
||||
shortcuts: unknown[];
|
||||
transferRecent: unknown[];
|
||||
}> {
|
||||
const db = getDb();
|
||||
const [recent, pinned, shortcuts, transferRecent] = await Promise.all([
|
||||
db.all(sql`SELECT * FROM p_file_manager_recent WHERE user_id = ${userId}`),
|
||||
db.all(sql`SELECT * FROM p_file_manager_pinned WHERE user_id = ${userId}`),
|
||||
db.all(
|
||||
sql`SELECT * FROM p_file_manager_shortcuts WHERE user_id = ${userId}`,
|
||||
),
|
||||
db.all(
|
||||
sql`SELECT * FROM p_file_manager_transfer_recent WHERE user_id = ${userId}`,
|
||||
),
|
||||
]);
|
||||
return { recent, pinned, shortcuts, transferRecent };
|
||||
}
|
||||
|
||||
interface UserExportData {
|
||||
version: string;
|
||||
exportedAt: string;
|
||||
@@ -90,19 +112,12 @@ class UserDataExport {
|
||||
: credentials;
|
||||
}
|
||||
|
||||
const [recentFiles, pinnedFiles, shortcuts, transferRecentData] =
|
||||
await Promise.all([
|
||||
createCurrentFileManagerBookmarkRepository().listRecentByUserId(
|
||||
userId,
|
||||
),
|
||||
createCurrentFileManagerBookmarkRepository().listPinnedByUserId(
|
||||
userId,
|
||||
),
|
||||
createCurrentFileManagerBookmarkRepository().listShortcutsByUserId(
|
||||
userId,
|
||||
),
|
||||
createCurrentTransferRecentRepository().listByUserId(userId),
|
||||
]);
|
||||
const {
|
||||
recent: recentFiles,
|
||||
pinned: pinnedFiles,
|
||||
shortcuts,
|
||||
transferRecent: transferRecentData,
|
||||
} = await listFileManagerExportData(userId);
|
||||
|
||||
const alerts =
|
||||
await createCurrentDismissedAlertRepository().listByUserId(userId);
|
||||
|
||||
Reference in new issue
Block a user