Merge pull request #528 from AppFlowy-IO/email-link-reuse
feat: reuse email link
This commit is contained in:
commit
8870607569
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n UPDATE public.af_workspace_invitation\n SET status = 1\n WHERE invitee_email = (SELECT email FROM public.af_user WHERE uuid = $1)\n AND id = $2\n ",
|
||||
"query": "\n UPDATE public.af_workspace_invitation\n SET status = 1\n WHERE invitee_email = (SELECT email FROM public.af_user WHERE uuid = $1)\n AND id = $2\n AND status = 0\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
|
|
@ -11,5 +11,5 @@
|
|||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "3b3dd104bf9e1fb9cf6d413e0e59db0cdbb009c92dce1c1e67900c44efdb8db4"
|
||||
"hash": "5d2ab1eb7ab9ebea8c162f4b742c72dbea7f3d18849f6cd7865068be9b01d759"
|
||||
}
|
||||
|
|
@ -143,6 +143,23 @@ pub async fn get_pending_workspace_invitations(
|
|||
from_json_response(resp).await
|
||||
}
|
||||
|
||||
pub async fn get_accepted_workspace_invitations(
|
||||
access_token: &str,
|
||||
appflowy_cloud_base_url: &str,
|
||||
) -> Result<Vec<AFWorkspaceInvitation>, Error> {
|
||||
let http_client = reqwest::Client::new();
|
||||
let resp = http_client
|
||||
.get(format!(
|
||||
"{}/api/workspace/invite?status=Accepted",
|
||||
appflowy_cloud_base_url
|
||||
))
|
||||
.header("Authorization", format!("Bearer {}", access_token))
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
from_json_response(resp).await
|
||||
}
|
||||
|
||||
async fn get_user_workspace_limits(
|
||||
workspace_id: &str,
|
||||
access_token: &str,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
use crate::askama_entities::WorkspaceWithMembers;
|
||||
use crate::error::WebAppError;
|
||||
use crate::ext::api::{
|
||||
accept_workspace_invitation, get_pending_workspace_invitations, get_user_owned_workspaces,
|
||||
get_user_profile, get_user_workspace_limit, get_user_workspace_usages, get_user_workspaces,
|
||||
get_workspace_members, verify_token_cloud,
|
||||
accept_workspace_invitation, get_accepted_workspace_invitations,
|
||||
get_pending_workspace_invitations, get_user_owned_workspaces, get_user_profile,
|
||||
get_user_workspace_limit, get_user_workspace_usages, get_user_workspaces, get_workspace_members,
|
||||
verify_token_cloud,
|
||||
};
|
||||
use crate::models::{OAuthLoginAction, WebAppOAuthLoginRequest};
|
||||
use crate::session::{self, new_session_cookie, UserSession};
|
||||
|
|
@ -68,35 +69,51 @@ async fn login_callback_handler() -> Result<Html<String>, WebAppError> {
|
|||
|
||||
async fn login_callback_query_handler(
|
||||
State(state): State<AppState>,
|
||||
session: Option<UserSession>,
|
||||
Query(query): Query<WebAppOAuthLoginRequest>,
|
||||
mut jar: CookieJar,
|
||||
) -> Result<(CookieJar, Html<String>), WebAppError> {
|
||||
if let Some(err) = query.error {
|
||||
tracing::error!(
|
||||
"OAuth login error: {:?}, code: {:?}, description: {:?}",
|
||||
err,
|
||||
query.error_code,
|
||||
query.error_description
|
||||
);
|
||||
return Ok((jar, render_template(templates::Redirect {
|
||||
redirect_url: format!(
|
||||
"https://appflowy.io/invitation/expired?workspace_name={}&workspace_icon={}&user_name={}&user_icon={}&workspace_member_count={}",
|
||||
query.workspace_name.unwrap_or_default(),
|
||||
query.workspace_icon.unwrap_or_default(),
|
||||
query.user_name.unwrap_or_default(),
|
||||
query.user_icon.unwrap_or_default(),
|
||||
query.workspace_member_count.unwrap_or_default()),
|
||||
})?));
|
||||
let refresh_token = {
|
||||
match query.refresh_token {
|
||||
Some(refresh_token) => refresh_token,
|
||||
None => match session {
|
||||
Some(session) => session.token.refresh_token,
|
||||
None => match query.error {
|
||||
Some(err) => {
|
||||
tracing::error!(
|
||||
"OAuth login error: {:?}, code: {:?}, description: {:?}",
|
||||
err,
|
||||
query.error_code,
|
||||
query.error_description
|
||||
);
|
||||
let expired_url = format!(
|
||||
"https://appflowy.io/invitation/expired?workspace_name={}&workspace_icon={}&user_name={}&user_icon={}&workspace_member_count={}",
|
||||
query.workspace_name.unwrap_or_default(),
|
||||
query.workspace_icon.unwrap_or_default(),
|
||||
query.user_name.unwrap_or_default(),
|
||||
query.user_icon.unwrap_or_default(),
|
||||
query.workspace_member_count.unwrap_or_default());
|
||||
return Ok((
|
||||
jar,
|
||||
render_template(templates::Redirect {
|
||||
redirect_url: expired_url,
|
||||
})?,
|
||||
));
|
||||
},
|
||||
None => {
|
||||
return Err(WebAppError::BadRequest(
|
||||
"refresh_token not found".to_string(),
|
||||
));
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
let token = state
|
||||
.gotrue_client
|
||||
.token(&gotrue::grant::Grant::RefreshToken(
|
||||
gotrue::grant::RefreshTokenGrant {
|
||||
refresh_token: query.refresh_token.ok_or(WebAppError::BadRequest(
|
||||
"refresh_token not found".to_string(),
|
||||
))?,
|
||||
},
|
||||
gotrue::grant::RefreshTokenGrant { refresh_token },
|
||||
))
|
||||
.await?;
|
||||
|
||||
|
|
@ -129,6 +146,22 @@ async fn login_callback_query_handler(
|
|||
.ok_or(WebAppError::BadRequest(
|
||||
"workspace_invitation_id not found".to_string(),
|
||||
))?;
|
||||
|
||||
{
|
||||
// If user has already accepted the invitation, redirect to open or download AppFlowy
|
||||
let accepted_invitations = get_accepted_workspace_invitations(
|
||||
&new_session.token.access_token,
|
||||
&state.appflowy_cloud_url,
|
||||
)
|
||||
.await?;
|
||||
let found = accepted_invitations
|
||||
.iter()
|
||||
.find(|w| w.invite_id.to_string() == invite_id);
|
||||
if let Some(_) = found {
|
||||
return Ok((jar, render_template(templates::OpenAppFlowyOrDownload {})?));
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(err) = accept_workspace_invitation(
|
||||
&new_session.token.access_token,
|
||||
&invite_id,
|
||||
|
|
@ -137,10 +170,17 @@ async fn login_callback_query_handler(
|
|||
.await
|
||||
{
|
||||
tracing::error!("accepting workspace invitation: {:?}", err);
|
||||
let expired_url = format!(
|
||||
"https://appflowy.io/invitation/expired?workspace_name={}&workspace_icon={}&user_name={}&user_icon={}&workspace_member_count={}",
|
||||
query.workspace_name.unwrap_or_default(),
|
||||
query.workspace_icon.unwrap_or_default(),
|
||||
query.user_name.unwrap_or_default(),
|
||||
query.user_icon.unwrap_or_default(),
|
||||
query.workspace_member_count.unwrap_or_default());
|
||||
return Ok((
|
||||
jar,
|
||||
render_template(templates::Redirect {
|
||||
redirect_url: "https://test.appflowy.io/invitation/expired".to_string(),
|
||||
redirect_url: expired_url,
|
||||
})?,
|
||||
));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -294,6 +294,7 @@ pub async fn update_workspace_invitation_set_status_accepted(
|
|||
SET status = 1
|
||||
WHERE invitee_email = (SELECT email FROM public.af_user WHERE uuid = $1)
|
||||
AND id = $2
|
||||
AND status = 0
|
||||
"#,
|
||||
invitee_uuid,
|
||||
invite_id,
|
||||
|
|
|
|||
Loading…
Reference in New Issue