From 20048837cd376234665fc0057b9ca7de7d4cced8 Mon Sep 17 00:00:00 2001 From: Jim Hodapp Date: Sun, 28 Jan 2024 16:47:15 -0600 Subject: [PATCH 01/17] Creates/documents the MVP DB schema for refactor_platform_rs using DBML --- docs/db/refactor_platform_rs.dbml | 128 ++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 docs/db/refactor_platform_rs.dbml diff --git a/docs/db/refactor_platform_rs.dbml b/docs/db/refactor_platform_rs.dbml new file mode 100644 index 00000000..12b3b64a --- /dev/null +++ b/docs/db/refactor_platform_rs.dbml @@ -0,0 +1,128 @@ +// Use DBML to define your database structure +// Docs: https://dbml.dbdiagram.io/docs + +Table refactor_platform_rs.organizations { + id integer [primary key, unique, not null, increment] + name varchar [note: 'The name of the organization that the coach <--> coachee belong to'] + created_at timestamp +} + +// Coaching relationship type belonging to the refactor_platform_rs schema +// from the perspective of the coachee +enum refactor_platform_rs.coaching_relationship { + client + direct_report +} + +// Declares a coach <--> coachee coaching relationship +// E.g. Manager <--> Software Engineer direct report +// E.g. Independent coach <--> Software Engineer client +Table refactor_platform_rs.coaches_coachees { + id integer [primary key, unique, not null, increment] + organization_id integer [note: 'The organization associated with this coaching relationship'] + coach_id integer [note: 'The coach associated with this coaching relationship'] + coachee_id integer [note: 'The coachee associated with this coaching relationship'] + relationship coaching_relationship +} + +Table refactor_platform_rs.users { + id integer [primary key, unique, not null, increment] + email varchar + first_name varchar + last_name varchar + display_name varchar [note: 'If a user wants to go by something other than first & last names'] + password varchar + timezone timezone + github_username varchar // Specifically GH for now, can generalize later + created_at timestamp +} + +Table refactor_platform_rs.coachees { + id integer [primary key, unique, not null, increment] + user_id integer + organization_id integer +} + +Table refactor_platform_rs.coaches { + id integer [primary key, unique, not null, increment] + user_id integer + organization_id integer +} + +Table refactor_platform_rs.coaching_sessions { + id integer [primary key, unique, not null, increment] + coaches_coachees_id integer [note: 'The coaching relationship (i.e. what coach & coachee under what organization) associated with this coaching session'] + date timestamp [note: 'The date and time of a session'] + timezone timezone [note: 'The baseline timezone used for the `date` field'] + created_at timestamp +} + +Table refactor_platform_rs.overarching_goals { + id integer [primary key, unique, not null, increment] + coaching_session_id integer [note: 'The coaching session that an overarching goal is associated with'] + title varchar [note: 'A short description of an overarching goal'] + details varchar [note: 'A long description of an overarching goal'] + completed boolean // May be unnecessary if there's a valid completed_at timestamp + completed_at timestamp [note: 'The date and time an overarching goal was completed'] + completed_by_id integer [note: 'The user that successfully completed an overarching goal'] + created_at timestamp + updated_at timestamp [note: 'The last date and time an overarching goal\'s fields were changed'] +} + +Table refactor_platform_rs.notes { + id integer [primary key, unique, not null, increment] + coaching_session_id integer + body varchar [note: 'Main text of the note supporting Markdown'] + created_at timestamp + updated_at timestamp [note: 'The last date and time an overarching note\'s fields were changed'] +} + +Table refactor_platform_rs.agreements { + id integer [primary key, unique, not null, increment] + coaching_session_id integer + details varchar [note: 'Either a short or long description of an agreement reached between coach and coachee in a coaching session'] + created_at timestamp + updated_at timestamp [note: 'The last date and time an overarching agreement\'s fields were changed'] +} + +Table refactor_platform_rs.actions { + id integer [primary key, unique, not null, increment] + // The first session where this action was created + // It will carry forward to every future session until + // its due_by is passed or it was completed by the coachee + coaching_session_id integer + due_by timestamp + completed boolean // May be unnecessary if there's a valid completed_at timestamp + completed_at timestamp + created_at timestamp + updated_at timestamp +} + +// coaches_coachees relationships +Ref: refactor_platform_rs.coaches_coachees.organization_id - refactor_platform_rs.organizations.id +Ref: refactor_platform_rs.coaches_coachees.coachee_id - refactor_platform_rs.coachees.id +Ref: refactor_platform_rs.coaches_coachees.coach_id - refactor_platform_rs.coaches.id + +// coachees relationships +Ref: refactor_platform_rs.coachees.user_id - refactor_platform_rs.users.id +Ref: refactor_platform_rs.coachees.organization_id > refactor_platform_rs.organizations.id + +// coaches relationships +Ref: refactor_platform_rs.coaches.user_id - refactor_platform_rs.users.id +Ref: refactor_platform_rs.coaches.organization_id > refactor_platform_rs.organizations.id + +// overarching_goals relationships +Ref: refactor_platform_rs.overarching_goals.coaching_session_id - refactor_platform_rs.coaching_sessions.id +Ref: refactor_platform_rs.overarching_goals.completed_by_id - refactor_platform_rs.users.id + +// notes relationships +Ref: refactor_platform_rs.notes.coaching_session_id - refactor_platform_rs.coaching_sessions.id + +// coaching_sessions relationships +Ref: refactor_platform_rs.coaching_sessions.coaches_coachees_id > refactor_platform_rs.coaches_coachees.id + +// agreements relationships +Ref: refactor_platform_rs.agreements.coaching_session_id > refactor_platform_rs.coaching_sessions.id + +// actions relationships +Ref: refactor_platform_rs.actions.coaching_session_id > refactor_platform_rs.coaching_sessions.id From dde080738e00d2f7aac1b6f9397b582443646b02 Mon Sep 17 00:00:00 2001 From: Jim Hodapp Date: Sun, 28 Jan 2024 17:01:55 -0600 Subject: [PATCH 02/17] Change the DB schema to just refactor_platform --- docs/db/refactor_platform_rs.dbml | 50 +++++++++++++++---------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/docs/db/refactor_platform_rs.dbml b/docs/db/refactor_platform_rs.dbml index 12b3b64a..73d5edd6 100644 --- a/docs/db/refactor_platform_rs.dbml +++ b/docs/db/refactor_platform_rs.dbml @@ -1,15 +1,15 @@ // Use DBML to define your database structure // Docs: https://dbml.dbdiagram.io/docs -Table refactor_platform_rs.organizations { +Table refactor_platform.organizations { id integer [primary key, unique, not null, increment] name varchar [note: 'The name of the organization that the coach <--> coachee belong to'] created_at timestamp } -// Coaching relationship type belonging to the refactor_platform_rs schema +// Coaching relationship type belonging to the refactor_platform schema // from the perspective of the coachee -enum refactor_platform_rs.coaching_relationship { +enum refactor_platform.coaching_relationship { client direct_report } @@ -17,7 +17,7 @@ enum refactor_platform_rs.coaching_relationship { // Declares a coach <--> coachee coaching relationship // E.g. Manager <--> Software Engineer direct report // E.g. Independent coach <--> Software Engineer client -Table refactor_platform_rs.coaches_coachees { +Table refactor_platform.coaches_coachees { id integer [primary key, unique, not null, increment] organization_id integer [note: 'The organization associated with this coaching relationship'] coach_id integer [note: 'The coach associated with this coaching relationship'] @@ -25,7 +25,7 @@ Table refactor_platform_rs.coaches_coachees { relationship coaching_relationship } -Table refactor_platform_rs.users { +Table refactor_platform.users { id integer [primary key, unique, not null, increment] email varchar first_name varchar @@ -37,19 +37,19 @@ Table refactor_platform_rs.users { created_at timestamp } -Table refactor_platform_rs.coachees { +Table refactor_platform.coachees { id integer [primary key, unique, not null, increment] user_id integer organization_id integer } -Table refactor_platform_rs.coaches { +Table refactor_platform.coaches { id integer [primary key, unique, not null, increment] user_id integer organization_id integer } -Table refactor_platform_rs.coaching_sessions { +Table refactor_platform.coaching_sessions { id integer [primary key, unique, not null, increment] coaches_coachees_id integer [note: 'The coaching relationship (i.e. what coach & coachee under what organization) associated with this coaching session'] date timestamp [note: 'The date and time of a session'] @@ -57,7 +57,7 @@ Table refactor_platform_rs.coaching_sessions { created_at timestamp } -Table refactor_platform_rs.overarching_goals { +Table refactor_platform.overarching_goals { id integer [primary key, unique, not null, increment] coaching_session_id integer [note: 'The coaching session that an overarching goal is associated with'] title varchar [note: 'A short description of an overarching goal'] @@ -69,7 +69,7 @@ Table refactor_platform_rs.overarching_goals { updated_at timestamp [note: 'The last date and time an overarching goal\'s fields were changed'] } -Table refactor_platform_rs.notes { +Table refactor_platform.notes { id integer [primary key, unique, not null, increment] coaching_session_id integer body varchar [note: 'Main text of the note supporting Markdown'] @@ -77,7 +77,7 @@ Table refactor_platform_rs.notes { updated_at timestamp [note: 'The last date and time an overarching note\'s fields were changed'] } -Table refactor_platform_rs.agreements { +Table refactor_platform.agreements { id integer [primary key, unique, not null, increment] coaching_session_id integer details varchar [note: 'Either a short or long description of an agreement reached between coach and coachee in a coaching session'] @@ -85,7 +85,7 @@ Table refactor_platform_rs.agreements { updated_at timestamp [note: 'The last date and time an overarching agreement\'s fields were changed'] } -Table refactor_platform_rs.actions { +Table refactor_platform.actions { id integer [primary key, unique, not null, increment] // The first session where this action was created // It will carry forward to every future session until @@ -99,30 +99,30 @@ Table refactor_platform_rs.actions { } // coaches_coachees relationships -Ref: refactor_platform_rs.coaches_coachees.organization_id - refactor_platform_rs.organizations.id -Ref: refactor_platform_rs.coaches_coachees.coachee_id - refactor_platform_rs.coachees.id -Ref: refactor_platform_rs.coaches_coachees.coach_id - refactor_platform_rs.coaches.id +Ref: refactor_platform.coaches_coachees.organization_id - refactor_platform.organizations.id +Ref: refactor_platform.coaches_coachees.coachee_id - refactor_platform.coachees.id +Ref: refactor_platform.coaches_coachees.coach_id - refactor_platform.coaches.id // coachees relationships -Ref: refactor_platform_rs.coachees.user_id - refactor_platform_rs.users.id -Ref: refactor_platform_rs.coachees.organization_id > refactor_platform_rs.organizations.id +Ref: refactor_platform.coachees.user_id - refactor_platform.users.id +Ref: refactor_platform.coachees.organization_id > refactor_platform.organizations.id // coaches relationships -Ref: refactor_platform_rs.coaches.user_id - refactor_platform_rs.users.id -Ref: refactor_platform_rs.coaches.organization_id > refactor_platform_rs.organizations.id +Ref: refactor_platform.coaches.user_id - refactor_platform.users.id +Ref: refactor_platform.coaches.organization_id > refactor_platform.organizations.id // overarching_goals relationships -Ref: refactor_platform_rs.overarching_goals.coaching_session_id - refactor_platform_rs.coaching_sessions.id -Ref: refactor_platform_rs.overarching_goals.completed_by_id - refactor_platform_rs.users.id +Ref: refactor_platform.overarching_goals.coaching_session_id - refactor_platform.coaching_sessions.id +Ref: refactor_platform.overarching_goals.completed_by_id - refactor_platform.users.id // notes relationships -Ref: refactor_platform_rs.notes.coaching_session_id - refactor_platform_rs.coaching_sessions.id +Ref: refactor_platform.notes.coaching_session_id - refactor_platform.coaching_sessions.id // coaching_sessions relationships -Ref: refactor_platform_rs.coaching_sessions.coaches_coachees_id > refactor_platform_rs.coaches_coachees.id +Ref: refactor_platform.coaching_sessions.coaches_coachees_id > refactor_platform.coaches_coachees.id // agreements relationships -Ref: refactor_platform_rs.agreements.coaching_session_id > refactor_platform_rs.coaching_sessions.id +Ref: refactor_platform.agreements.coaching_session_id > refactor_platform.coaching_sessions.id // actions relationships -Ref: refactor_platform_rs.actions.coaching_session_id > refactor_platform_rs.coaching_sessions.id +Ref: refactor_platform.actions.coaching_session_id > refactor_platform.coaching_sessions.id From 4b2a48fb019de843c8d8f2a4c6223991a541c44c Mon Sep 17 00:00:00 2001 From: Jim Hodapp Date: Sun, 28 Jan 2024 17:04:09 -0600 Subject: [PATCH 03/17] Update coaching_relationship comment --- docs/db/refactor_platform_rs.dbml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/db/refactor_platform_rs.dbml b/docs/db/refactor_platform_rs.dbml index 73d5edd6..47bf4224 100644 --- a/docs/db/refactor_platform_rs.dbml +++ b/docs/db/refactor_platform_rs.dbml @@ -8,7 +8,7 @@ Table refactor_platform.organizations { } // Coaching relationship type belonging to the refactor_platform schema -// from the perspective of the coachee +// from the perspective of the coach enum refactor_platform.coaching_relationship { client direct_report From ca5a6851f705dd456fbf6e48351ff1f64f962c87 Mon Sep 17 00:00:00 2001 From: Jim Hodapp Date: Sun, 28 Jan 2024 18:22:50 -0600 Subject: [PATCH 04/17] Update README.md new database creation SQL to use refactor_platform schema --- README.md | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 239ecc5b..1da39106 100644 --- a/README.md +++ b/README.md @@ -13,39 +13,48 @@ The platform itself is useful for professional independent coaches, informal men ### Set Up Database -Note: these are commands meant to run against a real Postgresql server. +Note: these are commands meant to run against a real Postgresql server with an admin level user. ```sql ---create user -CREATE USER refactor_rs WITH PASSWORD 'password'; ---create schema -CREATE SCHEMA IF NOT EXISTS refactor_platform_rs; ---Check to see that the schema exists -SELECT schema_name FROM information_schema.schemata; ---Grant schema access to user -GRANT CREATE ON SCHEMA public TO refactor_rs; +--create new database `refactor_platform` +CREATE DATABASE refactor_platform; ``` -### Generate a New Migration -```bash -sea-orm-cli migrate generate your_table_name +Change to the refactor_platform DB visually if using app like Postico, otherwise change using the +Postgresql CLI: + +```sh +\c refactor_platform +``` + +```sql +--create new database user `refactor` +CREATE USER refactor WITH PASSWORD 'password'; +--create a new schema owned by user `refactor` +CREATE SCHEMA IF NOT EXISTS refactor_platform AUTHORIZATION refactor; +--Check to see that the schema `refactor_platform` exists in the results +SELECT schema_name FROM information_schema.schemata; +--Grant all privileges on schema `refactor_platform` to user `refactor` +GRANT ALL PRIVILEGES ON SCHEMA refactor_platform TO refactor; ``` ### Run Migrations -Note: this assumes a database name of `refactor_platform_rs` +Note: this assumes a database name of `refactor_platform` ```bash -DATABASE_URL=postgres://refactor_rs:password@localhost:5432/refactor_platform_rs sea-orm-cli migrate up -s refactor_platform_rs +DATABASE_URL=postgres://refactor:password@localhost:5432/refactor_platform sea-orm-cli migrate up -s refactor_platform_rs ``` -### Generate Entity from Database +### Generate a new Entity from Database ```bash - DATABASE_URL=postgres://refactor_rs:password@localhost:5432/refactor_platform_rs sea-orm-cli generate entity -s refactor_platform_rs -o entity/src + DATABASE_URL=postgres://refactor:password@localhost:5432/refactor_platform sea-orm-cli generate entity -s refactor_platform -o entity/src ``` ## Project Directory Structure +`docs` - project documentation including architectural records, DB schema, API docs, etc + `entity_api` - data operations on the various `Entity` models `entity` - shape of the data models and the relationships to each other From 9de6e9fc65caa203ee8957ed13724996aef7ee33 Mon Sep 17 00:00:00 2001 From: Jim Hodapp Date: Mon, 29 Jan 2024 14:58:00 -0600 Subject: [PATCH 05/17] Added logo URI field to organizations --- docs/db/refactor_platform_rs.dbml | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/db/refactor_platform_rs.dbml b/docs/db/refactor_platform_rs.dbml index 47bf4224..f4e59564 100644 --- a/docs/db/refactor_platform_rs.dbml +++ b/docs/db/refactor_platform_rs.dbml @@ -4,6 +4,7 @@ Table refactor_platform.organizations { id integer [primary key, unique, not null, increment] name varchar [note: 'The name of the organization that the coach <--> coachee belong to'] + logo varchar [note: 'A URI pointing to the organization\'s logo icon file'] created_at timestamp } From 90bd8f7afabe565833106d207240267c89050685 Mon Sep 17 00:00:00 2001 From: Jim Hodapp Date: Sun, 4 Feb 2024 11:57:45 -0600 Subject: [PATCH 06/17] Add a URL to users capturing their github profile URL --- docs/db/refactor_platform_rs.dbml | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/db/refactor_platform_rs.dbml b/docs/db/refactor_platform_rs.dbml index f4e59564..9b2df3cd 100644 --- a/docs/db/refactor_platform_rs.dbml +++ b/docs/db/refactor_platform_rs.dbml @@ -35,6 +35,7 @@ Table refactor_platform.users { password varchar timezone timezone github_username varchar // Specifically GH for now, can generalize later + github_profile_url varchar created_at timestamp } From f126cb63eb597774c8e86268ebea568d6203274b Mon Sep 17 00:00:00 2001 From: Caleb Bourg Date: Tue, 13 Feb 2024 13:13:44 -0800 Subject: [PATCH 07/17] run sql file as base_migration --- README.md | 2 +- migration/src/lib.rs | 10 +--- .../m20230930_182906_create_organizations.rs | 39 ------------- ...m20230930_195750_coaching_relationships.rs | 55 ------------------- migration/src/m20230930_200501_users.rs | 50 ----------------- .../src/m20240211_174355_base_migration.rs | 36 ++++++++++++ 6 files changed, 39 insertions(+), 153 deletions(-) delete mode 100644 migration/src/m20230930_182906_create_organizations.rs delete mode 100644 migration/src/m20230930_195750_coaching_relationships.rs delete mode 100644 migration/src/m20230930_200501_users.rs create mode 100644 migration/src/m20240211_174355_base_migration.rs diff --git a/README.md b/README.md index 1da39106..926a5d4a 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ GRANT ALL PRIVILEGES ON SCHEMA refactor_platform TO refactor; Note: this assumes a database name of `refactor_platform` ```bash -DATABASE_URL=postgres://refactor:password@localhost:5432/refactor_platform sea-orm-cli migrate up -s refactor_platform_rs +DATABASE_URL=postgres://refactor:password@localhost:5432/refactor_platform sea-orm-cli migrate up -s refactor_platform ``` ### Generate a new Entity from Database diff --git a/migration/src/lib.rs b/migration/src/lib.rs index 10f25928..0a61a398 100644 --- a/migration/src/lib.rs +++ b/migration/src/lib.rs @@ -1,18 +1,12 @@ pub use sea_orm_migration::prelude::*; -mod m20230930_182906_create_organizations; -mod m20230930_195750_coaching_relationships; -mod m20230930_200501_users; +mod m20240211_174355_base_migration; pub struct Migrator; #[async_trait::async_trait] impl MigratorTrait for Migrator { fn migrations() -> Vec> { - vec![ - Box::new(m20230930_182906_create_organizations::Migration), - Box::new(m20230930_195750_coaching_relationships::Migration), - Box::new(m20230930_200501_users::Migration), - ] + vec![Box::new(m20240211_174355_base_migration::Migration)] } } diff --git a/migration/src/m20230930_182906_create_organizations.rs b/migration/src/m20230930_182906_create_organizations.rs deleted file mode 100644 index 8d8d3355..00000000 --- a/migration/src/m20230930_182906_create_organizations.rs +++ /dev/null @@ -1,39 +0,0 @@ -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 - .create_table( - Table::create() - .table(Organizations::Table) - .if_not_exists() - .col( - ColumnDef::new(Organizations::Id) - .integer() - .not_null() - .auto_increment() - .primary_key(), - ) - .col(ColumnDef::new(Organizations::Name).string().not_null()) - .to_owned(), - ) - .await - } - - async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .drop_table(Table::drop().table(Organizations::Table).to_owned()) - .await - } -} - -#[derive(DeriveIden)] -enum Organizations { - Table, - Id, - Name, -} diff --git a/migration/src/m20230930_195750_coaching_relationships.rs b/migration/src/m20230930_195750_coaching_relationships.rs deleted file mode 100644 index 66aa5015..00000000 --- a/migration/src/m20230930_195750_coaching_relationships.rs +++ /dev/null @@ -1,55 +0,0 @@ -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 - .create_table( - Table::create() - .table(CoachingRelationships::Table) - .if_not_exists() - .col( - ColumnDef::new(CoachingRelationships::Id) - .integer() - .not_null() - .auto_increment() - .primary_key(), - ) - .col( - ColumnDef::new(CoachingRelationships::CoacheeId) - .string() - .not_null(), - ) - .col( - ColumnDef::new(CoachingRelationships::CoachId) - .string() - .not_null(), - ) - .col( - ColumnDef::new(CoachingRelationships::OrganizationId) - .string() - .not_null(), - ) - .to_owned(), - ) - .await - } - - async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .drop_table(Table::drop().table(CoachingRelationships::Table).to_owned()) - .await - } -} - -#[derive(DeriveIden)] -enum CoachingRelationships { - Table, - Id, - CoacheeId, - CoachId, - OrganizationId, -} diff --git a/migration/src/m20230930_200501_users.rs b/migration/src/m20230930_200501_users.rs deleted file mode 100644 index d3123ccb..00000000 --- a/migration/src/m20230930_200501_users.rs +++ /dev/null @@ -1,50 +0,0 @@ -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 - .create_table( - Table::create() - .table(Users::Table) - .if_not_exists() - .col( - ColumnDef::new(Users::Id) - .integer() - .not_null() - .auto_increment() - .primary_key(), - ) - .col( - ColumnDef::new(Users::Email) - .string() - .not_null() - .unique_key(), - ) - .col(ColumnDef::new(Users::Password).string().not_null()) - .col(ColumnDef::new(Users::FirstName).string().not_null()) - .col(ColumnDef::new(Users::LastName).string().not_null()) - .to_owned(), - ) - .await - } - - async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .drop_table(Table::drop().table(Users::Table).to_owned()) - .await - } -} - -#[derive(DeriveIden)] -enum Users { - Table, - Id, - Email, - Password, - FirstName, - LastName, -} diff --git a/migration/src/m20240211_174355_base_migration.rs b/migration/src/m20240211_174355_base_migration.rs new file mode 100644 index 00000000..b3fdff6d --- /dev/null +++ b/migration/src/m20240211_174355_base_migration.rs @@ -0,0 +1,36 @@ +use sea_orm_migration::prelude::*; +use std::fs::File; +use std::io::Read; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + let db = manager.get_connection(); + + let stringify_err = |err| -> DbErr { + let string = format!("Migration error: {:?}", err); + DbErr::Migration(string) + }; + let mut file = + File::open("migration/src/refactor_platform_rs.sql").map_err(stringify_err)?; + + let mut sql = String::new(); + + file.read_to_string(&mut sql).map_err(stringify_err)?; + + // format sql as valid sql statements + sql = sql.replace(";", ";\n"); + + db.execute_unprepared(&sql).await?; + + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + // Replace the sample below with your own migration scripts + todo!(); + } +} From b9a41dda59259f5de6f41a1b2e4bd10ae3305216 Mon Sep 17 00:00:00 2001 From: Caleb Bourg Date: Sat, 17 Feb 2024 13:45:27 -0500 Subject: [PATCH 08/17] fixup --- .gitignore | 1 + README.md | 41 ++++- docs/db/refactor_platform_rs.dbml | 99 +++++------- .../src/m20240211_174355_base_migration.rs | 15 +- migration/src/refactor_platform_rs.sql | 150 ++++++++++++++++++ scripts/rebuild_db.sh | 68 ++++++++ 6 files changed, 308 insertions(+), 66 deletions(-) create mode 100644 migration/src/refactor_platform_rs.sql create mode 100755 scripts/rebuild_db.sh diff --git a/.gitignore b/.gitignore index ea8c4bf7..b3041e56 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +dbml-error.log diff --git a/README.md b/README.md index 926a5d4a..49e44b4a 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,46 @@ The platform itself is useful for professional independent coaches, informal men ## Basic Local DB Setup and Management -### Set Up Database +## Running the Database Setup Script + +1. Ensure you have PostgreSQL installed and running on your machine. If you're using macOS, you can install it with Homebrew: + + ```shell + brew install postgresql + brew services start postgresql + ``` + +2. Make sure you have the `dbml2sql` tool installed. You can install it with npm: + + ```shell + npm install -g dbml2sql + ``` + +3. Make the script executable: + + ```shell + chmod +x rebuild_db.sh + ``` + +4. Run the script with default settings: + + ```shell + ./rebuild_db.sh + ``` + + This will create a database named `refactor_platform`, a user named `refactor`, and a schema named `refactor_platform`. + +5. If you want to use different settings, you can provide them as arguments to the script: + + ```shell + ./rebuild_db.sh my_database my_user my_schema + ``` + + This will create a database named `my_database`, a user named `my_user`, and a schema named `my_schema`. + +Please note that the script assumes that the password for the new PostgreSQL user is `password`. If you want to use a different password, you'll need to modify the script accordingly. + +### Set Up Database Manually Note: these are commands meant to run against a real Postgresql server with an admin level user. diff --git a/docs/db/refactor_platform_rs.dbml b/docs/db/refactor_platform_rs.dbml index 9b2df3cd..45e7bac7 100644 --- a/docs/db/refactor_platform_rs.dbml +++ b/docs/db/refactor_platform_rs.dbml @@ -2,97 +2,81 @@ // Docs: https://dbml.dbdiagram.io/docs Table refactor_platform.organizations { - id integer [primary key, unique, not null, increment] + id uuid [primary key, unique, not null] name varchar [note: 'The name of the organization that the coach <--> coachee belong to'] logo varchar [note: 'A URI pointing to the organization\'s logo icon file'] - created_at timestamp + created_at timestamp + updated_at timestamp [note: 'The last date and time fields were changed'] } // Coaching relationship type belonging to the refactor_platform schema // from the perspective of the coach -enum refactor_platform.coaching_relationship { - client - direct_report -} - -// Declares a coach <--> coachee coaching relationship -// E.g. Manager <--> Software Engineer direct report -// E.g. Independent coach <--> Software Engineer client -Table refactor_platform.coaches_coachees { - id integer [primary key, unique, not null, increment] - organization_id integer [note: 'The organization associated with this coaching relationship'] - coach_id integer [note: 'The coach associated with this coaching relationship'] - coachee_id integer [note: 'The coachee associated with this coaching relationship'] - relationship coaching_relationship +Table refactor_platform.coaching_relationships { + id uuid [primary key, unique, not null] + organization_id uuid [not null, note: 'The organization associated with this coaching relationship'] + coach_id uuid [not null, note: 'The coach associated with this coaching relationship'] + coachee_id uuid [not null, note: 'The coachee associated with this coaching relationship'] + created_at timestamp + updated_at timestamp [note: 'The last date and time fields were changed'] } Table refactor_platform.users { - id integer [primary key, unique, not null, increment] + id uuid [primary key, unique, not null] email varchar first_name varchar last_name varchar display_name varchar [note: 'If a user wants to go by something other than first & last names'] password varchar - timezone timezone + timezone varchar github_username varchar // Specifically GH for now, can generalize later github_profile_url varchar created_at timestamp -} - -Table refactor_platform.coachees { - id integer [primary key, unique, not null, increment] - user_id integer - organization_id integer -} - -Table refactor_platform.coaches { - id integer [primary key, unique, not null, increment] - user_id integer - organization_id integer + updated_at timestamp [note: 'The last date and time fields were changed'] } Table refactor_platform.coaching_sessions { - id integer [primary key, unique, not null, increment] - coaches_coachees_id integer [note: 'The coaching relationship (i.e. what coach & coachee under what organization) associated with this coaching session'] + id uuid [primary key, unique, not null] + coaching_relationship_id uuid [not null, note: 'The coaching relationship (i.e. what coach & coachee under what organization) associated with this coaching session'] date timestamp [note: 'The date and time of a session'] - timezone timezone [note: 'The baseline timezone used for the `date` field'] + timezone varchar [note: 'The baseline timezone used for the `date` field'] created_at timestamp + updated_at timestamp [note: 'The last date and time fields were changed'] } Table refactor_platform.overarching_goals { - id integer [primary key, unique, not null, increment] - coaching_session_id integer [note: 'The coaching session that an overarching goal is associated with'] + id uuid [primary key, unique, not null] + coaching_session_id uuid [note: 'The coaching session that an overarching goal is associated with'] title varchar [note: 'A short description of an overarching goal'] details varchar [note: 'A long description of an overarching goal'] - completed boolean // May be unnecessary if there's a valid completed_at timestamp completed_at timestamp [note: 'The date and time an overarching goal was completed'] - completed_by_id integer [note: 'The user that successfully completed an overarching goal'] created_at timestamp - updated_at timestamp [note: 'The last date and time an overarching goal\'s fields were changed'] + updated_at timestamp [note: 'The last date and time fields were changed'] } Table refactor_platform.notes { - id integer [primary key, unique, not null, increment] - coaching_session_id integer + id uuid [primary key, unique, not null] + coaching_session_id uuid [not null] body varchar [note: 'Main text of the note supporting Markdown'] + user_id uuid [not null, note: 'User that created (owns) the note'] created_at timestamp updated_at timestamp [note: 'The last date and time an overarching note\'s fields were changed'] } Table refactor_platform.agreements { - id integer [primary key, unique, not null, increment] - coaching_session_id integer + id uuid [primary key, unique, not null] + coaching_session_id uuid [not null] details varchar [note: 'Either a short or long description of an agreement reached between coach and coachee in a coaching session'] + user_id uuid [not null, note: 'User that created (owns) the agreement'] created_at timestamp updated_at timestamp [note: 'The last date and time an overarching agreement\'s fields were changed'] } Table refactor_platform.actions { - id integer [primary key, unique, not null, increment] + id uuid [primary key, unique, not null] // The first session where this action was created // It will carry forward to every future session until // its due_by is passed or it was completed by the coachee - coaching_session_id integer + coaching_session_id uuid [not null] due_by timestamp completed boolean // May be unnecessary if there's a valid completed_at timestamp completed_at timestamp @@ -100,31 +84,24 @@ Table refactor_platform.actions { updated_at timestamp } -// coaches_coachees relationships -Ref: refactor_platform.coaches_coachees.organization_id - refactor_platform.organizations.id -Ref: refactor_platform.coaches_coachees.coachee_id - refactor_platform.coachees.id -Ref: refactor_platform.coaches_coachees.coach_id - refactor_platform.coaches.id - -// coachees relationships -Ref: refactor_platform.coachees.user_id - refactor_platform.users.id -Ref: refactor_platform.coachees.organization_id > refactor_platform.organizations.id +// coaching_relationships relationships +Ref: refactor_platform.coaching_relationships.organization_id > refactor_platform.organizations.id +Ref: refactor_platform.coaching_relationships.coachee_id > refactor_platform.users.id +Ref: refactor_platform.coaching_relationships.coach_id > refactor_platform.users.id -// coaches relationships -Ref: refactor_platform.coaches.user_id - refactor_platform.users.id -Ref: refactor_platform.coaches.organization_id > refactor_platform.organizations.id +// coaching_sessions relationships +Ref: refactor_platform.coaching_sessions.coaching_relationship_id > refactor_platform.coaching_relationships.id // overarching_goals relationships -Ref: refactor_platform.overarching_goals.coaching_session_id - refactor_platform.coaching_sessions.id -Ref: refactor_platform.overarching_goals.completed_by_id - refactor_platform.users.id +Ref: refactor_platform.overarching_goals.coaching_session_id > refactor_platform.coaching_sessions.id // notes relationships -Ref: refactor_platform.notes.coaching_session_id - refactor_platform.coaching_sessions.id - -// coaching_sessions relationships -Ref: refactor_platform.coaching_sessions.coaches_coachees_id > refactor_platform.coaches_coachees.id +Ref: refactor_platform.notes.coaching_session_id > refactor_platform.coaching_sessions.id +Ref: refactor_platform.notes.user_id > refactor_platform.users.id // agreements relationships Ref: refactor_platform.agreements.coaching_session_id > refactor_platform.coaching_sessions.id +Ref: refactor_platform.agreements.user_id > refactor_platform.users.id // actions relationships Ref: refactor_platform.actions.coaching_session_id > refactor_platform.coaching_sessions.id diff --git a/migration/src/m20240211_174355_base_migration.rs b/migration/src/m20240211_174355_base_migration.rs index b3fdff6d..7eb2b39f 100644 --- a/migration/src/m20240211_174355_base_migration.rs +++ b/migration/src/m20240211_174355_base_migration.rs @@ -21,8 +21,7 @@ impl MigrationTrait for Migration { file.read_to_string(&mut sql).map_err(stringify_err)?; - // format sql as valid sql statements - sql = sql.replace(";", ";\n"); + process_sql(&sql); db.execute_unprepared(&sql).await?; @@ -30,7 +29,15 @@ impl MigrationTrait for Migration { } async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - // Replace the sample below with your own migration scripts - todo!(); + Ok(()) } } + +// format sql as valid sql statements +fn process_sql(sql: &str) -> String { + sql.replace(";", ";\n") + .lines() + .filter(|line| !line.trim().starts_with("--")) + .collect::>() + .join("\n") +} diff --git a/migration/src/refactor_platform_rs.sql b/migration/src/refactor_platform_rs.sql new file mode 100644 index 00000000..ac84af0e --- /dev/null +++ b/migration/src/refactor_platform_rs.sql @@ -0,0 +1,150 @@ +-- SQL dump generated using DBML (dbml-lang.org) +-- Database: PostgreSQL +-- Generated at: 2024-02-17T18:41:48.352Z + + +CREATE TABLE "refactor_platform"."organizations" ( + "id" uuid UNIQUE PRIMARY KEY NOT NULL, + "name" varchar, + "logo" varchar, + "created_at" timestamp, + "updated_at" timestamp +); + +CREATE TABLE "refactor_platform"."coaching_relationships" ( + "id" uuid UNIQUE PRIMARY KEY NOT NULL, + "organization_id" uuid NOT NULL, + "coach_id" uuid NOT NULL, + "coachee_id" uuid NOT NULL, + "created_at" timestamp, + "updated_at" timestamp +); + +CREATE TABLE "refactor_platform"."users" ( + "id" uuid UNIQUE PRIMARY KEY NOT NULL, + "email" varchar, + "first_name" varchar, + "last_name" varchar, + "display_name" varchar, + "password" varchar, + "timezone" varchar, + "github_username" varchar, + "github_profile_url" varchar, + "created_at" timestamp, + "updated_at" timestamp +); + +CREATE TABLE "refactor_platform"."coaching_sessions" ( + "id" uuid UNIQUE PRIMARY KEY NOT NULL, + "coaching_relationship_id" uuid NOT NULL, + "date" timestamp, + "timezone" varchar, + "created_at" timestamp, + "updated_at" timestamp +); + +CREATE TABLE "refactor_platform"."overarching_goals" ( + "id" uuid UNIQUE PRIMARY KEY NOT NULL, + "coaching_session_id" uuid, + "title" varchar, + "details" varchar, + "completed_at" timestamp, + "created_at" timestamp, + "updated_at" timestamp +); + +CREATE TABLE "refactor_platform"."notes" ( + "id" uuid UNIQUE PRIMARY KEY NOT NULL, + "coaching_session_id" uuid NOT NULL, + "body" varchar, + "user_id" uuid NOT NULL, + "created_at" timestamp, + "updated_at" timestamp +); + +CREATE TABLE "refactor_platform"."agreements" ( + "id" uuid UNIQUE PRIMARY KEY NOT NULL, + "coaching_session_id" uuid NOT NULL, + "details" varchar, + "user_id" uuid NOT NULL, + "created_at" timestamp, + "updated_at" timestamp +); + +CREATE TABLE "refactor_platform"."actions" ( + "id" uuid UNIQUE PRIMARY KEY NOT NULL, + "coaching_session_id" uuid NOT NULL, + "due_by" timestamp, + "completed" boolean, + "completed_at" timestamp, + "created_at" timestamp, + "updated_at" timestamp +); + +COMMENT ON COLUMN "refactor_platform"."organizations"."name" IS 'The name of the organization that the coach <--> coachee belong to'; + +COMMENT ON COLUMN "refactor_platform"."organizations"."logo" IS 'A URI pointing to the organization''s logo icon file'; + +COMMENT ON COLUMN "refactor_platform"."organizations"."updated_at" IS 'The last date and time fields were changed'; + +COMMENT ON COLUMN "refactor_platform"."coaching_relationships"."organization_id" IS 'The organization associated with this coaching relationship'; + +COMMENT ON COLUMN "refactor_platform"."coaching_relationships"."coach_id" IS 'The coach associated with this coaching relationship'; + +COMMENT ON COLUMN "refactor_platform"."coaching_relationships"."coachee_id" IS 'The coachee associated with this coaching relationship'; + +COMMENT ON COLUMN "refactor_platform"."coaching_relationships"."updated_at" IS 'The last date and time fields were changed'; + +COMMENT ON COLUMN "refactor_platform"."users"."display_name" IS 'If a user wants to go by something other than first & last names'; + +COMMENT ON COLUMN "refactor_platform"."users"."updated_at" IS 'The last date and time fields were changed'; + +COMMENT ON COLUMN "refactor_platform"."coaching_sessions"."coaching_relationship_id" IS 'The coaching relationship (i.e. what coach & coachee under what organization) associated with this coaching session'; + +COMMENT ON COLUMN "refactor_platform"."coaching_sessions"."date" IS 'The date and time of a session'; + +COMMENT ON COLUMN "refactor_platform"."coaching_sessions"."timezone" IS 'The baseline timezone used for the `date` field'; + +COMMENT ON COLUMN "refactor_platform"."coaching_sessions"."updated_at" IS 'The last date and time fields were changed'; + +COMMENT ON COLUMN "refactor_platform"."overarching_goals"."coaching_session_id" IS 'The coaching session that an overarching goal is associated with'; + +COMMENT ON COLUMN "refactor_platform"."overarching_goals"."title" IS 'A short description of an overarching goal'; + +COMMENT ON COLUMN "refactor_platform"."overarching_goals"."details" IS 'A long description of an overarching goal'; + +COMMENT ON COLUMN "refactor_platform"."overarching_goals"."completed_at" IS 'The date and time an overarching goal was completed'; + +COMMENT ON COLUMN "refactor_platform"."overarching_goals"."updated_at" IS 'The last date and time fields were changed'; + +COMMENT ON COLUMN "refactor_platform"."notes"."body" IS 'Main text of the note supporting Markdown'; + +COMMENT ON COLUMN "refactor_platform"."notes"."user_id" IS 'User that created (owns) the note'; + +COMMENT ON COLUMN "refactor_platform"."notes"."updated_at" IS 'The last date and time an overarching note''s fields were changed'; + +COMMENT ON COLUMN "refactor_platform"."agreements"."details" IS 'Either a short or long description of an agreement reached between coach and coachee in a coaching session'; + +COMMENT ON COLUMN "refactor_platform"."agreements"."user_id" IS 'User that created (owns) the agreement'; + +COMMENT ON COLUMN "refactor_platform"."agreements"."updated_at" IS 'The last date and time an overarching agreement''s fields were changed'; + +ALTER TABLE "refactor_platform"."coaching_relationships" ADD FOREIGN KEY ("organization_id") REFERENCES "refactor_platform"."organizations" ("id"); + +ALTER TABLE "refactor_platform"."coaching_relationships" ADD FOREIGN KEY ("coachee_id") REFERENCES "refactor_platform"."users" ("id"); + +ALTER TABLE "refactor_platform"."coaching_relationships" ADD FOREIGN KEY ("coach_id") REFERENCES "refactor_platform"."users" ("id"); + +ALTER TABLE "refactor_platform"."coaching_sessions" ADD FOREIGN KEY ("coaching_relationship_id") REFERENCES "refactor_platform"."coaching_relationships" ("id"); + +ALTER TABLE "refactor_platform"."overarching_goals" ADD FOREIGN KEY ("coaching_session_id") REFERENCES "refactor_platform"."coaching_sessions" ("id"); + +ALTER TABLE "refactor_platform"."notes" ADD FOREIGN KEY ("coaching_session_id") REFERENCES "refactor_platform"."coaching_sessions" ("id"); + +ALTER TABLE "refactor_platform"."notes" ADD FOREIGN KEY ("user_id") REFERENCES "refactor_platform"."users" ("id"); + +ALTER TABLE "refactor_platform"."agreements" ADD FOREIGN KEY ("coaching_session_id") REFERENCES "refactor_platform"."coaching_sessions" ("id"); + +ALTER TABLE "refactor_platform"."agreements" ADD FOREIGN KEY ("user_id") REFERENCES "refactor_platform"."users" ("id"); + +ALTER TABLE "refactor_platform"."actions" ADD FOREIGN KEY ("coaching_session_id") REFERENCES "refactor_platform"."coaching_sessions" ("id"); diff --git a/scripts/rebuild_db.sh b/scripts/rebuild_db.sh new file mode 100755 index 00000000..5421d1f9 --- /dev/null +++ b/scripts/rebuild_db.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +# Define default variables +DB_NAME=${1:-"refactor_platform"} +DB_USER=${2:-"refactor"} +SCHEMA_NAME=${3:-"refactor_platform"} + +echo "Using the following configuration:" +echo "Database Name: $DB_NAME" +echo "Database User: $DB_USER" +echo "Schema Name: $SCHEMA_NAME" + +# Check if postgres is installed with homebrew and if not print message saying to install postgres with homebrew and exit +brew list postgresql > /dev/null 2>&1 || { echo "Postgres is not installed with homebrew. Please install postgres with homebrew and try again"; exit 1; } + +# Ensure postgres is running and start postgres with homebrew if it is not running +pg_ctl status > /dev/null 2>&1 || { echo "Starting Postgres..."; brew services start postgresql; } + +# Check if the postgres database exists and create it if it doesn't +POSTGRES_DB_EXISTS=$(psql -U postgres -tAc "SELECT 1 FROM pg_database WHERE datname='postgres'") +if [ "$POSTGRES_DB_EXISTS" != "1" ]; then + echo "Creating 'postgres' database..." + createdb -U postgres postgres || { echo "Failed to create 'postgres' database"; exit 1; } +fi + +# Check if the user exists and create it if it doesn't +USER_EXISTS=$(psql -U postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='$DB_USER'") +if [ "$USER_EXISTS" != "1" ]; then + echo "Creating user $DB_USER..." + psql -U postgres -c "CREATE USER $DB_USER;" || { echo "Failed to create user $DB_USER"; exit 1; } +fi + +# Check if the database exists +DB_EXISTS=$(psql -U postgres -tAc "SELECT 1 FROM pg_database WHERE datname='$DB_NAME'") + +# If the database exists, drop it +if [ "$DB_EXISTS" = "1" ]; then + echo "Database $DB_NAME exists. Dropping the database..." + psql -U postgres -c "DROP DATABASE IF EXISTS $DB_NAME;" || { echo "Failed to drop database $DB_NAME"; exit 1; } +fi + +echo "Creating the database $DB_NAME..." +psql -U postgres -c "CREATE DATABASE $DB_NAME;" || { echo "Failed to create database $DB_NAME"; exit 1; } + +echo "Granting privileges to $DB_USER on $DB_NAME..." +psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;" + +# Check if the schema exists +SCHEMA_EXISTS=$(psql -U $DB_USER -d $DB_NAME -tAc "SELECT 1 FROM information_schema.schemata WHERE schema_name = '$SCHEMA_NAME'") + +# If the schema does not exist, create it +if [ "$SCHEMA_EXISTS" != "1" ]; then + echo "Creating schema $SCHEMA_NAME..." + psql -U $DB_USER -d $DB_NAME -c "CREATE SCHEMA $SCHEMA_NAME;" || { echo "Failed to create schema $SCHEMA_NAME"; exit 1; } +fi + +# Generating SQL for the migrations using dbml2sql +echo "Generating SQL for the migrations..." +dbml2sql docs/db/refactor_platform_rs.dbml -o migration/src/refactor_platform_rs.sql || { echo "Error generating SQL file"; exit 1; } + +# Remove the line to create a schema from the generated SQL file +echo "Modifying the generated SQL file..." +sed -i '' '/CREATE SCHEMA/d' migration/src/refactor_platform_rs.sql + +echo "Running the migrations..." +DATABASE_URL=postgres://$DB_USER:password@localhost:5432/$DB_NAME sea-orm-cli migrate up -s $SCHEMA_NAME || { echo "Failed to run migrations"; exit 1; } + +echo "Database setup and migrations completed successfully" \ No newline at end of file From e95bfa7d0f302a06fbe37f88d4b7bbe296b7327f Mon Sep 17 00:00:00 2001 From: Jim Hodapp Date: Sat, 17 Feb 2024 19:02:49 -0600 Subject: [PATCH 09/17] Make the rebuild.sh script more OS-agnostic. Also migrate the codebase to work with UUID and timestamps with timezone support.. --- Cargo.lock | 10 +++- README.md | 20 +++---- docs/db/refactor_platform_rs.dbml | 57 +++++++++--------- entity/Cargo.toml | 4 +- entity/src/coaching_relationship.rs | 5 +- entity/src/lib.rs | 4 +- entity/src/organization.rs | 7 +-- entity/src/user.rs | 12 +++- entity_api/src/user.rs | 18 +++++- .../src/m20240211_174355_base_migration.rs | 4 +- migration/src/refactor_platform_rs.sql | 59 +++++++++---------- scripts/rebuild_db.sh | 13 +++- service/Cargo.toml | 3 +- web/Cargo.toml | 3 +- web/src/lib.rs | 2 +- 15 files changed, 125 insertions(+), 96 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1b333958..e2b2feae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -630,15 +630,17 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" dependencies = [ "android-tzdata", "iana-time-zone", + "js-sys", "num-traits", "serde", - "windows-targets 0.48.5", + "wasm-bindgen", + "windows-targets 0.52.0", ] [[package]] @@ -851,8 +853,10 @@ name = "entity" version = "0.1.0" dependencies = [ "axum-login", + "chrono", "sea-orm", "serde", + "uuid", ] [[package]] diff --git a/README.md b/README.md index 49e44b4a..3fe14255 100644 --- a/README.md +++ b/README.md @@ -13,37 +13,31 @@ The platform itself is useful for professional independent coaches, informal men ## Running the Database Setup Script -1. Ensure you have PostgreSQL installed and running on your machine. If you're using macOS, you can install it with Homebrew: +1. Ensure you have PostgreSQL installed and running on your machine. If you're using macOS, you can use +[Postgres.app](https://postgresapp.com/) or install it with Homebrew: ```shell brew install postgresql - brew services start postgresql ``` 2. Make sure you have the `dbml2sql` tool installed. You can install it with npm: ```shell - npm install -g dbml2sql + npm install -g @dbml/cli ``` -3. Make the script executable: +3. Run the script with default settings: ```shell - chmod +x rebuild_db.sh - ``` - -4. Run the script with default settings: - - ```shell - ./rebuild_db.sh + ./scripts/rebuild_db.sh ``` This will create a database named `refactor_platform`, a user named `refactor`, and a schema named `refactor_platform`. -5. If you want to use different settings, you can provide them as arguments to the script: +4. If you want to use different settings, you can provide them as arguments to the script: ```shell - ./rebuild_db.sh my_database my_user my_schema + ./scripts/rebuild_db.sh my_database my_user my_schema ``` This will create a database named `my_database`, a user named `my_user`, and a schema named `my_schema`. diff --git a/docs/db/refactor_platform_rs.dbml b/docs/db/refactor_platform_rs.dbml index 45e7bac7..c825d7c3 100644 --- a/docs/db/refactor_platform_rs.dbml +++ b/docs/db/refactor_platform_rs.dbml @@ -2,86 +2,85 @@ // Docs: https://dbml.dbdiagram.io/docs Table refactor_platform.organizations { - id uuid [primary key, unique, not null] + id uuid [primary key, unique, not null, default: `gen_random_uuid()`] name varchar [note: 'The name of the organization that the coach <--> coachee belong to'] logo varchar [note: 'A URI pointing to the organization\'s logo icon file'] - created_at timestamp - updated_at timestamp [note: 'The last date and time fields were changed'] + created_at timestamptz [default: `now()`] + updated_at timestamptz [default: `now()`, note: 'The last date and time fields were changed'] } // Coaching relationship type belonging to the refactor_platform schema // from the perspective of the coach Table refactor_platform.coaching_relationships { - id uuid [primary key, unique, not null] + id uuid [primary key, unique, not null, default: `gen_random_uuid()`] organization_id uuid [not null, note: 'The organization associated with this coaching relationship'] coach_id uuid [not null, note: 'The coach associated with this coaching relationship'] coachee_id uuid [not null, note: 'The coachee associated with this coaching relationship'] - created_at timestamp - updated_at timestamp [note: 'The last date and time fields were changed'] + created_at timestamptz [default: `now()`] + updated_at timestamptz [default: `now()`, note: 'The last date and time fields were changed'] } Table refactor_platform.users { - id uuid [primary key, unique, not null] - email varchar + id uuid [primary key, unique, not null, default: `gen_random_uuid()`] + email varchar [unique, not null] first_name varchar last_name varchar display_name varchar [note: 'If a user wants to go by something other than first & last names'] password varchar - timezone varchar github_username varchar // Specifically GH for now, can generalize later github_profile_url varchar - created_at timestamp - updated_at timestamp [note: 'The last date and time fields were changed'] + created_at timestamptz [default: `now()`] + updated_at timestamptz [default: `now()`, note: 'The last date and time fields were changed'] } Table refactor_platform.coaching_sessions { - id uuid [primary key, unique, not null] + id uuid [primary key, unique, not null, default: `gen_random_uuid()`] coaching_relationship_id uuid [not null, note: 'The coaching relationship (i.e. what coach & coachee under what organization) associated with this coaching session'] date timestamp [note: 'The date and time of a session'] timezone varchar [note: 'The baseline timezone used for the `date` field'] - created_at timestamp - updated_at timestamp [note: 'The last date and time fields were changed'] + created_at timestamptz [default: `now()`] + updated_at timestamptz [default: `now()`, note: 'The last date and time fields were changed'] } Table refactor_platform.overarching_goals { - id uuid [primary key, unique, not null] + id uuid [primary key, unique, not null, default: `gen_random_uuid()`] coaching_session_id uuid [note: 'The coaching session that an overarching goal is associated with'] title varchar [note: 'A short description of an overarching goal'] details varchar [note: 'A long description of an overarching goal'] - completed_at timestamp [note: 'The date and time an overarching goal was completed'] - created_at timestamp - updated_at timestamp [note: 'The last date and time fields were changed'] + completed_at timestamptz [note: 'The date and time an overarching goal was completed'] + created_at timestamptz [default: `now()`] + updated_at timestamptz [default: `now()`, note: 'The last date and time fields were changed'] } Table refactor_platform.notes { - id uuid [primary key, unique, not null] + id uuid [primary key, unique, not null, default: `gen_random_uuid()`] coaching_session_id uuid [not null] body varchar [note: 'Main text of the note supporting Markdown'] user_id uuid [not null, note: 'User that created (owns) the note'] - created_at timestamp - updated_at timestamp [note: 'The last date and time an overarching note\'s fields were changed'] + created_at timestamptz [default: `now()`] + updated_at timestamptz [default: `now()`, note: 'The last date and time an overarching note\'s fields were changed'] } Table refactor_platform.agreements { - id uuid [primary key, unique, not null] + id uuid [primary key, unique, not null, default: `gen_random_uuid()`] coaching_session_id uuid [not null] details varchar [note: 'Either a short or long description of an agreement reached between coach and coachee in a coaching session'] user_id uuid [not null, note: 'User that created (owns) the agreement'] - created_at timestamp - updated_at timestamp [note: 'The last date and time an overarching agreement\'s fields were changed'] + created_at timestamptz [default: `now()`] + updated_at timestamptz [default: `now()`, note: 'The last date and time an overarching agreement\'s fields were changed'] } Table refactor_platform.actions { - id uuid [primary key, unique, not null] + id uuid [primary key, unique, not null, default: `gen_random_uuid()`] // The first session where this action was created // It will carry forward to every future session until // its due_by is passed or it was completed by the coachee coaching_session_id uuid [not null] - due_by timestamp + due_by timestamptz completed boolean // May be unnecessary if there's a valid completed_at timestamp - completed_at timestamp - created_at timestamp - updated_at timestamp + completed_at timestamptz + created_at timestamp [default: `now()`] + updated_at timestamp [default: `now()`] } // coaching_relationships relationships diff --git a/entity/Cargo.toml b/entity/Cargo.toml index f9030066..6ace53d0 100644 --- a/entity/Cargo.toml +++ b/entity/Cargo.toml @@ -9,8 +9,10 @@ path = "src/lib.rs" [dependencies] axum-login = "0.12.0" +chrono = { version = "0.4.34", features = ["serde"] } serde = { version = "1", features = ["derive"] } - +uuid = "1.7.0" [dependencies.sea-orm] version = "0.12" +features = [ "with-uuid" ] diff --git a/entity/src/coaching_relationship.rs b/entity/src/coaching_relationship.rs index ff18de05..db9c4d75 100644 --- a/entity/src/coaching_relationship.rs +++ b/entity/src/coaching_relationship.rs @@ -1,17 +1,18 @@ //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.3 +use crate::Id; use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Deserialize, Serialize)] #[sea_orm( - schema_name = "refactor_platform_rs", + schema_name = "refactor_platform", table_name = "coaching_relationships" )] pub struct Model { #[sea_orm(primary_key)] #[serde(skip_deserializing)] - pub id: i32, + pub id: Id, pub coachee_id: String, pub coach_id: String, pub organization_id: String, diff --git a/entity/src/lib.rs b/entity/src/lib.rs index b0954dc4..a072882a 100644 --- a/entity/src/lib.rs +++ b/entity/src/lib.rs @@ -1,6 +1,8 @@ +use uuid::Uuid; + pub mod coaching_relationship; pub mod organization; pub mod user; /// A type alias that represents any Entity's id field data type -pub type Id = i32; // TODO: consider changing this to a u64 +pub type Id = Uuid; diff --git a/entity/src/organization.rs b/entity/src/organization.rs index 3ca749b3..0c52bc3c 100644 --- a/entity/src/organization.rs +++ b/entity/src/organization.rs @@ -1,15 +1,14 @@ //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.3 +use crate::Id; use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; - #[derive(Clone, Debug, Default, PartialEq, DeriveEntityModel, Eq, Deserialize, Serialize)] -#[sea_orm(schema_name = "refactor_platform_rs", table_name = "organizations")] +#[sea_orm(schema_name = "refactor_platform", table_name = "organizations")] pub struct Model { #[sea_orm(primary_key)] #[serde(skip_deserializing)] - // TODO: consider changing this to a u64 - pub id: i32, + pub id: Id, pub name: String, } diff --git a/entity/src/user.rs b/entity/src/user.rs index a20c605a..05e48cf1 100644 --- a/entity/src/user.rs +++ b/entity/src/user.rs @@ -2,20 +2,26 @@ use crate::Id; use axum_login::AuthUser; +use chrono::{DateTime, Utc}; use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; -#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Deserialize, Serialize)] -#[sea_orm(schema_name = "refactor_platform_rs", table_name = "users")] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Deserialize, Serialize)] +#[sea_orm(schema_name = "refactor_platform", table_name = "users")] pub struct Model { #[sea_orm(primary_key)] #[serde(skip_deserializing)] pub id: Id, #[sea_orm(unique, indexed)] pub email: String, - pub password: String, pub first_name: String, pub last_name: String, + pub display_name: String, + pub password: String, + pub github_username: String, + pub github_profile_url: String, + pub created_at: DateTime, + pub updated_at: DateTime, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/entity_api/src/user.rs b/entity_api/src/user.rs index 1968feb6..618a727e 100644 --- a/entity_api/src/user.rs +++ b/entity_api/src/user.rs @@ -76,14 +76,24 @@ pub(crate) async fn seed_database(db: &DatabaseConnection) { email: ActiveValue::Set("james.hodapp@gmail.com".to_owned()), first_name: ActiveValue::Set("Jim".to_owned()), last_name: ActiveValue::Set("Hodapp".to_owned()), + display_name: ActiveValue::Set("Jim H".to_owned()), password: ActiveValue::Set(generate_hash("password1").to_owned()), + github_username: ActiveValue::Set("jhodapp".to_owned()), + github_profile_url: ActiveValue::Set("https://github.com/jhodapp".to_owned()), + created_at: ActiveValue::NotSet, + updated_at: ActiveValue::NotSet, }, user::ActiveModel { id: ActiveValue::NotSet, email: ActiveValue::Set("test@gmail.com".to_owned()), first_name: ActiveValue::Set("Test First".to_owned()), last_name: ActiveValue::Set("Test Last".to_owned()), + display_name: ActiveValue::Set("Test User".to_owned()), password: ActiveValue::Set(generate_hash("password2").to_owned()), + github_username: ActiveValue::Set("test".to_owned()), + github_profile_url: ActiveValue::Set("https://github.com/test".to_owned()), + created_at: ActiveValue::NotSet, + updated_at: ActiveValue::NotSet, }, ]; @@ -91,7 +101,7 @@ pub(crate) async fn seed_database(db: &DatabaseConnection) { debug!("user: {:?}", user); // Upserts seeded user data: - let _res = user::Entity::insert(user) + match user::Entity::insert(user) .on_conflict( // on conflict do update sea_query::OnConflict::column(user::Column::Email) @@ -101,6 +111,10 @@ pub(crate) async fn seed_database(db: &DatabaseConnection) { .to_owned(), ) .exec(db) - .await; + .await + { + Ok(_) => info!("Succeeded in seeding user data."), + Err(e) => error!("Failed to insert or update user when seeding user data: {e}"), + }; } } diff --git a/migration/src/m20240211_174355_base_migration.rs b/migration/src/m20240211_174355_base_migration.rs index 7eb2b39f..e3800e6f 100644 --- a/migration/src/m20240211_174355_base_migration.rs +++ b/migration/src/m20240211_174355_base_migration.rs @@ -28,14 +28,14 @@ impl MigrationTrait for Migration { Ok(()) } - async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> { Ok(()) } } // format sql as valid sql statements fn process_sql(sql: &str) -> String { - sql.replace(";", ";\n") + sql.replace(';', ";\n") .lines() .filter(|line| !line.trim().starts_with("--")) .collect::>() diff --git a/migration/src/refactor_platform_rs.sql b/migration/src/refactor_platform_rs.sql index ac84af0e..24796275 100644 --- a/migration/src/refactor_platform_rs.sql +++ b/migration/src/refactor_platform_rs.sql @@ -1,84 +1,83 @@ -- SQL dump generated using DBML (dbml-lang.org) -- Database: PostgreSQL --- Generated at: 2024-02-17T18:41:48.352Z +-- Generated at: 2024-02-18T00:58:44.704Z CREATE TABLE "refactor_platform"."organizations" ( - "id" uuid UNIQUE PRIMARY KEY NOT NULL, + "id" uuid UNIQUE PRIMARY KEY NOT NULL DEFAULT (gen_random_uuid()), "name" varchar, "logo" varchar, - "created_at" timestamp, - "updated_at" timestamp + "created_at" timestamptz DEFAULT (now()), + "updated_at" timestamptz DEFAULT (now()) ); CREATE TABLE "refactor_platform"."coaching_relationships" ( - "id" uuid UNIQUE PRIMARY KEY NOT NULL, + "id" uuid UNIQUE PRIMARY KEY NOT NULL DEFAULT (gen_random_uuid()), "organization_id" uuid NOT NULL, "coach_id" uuid NOT NULL, "coachee_id" uuid NOT NULL, - "created_at" timestamp, - "updated_at" timestamp + "created_at" timestamptz DEFAULT (now()), + "updated_at" timestamptz DEFAULT (now()) ); CREATE TABLE "refactor_platform"."users" ( - "id" uuid UNIQUE PRIMARY KEY NOT NULL, - "email" varchar, + "id" uuid UNIQUE PRIMARY KEY NOT NULL DEFAULT (gen_random_uuid()), + "email" varchar UNIQUE NOT NULL, "first_name" varchar, "last_name" varchar, "display_name" varchar, "password" varchar, - "timezone" varchar, "github_username" varchar, "github_profile_url" varchar, - "created_at" timestamp, - "updated_at" timestamp + "created_at" timestamptz DEFAULT (now()), + "updated_at" timestamptz DEFAULT (now()) ); CREATE TABLE "refactor_platform"."coaching_sessions" ( - "id" uuid UNIQUE PRIMARY KEY NOT NULL, + "id" uuid UNIQUE PRIMARY KEY NOT NULL DEFAULT (gen_random_uuid()), "coaching_relationship_id" uuid NOT NULL, "date" timestamp, "timezone" varchar, - "created_at" timestamp, - "updated_at" timestamp + "created_at" timestamptz DEFAULT (now()), + "updated_at" timestamptz DEFAULT (now()) ); CREATE TABLE "refactor_platform"."overarching_goals" ( - "id" uuid UNIQUE PRIMARY KEY NOT NULL, + "id" uuid UNIQUE PRIMARY KEY NOT NULL DEFAULT (gen_random_uuid()), "coaching_session_id" uuid, "title" varchar, "details" varchar, - "completed_at" timestamp, - "created_at" timestamp, - "updated_at" timestamp + "completed_at" timestamptz, + "created_at" timestamptz DEFAULT (now()), + "updated_at" timestamptz DEFAULT (now()) ); CREATE TABLE "refactor_platform"."notes" ( - "id" uuid UNIQUE PRIMARY KEY NOT NULL, + "id" uuid UNIQUE PRIMARY KEY NOT NULL DEFAULT (gen_random_uuid()), "coaching_session_id" uuid NOT NULL, "body" varchar, "user_id" uuid NOT NULL, - "created_at" timestamp, - "updated_at" timestamp + "created_at" timestamptz DEFAULT (now()), + "updated_at" timestamptz DEFAULT (now()) ); CREATE TABLE "refactor_platform"."agreements" ( - "id" uuid UNIQUE PRIMARY KEY NOT NULL, + "id" uuid UNIQUE PRIMARY KEY NOT NULL DEFAULT (gen_random_uuid()), "coaching_session_id" uuid NOT NULL, "details" varchar, "user_id" uuid NOT NULL, - "created_at" timestamp, - "updated_at" timestamp + "created_at" timestamptz DEFAULT (now()), + "updated_at" timestamptz DEFAULT (now()) ); CREATE TABLE "refactor_platform"."actions" ( - "id" uuid UNIQUE PRIMARY KEY NOT NULL, + "id" uuid UNIQUE PRIMARY KEY NOT NULL DEFAULT (gen_random_uuid()), "coaching_session_id" uuid NOT NULL, - "due_by" timestamp, + "due_by" timestamptz, "completed" boolean, - "completed_at" timestamp, - "created_at" timestamp, - "updated_at" timestamp + "completed_at" timestamptz, + "created_at" timestamp DEFAULT (now()), + "updated_at" timestamp DEFAULT (now()) ); COMMENT ON COLUMN "refactor_platform"."organizations"."name" IS 'The name of the organization that the coach <--> coachee belong to'; diff --git a/scripts/rebuild_db.sh b/scripts/rebuild_db.sh index 5421d1f9..ab176334 100755 --- a/scripts/rebuild_db.sh +++ b/scripts/rebuild_db.sh @@ -10,11 +10,18 @@ echo "Database Name: $DB_NAME" echo "Database User: $DB_USER" echo "Schema Name: $SCHEMA_NAME" -# Check if postgres is installed with homebrew and if not print message saying to install postgres with homebrew and exit -brew list postgresql > /dev/null 2>&1 || { echo "Postgres is not installed with homebrew. Please install postgres with homebrew and try again"; exit 1; } +# Check if postgres is installed with its client CLI +[ -f $(which postgres) ] && +[ -f $(which pg_ctl ) ] && +[ -f $(which psql) ] > /dev/null 2>&1 || + { echo "Postgres and psql are not completely installed. Please install postgres with your package manager or Postgres.app and try again"; exit 1; } + +if [[ -z "${PGDATA}" ]]; then + echo 'Environment variable PGDATA unset. See `pg_ctl --help for more information.' +fi # Ensure postgres is running and start postgres with homebrew if it is not running -pg_ctl status > /dev/null 2>&1 || { echo "Starting Postgres..."; brew services start postgresql; } +pg_ctl status > /dev/null 2>&1 || { echo "Starting Postgres..."; pg_ctl -w -t 15 start; } # Check if the postgres database exists and create it if it doesn't POSTGRES_DB_EXISTS=$(psql -U postgres -tAc "SELECT 1 FROM pg_database WHERE datname='postgres'") diff --git a/service/Cargo.toml b/service/Cargo.toml index f847da10..0e372ddd 100644 --- a/service/Cargo.toml +++ b/service/Cargo.toml @@ -10,7 +10,8 @@ version = "0.12" # sea-orm version features = [ "debug-print", "runtime-tokio-native-tls", - "sqlx-postgres" + "sqlx-postgres", + "with-uuid" ] [dependencies] diff --git a/web/Cargo.toml b/web/Cargo.toml index ad72edb6..cba36f05 100644 --- a/web/Cargo.toml +++ b/web/Cargo.toml @@ -27,7 +27,8 @@ features = [ "debug-print", "runtime-tokio-native-tls", "sea-orm-internal", - "sqlx-postgres" + "sqlx-postgres", + "with-uuid" ] [features] diff --git a/web/src/lib.rs b/web/src/lib.rs index 233ff1a2..d1736ddd 100644 --- a/web/src/lib.rs +++ b/web/src/lib.rs @@ -10,8 +10,8 @@ use service::AppState; use std::net::SocketAddr; use std::str::FromStr; use time::Duration; -use tower_http::cors::CorsLayer; use tokio::net::TcpListener; +use tower_http::cors::CorsLayer; mod controller; mod error; From 1573745f5e0137cac77110e631bed0afb4c2c022 Mon Sep 17 00:00:00 2001 From: Jim Hodapp Date: Sat, 17 Feb 2024 19:33:27 -0600 Subject: [PATCH 10/17] Move the tower-sessions DB table into the refactor_platform schema and rename the table to authorized_sessions --- migration/src/refactor_platform_rs.sql | 2 +- service/src/config.rs | 2 +- service/src/lib.rs | 2 +- web/src/lib.rs | 11 ++++++----- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/migration/src/refactor_platform_rs.sql b/migration/src/refactor_platform_rs.sql index 24796275..d3289564 100644 --- a/migration/src/refactor_platform_rs.sql +++ b/migration/src/refactor_platform_rs.sql @@ -1,6 +1,6 @@ -- SQL dump generated using DBML (dbml-lang.org) -- Database: PostgreSQL --- Generated at: 2024-02-18T00:58:44.704Z +-- Generated at: 2024-02-18T01:30:26.059Z CREATE TABLE "refactor_platform"."organizations" ( diff --git a/service/src/config.rs b/service/src/config.rs index 34500cea..b1b0d064 100644 --- a/service/src/config.rs +++ b/service/src/config.rs @@ -10,7 +10,7 @@ pub struct Config { short, long, env, - default_value = "postgres://refactor_rs:password@localhost:5432/refactor_platform_rs" + default_value = "postgres://refactor:password@localhost:5432/refactor_platform" )] database_uri: Option, diff --git a/service/src/lib.rs b/service/src/lib.rs index 947910dd..3bd1b83a 100644 --- a/service/src/lib.rs +++ b/service/src/lib.rs @@ -16,7 +16,7 @@ pub async fn init_database(database_uri: &str) -> Result Result<()> { .db_conn_ref() .get_postgres_connection_pool() .to_owned(), - ); - // TODO: this put the created session under the tower_sessions/sessions in the DB, do we want this to - // be under refactor_platform_rs/user_sessions or something? - // See the following for setting the schema/table name pair: - // https://docs.rs/tower-sessions/latest/tower_sessions/struct.PostgresStore.html + ) + .with_schema_name("refactor_platform") // FIXME: consolidate all schema strings into a config field with default option + .unwrap() + .with_table_name("authorized_sessions") + .unwrap(); + session_store.migrate().await.unwrap(); let deletion_task = tokio::task::spawn( From afdfed556060bd6ed9cf3d7d390e72d67cde10f5 Mon Sep 17 00:00:00 2001 From: Jim Hodapp Date: Sat, 17 Feb 2024 19:37:19 -0600 Subject: [PATCH 11/17] Remove the sqlite feature from sqlx since we don't use it. --- service/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/Cargo.toml b/service/Cargo.toml index 0e372ddd..30d6bb7d 100644 --- a/service/Cargo.toml +++ b/service/Cargo.toml @@ -19,6 +19,6 @@ clap = { version = "4.4.6", features = ["cargo", "derive", "env"] } log = "0.4" simplelog = { version = "0.12", features = ["paris"] } serde_json = "1.0.107" -sqlx = { version = "0.7.3", features = ["sqlite", "time", "runtime-tokio"] } +sqlx = { version = "0.7.3", features = ["time", "runtime-tokio"] } tokio = { version = "1.35", features = ["full"] } tower = "0.4.13" From fd817af3badf08fdb0a005745d71326d8f2109c8 Mon Sep 17 00:00:00 2001 From: Caleb Bourg Date: Sun, 18 Feb 2024 08:47:37 -0500 Subject: [PATCH 12/17] add external_id to tables Also reverts primary keys to integer values --- docs/db/refactor_platform_rs.dbml | 44 ++++++++++-------- entity/src/lib.rs | 3 +- migration/src/refactor_platform_rs.sql | 62 ++++++++++++++++++-------- 3 files changed, 70 insertions(+), 39 deletions(-) diff --git a/docs/db/refactor_platform_rs.dbml b/docs/db/refactor_platform_rs.dbml index c825d7c3..bcc3fb55 100644 --- a/docs/db/refactor_platform_rs.dbml +++ b/docs/db/refactor_platform_rs.dbml @@ -2,7 +2,8 @@ // Docs: https://dbml.dbdiagram.io/docs Table refactor_platform.organizations { - id uuid [primary key, unique, not null, default: `gen_random_uuid()`] + id integer [primary key, unique, not null, increment] + external_id uuid [unique, not null, default: `gen_random_uuid()`, note: 'The publicly visible identifier for a record'] name varchar [note: 'The name of the organization that the coach <--> coachee belong to'] logo varchar [note: 'A URI pointing to the organization\'s logo icon file'] created_at timestamptz [default: `now()`] @@ -12,16 +13,18 @@ Table refactor_platform.organizations { // Coaching relationship type belonging to the refactor_platform schema // from the perspective of the coach Table refactor_platform.coaching_relationships { - id uuid [primary key, unique, not null, default: `gen_random_uuid()`] - organization_id uuid [not null, note: 'The organization associated with this coaching relationship'] - coach_id uuid [not null, note: 'The coach associated with this coaching relationship'] - coachee_id uuid [not null, note: 'The coachee associated with this coaching relationship'] + id integer [primary key, unique, not null, increment] + external_id uuid [unique, not null, default: `gen_random_uuid()`, note: 'The publicly visible identifier for a record'] + organization_id integer [not null, note: 'The organization associated with this coaching relationship'] + coach_id integer [not null, note: 'The coach associated with this coaching relationship'] + coachee_id integer [not null, note: 'The coachee associated with this coaching relationship'] created_at timestamptz [default: `now()`] updated_at timestamptz [default: `now()`, note: 'The last date and time fields were changed'] } Table refactor_platform.users { - id uuid [primary key, unique, not null, default: `gen_random_uuid()`] + id integer [primary key, unique, not null, increment] + external_id uuid [unique, not null, default: `gen_random_uuid()`, note: 'The publicly visible identifier for a record'] email varchar [unique, not null] first_name varchar last_name varchar @@ -34,8 +37,9 @@ Table refactor_platform.users { } Table refactor_platform.coaching_sessions { - id uuid [primary key, unique, not null, default: `gen_random_uuid()`] - coaching_relationship_id uuid [not null, note: 'The coaching relationship (i.e. what coach & coachee under what organization) associated with this coaching session'] + id integer [primary key, unique, not null, increment] + external_id uuid [unique, not null, default: `gen_random_uuid()`, note: 'The publicly visible identifier for a record'] + coaching_relationship_id integer [not null, note: 'The coaching relationship (i.e. what coach & coachee under what organization) associated with this coaching session'] date timestamp [note: 'The date and time of a session'] timezone varchar [note: 'The baseline timezone used for the `date` field'] created_at timestamptz [default: `now()`] @@ -43,8 +47,9 @@ Table refactor_platform.coaching_sessions { } Table refactor_platform.overarching_goals { - id uuid [primary key, unique, not null, default: `gen_random_uuid()`] - coaching_session_id uuid [note: 'The coaching session that an overarching goal is associated with'] + id integer [primary key, unique, not null, increment] + external_id uuid [unique, not null, default: `gen_random_uuid()`, note: 'The publicly visible identifier for a record'] + coaching_session_id integer [note: 'The coaching session that an overarching goal is associated with'] title varchar [note: 'A short description of an overarching goal'] details varchar [note: 'A long description of an overarching goal'] completed_at timestamptz [note: 'The date and time an overarching goal was completed'] @@ -53,29 +58,32 @@ Table refactor_platform.overarching_goals { } Table refactor_platform.notes { - id uuid [primary key, unique, not null, default: `gen_random_uuid()`] - coaching_session_id uuid [not null] + id integer [primary key, unique, not null, increment] + external_id uuid [unique, not null, default: `gen_random_uuid()`, note: 'The publicly visible identifier for a record'] + coaching_session_id integer [not null] body varchar [note: 'Main text of the note supporting Markdown'] - user_id uuid [not null, note: 'User that created (owns) the note'] + user_id integer [not null, note: 'User that created (owns) the note'] created_at timestamptz [default: `now()`] updated_at timestamptz [default: `now()`, note: 'The last date and time an overarching note\'s fields were changed'] } Table refactor_platform.agreements { - id uuid [primary key, unique, not null, default: `gen_random_uuid()`] - coaching_session_id uuid [not null] + id integer [primary key, unique, not null, increment] + external_id uuid [unique, not null, default: `gen_random_uuid()`, note: 'The publicly visible identifier for a record'] + coaching_session_id integer [not null] details varchar [note: 'Either a short or long description of an agreement reached between coach and coachee in a coaching session'] - user_id uuid [not null, note: 'User that created (owns) the agreement'] + user_id integer [not null, note: 'User that created (owns) the agreement'] created_at timestamptz [default: `now()`] updated_at timestamptz [default: `now()`, note: 'The last date and time an overarching agreement\'s fields were changed'] } Table refactor_platform.actions { - id uuid [primary key, unique, not null, default: `gen_random_uuid()`] + id integer [primary key, unique, not null, increment] + external_id uuid [unique, not null, default: `gen_random_uuid()`, note: 'The publicly visible identifier for a record'] // The first session where this action was created // It will carry forward to every future session until // its due_by is passed or it was completed by the coachee - coaching_session_id uuid [not null] + coaching_session_id integer [not null] due_by timestamptz completed boolean // May be unnecessary if there's a valid completed_at timestamp completed_at timestamptz diff --git a/entity/src/lib.rs b/entity/src/lib.rs index a072882a..c1d9ea4f 100644 --- a/entity/src/lib.rs +++ b/entity/src/lib.rs @@ -1,8 +1,7 @@ -use uuid::Uuid; pub mod coaching_relationship; pub mod organization; pub mod user; /// A type alias that represents any Entity's id field data type -pub type Id = Uuid; +pub type Id = u64; diff --git a/migration/src/refactor_platform_rs.sql b/migration/src/refactor_platform_rs.sql index d3289564..938e2d13 100644 --- a/migration/src/refactor_platform_rs.sql +++ b/migration/src/refactor_platform_rs.sql @@ -1,10 +1,11 @@ -- SQL dump generated using DBML (dbml-lang.org) -- Database: PostgreSQL --- Generated at: 2024-02-18T01:30:26.059Z +-- Generated at: 2024-02-18T13:46:48.698Z CREATE TABLE "refactor_platform"."organizations" ( - "id" uuid UNIQUE PRIMARY KEY NOT NULL DEFAULT (gen_random_uuid()), + "id" INTEGER GENERATED BY DEFAULT AS IDENTITY UNIQUE PRIMARY KEY NOT NULL, + "external_id" uuid UNIQUE NOT NULL DEFAULT (gen_random_uuid()), "name" varchar, "logo" varchar, "created_at" timestamptz DEFAULT (now()), @@ -12,16 +13,18 @@ CREATE TABLE "refactor_platform"."organizations" ( ); CREATE TABLE "refactor_platform"."coaching_relationships" ( - "id" uuid UNIQUE PRIMARY KEY NOT NULL DEFAULT (gen_random_uuid()), - "organization_id" uuid NOT NULL, - "coach_id" uuid NOT NULL, - "coachee_id" uuid NOT NULL, + "id" INTEGER GENERATED BY DEFAULT AS IDENTITY UNIQUE PRIMARY KEY NOT NULL, + "external_id" uuid UNIQUE NOT NULL DEFAULT (gen_random_uuid()), + "organization_id" integer NOT NULL, + "coach_id" integer NOT NULL, + "coachee_id" integer NOT NULL, "created_at" timestamptz DEFAULT (now()), "updated_at" timestamptz DEFAULT (now()) ); CREATE TABLE "refactor_platform"."users" ( - "id" uuid UNIQUE PRIMARY KEY NOT NULL DEFAULT (gen_random_uuid()), + "id" INTEGER GENERATED BY DEFAULT AS IDENTITY UNIQUE PRIMARY KEY NOT NULL, + "external_id" uuid UNIQUE NOT NULL DEFAULT (gen_random_uuid()), "email" varchar UNIQUE NOT NULL, "first_name" varchar, "last_name" varchar, @@ -34,8 +37,9 @@ CREATE TABLE "refactor_platform"."users" ( ); CREATE TABLE "refactor_platform"."coaching_sessions" ( - "id" uuid UNIQUE PRIMARY KEY NOT NULL DEFAULT (gen_random_uuid()), - "coaching_relationship_id" uuid NOT NULL, + "id" INTEGER GENERATED BY DEFAULT AS IDENTITY UNIQUE PRIMARY KEY NOT NULL, + "external_id" uuid UNIQUE NOT NULL DEFAULT (gen_random_uuid()), + "coaching_relationship_id" integer NOT NULL, "date" timestamp, "timezone" varchar, "created_at" timestamptz DEFAULT (now()), @@ -43,8 +47,9 @@ CREATE TABLE "refactor_platform"."coaching_sessions" ( ); CREATE TABLE "refactor_platform"."overarching_goals" ( - "id" uuid UNIQUE PRIMARY KEY NOT NULL DEFAULT (gen_random_uuid()), - "coaching_session_id" uuid, + "id" INTEGER GENERATED BY DEFAULT AS IDENTITY UNIQUE PRIMARY KEY NOT NULL, + "external_id" uuid UNIQUE NOT NULL DEFAULT (gen_random_uuid()), + "coaching_session_id" integer, "title" varchar, "details" varchar, "completed_at" timestamptz, @@ -53,26 +58,29 @@ CREATE TABLE "refactor_platform"."overarching_goals" ( ); CREATE TABLE "refactor_platform"."notes" ( - "id" uuid UNIQUE PRIMARY KEY NOT NULL DEFAULT (gen_random_uuid()), - "coaching_session_id" uuid NOT NULL, + "id" INTEGER GENERATED BY DEFAULT AS IDENTITY UNIQUE PRIMARY KEY NOT NULL, + "external_id" uuid UNIQUE NOT NULL DEFAULT (gen_random_uuid()), + "coaching_session_id" integer NOT NULL, "body" varchar, - "user_id" uuid NOT NULL, + "user_id" integer NOT NULL, "created_at" timestamptz DEFAULT (now()), "updated_at" timestamptz DEFAULT (now()) ); CREATE TABLE "refactor_platform"."agreements" ( - "id" uuid UNIQUE PRIMARY KEY NOT NULL DEFAULT (gen_random_uuid()), - "coaching_session_id" uuid NOT NULL, + "id" INTEGER GENERATED BY DEFAULT AS IDENTITY UNIQUE PRIMARY KEY NOT NULL, + "external_id" uuid UNIQUE NOT NULL DEFAULT (gen_random_uuid()), + "coaching_session_id" integer NOT NULL, "details" varchar, - "user_id" uuid NOT NULL, + "user_id" integer NOT NULL, "created_at" timestamptz DEFAULT (now()), "updated_at" timestamptz DEFAULT (now()) ); CREATE TABLE "refactor_platform"."actions" ( - "id" uuid UNIQUE PRIMARY KEY NOT NULL DEFAULT (gen_random_uuid()), - "coaching_session_id" uuid NOT NULL, + "id" INTEGER GENERATED BY DEFAULT AS IDENTITY UNIQUE PRIMARY KEY NOT NULL, + "external_id" uuid UNIQUE NOT NULL DEFAULT (gen_random_uuid()), + "coaching_session_id" integer NOT NULL, "due_by" timestamptz, "completed" boolean, "completed_at" timestamptz, @@ -80,12 +88,16 @@ CREATE TABLE "refactor_platform"."actions" ( "updated_at" timestamp DEFAULT (now()) ); +COMMENT ON COLUMN "refactor_platform"."organizations"."external_id" IS 'The publicly visible identifier for a record'; + COMMENT ON COLUMN "refactor_platform"."organizations"."name" IS 'The name of the organization that the coach <--> coachee belong to'; COMMENT ON COLUMN "refactor_platform"."organizations"."logo" IS 'A URI pointing to the organization''s logo icon file'; COMMENT ON COLUMN "refactor_platform"."organizations"."updated_at" IS 'The last date and time fields were changed'; +COMMENT ON COLUMN "refactor_platform"."coaching_relationships"."external_id" IS 'The publicly visible identifier for a record'; + COMMENT ON COLUMN "refactor_platform"."coaching_relationships"."organization_id" IS 'The organization associated with this coaching relationship'; COMMENT ON COLUMN "refactor_platform"."coaching_relationships"."coach_id" IS 'The coach associated with this coaching relationship'; @@ -94,10 +106,14 @@ COMMENT ON COLUMN "refactor_platform"."coaching_relationships"."coachee_id" IS ' COMMENT ON COLUMN "refactor_platform"."coaching_relationships"."updated_at" IS 'The last date and time fields were changed'; +COMMENT ON COLUMN "refactor_platform"."users"."external_id" IS 'The publicly visible identifier for a record'; + COMMENT ON COLUMN "refactor_platform"."users"."display_name" IS 'If a user wants to go by something other than first & last names'; COMMENT ON COLUMN "refactor_platform"."users"."updated_at" IS 'The last date and time fields were changed'; +COMMENT ON COLUMN "refactor_platform"."coaching_sessions"."external_id" IS 'The publicly visible identifier for a record'; + COMMENT ON COLUMN "refactor_platform"."coaching_sessions"."coaching_relationship_id" IS 'The coaching relationship (i.e. what coach & coachee under what organization) associated with this coaching session'; COMMENT ON COLUMN "refactor_platform"."coaching_sessions"."date" IS 'The date and time of a session'; @@ -106,6 +122,8 @@ COMMENT ON COLUMN "refactor_platform"."coaching_sessions"."timezone" IS 'The bas COMMENT ON COLUMN "refactor_platform"."coaching_sessions"."updated_at" IS 'The last date and time fields were changed'; +COMMENT ON COLUMN "refactor_platform"."overarching_goals"."external_id" IS 'The publicly visible identifier for a record'; + COMMENT ON COLUMN "refactor_platform"."overarching_goals"."coaching_session_id" IS 'The coaching session that an overarching goal is associated with'; COMMENT ON COLUMN "refactor_platform"."overarching_goals"."title" IS 'A short description of an overarching goal'; @@ -116,18 +134,24 @@ COMMENT ON COLUMN "refactor_platform"."overarching_goals"."completed_at" IS 'The COMMENT ON COLUMN "refactor_platform"."overarching_goals"."updated_at" IS 'The last date and time fields were changed'; +COMMENT ON COLUMN "refactor_platform"."notes"."external_id" IS 'The publicly visible identifier for a record'; + COMMENT ON COLUMN "refactor_platform"."notes"."body" IS 'Main text of the note supporting Markdown'; COMMENT ON COLUMN "refactor_platform"."notes"."user_id" IS 'User that created (owns) the note'; COMMENT ON COLUMN "refactor_platform"."notes"."updated_at" IS 'The last date and time an overarching note''s fields were changed'; +COMMENT ON COLUMN "refactor_platform"."agreements"."external_id" IS 'The publicly visible identifier for a record'; + COMMENT ON COLUMN "refactor_platform"."agreements"."details" IS 'Either a short or long description of an agreement reached between coach and coachee in a coaching session'; COMMENT ON COLUMN "refactor_platform"."agreements"."user_id" IS 'User that created (owns) the agreement'; COMMENT ON COLUMN "refactor_platform"."agreements"."updated_at" IS 'The last date and time an overarching agreement''s fields were changed'; +COMMENT ON COLUMN "refactor_platform"."actions"."external_id" IS 'The publicly visible identifier for a record'; + ALTER TABLE "refactor_platform"."coaching_relationships" ADD FOREIGN KEY ("organization_id") REFERENCES "refactor_platform"."organizations" ("id"); ALTER TABLE "refactor_platform"."coaching_relationships" ADD FOREIGN KEY ("coachee_id") REFERENCES "refactor_platform"."users" ("id"); From b6b64ccf88340232adcc5fe985ca4ce22b417ac9 Mon Sep 17 00:00:00 2001 From: Caleb Bourg Date: Sun, 18 Feb 2024 08:56:53 -0500 Subject: [PATCH 13/17] generate new entities using seaORM CLI --- README.md | 5 ++- entity/src/actions.rs | 40 +++++++++++++++++++ entity/src/agreements.rs | 53 ++++++++++++++++++++++++ entity/src/coaching_sessions.rs | 71 +++++++++++++++++++++++++++++++++ entity/src/mod.rs | 9 +++-- entity/src/notes.rs | 53 ++++++++++++++++++++++++ entity/src/overarching_goals.rs | 40 +++++++++++++++++++ entity/src/prelude.rs | 9 +++-- entity/src/seaql_migrations.rs | 18 +++++++++ 9 files changed, 291 insertions(+), 7 deletions(-) create mode 100644 entity/src/actions.rs create mode 100644 entity/src/agreements.rs create mode 100644 entity/src/coaching_sessions.rs create mode 100644 entity/src/notes.rs create mode 100644 entity/src/overarching_goals.rs create mode 100644 entity/src/seaql_migrations.rs diff --git a/README.md b/README.md index 3fe14255..c891b48d 100644 --- a/README.md +++ b/README.md @@ -80,8 +80,11 @@ DATABASE_URL=postgres://refactor:password@localhost:5432/refactor_platform sea-o ``` ### Generate a new Entity from Database +Note that to generate a new Entity using the CLI you must ignore all other tables using the `--ignore-tables` option. You must add the option for _each_ table you are ignoring. + + ```bash - DATABASE_URL=postgres://refactor:password@localhost:5432/refactor_platform sea-orm-cli generate entity -s refactor_platform -o entity/src + DATABASE_URL=postgres://refactor:password@localhost:5432/refactor_platform sea-orm-cli generate entity -s refactor_platform -o entity/src -v --with-serde both --serde-skip-deserializing-primary-key --ignore-tables {table to ignore} --ignore-tables {other table to ignore} ``` ## Project Directory Structure diff --git a/entity/src/actions.rs b/entity/src/actions.rs new file mode 100644 index 00000000..d4c3286d --- /dev/null +++ b/entity/src/actions.rs @@ -0,0 +1,40 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.3 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(schema_name = "refactor_platform", table_name = "actions")] +pub struct Model { + #[sea_orm(primary_key)] + #[serde(skip_deserializing)] + pub id: i32, + #[sea_orm(unique)] + pub external_id: Uuid, + pub coaching_session_id: i32, + pub due_by: Option, + pub completed: Option, + pub completed_at: Option, + pub created_at: Option, + pub updated_at: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::coaching_sessions::Entity", + from = "Column::CoachingSessionId", + to = "super::coaching_sessions::Column::Id", + on_update = "NoAction", + on_delete = "NoAction" + )] + CoachingSessions, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::CoachingSessions.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/agreements.rs b/entity/src/agreements.rs new file mode 100644 index 00000000..a26574b8 --- /dev/null +++ b/entity/src/agreements.rs @@ -0,0 +1,53 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.3 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(schema_name = "refactor_platform", table_name = "agreements")] +pub struct Model { + #[sea_orm(primary_key)] + #[serde(skip_deserializing)] + pub id: i32, + #[sea_orm(unique)] + pub external_id: Uuid, + pub coaching_session_id: i32, + pub details: Option, + pub user_id: i32, + pub created_at: Option, + pub updated_at: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::coaching_sessions::Entity", + from = "Column::CoachingSessionId", + to = "super::coaching_sessions::Column::Id", + on_update = "NoAction", + on_delete = "NoAction" + )] + CoachingSessions, + #[sea_orm( + belongs_to = "super::users::Entity", + from = "Column::UserId", + to = "super::users::Column::Id", + on_update = "NoAction", + on_delete = "NoAction" + )] + Users, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::CoachingSessions.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Users.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/coaching_sessions.rs b/entity/src/coaching_sessions.rs new file mode 100644 index 00000000..e15f6457 --- /dev/null +++ b/entity/src/coaching_sessions.rs @@ -0,0 +1,71 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.3 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(schema_name = "refactor_platform", table_name = "coaching_sessions")] +pub struct Model { + #[sea_orm(primary_key)] + #[serde(skip_deserializing)] + pub id: i32, + #[sea_orm(unique)] + pub external_id: Uuid, + pub coaching_relationship_id: i32, + pub date: Option, + pub timezone: Option, + pub created_at: Option, + pub updated_at: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::actions::Entity")] + Actions, + #[sea_orm(has_many = "super::agreements::Entity")] + Agreements, + #[sea_orm( + belongs_to = "super::coaching_relationships::Entity", + from = "Column::CoachingRelationshipId", + to = "super::coaching_relationships::Column::Id", + on_update = "NoAction", + on_delete = "NoAction" + )] + CoachingRelationships, + #[sea_orm(has_many = "super::notes::Entity")] + Notes, + #[sea_orm(has_many = "super::overarching_goals::Entity")] + OverarchingGoals, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Actions.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Agreements.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::CoachingRelationships.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Notes.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::OverarchingGoals.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/mod.rs b/entity/src/mod.rs index 817ad2dd..49ed2372 100644 --- a/entity/src/mod.rs +++ b/entity/src/mod.rs @@ -2,6 +2,9 @@ pub mod prelude; -pub mod coaching_relationship; -pub mod organization; -pub mod user; +pub mod actions; +pub mod agreements; +pub mod coaching_sessions; +pub mod notes; +pub mod overarching_goals; +pub mod seaql_migrations; diff --git a/entity/src/notes.rs b/entity/src/notes.rs new file mode 100644 index 00000000..7424b0f1 --- /dev/null +++ b/entity/src/notes.rs @@ -0,0 +1,53 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.3 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(schema_name = "refactor_platform", table_name = "notes")] +pub struct Model { + #[sea_orm(primary_key)] + #[serde(skip_deserializing)] + pub id: i32, + #[sea_orm(unique)] + pub external_id: Uuid, + pub coaching_session_id: i32, + pub body: Option, + pub user_id: i32, + pub created_at: Option, + pub updated_at: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::coaching_sessions::Entity", + from = "Column::CoachingSessionId", + to = "super::coaching_sessions::Column::Id", + on_update = "NoAction", + on_delete = "NoAction" + )] + CoachingSessions, + #[sea_orm( + belongs_to = "super::users::Entity", + from = "Column::UserId", + to = "super::users::Column::Id", + on_update = "NoAction", + on_delete = "NoAction" + )] + Users, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::CoachingSessions.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Users.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/overarching_goals.rs b/entity/src/overarching_goals.rs new file mode 100644 index 00000000..5be58155 --- /dev/null +++ b/entity/src/overarching_goals.rs @@ -0,0 +1,40 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.3 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(schema_name = "refactor_platform", table_name = "overarching_goals")] +pub struct Model { + #[sea_orm(primary_key)] + #[serde(skip_deserializing)] + pub id: i32, + #[sea_orm(unique)] + pub external_id: Uuid, + pub coaching_session_id: Option, + pub title: Option, + pub details: Option, + pub completed_at: Option, + pub created_at: Option, + pub updated_at: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::coaching_sessions::Entity", + from = "Column::CoachingSessionId", + to = "super::coaching_sessions::Column::Id", + on_update = "NoAction", + on_delete = "NoAction" + )] + CoachingSessions, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::CoachingSessions.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/prelude.rs b/entity/src/prelude.rs index a2a78f2e..7979ec41 100644 --- a/entity/src/prelude.rs +++ b/entity/src/prelude.rs @@ -1,5 +1,8 @@ //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.3 -pub use super::coaching_relationships::Entity as CoachingRelationships; -pub use super::organizations::Entity as Organizations; -pub use super::users::Entity as Users; +pub use super::actions::Entity as Actions; +pub use super::agreements::Entity as Agreements; +pub use super::coaching_sessions::Entity as CoachingSessions; +pub use super::notes::Entity as Notes; +pub use super::overarching_goals::Entity as OverarchingGoals; +pub use super::seaql_migrations::Entity as SeaqlMigrations; diff --git a/entity/src/seaql_migrations.rs b/entity/src/seaql_migrations.rs new file mode 100644 index 00000000..093c3db9 --- /dev/null +++ b/entity/src/seaql_migrations.rs @@ -0,0 +1,18 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.3 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(schema_name = "refactor_platform", table_name = "seaql_migrations")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + #[serde(skip_deserializing)] + pub version: String, + pub applied_at: i64, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} From 69bfdcbb25427cc94a3a34ddde1602ed6d7e950a Mon Sep 17 00:00:00 2001 From: Jim Hodapp Date: Sun, 18 Feb 2024 11:20:03 -0600 Subject: [PATCH 14/17] Clean up a warning and code formatting --- web/src/controller/user_session_controller.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/web/src/controller/user_session_controller.rs b/web/src/controller/user_session_controller.rs index 062ac062..1049c8fd 100644 --- a/web/src/controller/user_session_controller.rs +++ b/web/src/controller/user_session_controller.rs @@ -12,7 +12,7 @@ use serde_json::json; // to redirect after log in. #[derive(Debug, Deserialize)] pub struct NextUrl { - next: Option, + _next: Option, } pub struct UserSessionController {} @@ -63,7 +63,8 @@ impl UserSessionController { Ok(Redirect::to(next).into_response()) } else { let response_json = Json( - json!({"first_name": user.first_name, "last_name": user.last_name, "email": user.email}), + json!({"first_name": user.first_name, "last_name": user.last_name, + "email": user.email, "display_name": user.display_name}), ); debug!("JSON response with 200 OK: {:?}", response_json); Ok(response_json.into_response()) From 1a5ac07b9c3465e261274d32a1354d4f03fe8dbd Mon Sep 17 00:00:00 2001 From: Jim Hodapp Date: Sun, 18 Feb 2024 11:33:49 -0600 Subject: [PATCH 15/17] Update the DB schema diagram to be in sync with refactor_platform_rs.dbml --- entity/README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/entity/README.md b/entity/README.md index a7b26150..a2a0cdd9 100644 --- a/entity/README.md +++ b/entity/README.md @@ -1,10 +1,6 @@ ## Entity Schema Diagram - Definitions and Relationships -![refactor_entity_schema](https://github.com/Jim-Hodapp-Coaching/refactor-platform-rs/assets/3219120/1656ee0f-da18-41fb-9472-379fcca29500) - -## Example Data - A Journey with Multiple Steps - -![refactor_entity_example_multiple_journey_steps](https://github.com/Jim-Hodapp-Coaching/refactor-platform-rs/assets/3219120/e933a0f5-8651-4638-8d72-e4903b54d026) +![refactor_entity_schema](https://github.com/Jim-Hodapp-Coaching/refactor-platform-rs/assets/3219120/d8e25a4d-376e-40aa-99de-532f8be06fb0) ## Example Data - A User as a Coach and Coachee in Two Different Organizations From 0329eeef1350cf64589ec647b9c74bb77ba1d0f4 Mon Sep 17 00:00:00 2001 From: Jim Hodapp Date: Sun, 18 Feb 2024 11:46:56 -0600 Subject: [PATCH 16/17] Integer-based primary keys seem to need to be i32 (INT4 SQL type) for sqlx-postgres compatability --- entity/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/entity/src/lib.rs b/entity/src/lib.rs index c1d9ea4f..db87f1ff 100644 --- a/entity/src/lib.rs +++ b/entity/src/lib.rs @@ -4,4 +4,4 @@ pub mod organization; pub mod user; /// A type alias that represents any Entity's id field data type -pub type Id = u64; +pub type Id = i32; From cf8fe3dbe6e32ca7465f4aaaa9005589aef681dd Mon Sep 17 00:00:00 2001 From: Jim Hodapp Date: Sun, 18 Feb 2024 11:49:48 -0600 Subject: [PATCH 17/17] Ran cargo fmt --- entity/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/entity/src/lib.rs b/entity/src/lib.rs index db87f1ff..79895d5e 100644 --- a/entity/src/lib.rs +++ b/entity/src/lib.rs @@ -1,4 +1,3 @@ - pub mod coaching_relationship; pub mod organization; pub mod user;