From d1059f50e5ab56673cd08defd4aac457de82f033 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 31 Oct 2022 16:55:20 +0000 Subject: [PATCH] feat: [#56] trasnfer user data from v1.0.0 to v2.0.0 TODO: transfer password --- .../databases/sqlite_v1_0_0.rs | 19 +++++ .../databases/sqlite_v2_0_0.rs | 38 ++++++++++ .../from_v1_0_0_to_v2_0_0/upgrader.rs | 76 ++++++++++++++++++- 3 files changed, 132 insertions(+), 1 deletion(-) diff --git a/src/upgrades/from_v1_0_0_to_v2_0_0/databases/sqlite_v1_0_0.rs b/src/upgrades/from_v1_0_0_to_v2_0_0/databases/sqlite_v1_0_0.rs index a7351479..b38957fd 100644 --- a/src/upgrades/from_v1_0_0_to_v2_0_0/databases/sqlite_v1_0_0.rs +++ b/src/upgrades/from_v1_0_0_to_v2_0_0/databases/sqlite_v1_0_0.rs @@ -9,6 +9,17 @@ pub struct Category { pub category_id: i64, pub name: String, } + +#[derive(Debug, Serialize, Deserialize, sqlx::FromRow)] +pub struct User { + pub user_id: i64, + pub username: String, + pub email: String, + pub email_verified: bool, + pub password: String, + pub administrator: bool, +} + pub struct SqliteDatabaseV1_0_0 { pub pool: SqlitePool, } @@ -30,4 +41,12 @@ impl SqliteDatabaseV1_0_0 { .await .map_err(|_| DatabaseError::Error) } + + pub async fn get_users(&self) -> Result, sqlx::Error> { + query_as::<_, User>( + "SELECT * FROM torrust_users ORDER BY user_id ASC", + ) + .fetch_all(&self.pool) + .await + } } diff --git a/src/upgrades/from_v1_0_0_to_v2_0_0/databases/sqlite_v2_0_0.rs b/src/upgrades/from_v1_0_0_to_v2_0_0/databases/sqlite_v2_0_0.rs index 8dce7584..5aa83fde 100644 --- a/src/upgrades/from_v1_0_0_to_v2_0_0/databases/sqlite_v2_0_0.rs +++ b/src/upgrades/from_v1_0_0_to_v2_0_0/databases/sqlite_v2_0_0.rs @@ -57,6 +57,44 @@ impl SqliteDatabaseV2_0_0 { }) } + pub async fn insert_user( + &self, + user_id: i64, + date_registered: &str, + administrator: bool, + ) -> Result { + query( + "INSERT INTO torrust_users (user_id, date_registered, administrator) VALUES (?, ?, ?)", + ) + .bind(user_id) + .bind(date_registered) + .bind(administrator) + .execute(&self.pool) + .await + .map(|v| v.last_insert_rowid()) + } + + pub async fn insert_user_profile( + &self, + user_id: i64, + username: &str, + email: &str, + email_verified: bool, + bio: &str, + avatar: &str, + ) -> Result { + query("INSERT INTO torrust_user_profiles (user_id, username, email, email_verified, bio, avatar) VALUES (?, ?, ?, ?, ?, ?)") + .bind(user_id) + .bind(username) + .bind(email) + .bind(email_verified) + .bind(bio) + .bind(avatar) + .execute(&self.pool) + .await + .map(|v| v.last_insert_rowid()) + } + pub async fn delete_all_database_rows(&self) -> Result<(), DatabaseError> { query("DELETE FROM torrust_categories;") .execute(&self.pool) diff --git a/src/upgrades/from_v1_0_0_to_v2_0_0/upgrader.rs b/src/upgrades/from_v1_0_0_to_v2_0_0/upgrader.rs index 1be682cd..29ad2a85 100644 --- a/src/upgrades/from_v1_0_0_to_v2_0_0/upgrader.rs +++ b/src/upgrades/from_v1_0_0_to_v2_0_0/upgrader.rs @@ -1,9 +1,24 @@ +//! It updates the application from version v1.0.0 to v2.0.0. +//! +//! NOTES for `torrust_users` table transfer: +//! +//! - In v2, the table `torrust_user` contains a field `date_registered` non existing in v1. +//! It's used the day when the upgrade command is executed. +//! - In v2, the table `torrust_user_profiles` contains two new fields: `bio` and `avatar`. +//! Empty string is used as default value. + use crate::upgrades::from_v1_0_0_to_v2_0_0::databases::sqlite_v1_0_0::SqliteDatabaseV1_0_0; use crate::upgrades::from_v1_0_0_to_v2_0_0::databases::sqlite_v2_0_0::SqliteDatabaseV2_0_0; -use std::sync::Arc; +use chrono::prelude::{DateTime, Utc}; +use std::{sync::Arc, time::SystemTime}; use crate::config::Configuration; +fn today_iso8601() -> String { + let dt: DateTime = SystemTime::now().into(); + format!("{}", dt.format("%Y-%m-%d")) +} + async fn current_db() -> Arc { // Connect to the old v1.0.0 DB let cfg = match Configuration::load_from_file().await { @@ -75,5 +90,64 @@ pub async fn upgrade() { reset_destiny_database(dest_database.clone()).await; transfer_categories(source_database.clone(), dest_database.clone()).await; + // Transfer `torrust_users` + + let users = source_database.get_users().await.unwrap(); + + for user in &users { + // [v2] table torrust_users + + println!( + "[v2][torrust_users] adding user: {:?} {:?} ...", + &user.user_id, &user.username + ); + + let default_data_registered = today_iso8601(); + + let id = dest_database + .insert_user(user.user_id, &default_data_registered, user.administrator) + .await + .unwrap(); + + if id != user.user_id { + panic!( + "Error copying user {:?} from source DB to destiny DB", + &user.user_id + ); + } + + println!( + "[v2][torrust_users] user: {:?} {:?} added.", + &user.user_id, &user.username + ); + + // [v2] table torrust_user_profiles + + println!( + "[v2][torrust_user_profiles] adding user: {:?} {:?} ...", + &user.user_id, &user.username + ); + + let default_user_bio = "".to_string(); + let default_user_avatar = "".to_string(); + + dest_database + .insert_user_profile( + user.user_id, + &user.username, + &user.email, + user.email_verified, + &default_user_bio, + &default_user_avatar, + ) + .await + .unwrap(); + + println!( + "[v2][torrust_user_profiles] user: {:?} {:?} added.", + &user.user_id, &user.username + ); + } + // TODO: WIP. We have to transfer data from the 5 tables in V1 and the torrent files in folder `uploads`. }