      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100

    use actix_utils::future::{ready, Ready};
    use actix_web::{
        dev::{Extensions, Payload},
        Error, FromRequest, HttpMessage as _, HttpRequest,
    };

    pub(crate) struct IdentityItem {
        pub(crate) id: Option<String>,
        pub(crate) changed: bool,
    }

    /// The extractor type to obtain your identity from a request.
    ///
    /// ```
    /// use actix_web::*;
    /// use actix_identity::Identity;
    ///
    /// #[get("/")]
    /// async fn index(id: Identity) -> impl Responder {
    ///     // access request identity
    ///     if let Some(id) = id.identity() {
    ///         format!("Welcome! {}", id)
    ///     } else {
    ///         "Welcome Anonymous!".to_owned()
    ///     }
    /// }
    ///
    /// #[post("/login")]
    /// async fn login(id: Identity) -> impl Responder {
    ///     // remember identity
    ///     id.remember("User1".to_owned());
    ///
    ///     HttpResponse::Ok()
    /// }
    ///
    /// #[post("/logout")]
    /// async fn logout(id: Identity) -> impl Responder {
    ///     // remove identity
    ///     id.forget();
    ///
    ///     HttpResponse::Ok()
    /// }
    /// ```
    #[derive(Clone)]
    pub struct Identity(HttpRequest);

    impl Identity {
        /// Return the claimed identity of the user associated request or `None` if no identity can be
        /// found associated with the request.
        pub fn identity(&self) -> Option<String> {
            Identity::get_identity(&self.0.extensions())
        }

        /// Remember identity.
        pub fn remember(&self, identity: String) {
            if let Some(id) = self.0.extensions_mut().get_mut::<IdentityItem>() {
                id.id = Some(identity);
                id.changed = true;
            }
        }

        /// This method is used to 'forget' the current identity on subsequent requests.
        pub fn forget(&self) {
            if let Some(id) = self.0.extensions_mut().get_mut::<IdentityItem>() {
                id.id = None;
                id.changed = true;
            }
        }

        pub(crate) fn get_identity(extensions: &Extensions) -> Option<String> {
            let id = extensions.get::<IdentityItem>()?;
            id.id.clone()
        }
    }

    /// Extractor implementation for Identity type.
    ///
    /// ```
    /// # use actix_web::*;
    /// use actix_identity::Identity;
    ///
    /// #[get("/")]
    /// async fn index(id: Identity) -> impl Responder {
    ///     // access request identity
    ///     if let Some(id) = id.identity() {
    ///         format!("Welcome! {}", id)
    ///     } else {
    ///         "Welcome Anonymous!".to_owned()
    ///     }
    /// }
    /// ```
    impl FromRequest for Identity {
        type Error = Error;
        type Future = Ready<Result<Identity, Error>>;

        #[inline]
        fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
            ready(Ok(Identity(req.clone())))
        }
    }