feat: self host support: sign up auto confirm

This commit is contained in:
Fu Zi Xiang 2023-11-09 13:38:32 +08:00
parent e2d6d1df02
commit 6803ff9cca
No known key found for this signature in database
3 changed files with 59 additions and 14 deletions

View File

@ -21,6 +21,7 @@ body {
padding: 4px 8px; padding: 4px 8px;
font-size: 16px; font-size: 16px;
cursor: pointer; cursor: pointer;
margin: auto;
} }
.purple:hover { .purple:hover {

View File

@ -15,7 +15,8 @@ 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::params::{AdminDeleteUserParams, AdminUserParams, GenerateLinkParams, MagicLinkParams}; use gotrue::params::{AdminDeleteUserParams, AdminUserParams, GenerateLinkParams, MagicLinkParams};
use gotrue_entity::dto::{UpdateGotrueUserParams, User}; use gotrue_entity::dto::{GotrueTokenResponse, SignUpResponse, UpdateGotrueUserParams, User};
use gotrue_entity::error::GoTrueError;
pub fn router() -> Router<AppState> { pub fn router() -> Router<AppState> {
Router::new() Router::new()
@ -221,14 +222,15 @@ pub async fn login_refresh_handler(
Ok(jar.add(cookie)) Ok(jar.add(cookie))
} }
// TODO: Support OAuth2 login
// login and set the cookie // login and set the cookie
// sign up if not exist
pub async fn login_handler( pub async fn login_handler(
State(state): State<AppState>, State(state): State<AppState>,
jar: CookieJar, jar: CookieJar,
Form(param): Form<WebApiLoginRequest>, Form(param): Form<WebApiLoginRequest>,
) -> Result<(CookieJar, HeaderMap), WebApiError<'static>> { ) -> Result<(CookieJar, HeaderMap), WebApiError<'static>> {
let token = state // Attempt to sign in with email and password
let token_res = state
.gotrue_client .gotrue_client
.token(&gotrue::grant::Grant::Password( .token(&gotrue::grant::Grant::Password(
gotrue::grant::PasswordGrant { gotrue::grant::PasswordGrant {
@ -236,16 +238,44 @@ pub async fn login_handler(
password: param.password.to_owned(), password: param.password.to_owned(),
}, },
)) ))
.await?; .await;
let new_session_id = uuid::Uuid::new_v4(); match token_res {
let new_session = session::UserSession::new(new_session_id.to_string(), token); Ok(token) => session_login(State(state), token, jar).await, // login success
state.session_store.put_user_session(&new_session).await?; Err(err) => match &err {
GoTrueError::ClientError(client_err) => {
match (
client_err.error.as_str(),
client_err.error_description.as_ref().map(|s| s.as_str()),
) {
// Email not exist or wrong password
("invalid_grant", Some("Invalid login credentials")) => {
let sign_up_res = state
.gotrue_client
.sign_up(&param.email, &param.password)
.await;
Ok(( match sign_up_res {
jar.add(new_session_cookie(new_session_id)), Ok(resp) => match resp {
htmx_redirect("/web/home"), // when GOTRUE_MAILER_AUTOCONFIRM=true, auto sign in
)) SignUpResponse::Authenticated(token) => {
session_login(State(state), token, jar).await
},
SignUpResponse::NotAuthenticated(user) => match user.identities {
Some(_identities) => todo!(), // new user
None => Err(err.into()), // user exists but sign in password not correct
},
},
Err(err) => Err(err.into()),
}
},
_ => Err(err.into()),
}
},
_ => Err(err.into()),
},
}
} }
pub async fn logout_handler( pub async fn logout_handler(
@ -278,3 +308,18 @@ fn new_session_cookie(id: uuid::Uuid) -> Cookie<'static> {
cookie.set_path("/"); cookie.set_path("/");
cookie cookie
} }
async fn session_login(
State(state): State<AppState>,
token: GotrueTokenResponse,
jar: CookieJar,
) -> Result<(CookieJar, HeaderMap), WebApiError<'static>> {
let new_session_id = uuid::Uuid::new_v4();
let new_session = session::UserSession::new(new_session_id.to_string(), token);
state.session_store.put_user_session(&new_session).await?;
Ok((
jar.add(new_session_cookie(new_session_id)),
htmx_redirect("/web/home"),
))
}

View File

@ -49,14 +49,13 @@
</td> </td>
</tr> </tr>
</table> </table>
<br />
<button <button
class="button cyan" class="button cyan"
type="submit" type="submit"
style="width: 100%; padding: 8px 8px" style="width: 100%; margin: 16px auto 0; padding: 8px 8px"
id="submitBtn" id="submitBtn"
> >
Sign In Sign In / Sign Up
</button> </button>
</form> </form>
<br /> <br />