use reqwest::Method;
use serde::Serialize;
use serde_json::json;
use crate::client::{Client, object_or_null, segment};
use crate::error::Result;
use crate::event::{Group, Serialized, object_or_empty};
use crate::models::TrackedGroup;
use crate::paging::{ItemStream, ListCall, Page, Paging, filter, paging_setters};
#[derive(Debug, Clone, Copy)]
pub struct Groups<'a> {
client: &'a Client,
}
impl<'a> Groups<'a> {
pub(crate) fn new(client: &'a Client) -> Self {
Groups { client }
}
pub async fn list(&self, params: ListGroups) -> Result<Page<TrackedGroup>> {
params.call().page(self.client).await
}
pub fn list_all(&self, params: ListGroups) -> ItemStream<TrackedGroup> {
params.call().walk(self.client)
}
pub async fn get(&self, group_type: &str, group_id: &str) -> Result<TrackedGroup> {
let payload = self
.client
.request(Method::GET, &path(group_type, group_id, "")?, &[], None)
.await?;
Ok(TrackedGroup::from_value(object_or_null(payload)))
}
pub async fn create(&self, group: Group) -> Result<TrackedGroup> {
let body = group.into_create_body()?;
let payload = self
.client
.request(Method::POST, "/groups", &[], Some(&body))
.await?;
Ok(TrackedGroup::from_value(object_or_null(payload)))
}
pub async fn update(
&self,
group_type: &str,
group_id: &str,
attributes: impl Serialize,
) -> Result<TrackedGroup> {
let path = path(group_type, group_id, "")?;
let attributes = object_or_empty(Some(Serialized::from(attributes)), "attributes")?;
let body = json!({ "attributes": attributes });
let payload = self
.client
.request(Method::PATCH, &path, &[], Some(&body))
.await?;
Ok(TrackedGroup::from_value(object_or_null(payload)))
}
pub async fn add_member(
&self,
group_type: &str,
group_id: &str,
identity_id: &str,
) -> Result<()> {
self.member(Method::PUT, group_type, group_id, identity_id)
.await
}
pub async fn remove_member(
&self,
group_type: &str,
group_id: &str,
identity_id: &str,
) -> Result<()> {
self.member(Method::DELETE, group_type, group_id, identity_id)
.await
}
async fn member(
&self,
method: Method,
group_type: &str,
group_id: &str,
identity_id: &str,
) -> Result<()> {
let suffix = format!("/identities/{}", segment(identity_id, "An identity id")?);
self.client
.request(method, &path(group_type, group_id, &suffix)?, &[], None)
.await?;
Ok(())
}
}
#[derive(Debug, Clone, Default)]
pub struct ListGroups {
group_type: Option<String>,
identity: Option<String>,
term: Option<String>,
paging: Paging,
}
impl ListGroups {
pub fn new() -> Self {
ListGroups::default()
}
pub fn group_type(mut self, group_type: impl Into<String>) -> Self {
self.group_type = Some(group_type.into());
self
}
pub fn identity(mut self, identity_id: impl Into<String>) -> Self {
self.identity = Some(identity_id.into());
self
}
pub fn term(mut self, term: impl Into<String>) -> Self {
self.term = Some(term.into());
self
}
paging_setters!();
fn call(self) -> ListCall<TrackedGroup> {
let mut filters = Vec::new();
filter(&mut filters, "type", self.group_type);
filter(&mut filters, "identity", self.identity);
filter(&mut filters, "term", self.term);
ListCall {
path: "/groups",
filters,
paging: self.paging,
parse: TrackedGroup::from_value,
}
}
}
fn path(group_type: &str, group_id: &str, suffix: &str) -> Result<String> {
Ok(format!(
"/groups/{}/{}{suffix}",
segment(group_type, "A group type")?,
segment(group_id, "A group id")?
))
}