feat: use current token for go to app instead of refresh token
This commit is contained in:
parent
680d6fe5b1
commit
e2d6d1df02
|
|
@ -8,6 +8,7 @@ use axum::{
|
||||||
};
|
};
|
||||||
use axum_extra::extract::CookieJar;
|
use axum_extra::extract::CookieJar;
|
||||||
use gotrue::grant::{Grant, RefreshTokenGrant};
|
use gotrue::grant::{Grant, RefreshTokenGrant};
|
||||||
|
use gotrue_entity::dto::GotrueTokenResponse;
|
||||||
use jwt::{Claims, Header};
|
use jwt::{Claims, Header};
|
||||||
use redis::{aio::ConnectionManager, AsyncCommands, FromRedisValue, ToRedisArgs};
|
use redis::{aio::ConnectionManager, AsyncCommands, FromRedisValue, ToRedisArgs};
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
|
|
@ -66,17 +67,12 @@ impl SessionStorage {
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct UserSession {
|
pub struct UserSession {
|
||||||
pub session_id: String,
|
pub session_id: String,
|
||||||
pub access_token: String,
|
pub token: GotrueTokenResponse,
|
||||||
pub refresh_token: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserSession {
|
impl UserSession {
|
||||||
pub fn new(session_id: String, access_token: String, refresh_token: String) -> Self {
|
pub fn new(session_id: String, token: GotrueTokenResponse) -> Self {
|
||||||
Self {
|
Self { session_id, token }
|
||||||
session_id,
|
|
||||||
access_token,
|
|
||||||
refresh_token,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,9 +99,9 @@ impl FromRequestParts<AppState> for UserSession {
|
||||||
.await
|
.await
|
||||||
.ok_or(SessionRejection::SessionNotFound)?;
|
.ok_or(SessionRejection::SessionNotFound)?;
|
||||||
|
|
||||||
if has_expired(session.access_token.as_str()) {
|
if has_expired(session.token.access_token.as_str()) {
|
||||||
// Get new pair of access token and refresh token
|
// Get new pair of access token and refresh token
|
||||||
let refresh_token = session.refresh_token;
|
let refresh_token = session.token.refresh_token;
|
||||||
let new_token = state
|
let new_token = state
|
||||||
.gotrue_client
|
.gotrue_client
|
||||||
.clone()
|
.clone()
|
||||||
|
|
@ -113,8 +109,8 @@ impl FromRequestParts<AppState> for UserSession {
|
||||||
.await
|
.await
|
||||||
.map_err(|err| SessionRejection::RefreshTokenError(err.to_string()))?;
|
.map_err(|err| SessionRejection::RefreshTokenError(err.to_string()))?;
|
||||||
|
|
||||||
session.access_token = new_token.access_token;
|
session.token.access_token = new_token.access_token;
|
||||||
session.refresh_token = new_token.refresh_token;
|
session.token.refresh_token = new_token.refresh_token;
|
||||||
|
|
||||||
// Update session in redis
|
// Update session in redis
|
||||||
let _ = state
|
let _ = state
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ use axum::Form;
|
||||||
use axum::{extract::State, routing::post, Router};
|
use axum::{extract::State, routing::post, Router};
|
||||||
use axum_extra::extract::cookie::Cookie;
|
use axum_extra::extract::cookie::Cookie;
|
||||||
use axum_extra::extract::CookieJar;
|
use axum_extra::extract::CookieJar;
|
||||||
use gotrue::grant::{Grant, RefreshTokenGrant};
|
|
||||||
use gotrue::params::{AdminDeleteUserParams, AdminUserParams, GenerateLinkParams, MagicLinkParams};
|
use gotrue::params::{AdminDeleteUserParams, AdminUserParams, GenerateLinkParams, MagicLinkParams};
|
||||||
use gotrue_entity::dto::{UpdateGotrueUserParams, User};
|
use gotrue_entity::dto::{UpdateGotrueUserParams, User};
|
||||||
|
|
||||||
|
|
@ -43,27 +42,14 @@ pub fn router() -> Router<AppState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// provide a link which when open in browser, opens the appflowy app
|
// provide a link which when open in browser, opens the appflowy app
|
||||||
pub async fn open_app_handler(
|
pub async fn open_app_handler(session: UserSession) -> Result<HeaderMap, WebApiError<'static>> {
|
||||||
State(state): State<AppState>,
|
|
||||||
session: UserSession,
|
|
||||||
) -> Result<HeaderMap, WebApiError<'static>> {
|
|
||||||
let access_token_resp = state
|
|
||||||
.gotrue_client
|
|
||||||
.token(&Grant::RefreshToken(RefreshTokenGrant {
|
|
||||||
refresh_token: session.refresh_token.to_owned(),
|
|
||||||
}))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
// appflowy-flutter:// -> scheme that opens the Appflowy app
|
|
||||||
// login-callback -> agreed upon convention that frontend recognizes
|
|
||||||
// The rest are params that are passed to the app needed for login
|
|
||||||
let app_sign_in_url = format!(
|
let app_sign_in_url = format!(
|
||||||
"appflowy-flutter://login-callback#access_token={}&expires_at={}&expires_in={}&refresh_token={}&token_type={}",
|
"appflowy-flutter://login-callback#access_token={}&expires_at={}&expires_in={}&refresh_token={}&token_type={}",
|
||||||
access_token_resp.access_token,
|
session.token.access_token,
|
||||||
access_token_resp.expires_at,
|
session.token.expires_at,
|
||||||
access_token_resp.expires_in,
|
session.token.expires_in,
|
||||||
access_token_resp.refresh_token,
|
session.token.refresh_token,
|
||||||
access_token_resp.token_type,
|
session.token.token_type,
|
||||||
);
|
);
|
||||||
Ok(htmx_redirect(&app_sign_in_url))
|
Ok(htmx_redirect(&app_sign_in_url))
|
||||||
}
|
}
|
||||||
|
|
@ -78,7 +64,7 @@ pub async fn invite_handler(
|
||||||
state
|
state
|
||||||
.gotrue_client
|
.gotrue_client
|
||||||
.magic_link(
|
.magic_link(
|
||||||
&session.access_token,
|
&session.token.access_token,
|
||||||
&MagicLinkParams {
|
&MagicLinkParams {
|
||||||
email: param.email,
|
email: param.email,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
@ -102,7 +88,7 @@ pub async fn change_password_handler(
|
||||||
let res = state
|
let res = state
|
||||||
.gotrue_client
|
.gotrue_client
|
||||||
.update_user(
|
.update_user(
|
||||||
&session.access_token,
|
&session.token.access_token,
|
||||||
&UpdateGotrueUserParams {
|
&UpdateGotrueUserParams {
|
||||||
password: Some(param.new_password),
|
password: Some(param.new_password),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
@ -147,7 +133,7 @@ pub async fn admin_update_user_handler(
|
||||||
let res = state
|
let res = state
|
||||||
.gotrue_client
|
.gotrue_client
|
||||||
.admin_update_user(
|
.admin_update_user(
|
||||||
&session.access_token,
|
&session.token.access_token,
|
||||||
&user_uuid,
|
&user_uuid,
|
||||||
&AdminUserParams {
|
&AdminUserParams {
|
||||||
password: Some(param.password.to_owned()),
|
password: Some(param.password.to_owned()),
|
||||||
|
|
@ -167,7 +153,7 @@ pub async fn post_user_generate_link_handler(
|
||||||
let res = state
|
let res = state
|
||||||
.gotrue_client
|
.gotrue_client
|
||||||
.admin_generate_link(
|
.admin_generate_link(
|
||||||
&session.access_token,
|
&session.token.access_token,
|
||||||
&GenerateLinkParams {
|
&GenerateLinkParams {
|
||||||
email,
|
email,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
@ -185,7 +171,7 @@ pub async fn admin_delete_user_handler(
|
||||||
state
|
state
|
||||||
.gotrue_client
|
.gotrue_client
|
||||||
.admin_delete_user(
|
.admin_delete_user(
|
||||||
&session.access_token,
|
&session.token.access_token,
|
||||||
&user_uuid,
|
&user_uuid,
|
||||||
&AdminDeleteUserParams {
|
&AdminDeleteUserParams {
|
||||||
should_soft_delete: true,
|
should_soft_delete: true,
|
||||||
|
|
@ -208,7 +194,7 @@ pub async fn admin_add_user_handler(
|
||||||
};
|
};
|
||||||
let user = state
|
let user = state
|
||||||
.gotrue_client
|
.gotrue_client
|
||||||
.admin_add_user(&session.access_token, &add_user_params)
|
.admin_add_user(&session.token.access_token, &add_user_params)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(user.into())
|
Ok(user.into())
|
||||||
}
|
}
|
||||||
|
|
@ -226,11 +212,7 @@ pub async fn login_refresh_handler(
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let new_session_id = uuid::Uuid::new_v4();
|
let new_session_id = uuid::Uuid::new_v4();
|
||||||
let new_session = session::UserSession::new(
|
let new_session = session::UserSession::new(new_session_id.to_string(), token);
|
||||||
new_session_id.to_string(),
|
|
||||||
token.access_token.to_string(),
|
|
||||||
token.refresh_token.to_owned(),
|
|
||||||
);
|
|
||||||
state.session_store.put_user_session(&new_session).await?;
|
state.session_store.put_user_session(&new_session).await?;
|
||||||
|
|
||||||
let mut cookie = Cookie::new("session_id", new_session_id.to_string());
|
let mut cookie = Cookie::new("session_id", new_session_id.to_string());
|
||||||
|
|
@ -257,11 +239,7 @@ pub async fn login_handler(
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let new_session_id = uuid::Uuid::new_v4();
|
let new_session_id = uuid::Uuid::new_v4();
|
||||||
let new_session = session::UserSession::new(
|
let new_session = session::UserSession::new(new_session_id.to_string(), token);
|
||||||
new_session_id.to_string(),
|
|
||||||
token.access_token.to_string(),
|
|
||||||
token.refresh_token.to_owned(),
|
|
||||||
);
|
|
||||||
state.session_store.put_user_session(&new_session).await?;
|
state.session_store.put_user_session(&new_session).await?;
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,10 @@ pub async fn user_user_handler(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
session: UserSession,
|
session: UserSession,
|
||||||
) -> Result<Html<String>, WebAppError> {
|
) -> Result<Html<String>, WebAppError> {
|
||||||
let user = state.gotrue_client.user_info(&session.access_token).await?;
|
let user = state
|
||||||
|
.gotrue_client
|
||||||
|
.user_info(&session.token.access_token)
|
||||||
|
.await?;
|
||||||
render_template(templates::UserDetails { user: &user })
|
render_template(templates::UserDetails { user: &user })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,7 +76,10 @@ pub async fn home_handler(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
session: UserSession,
|
session: UserSession,
|
||||||
) -> Result<Html<String>, WebAppError> {
|
) -> Result<Html<String>, WebAppError> {
|
||||||
let user = state.gotrue_client.user_info(&session.access_token).await?;
|
let user = state
|
||||||
|
.gotrue_client
|
||||||
|
.user_info(&session.token.access_token)
|
||||||
|
.await?;
|
||||||
render_template(templates::Home {
|
render_template(templates::Home {
|
||||||
user: &user,
|
user: &user,
|
||||||
is_admin: is_admin(&user),
|
is_admin: is_admin(&user),
|
||||||
|
|
@ -84,7 +90,10 @@ pub async fn admin_home_handler(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
session: UserSession,
|
session: UserSession,
|
||||||
) -> Result<Html<String>, WebAppError> {
|
) -> Result<Html<String>, WebAppError> {
|
||||||
let user = state.gotrue_client.user_info(&session.access_token).await?;
|
let user = state
|
||||||
|
.gotrue_client
|
||||||
|
.user_info(&session.token.access_token)
|
||||||
|
.await?;
|
||||||
render_template(templates::AdminHome { user: &user })
|
render_template(templates::AdminHome { user: &user })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,7 +103,7 @@ pub async fn admin_users_handler(
|
||||||
) -> Result<Html<String>, WebAppError> {
|
) -> Result<Html<String>, WebAppError> {
|
||||||
let users = state
|
let users = state
|
||||||
.gotrue_client
|
.gotrue_client
|
||||||
.admin_list_user(&session.access_token)
|
.admin_list_user(&session.token.access_token)
|
||||||
.await
|
.await
|
||||||
.map_or_else(
|
.map_or_else(
|
||||||
|err| {
|
|err| {
|
||||||
|
|
@ -117,7 +126,7 @@ pub async fn admin_user_details_handler(
|
||||||
) -> Result<Html<String>, WebAppError> {
|
) -> Result<Html<String>, WebAppError> {
|
||||||
let user = state
|
let user = state
|
||||||
.gotrue_client
|
.gotrue_client
|
||||||
.admin_user_details(&session.access_token, &user_id)
|
.admin_user_details(&session.token.access_token, &user_id)
|
||||||
.await
|
.await
|
||||||
.unwrap(); // TODO: handle error
|
.unwrap(); // TODO: handle error
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue