alibi_sqlx/store/
organization_roles.rs1use super::SqlxStore;
2use super::entities::organization_role::Model;
3use crate::model::{self, ActiveRow, SqlxModel};
4use crate::schema::AuthSchema;
5use crate::sql::Sql;
6use alibi_core::error::{AuthError, AuthResult};
7use alibi_core::store::OrganizationRoleStore;
8use alibi_core::types::{
9 CreateOrganizationRole, OrganizationRole, OrganizationRoleSelector, UpdateOrganizationRole,
10};
11use async_trait::async_trait;
12use chrono::Utc;
13use uuid::Uuid;
14
15fn scope(sql: &mut Sql, organization_id: &str, selector: &OrganizationRoleSelector) {
17 sql.push(" WHERE ");
18 sql.compare(Model::TABLE, "organization_id", " = ", organization_id);
19 sql.push(" AND ");
20 match selector {
21 OrganizationRoleSelector::Id(id) => {
22 sql.compare(Model::TABLE, "id", " = ", id.as_str());
23 }
24 OrganizationRoleSelector::Name(name) => {
25 sql.compare(Model::TABLE, "role", " = ", name.as_str());
26 }
27 }
28}
29
30#[async_trait]
31impl<S: AuthSchema> OrganizationRoleStore for SqlxStore<S> {
32 async fn create_organization_role(
33 &self,
34 data: CreateOrganizationRole,
35 ) -> AuthResult<OrganizationRole> {
36 let mut active = ActiveRow::new();
37 active.set("id", Uuid::new_v4().to_string());
38 active.set("organization_id", data.organization_id);
39 active.set("role", data.role);
40 active.set("permission", serde_json::to_string(&data.permission)?);
41 active.set("created_at", Utc::now());
42 active.set("updated_at", None::<chrono::DateTime<Utc>>);
43 model::insert::<Model>(self.exec(), &active)
44 .await?
45 .try_into()
46 }
47 async fn get_organization_role(
48 &self,
49 organization_id: &str,
50 selector: &OrganizationRoleSelector,
51 ) -> AuthResult<Option<OrganizationRole>> {
52 let mut sql = model::select_model::<Model>(self.exec());
53 scope(&mut sql, organization_id, selector);
54 model::limit_one(&mut sql);
55 self.exec()
56 .fetch_optional::<Model>(sql)
57 .await?
58 .map(TryInto::try_into)
59 .transpose()
60 }
61 async fn list_organization_roles(
62 &self,
63 organization_id: &str,
64 ) -> AuthResult<Vec<OrganizationRole>> {
65 let mut sql = model::select_model::<Model>(self.exec());
66 sql.push(" WHERE ");
67 sql.compare(Model::TABLE, "organization_id", " = ", organization_id);
68 sql.push(" LIMIT ");
69 sql.bind(self.find_many_limit());
70 self.exec()
71 .fetch_all::<Model>(sql)
72 .await?
73 .into_iter()
74 .map(TryInto::try_into)
75 .collect()
76 }
77 async fn count_organization_roles(&self, organization_id: &str) -> AuthResult<usize> {
78 let mut sql = Sql::with(self.exec().engine(), "SELECT COUNT(*) FROM ");
79 sql.ident(Model::TABLE);
80 sql.push(" WHERE ");
81 sql.compare(Model::TABLE, "organization_id", " = ", organization_id);
82 let count = self
83 .exec()
84 .fetch_scalar::<i64>(sql)
85 .await?
86 .unwrap_or_default();
87 usize::try_from(count)
88 .map_err(|_error| AuthError::internal("Organization role count overflow"))
89 }
90 async fn has_organization_role_members(
91 &self,
92 organization_id: &str,
93 role: &str,
94 ) -> AuthResult<bool> {
95 let mut sql = self.organization_models.member.select(self.exec());
96 sql.push(" WHERE ");
97 self.organization_models.member.compare(
98 &mut sql,
99 "organization_id",
100 " = ",
101 organization_id,
102 )?;
103 sql.push(" AND ");
104 self.organization_models
105 .member
106 .compare(&mut sql, "role", " LIKE ", format!("%{role}%"))?;
107 sql.push(" LIMIT ");
108 sql.bind(self.find_many_limit());
109 let members = self
110 .organization_models
111 .member
112 .fetch_all(self.exec(), sql)
113 .await?;
114 Ok(members.iter().any(|member| {
115 member
116 .role
117 .split(',')
118 .map(str::trim)
119 .any(|name| name == role)
120 }))
121 }
122 async fn update_organization_role(
123 &self,
124 organization_id: &str,
125 selector: &OrganizationRoleSelector,
126 update: UpdateOrganizationRole,
127 ) -> AuthResult<OrganizationRole> {
128 let mut select = model::select_model::<Model>(self.exec());
129 scope(&mut select, organization_id, selector);
130 model::limit_one(&mut select);
131 let mut row = self
132 .exec()
133 .fetch_optional::<Model>(select)
134 .await?
135 .ok_or_else(|| AuthError::bad_request("Role not found"))?;
136 let updated_at = Utc::now();
137 let mut sql = Sql::with(self.exec().engine(), "UPDATE ");
138 sql.ident(Model::TABLE);
139 sql.push(" SET ");
140 sql.assign("updated_at", Some(updated_at));
141 if let Some(role) = update.role {
142 sql.push(", ");
143 sql.assign("role", role.clone());
144 row.role = role;
145 }
146 if let Some(permission) = update.permission {
147 let permission = serde_json::to_string(&permission)?;
148 sql.push(", ");
149 sql.assign("permission", permission.clone());
150 row.permission = permission;
151 }
152 scope(&mut sql, organization_id, selector);
153 _ = self.exec().execute(sql).await?;
154 row.updated_at = Some(updated_at);
155 row.try_into()
156 }
157 async fn delete_organization_role(
158 &self,
159 organization_id: &str,
160 selector: &OrganizationRoleSelector,
161 ) -> AuthResult<bool> {
162 let mut sql = Sql::with(self.exec().engine(), "DELETE FROM ");
163 sql.ident(Model::TABLE);
164 scope(&mut sql, organization_id, selector);
165 Ok(self.exec().execute(sql).await? > 0)
166 }
167}