headless_lms_server/controllers/main_frontend/
user_details.rs

1use models::{pages::SearchRequest, user_details::UserDetail};
2
3use crate::prelude::*;
4use headless_lms_utils::ip_to_country::IpToCountryMapper;
5use std::net::IpAddr;
6
7/**
8GET `/api/v0/main-frontend/user-details/[id]` - Find user details by user id
9*/
10#[instrument(skip(pool))]
11pub async fn get_user_details(
12    user: AuthUser,
13    pool: web::Data<PgPool>,
14    user_id: web::Path<Uuid>,
15) -> ControllerResult<web::Json<UserDetail>> {
16    let mut conn = pool.acquire().await?;
17
18    let token = authorize(
19        &mut conn,
20        Act::ViewUserProgressOrDetails,
21        Some(user.id),
22        Res::GlobalPermissions,
23    )
24    .await?;
25    let res = models::user_details::get_user_details_by_user_id(&mut conn, *user_id).await?;
26    token.authorized_ok(web::Json(res))
27}
28
29/**
30GET `/api/v0/main-frontend/user-details/search-by-email` - Allows to search user by their email
31*/
32#[instrument(skip(pool))]
33pub async fn search_users_by_email(
34    user: AuthUser,
35    pool: web::Data<PgPool>,
36    payload: web::Json<SearchRequest>,
37) -> ControllerResult<web::Json<Vec<UserDetail>>> {
38    let mut conn = pool.acquire().await?;
39
40    let token = authorize(
41        &mut conn,
42        Act::ViewUserProgressOrDetails,
43        Some(user.id),
44        Res::GlobalPermissions,
45    )
46    .await?;
47    let res =
48        models::user_details::search_for_user_details_by_email(&mut conn, &payload.query).await?;
49    token.authorized_ok(web::Json(res))
50}
51
52/**
53GET `/api/v0/main-frontend/user-details/search-by-other-details` - Allows to search user by their names etc.
54*/
55#[instrument(skip(pool))]
56pub async fn search_users_by_other_details(
57    user: AuthUser,
58    pool: web::Data<PgPool>,
59    payload: web::Json<SearchRequest>,
60) -> ControllerResult<web::Json<Vec<UserDetail>>> {
61    let mut conn = pool.acquire().await?;
62
63    let token = authorize(
64        &mut conn,
65        Act::ViewUserProgressOrDetails,
66        Some(user.id),
67        Res::GlobalPermissions,
68    )
69    .await?;
70    let res =
71        models::user_details::search_for_user_details_by_other_details(&mut conn, &payload.query)
72            .await?;
73    token.authorized_ok(web::Json(res))
74}
75
76/**
77GET `/api/v0/main-frontend/user-details/search-fuzzy-match` - Allows to find the right user details in cases where there is a small typing error in the search query
78*/
79#[instrument(skip(pool))]
80pub async fn search_users_fuzzy_match(
81    user: AuthUser,
82    pool: web::Data<PgPool>,
83    payload: web::Json<SearchRequest>,
84) -> ControllerResult<web::Json<Vec<UserDetail>>> {
85    let mut conn = pool.acquire().await?;
86
87    let token = authorize(
88        &mut conn,
89        Act::ViewUserProgressOrDetails,
90        Some(user.id),
91        Res::GlobalPermissions,
92    )
93    .await?;
94    let res = models::user_details::search_for_user_details_fuzzy_match(&mut conn, &payload.query)
95        .await?;
96    token.authorized_ok(web::Json(res))
97}
98
99/**
100GET `/api/v0/main-frontend/user-details/get-users-by-course-id` - Get user details of users that are in the course
101*/
102pub async fn get_users_by_course_id(
103    course_id: web::Path<Uuid>,
104    user: AuthUser,
105    pool: web::Data<PgPool>,
106) -> ControllerResult<web::Json<Vec<UserDetail>>> {
107    let mut conn = pool.acquire().await?;
108
109    let token = authorize(
110        &mut conn,
111        Act::ViewUserProgressOrDetails,
112        Some(user.id),
113        Res::Course(*course_id),
114    )
115    .await?;
116    let res = models::user_details::get_users_by_course_id(&mut conn, *course_id).await?;
117    token.authorized_ok(web::Json(res))
118}
119
120pub async fn get_user_country_by_ip(
121    req: HttpRequest,
122    ip_to_country_mapper: web::Data<IpToCountryMapper>,
123) -> ControllerResult<String> {
124    let connection_info = req.connection_info();
125
126    let ip: Option<IpAddr> = connection_info
127        .realip_remote_addr()
128        .and_then(|ip| ip.parse::<IpAddr>().ok());
129
130    let country = ip
131        .and_then(|ip| ip_to_country_mapper.map_ip_to_country(&ip))
132        .map(|c| c.to_string())
133        .unwrap_or_default();
134
135    let token = skip_authorize();
136    token.authorized_ok(country)
137}
138
139pub fn _add_routes(cfg: &mut ServiceConfig) {
140    cfg.route("/search-by-email", web::post().to(search_users_by_email))
141        .route(
142            "/search-by-other-details",
143            web::post().to(search_users_by_other_details),
144        )
145        .route(
146            "/search-fuzzy-match",
147            web::post().to(search_users_fuzzy_match),
148        )
149        .route("/user/{user_id}", web::get().to(get_user_details))
150        .route("/users-ip-country", web::get().to(get_user_country_by_ip))
151        .route(
152            "/{course_id}/get-users-by-course-id",
153            web::get().to(get_users_by_course_id),
154        );
155}