chore: upgrade Juniper to 0.17

This commit is contained in:
Valentin Tolmer
2026-05-01 00:07:11 +02:00
committed by nitnelave
parent 40121b80b7
commit 2b3dbb46de
11 changed files with 275 additions and 251 deletions
Generated
+101 -101
View File
@@ -388,6 +388,12 @@ version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
[[package]]
name = "arcstr"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03918c3dbd7701a85c6b9887732e2921175f26c350b4563841d0958c21d57e6d"
[[package]] [[package]]
name = "arrayref" name = "arrayref"
version = "0.3.9" version = "0.3.9"
@@ -400,12 +406,6 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "ascii"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e"
[[package]] [[package]]
name = "asn1-rs" name = "asn1-rs"
version = "0.7.1" version = "0.7.1"
@@ -511,6 +511,18 @@ dependencies = [
"bytemuck", "bytemuck",
] ]
[[package]]
name = "auto_enums"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65398a2893f41bce5c9259f6e1a4f03fbae40637c1bdc755b4f387f48c613b03"
dependencies = [
"derive_utils",
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.5.0" version = "1.5.0"
@@ -702,6 +714,15 @@ dependencies = [
"bytes", "bytes",
] ]
[[package]]
name = "castaway"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a"
dependencies = [
"rustversion",
]
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.2.61" version = "1.2.61"
@@ -806,19 +827,6 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
[[package]]
name = "combine"
version = "3.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680"
dependencies = [
"ascii",
"byteorder",
"either",
"memchr",
"unreachable",
]
[[package]] [[package]]
name = "combine" name = "combine"
version = "4.6.7" version = "4.6.7"
@@ -829,6 +837,20 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "compact_str"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a"
dependencies = [
"castaway",
"cfg-if",
"itoa",
"rustversion",
"ryu",
"static_assertions",
]
[[package]] [[package]]
name = "concurrent-queue" name = "concurrent-queue"
version = "2.5.0" version = "2.5.0"
@@ -1216,13 +1238,13 @@ dependencies = [
[[package]] [[package]]
name = "derive_utils" name = "derive_utils"
version = "0.11.2" version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "532b4c15dccee12c7044f1fcad956e98410860b22231e44a3b827464797ca7bf" checksum = "362f47930db19fe7735f527e6595e4900316b893ebf6d48ad3d31be928d57dd6"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 1.0.109", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -1531,17 +1553,6 @@ version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
[[package]]
name = "futures-enum"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "888490b0e2e137dd4c1fae622efe7160e484e5fd0cc47c2a880e4614d90e48cc"
dependencies = [
"derive_utils",
"quote",
"syn 1.0.109",
]
[[package]] [[package]]
name = "futures-executor" name = "futures-executor"
version = "0.3.32" version = "0.3.32"
@@ -1870,23 +1881,13 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "graphql-parser"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1abd4ce5247dfc04a03ccde70f87a048458c9356c7e41d21ad8c407b3dde6f2"
dependencies = [
"combine 3.8.1",
"thiserror 1.0.69",
]
[[package]] [[package]]
name = "graphql-parser" name = "graphql-parser"
version = "0.4.1" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a818c0d883d7c0801df27be910917750932be279c7bc82dc541b8769425f409" checksum = "7a818c0d883d7c0801df27be910917750932be279c7bc82dc541b8769425f409"
dependencies = [ dependencies = [
"combine 4.6.7", "combine",
"thiserror 1.0.69", "thiserror 1.0.69",
] ]
@@ -1909,7 +1910,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f290ecfa3bea3e8a157899dc8a1d96ee7dd6405c18c8ddd213fc58939d18a0e9" checksum = "f290ecfa3bea3e8a157899dc8a1d96ee7dd6405c18c8ddd213fc58939d18a0e9"
dependencies = [ dependencies = [
"graphql-introspection-query", "graphql-introspection-query",
"graphql-parser 0.4.1", "graphql-parser",
"heck 0.4.1", "heck 0.4.1",
"lazy_static", "lazy_static",
"proc-macro2", "proc-macro2",
@@ -2333,7 +2334,6 @@ checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"hashbrown 0.9.1", "hashbrown 0.9.1",
"serde",
] ]
[[package]] [[package]]
@@ -2416,35 +2416,41 @@ dependencies = [
[[package]] [[package]]
name = "juniper" name = "juniper"
version = "0.15.12" version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "875dca5a0c08b1521e1bb0ed940e9955a9f38971008aaa2a9f64a2ac6b59e1b5" checksum = "118749c965e171dcccffb7ca0dff6ab00451b08ba2710914caaaebc3686a7c3f"
dependencies = [ dependencies = [
"arcstr",
"async-trait", "async-trait",
"auto_enums",
"chrono", "chrono",
"compact_str",
"derive_more",
"fnv", "fnv",
"futures", "futures",
"futures-enum", "graphql-parser",
"graphql-parser 0.3.0", "indexmap 2.14.0",
"indexmap 1.6.2", "itertools",
"juniper_codegen", "juniper_codegen",
"ref-cast",
"serde", "serde",
"smartstring",
"static_assertions", "static_assertions",
"url", "url",
"uuid 0.8.2", "uuid",
"void",
] ]
[[package]] [[package]]
name = "juniper_codegen" name = "juniper_codegen"
version = "0.15.9" version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aee97671061ad50301ba077d054d295e01d31a1868fbd07902db651f987e71db" checksum = "8634f500d6d2ec5c91c115b83e15d998d9ea05645aaa43f7afec09e660c483ba"
dependencies = [ dependencies = [
"proc-macro-error", "derive_more",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 1.0.109", "syn 2.0.117",
"url",
] ]
[[package]] [[package]]
@@ -2536,7 +2542,7 @@ dependencies = [
"thiserror 2.0.18", "thiserror 2.0.18",
"tokio-util", "tokio-util",
"tracing", "tracing",
"uuid 1.23.1", "uuid",
] ]
[[package]] [[package]]
@@ -2703,7 +2709,7 @@ dependencies = [
"tracing-subscriber", "tracing-subscriber",
"url", "url",
"urlencoding", "urlencoding",
"uuid 1.23.1", "uuid",
"webpki-roots 1.0.7", "webpki-roots 1.0.7",
] ]
@@ -2770,7 +2776,7 @@ dependencies = [
"serde", "serde",
"sha2 0.9.9", "sha2 0.9.9",
"thiserror 2.0.18", "thiserror 2.0.18",
"uuid 1.23.1", "uuid",
] ]
[[package]] [[package]]
@@ -2791,7 +2797,7 @@ dependencies = [
"serde", "serde",
"serde_bytes", "serde_bytes",
"strum 0.28.0", "strum 0.28.0",
"uuid 1.23.1", "uuid",
] ]
[[package]] [[package]]
@@ -2809,7 +2815,7 @@ dependencies = [
"pretty_assertions", "pretty_assertions",
"serde", "serde",
"serde_bytes", "serde_bytes",
"uuid 1.23.1", "uuid",
] ]
[[package]] [[package]]
@@ -2828,7 +2834,7 @@ dependencies = [
"serde", "serde",
"serde_bytes", "serde_bytes",
"thiserror 2.0.18", "thiserror 2.0.18",
"uuid 1.23.1", "uuid",
] ]
[[package]] [[package]]
@@ -2861,7 +2867,7 @@ dependencies = [
"tokio", "tokio",
"tracing", "tracing",
"urlencoding", "urlencoding",
"uuid 1.23.1", "uuid",
] ]
[[package]] [[package]]
@@ -2885,7 +2891,7 @@ dependencies = [
"rand 0.8.6", "rand 0.8.6",
"tokio", "tokio",
"tracing", "tracing",
"uuid 1.23.1", "uuid",
] ]
[[package]] [[package]]
@@ -2959,7 +2965,7 @@ dependencies = [
"tokio", "tokio",
"tracing", "tracing",
"tracing-subscriber", "tracing-subscriber",
"uuid 1.23.1", "uuid",
] ]
[[package]] [[package]]
@@ -2975,7 +2981,7 @@ dependencies = [
"lldap_opaque_handler", "lldap_opaque_handler",
"mockall", "mockall",
"tracing", "tracing",
"uuid 1.23.1", "uuid",
] ]
[[package]] [[package]]
@@ -3780,6 +3786,26 @@ dependencies = [
"bitflags 2.11.1", "bitflags 2.11.1",
] ]
[[package]]
name = "ref-cast"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d"
dependencies = [
"ref-cast-impl",
]
[[package]]
name = "ref-cast-impl"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.12.3" version = "1.12.3"
@@ -4144,7 +4170,7 @@ dependencies = [
"thiserror 2.0.18", "thiserror 2.0.18",
"tracing", "tracing",
"url", "url",
"uuid 1.23.1", "uuid",
] ]
[[package]] [[package]]
@@ -4170,7 +4196,7 @@ dependencies = [
"chrono", "chrono",
"inherent", "inherent",
"ordered-float", "ordered-float",
"uuid 1.23.1", "uuid",
] ]
[[package]] [[package]]
@@ -4182,7 +4208,7 @@ dependencies = [
"chrono", "chrono",
"sea-query", "sea-query",
"sqlx", "sqlx",
"uuid 1.23.1", "uuid",
] ]
[[package]] [[package]]
@@ -4482,17 +4508,6 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "smartstring"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29"
dependencies = [
"autocfg",
"static_assertions",
"version_check",
]
[[package]] [[package]]
name = "smawk" name = "smawk"
version = "0.3.2" version = "0.3.2"
@@ -4585,7 +4600,7 @@ dependencies = [
"tokio-stream", "tokio-stream",
"tracing", "tracing",
"url", "url",
"uuid 1.23.1", "uuid",
"webpki-roots 0.26.11", "webpki-roots 0.26.11",
] ]
@@ -4667,7 +4682,7 @@ dependencies = [
"stringprep", "stringprep",
"thiserror 2.0.18", "thiserror 2.0.18",
"tracing", "tracing",
"uuid 1.23.1", "uuid",
"whoami", "whoami",
] ]
@@ -4706,7 +4721,7 @@ dependencies = [
"stringprep", "stringprep",
"thiserror 2.0.18", "thiserror 2.0.18",
"tracing", "tracing",
"uuid 1.23.1", "uuid",
"whoami", "whoami",
] ]
@@ -4733,7 +4748,7 @@ dependencies = [
"thiserror 2.0.18", "thiserror 2.0.18",
"tracing", "tracing",
"url", "url",
"uuid 1.23.1", "uuid",
] ]
[[package]] [[package]]
@@ -5134,7 +5149,7 @@ dependencies = [
"mutually_exclusive_features", "mutually_exclusive_features",
"pin-project", "pin-project",
"tracing", "tracing",
"uuid 1.23.1", "uuid",
] ]
[[package]] [[package]]
@@ -5279,15 +5294,6 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "unreachable"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
dependencies = [
"void",
]
[[package]] [[package]]
name = "untrusted" name = "untrusted"
version = "0.9.0" version = "0.9.0"
@@ -5334,12 +5340,6 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "1.23.1" version = "1.23.1"
+1 -1
View File
@@ -63,7 +63,7 @@ features = ["jpeg"]
version = "0.14" version = "0.14"
[workspace.dependencies.juniper] [workspace.dependencies.juniper]
version = "0.15" version = "0.17"
default-features = false default-features = false
features = ["chrono", "schema-language", "url", "uuid"] features = ["chrono", "schema-language", "url", "uuid"]
+2 -1
View File
@@ -1 +1,2 @@
pub type DateTimeUtc = chrono::DateTime<chrono::Utc>; pub type DateTime = chrono::DateTime<chrono::Utc>;
pub type DateTimeUtc = DateTime;
+2 -2
View File
@@ -60,7 +60,7 @@ impl<Handler: BackendHandler> Context<Handler> {
impl<Handler: BackendHandler> juniper::Context for Context<Handler> {} impl<Handler: BackendHandler> juniper::Context for Context<Handler> {}
type Schema<Handler> = type Schema<Handler> =
RootNode<'static, Query<Handler>, Mutation<Handler>, EmptySubscription<Context<Handler>>>; RootNode<Query<Handler>, Mutation<Handler>, EmptySubscription<Context<Handler>>>;
pub fn schema<Handler: BackendHandler>() -> Schema<Handler> { pub fn schema<Handler: BackendHandler>() -> Schema<Handler> {
Schema::new( Schema::new(
@@ -73,7 +73,7 @@ pub fn schema<Handler: BackendHandler>() -> Schema<Handler> {
pub fn export_schema(output_file: Option<String>) -> anyhow::Result<()> { pub fn export_schema(output_file: Option<String>) -> anyhow::Result<()> {
use anyhow::Context; use anyhow::Context;
use lldap_sql_backend_handler::SqlBackendHandler; use lldap_sql_backend_handler::SqlBackendHandler;
let output = schema::<SqlBackendHandler>().as_schema_language(); let output = schema::<SqlBackendHandler>().as_sdl();
match output_file { match output_file {
None => println!("{output}"), None => println!("{output}"),
Some(path) => { Some(path) => {
+4 -4
View File
@@ -561,13 +561,13 @@ mod tests {
use mockall::predicate::eq; use mockall::predicate::eq;
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
fn mutation_schema<'q, C, Q, M>( fn mutation_schema<C, Q, M>(
query_root: Q, query_root: Q,
mutation_root: M, mutation_root: M,
) -> RootNode<'q, Q, M, EmptySubscription<C>> ) -> RootNode<Q, M, EmptySubscription<C>>
where where
Q: GraphQLType<DefaultScalarValue, Context = C, TypeInfo = ()> + 'q, Q: GraphQLType<DefaultScalarValue, Context = C, TypeInfo = ()>,
M: GraphQLType<DefaultScalarValue, Context = C, TypeInfo = ()> + 'q, M: GraphQLType<DefaultScalarValue, Context = C, TypeInfo = ()>,
{ {
RootNode::new(query_root, mutation_root, EmptySubscription::<C>::new()) RootNode::new(query_root, mutation_root, EmptySubscription::<C>::new())
} }
+1 -1
View File
@@ -93,7 +93,7 @@ impl<Handler: BackendHandler> AttributeValue<Handler> {
} }
} }
pub(super) fn name(&self) -> &str { pub(super) fn attribute_name(&self) -> &str {
self.attribute.name.as_str() self.attribute.name.as_str()
} }
} }
+20 -11
View File
@@ -47,7 +47,11 @@ impl<Handler: BackendHandler> Query<Handler> {
"1.0" "1.0"
} }
pub async fn user(context: &Context<Handler>, user_id: String) -> FieldResult<User<Handler>> { pub async fn user(
&self,
context: &Context<Handler>,
user_id: String,
) -> FieldResult<User<Handler>> {
use anyhow::Context; use anyhow::Context;
let span = debug_span!("[GraphQL query] user"); let span = debug_span!("[GraphQL query] user");
span.in_scope(|| { span.in_scope(|| {
@@ -61,14 +65,15 @@ impl<Handler: BackendHandler> Query<Handler> {
&span, &span,
"Unauthorized access to user data", "Unauthorized access to user data",
))?; ))?;
let schema = Arc::new(self.get_schema(context, span.clone()).await?); let schema: Arc<PublicSchema> = Arc::new(self.get_schema(context, span.clone()).await?);
let user = handler.get_user_details(&user_id).instrument(span).await?; let user = handler.get_user_details(&user_id).instrument(span).await?;
User::<Handler>::from_user(user, schema) User::<Handler>::from_user(user, schema)
} }
async fn users( async fn users(
&self,
context: &Context<Handler>, context: &Context<Handler>,
#[graphql(name = "where")] filters: Option<RequestFilter>, filters: Option<RequestFilter>,
) -> FieldResult<Vec<User<Handler>>> { ) -> FieldResult<Vec<User<Handler>>> {
let span = debug_span!("[GraphQL query] users"); let span = debug_span!("[GraphQL query] users");
span.in_scope(|| { span.in_scope(|| {
@@ -80,7 +85,7 @@ impl<Handler: BackendHandler> Query<Handler> {
&span, &span,
"Unauthorized access to user list", "Unauthorized access to user list",
))?; ))?;
let schema = Arc::new(self.get_schema(context, span.clone()).await?); let schema: Arc<PublicSchema> = Arc::new(self.get_schema(context, span.clone()).await?);
let users = handler let users = handler
.list_users( .list_users(
filters filters
@@ -96,7 +101,7 @@ impl<Handler: BackendHandler> Query<Handler> {
.collect() .collect()
} }
async fn groups(context: &Context<Handler>) -> FieldResult<Vec<Group<Handler>>> { async fn groups(&self, context: &Context<Handler>) -> FieldResult<Vec<Group<Handler>>> {
let span = debug_span!("[GraphQL query] groups"); let span = debug_span!("[GraphQL query] groups");
let handler = context let handler = context
.get_readonly_handler() .get_readonly_handler()
@@ -104,7 +109,7 @@ impl<Handler: BackendHandler> Query<Handler> {
&span, &span,
"Unauthorized access to group list", "Unauthorized access to group list",
))?; ))?;
let schema = Arc::new(self.get_schema(context, span.clone()).await?); let schema: Arc<PublicSchema> = Arc::new(self.get_schema(context, span.clone()).await?);
let domain_groups = handler.list_groups(None).instrument(span).await?; let domain_groups = handler.list_groups(None).instrument(span).await?;
domain_groups domain_groups
.into_iter() .into_iter()
@@ -112,7 +117,11 @@ impl<Handler: BackendHandler> Query<Handler> {
.collect() .collect()
} }
async fn group(context: &Context<Handler>, group_id: i32) -> FieldResult<Group<Handler>> { async fn group(
&self,
context: &Context<Handler>,
group_id: i32,
) -> FieldResult<Group<Handler>> {
let span = debug_span!("[GraphQL query] group"); let span = debug_span!("[GraphQL query] group");
span.in_scope(|| { span.in_scope(|| {
debug!(?group_id); debug!(?group_id);
@@ -123,7 +132,7 @@ impl<Handler: BackendHandler> Query<Handler> {
&span, &span,
"Unauthorized access to group data", "Unauthorized access to group data",
))?; ))?;
let schema = Arc::new(self.get_schema(context, span.clone()).await?); let schema: Arc<PublicSchema> = Arc::new(self.get_schema(context, span.clone()).await?);
let group_details = handler let group_details = handler
.get_group_details(GroupId(group_id)) .get_group_details(GroupId(group_id))
.instrument(span) .instrument(span)
@@ -131,7 +140,7 @@ impl<Handler: BackendHandler> Query<Handler> {
Group::<Handler>::from_group_details(group_details, schema.clone()) Group::<Handler>::from_group_details(group_details, schema.clone())
} }
async fn schema(context: &Context<Handler>) -> FieldResult<Schema<Handler>> { async fn schema(&self, context: &Context<Handler>) -> FieldResult<Schema<Handler>> {
let span = debug_span!("[GraphQL query] get_schema"); let span = debug_span!("[GraphQL query] get_schema");
self.get_schema(context, span).await.map(Into::into) self.get_schema(context, span).await.map(Into::into)
} }
@@ -175,9 +184,9 @@ mod tests {
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use std::collections::HashSet; use std::collections::HashSet;
fn schema<'q, C, Q>(query_root: Q) -> RootNode<'q, Q, EmptyMutation<C>, EmptySubscription<C>> fn schema<C, Q>(query_root: Q) -> RootNode<Q, EmptyMutation<C>, EmptySubscription<C>>
where where
Q: GraphQLType<DefaultScalarValue, Context = C, TypeInfo = ()> + 'q, Q: GraphQLType<DefaultScalarValue, Context = C, TypeInfo = ()>,
{ {
RootNode::new( RootNode::new(
query_root, query_root,
+3 -3
View File
@@ -70,7 +70,7 @@ impl<Handler: BackendHandler> User<Handler> {
fn first_name(&self) -> &str { fn first_name(&self) -> &str {
self.attributes self.attributes
.iter() .iter()
.find(|a| a.name() == "first_name") .find(|a| a.attribute_name() == "first_name")
.map(|a| a.attribute.value.as_str().unwrap_or_default()) .map(|a| a.attribute.value.as_str().unwrap_or_default())
.unwrap_or_default() .unwrap_or_default()
} }
@@ -78,7 +78,7 @@ impl<Handler: BackendHandler> User<Handler> {
fn last_name(&self) -> &str { fn last_name(&self) -> &str {
self.attributes self.attributes
.iter() .iter()
.find(|a| a.name() == "last_name") .find(|a| a.attribute_name() == "last_name")
.map(|a| a.attribute.value.as_str().unwrap_or_default()) .map(|a| a.attribute.value.as_str().unwrap_or_default())
.unwrap_or_default() .unwrap_or_default()
} }
@@ -86,7 +86,7 @@ impl<Handler: BackendHandler> User<Handler> {
fn avatar(&self) -> Option<String> { fn avatar(&self) -> Option<String> {
self.attributes self.attributes
.iter() .iter()
.find(|a| a.name() == "avatar") .find(|a| a.attribute_name() == "avatar")
.map(|a| { .map(|a| {
String::from( String::from(
a.attribute a.attribute
+137 -124
View File
@@ -1,63 +1,33 @@
type AttributeValue { schema {
name: String! query: Query
value: [String!]! mutation: Mutation
schema: AttributeSchema!
} }
type Mutation { enum AttributeType {
createUser(user: CreateUserInput!): User! STRING
createGroup(name: String!): Group! INTEGER
createGroupWithDetails(request: CreateGroupInput!): Group! JPEG_PHOTO
updateUser(user: UpdateUserInput!): Success! DATE_TIME
updateGroup(group: UpdateGroupInput!): Success!
addUserToGroup(userId: String!, groupId: Int!): Success!
removeUserFromGroup(userId: String!, groupId: Int!): Success!
deleteUser(userId: String!): Success!
deleteGroup(groupId: Int!): Success!
addUserAttribute(name: String!, attributeType: AttributeType!, isList: Boolean!, isVisible: Boolean!, isEditable: Boolean!): Success!
addGroupAttribute(name: String!, attributeType: AttributeType!, isList: Boolean!, isVisible: Boolean!, isEditable: Boolean!): Success!
deleteUserAttribute(name: String!): Success!
deleteGroupAttribute(name: String!): Success!
addUserObjectClass(name: String!): Success!
addGroupObjectClass(name: String!): Success!
deleteUserObjectClass(name: String!): Success!
deleteGroupObjectClass(name: String!): Success!
} }
type Group { input AttributeValueInput {
id: Int! """
The name of the attribute. It must be present in the schema, and the type informs how
to interpret the values.
""" name: String!
"""
The values of the attribute.
If the attribute is not a list, the vector must contain exactly one element.
Integers (signed 64 bits) are represented as strings.
Dates are represented as strings in RFC3339 format, e.g. "2019-10-12T07:20:50.52Z".
JpegPhotos are represented as base64 encoded strings. They must be valid JPEGs.
""" value: [String!]!
}
"The details required to create a group."
input CreateGroupInput {
displayName: String! displayName: String!
creationDate: DateTimeUtc! "User-defined attributes." attributes: [AttributeValueInput!]
uuid: String!
"User-defined attributes."
attributes: [AttributeValue!]!
"The groups to which this user belongs."
users: [User!]!
}
"""
A filter for requests, specifying a boolean expression based on field constraints. Only one of
the fields can be set at a time.
"""
input RequestFilter {
any: [RequestFilter!]
all: [RequestFilter!]
not: RequestFilter
eq: EqualityConstraint
memberOf: String
memberOfId: Int
}
"DateTime"
scalar DateTimeUtc
type Query {
apiVersion: String!
user(userId: String!): User!
users(filters: RequestFilter): [User!]!
groups: [Group!]!
group(groupId: Int!): Group!
schema: Schema!
} }
"The details required to create a user." "The details required to create a user."
@@ -80,19 +50,36 @@ input CreateUserInput {
"Attributes." attributes: [AttributeValueInput!] "Attributes." attributes: [AttributeValueInput!]
} }
type ObjectClassInfo { input EqualityConstraint {
objectClass: String! field: String!
isHardcoded: Boolean! value: String!
} }
type AttributeSchema { """
name: String! A filter for requests, specifying a boolean expression based on field constraints. Only one of
attributeType: AttributeType! the fields can be set at a time.
isList: Boolean! """
isVisible: Boolean! input RequestFilter {
isEditable: Boolean! any: [RequestFilter!]
isHardcoded: Boolean! all: [RequestFilter!]
isReadonly: Boolean! not: RequestFilter
eq: EqualityConstraint
memberOf: String
memberOfId: Int
}
"The fields that can be updated for a group."
input UpdateGroupInput {
"The group ID." id: Int!
"The new display name." displayName: String
"""
Attribute names to remove.
They are processed before insertions.
""" removeAttributes: [String!]
"""
Inserts or updates the given attributes.
For lists, the entire list must be provided.
""" insertAttributes: [AttributeValueInput!]
} }
"The fields that can be updated for a user." "The fields that can be updated for a user."
@@ -122,9 +109,87 @@ input UpdateUserInput {
""" insertAttributes: [AttributeValueInput!] """ insertAttributes: [AttributeValueInput!]
} }
input EqualityConstraint { """
field: String! Combined date and time (with time zone) in [RFC 3339][0] format.
value: String!
Represents a description of an exact instant on the time-line (such as the
instant that a user account was created).
[`DateTime` scalar][1] compliant.
See also [`chrono::DateTime`][2] for details.
[0]: https://datatracker.ietf.org/doc/html/rfc3339#section-5
[1]: https://graphql-scalars.dev/docs/scalars/date-time
[2]: https://docs.rs/chrono/latest/chrono/struct.DateTime.html
"""
scalar DateTime
type AttributeList {
attributes: [AttributeSchema!]!
extraLdapObjectClasses: [String!]!
ldapObjectClasses: [ObjectClassInfo!]!
}
type AttributeSchema {
name: String!
attributeType: AttributeType!
isList: Boolean!
isVisible: Boolean!
isEditable: Boolean!
isHardcoded: Boolean!
isReadonly: Boolean!
}
type AttributeValue {
name: String!
value: [String!]!
schema: AttributeSchema!
}
type Group {
id: Int!
displayName: String!
creationDate: DateTime!
uuid: String!
"User-defined attributes."
attributes: [AttributeValue!]!
"The groups to which this user belongs."
users: [User!]!
}
type Mutation {
createUser(user: CreateUserInput!): User!
createGroup(name: String!): Group!
createGroupWithDetails(request: CreateGroupInput!): Group!
updateUser(user: UpdateUserInput!): Success!
updateGroup(group: UpdateGroupInput!): Success!
addUserToGroup(userId: String!, groupId: Int!): Success!
removeUserFromGroup(userId: String!, groupId: Int!): Success!
deleteUser(userId: String!): Success!
deleteGroup(groupId: Int!): Success!
addUserAttribute(name: String!, attributeType: AttributeType!, isList: Boolean!, isVisible: Boolean!, isEditable: Boolean!): Success!
addGroupAttribute(name: String!, attributeType: AttributeType!, isList: Boolean!, isVisible: Boolean!, isEditable: Boolean!): Success!
deleteUserAttribute(name: String!): Success!
deleteGroupAttribute(name: String!): Success!
addUserObjectClass(name: String!): Success!
addGroupObjectClass(name: String!): Success!
deleteUserObjectClass(name: String!): Success!
deleteGroupObjectClass(name: String!): Success!
}
type ObjectClassInfo {
objectClass: String!
isHardcoded: Boolean!
}
type Query {
apiVersion: String!
user(userId: String!): User!
users(filters: RequestFilter): [User!]!
groups: [Group!]!
group(groupId: Int!): Group!
schema: Schema!
} }
type Schema { type Schema {
@@ -132,38 +197,8 @@ type Schema {
groupSchema: AttributeList! groupSchema: AttributeList!
} }
"The fields that can be updated for a group." type Success {
input UpdateGroupInput { ok: Boolean!
"The group ID." id: Int!
"The new display name." displayName: String
"""
Attribute names to remove.
They are processed before insertions.
""" removeAttributes: [String!]
"""
Inserts or updates the given attributes.
For lists, the entire list must be provided.
""" insertAttributes: [AttributeValueInput!]
}
input AttributeValueInput {
"""
The name of the attribute. It must be present in the schema, and the type informs how
to interpret the values.
""" name: String!
"""
The values of the attribute.
If the attribute is not a list, the vector must contain exactly one element.
Integers (signed 64 bits) are represented as strings.
Dates are represented as strings in RFC3339 format, e.g. "2019-10-12T07:20:50.52Z".
JpegPhotos are represented as base64 encoded strings. They must be valid JPEGs.
""" value: [String!]!
}
"The details required to create a group."
input CreateGroupInput {
displayName: String!
"User-defined attributes." attributes: [AttributeValueInput!]
} }
type User { type User {
@@ -173,32 +208,10 @@ type User {
firstName: String! firstName: String!
lastName: String! lastName: String!
avatar: String avatar: String
creationDate: DateTimeUtc! creationDate: DateTime!
uuid: String! uuid: String!
"User-defined attributes." "User-defined attributes."
attributes: [AttributeValue!]! attributes: [AttributeValue!]!
"The groups to which this user belongs." "The groups to which this user belongs."
groups: [Group!]! groups: [Group!]!
} }
enum AttributeType {
STRING
INTEGER
JPEG_PHOTO
DATE_TIME
}
type AttributeList {
attributes: [AttributeSchema!]!
extraLdapObjectClasses: [String!]!
ldapObjectClasses: [ObjectClassInfo!]!
}
type Success {
ok: Boolean!
}
schema {
query: Query
mutation: Mutation
}
+2 -2
View File
@@ -52,7 +52,7 @@ where
/// Actix GraphQL Handler for GET requests /// Actix GraphQL Handler for GET requests
pub async fn get_graphql_handler<Query, Mutation, Subscription, CtxT, S>( pub async fn get_graphql_handler<Query, Mutation, Subscription, CtxT, S>(
schema: &juniper::RootNode<'static, Query, Mutation, Subscription, S>, schema: &juniper::RootNode<Query, Mutation, Subscription, S>,
context: &CtxT, context: &CtxT,
req: HttpRequest, req: HttpRequest,
) -> Result<HttpResponse, Error> ) -> Result<HttpResponse, Error>
@@ -81,7 +81,7 @@ where
/// Actix GraphQL Handler for POST requests /// Actix GraphQL Handler for POST requests
pub async fn post_graphql_handler<Query, Mutation, Subscription, CtxT, S>( pub async fn post_graphql_handler<Query, Mutation, Subscription, CtxT, S>(
schema: &juniper::RootNode<'static, Query, Mutation, Subscription, S>, schema: &juniper::RootNode<Query, Mutation, Subscription, S>,
context: &CtxT, context: &CtxT,
req: HttpRequest, req: HttpRequest,
mut payload: actix_http::Payload, mut payload: actix_http::Payload,
+2 -1
View File
@@ -4,7 +4,8 @@ use anyhow::{Context, Result, anyhow};
use graphql_client::GraphQLQuery; use graphql_client::GraphQLQuery;
use reqwest::blocking::Client; use reqwest::blocking::Client;
pub type DateTimeUtc = chrono::DateTime<chrono::Utc>; pub type DateTime = chrono::DateTime<chrono::Utc>;
pub type DateTimeUtc = DateTime;
#[derive(GraphQLQuery)] #[derive(GraphQLQuery)]
#[graphql( #[graphql(