pub async fn authenticate(&self, auth_req: AuthReq) -> Result<AuthGranted> {
        debug!(
            "Retrieving/generating keypair for an application: {:?}",
            auth_req
        );
        if let Some((client, map_address)) = &self.safe {
            let app_id = auth_req.app_id.as_bytes().to_vec();
            let keypair = match client.get_map_value(*map_address, app_id.clone()).await {
                Ok(value) => {
                    // This app already has its own keypair
                    trace!(
                        "The app ('{}') already has a Keypair in the Safe",
                        auth_req.app_id
                    );

                    // TODO: support for scenario when app was previously revoked,
                    // in which case we should generate a new keypair

                    let keypair_bytes = match value {
                        MapValue::Seq(seq_value) => seq_value.data,
                        MapValue::Unseq(data) => data,
                    };
                    let keypair_str = String::from_utf8(keypair_bytes).map_err(|_err| {
                        Error::AuthError(
                            "The Safe contains an invalid keypair associated to this app"
                                .to_string(),
                        )
                    })?;
                    let keypair: Keypair = serde_json::from_str(&keypair_str).map_err(|_err| {
                        Error::AuthError(
                            "The Safe contains an invalid keypair associated to this app"
                                .to_string(),
                        )
                    })?;

                    debug!(
                        "Keypair for the app being authorised ('{}') retrieved from the Safe: {}",
                        auth_req.app_id,
                        keypair.public_key()
                    );

                    keypair
                }
                Err(ClientError::ErrorMessage(NoSuchEntry)) => {
                    // This is the first time this app is being authorised,
                    // thus let's generate a keypair for it
                    trace!(
                        "The app ('{}') was not assigned a Keypair yet in the Safe. Generating one for it...",
                        auth_req.app_id
                    );
                    let mut rng = OsRng;
                    let keypair = Keypair::new_ed25519(&mut rng);

                    let keypair_str = serde_json::to_string(&keypair).map_err(|err| {
                        Error::AuthError(format!(
                            "Failed to serialised keypair to store it in the Safe: {}",
                            err
                        ))
                    })?;

                    debug!(
                        "New keypair generated for app ('{}') being authorised: {}",
                        auth_req.app_id,
                        keypair.public_key()
                    );

                    // Allocate some test coins
                    // TODO: we may want to allow different options here, either accept
                    // a proof of payment from the requester, transfer from the Safe's balance,
                    // or simply allocate testcoins as it's now.
                    let mut tmp_client = Client::new(
                        Some(keypair.clone()),
                        self.config_path.as_deref(),
                        self.bootstrap_contacts.clone(),
                    )
                    .await?;
                    tmp_client
                        .trigger_simulated_farming_payout(Token::from_nano(
                            DEFAULT_TEST_COINS_AMOUNT,
                        ))
                        .await?;

                    // Store the keypair in the Safe, mapped to the app id
                    let map_actions =
                        MapSeqEntryActions::new().ins(app_id, keypair_str.as_bytes().to_vec(), 0);

                    client
                        .edit_map_entries(*map_address, MapEntryActions::Seq(map_actions))
                        .await?;

                    keypair
                }
                Err(err) => {
                    return Err(Error::AuthError(format!(
                        "Failed to retrieve keypair from the Safe: {}",
                        err
                    )))
                }
            };

            Ok(AuthGranted {
                app_keypair: keypair,
                bootstrap_config: self.bootstrap_contacts.clone(),
            })
        } else {
            Err(Error::AuthenticatorError(
                "No Safe is currently unlocked".to_string(),
            ))
        }
    }
