mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-03-19 15:18:02 -04:00
Fix migration tool params called from install.sh (#190)
This commit is contained in:
16
install.sh
16
install.sh
@@ -1659,7 +1659,7 @@ handle_migrate_db() {
|
||||
SQLITE_DB_NAME=$(basename "$SQLITE_DB_ABS")
|
||||
|
||||
# Get PostgreSQL password from .env file
|
||||
POSTGRES_PASSWORD=$(grep "^POSTGRES_PASSWORD=" "$ENV_FILE" | cut -d '=' -f2)
|
||||
POSTGRES_PASSWORD=$(grep "^POSTGRES_PASSWORD=" "$ENV_FILE" | cut -d= -f2-)
|
||||
if [ -z "$POSTGRES_PASSWORD" ]; then
|
||||
printf "${RED}Error: POSTGRES_PASSWORD not found in .env file${NC}\n"
|
||||
exit 1
|
||||
@@ -1670,9 +1670,17 @@ handle_migrate_db() {
|
||||
NETWORK_NAME=$(echo "$NETWORK_NAME" | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
printf "\n${YELLOW}Warning: This will migrate data from your SQLite database to PostgreSQL.${NC}\n"
|
||||
printf "\n"
|
||||
printf "This is a one-time operation necessary when upgrading from <= 0.9.x to 0.10.0+ and only needs to be run once.\n"
|
||||
printf "\n"
|
||||
printf "Source database: ${CYAN}${SQLITE_DB_ABS}${NC}\n"
|
||||
printf "Target: PostgreSQL database (using connection string from docker-compose.yml)\n"
|
||||
printf "Make sure you have backed up your data before proceeding.\n"
|
||||
|
||||
printf "\n${RED}WARNING: This operation will DELETE ALL EXISTING DATA in the PostgreSQL database.${NC}\n"
|
||||
printf "${RED}Only proceed if you understand that any current PostgreSQL data will be permanently lost.${NC}\n"
|
||||
printf "\n"
|
||||
|
||||
read -p "Continue with migration? [y/N]: " confirm
|
||||
if [[ ! $confirm =~ ^[Yy]$ ]]; then
|
||||
printf "${YELLOW}Migration cancelled.${NC}\n"
|
||||
@@ -1705,14 +1713,14 @@ handle_migrate_db() {
|
||||
docker run --rm \
|
||||
--network="${NETWORK_NAME}" \
|
||||
-v "${SQLITE_DB_DIR}:/sqlite" \
|
||||
${GITHUB_CONTAINER_REGISTRY}-installcli migrate-sqlite "/sqlite/${SQLITE_DB_NAME}" "Host=postgres;Database=aliasvault;Username=aliasvault;Password=${POSTGRES_PASSWORD}"
|
||||
installcli migrate-sqlite "/sqlite/${SQLITE_DB_NAME}" "Host=postgres;Database=aliasvault;Username=aliasvault;Password=${POSTGRES_PASSWORD}"
|
||||
else
|
||||
# Run migration with volume mount using pre-built image
|
||||
docker run --rm \
|
||||
--network="${NETWORK_NAME}" \
|
||||
-v "${SQLITE_DB_DIR}:/sqlite" \
|
||||
installcli migrate-sqlite "/sqlite/${SQLITE_DB_NAME}" "Host=postgres;Database=aliasvault;Username=aliasvault;Password=${POSTGRES_PASSWORD}"
|
||||
fi
|
||||
${GITHUB_CONTAINER_REGISTRY}-installcli:0.10.0 migrate-sqlite "/sqlite/${SQLITE_DB_NAME}" "Host=postgres;Database=aliasvault;Username=aliasvault;Password=${POSTGRES_PASSWORD}"
|
||||
fi
|
||||
|
||||
printf "${GREEN}> Check migration output above for details.${NC}\n"
|
||||
}
|
||||
|
||||
@@ -104,21 +104,40 @@ public partial class Program
|
||||
var optionsBuilderSqlite = new DbContextOptionsBuilder<AliasServerDbContext>()
|
||||
.UseSqlite(sqliteConnString);
|
||||
|
||||
var optionsBuilderPg = new DbContextOptionsBuilder<AliasServerDbContext>()
|
||||
.UseNpgsql(pgConnString);
|
||||
|
||||
// Make sure sqlite is on latest version migration
|
||||
Console.WriteLine("Update sqlite database to latest version...");
|
||||
await using var sqliteContext = new AliasServerDbContextSqlite(optionsBuilderSqlite.Options);
|
||||
await sqliteContext.Database.MigrateAsync();
|
||||
Console.WriteLine("Updating finished.");
|
||||
|
||||
var optionsBuilderPg = new DbContextOptionsBuilder<AliasServerDbContext>()
|
||||
.UseNpgsql(pgConnString);
|
||||
|
||||
// Make sure postgres is on latest version migration
|
||||
Console.WriteLine("Update postgres database to latest version...");
|
||||
await using var pgContext = new AliasServerDbContextPostgresql(optionsBuilderPg.Options);
|
||||
await pgContext.Database.MigrateAsync();
|
||||
Console.WriteLine("Updating finished.");
|
||||
|
||||
Console.WriteLine("Truncating existing tables in reverse dependency order...");
|
||||
|
||||
// Truncate tables in reverse order of dependencies
|
||||
await TruncateTable(pgContext.EmailAttachments, "EmailAttachments");
|
||||
await TruncateTable(pgContext.Emails, "Emails");
|
||||
await TruncateTable(pgContext.UserTokens, "UserTokens");
|
||||
await TruncateTable(pgContext.UserRoles, "UserRoles");
|
||||
await TruncateTable(pgContext.UserLogin, "UserLogins");
|
||||
await TruncateTable(pgContext.UserEmailClaims, "UserEmailClaims");
|
||||
await TruncateTable(pgContext.Vaults, "Vaults");
|
||||
await TruncateTable(pgContext.UserEncryptionKeys, "UserEncryptionKeys");
|
||||
await TruncateTable(pgContext.AliasVaultUserRefreshTokens, "AliasVaultUserRefreshTokens");
|
||||
await TruncateTable(pgContext.AuthLogs, "AuthLogs");
|
||||
await TruncateTable(pgContext.DataProtectionKeys, "DataProtectionKeys");
|
||||
await TruncateTable(pgContext.ServerSettings, "ServerSettings");
|
||||
await TruncateTable(pgContext.AliasVaultUsers, "AliasVaultUsers");
|
||||
await TruncateTable(pgContext.AliasVaultRoles, "AliasVaultRoles");
|
||||
await TruncateTable(pgContext.AdminUsers, "AdminUsers");
|
||||
|
||||
Console.WriteLine("Starting content migration...");
|
||||
|
||||
// First, migrate tables without foreign key dependencies
|
||||
@@ -155,6 +174,25 @@ public partial class Program
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Truncates a table in the PostgreSQL database.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The entity type of the table being truncated.</typeparam>
|
||||
/// <param name="table">The database table to truncate.</param>
|
||||
/// <param name="tableName">The name of the table being truncated (for logging purposes).</param>
|
||||
/// <returns>A task representing the asynchronous truncation operation.</returns>
|
||||
private static async Task TruncateTable<T>(DbSet<T> table, string tableName)
|
||||
where T : class
|
||||
{
|
||||
Console.WriteLine($"Truncating table {tableName}...");
|
||||
var count = await table.CountAsync();
|
||||
if (count > 0)
|
||||
{
|
||||
await table.ExecuteDeleteAsync();
|
||||
Console.WriteLine($"Removed {count} records from {tableName}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Migrates data from one database table to another, handling the transfer in batches.
|
||||
/// </summary>
|
||||
@@ -184,6 +222,15 @@ public partial class Program
|
||||
|
||||
if (items.Count > 0)
|
||||
{
|
||||
// Remove any existing entries in the destination table
|
||||
var existingEntries = await destination.ToListAsync();
|
||||
if (existingEntries.Any())
|
||||
{
|
||||
Console.WriteLine($"Removing {existingEntries.Count} existing entries from {tableName}...");
|
||||
destination.RemoveRange(existingEntries);
|
||||
await destinationContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
const int batchSize = 30;
|
||||
foreach (var batch in items.Chunk(batchSize))
|
||||
{
|
||||
@@ -220,9 +267,9 @@ public partial class Program
|
||||
}
|
||||
|
||||
// Ensure that the amount of records in the source and destination tables match
|
||||
if (await source.CountAsync() != await destination.CountAsync())
|
||||
if (await source.CountAsync() > await destination.CountAsync())
|
||||
{
|
||||
throw new ArgumentException($"The amount of records in the source and destination tables do not match. Check if the migration is working correctly.");
|
||||
throw new ArgumentException($"The amount of records in the source is greater than the destination. Check if the migration is working correctly.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user