autoendpoint/extractors/
registration_path_args_with_uaid.rs

1use crate::error::{ApiError, ApiErrorKind};
2use crate::extractors::registration_path_args::RegistrationPathArgs;
3use crate::extractors::routers::RouterType;
4use crate::server::AppState;
5use actix_web::dev::Payload;
6use actix_web::web::Data;
7use actix_web::{FromRequest, HttpRequest};
8use futures::future::LocalBoxFuture;
9use futures::FutureExt;
10use uuid::Uuid;
11
12use autopush_common::db::User;
13
14/// An extension of `RegistrationPathArgs` which requires a `uaid` path arg.
15/// The `uaid` is verified by checking if the user exists in the database.
16pub struct RegistrationPathArgsWithUaid {
17    pub router_type: RouterType,
18    pub app_id: String,
19    pub user: User,
20}
21
22impl FromRequest for RegistrationPathArgsWithUaid {
23    type Error = ApiError;
24    type Future = LocalBoxFuture<'static, Result<Self, Self::Error>>;
25
26    fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
27        let req = req.clone();
28
29        async move {
30            let app_state: Data<AppState> = Data::extract(&req)
31                .into_inner()
32                .expect("No server state found");
33            let path_args = RegistrationPathArgs::extract(&req).into_inner()?;
34            let uaid = req
35                .match_info()
36                .get("uaid")
37                .expect("{uaid} must be part of the path")
38                .parse::<Uuid>()
39                .map_err(|_| ApiErrorKind::NoUser)?;
40
41            // Verify that the user exists
42            let Some(user) = app_state.db.get_user(&uaid).await? else {
43                return Err(ApiErrorKind::NoUser.into());
44            };
45
46            Ok(Self {
47                router_type: path_args.router_type,
48                app_id: path_args.app_id,
49                user,
50            })
51        }
52        .boxed_local()
53    }
54}