mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 20:47:01 +01:00
Add mail support to groups (#2718)
* Add mail support to groups * Update libs/client/src/group.rs --------- Co-authored-by: James Hodgkinson <james@terminaloutcomes.com>
This commit is contained in:
parent
604adccdae
commit
afd674d346
|
@ -97,4 +97,22 @@ impl KanidmClient {
|
|||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn idm_group_purge_mail(&self, id: &str) -> Result<(), ClientError> {
|
||||
self.idm_group_purge_attr(id, "mail").await
|
||||
}
|
||||
|
||||
pub async fn idm_group_set_mail<T: serde::Serialize>(
|
||||
&self,
|
||||
id: &str,
|
||||
values: &[T],
|
||||
) -> Result<(), ClientError> {
|
||||
self.perform_put_request(&format!("/v1/group/{}/_attr/mail", id), values)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn idm_group_get_mail(&self, id: &str) -> Result<Option<Vec<String>>, ClientError> {
|
||||
self.perform_get_request(&format!("/v1/group/{}/_attr/mail", id))
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1330,6 +1330,29 @@ lazy_static! {
|
|||
};
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref IDM_ACP_ACCOUNT_MAIL_READ_DL6: BuiltinAcp = BuiltinAcp {
|
||||
classes: vec![
|
||||
EntryClass::Object,
|
||||
EntryClass::AccessControlProfile,
|
||||
EntryClass::AccessControlSearch
|
||||
],
|
||||
name: "idm_acp_account_mail_read",
|
||||
uuid: UUID_IDM_ACP_ACCOUNT_MAIL_READ_V1,
|
||||
description: "Builtin IDM Control for reading account and group mail attributes.",
|
||||
receiver: BuiltinAcpReceiver::Group(vec![UUID_IDM_ACCOUNT_MAIL_READ]),
|
||||
target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![
|
||||
ProtoFilter::Or(vec![
|
||||
match_class_filter!(EntryClass::Account),
|
||||
match_class_filter!(EntryClass::Group),
|
||||
]),
|
||||
FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone(),
|
||||
])),
|
||||
search_attrs: vec![Attribute::Mail],
|
||||
..Default::default()
|
||||
};
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref IDM_ACP_SYSTEM_CONFIG_ACCOUNT_POLICY_MANAGE_V1: BuiltinAcp = BuiltinAcp {
|
||||
classes: vec![
|
||||
|
@ -1499,6 +1522,7 @@ lazy_static! {
|
|||
Attribute::Spn,
|
||||
Attribute::Uuid,
|
||||
Attribute::Description,
|
||||
Attribute::Mail,
|
||||
Attribute::Member,
|
||||
Attribute::DynMember,
|
||||
Attribute::EntryManagedBy,
|
||||
|
@ -1508,6 +1532,7 @@ lazy_static! {
|
|||
Attribute::Name,
|
||||
Attribute::Uuid,
|
||||
Attribute::Description,
|
||||
Attribute::Mail,
|
||||
Attribute::Member,
|
||||
Attribute::EntryManagedBy,
|
||||
],
|
||||
|
@ -1518,11 +1543,13 @@ lazy_static! {
|
|||
modify_present_attrs: vec![
|
||||
Attribute::Name,
|
||||
Attribute::Description,
|
||||
Attribute::Mail,
|
||||
Attribute::Member,
|
||||
],
|
||||
modify_removed_attrs: vec![
|
||||
Attribute::Name,
|
||||
Attribute::Description,
|
||||
Attribute::Mail,
|
||||
Attribute::Member,
|
||||
],
|
||||
..Default::default()
|
||||
|
|
|
@ -768,6 +768,24 @@ pub static ref SCHEMA_CLASS_GROUP: SchemaClass = SchemaClass {
|
|||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref SCHEMA_CLASS_GROUP_DL6: SchemaClass = SchemaClass {
|
||||
uuid: UUID_SCHEMA_CLASS_GROUP,
|
||||
name: EntryClass::Group.into(),
|
||||
description: "Object representation of a group".to_string(),
|
||||
|
||||
sync_allowed: true,
|
||||
systemmay: vec![
|
||||
Attribute::Member.into(),
|
||||
Attribute::GrantUiHint.into(),
|
||||
Attribute::Description.into(),
|
||||
Attribute::Mail.into(),
|
||||
],
|
||||
systemmust: vec![
|
||||
Attribute::Name.into(),
|
||||
Attribute::Spn.into()],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref SCHEMA_CLASS_DYNGROUP: SchemaClass = SchemaClass {
|
||||
uuid: UUID_SCHEMA_CLASS_DYNGROUP,
|
||||
name: EntryClass::DynGroup.into(),
|
||||
|
|
|
@ -891,6 +891,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
SCHEMA_CLASS_DOMAIN_INFO_DL6.clone().into(),
|
||||
SCHEMA_CLASS_SERVICE_ACCOUNT_DL6.clone().into(),
|
||||
SCHEMA_CLASS_SYNC_ACCOUNT_DL6.clone().into(),
|
||||
SCHEMA_CLASS_GROUP_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_PROVIDER_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_PROVIDER_INTERNAL_DL6.clone().into(),
|
||||
SCHEMA_CLASS_KEY_OBJECT_DL6.clone().into(),
|
||||
|
@ -914,6 +915,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
IDM_ACP_GROUP_ACCOUNT_POLICY_MANAGE_DL6.clone().into(),
|
||||
IDM_ACP_PEOPLE_CREATE_DL6.clone().into(),
|
||||
IDM_ACP_GROUP_MANAGE_DL6.clone().into(),
|
||||
IDM_ACP_ACCOUNT_MAIL_READ_DL6.clone().into(),
|
||||
// Update anonymous with the correct entry manager,
|
||||
BUILTIN_ACCOUNT_ANONYMOUS_DL6.clone().into(),
|
||||
// Add the internal key provider.
|
||||
|
|
|
@ -207,6 +207,32 @@ async fn test_server_rest_group_lifecycle(rsclient: KanidmClient) {
|
|||
let members = rsclient.idm_group_get_members("demo_group").await.unwrap();
|
||||
assert!(members.is_none());
|
||||
|
||||
// Add a mail attribute.
|
||||
rsclient
|
||||
.idm_group_set_mail(
|
||||
"demo_group",
|
||||
&["primary@example.com", "secondary@example.com"],
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let mail_addrs = rsclient.idm_group_get_mail("demo_group").await.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
mail_addrs,
|
||||
Some(vec![
|
||||
"primary@example.com".to_string(),
|
||||
"secondary@example.com".to_string()
|
||||
])
|
||||
);
|
||||
|
||||
// Purge the mail addrs.
|
||||
rsclient.idm_group_purge_mail("demo_group").await.unwrap();
|
||||
|
||||
let mail_addrs = rsclient.idm_group_get_mail("demo_group").await.unwrap();
|
||||
|
||||
assert_eq!(mail_addrs, None);
|
||||
|
||||
// Delete the group
|
||||
rsclient.idm_group_delete("demo_group").await.unwrap();
|
||||
let g_list_3 = rsclient.idm_group_list().await.unwrap();
|
||||
|
|
|
@ -16,6 +16,7 @@ impl GroupOpt {
|
|||
GroupOpt::RemoveMembers(gcopt) => gcopt.copt.debug,
|
||||
GroupOpt::SetMembers(gcopt) => gcopt.copt.debug,
|
||||
GroupOpt::PurgeMembers(gcopt) => gcopt.copt.debug,
|
||||
GroupOpt::SetMail { copt, .. } => copt.debug,
|
||||
GroupOpt::Posix { commands } => match commands {
|
||||
GroupPosix::Show(gcopt) => gcopt.copt.debug,
|
||||
GroupPosix::Set(gcopt) => gcopt.copt.debug,
|
||||
|
@ -145,6 +146,22 @@ impl GroupOpt {
|
|||
Ok(_) => println!("Successfully set members for group {}", gcopt.name.as_str()),
|
||||
}
|
||||
}
|
||||
GroupOpt::SetMail { copt, name, mail } => {
|
||||
let client = copt.to_client(OpType::Write).await;
|
||||
|
||||
let result = if mail.is_empty() {
|
||||
client.idm_group_purge_mail(name.as_str()).await
|
||||
} else {
|
||||
client
|
||||
.idm_group_set_mail(name.as_str(), mail.as_slice())
|
||||
.await
|
||||
};
|
||||
|
||||
match result {
|
||||
Err(e) => handle_client_error(e, copt.output_mode),
|
||||
Ok(_) => println!("Successfully set mail for group {}", name.as_str()),
|
||||
}
|
||||
}
|
||||
GroupOpt::SetEntryManagedBy {
|
||||
name,
|
||||
entry_managed_by,
|
||||
|
|
|
@ -256,6 +256,16 @@ pub enum GroupOpt {
|
|||
/// set operation.
|
||||
#[clap(name = "set-members")]
|
||||
SetMembers(GroupNamedMembers),
|
||||
/// Set the exact list of mail addresses that this group is associated with. The first
|
||||
/// mail address in the list is the `primary` and the remainder are aliases. Setting
|
||||
/// an empty list will clear the mail attribute.
|
||||
#[clap(name = "set-mail")]
|
||||
SetMail {
|
||||
#[clap(flatten)]
|
||||
copt: CommonOpt,
|
||||
name: String,
|
||||
mail: Vec<String>,
|
||||
},
|
||||
/// Set a new entry-managed-by for this group.
|
||||
#[clap(name = "set-entry-manager")]
|
||||
SetEntryManagedBy {
|
||||
|
|
Loading…
Reference in a new issue