Skip to content

Commit be8929e

Browse files
committed
Support SeaORM RBAC (#212)
* Support rbac: unrestricted by default * Use generic inplace of RestrictedConnection in public API * guard behind feature flag `rbac`
1 parent c2cc527 commit be8929e

File tree

15 files changed

+155
-37
lines changed

15 files changed

+155
-37
lines changed

.github/workflows/tests.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,9 @@ jobs:
8282
- name: Additional Integration tests
8383
working-directory: ./examples/sqlite
8484
run: |
85-
cargo test --tests custom_
85+
cargo test --test custom_query_tests
86+
cargo test --test custom_mutation_tests
87+
cargo test --test query_tests --features=rbac
8688
cargo test --test plural_query_tests --features=field-pluralize
8789
cargo test --test entity_filter_tests --features=field-pluralize
8890
rm tests/custom_mutation_tests.rs tests/custom_query_tests.rs tests/plural_query_tests.rs

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pluralizer = { version = "0.5", optional = true }
3030
[features]
3131
default = ["field-camel-case"]
3232
macros = ["seaography-macros"]
33+
rbac = ["sea-orm/rbac"]
3334
with-json = ["sea-orm/with-json"]
3435
with-chrono = ["sea-orm/with-chrono", "async-graphql/chrono"]
3536
with-time = ["sea-orm/with-time", "async-graphql/time"]

examples/sqlite/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ serde_json = { version = "1.0.103" }
2525
members = []
2626

2727
[features]
28+
rbac = ["seaography/rbac"]
2829
field-pluralize = ["seaography/field-pluralize"]
2930

3031
[[test]]

examples/sqlite/src/query_root/queries.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
use super::*;
22
use async_graphql::Result as GqlResult;
33
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
4-
use seaography::apply_pagination;
5-
use seaography::{macros::CustomOperation, Connection, PaginationInput};
4+
use seaography::{apply_pagination, macros::CustomOperation, Connection, PaginationInput};
65

76
/*
87
@@ -37,8 +36,9 @@ impl Operations {
3736
pagination: PaginationInput,
3837
) -> GqlResult<Connection<customer::Entity>> {
3938
let db = ctx.data::<DatabaseConnection>()?;
39+
4040
let query = customer::Entity::find().filter(customer::Column::StoreId.eq(2));
41-
let connection = apply_pagination::<customer::Entity>(db, query, pagination).await?;
41+
let connection = apply_pagination::<customer::Entity, _>(db, query, pagination).await?;
4242

4343
Ok(connection)
4444
}

examples/sqlite/tests/query_tests.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use async_graphql::{dynamic::*, Response};
22
use sea_orm::Database;
3-
use seaography::async_graphql;
3+
use seaography::{async_graphql, DatabaseContext};
44

55
pub async fn get_schema() -> Schema {
66
let database = Database::connect("sqlite://sakila.db").await.unwrap();
7-
let schema = seaography_sqlite_example::query_root::schema(database, None, None).unwrap();
7+
let schema =
8+
seaography_sqlite_example::query_root::schema(database.unrestricted(), None, None).unwrap();
89

910
schema
1011
}

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,9 @@ pub use builder::*;
264264
pub mod error;
265265
pub use error::*;
266266

267+
pub mod rbac;
268+
pub use rbac::*;
269+
267270
pub type SimpleNamingFn = Box<dyn Fn(&str) -> String + Sync + Send>;
268271
pub type ComplexNamingFn = Box<dyn Fn(&str, &str) -> String + Sync + Send>;
269272

src/mutation/entity_create_batch_mutation.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ use sea_orm::{
44
};
55

66
use crate::{
7-
apply_guard, guard_error, prepare_active_model, BuilderContext, EntityInputBuilder,
8-
EntityObjectBuilder, EntityQueryFieldBuilder, GuardAction, OperationType,
7+
apply_guard, guard_error, prepare_active_model, BuilderContext, DatabaseContext,
8+
EntityInputBuilder, EntityObjectBuilder, EntityQueryFieldBuilder, GuardAction, OperationType,
9+
UserContext,
910
};
1011

1112
/// The configuration structure of EntityCreateBatchMutationBuilder
@@ -90,7 +91,10 @@ impl EntityCreateBatchMutationBuilder {
9091
return Err(guard_error(reason, "Entity guard triggered."));
9192
}
9293

93-
let db = ctx.data::<DatabaseConnection>()?;
94+
let db = &ctx
95+
.data::<DatabaseConnection>()?
96+
.restricted(ctx.data_opt::<UserContext>())?;
97+
9498
let transaction = db.begin().await?;
9599

96100
let entity_input_builder = EntityInputBuilder { context };

src/mutation/entity_create_one_mutation.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use sea_orm::{
55
};
66

77
use crate::{
8-
apply_guard, guard_error, BuilderContext, EntityInputBuilder, EntityObjectBuilder,
9-
EntityQueryFieldBuilder, GuardAction, OperationType,
8+
apply_guard, guard_error, BuilderContext, DatabaseContext, EntityInputBuilder,
9+
EntityObjectBuilder, EntityQueryFieldBuilder, GuardAction, OperationType, UserContext,
1010
};
1111

1212
/// The configuration structure of EntityCreateOneMutationBuilder
@@ -93,7 +93,6 @@ impl EntityCreateOneMutationBuilder {
9393

9494
let entity_input_builder = EntityInputBuilder { context };
9595
let entity_object_builder = EntityObjectBuilder { context };
96-
let db = ctx.data::<DatabaseConnection>()?;
9796
let value_accessor = ctx
9897
.args
9998
.try_get(&context.entity_create_one_mutation.data_field)?;
@@ -115,6 +114,10 @@ impl EntityCreateOneMutationBuilder {
115114
}
116115
}
117116

117+
let db = &ctx
118+
.data::<DatabaseConnection>()?
119+
.restricted(ctx.data_opt::<UserContext>())?;
120+
118121
let active_model = prepare_active_model::<T, A>(
119122
&entity_input_builder,
120123
&entity_object_builder,

src/mutation/entity_delete_mutation.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ use sea_orm::{
44
};
55

66
use crate::{
7-
apply_guard, get_filter_conditions, guard_error, BuilderContext, EntityObjectBuilder,
8-
EntityQueryFieldBuilder, FilterInputBuilder, GuardAction, OperationType,
7+
apply_guard, get_filter_conditions, guard_error, BuilderContext, DatabaseContext,
8+
EntityObjectBuilder, EntityQueryFieldBuilder, FilterInputBuilder, GuardAction, OperationType,
9+
UserContext,
910
};
1011

1112
/// The configuration structure of EntityDeleteMutationBuilder
@@ -90,7 +91,9 @@ impl EntityDeleteMutationBuilder {
9091
return Err(guard_error(reason, "Entity guard triggered."));
9192
}
9293

93-
let db = ctx.data::<DatabaseConnection>()?;
94+
let db = &ctx
95+
.data::<DatabaseConnection>()?
96+
.restricted(ctx.data_opt::<UserContext>())?;
9497

9598
let filters = ctx.args.get(&context.entity_delete_mutation.filter_field);
9699
let filter_condition = get_filter_conditions::<T>(context, filters)?;

src/mutation/entity_update_mutation.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use sea_orm::{
66

77
use crate::{
88
apply_guard, get_filter_conditions, guard_error, prepare_active_model, BuilderContext,
9-
EntityInputBuilder, EntityObjectBuilder, EntityQueryFieldBuilder, FilterInputBuilder,
10-
GuardAction, OperationType,
9+
DatabaseContext, EntityInputBuilder, EntityObjectBuilder, EntityQueryFieldBuilder,
10+
FilterInputBuilder, GuardAction, OperationType, UserContext,
1111
};
1212

1313
/// The configuration structure of EntityUpdateMutationBuilder
@@ -101,7 +101,10 @@ impl EntityUpdateMutationBuilder {
101101
return Err(guard_error(reason, "Entity guard triggered."));
102102
}
103103

104-
let db = ctx.data::<DatabaseConnection>()?;
104+
let db = ctx
105+
.data::<DatabaseConnection>()?
106+
.restricted(ctx.data_opt::<UserContext>())?;
107+
105108
let transaction = db.begin().await?;
106109

107110
let entity_input_builder = EntityInputBuilder { context };

0 commit comments

Comments
 (0)