79 lines
2.1 KiB
Rust
79 lines
2.1 KiB
Rust
use std::collections::HashSet;
|
|
|
|
use anyhow::{Context as _, Result};
|
|
use interim_pgtypes::{
|
|
pg_acl::PgPrivilegeType,
|
|
pg_database::PgDatabase,
|
|
pg_role::{PgRole, RoleTree, user_id_from_rolname},
|
|
};
|
|
use sqlx::{PgConnection, query};
|
|
use uuid::Uuid;
|
|
|
|
use crate::bases::Base;
|
|
|
|
pub struct BaseUserPerm {
|
|
pub id: Uuid,
|
|
pub base_id: Uuid,
|
|
pub user_id: Uuid,
|
|
pub perm: String,
|
|
}
|
|
|
|
pub async fn sync_perms_for_base(
|
|
base_id: Uuid,
|
|
app_db: &mut PgConnection,
|
|
client: &mut PgConnection,
|
|
) -> Result<()> {
|
|
let db = PgDatabase::fetch_current(&mut *client).await?;
|
|
let explicit_roles = PgRole::fetch_by_names_any(
|
|
db.datacl
|
|
.unwrap_or(vec![])
|
|
.into_iter()
|
|
.filter(|item| {
|
|
item.privileges
|
|
.iter()
|
|
.any(|privilege| privilege.privilege == PgPrivilegeType::Connect)
|
|
})
|
|
.map(|item| item.grantee)
|
|
.collect(),
|
|
&mut *client,
|
|
)
|
|
.await?;
|
|
let mut all_roles: HashSet<PgRole> = HashSet::new();
|
|
for explicit_role in explicit_roles {
|
|
if let Some(role_tree) = RoleTree::fetch_members(explicit_role.oid, &mut *client).await? {
|
|
for implicit_role in role_tree.flatten_inherited() {
|
|
all_roles.insert(implicit_role.clone());
|
|
}
|
|
}
|
|
}
|
|
let base = Base::fetch_by_id(base_id, &mut *app_db)
|
|
.await?
|
|
.context("base with that id not found")?;
|
|
let user_ids: Vec<Uuid> = all_roles
|
|
.iter()
|
|
.filter_map(|role| user_id_from_rolname(&role.rolname, &base.user_role_prefix).ok())
|
|
.collect();
|
|
query!(
|
|
"delete from base_user_perms where base_id = $1 and not (user_id = any($2))",
|
|
base_id,
|
|
user_ids.as_slice(),
|
|
)
|
|
.execute(&mut *app_db)
|
|
.await?;
|
|
for user_id in user_ids {
|
|
query!(
|
|
"
|
|
insert into base_user_perms
|
|
(id, base_id, user_id, perm)
|
|
values ($1, $2, $3, 'connect')
|
|
on conflict (base_id, user_id, perm) do nothing
|
|
",
|
|
Uuid::now_v7(),
|
|
base.id,
|
|
user_id
|
|
)
|
|
.execute(&mut *app_db)
|
|
.await?;
|
|
}
|
|
Ok(())
|
|
}
|