Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(db): Update UserDAO to use query_as! and use i64 IDs in most pl… #1760

Merged
merged 3 commits into from
Apr 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions ee/tabby-db/src/job_runs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ impl DbConn {
Ok(rowid as i32)
}

pub async fn update_job_stdout(&self, job_id: i32, stdout: String) -> Result<()> {
pub async fn update_job_stdout(&self, job_id: i64, stdout: String) -> Result<()> {
query!(
r#"UPDATE job_runs SET stdout = stdout || ?, updated_at = datetime('now') WHERE id = ?"#,
stdout,
Expand All @@ -48,7 +48,7 @@ impl DbConn {
Ok(())
}

pub async fn update_job_stderr(&self, job_id: i32, stderr: String) -> Result<()> {
pub async fn update_job_stderr(&self, job_id: i64, stderr: String) -> Result<()> {
query!(
r#"UPDATE job_runs SET stderr = stderr || ?, updated_at = datetime('now') WHERE id = ?"#,
stderr,
Expand All @@ -57,7 +57,7 @@ impl DbConn {
Ok(())
}

pub async fn update_job_status(&self, job_id: i32, exit_code: i32) -> Result<()> {
pub async fn update_job_status(&self, job_id: i64, exit_code: i32) -> Result<()> {
query!(
r#"UPDATE job_runs SET end_ts = datetime('now'), exit_code = ?, updated_at = datetime('now') WHERE id = ?"#,
exit_code,
Expand Down
2 changes: 1 addition & 1 deletion ee/tabby-db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
select.as_string()
}

fn make_pagination_query(

Check warning on line 85 in ee/tabby-db/src/lib.rs

View workflow job for this annotation

GitHub Actions / autofix

function `make_pagination_query` is never used

Check warning on line 85 in ee/tabby-db/src/lib.rs

View workflow job for this annotation

GitHub Actions / autofix

function `make_pagination_query` is never used
table_name: &str,
field_names: &[&str],
limit: Option<usize>,
Expand Down Expand Up @@ -355,7 +355,7 @@
pub mod testutils {
use super::*;

pub async fn create_user(conn: &DbConn) -> i32 {
pub async fn create_user(conn: &DbConn) -> i64 {
let email: &str = "[email protected]";
let password: &str = "123456789";
conn.create_user(email.to_string(), Some(password.to_string()), true)
Expand Down
4 changes: 2 additions & 2 deletions ee/tabby-db/src/password_reset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,15 @@ impl DbConn {
.ok_or_else(|| anyhow!("Invalid code"))?;

let user_res = self
.get_user(password_reset.user_id as i32)
.get_user(password_reset.user_id)
.await?
.filter(|user| user.active)
.ok_or_else(|| anyhow!("Invalid code"))?;

if Utc::now().signed_duration_since(*password_reset.created_at) > Duration::minutes(15) {
Err(anyhow!("Invalid code"))
} else {
Ok(user_res.id as i64)
Ok(user_res.id)
}
}

Expand Down
8 changes: 4 additions & 4 deletions ee/tabby-db/src/refresh_tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl RefreshTokenDAO {

/// db read/write operations for `refresh_tokens` table
impl DbConn {
pub async fn create_refresh_token(&self, user_id: i32) -> Result<String> {
pub async fn create_refresh_token(&self, user_id: i64) -> Result<String> {
let token = generate_refresh_token(0);
let res = query!(
r#"INSERT INTO refresh_tokens (user_id, token, expires_at) VALUES (?, ?, datetime('now', '+7 days'))"#,
Expand All @@ -43,8 +43,8 @@ impl DbConn {
Ok(token)
}

pub async fn renew_refresh_token(&self, id: i32, old: &str) -> Result<String> {
let new = generate_refresh_token(id as i64);
pub async fn renew_refresh_token(&self, id: i64, old: &str) -> Result<String> {
let new = generate_refresh_token(id);
let res = query!(
"UPDATE refresh_tokens SET token = $1, expires_at = datetime('now', '+7 days') WHERE token = $2 AND id = $3",
new,
Expand Down Expand Up @@ -82,7 +82,7 @@ impl DbConn {
Ok(token)
}

pub async fn delete_tokens_by_user_id(&self, id: i32) -> Result<()> {
pub async fn delete_tokens_by_user_id(&self, id: i64) -> Result<()> {
query!("DELETE FROM refresh_tokens WHERE user_id = ?", id)
.execute(&self.pool)
.await?;
Expand Down
2 changes: 1 addition & 1 deletion ee/tabby-db/src/user_completions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl DbConn {
pub async fn create_user_completion(
&self,
ts: u128,
user_id: i32,
user_id: i64,
completion_id: String,
language: String,
) -> Result<i32> {
Expand Down
88 changes: 44 additions & 44 deletions ee/tabby-db/src/users.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
use anyhow::{anyhow, bail, Result};
use chrono::{DateTime, Utc};
use sqlx::{query, query_scalar, FromRow};
use sqlx::{query, query_as, query_scalar, FromRow};
use tabby_db_macros::query_paged_as;
use uuid::Uuid;

use super::DbConn;
use crate::{make_pagination_query, SQLXResultExt};
use crate::{DateTimeUtc, SQLXResultExt};

#[allow(unused)]
#[derive(FromRow)]
pub struct UserDAO {
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub created_at: DateTimeUtc,
pub updated_at: DateTimeUtc,

pub id: i32,
pub id: i64,
pub email: String,
pub password_encrypted: Option<String>,
pub is_admin: bool,
Expand All @@ -22,15 +22,19 @@
pub active: bool,
}

static OWNER_USER_ID: i32 = 1;
static OWNER_USER_ID: i64 = 1;

impl UserDAO {
fn select(clause: &str) -> String {
r#"SELECT id, email, password_encrypted, is_admin, created_at, updated_at, auth_token, active FROM users WHERE "#
.to_owned()
+ clause
macro_rules! select {
($str:literal $(,)? $($val:expr),*) => {
query_as!(
UserDAO,
r#"SELECT id as "id!", email, password_encrypted, is_admin, created_at as "created_at!", updated_at as "updated_at!", auth_token, active FROM users WHERE "# + $str,
$($val),*
)
}
}

impl UserDAO {
pub fn is_owner(&self) -> bool {
self.id == OWNER_USER_ID
}
Expand All @@ -43,7 +47,7 @@
email: String,
password_encrypted: Option<String>,
is_admin: bool,
) -> Result<i32> {
) -> Result<i64> {
self.create_user_impl(email, password_encrypted, is_admin, None)
.await
}
Expand All @@ -53,8 +57,8 @@
email: String,
password_encrypted: Option<String>,
is_admin: bool,
invitation_id: i32,
) -> Result<i32> {
invitation_id: i64,
) -> Result<i64> {
self.create_user_impl(email, password_encrypted, is_admin, Some(invitation_id))
.await
}
Expand All @@ -64,8 +68,8 @@
email: String,
password_encrypted: Option<String>,
is_admin: bool,
invitation_id: Option<i32>,
) -> Result<i32> {
invitation_id: Option<i64>,
) -> Result<i64> {
let mut transaction = self.pool.begin().await?;
if let Some(invitation_id) = invitation_id {
query!("DELETE FROM invitations WHERE id = ?", invitation_id)
Expand All @@ -84,31 +88,25 @@
self.cache.active_admin_count.invalidate().await;
}

Ok(res.last_insert_rowid() as i32)
Ok(res.last_insert_rowid())
}

pub async fn get_user(&self, id: i32) -> Result<Option<UserDAO>> {
let user = sqlx::query_as(&UserDAO::select("id = ?"))
.bind(id)
.fetch_optional(&self.pool)
.await?;
pub async fn get_user(&self, id: i64) -> Result<Option<UserDAO>> {
let user = select!("id = ?", id).fetch_optional(&self.pool).await?;

Ok(user)
}

pub async fn get_user_by_email(&self, email: &str) -> Result<Option<UserDAO>> {
let user = sqlx::query_as(&UserDAO::select("email = ?"))
.bind(email)
let user = select!("email = ?", email)
.fetch_optional(&self.pool)
.await?;

Ok(user)
}

pub async fn list_admin_users(&self) -> Result<Vec<UserDAO>> {
let users = sqlx::query_as(&UserDAO::select("is_admin"))
.fetch_all(&self.pool)
.await?;
let users = select!("is_admin").fetch_all(&self.pool).await?;

Ok(users)
}
Expand All @@ -119,24 +117,26 @@
skip_id: Option<i32>,
backwards: bool,
) -> Result<Vec<UserDAO>> {
let query = make_pagination_query(
let users = query_paged_as!(
UserDAO,

Check warning on line 121 in ee/tabby-db/src/users.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-db/src/users.rs#L121

Added line #L121 was not covered by tests
"users",
&[
"id",
[
"id"!,

Check warning on line 124 in ee/tabby-db/src/users.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-db/src/users.rs#L123-L124

Added lines #L123 - L124 were not covered by tests
"email",
"password_encrypted",
"is_admin",
"created_at",
"updated_at",
"created_at"!,
"updated_at"!,

Check warning on line 129 in ee/tabby-db/src/users.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-db/src/users.rs#L128-L129

Added lines #L128 - L129 were not covered by tests
"auth_token",
"active",
"active"

Check warning on line 131 in ee/tabby-db/src/users.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-db/src/users.rs#L131

Added line #L131 was not covered by tests
],
limit,
skip_id,
backwards,
);
backwards
)

Check warning on line 136 in ee/tabby-db/src/users.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-db/src/users.rs#L135-L136

Added lines #L135 - L136 were not covered by tests
.fetch_all(&self.pool)
.await?;

let users = sqlx::query_as(&query).fetch_all(&self.pool).await?;
Ok(users)
}

Expand All @@ -157,7 +157,7 @@
Ok(id)
}

pub async fn reset_user_auth_token_by_id(&self, id: i32) -> Result<()> {
pub async fn reset_user_auth_token_by_id(&self, id: i64) -> Result<()> {
let updated_at = chrono::Utc::now();
let token = generate_auth_token();
query!(
Expand All @@ -172,7 +172,7 @@
Ok(())
}

pub async fn update_user_active(&self, id: i32, active: bool) -> Result<()> {
pub async fn update_user_active(&self, id: i64, active: bool) -> Result<()> {
let not_active = !active;
let changed = query!(
"UPDATE users SET active = ? WHERE id = ? AND active = ?",
Expand All @@ -191,7 +191,7 @@
Ok(())
}

pub async fn update_user_role(&self, id: i32, is_admin: bool) -> Result<()> {
pub async fn update_user_role(&self, id: i64, is_admin: bool) -> Result<()> {
let not_admin = !is_admin;
let changed = query!(
"UPDATE users SET is_admin = ? WHERE id = ? AND is_admin = ?",
Expand All @@ -210,7 +210,7 @@
}
}

pub async fn update_user_password(&self, id: i32, password_encrypted: String) -> Result<()> {
pub async fn update_user_password(&self, id: i64, password_encrypted: String) -> Result<()> {
query!(
"UPDATE users SET password_encrypted = ? WHERE id = ?",
password_encrypted,
Expand All @@ -221,14 +221,14 @@
Ok(())
}

pub async fn update_user_avatar(&self, id: i32, avatar: Option<Box<[u8]>>) -> Result<()> {
pub async fn update_user_avatar(&self, id: i64, avatar: Option<Box<[u8]>>) -> Result<()> {

Check warning on line 224 in ee/tabby-db/src/users.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-db/src/users.rs#L224

Added line #L224 was not covered by tests
query!("UPDATE users SET avatar = ? WHERE id = ?;", avatar, id)
.execute(&self.pool)
.await?;
Ok(())
}

pub async fn get_user_avatar(&self, id: i32) -> Result<Option<Box<[u8]>>> {
pub async fn get_user_avatar(&self, id: i64) -> Result<Option<Box<[u8]>>> {

Check warning on line 231 in ee/tabby-db/src/users.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-db/src/users.rs#L231

Added line #L231 was not covered by tests
let avatar = query_scalar!("SELECT avatar FROM users WHERE id = ?", id)
.fetch_one(&self.pool)
.await?;
Expand Down Expand Up @@ -341,7 +341,7 @@
async fn test_list_users_with_filter() {
let conn = DbConn::new_in_memory().await.unwrap();

let empty: Vec<i32> = vec![];
let empty: Vec<i64> = vec![];
let to_ids = |users: Vec<UserDAO>| users.into_iter().map(|u| u.id).collect::<Vec<_>>();

// empty
Expand Down
Loading
Loading