🐸 Frogue(Fed)

~ololduck/Frogue

Raw

// SPDX-FileCopyrightText: 2026 Ololduck <ololduck@vit.am> and contributors
//
// SPDX-License-Identifier: GPL-3.0-or-later

use sea_orm_migration::prelude::*;

#[derive(DeriveMigrationName)]
pub struct Migration;

#[async_trait::async_trait]
impl MigrationTrait for Migration {
    async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
        manager
            .get_connection()
            .execute_unprepared("ALTER TABLE reports ADD COLUMN activity_url TEXT NULL")
            .await?;

        manager
            .get_connection()
            .execute_unprepared(
                "CREATE UNIQUE INDEX idx_reports_activity_url ON reports(activity_url) WHERE activity_url IS NOT NULL",
            )
            .await?;

        Ok(())
    }

    async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
        manager
            .get_connection()
            .execute_unprepared("DROP INDEX IF EXISTS idx_reports_activity_url")
            .await?;

        // SQLite doesn't support DROP COLUMN before 3.35.0, so we recreate the
        // table
        manager
            .get_connection()
            .execute_unprepared(
                "CREATE TABLE reports_backup AS SELECT id, uuid, created_at, reporter_local_user_id, reporter_remote_actor_url, target_local_user_id, target_remote_actor_id, object_urls, comment, state, forwarded, inbound FROM reports",
            )
            .await?;

        manager
            .get_connection()
            .execute_unprepared("DROP TABLE reports")
            .await?;

        manager
            .get_connection()
            .execute_unprepared(
                "CREATE TABLE reports (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    uuid TEXT NOT NULL UNIQUE,
                    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
                    reporter_local_user_id INTEGER,
                    reporter_remote_actor_url TEXT,
                    target_local_user_id INTEGER,
                    target_remote_actor_id INTEGER,
                    object_urls TEXT NOT NULL,
                    comment TEXT,
                    state TEXT NOT NULL DEFAULT 'open',
                    forwarded INTEGER NOT NULL DEFAULT 0,
                    inbound INTEGER NOT NULL DEFAULT 0,
                    FOREIGN KEY (reporter_local_user_id) REFERENCES users(id) ON DELETE CASCADE,
                    FOREIGN KEY (target_local_user_id) REFERENCES users(id) ON DELETE CASCADE,
                    FOREIGN KEY (target_remote_actor_id) REFERENCES ap_remote_actors(id) ON DELETE CASCADE,
                    CHECK (
                        (reporter_local_user_id IS NOT NULL AND reporter_remote_actor_url IS NULL) OR
                        (reporter_local_user_id IS NULL AND reporter_remote_actor_url IS NOT NULL)
                    ),
                    CHECK (
                        (target_local_user_id IS NOT NULL AND target_remote_actor_id IS NULL) OR
                        (target_local_user_id IS NULL AND target_remote_actor_id IS NOT NULL)
                    ),
                    CHECK (state IN ('open', 'resolved', 'dismissed'))
                )",
            )
            .await?;

        manager
            .get_connection()
            .execute_unprepared("INSERT INTO reports SELECT * FROM reports_backup")
            .await?;

        manager
            .get_connection()
            .execute_unprepared("DROP TABLE reports_backup")
            .await?;

        Ok(())
    }
}