qcs_api_client_openapi/apis/
authentication_api.rs

1// Copyright 2022 Rigetti Computing
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15/*
16 * Rigetti QCS API
17 *
18 * # Introduction  This is the documentation for the Rigetti QCS HTTP API.  You can find out more about Rigetti at [https://rigetti.com](https://rigetti.com), and also interact with QCS via the web at [https://qcs.rigetti.com](https://qcs.rigetti.com).  This API is documented in **OpenAPI format** and so is compatible with the dozens of language-specific client generators available [here](https://github.com/OpenAPITools/openapi-generator) and elsewhere on the web.  # Principles  This API follows REST design principles where appropriate, and otherwise an HTTP RPC paradigm. We adhere to the Google [API Improvement Proposals](https://google.aip.dev/general) where reasonable to provide a consistent, intuitive developer experience. HTTP response codes match their specifications, and error messages fit a common format.  # Authentication  All access to the QCS API requires OAuth2 authentication provided by Okta. You can request access [here](https://www.rigetti.com/get-quantum). Once you have a user account, you can download your access token from QCS [here](https://qcs.rigetti.com/auth/token).   That access token is valid for 24 hours after issuance. The value of `access_token` within the JSON file is the token used for authentication (don't use the entire JSON file).  Authenticate requests using the `Authorization` header and a `Bearer` prefix:  ``` curl --header \"Authorization: Bearer eyJraW...Iow\" ```  # Quantum Processor Access  Access to the quantum processors themselves is not yet provided directly by this HTTP API, but is instead performed over ZeroMQ/[rpcq](https://github.com/rigetti/rpcq). Until that changes, we suggest using [pyquil](https://github.com/rigetti/pyquil) to build and execute quantum programs via the Legacy API.  # Legacy API  Our legacy HTTP API remains accessible at https://forest-server.qcs.rigetti.com, and it shares a source of truth with this API's services. You can use either service with the same user account and means of authentication. We strongly recommend using the API documented here, as the legacy API is on the path to deprecation.
19 *
20 * The version of the OpenAPI document: 2020-07-31
21 * Contact: support@rigetti.com
22 * Generated by: https://openapi-generator.tech
23 */
24
25use super::{configuration, Error};
26use crate::apis::ResponseContent;
27use ::qcs_api_client_common::backoff::{
28    duration_from_io_error, duration_from_reqwest_error, duration_from_response, ExponentialBackoff,
29};
30#[cfg(feature = "tracing")]
31use qcs_api_client_common::configuration::tokens::TokenRefresher;
32use reqwest::StatusCode;
33use serde::{Deserialize, Serialize};
34
35/// Serialize command-line arguments for [`auth_email_password_reset_token`]
36#[cfg(feature = "clap")]
37#[derive(Debug, clap::Args)]
38pub struct AuthEmailPasswordResetTokenClapParams {
39    pub auth_email_password_reset_token_request: Option<
40        crate::clap_utils::JsonMaybeStdin<crate::models::AuthEmailPasswordResetTokenRequest>,
41    >,
42}
43
44#[cfg(feature = "clap")]
45impl AuthEmailPasswordResetTokenClapParams {
46    pub async fn execute(
47        self,
48        configuration: &configuration::Configuration,
49    ) -> Result<(), anyhow::Error> {
50        let request = self
51            .auth_email_password_reset_token_request
52            .map(|body| body.into_inner().into_inner());
53
54        auth_email_password_reset_token(configuration, request)
55            .await
56            .map_err(Into::into)
57    }
58}
59
60/// Serialize command-line arguments for [`auth_get_user`]
61#[cfg(feature = "clap")]
62#[derive(Debug, clap::Args)]
63pub struct AuthGetUserClapParams {}
64
65#[cfg(feature = "clap")]
66impl AuthGetUserClapParams {
67    pub async fn execute(
68        self,
69        configuration: &configuration::Configuration,
70    ) -> Result<crate::models::User, anyhow::Error> {
71        auth_get_user(configuration).await.map_err(Into::into)
72    }
73}
74
75/// Serialize command-line arguments for [`auth_reset_password`]
76#[cfg(feature = "clap")]
77#[derive(Debug, clap::Args)]
78pub struct AuthResetPasswordClapParams {
79    pub auth_reset_password_request:
80        crate::clap_utils::JsonMaybeStdin<crate::models::AuthResetPasswordRequest>,
81}
82
83#[cfg(feature = "clap")]
84impl AuthResetPasswordClapParams {
85    pub async fn execute(
86        self,
87        configuration: &configuration::Configuration,
88    ) -> Result<(), anyhow::Error> {
89        let request = self.auth_reset_password_request.into_inner().into_inner();
90
91        auth_reset_password(configuration, request)
92            .await
93            .map_err(Into::into)
94    }
95}
96
97/// Serialize command-line arguments for [`auth_reset_password_with_token`]
98#[cfg(feature = "clap")]
99#[derive(Debug, clap::Args)]
100pub struct AuthResetPasswordWithTokenClapParams {
101    pub auth_reset_password_with_token_request:
102        crate::clap_utils::JsonMaybeStdin<crate::models::AuthResetPasswordWithTokenRequest>,
103}
104
105#[cfg(feature = "clap")]
106impl AuthResetPasswordWithTokenClapParams {
107    pub async fn execute(
108        self,
109        configuration: &configuration::Configuration,
110    ) -> Result<(), anyhow::Error> {
111        let request = self
112            .auth_reset_password_with_token_request
113            .into_inner()
114            .into_inner();
115
116        auth_reset_password_with_token(configuration, request)
117            .await
118            .map_err(Into::into)
119    }
120}
121
122/// struct for typed errors of method [`auth_email_password_reset_token`]
123#[derive(Debug, Clone, Serialize, Deserialize)]
124#[serde(untagged)]
125pub enum AuthEmailPasswordResetTokenError {
126    Status422(crate::models::Error),
127    UnknownValue(serde_json::Value),
128}
129
130/// struct for typed errors of method [`auth_get_user`]
131#[derive(Debug, Clone, Serialize, Deserialize)]
132#[serde(untagged)]
133pub enum AuthGetUserError {
134    Status401(crate::models::Error),
135    Status404(crate::models::Error),
136    UnknownValue(serde_json::Value),
137}
138
139/// struct for typed errors of method [`auth_reset_password`]
140#[derive(Debug, Clone, Serialize, Deserialize)]
141#[serde(untagged)]
142pub enum AuthResetPasswordError {
143    Status401(crate::models::Error),
144    Status422(crate::models::Error),
145    UnknownValue(serde_json::Value),
146}
147
148/// struct for typed errors of method [`auth_reset_password_with_token`]
149#[derive(Debug, Clone, Serialize, Deserialize)]
150#[serde(untagged)]
151pub enum AuthResetPasswordWithTokenError {
152    Status404(crate::models::Error),
153    Status422(crate::models::Error),
154    UnknownValue(serde_json::Value),
155}
156
157async fn auth_email_password_reset_token_inner(
158    configuration: &configuration::Configuration,
159    backoff: &mut ExponentialBackoff,
160    auth_email_password_reset_token_request: Option<
161        crate::models::AuthEmailPasswordResetTokenRequest,
162    >,
163) -> Result<(), Error<AuthEmailPasswordResetTokenError>> {
164    let local_var_configuration = configuration;
165
166    let local_var_client = &local_var_configuration.client;
167
168    let local_var_uri_str = format!(
169        "{}/v1/auth:emailPasswordResetToken",
170        local_var_configuration.qcs_config.api_url()
171    );
172    let mut local_var_req_builder =
173        local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str());
174
175    #[cfg(feature = "tracing")]
176    {
177        // Ignore parsing errors if the URL is invalid for some reason.
178        // If it is invalid, it will turn up as an error later when actually making the request.
179        let local_var_do_tracing = local_var_uri_str
180            .parse::<::url::Url>()
181            .ok()
182            .is_none_or(|url| {
183                configuration
184                    .qcs_config
185                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
186            });
187
188        if local_var_do_tracing {
189            ::tracing::debug!(
190                url=%local_var_uri_str,
191                method="POST",
192                "making auth_email_password_reset_token request",
193            );
194        }
195    }
196
197    // Use the QCS Bearer token if a client OAuthSession is present,
198    // but do not require one when the security schema says it is optional.
199    {
200        use qcs_api_client_common::configuration::TokenError;
201
202        #[allow(
203            clippy::nonminimal_bool,
204            clippy::eq_op,
205            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
206        )]
207        let is_jwt_bearer_optional: bool = false;
208
209        let token = local_var_configuration
210            .qcs_config
211            .get_bearer_access_token()
212            .await;
213
214        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
215            // the client is configured without any OAuthSession, but this call does not require one.
216            #[cfg(feature = "tracing")]
217            tracing::debug!(
218                "No client credentials found, but this call does not require authentication."
219            );
220        } else {
221            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
222        }
223    }
224
225    local_var_req_builder = local_var_req_builder.json(&auth_email_password_reset_token_request);
226
227    let local_var_req = local_var_req_builder.build()?;
228    let local_var_resp = local_var_client.execute(local_var_req).await?;
229
230    let local_var_status = local_var_resp.status();
231
232    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
233        Ok(())
234    } else {
235        let local_var_retry_delay =
236            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
237        let local_var_content = local_var_resp.text().await?;
238        let local_var_entity: Option<AuthEmailPasswordResetTokenError> =
239            serde_json::from_str(&local_var_content).ok();
240        let local_var_error = ResponseContent {
241            status: local_var_status,
242            content: local_var_content,
243            entity: local_var_entity,
244            retry_delay: local_var_retry_delay,
245        };
246        Err(Error::ResponseError(local_var_error))
247    }
248}
249
250/// Send a password reset link to the provided email address, if that email matches a registered user.
251pub async fn auth_email_password_reset_token(
252    configuration: &configuration::Configuration,
253    auth_email_password_reset_token_request: Option<
254        crate::models::AuthEmailPasswordResetTokenRequest,
255    >,
256) -> Result<(), Error<AuthEmailPasswordResetTokenError>> {
257    let mut backoff = configuration.backoff.clone();
258    let mut refreshed_credentials = false;
259    let method = reqwest::Method::POST;
260    loop {
261        let result = auth_email_password_reset_token_inner(
262            configuration,
263            &mut backoff,
264            auth_email_password_reset_token_request.clone(),
265        )
266        .await;
267
268        match result {
269            Ok(result) => return Ok(result),
270            Err(Error::ResponseError(response)) => {
271                if !refreshed_credentials
272                    && matches!(
273                        response.status,
274                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
275                    )
276                {
277                    configuration.qcs_config.refresh().await?;
278                    refreshed_credentials = true;
279                    continue;
280                } else if let Some(duration) = response.retry_delay {
281                    tokio::time::sleep(duration).await;
282                    continue;
283                }
284
285                return Err(Error::ResponseError(response));
286            }
287            Err(Error::Reqwest(error)) => {
288                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
289                    tokio::time::sleep(duration).await;
290                    continue;
291                }
292
293                return Err(Error::Reqwest(error));
294            }
295            Err(Error::Io(error)) => {
296                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
297                    tokio::time::sleep(duration).await;
298                    continue;
299                }
300
301                return Err(Error::Io(error));
302            }
303            Err(error) => return Err(error),
304        }
305    }
306}
307async fn auth_get_user_inner(
308    configuration: &configuration::Configuration,
309    backoff: &mut ExponentialBackoff,
310) -> Result<crate::models::User, Error<AuthGetUserError>> {
311    let local_var_configuration = configuration;
312
313    let local_var_client = &local_var_configuration.client;
314
315    let local_var_uri_str = format!(
316        "{}/v1/auth:getUser",
317        local_var_configuration.qcs_config.api_url()
318    );
319    let mut local_var_req_builder =
320        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
321
322    #[cfg(feature = "tracing")]
323    {
324        // Ignore parsing errors if the URL is invalid for some reason.
325        // If it is invalid, it will turn up as an error later when actually making the request.
326        let local_var_do_tracing = local_var_uri_str
327            .parse::<::url::Url>()
328            .ok()
329            .is_none_or(|url| {
330                configuration
331                    .qcs_config
332                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
333            });
334
335        if local_var_do_tracing {
336            ::tracing::debug!(
337                url=%local_var_uri_str,
338                method="GET",
339                "making auth_get_user request",
340            );
341        }
342    }
343
344    // Use the QCS Bearer token if a client OAuthSession is present,
345    // but do not require one when the security schema says it is optional.
346    {
347        use qcs_api_client_common::configuration::TokenError;
348
349        #[allow(
350            clippy::nonminimal_bool,
351            clippy::eq_op,
352            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
353        )]
354        let is_jwt_bearer_optional: bool = false || "JWTBearer" == "JWTBearerOptional";
355
356        let token = local_var_configuration
357            .qcs_config
358            .get_bearer_access_token()
359            .await;
360
361        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
362            // the client is configured without any OAuthSession, but this call does not require one.
363            #[cfg(feature = "tracing")]
364            tracing::debug!(
365                "No client credentials found, but this call does not require authentication."
366            );
367        } else {
368            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
369        }
370    }
371
372    let local_var_req = local_var_req_builder.build()?;
373    let local_var_resp = local_var_client.execute(local_var_req).await?;
374
375    let local_var_status = local_var_resp.status();
376
377    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
378        let local_var_content = local_var_resp.text().await?;
379        serde_json::from_str(&local_var_content).map_err(Error::from)
380    } else {
381        let local_var_retry_delay =
382            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
383        let local_var_content = local_var_resp.text().await?;
384        let local_var_entity: Option<AuthGetUserError> =
385            serde_json::from_str(&local_var_content).ok();
386        let local_var_error = ResponseContent {
387            status: local_var_status,
388            content: local_var_content,
389            entity: local_var_entity,
390            retry_delay: local_var_retry_delay,
391        };
392        Err(Error::ResponseError(local_var_error))
393    }
394}
395
396/// Retrieve the profile of the authenticated user.
397pub async fn auth_get_user(
398    configuration: &configuration::Configuration,
399) -> Result<crate::models::User, Error<AuthGetUserError>> {
400    let mut backoff = configuration.backoff.clone();
401    let mut refreshed_credentials = false;
402    let method = reqwest::Method::GET;
403    loop {
404        let result = auth_get_user_inner(configuration, &mut backoff).await;
405
406        match result {
407            Ok(result) => return Ok(result),
408            Err(Error::ResponseError(response)) => {
409                if !refreshed_credentials
410                    && matches!(
411                        response.status,
412                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
413                    )
414                {
415                    configuration.qcs_config.refresh().await?;
416                    refreshed_credentials = true;
417                    continue;
418                } else if let Some(duration) = response.retry_delay {
419                    tokio::time::sleep(duration).await;
420                    continue;
421                }
422
423                return Err(Error::ResponseError(response));
424            }
425            Err(Error::Reqwest(error)) => {
426                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
427                    tokio::time::sleep(duration).await;
428                    continue;
429                }
430
431                return Err(Error::Reqwest(error));
432            }
433            Err(Error::Io(error)) => {
434                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
435                    tokio::time::sleep(duration).await;
436                    continue;
437                }
438
439                return Err(Error::Io(error));
440            }
441            Err(error) => return Err(error),
442        }
443    }
444}
445async fn auth_reset_password_inner(
446    configuration: &configuration::Configuration,
447    backoff: &mut ExponentialBackoff,
448    auth_reset_password_request: crate::models::AuthResetPasswordRequest,
449) -> Result<(), Error<AuthResetPasswordError>> {
450    let local_var_configuration = configuration;
451
452    let local_var_client = &local_var_configuration.client;
453
454    let local_var_uri_str = format!(
455        "{}/v1/auth:resetPassword",
456        local_var_configuration.qcs_config.api_url()
457    );
458    let mut local_var_req_builder =
459        local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str());
460
461    #[cfg(feature = "tracing")]
462    {
463        // Ignore parsing errors if the URL is invalid for some reason.
464        // If it is invalid, it will turn up as an error later when actually making the request.
465        let local_var_do_tracing = local_var_uri_str
466            .parse::<::url::Url>()
467            .ok()
468            .is_none_or(|url| {
469                configuration
470                    .qcs_config
471                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
472            });
473
474        if local_var_do_tracing {
475            ::tracing::debug!(
476                url=%local_var_uri_str,
477                method="POST",
478                "making auth_reset_password request",
479            );
480        }
481    }
482
483    // Use the QCS Bearer token if a client OAuthSession is present,
484    // but do not require one when the security schema says it is optional.
485    {
486        use qcs_api_client_common::configuration::TokenError;
487
488        #[allow(
489            clippy::nonminimal_bool,
490            clippy::eq_op,
491            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
492        )]
493        let is_jwt_bearer_optional: bool = false || "JWTBearer" == "JWTBearerOptional";
494
495        let token = local_var_configuration
496            .qcs_config
497            .get_bearer_access_token()
498            .await;
499
500        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
501            // the client is configured without any OAuthSession, but this call does not require one.
502            #[cfg(feature = "tracing")]
503            tracing::debug!(
504                "No client credentials found, but this call does not require authentication."
505            );
506        } else {
507            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
508        }
509    }
510
511    local_var_req_builder = local_var_req_builder.json(&auth_reset_password_request);
512
513    let local_var_req = local_var_req_builder.build()?;
514    let local_var_resp = local_var_client.execute(local_var_req).await?;
515
516    let local_var_status = local_var_resp.status();
517
518    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
519        Ok(())
520    } else {
521        let local_var_retry_delay =
522            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
523        let local_var_content = local_var_resp.text().await?;
524        let local_var_entity: Option<AuthResetPasswordError> =
525            serde_json::from_str(&local_var_content).ok();
526        let local_var_error = ResponseContent {
527            status: local_var_status,
528            content: local_var_content,
529            entity: local_var_entity,
530            retry_delay: local_var_retry_delay,
531        };
532        Err(Error::ResponseError(local_var_error))
533    }
534}
535
536/// Reset the password using the user's existing password. Note, this is an authenticated route.
537pub async fn auth_reset_password(
538    configuration: &configuration::Configuration,
539    auth_reset_password_request: crate::models::AuthResetPasswordRequest,
540) -> Result<(), Error<AuthResetPasswordError>> {
541    let mut backoff = configuration.backoff.clone();
542    let mut refreshed_credentials = false;
543    let method = reqwest::Method::POST;
544    loop {
545        let result = auth_reset_password_inner(
546            configuration,
547            &mut backoff,
548            auth_reset_password_request.clone(),
549        )
550        .await;
551
552        match result {
553            Ok(result) => return Ok(result),
554            Err(Error::ResponseError(response)) => {
555                if !refreshed_credentials
556                    && matches!(
557                        response.status,
558                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
559                    )
560                {
561                    configuration.qcs_config.refresh().await?;
562                    refreshed_credentials = true;
563                    continue;
564                } else if let Some(duration) = response.retry_delay {
565                    tokio::time::sleep(duration).await;
566                    continue;
567                }
568
569                return Err(Error::ResponseError(response));
570            }
571            Err(Error::Reqwest(error)) => {
572                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
573                    tokio::time::sleep(duration).await;
574                    continue;
575                }
576
577                return Err(Error::Reqwest(error));
578            }
579            Err(Error::Io(error)) => {
580                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
581                    tokio::time::sleep(duration).await;
582                    continue;
583                }
584
585                return Err(Error::Io(error));
586            }
587            Err(error) => return Err(error),
588        }
589    }
590}
591async fn auth_reset_password_with_token_inner(
592    configuration: &configuration::Configuration,
593    backoff: &mut ExponentialBackoff,
594    auth_reset_password_with_token_request: crate::models::AuthResetPasswordWithTokenRequest,
595) -> Result<(), Error<AuthResetPasswordWithTokenError>> {
596    let local_var_configuration = configuration;
597
598    let local_var_client = &local_var_configuration.client;
599
600    let local_var_uri_str = format!(
601        "{}/v1/auth:resetPasswordWithToken",
602        local_var_configuration.qcs_config.api_url()
603    );
604    let mut local_var_req_builder =
605        local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str());
606
607    #[cfg(feature = "tracing")]
608    {
609        // Ignore parsing errors if the URL is invalid for some reason.
610        // If it is invalid, it will turn up as an error later when actually making the request.
611        let local_var_do_tracing = local_var_uri_str
612            .parse::<::url::Url>()
613            .ok()
614            .is_none_or(|url| {
615                configuration
616                    .qcs_config
617                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
618            });
619
620        if local_var_do_tracing {
621            ::tracing::debug!(
622                url=%local_var_uri_str,
623                method="POST",
624                "making auth_reset_password_with_token request",
625            );
626        }
627    }
628
629    // Use the QCS Bearer token if a client OAuthSession is present,
630    // but do not require one when the security schema says it is optional.
631    {
632        use qcs_api_client_common::configuration::TokenError;
633
634        #[allow(
635            clippy::nonminimal_bool,
636            clippy::eq_op,
637            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
638        )]
639        let is_jwt_bearer_optional: bool = false;
640
641        let token = local_var_configuration
642            .qcs_config
643            .get_bearer_access_token()
644            .await;
645
646        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
647            // the client is configured without any OAuthSession, but this call does not require one.
648            #[cfg(feature = "tracing")]
649            tracing::debug!(
650                "No client credentials found, but this call does not require authentication."
651            );
652        } else {
653            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
654        }
655    }
656
657    local_var_req_builder = local_var_req_builder.json(&auth_reset_password_with_token_request);
658
659    let local_var_req = local_var_req_builder.build()?;
660    let local_var_resp = local_var_client.execute(local_var_req).await?;
661
662    let local_var_status = local_var_resp.status();
663
664    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
665        Ok(())
666    } else {
667        let local_var_retry_delay =
668            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
669        let local_var_content = local_var_resp.text().await?;
670        let local_var_entity: Option<AuthResetPasswordWithTokenError> =
671            serde_json::from_str(&local_var_content).ok();
672        let local_var_error = ResponseContent {
673            status: local_var_status,
674            content: local_var_content,
675            entity: local_var_entity,
676            retry_delay: local_var_retry_delay,
677        };
678        Err(Error::ResponseError(local_var_error))
679    }
680}
681
682/// Complete the forgot password flow, resetting the new password in exchange for an emailed token.
683pub async fn auth_reset_password_with_token(
684    configuration: &configuration::Configuration,
685    auth_reset_password_with_token_request: crate::models::AuthResetPasswordWithTokenRequest,
686) -> Result<(), Error<AuthResetPasswordWithTokenError>> {
687    let mut backoff = configuration.backoff.clone();
688    let mut refreshed_credentials = false;
689    let method = reqwest::Method::POST;
690    loop {
691        let result = auth_reset_password_with_token_inner(
692            configuration,
693            &mut backoff,
694            auth_reset_password_with_token_request.clone(),
695        )
696        .await;
697
698        match result {
699            Ok(result) => return Ok(result),
700            Err(Error::ResponseError(response)) => {
701                if !refreshed_credentials
702                    && matches!(
703                        response.status,
704                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
705                    )
706                {
707                    configuration.qcs_config.refresh().await?;
708                    refreshed_credentials = true;
709                    continue;
710                } else if let Some(duration) = response.retry_delay {
711                    tokio::time::sleep(duration).await;
712                    continue;
713                }
714
715                return Err(Error::ResponseError(response));
716            }
717            Err(Error::Reqwest(error)) => {
718                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
719                    tokio::time::sleep(duration).await;
720                    continue;
721                }
722
723                return Err(Error::Reqwest(error));
724            }
725            Err(Error::Io(error)) => {
726                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
727                    tokio::time::sleep(duration).await;
728                    continue;
729                }
730
731                return Err(Error::Io(error));
732            }
733            Err(error) => return Err(error),
734        }
735    }
736}