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
mod app_access_token;
pub mod errors;
mod user_token;
pub use app_access_token::AppAccessToken;
pub use user_token::UserToken;
use crate::{scopes::Scope, validate_token};
use errors::*;
use oauth2::{AccessToken, ClientId};
use oauth2::{HttpRequest, HttpResponse};
use serde::Deserialize;
use std::future::Future;
#[async_trait::async_trait(?Send)]
pub trait TwitchToken {
fn client_id(&self) -> &ClientId;
fn token(&self) -> &AccessToken;
fn login(&self) -> Option<&str>;
async fn refresh_token<RE, C, F>(
&mut self,
http_client: C,
) -> Result<(), RefreshTokenError<RE>>
where
RE: std::error::Error + Send + Sync + 'static,
C: FnOnce(HttpRequest) -> F,
F: Future<Output = Result<HttpResponse, RE>>;
fn expires(&self) -> Option<std::time::Instant>;
fn scopes(&self) -> Option<&[Scope]>;
async fn validate_token<RE, C, F>(
&self,
http_client: C,
) -> Result<ValidatedToken, ValidationError<RE>>
where
RE: std::error::Error + Send + Sync + 'static,
C: FnOnce(HttpRequest) -> F,
F: Future<Output = Result<HttpResponse, RE>>,
{
validate_token(http_client, &self.token()).await
}
async fn revoke_token<RE, C, F>(self, http_client: C) -> Result<(), RevokeTokenError<RE>>
where
Self: Sized,
RE: std::error::Error + Send + Sync + 'static,
C: FnOnce(HttpRequest) -> F,
F: Future<Output = Result<HttpResponse, RE>>, {
crate::revoke_token(http_client, self.token(), self.client_id()).await
}
}
#[async_trait::async_trait(?Send)]
impl<T: TwitchToken> TwitchToken for Box<T> {
fn client_id(&self) -> &ClientId { (**self).client_id() }
fn token(&self) -> &AccessToken { (**self).token() }
fn login(&self) -> Option<&str> { (**self).login() }
async fn refresh_token<RE, C, F>(
&mut self,
http_client: C,
) -> Result<(), RefreshTokenError<RE>>
where
RE: std::error::Error + Send + Sync + 'static,
C: FnOnce(HttpRequest) -> F,
F: Future<Output = Result<HttpResponse, RE>>,
{
(**self).refresh_token(http_client).await
}
fn expires(&self) -> Option<std::time::Instant> { (**self).expires() }
fn scopes(&self) -> Option<&[Scope]> { (**self).scopes() }
}
#[derive(Debug, Clone, Deserialize)]
pub struct ValidatedToken {
pub client_id: ClientId,
pub login: Option<String>,
pub user_id: Option<String>,
pub scopes: Option<Vec<Scope>>,
}