feat: email redirect to invite page

This commit is contained in:
Zack Fu Zi Xiang 2024-03-21 14:01:48 +08:00
parent aa3f0fd86e
commit 528dd6ae5b
No known key found for this signature in database
5 changed files with 15 additions and 33 deletions

0
2
View File

View File

@ -28,11 +28,11 @@ pub fn router() -> Router<AppState> {
Router::new()
.route("/signin", post(sign_in_handler))
.route("/signup", post(sign_up_handler))
.route("/login_refresh/:refresh_token", post(login_refresh_handler))
.route("/login-refresh/:refresh_token", post(login_refresh_handler))
.route("/logout", post(logout_handler))
// user
.route("/change_password", post(change_password_handler))
.route("/change-password", post(change_password_handler))
.route("/oauth_login/:provider", post(post_oauth_login_handler))
.route("/invite", post(invite_handler))
.route("/workspace/:workspace_id/invite", post(workspace_invite_handler))

View File

@ -107,13 +107,14 @@
</div>
<script>
// OAuthLogin
// OAuthLogin (This is done because axum doesn't support fragment in the URL)
// https://github.com/tokio-rs/axum/discussions/2147
if (window.location.hash) {
// Extract data from the URL fragment
const fragmentData = window.location.hash.substring(1); // Remove the leading #
const fragmentData = window.location.hash.substring(1); // Remove the leading #
const fragmentParams = new URLSearchParams(fragmentData); // Parse the fragment data as a URLSearchParams object
const refreshToken = fragmentParams.get("refresh_token"); // Extract the refresh_token
fetch(`/web-api/login_refresh/${refreshToken}`, {
fetch(`/web-api/login-refresh/${refreshToken}`, {
// Login in via refresh_token
method: "POST",
}).then((response) => {
@ -123,6 +124,9 @@
window.location.href = "/web/home";
}
});
// Remove # from url, prevent access_token from being reused event though refresh token is already invalid
history.replaceState("", document.title, window.location.pathname + window.location.search);
}
</script>
{% endblock %}

View File

@ -250,7 +250,6 @@ async fn post_workspace_invite_handler(
let invited_members = payload.into_inner();
workspace::ops::invite_workspace_members(
&state.pg_pool,
&state.gotrue_admin,
&state.gotrue_client,
&user_uuid,
&workspace_id,

View File

@ -21,7 +21,7 @@ use database_entity::dto::{
WorkspaceUsage,
};
use gotrue::params::InviteUserParams;
use gotrue::params::{InviteUserParams, MagicLinkParams};
use shared_entity::dto::workspace_dto::{
CreateWorkspaceMember, WorkspaceMemberChangeset, WorkspaceMemberInvitation,
};
@ -164,7 +164,6 @@ pub async fn accept_workspace_invite(
#[instrument(level = "debug", skip_all, err)]
pub async fn invite_workspace_members(
pg_pool: &PgPool,
gotrue_admin: &GoTrueAdmin,
gotrue_client: &gotrue::api::Client,
inviter: &Uuid,
workspace_id: &Uuid,
@ -175,36 +174,16 @@ pub async fn invite_workspace_members(
.await
.context("Begin transaction to invite workspace members")?;
let admin_token = gotrue_admin.token(gotrue_client).await?;
for invitation in invitations {
match gotrue_client
.admin_invite_user(
&admin_token,
&InviteUserParams {
gotrue_client
.magic_link(
&MagicLinkParams {
email: invitation.email.clone(),
..Default::default()
},
Some("/web/home#invite".to_owned()),
)
.await
{
Ok(new_user) => {
info!(
"Invited new user: {:?} to workspace: {:?}",
new_user, workspace_id
);
},
Err(err) => match err {
app_error::gotrue::GoTrueError::Internal(ref err_serde) => {
match (err_serde.code, err_serde.msg.as_str()) {
(422, "A user with this email address has already been registered") => {
info!("User already exists, skipping invite");
},
_ => return Err(AppError::Internal(err.into())),
}
},
_ => return Err(err.into()),
},
}
.await?;
// Generate a link such that when clicked, the user is added to the workspace.
insert_workspace_invitation(