headless_lms_models/
pending_roles.rs1use crate::{
2 prelude::*,
3 roles::{RoleDomain, RoleInfo, UserRole},
4};
5
6#[derive(Debug, Serialize)]
7#[cfg_attr(feature = "ts_rs", derive(TS))]
8pub struct PendingRole {
9 pub id: Uuid,
10 pub user_email: String,
11 pub role: UserRole,
12 pub expires_at: DateTime<Utc>,
13}
14
15pub async fn insert(
16 conn: &mut PgConnection,
17 pkey_policy: PKeyPolicy<Uuid>,
18 role_info: RoleInfo,
19) -> ModelResult<Uuid> {
20 match role_info.domain {
21 crate::roles::RoleDomain::Global
22 | crate::roles::RoleDomain::Organization(_)
23 | crate::roles::RoleDomain::Exam(_) => {
24 return Err(ModelError::new(
25 ModelErrorType::InvalidRequest,
26 "Cannot use a pending role for a role this broad".to_string(),
27 None,
28 ));
29 }
30
31 crate::roles::RoleDomain::Course(_) | crate::roles::RoleDomain::CourseInstance(_) => (),
32 };
33
34 match role_info.role {
35 UserRole::Admin | UserRole::Teacher => {
36 return Err(ModelError::new(
37 ModelErrorType::InvalidRequest,
38 "Cannot use a pending role with this much power".to_string(),
39 None,
40 ));
41 }
42 _ => (),
43 }
44
45 let course_id = match role_info.domain {
46 crate::roles::RoleDomain::Course(id) => Some(id),
47 _ => None,
48 };
49
50 let course_instance_id = match role_info.domain {
51 crate::roles::RoleDomain::CourseInstance(id) => Some(id),
52 _ => None,
53 };
54
55 let id = sqlx::query!(
56 r#"
57INSERT INTO pending_roles (
58 id,
59 user_email,
60 role,
61 course_id,
62 course_instance_id
63 )
64VALUES ($1, $2, $3, $4, $5)
65RETURNING id;
66 "#,
67 pkey_policy.into_uuid(),
68 role_info.email,
69 role_info.role as UserRole,
70 course_id,
71 course_instance_id
72 )
73 .fetch_one(conn)
74 .await?
75 .id;
76 Ok(id)
77}
78
79pub async fn get_all(conn: &mut PgConnection, domain: RoleDomain) -> ModelResult<Vec<PendingRole>> {
80 let res = match domain {
81 RoleDomain::Global | RoleDomain::Organization(_) | RoleDomain::Exam(_) => {
82 return Ok(Vec::new());
83 }
84 RoleDomain::Course(course_id) => {
85 sqlx::query_as!(
86 PendingRole,
87 r#"
88SELECT id, user_email, expires_at, role AS "role!: UserRole" FROM pending_roles
89WHERE course_id = $1
90AND deleted_at IS NULL
91AND expires_at > NOW()
92 "#,
93 course_id
94 )
95 .fetch_all(&mut *conn)
96 .await?
97 }
98 RoleDomain::CourseInstance(course_instance_id) => {
99 sqlx::query_as!(
100 PendingRole,
101 r#"
102SELECT id, user_email, expires_at, role AS "role!: UserRole" FROM pending_roles
103WHERE course_instance_id = $1
104AND deleted_at IS NULL
105AND expires_at > NOW()
106 "#,
107 course_instance_id
108 )
109 .fetch_all(&mut *conn)
110 .await?
111 }
112 };
113 Ok(res)
114}