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