Skip to content

Commit

Permalink
feat(webserver): complete github_auth method (TabbyML#1169)
Browse files Browse the repository at this point in the history
* feat(webserver): register user when oauth by github

* [autofix.ci] apply automated fixes

* add comment

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
  • Loading branch information
darknight and autofix-ci[bot] authored Jan 7, 2024
1 parent 81f46dc commit 3003a4f
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 4 deletions.
18 changes: 18 additions & 0 deletions ee/tabby-db/src/invitations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,24 @@ impl DbConn {
Ok(token?)
}

pub async fn get_invitation_by_email(&self, email: &str) -> Result<Option<InvitationDAO>> {
let email = email.to_owned();
let token = self
.conn
.call(|conn| {
Ok(conn
.query_row(
r#"SELECT id, email, code, created_at FROM invitations WHERE email = ?"#,
[email],
InvitationDAO::from_row,
)
.optional())
})
.await?;

Ok(token?)
}

pub async fn create_invitation(&self, email: String) -> Result<i32> {
if self.get_user_by_email(&email).await?.is_some() {
return Err(anyhow!("User already registered"));
Expand Down
1 change: 1 addition & 0 deletions ee/tabby-webserver/src/oauth/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ async fn github_callback(
}
Err(GithubAuthError::InvalidVerificationCode) => Err(StatusCode::BAD_REQUEST),
Err(GithubAuthError::CredentialNotActive) => Err(StatusCode::NOT_FOUND),
Err(GithubAuthError::UserNotInvited) => Err(StatusCode::UNAUTHORIZED),
Err(e) => {
error!("Failed to authenticate with Github: {:?}", e);
Err(StatusCode::INTERNAL_SERVER_ERROR)
Expand Down
3 changes: 3 additions & 0 deletions ee/tabby-webserver/src/schema/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ pub enum GithubAuthError {
#[error("The Github credential is not active")]
CredentialNotActive,

#[error("The user is not invited to access the system")]
UserNotInvited,

#[error(transparent)]
Other(#[from] anyhow::Error),

Expand Down
32 changes: 28 additions & 4 deletions ee/tabby-webserver/src/service/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,11 +357,35 @@ impl AuthenticationService for DbConn {
return Err(GithubAuthError::CredentialNotActive);
}

let _email = client.fetch_user_email(code, credential).await?;
let email = client.fetch_user_email(code, credential).await?;

// TODO: auto register & generate token
let user = if let Some(user) = self.get_user_by_email(&email).await? {
user
} else {
let Some(invitation) = self.get_invitation_by_email(&email).await? else {
return Err(GithubAuthError::UserNotInvited);
};
// it's ok to set password to empty string here, because
// 1. both `register` & `token_auth` mutation will do input validation, so empty password won't be accepted
// 2. `password_verify` will always return false for empty password hash read from user table
// so user created here is only able to login by github oauth, normal login won't work
let id = self
.create_user_with_invitation(email, "".to_owned(), false, invitation.id)
.await?;
self.get_user(id).await?.unwrap()
};

let refresh_token = generate_refresh_token();
self.create_refresh_token(user.id, &refresh_token).await?;

let access_token = generate_jwt(JWTPayload::new(user.email.clone(), user.is_admin))
.map_err(|_| GithubAuthError::Unknown)?;

Ok(GithubAuthResponse::default())
let resp = GithubAuthResponse {
access_token,
refresh_token,
};
Ok(resp)
}
}

Expand Down Expand Up @@ -492,7 +516,7 @@ mod tests {
email.to_owned(),
password.to_owned(),
password.to_owned(),
Some(invitation.code.clone())
Some(invitation.code.clone()),
)
.await
.is_ok());
Expand Down

0 comments on commit 3003a4f

Please sign in to comment.