headless_lms_server/controllers/course_material/
user_details.rs

1use std::net::IpAddr;
2
3use headless_lms_utils::ip_to_country::IpToCountryMapper;
4use models::user_details::UserDetail;
5
6use crate::prelude::*;
7
8/**
9GET `/api/v0/course-material/user-details/user` - Find user details by user id
10*/
11#[instrument(skip(pool))]
12pub async fn get_user_details(
13    user: AuthUser,
14    pool: web::Data<PgPool>,
15) -> ControllerResult<web::Json<UserDetail>> {
16    let mut conn = pool.acquire().await?;
17
18    let token = skip_authorize();
19
20    let res = models::user_details::get_user_details_by_user_id(&mut conn, user.id).await?;
21    token.authorized_ok(web::Json(res))
22}
23
24#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
25#[cfg_attr(feature = "ts_rs", derive(TS))]
26pub struct UserInfoPayload {
27    pub email: String,
28    pub first_name: String,
29    pub last_name: String,
30    pub country: String,
31    pub email_communication_consent: bool,
32}
33
34/**
35POST `/api/v0/course-material/user-details/update-user-info` - Updates the users information such as email, name, country and email communication consent
36*/
37#[instrument(skip(pool))]
38pub async fn update_user_info(
39    user: AuthUser,
40    pool: web::Data<PgPool>,
41    payload: web::Json<UserInfoPayload>,
42) -> ControllerResult<web::Json<UserDetail>> {
43    let mut conn = pool.acquire().await?;
44    let res = models::user_details::update_user_info(
45        &mut conn,
46        user.id,
47        &payload.email,
48        &payload.first_name,
49        &payload.last_name,
50        &payload.country,
51        payload.email_communication_consent,
52    )
53    .await?;
54
55    let token = skip_authorize();
56    token.authorized_ok(web::Json(res))
57}
58
59/**
60GET `/api/v0/course-material/user-details/users-ip-country` - Find users country by their IP  address
61*/
62pub async fn get_user_country_by_ip(
63    req: HttpRequest,
64    ip_to_country_mapper: web::Data<IpToCountryMapper>,
65) -> ControllerResult<String> {
66    let connection_info = req.connection_info();
67
68    let ip: Option<IpAddr> = connection_info
69        .realip_remote_addr()
70        .and_then(|ip| ip.parse::<IpAddr>().ok());
71
72    let country = ip
73        .and_then(|ip| ip_to_country_mapper.map_ip_to_country(&ip))
74        .map(|c| c.to_string())
75        .unwrap_or_default();
76
77    let token = skip_authorize();
78    token.authorized_ok(country.to_string())
79}
80
81/**
82Add a route for each controller in this module.
83
84The name starts with an underline in order to appear before other functions in the module documentation.
85
86We add the routes by calling the route method instead of using the route annotations because this method preserves the function signatures for documentation.
87*/
88pub fn _add_routes(cfg: &mut ServiceConfig) {
89    cfg.route("/user", web::get().to(get_user_details))
90        .route("/update-user-info", web::post().to(update_user_info))
91        .route("/users-ip-country", web::get().to(get_user_country_by_ip));
92}