/// Authenticate an app request.
///
/// First, this function searches for an app info in the Safe.
/// If the app is found, then the `AuthGranted` struct is returned based on that information.
/// If the app is not found in the Safe, then it will be authenticated.
Authenticate an app request.
First, this function searches for an app info in the Safe.
If the app is found, then the `AuthGranted` struct is returned based on that information.
If the app is not found in the Safe, then it will be authenticated.
Authenticate an app request . First this function searches for an app info in the Safe . If the app is found then the ` AuthGranted ` struct is returned based on that information . If the app is not found in the Safe then it will be authenticated .
pub async fn authenticate(&self, auth_req: AuthReq) -> Result<AuthGranted> {
        debug!(
            "Retrieving/generating keypair for an application: {:?}",
            auth_req
        );
        if let Some((client, map_address)) = &self.safe {
            let app_id = auth_req.app_id.as_bytes().to_vec();
            let keypair = match client.get_map_value(*map_address, app_id.clone()).await {
                Ok(value) => {
                    // This app already has its own keypair
                    trace!(
                        "The app ('{}') already has a Keypair in the Safe",
                        auth_req.app_id
                    );
                    // TODO: support for scenario when app was previously revoked,
                    // in which case we should generate a new keypair
                    let keypair_bytes = match value {
                        MapValue::Seq(seq_value) => seq_value.data,
                        MapValue::Unseq(data) => data,
                    };
                    let keypair_str = String::from_utf8(keypair_bytes).map_err(|_err| {
                        Error::AuthError(
                            "The Safe contains an invalid keypair associated to this app"
                                .to_string(),
                        )
                    })?;
                    let keypair: Keypair = serde_json::from_str(&keypair_str).map_err(|_err| {
                        Error::AuthError(
                            "The Safe contains an invalid keypair associated to this app"
                                .to_string(),
                        )
                    })?;
                    debug!(
                        "Keypair for the app being authorised ('{}') retrieved from the Safe: {}",
                        auth_req.app_id,
                        keypair.public_key()
                    );
                    keypair
                }
                Err(ClientError::ErrorMessage(NoSuchEntry)) => {
                    // This is the first time this app is being authorised,
                    // thus let's generate a keypair for it
                    trace!(
                        "The app ('{}') was not assigned a Keypair yet in the Safe. Generating one for it...",
                        auth_req.app_id
                    );
                    let mut rng = OsRng;
                    let keypair = Keypair::new_ed25519(&mut rng);
                    let keypair_str = serde_json::to_string(&keypair).map_err(|err| {
                        Error::AuthError(format!(
                            "Failed to serialised keypair to store it in the Safe: {}",
                            err
                        ))
                    })?;
                    debug!(
                        "New keypair generated for app ('{}') being authorised: {}",
                        auth_req.app_id,
                        keypair.public_key()
                    );
                    // Allocate some test coins
                    // TODO: we may want to allow different options here, either accept
                    // a proof of payment from the requester, transfer from the Safe's balance,
                    // or simply allocate testcoins as it's now.
                    let mut tmp_client = Client::new(
                        Some(keypair.clone()),
                        self.config_path.as_deref(),
                        self.bootstrap_contacts.clone(),
                    )
                    .await?;
                    tmp_client
                        .trigger_simulated_farming_payout(Token::from_nano(
                            DEFAULT_TEST_COINS_AMOUNT,
                        ))
                        .await?;
                    // Store the keypair in the Safe, mapped to the app id
                    let map_actions =
                        MapSeqEntryActions::new().ins(app_id, keypair_str.as_bytes().to_vec(), 0);
                    client
                        .edit_map_entries(*map_address, MapEntryActions::Seq(map_actions))
                        .await?;
                    keypair
                }
                Err(err) => {
                    return Err(Error::AuthError(format!(
                        "Failed to retrieve keypair from the Safe: {}",
                        err
                    )))
                }
            };
            Ok(AuthGranted {
                app_keypair: keypair,
                bootstrap_config: self.bootstrap_contacts.clone(),
            })
        } else {
            Err(Error::AuthenticatorError(
                "No Safe is currently unlocked".to_string(),
            ))
        }
    }
pub async fn authenticate ( & self , auth_req : AuthReq ) -> Result < AuthGranted > { debug ! ( " " auth_req ) ; if let Some ( ( client , map_address ) ) = & self . safe { let app_id = auth_req . app_id . as_bytes ( ) . to_vec ( ) ; let keypair = match client . get_map_value ( * map_address , app_id . clone ( ) ) . await { Ok ( value ) => { // This app already has its own keypair trace ! ( " " auth_req app_id ) ; // TODO: support for scenario when app was previously revoked, // in which case we should generate a new keypair let keypair_bytes = match value { MapValue :: Seq ( seq_value ) => seq_value . data , MapValue :: Unseq ( data ) => data , } ; let keypair_str = String :: from_utf8 ( keypair_bytes ) . map_err ( | _err | { Error :: AuthError ( " " . to_string ( ) , ) } ) ? ; let keypair : Keypair = serde_json :: from_str ( & keypair_str ) . map_err ( | _err | { Error :: AuthError ( " " . to_string ( ) , ) } ) ? ; debug ! ( " " auth_req app_id keypair public_key ( ) ) ; keypair } Err ( ClientError :: ErrorMessage ( NoSuchEntry ) ) => { // This is the first time this app is being authorised, // thus let's generate a keypair for it trace ! ( " " auth_req app_id ) ; let mut rng = OsRng ; let keypair = Keypair :: new_ed25519 ( & mut rng ) ; let keypair_str = serde_json :: to_string ( & keypair ) . map_err ( | err | { Error :: AuthError ( format ! ( " " err ) ) } ) ? ; debug ! ( " " auth_req app_id keypair public_key ( ) ) ; // Allocate some test coins // TODO: we may want to allow different options here, either accept // a proof of payment from the requester, transfer from the Safe's balance, // or simply allocate testcoins as it's now. let mut tmp_client = Client :: new ( Some ( keypair . clone ( ) ) , self . config_path . as_deref ( ) , self . bootstrap_contacts . clone ( ) , ) . await ? ; tmp_client . trigger_simulated_farming_payout ( Token :: from_nano ( DEFAULT_TEST_COINS_AMOUNT , ) ) . await ? ; // Store the keypair in the Safe, mapped to the app id let map_actions = MapSeqEntryActions :: new ( ) . ins ( app_id , keypair_str . as_bytes ( ) . to_vec ( ) , 0 ) ; client . edit_map_entries ( * map_address , MapEntryActions :: Seq ( map_actions ) ) . await ? ; keypair } Err ( err ) => { return Err ( Error :: AuthError ( format ! ( " " err ) ) ) } } ; Ok ( AuthGranted { app_keypair : keypair , bootstrap_config : self . bootstrap_contacts . clone ( ) , } ) } else { Err ( Error :: AuthenticatorError ( " " . to_string ( ) , ) ) } }
Authenticate an app request.
Authenticate an app request .
&self
auth_req
AuthReq