mirror of
https://github.com/lldap/lldap.git
synced 2026-07-25 17:58:44 +00:00
server: return user-defined attributes for groups in graphql
Part of #67
This commit is contained in:
committed by
nitnelave
parent
e53ce92c96
commit
034794d58d
Generated
+3
@@ -24,6 +24,8 @@ type Group {
|
|||||||
displayName: String!
|
displayName: String!
|
||||||
creationDate: DateTimeUtc!
|
creationDate: DateTimeUtc!
|
||||||
uuid: String!
|
uuid: String!
|
||||||
|
"User-defined attributes."
|
||||||
|
attributes: [AttributeValue!]!
|
||||||
"The groups to which this user belongs."
|
"The groups to which this user belongs."
|
||||||
users: [User!]!
|
users: [User!]!
|
||||||
}
|
}
|
||||||
@@ -83,6 +85,7 @@ type User {
|
|||||||
avatar: String
|
avatar: String
|
||||||
creationDate: DateTimeUtc!
|
creationDate: DateTimeUtc!
|
||||||
uuid: String!
|
uuid: String!
|
||||||
|
"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!]!
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::domain::types::{GroupId, Serialized};
|
use crate::domain::types::{AttributeValue, GroupId, Serialized};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
|
||||||
#[sea_orm(table_name = "group_attributes")]
|
#[sea_orm(table_name = "group_attributes")]
|
||||||
@@ -55,3 +55,18 @@ impl Related<super::GroupAttributeSchema> for Entity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
|
||||||
|
impl From<Model> for AttributeValue {
|
||||||
|
fn from(
|
||||||
|
Model {
|
||||||
|
group_id: _,
|
||||||
|
attribute_name,
|
||||||
|
value,
|
||||||
|
}: Model,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
name: attribute_name,
|
||||||
|
value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ impl From<Model> for crate::domain::types::Group {
|
|||||||
creation_date: group.creation_date,
|
creation_date: group.creation_date,
|
||||||
uuid: group.uuid,
|
uuid: group.uuid,
|
||||||
users: vec![],
|
users: vec![],
|
||||||
|
attributes: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,6 +49,7 @@ impl From<Model> for crate::domain::types::GroupDetails {
|
|||||||
display_name: group.display_name,
|
display_name: group.display_name,
|
||||||
creation_date: group.creation_date,
|
creation_date: group.creation_date,
|
||||||
uuid: group.uuid,
|
uuid: group.uuid,
|
||||||
|
attributes: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use crate::domain::{
|
|||||||
},
|
},
|
||||||
model::{self, GroupColumn, MembershipColumn},
|
model::{self, GroupColumn, MembershipColumn},
|
||||||
sql_backend_handler::SqlBackendHandler,
|
sql_backend_handler::SqlBackendHandler,
|
||||||
types::{Group, GroupDetails, GroupId, Uuid},
|
types::{AttributeValue, Group, GroupDetails, GroupId, Uuid},
|
||||||
};
|
};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use sea_orm::{
|
use sea_orm::{
|
||||||
@@ -63,8 +63,7 @@ impl GroupListerBackendHandler for SqlBackendHandler {
|
|||||||
#[instrument(skip(self), level = "debug", ret, err)]
|
#[instrument(skip(self), level = "debug", ret, err)]
|
||||||
async fn list_groups(&self, filters: Option<GroupRequestFilter>) -> Result<Vec<Group>> {
|
async fn list_groups(&self, filters: Option<GroupRequestFilter>) -> Result<Vec<Group>> {
|
||||||
let results = model::Group::find()
|
let results = model::Group::find()
|
||||||
// The order_by must be before find_with_related otherwise the primary order is by group_id.
|
.order_by_asc(GroupColumn::GroupId)
|
||||||
.order_by_asc(GroupColumn::DisplayName)
|
|
||||||
.find_with_related(model::Membership)
|
.find_with_related(model::Membership)
|
||||||
.filter(
|
.filter(
|
||||||
filters
|
filters
|
||||||
@@ -84,7 +83,7 @@ impl GroupListerBackendHandler for SqlBackendHandler {
|
|||||||
)
|
)
|
||||||
.all(&self.sql_pool)
|
.all(&self.sql_pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(results
|
let mut groups: Vec<_> = results
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(group, users)| {
|
.map(|(group, users)| {
|
||||||
let users: Vec<_> = users.into_iter().map(|u| u.user_id).collect();
|
let users: Vec<_> = users.into_iter().map(|u| u.user_id).collect();
|
||||||
@@ -93,7 +92,30 @@ impl GroupListerBackendHandler for SqlBackendHandler {
|
|||||||
..group.into()
|
..group.into()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect())
|
.collect();
|
||||||
|
let group_ids = groups.iter().map(|u| &u.id);
|
||||||
|
let attributes = model::GroupAttributes::find()
|
||||||
|
.filter(model::GroupAttributesColumn::GroupId.is_in(group_ids))
|
||||||
|
.order_by_asc(model::GroupAttributesColumn::GroupId)
|
||||||
|
.order_by_asc(model::GroupAttributesColumn::AttributeName)
|
||||||
|
.all(&self.sql_pool)
|
||||||
|
.await?;
|
||||||
|
let mut attributes_iter = attributes.into_iter().peekable();
|
||||||
|
use itertools::Itertools; // For take_while_ref
|
||||||
|
for group in groups.iter_mut() {
|
||||||
|
assert!(attributes_iter
|
||||||
|
.peek()
|
||||||
|
.map(|u| u.group_id >= group.id)
|
||||||
|
.unwrap_or(true),
|
||||||
|
"Attributes are not sorted, groups are not sorted, or previous group didn't consume all the attributes");
|
||||||
|
|
||||||
|
group.attributes = attributes_iter
|
||||||
|
.take_while_ref(|u| u.group_id == group.id)
|
||||||
|
.map(AttributeValue::from)
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
|
groups.sort_by(|g1, g2| g1.display_name.cmp(&g2.display_name));
|
||||||
|
Ok(groups)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,11 +123,18 @@ impl GroupListerBackendHandler for SqlBackendHandler {
|
|||||||
impl GroupBackendHandler for SqlBackendHandler {
|
impl GroupBackendHandler for SqlBackendHandler {
|
||||||
#[instrument(skip(self), level = "debug", ret, err)]
|
#[instrument(skip(self), level = "debug", ret, err)]
|
||||||
async fn get_group_details(&self, group_id: GroupId) -> Result<GroupDetails> {
|
async fn get_group_details(&self, group_id: GroupId) -> Result<GroupDetails> {
|
||||||
model::Group::find_by_id(group_id)
|
let mut group_details = model::Group::find_by_id(group_id)
|
||||||
.one(&self.sql_pool)
|
.one(&self.sql_pool)
|
||||||
.await?
|
.await?
|
||||||
.map(Into::<GroupDetails>::into)
|
.map(Into::<GroupDetails>::into)
|
||||||
.ok_or_else(|| DomainError::EntityNotFound(format!("{:?}", group_id)))
|
.ok_or_else(|| DomainError::EntityNotFound(format!("{:?}", group_id)))?;
|
||||||
|
let attributes = model::GroupAttributes::find()
|
||||||
|
.filter(model::GroupAttributesColumn::GroupId.eq(group_details.group_id))
|
||||||
|
.order_by_asc(model::GroupAttributesColumn::AttributeName)
|
||||||
|
.all(&self.sql_pool)
|
||||||
|
.await?;
|
||||||
|
group_details.attributes = attributes.into_iter().map(AttributeValue::from).collect();
|
||||||
|
Ok(group_details)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self), level = "debug", err, fields(group_id = ?request.group_id))]
|
#[instrument(skip(self), level = "debug", err, fields(group_id = ?request.group_id))]
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ macro_rules! uuid {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, DeriveValueType)]
|
#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, DeriveValueType)]
|
||||||
#[sea_orm(column_type = "Binary(BlobSize::Long)", array_type = "Bytes")]
|
#[sea_orm(column_type = "Binary(BlobSize::Long)", array_type = "Bytes")]
|
||||||
pub struct Serialized(Vec<u8>);
|
pub struct Serialized(Vec<u8>);
|
||||||
|
|
||||||
@@ -283,7 +283,7 @@ impl IntoActiveValue<Serialized> for JpegPhoto {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
|
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize, Hash)]
|
||||||
pub struct AttributeValue {
|
pub struct AttributeValue {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub value: Serialized,
|
pub value: Serialized,
|
||||||
@@ -314,7 +314,19 @@ impl Default for User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, DeriveValueType)]
|
#[derive(
|
||||||
|
Debug,
|
||||||
|
Copy,
|
||||||
|
Clone,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
PartialOrd,
|
||||||
|
Ord,
|
||||||
|
Hash,
|
||||||
|
Serialize,
|
||||||
|
Deserialize,
|
||||||
|
DeriveValueType,
|
||||||
|
)]
|
||||||
pub struct GroupId(pub i32);
|
pub struct GroupId(pub i32);
|
||||||
|
|
||||||
impl TryFromU64 for GroupId {
|
impl TryFromU64 for GroupId {
|
||||||
@@ -323,6 +335,12 @@ impl TryFromU64 for GroupId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&GroupId> for Value {
|
||||||
|
fn from(id: &GroupId) -> Self {
|
||||||
|
(*id).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, EnumString, IntoStaticStr,
|
Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, EnumString, IntoStaticStr,
|
||||||
)]
|
)]
|
||||||
@@ -375,6 +393,7 @@ pub struct Group {
|
|||||||
pub creation_date: NaiveDateTime,
|
pub creation_date: NaiveDateTime,
|
||||||
pub uuid: Uuid,
|
pub uuid: Uuid,
|
||||||
pub users: Vec<UserId>,
|
pub users: Vec<UserId>,
|
||||||
|
pub attributes: Vec<AttributeValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
@@ -383,6 +402,7 @@ pub struct GroupDetails {
|
|||||||
pub display_name: String,
|
pub display_name: String,
|
||||||
pub creation_date: NaiveDateTime,
|
pub creation_date: NaiveDateTime,
|
||||||
pub uuid: Uuid,
|
pub uuid: Uuid,
|
||||||
|
pub attributes: Vec<AttributeValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
|||||||
@@ -286,7 +286,8 @@ impl<Handler: BackendHandler> User<Handler> {
|
|||||||
self.user.uuid.as_str()
|
self.user.uuid.as_str()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attributes(&self) -> Vec<AttributeValue<Handler>> {
|
/// User-defined attributes.
|
||||||
|
fn attributes(&self) -> Vec<AttributeValue<Handler, SchemaUserAttributeExtractor>> {
|
||||||
self.user
|
self.user
|
||||||
.attributes
|
.attributes
|
||||||
.clone()
|
.clone()
|
||||||
@@ -344,6 +345,7 @@ pub struct Group<Handler: BackendHandler> {
|
|||||||
display_name: String,
|
display_name: String,
|
||||||
creation_date: chrono::NaiveDateTime,
|
creation_date: chrono::NaiveDateTime,
|
||||||
uuid: String,
|
uuid: String,
|
||||||
|
attributes: Vec<DomainAttributeValue>,
|
||||||
members: Option<Vec<String>>,
|
members: Option<Vec<String>>,
|
||||||
_phantom: std::marker::PhantomData<Box<Handler>>,
|
_phantom: std::marker::PhantomData<Box<Handler>>,
|
||||||
}
|
}
|
||||||
@@ -362,6 +364,16 @@ impl<Handler: BackendHandler> Group<Handler> {
|
|||||||
fn uuid(&self) -> String {
|
fn uuid(&self) -> String {
|
||||||
self.uuid.clone()
|
self.uuid.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// User-defined attributes.
|
||||||
|
fn attributes(&self) -> Vec<AttributeValue<Handler, SchemaGroupAttributeExtractor>> {
|
||||||
|
self.attributes
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.map(Into::into)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
/// The groups to which this user belongs.
|
/// The groups to which this user belongs.
|
||||||
async fn users(&self, context: &Context<Handler>) -> FieldResult<Vec<User<Handler>>> {
|
async fn users(&self, context: &Context<Handler>) -> FieldResult<Vec<User<Handler>>> {
|
||||||
let span = debug_span!("[GraphQL query] group::users");
|
let span = debug_span!("[GraphQL query] group::users");
|
||||||
@@ -392,6 +404,7 @@ impl<Handler: BackendHandler> From<GroupDetails> for Group<Handler> {
|
|||||||
display_name: group_details.display_name,
|
display_name: group_details.display_name,
|
||||||
creation_date: group_details.creation_date,
|
creation_date: group_details.creation_date,
|
||||||
uuid: group_details.uuid.into_string(),
|
uuid: group_details.uuid.into_string(),
|
||||||
|
attributes: group_details.attributes,
|
||||||
members: None,
|
members: None,
|
||||||
_phantom: std::marker::PhantomData,
|
_phantom: std::marker::PhantomData,
|
||||||
}
|
}
|
||||||
@@ -405,6 +418,7 @@ impl<Handler: BackendHandler> From<DomainGroup> for Group<Handler> {
|
|||||||
display_name: group.display_name,
|
display_name: group.display_name,
|
||||||
creation_date: group.creation_date,
|
creation_date: group.creation_date,
|
||||||
uuid: group.uuid.into_string(),
|
uuid: group.uuid.into_string(),
|
||||||
|
attributes: group.attributes,
|
||||||
members: Some(group.users.into_iter().map(UserId::into_string).collect()),
|
members: Some(group.users.into_iter().map(UserId::into_string).collect()),
|
||||||
_phantom: std::marker::PhantomData,
|
_phantom: std::marker::PhantomData,
|
||||||
}
|
}
|
||||||
@@ -501,14 +515,37 @@ impl<Handler: BackendHandler> From<DomainSchema> for Schema<Handler> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait SchemaAttributeExtractor: std::marker::Send {
|
||||||
|
fn get_attributes(schema: &DomainSchema) -> &DomainAttributeList;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SchemaUserAttributeExtractor;
|
||||||
|
|
||||||
|
impl SchemaAttributeExtractor for SchemaUserAttributeExtractor {
|
||||||
|
fn get_attributes(schema: &DomainSchema) -> &DomainAttributeList {
|
||||||
|
&schema.get_schema().user_attributes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SchemaGroupAttributeExtractor;
|
||||||
|
|
||||||
|
impl SchemaAttributeExtractor for SchemaGroupAttributeExtractor {
|
||||||
|
fn get_attributes(schema: &DomainSchema) -> &DomainAttributeList {
|
||||||
|
&schema.get_schema().group_attributes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug, Serialize, Deserialize)]
|
#[derive(PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||||
pub struct AttributeValue<Handler: BackendHandler> {
|
pub struct AttributeValue<Handler: BackendHandler, Extractor> {
|
||||||
attribute: DomainAttributeValue,
|
attribute: DomainAttributeValue,
|
||||||
_phantom: std::marker::PhantomData<Box<Handler>>,
|
_phantom: std::marker::PhantomData<Box<Handler>>,
|
||||||
|
_phantom_extractor: std::marker::PhantomData<Extractor>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[graphql_object(context = Context<Handler>)]
|
#[graphql_object(context = Context<Handler>)]
|
||||||
impl<Handler: BackendHandler> AttributeValue<Handler> {
|
impl<Handler: BackendHandler, Extractor: SchemaAttributeExtractor>
|
||||||
|
AttributeValue<Handler, Extractor>
|
||||||
|
{
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
&self.attribute.name
|
&self.attribute.name
|
||||||
}
|
}
|
||||||
@@ -518,19 +555,17 @@ impl<Handler: BackendHandler> AttributeValue<Handler> {
|
|||||||
.get_user_restricted_lister_handler(&context.validation_result);
|
.get_user_restricted_lister_handler(&context.validation_result);
|
||||||
serialize_attribute(
|
serialize_attribute(
|
||||||
&self.attribute,
|
&self.attribute,
|
||||||
&PublicSchema::from(handler.get_schema().await?),
|
Extractor::get_attributes(&PublicSchema::from(handler.get_schema().await?)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serialize_attribute(
|
pub fn serialize_attribute(
|
||||||
attribute: &DomainAttributeValue,
|
attribute: &DomainAttributeValue,
|
||||||
schema: &DomainSchema,
|
attributes: &DomainAttributeList,
|
||||||
) -> FieldResult<Vec<String>> {
|
) -> FieldResult<Vec<String>> {
|
||||||
let convert_date = |date| chrono::Utc.from_utc_datetime(&date).to_rfc3339();
|
let convert_date = |date| chrono::Utc.from_utc_datetime(&date).to_rfc3339();
|
||||||
schema
|
attributes
|
||||||
.get_schema()
|
|
||||||
.user_attributes
|
|
||||||
.get_attribute_type(&attribute.name)
|
.get_attribute_type(&attribute.name)
|
||||||
.map(|attribute_type| {
|
.map(|attribute_type| {
|
||||||
match attribute_type {
|
match attribute_type {
|
||||||
@@ -575,11 +610,14 @@ pub fn serialize_attribute(
|
|||||||
.ok_or_else(|| FieldError::from(anyhow::anyhow!("Unknown attribute: {}", &attribute.name)))
|
.ok_or_else(|| FieldError::from(anyhow::anyhow!("Unknown attribute: {}", &attribute.name)))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Handler: BackendHandler> From<DomainAttributeValue> for AttributeValue<Handler> {
|
impl<Handler: BackendHandler, Extractor> From<DomainAttributeValue>
|
||||||
|
for AttributeValue<Handler, Extractor>
|
||||||
|
{
|
||||||
fn from(value: DomainAttributeValue) -> Self {
|
fn from(value: DomainAttributeValue) -> Self {
|
||||||
Self {
|
Self {
|
||||||
attribute: value,
|
attribute: value,
|
||||||
_phantom: std::marker::PhantomData,
|
_phantom: std::marker::PhantomData,
|
||||||
|
_phantom_extractor: std::marker::PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -634,12 +672,49 @@ mod tests {
|
|||||||
displayName
|
displayName
|
||||||
creationDate
|
creationDate
|
||||||
uuid
|
uuid
|
||||||
|
attributes {
|
||||||
|
name
|
||||||
|
value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}"#;
|
}"#;
|
||||||
|
|
||||||
let mut mock = MockTestBackendHandler::new();
|
let mut mock = MockTestBackendHandler::new();
|
||||||
setup_default_schema(&mut mock);
|
mock.expect_get_schema().returning(|| {
|
||||||
|
Ok(crate::domain::handler::Schema {
|
||||||
|
user_attributes: DomainAttributeList {
|
||||||
|
attributes: vec![
|
||||||
|
DomainAttributeSchema {
|
||||||
|
name: "first_name".to_owned(),
|
||||||
|
attribute_type: AttributeType::String,
|
||||||
|
is_list: false,
|
||||||
|
is_visible: true,
|
||||||
|
is_editable: true,
|
||||||
|
is_hardcoded: true,
|
||||||
|
},
|
||||||
|
DomainAttributeSchema {
|
||||||
|
name: "last_name".to_owned(),
|
||||||
|
attribute_type: AttributeType::String,
|
||||||
|
is_list: false,
|
||||||
|
is_visible: true,
|
||||||
|
is_editable: true,
|
||||||
|
is_hardcoded: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
group_attributes: DomainAttributeList {
|
||||||
|
attributes: vec![DomainAttributeSchema {
|
||||||
|
name: "club_name".to_owned(),
|
||||||
|
attribute_type: AttributeType::String,
|
||||||
|
is_list: false,
|
||||||
|
is_visible: true,
|
||||||
|
is_editable: true,
|
||||||
|
is_hardcoded: false,
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
});
|
||||||
mock.expect_get_user_details()
|
mock.expect_get_user_details()
|
||||||
.with(eq(UserId::new("bob")))
|
.with(eq(UserId::new("bob")))
|
||||||
.return_once(|_| {
|
.return_once(|_| {
|
||||||
@@ -667,12 +742,17 @@ mod tests {
|
|||||||
display_name: "Bobbersons".to_string(),
|
display_name: "Bobbersons".to_string(),
|
||||||
creation_date: chrono::Utc.timestamp_nanos(42).naive_utc(),
|
creation_date: chrono::Utc.timestamp_nanos(42).naive_utc(),
|
||||||
uuid: crate::uuid!("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"),
|
uuid: crate::uuid!("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"),
|
||||||
|
attributes: vec![DomainAttributeValue {
|
||||||
|
name: "club_name".to_owned(),
|
||||||
|
value: Serialized::from("Gang of Four"),
|
||||||
|
}],
|
||||||
});
|
});
|
||||||
groups.insert(GroupDetails {
|
groups.insert(GroupDetails {
|
||||||
group_id: GroupId(7),
|
group_id: GroupId(7),
|
||||||
display_name: "Jefferees".to_string(),
|
display_name: "Jefferees".to_string(),
|
||||||
creation_date: chrono::Utc.timestamp_nanos(12).naive_utc(),
|
creation_date: chrono::Utc.timestamp_nanos(12).naive_utc(),
|
||||||
uuid: crate::uuid!("b1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"),
|
uuid: crate::uuid!("b1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"),
|
||||||
|
attributes: Vec::new(),
|
||||||
});
|
});
|
||||||
mock.expect_get_user_groups()
|
mock.expect_get_user_groups()
|
||||||
.with(eq(UserId::new("bob")))
|
.with(eq(UserId::new("bob")))
|
||||||
@@ -704,13 +784,19 @@ mod tests {
|
|||||||
"id": 3,
|
"id": 3,
|
||||||
"displayName": "Bobbersons",
|
"displayName": "Bobbersons",
|
||||||
"creationDate": "1970-01-01T00:00:00.000000042+00:00",
|
"creationDate": "1970-01-01T00:00:00.000000042+00:00",
|
||||||
"uuid": "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8"
|
"uuid": "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",
|
||||||
|
"attributes": [{
|
||||||
|
"name": "club_name",
|
||||||
|
"value": ["Gang of Four"],
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 7,
|
"id": 7,
|
||||||
"displayName": "Jefferees",
|
"displayName": "Jefferees",
|
||||||
"creationDate": "1970-01-01T00:00:00.000000012+00:00",
|
"creationDate": "1970-01-01T00:00:00.000000012+00:00",
|
||||||
"uuid": "b1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8"
|
"uuid": "b1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",
|
||||||
|
"attributes": [],
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -856,6 +856,7 @@ mod tests {
|
|||||||
display_name: group,
|
display_name: group,
|
||||||
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
||||||
uuid: uuid!("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"),
|
uuid: uuid!("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"),
|
||||||
|
attributes: Vec::new(),
|
||||||
});
|
});
|
||||||
Ok(set)
|
Ok(set)
|
||||||
});
|
});
|
||||||
@@ -942,6 +943,7 @@ mod tests {
|
|||||||
display_name: "lldap_admin".to_string(),
|
display_name: "lldap_admin".to_string(),
|
||||||
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
||||||
uuid: uuid!("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"),
|
uuid: uuid!("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"),
|
||||||
|
attributes: Vec::new(),
|
||||||
});
|
});
|
||||||
Ok(set)
|
Ok(set)
|
||||||
});
|
});
|
||||||
@@ -1028,6 +1030,7 @@ mod tests {
|
|||||||
display_name: "rockstars".to_string(),
|
display_name: "rockstars".to_string(),
|
||||||
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
||||||
uuid: uuid!("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"),
|
uuid: uuid!("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"),
|
||||||
|
attributes: Vec::new(),
|
||||||
}]),
|
}]),
|
||||||
}])
|
}])
|
||||||
});
|
});
|
||||||
@@ -1344,6 +1347,7 @@ mod tests {
|
|||||||
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
||||||
users: vec![UserId::new("bob"), UserId::new("john")],
|
users: vec![UserId::new("bob"), UserId::new("john")],
|
||||||
uuid: uuid!("04ac75e0-2900-3e21-926c-2f732c26b3fc"),
|
uuid: uuid!("04ac75e0-2900-3e21-926c-2f732c26b3fc"),
|
||||||
|
attributes: Vec::new(),
|
||||||
},
|
},
|
||||||
Group {
|
Group {
|
||||||
id: GroupId(3),
|
id: GroupId(3),
|
||||||
@@ -1351,6 +1355,7 @@ mod tests {
|
|||||||
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
||||||
users: vec![UserId::new("john")],
|
users: vec![UserId::new("john")],
|
||||||
uuid: uuid!("04ac75e0-2900-3e21-926c-2f732c26b3fc"),
|
uuid: uuid!("04ac75e0-2900-3e21-926c-2f732c26b3fc"),
|
||||||
|
attributes: Vec::new(),
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
});
|
});
|
||||||
@@ -1442,6 +1447,7 @@ mod tests {
|
|||||||
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
||||||
users: vec![],
|
users: vec![],
|
||||||
uuid: uuid!("04ac75e0-2900-3e21-926c-2f732c26b3fc"),
|
uuid: uuid!("04ac75e0-2900-3e21-926c-2f732c26b3fc"),
|
||||||
|
attributes: Vec::new(),
|
||||||
}])
|
}])
|
||||||
});
|
});
|
||||||
let mut ldap_handler = setup_bound_admin_handler(mock).await;
|
let mut ldap_handler = setup_bound_admin_handler(mock).await;
|
||||||
@@ -1512,6 +1518,7 @@ mod tests {
|
|||||||
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
||||||
users: vec![],
|
users: vec![],
|
||||||
uuid: uuid!("04ac75e0-2900-3e21-926c-2f732c26b3fc"),
|
uuid: uuid!("04ac75e0-2900-3e21-926c-2f732c26b3fc"),
|
||||||
|
attributes: Vec::new(),
|
||||||
}])
|
}])
|
||||||
});
|
});
|
||||||
let mut ldap_handler = setup_bound_admin_handler(mock).await;
|
let mut ldap_handler = setup_bound_admin_handler(mock).await;
|
||||||
@@ -1881,6 +1888,7 @@ mod tests {
|
|||||||
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
||||||
users: vec![UserId::new("bob"), UserId::new("john")],
|
users: vec![UserId::new("bob"), UserId::new("john")],
|
||||||
uuid: uuid!("04ac75e0-2900-3e21-926c-2f732c26b3fc"),
|
uuid: uuid!("04ac75e0-2900-3e21-926c-2f732c26b3fc"),
|
||||||
|
attributes: Vec::new(),
|
||||||
}])
|
}])
|
||||||
});
|
});
|
||||||
let mut ldap_handler = setup_bound_admin_handler(mock).await;
|
let mut ldap_handler = setup_bound_admin_handler(mock).await;
|
||||||
@@ -1963,6 +1971,7 @@ mod tests {
|
|||||||
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
||||||
users: vec![UserId::new("bob"), UserId::new("john")],
|
users: vec![UserId::new("bob"), UserId::new("john")],
|
||||||
uuid: uuid!("04ac75e0-2900-3e21-926c-2f732c26b3fc"),
|
uuid: uuid!("04ac75e0-2900-3e21-926c-2f732c26b3fc"),
|
||||||
|
attributes: Vec::new(),
|
||||||
}])
|
}])
|
||||||
});
|
});
|
||||||
let mut ldap_handler = setup_bound_admin_handler(mock).await;
|
let mut ldap_handler = setup_bound_admin_handler(mock).await;
|
||||||
@@ -2344,6 +2353,7 @@ mod tests {
|
|||||||
display_name: "lldap_admin".to_string(),
|
display_name: "lldap_admin".to_string(),
|
||||||
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
||||||
uuid: uuid!("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"),
|
uuid: uuid!("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"),
|
||||||
|
attributes: Vec::new(),
|
||||||
});
|
});
|
||||||
mock.expect_get_user_groups()
|
mock.expect_get_user_groups()
|
||||||
.with(eq(UserId::new("bob")))
|
.with(eq(UserId::new("bob")))
|
||||||
@@ -2571,6 +2581,7 @@ mod tests {
|
|||||||
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
||||||
users: vec![UserId::new("bob")],
|
users: vec![UserId::new("bob")],
|
||||||
uuid: uuid!("04ac75e0-2900-3e21-926c-2f732c26b3fc"),
|
uuid: uuid!("04ac75e0-2900-3e21-926c-2f732c26b3fc"),
|
||||||
|
attributes: Vec::new(),
|
||||||
}])
|
}])
|
||||||
});
|
});
|
||||||
let mut ldap_handler = setup_bound_admin_handler(mock).await;
|
let mut ldap_handler = setup_bound_admin_handler(mock).await;
|
||||||
@@ -2664,6 +2675,7 @@ mod tests {
|
|||||||
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
creation_date: chrono::Utc.timestamp_opt(42, 42).unwrap().naive_utc(),
|
||||||
users: vec![UserId::new("bob")],
|
users: vec![UserId::new("bob")],
|
||||||
uuid: uuid!("04ac75e0-2900-3e21-926c-2f732c26b3fc"),
|
uuid: uuid!("04ac75e0-2900-3e21-926c-2f732c26b3fc"),
|
||||||
|
attributes: Vec::new(),
|
||||||
}])
|
}])
|
||||||
});
|
});
|
||||||
let mut ldap_handler = setup_bound_admin_handler(mock).await;
|
let mut ldap_handler = setup_bound_admin_handler(mock).await;
|
||||||
|
|||||||
Reference in New Issue
Block a user