systemprompt_users/repository/
role_directory.rs1use std::sync::Arc;
8
9use async_trait::async_trait;
10use sqlx::PgPool;
11use systemprompt_security::authz::{AuthzError, RoleDirectory, SharedRoleDirectory};
12
13#[derive(Debug)]
14pub struct UsersRoleDirectory {
15 pool: Arc<PgPool>,
16}
17
18impl UsersRoleDirectory {
19 #[must_use]
20 pub fn shared(pool: Arc<PgPool>) -> SharedRoleDirectory {
21 Arc::new(Self { pool })
22 }
23}
24
25#[async_trait]
26impl RoleDirectory for UsersRoleDirectory {
27 async fn unknown_roles(&self, candidates: &[String]) -> Result<Vec<String>, AuthzError> {
28 let rows = sqlx::query!(
29 r#"
30 SELECT candidate AS "candidate!"
31 FROM UNNEST($1::text[]) AS candidate
32 WHERE NOT EXISTS (
33 SELECT 1 FROM users WHERE candidate = ANY(users.roles)
34 )
35 "#,
36 candidates,
37 )
38 .fetch_all(&*self.pool)
39 .await?;
40 Ok(rows.into_iter().map(|row| row.candidate).collect())
41 }
42}
43
44systemprompt_security::register_role_directory!(UsersRoleDirectory::shared);