diff --git a/.gitignore b/.gitignore index 73f61ed..3685a1e 100644 --- a/.gitignore +++ b/.gitignore @@ -162,5 +162,5 @@ target/ # mdBook book/book/ -# Tailwind CSS ouput -tailwind.output.css +# SeaORM +packages/storage/shield-seaorm/src/entities_template/ diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..4327855 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,19 @@ +services: + mysql: + image: mysql + ports: + - 13306:3306 + environment: + MYSQL_ROOT_PASSWORD: shield + MYSQL_USER: shield + MYSQL_PASSWORD: shield + MYSQL_DATABASE: shield + + postgresql: + image: postgres + ports: + - 15432:5432 + environment: + POSTGRES_USER: shield + POSTGRES_PASSWORD: shield + POSTGRES_DB: shield diff --git a/examples/seaorm/Cargo.toml b/examples/seaorm/Cargo.toml index eb9dfad..84eff0f 100644 --- a/examples/seaorm/Cargo.toml +++ b/examples/seaorm/Cargo.toml @@ -14,11 +14,15 @@ async-std = { workspace = true, features = ["attributes", "tokio1"] } sea-orm = { workspace = true, features = [ "macros", "runtime-tokio-native-tls", - "sqlx-sqlite", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite" ] } sea-orm-migration = { workspace = true, features = [ "runtime-tokio-native-tls", - "sqlx-sqlite", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite" ] } shield-seaorm = { path = "../../packages/storage/shield-seaorm", features = [ "all-providers", diff --git a/packages/storage/shield-seaorm/development.md b/packages/storage/shield-seaorm/development.md index 8c75487..8cf62e9 100644 --- a/packages/storage/shield-seaorm/development.md +++ b/packages/storage/shield-seaorm/development.md @@ -3,7 +3,13 @@ ``` sea-orm-cli migrate generate -d packages/storage/shield-seaorm/src/migrations/ +docker compose up -d + +sea-orm-cli migrate fresh -u "mysql://shield:shield@localhost:13306/shield" -d ./examples/seaorm +sea-orm-cli migrate fresh -u "postgres://shield:shield@localhost:15432/shield" -d ./examples/seaorm sea-orm-cli migrate fresh -u "sqlite:///tmp/shield-seaorm.sqlite?mode=rwc" -d ./examples/seaorm -sea-orm-cli generate entity -u "sqlite:///tmp/shield-seaorm.sqlite?mode=rwc" -o packages/storage/shield-seaorm/src/entities_template --with-serde both +sea-orm-cli generate entity -u "mysql://shield:shield@localhost:13306/shield" -o packages/storage/shield-seaorm/src/entities_template/mysql --with-serde both +sea-orm-cli generate entity -u "postgres://shield:shield@localhost:15432/shield" -o packages/storage/shield-seaorm/src/entities_template/postgresql --with-serde both +sea-orm-cli generate entity -u "sqlite:///tmp/shield-seaorm.sqlite?mode=rwc" -o packages/storage/shield-seaorm/src/entities_template/sqlite --with-serde both ``` diff --git a/packages/storage/shield-seaorm/src/base.rs b/packages/storage/shield-seaorm/src/base.rs index 225b116..eb8c15e 100644 --- a/packages/storage/shield-seaorm/src/base.rs +++ b/packages/storage/shield-seaorm/src/base.rs @@ -20,9 +20,8 @@ impl BaseTable { .not_null() .primary_key() .default(match manager.get_database_backend() { - DatabaseBackend::MySql => Expr::cust("uuid()"), + DatabaseBackend::MySql | DatabaseBackend::Sqlite => Expr::cust("(uuid())"), DatabaseBackend::Postgres => PgFunc::gen_random_uuid().into(), - DatabaseBackend::Sqlite => Expr::cust("(uuid())"), }), ) .col( diff --git a/packages/storage/shield-seaorm/src/entities/oauth_provider.rs b/packages/storage/shield-seaorm/src/entities/oauth_provider.rs index 2dddd4f..b7ce977 100644 --- a/packages/storage/shield-seaorm/src/entities/oauth_provider.rs +++ b/packages/storage/shield-seaorm/src/entities/oauth_provider.rs @@ -3,6 +3,45 @@ use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; +#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)] +#[sea_orm( + rs_type = "String", + db_type = "Enum", + enum_name = "oauth_provider_pkce_code_challenge" +)] +pub enum OauthProviderPkceCodeChallenge { + #[sea_orm(string_value = "none")] + None, + #[sea_orm(string_value = "plain")] + Plain, + #[sea_orm(string_value = "s256")] + S256, +} + +#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)] +#[sea_orm( + rs_type = "String", + db_type = "Enum", + enum_name = "oauth_provider_type" +)] +pub enum OauthProviderType { + #[sea_orm(string_value = "custom")] + Custom, +} + +#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)] +#[sea_orm( + rs_type = "String", + db_type = "Enum", + enum_name = "oauth_provider_visibility" +)] +pub enum OauthProviderVisibility { + #[sea_orm(string_value = "private")] + Private, + #[sea_orm(string_value = "public")] + Public, +} + #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] #[sea_orm(table_name = "oauth_provider")] pub struct Model { @@ -12,10 +51,8 @@ pub struct Model { pub updated_at: DateTimeUtc, pub name: String, pub slug: Option, - #[sea_orm(column_type = "custom(\"enum_text\")")] - pub r#type: String, - #[sea_orm(column_type = "custom(\"enum_text\")")] - pub visibility: String, + pub r#type: OauthProviderType, + pub visibility: OauthProviderVisibility, #[sea_orm(column_type = "Text")] pub client_id: String, #[sea_orm(column_type = "Text", nullable)] @@ -40,8 +77,7 @@ pub struct Model { pub revocation_url: Option, #[sea_orm(column_type = "Text", nullable)] pub revocation_url_params: Option, - #[sea_orm(column_type = "custom(\"enum_text\")")] - pub pcke_code_challenge: String, + pub pkce_code_challenge: OauthProviderPkceCodeChallenge, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/packages/storage/shield-seaorm/src/entities/oauth_provider_connection.rs b/packages/storage/shield-seaorm/src/entities/oauth_provider_connection.rs index 82dcfbb..272eb20 100644 --- a/packages/storage/shield-seaorm/src/entities/oauth_provider_connection.rs +++ b/packages/storage/shield-seaorm/src/entities/oauth_provider_connection.rs @@ -10,7 +10,6 @@ pub struct Model { pub id: Uuid, pub created_at: DateTimeUtc, pub updated_at: DateTimeUtc, - #[sea_orm(column_type = "Text")] pub identifier: String, #[sea_orm(column_type = "Text")] pub token_type: String, diff --git a/packages/storage/shield-seaorm/src/entities/oidc_provider.rs b/packages/storage/shield-seaorm/src/entities/oidc_provider.rs index c9cbc20..8933aba 100644 --- a/packages/storage/shield-seaorm/src/entities/oidc_provider.rs +++ b/packages/storage/shield-seaorm/src/entities/oidc_provider.rs @@ -3,6 +3,41 @@ use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; +#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)] +#[sea_orm( + rs_type = "String", + db_type = "Enum", + enum_name = "oidc_provider_pkce_code_challenge" +)] +pub enum OidcProviderPkceCodeChallenge { + #[sea_orm(string_value = "none")] + None, + #[sea_orm(string_value = "plain")] + Plain, + #[sea_orm(string_value = "s256")] + S256, +} + +#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)] +#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "oidc_provider_type")] +pub enum OidcProviderType { + #[sea_orm(string_value = "custom")] + Custom, +} + +#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Serialize, Deserialize)] +#[sea_orm( + rs_type = "String", + db_type = "Enum", + enum_name = "oidc_provider_visibility" +)] +pub enum OidcProviderVisibility { + #[sea_orm(string_value = "private")] + Private, + #[sea_orm(string_value = "public")] + Public, +} + #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] #[sea_orm(table_name = "oidc_provider")] pub struct Model { @@ -12,10 +47,8 @@ pub struct Model { pub updated_at: DateTimeUtc, pub name: String, pub slug: Option, - #[sea_orm(column_type = "custom(\"enum_text\")")] - pub r#type: String, - #[sea_orm(column_type = "custom(\"enum_text\")")] - pub visibility: String, + pub r#type: OidcProviderType, + pub visibility: OidcProviderVisibility, #[sea_orm(column_type = "Text")] pub client_id: String, #[sea_orm(column_type = "Text", nullable)] @@ -48,8 +81,7 @@ pub struct Model { pub json_web_key_set_url: Option, #[sea_orm(column_type = "JsonBinary", nullable)] pub json_web_key_set: Option, - #[sea_orm(column_type = "custom(\"enum_text\")")] - pub pcke_code_challenge: String, + pub pkce_code_challenge: OidcProviderPkceCodeChallenge, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/packages/storage/shield-seaorm/src/entities/oidc_provider_connection.rs b/packages/storage/shield-seaorm/src/entities/oidc_provider_connection.rs index fcaaf85..7905436 100644 --- a/packages/storage/shield-seaorm/src/entities/oidc_provider_connection.rs +++ b/packages/storage/shield-seaorm/src/entities/oidc_provider_connection.rs @@ -10,7 +10,6 @@ pub struct Model { pub id: Uuid, pub created_at: DateTimeUtc, pub updated_at: DateTimeUtc, - #[sea_orm(column_type = "Text")] pub identifier: String, #[sea_orm(column_type = "Text")] pub token_type: String, diff --git a/packages/storage/shield-seaorm/src/entities/prelude.rs b/packages/storage/shield-seaorm/src/entities/prelude.rs index 5a412a1..a18c578 100644 --- a/packages/storage/shield-seaorm/src/entities/prelude.rs +++ b/packages/storage/shield-seaorm/src/entities/prelude.rs @@ -8,11 +8,16 @@ pub use super::entity::Entity; pub use super::email_auth_token::Entity as EmailAuthToken; #[cfg(feature = "provider-oauth")] -pub use super::oauth_provider::Entity as OauthProvider; +pub use super::oauth_provider::{ + Entity as OauthProvider, OauthProviderPkceCodeChallenge, OauthProviderType, + OauthProviderVisibility, +}; #[cfg(feature = "provider-oauth")] pub use super::oauth_provider_connection::Entity as OauthProviderConnection; #[cfg(feature = "provider-oidc")] -pub use super::oidc_provider::Entity as OidcProvider; +pub use super::oidc_provider::{ + Entity as OidcProvider, OidcProviderPkceCodeChallenge, OidcProviderType, OidcProviderVisibility, +}; #[cfg(feature = "provider-oidc")] pub use super::oidc_provider_connection::Entity as OidcProviderConnection; diff --git a/packages/storage/shield-seaorm/src/migrations/providers/oauth/m20241211_095111_create_provider_oauth.rs b/packages/storage/shield-seaorm/src/migrations/providers/oauth/m20241211_095111_create_provider_oauth.rs index 8409ceb..edd776a 100644 --- a/packages/storage/shield-seaorm/src/migrations/providers/oauth/m20241211_095111_create_provider_oauth.rs +++ b/packages/storage/shield-seaorm/src/migrations/providers/oauth/m20241211_095111_create_provider_oauth.rs @@ -16,7 +16,7 @@ impl MigrationTrait for Migration { manager .create_type( Type::create() - .as_enum(OauthProviderType::Enum) + .as_enum(OauthProviderType::Table) .values(OauthProviderType::variants()) .to_owned(), ) @@ -25,11 +25,20 @@ impl MigrationTrait for Migration { manager .create_type( Type::create() - .as_enum(OauthProviderVisibility::Enum) + .as_enum(OauthProviderVisibility::Table) .values(OauthProviderVisibility::variants()) .to_owned(), ) .await?; + + manager + .create_type( + Type::create() + .as_enum(OauthProviderPkceCodeChallenge::Table) + .values(OauthProviderPkceCodeChallenge::variants()) + .to_owned(), + ) + .await?; } } @@ -49,10 +58,13 @@ impl MigrationTrait for Migration { match manager.get_database_backend() { DatabaseBackend::MySql | DatabaseBackend::Sqlite => column - .enumeration(OauthProviderType::Enum, OauthProviderType::variants()) + .enumeration( + OauthProviderType::Table, + OauthProviderType::variants(), + ) .into_column_def(), DatabaseBackend::Postgres => { - column.custom(OauthProviderType::Enum).into_column_def() + column.custom(OauthProviderType::Table).into_column_def() } } }) @@ -64,12 +76,12 @@ impl MigrationTrait for Migration { match manager.get_database_backend() { DatabaseBackend::MySql | DatabaseBackend::Sqlite => column .enumeration( - OauthProviderVisibility::Enum, + OauthProviderVisibility::Table, OauthProviderVisibility::variants(), ) .into_column_def(), DatabaseBackend::Postgres => column - .custom(OauthProviderVisibility::Enum) + .custom(OauthProviderVisibility::Table) .into_column_def(), } }) @@ -86,19 +98,19 @@ impl MigrationTrait for Migration { .col(ColumnDef::new(OauthProvider::RevocationUrl).text()) .col(ColumnDef::new(OauthProvider::RevocationUrlParams).text()) .col({ - let mut column = ColumnDef::new(OauthProvider::PckeCodeChallenge) + let mut column = ColumnDef::new(OauthProvider::PkceCodeChallenge) .not_null() .into_column_def(); match manager.get_database_backend() { DatabaseBackend::MySql | DatabaseBackend::Sqlite => column .enumeration( - OauthProviderPkceCodeChallenge::Enum, + OauthProviderPkceCodeChallenge::Table, OauthProviderPkceCodeChallenge::variants(), ) .into_column_def(), DatabaseBackend::Postgres => column - .custom(OauthProviderPkceCodeChallenge::Enum) + .custom(OauthProviderPkceCodeChallenge::Table) .into_column_def(), } }) @@ -111,7 +123,7 @@ impl MigrationTrait for Migration { BaseTable::create(OauthProviderConnection::Table, manager) .col( ColumnDef::new(OauthProviderConnection::Identifier) - .text() + .string_len(256) .not_null(), ) .col( @@ -139,7 +151,10 @@ impl MigrationTrait for Migration { ) .foreign_key( ForeignKey::create() - .name(OauthProviderConnection::FkConnectionProvider.to_string()) + .name( + OauthProviderConnection::FkOauthProviderConnectionProvider + .to_string(), + ) .from( OauthProviderConnection::Table, OauthProviderConnection::ProviderId, @@ -150,7 +165,9 @@ impl MigrationTrait for Migration { ) .foreign_key( ForeignKey::create() - .name(OauthProviderConnection::FkConnectionUser.to_string()) + .name( + OauthProviderConnection::FkOauthProviderConnectionUser.to_string(), + ) .from( OauthProviderConnection::Table, OauthProviderConnection::UserId, @@ -161,7 +178,9 @@ impl MigrationTrait for Migration { ) .index( Index::create() - .name(OauthProviderConnection::UniqueProviderIdentifier.to_string()) + .name( + OauthProviderConnection::UniqueOauthProviderIdentifier.to_string(), + ) .col(OauthProviderConnection::ProviderId) .col(OauthProviderConnection::Identifier) .unique(), @@ -190,11 +209,11 @@ impl MigrationTrait for Migration { DatabaseBackend::MySql | DatabaseBackend::Sqlite => {} DatabaseBackend::Postgres => { manager - .drop_type(Type::drop().name(OauthProviderVisibility::Enum).to_owned()) + .drop_type(Type::drop().name(OauthProviderVisibility::Table).to_owned()) .await?; manager - .drop_type(Type::drop().name(OauthProviderType::Enum).to_owned()) + .drop_type(Type::drop().name(OauthProviderType::Table).to_owned()) .await?; } } @@ -210,7 +229,7 @@ enum User { #[derive(DeriveIden)] enum OauthProviderType { - Enum, + Table, Custom, } @@ -223,7 +242,7 @@ impl OauthProviderType { #[derive(DeriveIden)] enum OauthProviderVisibility { - Enum, + Table, Public, Private, @@ -237,7 +256,7 @@ impl OauthProviderVisibility { #[derive(DeriveIden)] enum OauthProviderPkceCodeChallenge { - Enum, + Table, None, Plain, @@ -270,7 +289,7 @@ enum OauthProvider { IntrospectionUrlParams, RevocationUrl, RevocationUrlParams, - PckeCodeChallenge, + PkceCodeChallenge, } #[derive(DeriveIden)] @@ -287,8 +306,8 @@ enum OauthProviderConnection { ProviderId, UserId, - FkConnectionProvider, - FkConnectionUser, + FkOauthProviderConnectionProvider, + FkOauthProviderConnectionUser, - UniqueProviderIdentifier, + UniqueOauthProviderIdentifier, } diff --git a/packages/storage/shield-seaorm/src/migrations/providers/oidc/m20241211_184751_create_provider_oidc.rs b/packages/storage/shield-seaorm/src/migrations/providers/oidc/m20241211_184751_create_provider_oidc.rs index 25e15ba..dd49332 100644 --- a/packages/storage/shield-seaorm/src/migrations/providers/oidc/m20241211_184751_create_provider_oidc.rs +++ b/packages/storage/shield-seaorm/src/migrations/providers/oidc/m20241211_184751_create_provider_oidc.rs @@ -16,7 +16,7 @@ impl MigrationTrait for Migration { manager .create_type( Type::create() - .as_enum(OidcProviderType::Enum) + .as_enum(OidcProviderType::Table) .values(OidcProviderType::variants()) .to_owned(), ) @@ -25,11 +25,20 @@ impl MigrationTrait for Migration { manager .create_type( Type::create() - .as_enum(OidcProviderVisibility::Enum) + .as_enum(OidcProviderVisibility::Table) .values(OidcProviderVisibility::variants()) .to_owned(), ) .await?; + + manager + .create_type( + Type::create() + .as_enum(OidcProviderPkceCodeChallenge::Table) + .values(OidcProviderPkceCodeChallenge::variants()) + .to_owned(), + ) + .await?; } } @@ -49,10 +58,10 @@ impl MigrationTrait for Migration { match manager.get_database_backend() { DatabaseBackend::MySql | DatabaseBackend::Sqlite => column - .enumeration(OidcProviderType::Enum, OidcProviderType::variants()) + .enumeration(OidcProviderType::Table, OidcProviderType::variants()) .into_column_def(), DatabaseBackend::Postgres => { - column.custom(OidcProviderType::Enum).into_column_def() + column.custom(OidcProviderType::Table).into_column_def() } } }) @@ -64,12 +73,12 @@ impl MigrationTrait for Migration { match manager.get_database_backend() { DatabaseBackend::MySql | DatabaseBackend::Sqlite => column .enumeration( - OidcProviderVisibility::Enum, + OidcProviderVisibility::Table, OidcProviderVisibility::variants(), ) .into_column_def(), DatabaseBackend::Postgres => column - .custom(OidcProviderVisibility::Enum) + .custom(OidcProviderVisibility::Table) .into_column_def(), } }) @@ -90,19 +99,19 @@ impl MigrationTrait for Migration { .col(ColumnDef::new(OidcProvider::JsonWebKeySetUrl).text()) .col(ColumnDef::new(OidcProvider::JsonWebKeySet).json_binary()) .col({ - let mut column = ColumnDef::new(OidcProvider::PckeCodeChallenge) + let mut column = ColumnDef::new(OidcProvider::PkceCodeChallenge) .not_null() .into_column_def(); match manager.get_database_backend() { DatabaseBackend::MySql | DatabaseBackend::Sqlite => column .enumeration( - OidcProviderPkceCodeChallenge::Enum, + OidcProviderPkceCodeChallenge::Table, OidcProviderPkceCodeChallenge::variants(), ) .into_column_def(), DatabaseBackend::Postgres => column - .custom(OidcProviderPkceCodeChallenge::Enum) + .custom(OidcProviderPkceCodeChallenge::Table) .into_column_def(), } }) @@ -115,7 +124,7 @@ impl MigrationTrait for Migration { BaseTable::create(OidcProviderConnection::Table, manager) .col( ColumnDef::new(OidcProviderConnection::Identifier) - .text() + .string_len(256) .not_null(), ) .col( @@ -144,7 +153,10 @@ impl MigrationTrait for Migration { ) .foreign_key( ForeignKey::create() - .name(OidcProviderConnection::FkConnectionProvider.to_string()) + .name( + OidcProviderConnection::FkOidcProviderConnectionProvider + .to_string(), + ) .from( OidcProviderConnection::Table, OidcProviderConnection::ProviderId, @@ -155,7 +167,7 @@ impl MigrationTrait for Migration { ) .foreign_key( ForeignKey::create() - .name(OidcProviderConnection::FkConnectionUser.to_string()) + .name(OidcProviderConnection::FkOidcProviderConnectionUser.to_string()) .from( OidcProviderConnection::Table, OidcProviderConnection::UserId, @@ -166,7 +178,7 @@ impl MigrationTrait for Migration { ) .index( Index::create() - .name(OidcProviderConnection::UniqueProviderIdentifier.to_string()) + .name(OidcProviderConnection::UniqueOidcProviderIdentifier.to_string()) .col(OidcProviderConnection::ProviderId) .col(OidcProviderConnection::Identifier) .unique(), @@ -195,11 +207,11 @@ impl MigrationTrait for Migration { DatabaseBackend::MySql | DatabaseBackend::Sqlite => {} DatabaseBackend::Postgres => { manager - .drop_type(Type::drop().name(OidcProviderVisibility::Enum).to_owned()) + .drop_type(Type::drop().name(OidcProviderVisibility::Table).to_owned()) .await?; manager - .drop_type(Type::drop().name(OidcProviderType::Enum).to_owned()) + .drop_type(Type::drop().name(OidcProviderType::Table).to_owned()) .await?; } } @@ -215,7 +227,7 @@ enum User { #[derive(DeriveIden)] enum OidcProviderType { - Enum, + Table, Custom, } @@ -228,7 +240,7 @@ impl OidcProviderType { #[derive(DeriveIden)] enum OidcProviderVisibility { - Enum, + Table, Public, Private, @@ -242,7 +254,7 @@ impl OidcProviderVisibility { #[derive(DeriveIden)] enum OidcProviderPkceCodeChallenge { - Enum, + Table, None, Plain, @@ -279,7 +291,7 @@ enum OidcProvider { UserInfoUrl, JsonWebKeySetUrl, JsonWebKeySet, - PckeCodeChallenge, + PkceCodeChallenge, } #[derive(DeriveIden)] @@ -297,8 +309,8 @@ enum OidcProviderConnection { ProviderId, UserId, - FkConnectionProvider, - FkConnectionUser, + FkOidcProviderConnectionProvider, + FkOidcProviderConnectionUser, - UniqueProviderIdentifier, + UniqueOidcProviderIdentifier, }