From 1e06e2bd4b7e034ed43187817fbdbb07865da3b3 Mon Sep 17 00:00:00 2001
From: Arunavo Ray
Date: Sat, 19 Jul 2025 00:28:12 +0530
Subject: [PATCH] Remove Auto Migrate
---
README.md | 4 +-
UPGRADE.md | 74 +++++++++++++++
docker-entrypoint.sh | 77 +--------------
package.json | 2 -
scripts/migrate-better-auth.ts | 100 --------------------
scripts/migrate-to-better-auth.ts | 87 -----------------
scripts/migrate-tokens-encryption.ts | 135 ---------------------------
7 files changed, 77 insertions(+), 402 deletions(-)
create mode 100644 UPGRADE.md
delete mode 100644 scripts/migrate-better-auth.ts
delete mode 100644 scripts/migrate-to-better-auth.ts
delete mode 100644 scripts/migrate-tokens-encryption.ts
diff --git a/README.md b/README.md
index e0916d5..cb92fda 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@
> [!IMPORTANT]
-> **Upgrading to v3?** Please read the [Migration Guide](MIGRATION_GUIDE.md) for breaking changes and upgrade instructions.
+> **Upgrading to v3?** v3 requires a fresh start with a new data volume. Please read the [Upgrade Guide](UPGRADE.md) for instructions.
## š Quick Start
@@ -35,7 +35,7 @@ First user signup becomes admin. Configure GitHub and Gitea through the web inte
- š Mirror public, private, and starred GitHub repos to Gitea
- š¢ Mirror entire organizations with flexible strategies
- šÆ Custom destination control for repos and organizations
-- š Secure authentication with JWT tokens
+- š Secure authentication with Better Auth (email/password, SSO, OIDC)
- š Real-time dashboard with activity logs
- ā±ļø Scheduled automatic mirroring
- š³ Dockerized with multi-arch support (AMD64/ARM64)
diff --git a/UPGRADE.md b/UPGRADE.md
new file mode 100644
index 0000000..a08df45
--- /dev/null
+++ b/UPGRADE.md
@@ -0,0 +1,74 @@
+# Upgrade Guide
+
+## Upgrading to v3.0
+
+> **ā ļø IMPORTANT**: v3.0 requires a fresh start. There is no automated migration from v2.x to v3.0.
+
+### Why No Migration?
+
+v3.0 introduces fundamental changes to the application architecture:
+- **Authentication**: Switched from JWT to Better Auth
+- **Database**: Now uses Drizzle ORM with proper migrations
+- **Security**: All tokens are now encrypted
+- **Features**: Added SSO support and OIDC provider functionality
+
+Due to these extensive changes, we recommend starting fresh with v3.0 for the best experience.
+
+### Upgrade Steps
+
+1. **Stop your v2.x container**
+ ```bash
+ docker stop gitea-mirror
+ docker rm gitea-mirror
+ ```
+
+2. **Backup your v2.x data (optional)**
+ ```bash
+ # If you want to keep your v2 data for reference
+ docker run --rm -v gitea-mirror-data:/data -v $(pwd):/backup alpine tar czf /backup/gitea-mirror-v2-backup.tar.gz -C /data .
+ ```
+
+3. **Create a new volume for v3**
+ ```bash
+ docker volume create gitea-mirror-v3-data
+ ```
+
+4. **Run v3 with the new volume**
+ ```bash
+ docker run -d \
+ --name gitea-mirror \
+ -p 4321:4321 \
+ -v gitea-mirror-v3-data:/app/data \
+ -e BETTER_AUTH_SECRET=your-secret-key \
+ -e ENCRYPTION_SECRET=your-encryption-key \
+ arunavo4/gitea-mirror:latest
+ ```
+
+5. **Set up your configuration again**
+ - Navigate to http://localhost:4321
+ - Create a new admin account
+ - Re-enter your GitHub and Gitea credentials
+ - Configure your mirror settings
+
+### What Happens to My Existing Mirrors?
+
+Your existing mirrors in Gitea are **not affected**. The application will:
+- Recognize existing repositories when you re-import
+- Skip creating duplicates
+- Resume normal mirror operations
+
+### Environment Variable Changes
+
+v3.0 uses different environment variables:
+
+| v2.x | v3.0 | Notes |
+|------|------|-------|
+| `JWT_SECRET` | `BETTER_AUTH_SECRET` | Required for session management |
+| - | `ENCRYPTION_SECRET` | New - required for token encryption |
+
+### Need Help?
+
+If you have questions about upgrading:
+1. Check the [README](README.md) for v3 setup instructions
+2. Review your v2 configuration before upgrading
+3. Open an issue if you encounter problems
\ No newline at end of file
diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh
index c010719..6015c11 100644
--- a/docker-entrypoint.sh
+++ b/docker-entrypoint.sh
@@ -269,82 +269,7 @@ else
bun scripts/manage-db.ts fix
fi
- # Run database migrations
- echo "Running database migrations..."
-
- # Update mirror_jobs table with new columns for resilience
- if [ -f "dist/scripts/update-mirror-jobs-table.js" ]; then
- echo "Updating mirror_jobs table..."
- bun dist/scripts/update-mirror-jobs-table.js
- elif [ -f "scripts/update-mirror-jobs-table.ts" ]; then
- echo "Updating mirror_jobs table using TypeScript script..."
- bun scripts/update-mirror-jobs-table.ts
- else
- echo "Warning: Could not find mirror_jobs table update script."
- fi
-
- # Run v3 migrations if needed
- echo "Checking for v3 migrations..."
-
- # Check if we need to run Better Auth migration (check if accounts table exists)
- if ! sqlite3 /app/data/gitea-mirror.db "SELECT name FROM sqlite_master WHERE type='table' AND name='accounts';" | grep -q accounts; then
- echo "š v3 Migration: Creating Better Auth tables..."
- # Create Better Auth tables
- sqlite3 /app/data/gitea-mirror.db < 0) {
- console.log("ā Better Auth migration already completed");
- return;
- }
-
- // Check if we have old users table with passwords
- // This query checks if password column exists in users table
- const hasPasswordColumn = await db.get<{ count: number }>(
- sql`SELECT COUNT(*) as count FROM pragma_table_info('users') WHERE name = 'password'`
- );
-
- if (!hasPasswordColumn || hasPasswordColumn.count === 0) {
- console.log("ā¹ļø Users table doesn't have password column - migration may have already been done");
-
- // Check if we have any users without accounts
- const usersWithoutAccounts = await db.all<{ id: string; email: string }>(
- sql`SELECT u.id, u.email FROM users u LEFT JOIN accounts a ON u.id = a.user_id WHERE a.id IS NULL`
- );
-
- if (usersWithoutAccounts.length === 0) {
- console.log("ā All users have accounts - migration complete");
- return;
- }
-
- console.log(`ā ļø Found ${usersWithoutAccounts.length} users without accounts - they may need to reset passwords`);
- return;
- }
-
- // Get all users with password hashes using raw SQL since the schema doesn't have password
- const allUsersWithPasswords = await db.all<{ id: string; email: string; username: string; password: string }>(
- sql`SELECT id, email, username, password FROM users WHERE password IS NOT NULL`
- );
-
- if (allUsersWithPasswords.length === 0) {
- console.log("ā¹ļø No users with passwords to migrate");
- return;
- }
-
- console.log(`š Found ${allUsersWithPasswords.length} users to migrate`);
-
- // Migrate each user
- for (const user of allUsersWithPasswords) {
- try {
- // Create Better Auth account entry
- await db.insert(accounts).values({
- id: crypto.randomUUID(),
- userId: user.id,
- accountId: user.email, // Use email as account ID
- providerId: "credential", // Better Auth credential provider
- providerUserId: null,
- accessToken: null,
- refreshToken: null,
- expiresAt: null,
- password: user.password, // Move password hash to accounts table
- createdAt: new Date(),
- updatedAt: new Date()
- });
-
- console.log(`ā Migrated user: ${user.email}`);
- } catch (error) {
- console.error(`ā Failed to migrate user ${user.email}:`, error);
- // Continue with other users even if one fails
- }
- }
-
- // Remove password column from users table if it exists
- console.log("š Cleaning up old password column...");
- try {
- // SQLite doesn't support DROP COLUMN directly, so we need to recreate the table
- // For now, we'll just leave it as is since it's not harmful
- console.log("ā¹ļø Password column left in users table for compatibility");
- } catch (error) {
- console.error("ā ļø Could not remove password column:", error);
- }
-
- console.log("ā
Better Auth migration completed successfully");
-
- // Verify migration
- const migratedAccounts = await db.select().from(accounts);
- console.log(`š Total accounts after migration: ${migratedAccounts.length}`);
-
- } catch (error) {
- console.error("ā Better Auth migration failed:", error);
- process.exit(1);
- }
-}
-
-// Run migration
-migrateToBetterAuth();
\ No newline at end of file
diff --git a/scripts/migrate-to-better-auth.ts b/scripts/migrate-to-better-auth.ts
deleted file mode 100644
index 9790021..0000000
--- a/scripts/migrate-to-better-auth.ts
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/usr/bin/env bun
-
-import { db, users, accounts } from "../src/lib/db";
-import { eq } from "drizzle-orm";
-import { v4 as uuidv4 } from "uuid";
-
-/**
- * Migrate existing users to Better Auth schema
- *
- * This script:
- * 1. Moves existing password hashes from users table to accounts table
- * 2. Updates user data to match Better Auth requirements
- * 3. Creates credential accounts for existing users
- */
-
-async function migrateUsers() {
- console.log("š Starting user migration to Better Auth...");
-
- try {
- // Get all existing users
- const existingUsers = await db.select().from(users);
-
- if (existingUsers.length === 0) {
- console.log("ā
No users to migrate");
- return;
- }
-
- console.log(`Found ${existingUsers.length} users to migrate`);
-
- for (const user of existingUsers) {
- console.log(`\nMigrating user: ${user.username} (${user.email})`);
-
- // Check if user already has a credential account
- const existingAccount = await db
- .select()
- .from(accounts)
- .where(
- eq(accounts.userId, user.id) &&
- eq(accounts.providerId, "credential")
- )
- .limit(1);
-
- if (existingAccount.length > 0) {
- console.log("ā User already migrated");
- continue;
- }
-
- // Create credential account with existing password hash
- const accountId = uuidv4();
- await db.insert(accounts).values({
- id: accountId,
- accountId: accountId,
- userId: user.id,
- providerId: "credential",
- providerUserId: user.email, // Use email as provider user ID
- // password: user.password, // Password is not in users table anymore
- createdAt: user.createdAt,
- updatedAt: user.updatedAt,
- });
-
- console.log("ā Created credential account");
-
- // Update user name field if it's null (Better Auth uses 'name' field)
- // Note: Better Auth expects a 'name' field, but we're using username
- // This is handled by our additional fields configuration
- }
-
- console.log("\nā
User migration completed successfully!");
-
- // Summary
- const migratedAccounts = await db
- .select()
- .from(accounts)
- .where(eq(accounts.providerId, "credential"));
-
- console.log(`\nMigration Summary:`);
- console.log(`- Total users: ${existingUsers.length}`);
- console.log(`- Migrated accounts: ${migratedAccounts.length}`);
-
- } catch (error) {
- console.error("ā Migration failed:", error);
- process.exit(1);
- }
-}
-
-// Run migration
-migrateUsers();
\ No newline at end of file
diff --git a/scripts/migrate-tokens-encryption.ts b/scripts/migrate-tokens-encryption.ts
deleted file mode 100644
index f9c1c6c..0000000
--- a/scripts/migrate-tokens-encryption.ts
+++ /dev/null
@@ -1,135 +0,0 @@
-#!/usr/bin/env bun
-/**
- * Migration script to encrypt existing GitHub and Gitea tokens in the database
- * Run with: bun run scripts/migrate-tokens-encryption.ts
- */
-
-import { db, configs } from "../src/lib/db";
-import { eq } from "drizzle-orm";
-import { encrypt, isEncrypted, migrateToken } from "../src/lib/utils/encryption";
-
-async function migrateTokens() {
- console.log("Starting token encryption migration...");
-
- try {
- // Fetch all configs
- const allConfigs = await db.select().from(configs);
-
- console.log(`Found ${allConfigs.length} configurations to check`);
-
- let migratedCount = 0;
- let skippedCount = 0;
- let errorCount = 0;
-
- for (const config of allConfigs) {
- try {
- let githubUpdated = false;
- let giteaUpdated = false;
-
- // Parse configs
- const githubConfig = typeof config.githubConfig === "string"
- ? JSON.parse(config.githubConfig)
- : config.githubConfig;
-
- const giteaConfig = typeof config.giteaConfig === "string"
- ? JSON.parse(config.giteaConfig)
- : config.giteaConfig;
-
- // Check and migrate GitHub token
- if (githubConfig.token) {
- if (!isEncrypted(githubConfig.token)) {
- console.log(`Encrypting GitHub token for config ${config.id} (user: ${config.userId})`);
- githubConfig.token = encrypt(githubConfig.token);
- githubUpdated = true;
- } else {
- console.log(`GitHub token already encrypted for config ${config.id}`);
- }
- }
-
- // Check and migrate Gitea token
- if (giteaConfig.token) {
- if (!isEncrypted(giteaConfig.token)) {
- console.log(`Encrypting Gitea token for config ${config.id} (user: ${config.userId})`);
- giteaConfig.token = encrypt(giteaConfig.token);
- giteaUpdated = true;
- } else {
- console.log(`Gitea token already encrypted for config ${config.id}`);
- }
- }
-
- // Update config if any tokens were migrated
- if (githubUpdated || giteaUpdated) {
- await db
- .update(configs)
- .set({
- githubConfig,
- giteaConfig,
- updatedAt: new Date(),
- })
- .where(eq(configs.id, config.id));
-
- migratedCount++;
- console.log(`ā Config ${config.id} updated successfully`);
- } else {
- skippedCount++;
- }
-
- } catch (error) {
- errorCount++;
- console.error(`ā Error processing config ${config.id}:`, error);
- }
- }
-
- console.log("\n=== Migration Summary ===");
- console.log(`Total configs: ${allConfigs.length}`);
- console.log(`Migrated: ${migratedCount}`);
- console.log(`Skipped (already encrypted): ${skippedCount}`);
- console.log(`Errors: ${errorCount}`);
-
- if (errorCount > 0) {
- console.error("\nā ļø Some configs failed to migrate. Please check the errors above.");
- process.exit(1);
- } else {
- console.log("\nā
Token encryption migration completed successfully!");
- }
-
- } catch (error) {
- console.error("Fatal error during migration:", error);
- process.exit(1);
- }
-}
-
-// Verify environment setup
-function verifyEnvironment() {
- const requiredEnvVars = ["ENCRYPTION_SECRET", "JWT_SECRET", "BETTER_AUTH_SECRET"];
- const availableSecrets = requiredEnvVars.filter(varName => process.env[varName]);
-
- if (availableSecrets.length === 0) {
- console.error("ā No encryption secret found!");
- console.error("Please set one of the following environment variables:");
- console.error(" - ENCRYPTION_SECRET (recommended)");
- console.error(" - JWT_SECRET");
- console.error(" - BETTER_AUTH_SECRET");
- process.exit(1);
- }
-
- console.log(`Using encryption secret from: ${availableSecrets[0]}`);
-}
-
-// Main execution
-async function main() {
- console.log("=== Gitea Mirror Token Encryption Migration ===\n");
-
- // Verify environment
- verifyEnvironment();
-
- // Run migration
- await migrateTokens();
-
- process.exit(0);
-}
-
-main().catch((error) => {
- console.error("Unexpected error:", error);
- process.exit(1);
-});
\ No newline at end of file