sofie_identity/role_grant/
factory.rs1use sofie::http::{Permissions, is_permission};
2use sofie::prelude::*;
3
4use super::RoleGrant;
5use crate::role::RoleId;
6
7pub async fn grant(read: &Read, role: RoleId, permission: &str) -> Result<RoleGrant> {
10 refuse_unless_permission("permission", permission)?;
11 if let Some(held) = held(read, role, permission).await? {
12 return Ok(held);
13 }
14 Ok(RoleGrant {
15 meta: Meta::new()?,
16 role,
17 permission: permission.to_owned(),
18 })
19}
20
21pub async fn grant_as(
23 read: &Read,
24 granter: &Permissions,
25 role: RoleId,
26 permission: &str,
27) -> Result<RoleGrant> {
28 refuse_unless_held(granter, permission)?;
29 grant(read, role, permission).await
30}
31
32pub async fn revoke(read: &Read, role: RoleId, permission: &str) -> Result<RoleGrant> {
33 let mut held = held(read, role, permission).await?.ok_or(Error::NotFound)?;
34 held.delete();
35 Ok(held)
36}
37
38pub(crate) fn refuse_unless_permission(field: &str, text: &str) -> Result<()> {
39 if is_permission(text) {
40 return Ok(());
41 }
42 Err(Error::invalid(
43 field,
44 format!("`{text}` is not a permission such as `order.order.*.cancel`"),
45 ))
46}
47
48fn refuse_unless_held(granter: &Permissions, permission: &str) -> Result<()> {
49 refuse_unless_permission("permission", permission)?;
50 if granter.can_named(permission) {
51 return Ok(());
52 }
53 Err(Error::invalid(
54 "permission",
55 format!("`{permission}` is not covered by your own permissions, so you cannot grant it"),
56 ))
57}
58
59async fn held(read: &Read, role: RoleId, permission: &str) -> Result<Option<RoleGrant>> {
60 RoleGrant::query()
61 .where_(RoleGrant::ROLE.eq(role))
62 .where_(RoleGrant::PERMISSION.eq(permission.to_owned()))
63 .first(read)
64 .await
65}
66
67#[cfg(feature = "permitted-screens")]
68#[derive(Input)]
69pub struct Granted {
70 role: RoleId,
71 #[required]
72 #[unique]
73 permission: String,
74}
75
76#[cfg(feature = "permitted-screens")]
78pub struct Granter(Permissions);
79
80#[cfg(feature = "permitted-screens")]
81impl<A: sofie::http::Area> sofie::http::OwnerOf<A> for Granter {
82 fn of(context: &sofie::http::RequestContext<A>) -> Result<Self> {
83 Ok(Self(context.permissions().clone()))
84 }
85}
86
87#[cfg(feature = "permitted-screens")]
88impl sofie::db::Create for RoleGrant {
89 type Input = Granted;
90 type Owner = Granter;
91
92 fn create(input: Granted, granter: Granter) -> Result<Self> {
93 refuse_unless_held(&granter.0, &input.permission)?;
94 let mut grant = RoleGrant {
95 meta: Meta::new()?,
96 role: input.role,
97 permission: String::new(),
98 };
99 sofie::db::Update::update(&mut grant, input)?;
100 Ok(grant)
101 }
102}
103
104#[cfg(feature = "permitted-screens")]
105impl sofie::db::Update for RoleGrant {
106 type Input = Granted;
107
108 fn update(&mut self, input: Granted) -> Result<()> {
109 refuse_unless_permission("permission", &input.permission)?;
110 self.role = input.role;
111 self.permission = input.permission;
112 Ok(())
113 }
114}