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
|
use anyhow::Result;
use async_session::{Session, SessionStore};
use async_trait::async_trait;
use bon::Builder;
use oauth2::{AuthUrl, ClientId, ClientSecret, EndpointNotSet, EndpointSet, RedirectUrl, TokenUrl};
use secrecy::{ExposeSecret, SecretString};
use time::OffsetDateTime;
use tracing::{instrument, trace};
use crate::server::{driver::Services, entity};
pub(super) static COOKIE_NAME: &str = "SESSION";
pub(super) static CSRF_TOKEN: &str = "csrf_token";
#[derive(Builder, Debug)]
pub struct ClientOptions {
client_id: String,
client_secret: SecretString,
token_url: String,
auth_url: String,
redirect_url: String,
}
pub type OauthClient = oauth2::basic::BasicClient<
EndpointSet,
EndpointNotSet,
EndpointNotSet,
EndpointNotSet,
EndpointSet,
>;
pub fn oauth_client(opts: &ClientOptions) -> anyhow::Result<OauthClient> {
dbg!(&opts);
let redirect_url = RedirectUrl::new(opts.redirect_url.to_owned())?;
let client_id = ClientId::new(opts.client_id.to_owned());
let auth_url = AuthUrl::new(opts.auth_url.to_owned())?;
let token_url = TokenUrl::new(opts.token_url.to_owned())?;
let client_secret = ClientSecret::new(opts.client_secret.expose_secret().to_string());
Ok(oauth2::basic::BasicClient::new(client_id)
.set_client_secret(client_secret)
.set_auth_uri(auth_url)
.set_token_uri(token_url)
.set_redirect_uri(redirect_url))
}
#[async_trait]
impl SessionStore for Services {
#[instrument(skip(self))]
async fn load_session(&self, cookie_value: String) -> Result<Option<Session>> {
let id = Session::id_from_cookie_value(&cookie_value)?;
let result = sqlx::query_as!(
entity::auth::Session,
"select
*
from
session
where
id = $1
and
(
expires
is null
or
expires > $2
)
",
id,
OffsetDateTime::now_utc()
)
.fetch_optional(&self.database)
.await?
.map(|value| serde_json::from_str(&value.session));
Ok(result.transpose()?)
}
#[instrument(skip(self, session), fields(id = session.id()))]
async fn store_session(&self, session: Session) -> Result<Option<String>> {
let id = session.id();
trace!("storing session");
let mut connection = self.database.acquire().await?;
Ok(session.into_cookie_value())
}
async fn destroy_session(&self, session: Session) -> Result<()> {
todo!()
}
async fn clear_store(&self) -> Result<()> {
todo!()
}
}
|