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#[cfg(feature = "clap")]
36#[allow(unused, reason = "not used in all templates, but required in some")]
37use ::{miette::IntoDiagnostic as _, qcs_api_client_common::clap_utils::JsonMaybeStdin};
38
39/// Serialize command-line arguments for [`auth_email_password_reset_token`]
40#[cfg(feature = "clap")]
41#[derive(Debug, clap::Args)]
42pub struct AuthEmailPasswordResetTokenClapParams {
43    pub auth_email_password_reset_token_request:
44        Option<JsonMaybeStdin<crate::models::AuthEmailPasswordResetTokenRequest>>,
45}
46
47#[cfg(feature = "clap")]
48impl AuthEmailPasswordResetTokenClapParams {
49    pub async fn execute(
50        self,
51        configuration: &configuration::Configuration,
52    ) -> Result<(), miette::Error> {
53        let request = self
54            .auth_email_password_reset_token_request
55            .map(|body| body.into_inner().into_inner());
56
57        auth_email_password_reset_token(configuration, request)
58            .await
59            .into_diagnostic()
60    }
61}
62
63/// Serialize command-line arguments for [`auth_get_user`]
64#[cfg(feature = "clap")]
65#[derive(Debug, clap::Args)]
66pub struct AuthGetUserClapParams {}
67
68#[cfg(feature = "clap")]
69impl AuthGetUserClapParams {
70    pub async fn execute(
71        self,
72        configuration: &configuration::Configuration,
73    ) -> Result<crate::models::User, miette::Error> {
74        auth_get_user(configuration).await.into_diagnostic()
75    }
76}
77
78/// Serialize command-line arguments for [`auth_reset_password`]
79#[cfg(feature = "clap")]
80#[derive(Debug, clap::Args)]
81pub struct AuthResetPasswordClapParams {
82    pub auth_reset_password_request: JsonMaybeStdin<crate::models::AuthResetPasswordRequest>,
83}
84
85#[cfg(feature = "clap")]
86impl AuthResetPasswordClapParams {
87    pub async fn execute(
88        self,
89        configuration: &configuration::Configuration,
90    ) -> Result<(), miette::Error> {
91        let request = self.auth_reset_password_request.into_inner().into_inner();
92
93        auth_reset_password(configuration, request)
94            .await
95            .into_diagnostic()
96    }
97}
98
99/// Serialize command-line arguments for [`auth_reset_password_with_token`]
100#[cfg(feature = "clap")]
101#[derive(Debug, clap::Args)]
102pub struct AuthResetPasswordWithTokenClapParams {
103    pub auth_reset_password_with_token_request:
104        JsonMaybeStdin<crate::models::AuthResetPasswordWithTokenRequest>,
105}
106
107#[cfg(feature = "clap")]
108impl AuthResetPasswordWithTokenClapParams {
109    pub async fn execute(
110        self,
111        configuration: &configuration::Configuration,
112    ) -> Result<(), miette::Error> {
113        let request = self
114            .auth_reset_password_with_token_request
115            .into_inner()
116            .into_inner();
117
118        auth_reset_password_with_token(configuration, request)
119            .await
120            .into_diagnostic()
121    }
122}
123
124/// struct for typed errors of method [`auth_email_password_reset_token`]
125#[derive(Debug, Clone, Serialize, Deserialize)]
126#[serde(untagged)]
127pub enum AuthEmailPasswordResetTokenError {
128    Status422(crate::models::Error),
129    UnknownValue(serde_json::Value),
130}
131
132/// struct for typed errors of method [`auth_get_user`]
133#[derive(Debug, Clone, Serialize, Deserialize)]
134#[serde(untagged)]
135pub enum AuthGetUserError {
136    Status401(crate::models::Error),
137    Status404(crate::models::Error),
138    UnknownValue(serde_json::Value),
139}
140
141/// struct for typed errors of method [`auth_reset_password`]
142#[derive(Debug, Clone, Serialize, Deserialize)]
143#[serde(untagged)]
144pub enum AuthResetPasswordError {
145    Status401(crate::models::Error),
146    Status422(crate::models::Error),
147    UnknownValue(serde_json::Value),
148}
149
150/// struct for typed errors of method [`auth_reset_password_with_token`]
151#[derive(Debug, Clone, Serialize, Deserialize)]
152#[serde(untagged)]
153pub enum AuthResetPasswordWithTokenError {
154    Status404(crate::models::Error),
155    Status422(crate::models::Error),
156    UnknownValue(serde_json::Value),
157}
158
159async fn auth_email_password_reset_token_inner(
160    configuration: &configuration::Configuration,
161    backoff: &mut ExponentialBackoff,
162    auth_email_password_reset_token_request: Option<
163        crate::models::AuthEmailPasswordResetTokenRequest,
164    >,
165) -> Result<(), Error<AuthEmailPasswordResetTokenError>> {
166    let local_var_configuration = configuration;
167
168    let local_var_client = &local_var_configuration.client;
169
170    let local_var_uri_str = format!(
171        "{}/v1/auth:emailPasswordResetToken",
172        local_var_configuration.qcs_config.api_url()
173    );
174    let mut local_var_req_builder =
175        local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str());
176
177    #[cfg(feature = "tracing")]
178    {
179        // Ignore parsing errors if the URL is invalid for some reason.
180        // If it is invalid, it will turn up as an error later when actually making the request.
181        let local_var_do_tracing = local_var_uri_str
182            .parse::<::url::Url>()
183            .ok()
184            .is_none_or(|url| {
185                configuration
186                    .qcs_config
187                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
188            });
189
190        if local_var_do_tracing {
191            ::tracing::debug!(
192                url=%local_var_uri_str,
193                method="POST",
194                "making auth_email_password_reset_token request",
195            );
196        }
197    }
198
199    // Use the QCS Bearer token if a client OAuthSession is present,
200    // but do not require one when the security schema says it is optional.
201    {
202        use qcs_api_client_common::configuration::TokenError;
203
204        #[allow(
205            clippy::nonminimal_bool,
206            clippy::eq_op,
207            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
208        )]
209        let is_jwt_bearer_optional: bool = false;
210
211        let token = local_var_configuration
212            .qcs_config
213            .get_bearer_access_token()
214            .await;
215
216        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
217            // the client is configured without any OAuthSession, but this call does not require one.
218            #[cfg(feature = "tracing")]
219            tracing::debug!(
220                "No client credentials found, but this call does not require authentication."
221            );
222        } else {
223            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
224        }
225    }
226
227    local_var_req_builder = local_var_req_builder.json(&auth_email_password_reset_token_request);
228
229    let local_var_req = local_var_req_builder.build()?;
230    let local_var_resp = local_var_client.execute(local_var_req).await?;
231
232    let local_var_status = local_var_resp.status();
233
234    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
235        Ok(())
236    } else {
237        let local_var_retry_delay =
238            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
239        let local_var_content = local_var_resp.text().await?;
240        let local_var_entity: Option<AuthEmailPasswordResetTokenError> =
241            serde_json::from_str(&local_var_content).ok();
242        let local_var_error = ResponseContent {
243            status: local_var_status,
244            content: local_var_content,
245            entity: local_var_entity,
246            retry_delay: local_var_retry_delay,
247        };
248        Err(Error::ResponseError(local_var_error))
249    }
250}
251
252/// Send a password reset link to the provided email address, if that email matches a registered user.
253pub async fn auth_email_password_reset_token(
254    configuration: &configuration::Configuration,
255    auth_email_password_reset_token_request: Option<
256        crate::models::AuthEmailPasswordResetTokenRequest,
257    >,
258) -> Result<(), Error<AuthEmailPasswordResetTokenError>> {
259    let mut backoff = configuration.backoff.clone();
260    let mut refreshed_credentials = false;
261    let method = reqwest::Method::POST;
262    loop {
263        let result = auth_email_password_reset_token_inner(
264            configuration,
265            &mut backoff,
266            auth_email_password_reset_token_request.clone(),
267        )
268        .await;
269
270        match result {
271            Ok(result) => return Ok(result),
272            Err(Error::ResponseError(response)) => {
273                if !refreshed_credentials
274                    && matches!(
275                        response.status,
276                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
277                    )
278                {
279                    configuration.qcs_config.refresh().await?;
280                    refreshed_credentials = true;
281                    continue;
282                } else if let Some(duration) = response.retry_delay {
283                    tokio::time::sleep(duration).await;
284                    continue;
285                }
286
287                return Err(Error::ResponseError(response));
288            }
289            Err(Error::Reqwest(error)) => {
290                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
291                    tokio::time::sleep(duration).await;
292                    continue;
293                }
294
295                return Err(Error::Reqwest(error));
296            }
297            Err(Error::Io(error)) => {
298                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
299                    tokio::time::sleep(duration).await;
300                    continue;
301                }
302
303                return Err(Error::Io(error));
304            }
305            Err(error) => return Err(error),
306        }
307    }
308}
309async fn auth_get_user_inner(
310    configuration: &configuration::Configuration,
311    backoff: &mut ExponentialBackoff,
312) -> Result<crate::models::User, Error<AuthGetUserError>> {
313    let local_var_configuration = configuration;
314
315    let local_var_client = &local_var_configuration.client;
316
317    let local_var_uri_str = format!(
318        "{}/v1/auth:getUser",
319        local_var_configuration.qcs_config.api_url()
320    );
321    let mut local_var_req_builder =
322        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
323
324    #[cfg(feature = "tracing")]
325    {
326        // Ignore parsing errors if the URL is invalid for some reason.
327        // If it is invalid, it will turn up as an error later when actually making the request.
328        let local_var_do_tracing = local_var_uri_str
329            .parse::<::url::Url>()
330            .ok()
331            .is_none_or(|url| {
332                configuration
333                    .qcs_config
334                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
335            });
336
337        if local_var_do_tracing {
338            ::tracing::debug!(
339                url=%local_var_uri_str,
340                method="GET",
341                "making auth_get_user request",
342            );
343        }
344    }
345
346    // Use the QCS Bearer token if a client OAuthSession is present,
347    // but do not require one when the security schema says it is optional.
348    {
349        use qcs_api_client_common::configuration::TokenError;
350
351        #[allow(
352            clippy::nonminimal_bool,
353            clippy::eq_op,
354            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
355        )]
356        let is_jwt_bearer_optional: bool = false || "JWTBearer" == "JWTBearerOptional";
357
358        let token = local_var_configuration
359            .qcs_config
360            .get_bearer_access_token()
361            .await;
362
363        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
364            // the client is configured without any OAuthSession, but this call does not require one.
365            #[cfg(feature = "tracing")]
366            tracing::debug!(
367                "No client credentials found, but this call does not require authentication."
368            );
369        } else {
370            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
371        }
372    }
373
374    let local_var_req = local_var_req_builder.build()?;
375    let local_var_resp = local_var_client.execute(local_var_req).await?;
376
377    let local_var_status = local_var_resp.status();
378
379    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
380        let local_var_content = local_var_resp.text().await?;
381        serde_json::from_str(&local_var_content).map_err(Error::from)
382    } else {
383        let local_var_retry_delay =
384            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
385        let local_var_content = local_var_resp.text().await?;
386        let local_var_entity: Option<AuthGetUserError> =
387            serde_json::from_str(&local_var_content).ok();
388        let local_var_error = ResponseContent {
389            status: local_var_status,
390            content: local_var_content,
391            entity: local_var_entity,
392            retry_delay: local_var_retry_delay,
393        };
394        Err(Error::ResponseError(local_var_error))
395    }
396}
397
398/// Retrieve the profile of the authenticated user.
399pub async fn auth_get_user(
400    configuration: &configuration::Configuration,
401) -> Result<crate::models::User, Error<AuthGetUserError>> {
402    let mut backoff = configuration.backoff.clone();
403    let mut refreshed_credentials = false;
404    let method = reqwest::Method::GET;
405    loop {
406        let result = auth_get_user_inner(configuration, &mut backoff).await;
407
408        match result {
409            Ok(result) => return Ok(result),
410            Err(Error::ResponseError(response)) => {
411                if !refreshed_credentials
412                    && matches!(
413                        response.status,
414                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
415                    )
416                {
417                    configuration.qcs_config.refresh().await?;
418                    refreshed_credentials = true;
419                    continue;
420                } else if let Some(duration) = response.retry_delay {
421                    tokio::time::sleep(duration).await;
422                    continue;
423                }
424
425                return Err(Error::ResponseError(response));
426            }
427            Err(Error::Reqwest(error)) => {
428                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
429                    tokio::time::sleep(duration).await;
430                    continue;
431                }
432
433                return Err(Error::Reqwest(error));
434            }
435            Err(Error::Io(error)) => {
436                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
437                    tokio::time::sleep(duration).await;
438                    continue;
439                }
440
441                return Err(Error::Io(error));
442            }
443            Err(error) => return Err(error),
444        }
445    }
446}
447async fn auth_reset_password_inner(
448    configuration: &configuration::Configuration,
449    backoff: &mut ExponentialBackoff,
450    auth_reset_password_request: crate::models::AuthResetPasswordRequest,
451) -> Result<(), Error<AuthResetPasswordError>> {
452    let local_var_configuration = configuration;
453
454    let local_var_client = &local_var_configuration.client;
455
456    let local_var_uri_str = format!(
457        "{}/v1/auth:resetPassword",
458        local_var_configuration.qcs_config.api_url()
459    );
460    let mut local_var_req_builder =
461        local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str());
462
463    #[cfg(feature = "tracing")]
464    {
465        // Ignore parsing errors if the URL is invalid for some reason.
466        // If it is invalid, it will turn up as an error later when actually making the request.
467        let local_var_do_tracing = local_var_uri_str
468            .parse::<::url::Url>()
469            .ok()
470            .is_none_or(|url| {
471                configuration
472                    .qcs_config
473                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
474            });
475
476        if local_var_do_tracing {
477            ::tracing::debug!(
478                url=%local_var_uri_str,
479                method="POST",
480                "making auth_reset_password request",
481            );
482        }
483    }
484
485    // Use the QCS Bearer token if a client OAuthSession is present,
486    // but do not require one when the security schema says it is optional.
487    {
488        use qcs_api_client_common::configuration::TokenError;
489
490        #[allow(
491            clippy::nonminimal_bool,
492            clippy::eq_op,
493            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
494        )]
495        let is_jwt_bearer_optional: bool = false || "JWTBearer" == "JWTBearerOptional";
496
497        let token = local_var_configuration
498            .qcs_config
499            .get_bearer_access_token()
500            .await;
501
502        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
503            // the client is configured without any OAuthSession, but this call does not require one.
504            #[cfg(feature = "tracing")]
505            tracing::debug!(
506                "No client credentials found, but this call does not require authentication."
507            );
508        } else {
509            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
510        }
511    }
512
513    local_var_req_builder = local_var_req_builder.json(&auth_reset_password_request);
514
515    let local_var_req = local_var_req_builder.build()?;
516    let local_var_resp = local_var_client.execute(local_var_req).await?;
517
518    let local_var_status = local_var_resp.status();
519
520    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
521        Ok(())
522    } else {
523        let local_var_retry_delay =
524            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
525        let local_var_content = local_var_resp.text().await?;
526        let local_var_entity: Option<AuthResetPasswordError> =
527            serde_json::from_str(&local_var_content).ok();
528        let local_var_error = ResponseContent {
529            status: local_var_status,
530            content: local_var_content,
531            entity: local_var_entity,
532            retry_delay: local_var_retry_delay,
533        };
534        Err(Error::ResponseError(local_var_error))
535    }
536}
537
538/// Reset the password using the user's existing password. Note, this is an authenticated route.
539pub async fn auth_reset_password(
540    configuration: &configuration::Configuration,
541    auth_reset_password_request: crate::models::AuthResetPasswordRequest,
542) -> Result<(), Error<AuthResetPasswordError>> {
543    let mut backoff = configuration.backoff.clone();
544    let mut refreshed_credentials = false;
545    let method = reqwest::Method::POST;
546    loop {
547        let result = auth_reset_password_inner(
548            configuration,
549            &mut backoff,
550            auth_reset_password_request.clone(),
551        )
552        .await;
553
554        match result {
555            Ok(result) => return Ok(result),
556            Err(Error::ResponseError(response)) => {
557                if !refreshed_credentials
558                    && matches!(
559                        response.status,
560                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
561                    )
562                {
563                    configuration.qcs_config.refresh().await?;
564                    refreshed_credentials = true;
565                    continue;
566                } else if let Some(duration) = response.retry_delay {
567                    tokio::time::sleep(duration).await;
568                    continue;
569                }
570
571                return Err(Error::ResponseError(response));
572            }
573            Err(Error::Reqwest(error)) => {
574                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
575                    tokio::time::sleep(duration).await;
576                    continue;
577                }
578
579                return Err(Error::Reqwest(error));
580            }
581            Err(Error::Io(error)) => {
582                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
583                    tokio::time::sleep(duration).await;
584                    continue;
585                }
586
587                return Err(Error::Io(error));
588            }
589            Err(error) => return Err(error),
590        }
591    }
592}
593async fn auth_reset_password_with_token_inner(
594    configuration: &configuration::Configuration,
595    backoff: &mut ExponentialBackoff,
596    auth_reset_password_with_token_request: crate::models::AuthResetPasswordWithTokenRequest,
597) -> Result<(), Error<AuthResetPasswordWithTokenError>> {
598    let local_var_configuration = configuration;
599
600    let local_var_client = &local_var_configuration.client;
601
602    let local_var_uri_str = format!(
603        "{}/v1/auth:resetPasswordWithToken",
604        local_var_configuration.qcs_config.api_url()
605    );
606    let mut local_var_req_builder =
607        local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str());
608
609    #[cfg(feature = "tracing")]
610    {
611        // Ignore parsing errors if the URL is invalid for some reason.
612        // If it is invalid, it will turn up as an error later when actually making the request.
613        let local_var_do_tracing = local_var_uri_str
614            .parse::<::url::Url>()
615            .ok()
616            .is_none_or(|url| {
617                configuration
618                    .qcs_config
619                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
620            });
621
622        if local_var_do_tracing {
623            ::tracing::debug!(
624                url=%local_var_uri_str,
625                method="POST",
626                "making auth_reset_password_with_token request",
627            );
628        }
629    }
630
631    // Use the QCS Bearer token if a client OAuthSession is present,
632    // but do not require one when the security schema says it is optional.
633    {
634        use qcs_api_client_common::configuration::TokenError;
635
636        #[allow(
637            clippy::nonminimal_bool,
638            clippy::eq_op,
639            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
640        )]
641        let is_jwt_bearer_optional: bool = false;
642
643        let token = local_var_configuration
644            .qcs_config
645            .get_bearer_access_token()
646            .await;
647
648        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
649            // the client is configured without any OAuthSession, but this call does not require one.
650            #[cfg(feature = "tracing")]
651            tracing::debug!(
652                "No client credentials found, but this call does not require authentication."
653            );
654        } else {
655            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
656        }
657    }
658
659    local_var_req_builder = local_var_req_builder.json(&auth_reset_password_with_token_request);
660
661    let local_var_req = local_var_req_builder.build()?;
662    let local_var_resp = local_var_client.execute(local_var_req).await?;
663
664    let local_var_status = local_var_resp.status();
665
666    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
667        Ok(())
668    } else {
669        let local_var_retry_delay =
670            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
671        let local_var_content = local_var_resp.text().await?;
672        let local_var_entity: Option<AuthResetPasswordWithTokenError> =
673            serde_json::from_str(&local_var_content).ok();
674        let local_var_error = ResponseContent {
675            status: local_var_status,
676            content: local_var_content,
677            entity: local_var_entity,
678            retry_delay: local_var_retry_delay,
679        };
680        Err(Error::ResponseError(local_var_error))
681    }
682}
683
684/// Complete the forgot password flow, resetting the new password in exchange for an emailed token.
685pub async fn auth_reset_password_with_token(
686    configuration: &configuration::Configuration,
687    auth_reset_password_with_token_request: crate::models::AuthResetPasswordWithTokenRequest,
688) -> Result<(), Error<AuthResetPasswordWithTokenError>> {
689    let mut backoff = configuration.backoff.clone();
690    let mut refreshed_credentials = false;
691    let method = reqwest::Method::POST;
692    loop {
693        let result = auth_reset_password_with_token_inner(
694            configuration,
695            &mut backoff,
696            auth_reset_password_with_token_request.clone(),
697        )
698        .await;
699
700        match result {
701            Ok(result) => return Ok(result),
702            Err(Error::ResponseError(response)) => {
703                if !refreshed_credentials
704                    && matches!(
705                        response.status,
706                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
707                    )
708                {
709                    configuration.qcs_config.refresh().await?;
710                    refreshed_credentials = true;
711                    continue;
712                } else if let Some(duration) = response.retry_delay {
713                    tokio::time::sleep(duration).await;
714                    continue;
715                }
716
717                return Err(Error::ResponseError(response));
718            }
719            Err(Error::Reqwest(error)) => {
720                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
721                    tokio::time::sleep(duration).await;
722                    continue;
723                }
724
725                return Err(Error::Reqwest(error));
726            }
727            Err(Error::Io(error)) => {
728                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
729                    tokio::time::sleep(duration).await;
730                    continue;
731                }
732
733                return Err(Error::Io(error));
734            }
735            Err(error) => return Err(error),
736        }
737    }
738}