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