diff --git a/migrations/mysql/20230824164316_torrust_torrents_add_original_info_hash.sql b/migrations/mysql/20230824164316_torrust_torrents_add_original_info_hash.sql new file mode 100644 index 00000000..e81cb96c --- /dev/null +++ b/migrations/mysql/20230824164316_torrust_torrents_add_original_info_hash.sql @@ -0,0 +1 @@ +ALTER TABLE torrust_torrents ADD COLUMN original_info_hash TEXT DEFAULT NULL \ No newline at end of file diff --git a/migrations/sqlite3/20230824164316_torrust_torrents_add_original_info_hash.sql b/migrations/sqlite3/20230824164316_torrust_torrents_add_original_info_hash.sql new file mode 100644 index 00000000..e81cb96c --- /dev/null +++ b/migrations/sqlite3/20230824164316_torrust_torrents_add_original_info_hash.sql @@ -0,0 +1 @@ +ALTER TABLE torrust_torrents ADD COLUMN original_info_hash TEXT DEFAULT NULL \ No newline at end of file diff --git a/src/databases/database.rs b/src/databases/database.rs index 0ba2a5a1..72d15c18 100644 --- a/src/databases/database.rs +++ b/src/databases/database.rs @@ -191,6 +191,7 @@ pub trait Database: Sync + Send { /// Add new torrent and return the newly inserted `torrent_id` with `torrent`, `uploader_id`, `category_id`, `title` and `description`. async fn insert_torrent_and_get_id( &self, + original_info_hash: &InfoHash, torrent: &Torrent, uploader_id: UserId, category_id: i64, diff --git a/src/databases/mysql.rs b/src/databases/mysql.rs index 5b9f1ca4..e7d0babb 100644 --- a/src/databases/mysql.rs +++ b/src/databases/mysql.rs @@ -418,6 +418,7 @@ impl Database for Mysql { #[allow(clippy::too_many_lines)] async fn insert_torrent_and_get_id( &self, + original_info_hash: &InfoHash, torrent: &Torrent, uploader_id: UserId, category_id: i64, @@ -443,7 +444,7 @@ impl Database for Mysql { let private = torrent.info.private.unwrap_or(0); // add torrent - let torrent_id = query("INSERT INTO torrust_torrents (uploader_id, category_id, info_hash, size, name, pieces, piece_length, private, root_hash, `source`, date_uploaded) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, UTC_TIMESTAMP())") + let torrent_id = query("INSERT INTO torrust_torrents (uploader_id, category_id, info_hash, size, name, pieces, piece_length, private, root_hash, `source`, original_info_hash, date_uploaded) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, UTC_TIMESTAMP())") .bind(uploader_id) .bind(category_id) .bind(info_hash.to_lowercase()) @@ -454,6 +455,7 @@ impl Database for Mysql { .bind(private) .bind(root_hash) .bind(torrent.info.source.clone()) + .bind(original_info_hash.to_hex_string()) .execute(&self.pool) .await .map(|v| i64::try_from(v.last_insert_id()).expect("last ID is larger than i64")) diff --git a/src/databases/sqlite.rs b/src/databases/sqlite.rs index 5e8d5a7d..c300c188 100644 --- a/src/databases/sqlite.rs +++ b/src/databases/sqlite.rs @@ -406,6 +406,7 @@ impl Database for Sqlite { #[allow(clippy::too_many_lines)] async fn insert_torrent_and_get_id( &self, + original_info_hash: &InfoHash, torrent: &Torrent, uploader_id: UserId, category_id: i64, @@ -431,7 +432,7 @@ impl Database for Sqlite { let private = torrent.info.private.unwrap_or(0); // add torrent - let torrent_id = query("INSERT INTO torrust_torrents (uploader_id, category_id, info_hash, size, name, pieces, piece_length, private, root_hash, `source`, date_uploaded) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, strftime('%Y-%m-%d %H:%M:%S',DATETIME('now', 'utc')))") + let torrent_id = query("INSERT INTO torrust_torrents (uploader_id, category_id, info_hash, size, name, pieces, piece_length, private, root_hash, `source`, original_info_hash, date_uploaded) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, strftime('%Y-%m-%d %H:%M:%S',DATETIME('now', 'utc')))") .bind(uploader_id) .bind(category_id) .bind(info_hash.to_lowercase()) @@ -442,6 +443,7 @@ impl Database for Sqlite { .bind(private) .bind(root_hash) .bind(torrent.info.source.clone()) + .bind(original_info_hash.to_hex_string()) .execute(&self.pool) .await .map(|v| v.last_insert_rowid()) diff --git a/src/services/torrent.rs b/src/services/torrent.rs index ec3d63a8..88e5dfe5 100644 --- a/src/services/torrent.rs +++ b/src/services/torrent.rs @@ -130,6 +130,8 @@ impl Index { metadata.verify()?; + let original_info_hash = parse_torrent::calculate_info_hash(&add_torrent_form.torrent_buffer); + let mut torrent = parse_torrent::decode_torrent(&add_torrent_form.torrent_buffer).map_err(|_| ServiceError::InvalidTorrentFile)?; @@ -154,7 +156,11 @@ impl Index { .await .map_err(|_| ServiceError::InvalidCategory)?; - let torrent_id = self.torrent_repository.add(&torrent, &metadata, user_id, category).await?; + let torrent_id = self + .torrent_repository + .add(&original_info_hash, &torrent, &metadata, user_id, category) + .await?; + let info_hash: InfoHash = torrent .info_hash() .parse() @@ -474,13 +480,21 @@ impl DbTorrentRepository { /// This function will return an error there is a database error. pub async fn add( &self, + original_info_hash: &InfoHash, torrent: &Torrent, metadata: &Metadata, user_id: UserId, category: Category, ) -> Result { self.database - .insert_torrent_and_get_id(torrent, user_id, category.category_id, &metadata.title, &metadata.description) + .insert_torrent_and_get_id( + original_info_hash, + torrent, + user_id, + category.category_id, + &metadata.title, + &metadata.description, + ) .await }