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, "organizationId", " = ", 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(
38 "id",
39 self.generated_id(self.exec(), "organizationRole", "organizationRole", "id")
40 .await?
41 .unwrap_or_else(|| Uuid::new_v4().to_string()),
42 );
43 active.set("organizationId", data.organization_id);
44 active.set("role", data.role);
45 active.set("permission", serde_json::to_string(&data.permission)?);
46 active.set("createdAt", Utc::now());
47 active.set("updatedAt", None::<chrono::DateTime<Utc>>);
48 model::insert::<Model>(self.exec(), &active)
49 .await?
50 .try_into()
51 }
52 async fn get_organization_role(
53 &self,
54 organization_id: &str,
55 selector: &OrganizationRoleSelector,
56 ) -> AuthResult<Option<OrganizationRole>> {
57 let mut sql = model::select_model::<Model>(self.exec());
58 scope(&mut sql, organization_id, selector);
59 model::limit_one(&mut sql);
60 self.exec()
61 .fetch_optional::<Model>(sql)
62 .await?
63 .map(TryInto::try_into)
64 .transpose()
65 }
66 async fn list_organization_roles(
67 &self,
68 organization_id: &str,
69 ) -> AuthResult<Vec<OrganizationRole>> {
70 let mut sql = model::select_model::<Model>(self.exec());
71 sql.push(" WHERE ");
72 sql.compare(Model::TABLE, "organizationId", " = ", organization_id);
73 sql.push(" LIMIT ");
74 sql.bind(self.find_many_limit());
75 self.exec()
76 .fetch_all::<Model>(sql)
77 .await?
78 .into_iter()
79 .map(TryInto::try_into)
80 .collect()
81 }
82 async fn count_organization_roles(&self, organization_id: &str) -> AuthResult<usize> {
83 let mut sql = Sql::with(self.exec().engine(), "SELECT COUNT(*) FROM ");
84 sql.ident(Model::TABLE);
85 sql.push(" WHERE ");
86 sql.compare(Model::TABLE, "organizationId", " = ", organization_id);
87 let count = self
88 .exec()
89 .fetch_scalar::<i64>(sql)
90 .await?
91 .unwrap_or_default();
92 usize::try_from(count)
93 .map_err(|_error| AuthError::internal("Organization role count overflow"))
94 }
95 async fn has_organization_role_members(
96 &self,
97 organization_id: &str,
98 role: &str,
99 ) -> AuthResult<bool> {
100 let mut sql = self.organization_models.member.select(self.exec());
101 sql.push(" WHERE ");
102 self.organization_models.member.compare(
103 &mut sql,
104 "organizationId",
105 " = ",
106 organization_id,
107 )?;
108 sql.push(" AND ");
109 self.organization_models
110 .member
111 .compare(&mut sql, "role", " LIKE ", format!("%{role}%"))?;
112 sql.push(" LIMIT ");
113 sql.bind(self.find_many_limit());
114 let members = self
115 .organization_models
116 .member
117 .fetch_all(self.exec(), sql)
118 .await?;
119 Ok(members.iter().any(|member| {
120 member
121 .role
122 .split(',')
123 .map(str::trim)
124 .any(|name| name == role)
125 }))
126 }
127 async fn update_organization_role(
128 &self,
129 organization_id: &str,
130 selector: &OrganizationRoleSelector,
131 update: UpdateOrganizationRole,
132 ) -> AuthResult<OrganizationRole> {
133 let mut select = model::select_model::<Model>(self.exec());
134 scope(&mut select, organization_id, selector);
135 model::limit_one(&mut select);
136 let mut row = self
137 .exec()
138 .fetch_optional::<Model>(select)
139 .await?
140 .ok_or_else(|| AuthError::bad_request("Role not found"))?;
141 let updated_at = Utc::now();
142 let mut sql = Sql::with(self.exec().engine(), "UPDATE ");
143 sql.ident(Model::TABLE);
144 sql.push(" SET ");
145 sql.assign("updatedAt", Some(updated_at));
146 if let Some(role) = update.role {
147 sql.push(", ");
148 sql.assign("role", role.clone());
149 row.role = role;
150 }
151 if let Some(permission) = update.permission {
152 let permission = serde_json::to_string(&permission)?;
153 sql.push(", ");
154 sql.assign("permission", permission.clone());
155 row.permission = permission;
156 }
157 scope(&mut sql, organization_id, selector);
158 _ = self.exec().execute(sql).await?;
159 row.updated_at = Some(updated_at);
160 row.try_into()
161 }
162 async fn delete_organization_role(
163 &self,
164 organization_id: &str,
165 selector: &OrganizationRoleSelector,
166 ) -> AuthResult<bool> {
167 let mut sql = Sql::with(self.exec().engine(), "DELETE FROM ");
168 sql.ident(Model::TABLE);
169 scope(&mut sql, organization_id, selector);
170 Ok(self.exec().execute(sql).await? > 0)
171 }
172}