File size: 3,543 Bytes
e5034c3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use std::collections::HashMap;

use derive_more::{Deref, From};
use url::Url;

use super::{
    ApiKey, AuthorizationCode, DeviceCode, OAuthConfig, PkceVerifier, State, URLParam,
    URLParamSpec, URLParamValue, UserCode,
};

#[derive(Debug, Clone, PartialEq, Deref, From)]
pub struct URLParameters(HashMap<URLParam, URLParamValue>);

// API Key Flow

/// Request parameters for API key authentication
#[derive(Debug, Clone)]
pub struct ApiKeyRequest {
    pub required_params: Vec<URLParamSpec>,
    pub existing_params: Option<URLParameters>,
    pub api_key: Option<ApiKey>,
}

/// Response containing API key and URL parameters
#[derive(Debug, Clone)]
pub struct ApiKeyResponse {
    pub api_key: ApiKey,
    pub url_params: HashMap<URLParam, URLParamValue>,
}

// Authorization Code Flow

/// Authorization code OAuth authentication flow
#[derive(Debug, Clone)]
pub struct CodeAuthFlow;

/// Request parameters for authorization code flow
#[derive(Debug, Clone)]
pub struct CodeRequest {
    pub authorization_url: Url,
    pub state: State,
    pub pkce_verifier: Option<PkceVerifier>,
    pub oauth_config: OAuthConfig,
}

/// Response containing authorization code
#[derive(Debug, Clone)]
pub struct CodeResponse {
    pub code: AuthorizationCode,
}

// Device Code Flow

/// Device code OAuth authentication flow
#[derive(Debug, Clone)]
pub struct DeviceCodeAuthFlow;

/// Request parameters for device code flow
#[derive(Debug, Clone)]
pub struct DeviceCodeRequest {
    pub user_code: UserCode,
    pub device_code: DeviceCode,
    pub verification_uri: Url,
    pub verification_uri_complete: Option<Url>,
    pub expires_in: u64,
    pub interval: u64,
    pub oauth_config: OAuthConfig,
}

/// Response for device code flow
#[derive(Debug, Clone)]
pub struct DeviceCodeResponse;

/// Generic container that pairs a request with its corresponding response
#[derive(Debug, Clone)]
pub struct AuthContext<Request, Response> {
    pub request: Request,
    pub response: Response,
}

/// Represents different types of authentication requests
#[derive(Debug, Clone)]
pub enum AuthContextRequest {
    ApiKey(ApiKeyRequest),
    DeviceCode(DeviceCodeRequest),
    Code(CodeRequest),
}

/// Represents completed authentication flows with their request/response pairs
#[derive(Debug, Clone)]
pub enum AuthContextResponse {
    ApiKey(AuthContext<ApiKeyRequest, ApiKeyResponse>),
    DeviceCode(AuthContext<DeviceCodeRequest, DeviceCodeResponse>),
    Code(AuthContext<CodeRequest, CodeResponse>),
}

impl AuthContextResponse {
    /// Creates an API key authentication context
    pub fn api_key(
        request: ApiKeyRequest,
        api_key: impl ToString,
        url_params: HashMap<String, String>,
    ) -> Self {
        Self::ApiKey(AuthContext {
            request,
            response: ApiKeyResponse {
                api_key: api_key.to_string().into(),
                url_params: url_params
                    .into_iter()
                    .map(|(k, v)| (k.into(), v.into()))
                    .collect(),
            },
        })
    }

    /// Creates a device code authentication context
    pub fn device_code(request: DeviceCodeRequest) -> Self {
        Self::DeviceCode(AuthContext { request, response: DeviceCodeResponse })
    }

    /// Creates an authorization code authentication context
    pub fn code(request: CodeRequest, code: impl ToString) -> Self {
        Self::Code(AuthContext {
            request,
            response: CodeResponse { code: code.to_string().into() },
        })
    }
}