Skip to main content

sofie_tenancy/
acting.rs

1use sofie::http::{CurrentSession, RequestContext};
2use sofie::prelude::*;
3use sofie_identity::AccountId;
4
5use crate::organization::{OrganizationArea, OrganizationMember, OrganizationRole, membership};
6use sofie::db::{Context, Resolve};
7
8const GONE: &str = "You are no longer a member of this organization.";
9
10/// Read on every request, so a removed member or a changed role counts at once.
11pub struct Acting {
12    member: OrganizationMember,
13}
14
15impl Acting {
16    #[must_use]
17    pub fn member(&self) -> &OrganizationMember {
18        &self.member
19    }
20
21    #[must_use]
22    pub fn role(&self) -> OrganizationRole {
23        self.member.role()
24    }
25
26    #[must_use]
27    pub fn into_member(self) -> OrganizationMember {
28        self.member
29    }
30
31    pub(crate) fn owning(&self) -> Result<()> {
32        if self.role() != OrganizationRole::Owner {
33            return Err(Error::Rule(ONLY_AN_OWNER.to_owned()));
34        }
35        Ok(())
36    }
37}
38
39const ONLY_AN_OWNER: &str = "Only an owner renames, hands over or deletes the organization.";
40
41impl<O: OrganizationArea, M> Resolve<RequestContext<O, M>> for Acting {
42    async fn resolve(context: &mut RequestContext<O, M>) -> Result<Self> {
43        let organization = Principal::<O>::resolve(context).await?.id();
44        let current = CurrentSession::resolve(context).await?;
45        let session = current.id().ok_or(Error::NotFound)?;
46        let unscoped = context.db().read();
47        let account = match current.account() {
48            Some(account) => AccountId::from_uuid(account),
49            None => sofie_identity::sessions::account_of(&unscoped, session)
50                .await?
51                .ok_or_else(|| Error::Rule(GONE.to_owned()))?,
52        };
53        let member = membership(&unscoped, organization, account)
54            .await?
55            .ok_or_else(|| Error::Rule(GONE.to_owned()))?;
56        Ok(Self { member })
57    }
58}