Skip to main content

autter_core/database/
organization_memberships.rs

1use crate::{
2    DataManager,
3    model::{
4        Error, Result, User, UserPermission,
5        organizations::{OrganizationMembership, OrganizationRole},
6    },
7};
8use oiseau::{PostgresRow, cache::Cache, execute, get, params, query_row, query_rows};
9use tetratto_core2::{auto_method, model::id::Id};
10
11impl DataManager {
12    /// Get a [`OrganizationMembership`] from an SQL row.
13    pub(crate) fn get_organization_membership_from_row(x: &PostgresRow) -> OrganizationMembership {
14        OrganizationMembership {
15            id: Id::deserialize(&get!(x->0(String))),
16            created: get!(x->1(i64)) as u128,
17            organization: Id::deserialize(&get!(x->2(String))),
18            owner: Id::Legacy(get!(x->3(i64)) as usize),
19            role: serde_json::from_str(&get!(x->4(String))).unwrap(),
20        }
21    }
22
23    auto_method!(get_organization_membership_by_id()@get_organization_membership_from_row -> "SELECT * FROM a_organization_memberships WHERE id = $1" --name="organization_membership" --returns=OrganizationMembership --cache-key-tmpl="srmp.organization_membership:{}");
24
25    /// Get all organization_memberships by user.
26    ///
27    /// # Arguments
28    /// * `user` - the ID of the user to fetch organization_memberships for
29    pub async fn get_organization_memberships_by_user(
30        &self,
31        user: &Id,
32    ) -> Result<Vec<OrganizationMembership>> {
33        let conn = match self.0.connect().await {
34            Ok(c) => c,
35            Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
36        };
37
38        let res = query_rows!(
39            &conn,
40            "SELECT * FROM a_organization_memberships WHERE owner = $1 ORDER BY created",
41            &[&(user.as_usize() as i64)],
42            |x| { Self::get_organization_membership_from_row(x) }
43        );
44
45        if let Err(e) = res {
46            return Err(Error::DatabaseError(e.to_string()));
47        }
48
49        Ok(res.unwrap())
50    }
51
52    /// Get all organization_memberships by organization (paginated).
53    ///
54    /// # Arguments
55    /// * `organization` - the ID of the user to fetch organization_memberships for
56    pub async fn get_organization_memberships_by_organization(
57        &self,
58        organization: &Id,
59        batch: usize,
60        page: usize,
61    ) -> Result<Vec<OrganizationMembership>> {
62        let conn = match self.0.connect().await {
63            Ok(c) => c,
64            Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
65        };
66
67        let res = query_rows!(
68            &conn,
69            "SELECT * FROM a_organization_memberships WHERE organization = $1 ORDER BY created DESC LIMIT $2 OFFSET $3",
70            &[
71                &organization.printable(),
72                &(batch as i64),
73                &((page * batch) as i64)
74            ],
75            |x| { Self::get_organization_membership_from_row(x) }
76        );
77
78        if res.is_err() {
79            return Err(Error::GeneralNotFound(
80                "organization_membership".to_string(),
81            ));
82        }
83
84        Ok(res.unwrap())
85    }
86
87    /// Get an organization membership by user and organization.
88    ///
89    /// # Arguments
90    /// * `user` - the ID of the user to fetch organization_memberships for
91    /// * `org` - the ID of the organization
92    pub async fn get_organization_membership_by_owner_organization(
93        &self,
94        user: &Id,
95        organization: &Id,
96    ) -> Result<OrganizationMembership> {
97        let conn = match self.0.connect().await {
98            Ok(c) => c,
99            Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
100        };
101
102        let res = query_row!(
103            &conn,
104            "SELECT * FROM a_organization_memberships WHERE owner = $1 AND organization = $2 LIMIT 1",
105            &[&(user.as_usize() as i64), &organization.printable()],
106            |x| { Ok(Self::get_organization_membership_from_row(x)) }
107        );
108
109        if res.is_err() {
110            return Err(Error::GeneralNotFound(
111                "organization_membership".to_string(),
112            ));
113        }
114
115        Ok(res.unwrap())
116    }
117
118    /// Create a new organization_membership in the database.
119    ///
120    /// # Arguments
121    /// * `data` - a mock [`OrganizationMembership`] object to insert
122    pub async fn create_organization_membership(&self, data: OrganizationMembership) -> Result<()> {
123        let conn = match self.0.connect().await {
124            Ok(c) => c,
125            Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
126        };
127
128        let res = execute!(
129            &conn,
130            "INSERT INTO a_organization_memberships VALUES ($1, $2, $3, $4, $5)",
131            params![
132                &data.id.printable(),
133                &(data.created as i64),
134                &data.organization.printable(),
135                &(data.owner.as_usize() as i64),
136                &serde_json::to_string(&data.role).unwrap()
137            ]
138        );
139
140        if let Err(e) = res {
141            return Err(Error::DatabaseError(e.to_string()));
142        }
143
144        // return
145        self.incr_organization_members(&data.organization).await?;
146        Ok(())
147    }
148
149    pub async fn delete_organization_membership(&self, id: &Id, user: User) -> Result<()> {
150        let organization_membership = self.get_organization_membership_by_id(&id).await?;
151        let org = self
152            .get_organization_by_id(&organization_membership.organization)
153            .await?;
154
155        if user.id != organization_membership.owner
156            && user.id != org.owner
157            && !user
158                .permissions
159                .contains(&UserPermission::ManageOrganizations)
160        {
161            return Err(Error::NotAllowed);
162        }
163
164        // delete user if they're a tenant user and they're trying to leave the org
165        let membership_user = if user.id == organization_membership.owner {
166            user
167        } else {
168            self.get_user_by_id(&organization_membership.owner).await?
169        };
170
171        if membership_user.org_as_tenant
172            && membership_user.principal_org == organization_membership.organization
173        {
174            self.delete_user(&membership_user.id, "", true).await?;
175        }
176
177        // ...
178        let conn = match self.0.connect().await {
179            Ok(c) => c,
180            Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
181        };
182
183        let res = execute!(
184            &conn,
185            "DELETE FROM a_organization_memberships WHERE id = $1",
186            &[&id.printable()]
187        );
188
189        if let Err(e) = res {
190            return Err(Error::DatabaseError(e.to_string()));
191        }
192
193        self.0
194            .1
195            .remove(format!("srmp.organization_membership:{}", id))
196            .await;
197
198        // return
199        self.decr_organization_members(&org.id).await?;
200        Ok(())
201    }
202
203    auto_method!(update_organization_membership_role(OrganizationRole) -> "UPDATE a_organization_memberships SET role = $1 WHERE id = $2" --serde --cache-key-tmpl="srmp.organization_membership:{}");
204}