fix: skip existing hosts and credentials during JSON import (#485)
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 was merged in pull request #485.
This commit is contained in:
@@ -177,15 +177,33 @@ class UserDataImport {
|
||||
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 = {
|
||||
...host,
|
||||
id: tempId,
|
||||
userId: targetUserId,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
|
||||
if (existing.length === 0) {
|
||||
newHostData.createdAt = new Date().toISOString();
|
||||
}
|
||||
|
||||
let processedHostData = newHostData;
|
||||
if (options.userDataKey) {
|
||||
processedHostData = DataCrypto.encryptRecord(
|
||||
@@ -198,9 +216,18 @@ class UserDataImport {
|
||||
|
||||
delete processedHostData.id;
|
||||
|
||||
await getDb()
|
||||
.insert(sshData)
|
||||
.values(processedHostData as unknown as typeof sshData.$inferInsert);
|
||||
if (existing.length > 0 && options.replaceExisting) {
|
||||
await getDb()
|
||||
.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++;
|
||||
} catch (error) {
|
||||
errors.push(
|
||||
@@ -233,17 +260,33 @@ class UserDataImport {
|
||||
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 = {
|
||||
...credential,
|
||||
id: tempCredId,
|
||||
userId: targetUserId,
|
||||
usageCount: 0,
|
||||
lastUsed: null,
|
||||
createdAt: 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;
|
||||
if (options.userDataKey) {
|
||||
processedCredentialData = DataCrypto.encryptRecord(
|
||||
@@ -256,11 +299,20 @@ class UserDataImport {
|
||||
|
||||
delete processedCredentialData.id;
|
||||
|
||||
await getDb()
|
||||
.insert(sshCredentials)
|
||||
.values(
|
||||
processedCredentialData as unknown as typeof sshCredentials.$inferInsert,
|
||||
);
|
||||
if (existing.length > 0 && options.replaceExisting) {
|
||||
await getDb()
|
||||
.update(sshCredentials)
|
||||
.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++;
|
||||
} catch (error) {
|
||||
errors.push(
|
||||
|
||||
Reference in New Issue
Block a user