Complete conversion to postgres
This commit is contained in:
parent
4ff14e6fa1
commit
b39dde34e4
|
|
@ -23,7 +23,7 @@ oauth2 = "4.4"
|
|||
http = "1.1"
|
||||
tower-http = { version = "0.6.1", features = ["full"] }
|
||||
chrono = { version = "0.4.38", features = ["serde"] }
|
||||
sqlx = { version = "0.8", features = ["postgres", "runtime-tokio", "macros", "chrono", "uuid"] }
|
||||
sqlx = { version = "0.8", features = ["postgres", "sqlite","runtime-tokio", "macros", "chrono", "uuid"] }
|
||||
uuid = { version = "1.10", features = ["v4"] }
|
||||
dotenvy = "0.15"
|
||||
constant_time_eq = "0.3"
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
-- Drop Postgres tables
|
||||
drop table oauth2_state_storage;
|
||||
drop table user_sessions;
|
||||
drop table users;
|
||||
drop table roles;
|
||||
drop table user_roles;
|
||||
drop table role_permissions;
|
||||
drop table wishlist_items;
|
||||
drop table gift_exchange;
|
||||
drop table gift_exchange_participants;
|
||||
drop table calendar;
|
||||
drop table calendar_event_types;
|
||||
drop table calendar_events;
|
||||
drop table if exists oauth2_state_storage;
|
||||
drop table if exists user_sessions;
|
||||
drop table if exists users;
|
||||
drop table if exists roles;
|
||||
drop table if exists user_roles;
|
||||
drop table if exists role_permissions;
|
||||
drop table if exists wishlist_items;
|
||||
drop table if exists gift_exchange;
|
||||
drop table if exists gift_exchange_participants;
|
||||
drop table if exists calendar;
|
||||
drop table if exists calendar_event_types;
|
||||
drop table if exists calendar_events;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ create table IF NOT EXISTS user_roles (
|
|||
role_id uuid NOT NULL
|
||||
);
|
||||
|
||||
create unique index if not exists unique_user_role on user_roles(user_id, role_id);
|
||||
|
||||
create table IF NOT EXISTS role_permissions (
|
||||
id uuid PRIMARY KEY default gen_random_uuid(),
|
||||
created_at timestamp NOT NULL default now(),
|
||||
|
|
@ -64,8 +66,8 @@ create table if not exists wishlist_items (
|
|||
updated_at timestamp null default now(),
|
||||
updated_by uuid null,
|
||||
user_id uuid null,
|
||||
item varchar(255) null,
|
||||
item_url varchar(255) null,
|
||||
item varchar(512) null,
|
||||
item_url varchar(1024) null,
|
||||
purchased_by uuid null,
|
||||
received_at timestamp null
|
||||
);
|
||||
|
|
|
|||
|
|
@ -3,13 +3,12 @@ use axum::{
|
|||
routing::{get, get_service},
|
||||
Extension, Router,
|
||||
};
|
||||
use dotenvy::var;
|
||||
use secret_gift_exchange::{giftexchange, giftexchange_save, giftexchanges};
|
||||
use sqlx::migrate::Migrator;
|
||||
use sqlx::{PgPool, postgres::PgPoolOptions};
|
||||
use sqlx::{migrate::Migrator, sqlite::SqlitePoolOptions, sqlite::SqliteRow, Row, SqlitePool};
|
||||
use sqlx::{postgres::PgPoolOptions, PgPool};
|
||||
use std::net::SocketAddr;
|
||||
use tower_http::services::ServeDir;
|
||||
use dotenvy::var;
|
||||
|
||||
|
||||
mod calendar;
|
||||
mod email;
|
||||
|
|
@ -17,17 +16,21 @@ mod error_handling;
|
|||
mod google_oauth;
|
||||
mod middlewares;
|
||||
mod routes;
|
||||
mod secret_gift_exchange;
|
||||
mod user;
|
||||
mod wishlist;
|
||||
mod secret_gift_exchange;
|
||||
|
||||
use calendar::{calendar, get_events};
|
||||
use error_handling::AppError;
|
||||
use google_oauth::{google_auth_return, login, logout};
|
||||
use middlewares::inject_user_data;
|
||||
use routes::{about, contact, dashboard, index, profile, user_profile, useradmin};
|
||||
use user::{add_user_role, delete_user_role, UserData};
|
||||
use calendar::{calendar, get_events};
|
||||
use wishlist::{user_wishlist, user_wishlist_add, user_wishlist_add_item, user_wishlist_bought_item, user_wishlist_delete_item, user_wishlist_edit_item, user_wishlist_received_item, user_wishlist_returned_item, user_wishlist_save_item, wishlists};
|
||||
use wishlist::{
|
||||
user_wishlist, user_wishlist_add, user_wishlist_add_item, user_wishlist_bought_item,
|
||||
user_wishlist_delete_item, user_wishlist_edit_item, user_wishlist_received_item,
|
||||
user_wishlist_returned_item, user_wishlist_save_item, wishlists,
|
||||
};
|
||||
//use email::send_emails;
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
@ -44,9 +47,7 @@ async fn main() {
|
|||
let database_url = var("DATABASE_URL").expect("DATABASE_URL not set");
|
||||
let db_pool = PgPoolOptions::new().connect(&database_url).await.unwrap();
|
||||
|
||||
let app_state = AppState {
|
||||
db_pool: db_pool,
|
||||
};
|
||||
let app_state = AppState { db_pool: db_pool };
|
||||
|
||||
static MIGRATOR: Migrator = sqlx::migrate!();
|
||||
|
||||
|
|
@ -55,39 +56,74 @@ async fn main() {
|
|||
.await
|
||||
.expect("Failed to run migrations");
|
||||
|
||||
// Copy from old sqlite database if it exists
|
||||
if let Ok(source_db_url) = var("SOURCE_DB_URL") {
|
||||
let sdb_pool = SqlitePoolOptions::new()
|
||||
.max_connections(5)
|
||||
.connect(&source_db_url)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
copy_database(&sdb_pool, &app_state.db_pool).await;
|
||||
} else {
|
||||
println!("SOURCE_DB_URL not set");
|
||||
}
|
||||
|
||||
let user_data: Option<UserData> = None;
|
||||
|
||||
// build our application with some routes
|
||||
let app = Router::new()
|
||||
.route("/dashboard", get(dashboard))
|
||||
|
||||
// User
|
||||
.route("/profile", get(profile))
|
||||
.route("/useradmin", get(useradmin))
|
||||
.route("/users/:user_id", get(user_profile))
|
||||
.route("/roles/:user_id/:role_id/add", get(add_user_role))
|
||||
.route("/roles/:user_id/:user_role_id/delete", get(delete_user_role))
|
||||
|
||||
.route(
|
||||
"/roles/:user_id/:user_role_id/delete",
|
||||
get(delete_user_role),
|
||||
)
|
||||
// Calendar
|
||||
.route("/calendar", get(calendar))
|
||||
.route("/getevents/:calendar", get(get_events))
|
||||
|
||||
// Wishlist
|
||||
.route("/wishlists", get(wishlists))
|
||||
.route("/wishlists", get(wishlists))
|
||||
.route("/userwishlist/:user_id", get(user_wishlist))
|
||||
.route("/userwishlist/add/:user_id", get(user_wishlist_add).post(user_wishlist_add_item))
|
||||
.route("/userwishlist/edit/:item_id", get(user_wishlist_edit_item).post(user_wishlist_save_item))
|
||||
.route("/userwishlist/bought/:user_id", get(user_wishlist_bought_item))
|
||||
.route("/userwishlist/received/:user_id", get(user_wishlist_received_item))
|
||||
.route("/userwishlist/delete/:item_id", get(user_wishlist_delete_item))
|
||||
.route("/userwishlist/returned/:item_id", get(user_wishlist_returned_item))
|
||||
|
||||
.route(
|
||||
"/userwishlist/add/:user_id",
|
||||
get(user_wishlist_add).post(user_wishlist_add_item),
|
||||
)
|
||||
.route(
|
||||
"/userwishlist/edit/:item_id",
|
||||
get(user_wishlist_edit_item).post(user_wishlist_save_item),
|
||||
)
|
||||
.route(
|
||||
"/userwishlist/bought/:user_id",
|
||||
get(user_wishlist_bought_item),
|
||||
)
|
||||
.route(
|
||||
"/userwishlist/received/:user_id",
|
||||
get(user_wishlist_received_item),
|
||||
)
|
||||
.route(
|
||||
"/userwishlist/delete/:item_id",
|
||||
get(user_wishlist_delete_item),
|
||||
)
|
||||
.route(
|
||||
"/userwishlist/returned/:item_id",
|
||||
get(user_wishlist_returned_item),
|
||||
)
|
||||
// Secret Gift Exchange - Not ready for public use yet
|
||||
.route("/giftexchanges", get(giftexchanges))
|
||||
.route("/giftexchange/:giftexchange_id", get(giftexchange).post(giftexchange_save))
|
||||
|
||||
.nest_service("/assets", ServeDir::new("templates/assets")
|
||||
.fallback(get_service(ServeDir::new("templates/assets"))))
|
||||
.route(
|
||||
"/giftexchange/:giftexchange_id",
|
||||
get(giftexchange).post(giftexchange_save),
|
||||
)
|
||||
.nest_service(
|
||||
"/assets",
|
||||
ServeDir::new("templates/assets")
|
||||
.fallback(get_service(ServeDir::new("templates/assets"))),
|
||||
)
|
||||
.route("/", get(index))
|
||||
.route("/about", get(about))
|
||||
.route("/contactus", get(contact))
|
||||
|
|
@ -113,3 +149,169 @@ async fn main() {
|
|||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
async fn copy_database(sdb_pool: &SqlitePool, db_pool: &PgPool) {
|
||||
// Copy users
|
||||
let users = sqlx::query(
|
||||
r#"select
|
||||
datetime(u.created_at, 'unixepoch'),
|
||||
coalesce(cb.email, 'admin@jean-marie.ca') as created_by_email,
|
||||
datetime(u.updated_at, 'unixepoch'),
|
||||
coalesce(ub.email, 'admin@jean-marie.ca') as updated_by_email,
|
||||
u.email,
|
||||
u.name,
|
||||
u.family_name,
|
||||
u.given_name
|
||||
from users u
|
||||
left join users cb on cb.id = u.created_by
|
||||
left join users ub on ub.id = u.updated_by;"#,
|
||||
)
|
||||
.fetch_all(sdb_pool)
|
||||
.await
|
||||
.expect("Failed to copy users from SQLite to Postgres");
|
||||
|
||||
println!("\nCopying {} users", users.len());
|
||||
|
||||
for user in users {
|
||||
if let (
|
||||
Ok(created_at),
|
||||
Ok(created_by),
|
||||
Ok(updated_at),
|
||||
Ok(updated_by),
|
||||
Ok(email),
|
||||
Ok(name),
|
||||
Ok(family_name),
|
||||
Ok(given_name),
|
||||
) = (
|
||||
user.try_get::<chrono::NaiveDateTime, _>(0),
|
||||
user.try_get::<String, _>(1),
|
||||
user.try_get::<chrono::NaiveDateTime, _>(2),
|
||||
user.try_get::<String, _>(3),
|
||||
user.try_get::<String, _>(4),
|
||||
user.try_get::<String, _>(5),
|
||||
user.try_get::<String, _>(6),
|
||||
user.try_get::<String, _>(7),
|
||||
) {
|
||||
let result = sqlx::query(
|
||||
r#"insert into users (created_at, created_by, updated_at, updated_by, email, name, family_name, given_name)
|
||||
values ($1, (select id from users where email =$2), $3, (select id from users where email =$4), $5, $6, $7, $8)"#
|
||||
)
|
||||
.bind(created_at)
|
||||
.bind(created_by)
|
||||
.bind(updated_at)
|
||||
.bind(updated_by)
|
||||
.bind(email)
|
||||
.bind(name)
|
||||
.bind(family_name)
|
||||
.bind(given_name)
|
||||
.execute(db_pool)
|
||||
.await;
|
||||
|
||||
if let Err(e) = result {
|
||||
println!("Error: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy user roles
|
||||
let user_roles = sqlx::query(
|
||||
r#"select
|
||||
datetime(ur.created_at, 'unixepoch'),
|
||||
coalesce(cb.email, 'admin@jean-marie.ca') as created_by_email,
|
||||
datetime(ur.updated_at, 'unixepoch'),
|
||||
coalesce(ub.email, 'admin@jean-marie.ca') as updated_by_email,
|
||||
u.email as user_email,
|
||||
r.name as role_name
|
||||
from user_roles ur
|
||||
left join users cb on cb.id = ur.created_by
|
||||
left join users ub on ub.id = ur.updated_by
|
||||
join users u on u.id = ur.user_id
|
||||
join roles r on r.id = ur.role_id;"#,
|
||||
)
|
||||
.fetch_all(sdb_pool)
|
||||
.await
|
||||
.expect("Failed to copy user roles from SQLite to Postgres");
|
||||
|
||||
println!("\nCopying {} user roles", user_roles.len());
|
||||
|
||||
for user_role in user_roles {
|
||||
if let (
|
||||
Ok(created_at),
|
||||
Ok(created_by),
|
||||
Ok(updated_at),
|
||||
Ok(updated_by),
|
||||
Ok(user_email),
|
||||
Ok(role_name),
|
||||
) = (
|
||||
user_role.try_get::<chrono::NaiveDateTime, _>(0),
|
||||
user_role.try_get::<String, _>(1),
|
||||
user_role.try_get::<chrono::NaiveDateTime, _>(2),
|
||||
user_role.try_get::<String, _>(3),
|
||||
user_role.try_get::<String, _>(4),
|
||||
user_role.try_get::<String, _>(5),
|
||||
) {
|
||||
let result = sqlx::query(
|
||||
r#"insert into user_roles (created_at, created_by, updated_at, updated_by, user_id, role_id)
|
||||
values ($1, (select id from users where email=$2), $3, (select id from users where email=$4), (select id from users where email=$5), (select id from roles where name=$6))"#
|
||||
)
|
||||
.bind(created_at)
|
||||
.bind(created_by)
|
||||
.bind(updated_at)
|
||||
.bind(updated_by)
|
||||
.bind(user_email)
|
||||
.bind(role_name)
|
||||
.execute(db_pool)
|
||||
.await;
|
||||
|
||||
if let Err(e) = result {
|
||||
println!("Error: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy wishlistitems
|
||||
let wishlistitems = sqlx::query(
|
||||
r#"select
|
||||
datetime(wi.created_at, 'unixepoch'),
|
||||
coalesce(cb.email, 'admin@jean-marie.ca') as created_by_email,
|
||||
datetime(wi.updated_at, 'unixepoch'),
|
||||
coalesce(ub.email, 'admin@jean-marie.ca') as updated_by_email,
|
||||
u.email as user_email,
|
||||
wi.item,
|
||||
wi.item_url,
|
||||
pb.email,
|
||||
datetime(wi.received_at, 'unixepoch')
|
||||
from wishlist_items wi
|
||||
left join users cb on cb.id = wi.created_by
|
||||
left join users ub on ub.id = wi.updated_by
|
||||
left join users pb on pb.id = wi.purchased_by
|
||||
join users u on u.id = wi.user_id;"#,
|
||||
)
|
||||
.fetch_all(sdb_pool)
|
||||
.await
|
||||
.expect("Failed to copy wishlistitems from SQLite to Postgres");
|
||||
|
||||
println!("\nCopying {} wishlistitems", wishlistitems.len());
|
||||
|
||||
for wishlistitem in wishlistitems {
|
||||
let result = sqlx::query(
|
||||
r#"insert into wishlist_items (created_at, created_by, updated_at, updated_by, user_id, item, item_url, purchased_by, received_at)
|
||||
values ($1, (select id from users where email=$2), $3, (select id from users where email=$4), (select id from users where email=$5), $6, $7, (select id from users where email=$8), $9)"#
|
||||
)
|
||||
.bind(wishlistitem.try_get::<chrono::NaiveDateTime,_>(0).unwrap())
|
||||
.bind(wishlistitem.try_get::<String,_>(1).unwrap())
|
||||
.bind(wishlistitem.try_get::<chrono::NaiveDateTime,_>(2).unwrap())
|
||||
.bind(wishlistitem.try_get::<String,_>(3).unwrap())
|
||||
.bind(wishlistitem.try_get::<String,_>(4).unwrap())
|
||||
.bind(wishlistitem.try_get::<String,_>(5).unwrap())
|
||||
.bind(wishlistitem.try_get::<String,_>(6).unwrap())
|
||||
.bind(wishlistitem.try_get::<String,_>(7).unwrap())
|
||||
.bind(wishlistitem.try_get::<chrono::NaiveDateTime,_>(8).unwrap_or_default())
|
||||
.execute(db_pool)
|
||||
.await;
|
||||
|
||||
if let Err(e) = result {
|
||||
println!("Error: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue