Repository: meilisearch/meilisearch
File: meilisearch-http/src/extractors/authentication/mod.rs (Rust)

Code before:
            (token, None) => Err(AuthenticationError::InvalidToken(token).into()),
        }
    }

    async fn auth_token(auth: AuthController, data: Option<D>) -> Result<Self, ResponseError>
    where
        P: Policy + 'static,
    {
        match Self::authenticate(auth, "", None).await?.1 {
            Some(filters) => match data {
                Some(data) => Ok(Self {
                    data,
                    filters,
                    _marker: PhantomData,
                }),
                None => Err(AuthenticationError::IrretrievableState.into()),
            },
            None => Err(AuthenticationError::MissingAuthorizationHeader.into()),
        }
    }

    async fn authenticate<S>(
        auth: AuthController,
        token: S,
        index: Option<String>,
    ) -> Result<(S, Option<AuthFilter>), ResponseError>
    where
        P: Policy + 'static,
        S: AsRef<str> + 'static + Send,
    {
        Ok(tokio::task::spawn_blocking(move || {
            let res = P::authenticate(auth, token.as_ref(), index.as_deref());
            (token, res)
        })
        .await
        .map_err(|e| ResponseError::from_msg(e.to_string(), Code::Internal))?)
    }
}

impl<P, D> Deref for GuardedData<P, D> {
    type Target = D;

    fn deref(&self) -> &Self::Target {
        &self.data
    }
}

impl<P: Policy + 'static, D: 'static + Clone> FromRequest for GuardedData<P, D> {
    type Error = ResponseError;

    type Future = Pin<Box<dyn Future<Output = Result<Self, Self::Error>>>>;

Review comment (security):
We may return only an `Option<AuthFilter>`, this would simplify the upper functions.

Code after:
            None => Err(AuthenticationError::InvalidToken.into()),
        }
    }

    async fn auth_token(auth: AuthController, data: Option<D>) -> Result<Self, ResponseError>
    where
        P: Policy + 'static,
    {
        match Self::authenticate(auth, String::new(), None).await? {
            Some(filters) => match data {
                Some(data) => Ok(Self {
                    data,
                    filters,
                    _marker: PhantomData,
                }),
                None => Err(AuthenticationError::IrretrievableState.into()),
            },
            None => Err(AuthenticationError::MissingAuthorizationHeader.into()),
        }
    }

    async fn authenticate(
        auth: AuthController,
        token: String,
        index: Option<String>,
    ) -> Result<Option<AuthFilter>, ResponseError>
    where
        P: Policy + 'static,
    {
        Ok(tokio::task::spawn_blocking(move || {
            P::authenticate(auth, token.as_ref(), index.as_deref())
        })
        .await
        .map_err(|e| ResponseError::from_msg(e.to_string(), Code::Internal))?)
    }
}

impl<P, D> Deref for GuardedData<P, D> {
    type Target = D;

    fn deref(&self) -> &Self::Target {
        &self.data
    }
}

impl<P: Policy + 'static, D: 'static + Clone> FromRequest for GuardedData<P, D> {
    type Error = ResponseError;

    type Future = Pin<Box<dyn Future<Output = Result<Self, Self::Error>>>>;

    fn from_request(