openauth-plugins 0.0.3

Official OpenAuth plugin modules.
Documentation
use openauth_core::crypto::random::generate_random_string;
use openauth_core::db::{
    Count, Create, DbRecord, DbValue, Delete, DeleteMany, FindMany, FindOne, Sort, SortDirection,
    Update, Where,
};
use openauth_core::error::OpenAuthError;
use time::OffsetDateTime;

use super::{id_where, OrganizationStore, ID_LENGTH};
use crate::organization::record::{team_from_record, team_member_from_record};
use crate::organization::{Team, TeamMember};

impl<'a> OrganizationStore<'a> {
    pub async fn create_team(
        &self,
        organization_id: &str,
        name: &str,
        additional_fields: DbRecord,
    ) -> Result<Team, OpenAuthError> {
        let now = OffsetDateTime::now_utc();
        let mut create = Create::new("team")
            .data("id", DbValue::String(generate_random_string(ID_LENGTH)))
            .data("name", DbValue::String(name.to_owned()))
            .data(
                "organization_id",
                DbValue::String(organization_id.to_owned()),
            )
            .data("created_at", DbValue::Timestamp(now))
            .data("updated_at", DbValue::Timestamp(now))
            .force_allow_id();
        for (field, value) in additional_fields {
            create = create.data(field, value);
        }
        let record = self.adapter().create(create).await?;
        team_from_record(&record)
    }

    pub async fn update_team(
        &self,
        team_id: &str,
        name: &str,
        additional_fields: DbRecord,
    ) -> Result<Option<Team>, OpenAuthError> {
        let mut update = Update::new("team")
            .where_clause(id_where(team_id))
            .data("name", DbValue::String(name.to_owned()))
            .data("updated_at", DbValue::Timestamp(OffsetDateTime::now_utc()));
        for (field, value) in additional_fields {
            update = update.data(field, value);
        }
        self.adapter()
            .update(update)
            .await?
            .map(|record| team_from_record(&record))
            .transpose()
    }

    pub async fn delete_team(&self, team_id: &str) -> Result<(), OpenAuthError> {
        self.adapter()
            .delete_many(
                DeleteMany::new("team_member")
                    .where_clause(Where::new("team_id", DbValue::String(team_id.to_owned()))),
            )
            .await?;
        self.adapter()
            .delete(Delete::new("team").where_clause(id_where(team_id)))
            .await
    }

    pub async fn team_by_id(&self, team_id: &str) -> Result<Option<Team>, OpenAuthError> {
        self.adapter()
            .find_one(FindOne::new("team").where_clause(id_where(team_id)))
            .await?
            .map(|record| team_from_record(&record))
            .transpose()
    }

    pub async fn teams_for_organization(
        &self,
        organization_id: &str,
    ) -> Result<Vec<Team>, OpenAuthError> {
        self.adapter()
            .find_many(
                FindMany::new("team")
                    .where_clause(Where::new(
                        "organization_id",
                        DbValue::String(organization_id.to_owned()),
                    ))
                    .sort_by(Sort::new("created_at", SortDirection::Asc)),
            )
            .await?
            .iter()
            .map(team_from_record)
            .collect()
    }

    pub async fn create_team_member(
        &self,
        team_id: &str,
        user_id: &str,
        additional_fields: DbRecord,
    ) -> Result<TeamMember, OpenAuthError> {
        let mut create = Create::new("team_member")
            .data("id", DbValue::String(generate_random_string(ID_LENGTH)))
            .data("team_id", DbValue::String(team_id.to_owned()))
            .data("user_id", DbValue::String(user_id.to_owned()))
            .data("created_at", DbValue::Timestamp(OffsetDateTime::now_utc()))
            .force_allow_id();
        for (field, value) in additional_fields {
            create = create.data(field, value);
        }
        let record = self.adapter().create(create).await?;
        team_member_from_record(&record)
    }

    pub async fn team_member(
        &self,
        team_id: &str,
        user_id: &str,
    ) -> Result<Option<TeamMember>, OpenAuthError> {
        self.adapter()
            .find_one(
                FindOne::new("team_member")
                    .where_clause(Where::new("team_id", DbValue::String(team_id.to_owned())))
                    .where_clause(Where::new("user_id", DbValue::String(user_id.to_owned()))),
            )
            .await?
            .map(|record| team_member_from_record(&record))
            .transpose()
    }

    pub async fn team_members(&self, team_id: &str) -> Result<Vec<TeamMember>, OpenAuthError> {
        self.adapter()
            .find_many(
                FindMany::new("team_member")
                    .where_clause(Where::new("team_id", DbValue::String(team_id.to_owned())))
                    .sort_by(Sort::new("created_at", SortDirection::Asc)),
            )
            .await?
            .iter()
            .map(team_member_from_record)
            .collect()
    }

    pub async fn count_team_members(&self, team_id: &str) -> Result<u64, OpenAuthError> {
        self.adapter()
            .count(
                Count::new("team_member")
                    .where_clause(Where::new("team_id", DbValue::String(team_id.to_owned()))),
            )
            .await
    }

    pub async fn delete_team_member(
        &self,
        team_id: &str,
        user_id: &str,
    ) -> Result<(), OpenAuthError> {
        self.adapter()
            .delete_many(
                DeleteMany::new("team_member")
                    .where_clause(Where::new("team_id", DbValue::String(team_id.to_owned())))
                    .where_clause(Where::new("user_id", DbValue::String(user_id.to_owned()))),
            )
            .await?;
        Ok(())
    }

    pub async fn delete_team_members_for_user(
        &self,
        organization_id: &str,
        user_id: &str,
    ) -> Result<(), OpenAuthError> {
        for team in self.teams_for_organization(organization_id).await? {
            self.delete_team_member(&team.id, user_id).await?;
        }
        Ok(())
    }

    pub async fn set_active_team(
        &self,
        token: &str,
        team_id: Option<&str>,
    ) -> Result<(), OpenAuthError> {
        self.adapter()
            .update(
                Update::new("session")
                    .where_clause(Where::new("token", DbValue::String(token.to_owned())))
                    .data(
                        "activeTeamId",
                        team_id
                            .map(|value| DbValue::String(value.to_owned()))
                            .unwrap_or(DbValue::Null),
                    ),
            )
            .await?;
        Ok(())
    }

    pub async fn active_team_id(&self, token: &str) -> Result<Option<String>, OpenAuthError> {
        let Some(record) = self
            .adapter()
            .find_one(
                FindOne::new("session")
                    .where_clause(Where::new("token", DbValue::String(token.to_owned()))),
            )
            .await?
        else {
            return Ok(None);
        };
        crate::organization::models::optional_string(&record, "active_team_id").and_then(|value| {
            match value {
                Some(value) => Ok(Some(value)),
                None => crate::organization::models::optional_string(&record, "activeTeamId"),
            }
        })
    }
}