From 3d2e127a503e50080f61095051de5639be669f4f Mon Sep 17 00:00:00 2001 From: DrVilepis Date: Tue, 28 May 2024 12:03:49 +0300 Subject: [PATCH] remove LazyLock and remove clones --- Cargo.toml | 2 +- src/api/activity.rs | 6 ++---- src/api/auth.rs | 12 +++++------- src/api/friends.rs | 2 +- src/api/leaderboards.rs | 34 +++++++++++++++------------------- src/api/mod.rs | 7 +++---- src/api/oauth.rs | 25 +++++++++++-------------- src/api/users.rs | 12 ++++++------ src/database/activity.rs | 25 ++++++++----------------- src/database/auth.rs | 9 +++------ src/database/friends.rs | 3 +-- src/database/leaderboards.rs | 13 ++++++------- src/main.rs | 9 ++++++--- src/requests.rs | 5 ----- 14 files changed, 68 insertions(+), 96 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8281062..4d14f8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,5 +42,5 @@ url = "2.2" itertools = "0.10.3" governor = "0.6.0" -diesel = { version = "2.1.0", features = ["chrono", "serde_json"] } +diesel = { version = "2.1.0", features = ["chrono", "serde_json", "postgres_backend"] } diesel-async = { version = "0.4.1", features = ["postgres", "deadpool"] } diff --git a/src/api/activity.rs b/src/api/activity.rs index 1791e0c..779217b 100644 --- a/src/api/activity.rs +++ b/src/api/activity.rs @@ -173,9 +173,7 @@ pub async fn rename_project( db: DatabaseWrapper, body: Json, ) -> Result { - let renamed = db - .rename_project(user.id, body.from.clone(), body.to.clone()) - .await?; + let renamed = db.rename_project(user.id, &body.from, &body.to).await?; Ok(web::Json(json!({ "affected_activities": renamed }))) } @@ -187,7 +185,7 @@ pub async fn hide_project( body: Json, ) -> Result { let renamed = db - .set_project_hidden(user.id, body.target_project.clone(), body.hidden.clone()) + .set_project_hidden(user.id, &body.target_project, body.hidden) .await?; Ok(web::Json(json!({ "affected_activities": renamed }))) diff --git a/src/api/auth.rs b/src/api/auth.rs index f0c4153..eaa8a89 100644 --- a/src/api/auth.rs +++ b/src/api/auth.rs @@ -158,12 +158,11 @@ pub async fn register( "Password has to be between 8 and 128 characters long".to_string(), )); } - if !super::VALID_NAME_REGEX.is_match(&data.username) { + if !super::REGEX.with(|r| r.is_match(&data.username)) { return Err(TimeError::BadUsername); } - let username = data.username.clone(); - if db.get_user_by_name(username).await.is_ok() { + if db.get_user_by_name(&data.username).await.is_ok() { return Err(TimeError::UserExists); } @@ -206,17 +205,16 @@ pub async fn changeusername( "Username is not between 2 and 32 chars".to_string(), )); } - if !super::VALID_NAME_REGEX.is_match(&data.new) { + if !super::REGEX.with(|r| r.is_match(&data.new)) { return Err(TimeError::BadUsername); } - let username = data.new.clone(); - if db.get_user_by_name(username).await.is_ok() { + if db.get_user_by_name(&data.new).await.is_ok() { return Err(TimeError::UserExists); } let user = db.get_user_by_id(user.identity.id).await?; - db.change_username(user.id, data.new.clone()).await?; + db.change_username(user.id, &data.new).await?; Ok(HttpResponse::Ok().finish()) } diff --git a/src/api/friends.rs b/src/api/friends.rs index c582de4..b5f888b 100644 --- a/src/api/friends.rs +++ b/src/api/friends.rs @@ -106,7 +106,7 @@ pub async fn remove( db: DatabaseWrapper, body: String, ) -> Result { - let friend = db.get_user_by_name(body.clone()).await?; + let friend = db.get_user_by_name(&body).await?; let deleted = db.remove_friend(user.identity.id, friend.id).await?; if deleted { diff --git a/src/api/leaderboards.rs b/src/api/leaderboards.rs index 2a3a0d9..39d03f3 100644 --- a/src/api/leaderboards.rs +++ b/src/api/leaderboards.rs @@ -31,12 +31,11 @@ pub async fn create_leaderboard( body: Json, db: DatabaseWrapper, ) -> Result { - if !super::VALID_NAME_REGEX.is_match(&body.name) { + if !super::REGEX.with(|r| r.is_match(&body.name)) { return Err(TimeError::BadLeaderboardName); } - let lname = body.name.clone(); - if db.get_leaderboard_id_by_name(lname).await.is_ok() { + if db.get_leaderboard_id_by_name(&body.name).await.is_ok() { return Err(TimeError::LeaderboardExists); } @@ -62,12 +61,12 @@ pub async fn get_leaderboard( db: DatabaseWrapper, ) -> Result { let lid = db - .get_leaderboard_id_by_name(path.0.clone()) + .get_leaderboard_id_by_name(&path.0) .await .map_err(|_| TimeError::LeaderboardNotFound)?; if db.is_leaderboard_member(user.id, lid).await? { - let board = db.get_leaderboard(path.0.clone()).await?; + let board = db.get_leaderboard(&path.0).await?; Ok(web::Json(board)) } else { Err(TimeError::Unauthorized) @@ -81,12 +80,12 @@ pub async fn delete_leaderboard( db: DatabaseWrapper, ) -> Result { let lid = db - .get_leaderboard_id_by_name(path.0.clone()) + .get_leaderboard_id_by_name(&path.0) .await .map_err(|_| TimeError::LeaderboardNotFound)?; if db.is_leaderboard_admin(user.identity.id, lid).await? { - db.delete_leaderboard(path.0.clone()).await?; + db.delete_leaderboard(&path.0).await?; Ok(HttpResponse::Ok().finish()) } else { Err(TimeError::Unauthorized) @@ -100,10 +99,7 @@ pub async fn join_leaderboard( db: DatabaseWrapper, ) -> Result { match db - .add_user_to_leaderboard( - user.id, - body.invite.trim().trim_start_matches("ttlic_").to_string(), - ) + .add_user_to_leaderboard(user.id, body.invite.trim().trim_start_matches("ttlic_")) .await { Err(e) => { @@ -130,7 +126,7 @@ pub async fn leave_leaderboard( db: DatabaseWrapper, ) -> Result { let lid = db - .get_leaderboard_id_by_name(path.0.clone()) + .get_leaderboard_id_by_name(&path.0) .await .map_err(|_| TimeError::LeaderboardNotFound)?; @@ -158,13 +154,13 @@ pub async fn promote_member( promotion: Json, ) -> Result { let lid = db - .get_leaderboard_id_by_name(path.0.clone()) + .get_leaderboard_id_by_name(&path.0) .await .map_err(|_| TimeError::LeaderboardNotFound)?; if db.is_leaderboard_admin(user.identity.id, lid).await? { let newadmin = db - .get_user_by_name(promotion.user.clone()) + .get_user_by_name(&promotion.user) .await .map_err(|_| TimeError::UserNotFound)?; @@ -190,13 +186,13 @@ pub async fn demote_member( demotion: Json, ) -> Result { let lid = db - .get_leaderboard_id_by_name(path.0.clone()) + .get_leaderboard_id_by_name(&path.0) .await .map_err(|_| TimeError::LeaderboardNotFound)?; if db.is_leaderboard_admin(user.identity.id, lid).await? { let oldadmin = db - .get_user_by_name(demotion.user.clone()) + .get_user_by_name(&demotion.user) .await .map_err(|_| TimeError::UserNotFound)?; @@ -222,13 +218,13 @@ pub async fn kick_member( kick: Json, ) -> Result { let lid = db - .get_leaderboard_id_by_name(path.0.clone()) + .get_leaderboard_id_by_name(&path.0) .await .map_err(|_| TimeError::LeaderboardNotFound)?; if db.is_leaderboard_admin(user.identity.id, lid).await? { let kmember = db - .get_user_by_name(kick.user.clone()) + .get_user_by_name(&kick.user) .await .map_err(|_| TimeError::UserNotFound)?; @@ -248,7 +244,7 @@ pub async fn regenerate_invite( db: DatabaseWrapper, ) -> Result { let lid = db - .get_leaderboard_id_by_name(path.0.clone()) + .get_leaderboard_id_by_name(&path.0) .await .map_err(|_| TimeError::LeaderboardNotFound)?; diff --git a/src/api/mod.rs b/src/api/mod.rs index de3c261..afd13ed 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -1,5 +1,3 @@ -use std::sync::LazyLock; - use actix_web::{HttpResponse, Responder}; use regex::Regex; @@ -14,8 +12,9 @@ pub mod search; pub mod stats; pub mod users; -static VALID_NAME_REGEX: LazyLock = - LazyLock::new(|| Regex::new("^[[:word:]]{2,32}$").unwrap()); +thread_local! { + pub static REGEX: Regex = Regex::new("^[[:word:]]{2,32}$").unwrap(); +} #[get("/health")] async fn health() -> impl Responder { diff --git a/src/api/oauth.rs b/src/api/oauth.rs index 58ae93a..d9d9a90 100644 --- a/src/api/oauth.rs +++ b/src/api/oauth.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, sync::LazyLock}; +use std::collections::HashMap; use actix_web::{ cookie::Cookie, @@ -21,13 +21,14 @@ struct TokenResponse { token: String, } -#[derive(Deserialize)] -struct ClientInfo { +#[cfg(feature = "testausid")] +#[derive(Debug, Deserialize, Clone)] +pub struct ClientInfo { #[serde(rename = "client_id")] - id: String, + pub id: String, #[serde(rename = "client_secret")] - secret: String, - redirect_uri: String, + pub secret: String, + pub redirect_uri: String, } #[derive(Deserialize, Debug)] @@ -42,15 +43,11 @@ struct TestausIdPlatformInfo { id: String, } -static CLIENT_INFO: LazyLock = LazyLock::new(|| { - toml::from_str(&std::fs::read_to_string("settings.toml").expect("Missing settings.toml")) - .expect("Invalid Toml in settings.toml") -}); - #[get("/auth/callback")] async fn callback( request: Query, client: Data, + oauth_client: Data, db: DatabaseWrapper, ) -> Result { if request.code.chars().any(|c| !c.is_alphanumeric()) { @@ -62,9 +59,9 @@ async fn callback( .insert_header(("content-type", "application/x-www-form-urlencoded")) .send_form(&HashMap::from([ ("code", &request.code), - ("redirect_uri", &CLIENT_INFO.redirect_uri), - ("client_id", &CLIENT_INFO.id), - ("client_secret", &CLIENT_INFO.secret), + ("redirect_uri", &oauth_client.redirect_uri), + ("client_id", &oauth_client.id), + ("client_secret", &oauth_client.secret), ])) .await .unwrap() diff --git a/src/api/users.rs b/src/api/users.rs index eb34613..5ee5e03 100644 --- a/src/api/users.rs +++ b/src/api/users.rs @@ -79,7 +79,7 @@ pub async fn get_current_activity( user.id } else { let target_user = db - .get_user_by_name(path.0.clone()) + .get_user_by_name(&path.0) .await .map_err(|_| TimeError::UserNotFound)?; @@ -95,7 +95,7 @@ pub async fn get_current_activity( } } else { let target_user = db - .get_user_by_name(path.0.clone()) + .get_user_by_name(&path.0) .await .map_err(|_| TimeError::UserNotFound)?; @@ -145,7 +145,7 @@ pub async fn get_activities( ) -> Result { let Some(user) = opt_user.identity else { let target_user = db - .get_user_by_name(path.0.clone()) + .get_user_by_name(&path.0) .await .map_err(|_| TimeError::UserNotFound)?; @@ -164,7 +164,7 @@ pub async fn get_activities( //FIXME: This is technically not required when the username equals the username of the //authenticated user let target_user = db - .get_user_by_name(path.0.clone()) + .get_user_by_name(&path.0) .await .map_err(|_| TimeError::UserNotFound)?; @@ -193,7 +193,7 @@ pub async fn get_activity_summary( db.get_all_activity(user.id).await? } else { let target_user = db - .get_user_by_name(path.0.clone()) + .get_user_by_name(&path.0) .await .map_err(|_| TimeError::UserNotFound)?; @@ -208,7 +208,7 @@ pub async fn get_activity_summary( } } else { let target_user = db - .get_user_by_name(path.0.clone()) + .get_user_by_name(&path.0) .await .map_err(|_| TimeError::UserNotFound)?; diff --git a/src/database/activity.rs b/src/database/activity.rs index e2e647a..51c5b65 100644 --- a/src/database/activity.rs +++ b/src/database/activity.rs @@ -98,14 +98,14 @@ impl super::DatabaseWrapper { pub async fn get_user_coding_time_since( &self, uid: i32, - since: chrono::NaiveDateTime, + since: chrono::DateTime, ) -> Result { let mut conn = self.db.get().await?; use crate::schema::coding_activities::dsl::*; Ok(coding_activities - .filter(user_id.eq(uid).and(start_time.ge(since))) + .filter(user_id.eq(uid).and(start_time.ge(since.naive_local()))) .select(diesel::dsl::sum(duration)) .first::>(&mut conn) .await? @@ -115,24 +115,15 @@ impl super::DatabaseWrapper { pub async fn get_coding_time_steps(&self, uid: i32) -> CodingTimeSteps { CodingTimeSteps { all_time: self - .get_user_coding_time_since( - uid, - chrono::NaiveDateTime::from_timestamp_opt(0, 0).unwrap(), - ) + .get_user_coding_time_since(uid, chrono::DateTime::default()) .await .unwrap_or(0), past_month: self - .get_user_coding_time_since( - uid, - chrono::Local::now().naive_local() - chrono::Duration::days(30), - ) + .get_user_coding_time_since(uid, chrono::Local::now() - chrono::Duration::days(30)) .await .unwrap_or(0), past_week: self - .get_user_coding_time_since( - uid, - chrono::Local::now().naive_local() - chrono::Duration::days(7), - ) + .get_user_coding_time_since(uid, chrono::Local::now() - chrono::Duration::days(7)) .await .unwrap_or(0), } @@ -141,8 +132,8 @@ impl super::DatabaseWrapper { pub async fn rename_project( &self, target_user_id: i32, - from: String, - to: String, + from: &str, + to: &str, ) -> Result { let mut conn = self.db.get().await?; @@ -158,7 +149,7 @@ impl super::DatabaseWrapper { pub async fn set_project_hidden( &self, target_user_id: i32, - target_project: String, + target_project: &str, to: bool, ) -> Result { let mut conn = self.db.get().await?; diff --git a/src/database/auth.rs b/src/database/auth.rs index 3049d7f..8a4d185 100644 --- a/src/database/auth.rs +++ b/src/database/auth.rs @@ -25,10 +25,7 @@ impl super::DatabaseWrapper { .is_some()) } - pub async fn get_user_by_name( - &self, - target_username: String, - ) -> Result { + pub async fn get_user_by_name(&self, target_username: &str) -> Result { let mut conn = self.db.get().await?; use crate::schema::user_identities::dsl::*; sql_function!(fn lower(x: diesel::sql_types::Text) -> Text); @@ -158,7 +155,7 @@ impl super::DatabaseWrapper { Ok(new_user) } - pub async fn change_username(&self, user: i32, new_username: String) -> Result<(), TimeError> { + pub async fn change_username(&self, user: i32, new_username: &str) -> Result<(), TimeError> { let mut conn = self.db.get().await?; conn.build_transaction() @@ -168,7 +165,7 @@ impl super::DatabaseWrapper { use crate::schema::user_identities::dsl::*; if (user_identities - .filter(username.eq(new_username.clone())) + .filter(username.eq(new_username)) .first::(&mut conn) .await) .is_ok() diff --git a/src/database/friends.rs b/src/database/friends.rs index 119f460..4c81205 100644 --- a/src/database/friends.rs +++ b/src/database/friends.rs @@ -159,12 +159,11 @@ impl super::DatabaseWrapper { pub async fn regenerate_friend_code(&self, userid: i32) -> Result { use crate::schema::user_identities::dsl::*; let code = crate::utils::generate_friend_code(); - let code_clone = code.clone(); let mut conn = self.db.get().await?; diesel::update(user_identities.find(userid)) - .set(friend_code.eq(code_clone)) + .set(friend_code.eq(&code)) .execute(&mut conn) .await?; diff --git a/src/database/leaderboards.rs b/src/database/leaderboards.rs index 6ff5151..5501686 100644 --- a/src/database/leaderboards.rs +++ b/src/database/leaderboards.rs @@ -23,6 +23,7 @@ impl super::DatabaseWrapper { name: &str, ) -> Result { let code = crate::utils::generate_token(); + let board = NewLeaderboard { name: name.to_string(), creation_time: chrono::Local::now().naive_local(), @@ -65,20 +66,18 @@ impl super::DatabaseWrapper { pub async fn regenerate_leaderboard_invite(&self, lid: i32) -> Result { let newinvite = crate::utils::generate_token(); - let newinvite_clone = newinvite.clone(); - let mut conn = self.db.get().await?; use crate::schema::leaderboards::dsl::*; diesel::update(leaderboards.find(lid)) - .set(invite_code.eq(newinvite_clone)) + .set(invite_code.eq(&newinvite)) .execute(&mut conn) .await?; Ok(newinvite) } - pub async fn delete_leaderboard(&self, lname: String) -> Result { + pub async fn delete_leaderboard(&self, lname: &str) -> Result { let mut conn = self.db.get().await?; use crate::schema::leaderboards::dsl::*; @@ -89,7 +88,7 @@ impl super::DatabaseWrapper { != 0) } - pub async fn get_leaderboard_id_by_name(&self, lname: String) -> Result { + pub async fn get_leaderboard_id_by_name(&self, lname: &str) -> Result { sql_function!(fn lower(x: diesel::sql_types::Text) -> Text); use crate::schema::leaderboards::dsl::*; @@ -102,7 +101,7 @@ impl super::DatabaseWrapper { .await?) } - pub async fn get_leaderboard(&self, lname: String) -> Result { + pub async fn get_leaderboard(&self, lname: &str) -> Result { sql_function!(fn lower(x: diesel::sql_types::Text) -> Text); let mut conn = self.db.get().await?; @@ -157,7 +156,7 @@ impl super::DatabaseWrapper { pub async fn add_user_to_leaderboard( &self, uid: i32, - invite: String, + invite: &str, ) -> Result { use crate::schema::leaderboards::dsl::{invite_code, leaderboards}; diff --git a/src/main.rs b/src/main.rs index 22bcaf6..69643d4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,3 @@ -#![feature(lazy_cell, addr_parse_ascii, async_closure)] - mod api; mod auth; mod database; @@ -23,8 +21,9 @@ use actix_web::{ web::{Data, QueryConfig}, App, HttpMessage, HttpServer, }; -use auth::{secured_access::SecuredAccessTokenStorage, AuthMiddleware, Authentication}; #[cfg(feature = "testausid")] +use api::oauth::ClientInfo; +use auth::{secured_access::SecuredAccessTokenStorage, AuthMiddleware, Authentication}; use awc::Client; use chrono::NaiveDateTime; use dashmap::DashMap; @@ -55,6 +54,9 @@ pub struct TimeConfig { pub address: String, pub database_url: String, pub allowed_origin: String, + #[cfg(feature = "testausid")] + #[serde(flatten)] + pub oauth_client_info: ClientInfo, } pub struct TestaustimeRootSpanBuilder; @@ -187,6 +189,7 @@ async fn main() -> std::io::Result<()> { #[cfg(feature = "testausid")] { app.app_data(Data::new(client)) + .app_data(Data::new(config.oauth_client_info.clone())) } #[cfg(not(feature = "testausid"))] { diff --git a/src/requests.rs b/src/requests.rs index 74d3f47..161d41f 100644 --- a/src/requests.rs +++ b/src/requests.rs @@ -56,8 +56,3 @@ pub struct PasswordChangeRequest { pub old: String, pub new: String, } - -#[derive(Deserialize, Debug)] -pub struct FriendRequest { - pub code: String, -}