Skip to main content

sofie_http/
principal.rs

1use std::marker::PhantomData;
2
3use sofie_core::{Error, Result, Uuid};
4use sofie_db::{Id, Resolve};
5
6use crate::{Area, AreaPrincipal, RequestContext};
7
8/// The aggregate an area's principal signs in as.
9pub type PrincipalRecord<A> = <<A as Area>::Principal as AreaPrincipal>::Record;
10
11/// Resolves only in `A`, so a handler cannot ask for another area's principal.
12pub struct Principal<A: Area> {
13    id: Uuid,
14    area: PhantomData<fn() -> A>,
15}
16
17impl<A: Area> Principal<A> {
18    #[must_use]
19    pub fn id(&self) -> Id<PrincipalRecord<A>> {
20        Id::from_uuid(self.id)
21    }
22}
23
24/// The area's guard required it before the handler ran.
25impl<A: Area, M> Resolve<RequestContext<A, M>> for Principal<A> {
26    fn resolve(context: &mut RequestContext<A, M>) -> impl Future<Output = Result<Self>> + Send {
27        let principal = context
28            .session()
29            .principal_in(A::NAME)
30            .map(|id| Self {
31                id,
32                area: PhantomData,
33            })
34            .ok_or(Error::NotFound);
35        std::future::ready(principal)
36    }
37}