fix: skip existing hosts and credentials during JSON import
Added duplicate detection for SSH hosts (by ip+port+username) and credentials (by name) during import. Existing items are now skipped by default, or updated if replaceExisting option is enabled. This matches the existing behavior of importDismissedAlerts. Fixes #389
This commit is contained in:
@@ -177,15 +177,33 @@ class UserDataImport {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const tempId = `import-ssh-${targetUserId}-${Date.now()}-${imported}`;
|
const existing = await getDb()
|
||||||
|
.select()
|
||||||
|
.from(sshData)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(sshData.userId, targetUserId),
|
||||||
|
eq(sshData.ip, host.ip as string),
|
||||||
|
eq(sshData.port, host.port as number),
|
||||||
|
eq(sshData.username, host.username as string),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (existing.length > 0 && !options.replaceExisting) {
|
||||||
|
skipped++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const newHostData = {
|
const newHostData = {
|
||||||
...host,
|
...host,
|
||||||
id: tempId,
|
|
||||||
userId: targetUserId,
|
userId: targetUserId,
|
||||||
createdAt: new Date().toISOString(),
|
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (existing.length === 0) {
|
||||||
|
newHostData.createdAt = new Date().toISOString();
|
||||||
|
}
|
||||||
|
|
||||||
let processedHostData = newHostData;
|
let processedHostData = newHostData;
|
||||||
if (options.userDataKey) {
|
if (options.userDataKey) {
|
||||||
processedHostData = DataCrypto.encryptRecord(
|
processedHostData = DataCrypto.encryptRecord(
|
||||||
@@ -198,9 +216,18 @@ class UserDataImport {
|
|||||||
|
|
||||||
delete processedHostData.id;
|
delete processedHostData.id;
|
||||||
|
|
||||||
await getDb()
|
if (existing.length > 0 && options.replaceExisting) {
|
||||||
.insert(sshData)
|
await getDb()
|
||||||
.values(processedHostData as unknown as typeof sshData.$inferInsert);
|
.update(sshData)
|
||||||
|
.set(processedHostData as unknown as typeof sshData.$inferInsert)
|
||||||
|
.where(eq(sshData.id, existing[0].id));
|
||||||
|
} else {
|
||||||
|
await getDb()
|
||||||
|
.insert(sshData)
|
||||||
|
.values(
|
||||||
|
processedHostData as unknown as typeof sshData.$inferInsert,
|
||||||
|
);
|
||||||
|
}
|
||||||
imported++;
|
imported++;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
errors.push(
|
errors.push(
|
||||||
@@ -233,17 +260,33 @@ class UserDataImport {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const tempCredId = `import-cred-${targetUserId}-${Date.now()}-${imported}`;
|
const existing = await getDb()
|
||||||
|
.select()
|
||||||
|
.from(sshCredentials)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(sshCredentials.userId, targetUserId),
|
||||||
|
eq(sshCredentials.name, credential.name as string),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (existing.length > 0 && !options.replaceExisting) {
|
||||||
|
skipped++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const newCredentialData = {
|
const newCredentialData = {
|
||||||
...credential,
|
...credential,
|
||||||
id: tempCredId,
|
|
||||||
userId: targetUserId,
|
userId: targetUserId,
|
||||||
usageCount: 0,
|
|
||||||
lastUsed: null,
|
|
||||||
createdAt: new Date().toISOString(),
|
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (existing.length === 0) {
|
||||||
|
newCredentialData.usageCount = 0;
|
||||||
|
newCredentialData.lastUsed = null;
|
||||||
|
newCredentialData.createdAt = new Date().toISOString();
|
||||||
|
}
|
||||||
|
|
||||||
let processedCredentialData = newCredentialData;
|
let processedCredentialData = newCredentialData;
|
||||||
if (options.userDataKey) {
|
if (options.userDataKey) {
|
||||||
processedCredentialData = DataCrypto.encryptRecord(
|
processedCredentialData = DataCrypto.encryptRecord(
|
||||||
@@ -256,11 +299,20 @@ class UserDataImport {
|
|||||||
|
|
||||||
delete processedCredentialData.id;
|
delete processedCredentialData.id;
|
||||||
|
|
||||||
await getDb()
|
if (existing.length > 0 && options.replaceExisting) {
|
||||||
.insert(sshCredentials)
|
await getDb()
|
||||||
.values(
|
.update(sshCredentials)
|
||||||
processedCredentialData as unknown as typeof sshCredentials.$inferInsert,
|
.set(
|
||||||
);
|
processedCredentialData as unknown as typeof sshCredentials.$inferInsert,
|
||||||
|
)
|
||||||
|
.where(eq(sshCredentials.id, existing[0].id));
|
||||||
|
} else {
|
||||||
|
await getDb()
|
||||||
|
.insert(sshCredentials)
|
||||||
|
.values(
|
||||||
|
processedCredentialData as unknown as typeof sshCredentials.$inferInsert,
|
||||||
|
);
|
||||||
|
}
|
||||||
imported++;
|
imported++;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
errors.push(
|
errors.push(
|
||||||
|
|||||||
Reference in New Issue
Block a user