osauth/
basic.rs

1// Copyright 2020 Dmitry Tantsur <dtantsur@protonmail.com>
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//! HTTP basic authentication.
16
17use async_trait::async_trait;
18use reqwest::{Client, RequestBuilder, Url};
19use static_assertions::assert_impl_all;
20
21use super::{AuthType, EndpointFilters, Error, ErrorKind};
22
23/// Authentication type that uses HTTP basic authentication.
24///
25/// This type always uses a pre-defined endpoint:
26/// ```rust,no_run
27/// let auth = osauth::BasicAuth::new("https://cloud.local/baremetal",
28///                                   "username", "password")
29///     .expect("Invalid endpoint URL");
30/// let session = osauth::Session::new(auth);
31/// ```
32#[derive(Clone, Debug)]
33pub struct BasicAuth {
34    endpoint: Url,
35    username: String,
36    password: String,
37}
38
39assert_impl_all!(BasicAuth: Send, Sync);
40
41impl BasicAuth {
42    /// Create a new HTTP basic authentication method using a fixed endpoint.
43    ///
44    /// This endpoint will be returned in response to all `get_endpoint` calls
45    /// of the [AuthType](trait.AuthType.html) trait.
46    pub fn new<U, S1, S2>(endpoint: U, username: S1, password: S2) -> Result<BasicAuth, Error>
47    where
48        U: AsRef<str>,
49        S1: Into<String>,
50        S2: Into<String>,
51    {
52        let endpoint = Url::parse(endpoint.as_ref())
53            .map_err(|e| Error::new(ErrorKind::InvalidInput, e.to_string()))?;
54        Ok(BasicAuth {
55            endpoint,
56            username: username.into(),
57            password: password.into(),
58        })
59    }
60}
61
62#[async_trait]
63impl AuthType for BasicAuth {
64    /// Authenticate a request.
65    async fn authenticate(
66        &self,
67        _client: &Client,
68        request: RequestBuilder,
69    ) -> Result<RequestBuilder, Error> {
70        Ok(request.basic_auth(&self.username, Some(&self.password)))
71    }
72
73    /// Get a predefined endpoint for all service types
74    async fn get_endpoint(
75        &self,
76        _client: &Client,
77        _service_type: &str,
78        _filters: &EndpointFilters,
79    ) -> Result<Url, Error> {
80        Ok(self.endpoint.clone())
81    }
82
83    /// This call does nothing for `BasicAuth`.
84    async fn refresh(&self, _client: &Client) -> Result<(), Error> {
85        Ok(())
86    }
87}