diff --git a/.sqlx/query-e1c24a57013cbc64f463d3a49cb68989eced49b475c0bbab90b21908ae0e77b4.json b/.sqlx/query-e1c24a57013cbc64f463d3a49cb68989eced49b475c0bbab90b21908ae0e77b4.json new file mode 100644 index 000000000..dc23d4e2b --- /dev/null +++ b/.sqlx/query-e1c24a57013cbc64f463d3a49cb68989eced49b475c0bbab90b21908ae0e77b4.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "\n UPDATE users u\n SET balance = u.balance + v.amount\n FROM unnest($1::BIGINT[], $2::NUMERIC[]) AS v(id, amount)\n WHERE u.id = v.id\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8Array", + "NumericArray" + ] + }, + "nullable": [] + }, + "hash": "e1c24a57013cbc64f463d3a49cb68989eced49b475c0bbab90b21908ae0e77b4" +} diff --git a/src/queue/payouts.rs b/src/queue/payouts.rs index 301f94351..eed9079e4 100644 --- a/src/queue/payouts.rs +++ b/src/queue/payouts.rs @@ -726,7 +726,7 @@ pub async fn process_payout( let mut clear_cache_users = Vec::new(); let (mut insert_user_ids, mut insert_project_ids, mut insert_payouts, mut insert_starts) = (Vec::new(), Vec::new(), Vec::new(), Vec::new()); - let (mut update_user_ids, mut update_user_balances) = (Vec::new(), Vec::new()); + let mut update_user_balance: HashMap = HashMap::new(); for (id, project) in projects_map { if let Some(value) = &multipliers.values.get(&(id as u64)) { let project_multiplier: Decimal = @@ -744,8 +744,7 @@ pub async fn process_payout( insert_payouts.push(payout); insert_starts.push(start); - update_user_ids.push(user_id); - update_user_balances.push(payout); + *update_user_balance.entry(user_id).or_default() += payout; clear_cache_users.push(user_id); } @@ -754,16 +753,23 @@ pub async fn process_payout( } } - sqlx::query( + let (mut update_user_ids, mut update_user_balances) = (Vec::new(), Vec::new()); + + for (user_id, payout) in update_user_balance { + update_user_ids.push(user_id); + update_user_balances.push(payout); + } + + sqlx::query!( " UPDATE users u SET balance = u.balance + v.amount FROM unnest($1::BIGINT[], $2::NUMERIC[]) AS v(id, amount) WHERE u.id = v.id ", + &update_user_ids, + &update_user_balances ) - .bind(&update_user_ids) - .bind(&update_user_balances) .execute(&mut *transaction) .await?; diff --git a/src/routes/v3/oauth_clients.rs b/src/routes/v3/oauth_clients.rs index 03e50b9cb..32cec006b 100644 --- a/src/routes/v3/oauth_clients.rs +++ b/src/routes/v3/oauth_clients.rs @@ -14,12 +14,6 @@ use sqlx::PgPool; use validator::Validate; use super::ApiError; -use crate::{ - auth::checks::ValidateAllAuthorized, - file_hosting::FileHost, - models::{ids::base62_impl::parse_base62, oauth_clients::DeleteOAuthClientQueryParam}, - util::routes::read_from_payload, -}; use crate::{ auth::{checks::ValidateAuthorized, get_user_from_headers}, database::{ @@ -40,6 +34,11 @@ use crate::{ routes::v3::project_creation::CreateError, util::validate::validation_errors_to_string, }; +use crate::{ + file_hosting::FileHost, + models::{ids::base62_impl::parse_base62, oauth_clients::DeleteOAuthClientQueryParam}, + util::routes::read_from_payload, +}; use crate::database::models::oauth_client_item::OAuthClient as DBOAuthClient; use crate::models::ids::OAuthClientId as ApiOAuthClientId; @@ -80,10 +79,13 @@ pub async fn get_user_clients( let target_user = User::get(&info.into_inner(), &**pool, &redis).await?; if let Some(target_user) = target_user { + if target_user.id != current_user.id.into() && !current_user.role.is_admin() { + return Err(ApiError::CustomAuthentication( + "You do not have permission to see the OAuth clients of this user!".to_string(), + )); + } + let clients = OAuthClient::get_all_user_clients(target_user.id, &**pool).await?; - clients - .iter() - .validate_all_authorized(Some(¤t_user))?; let response = clients .into_iter() @@ -98,13 +100,10 @@ pub async fn get_user_clients( #[get("app/{id}")] pub async fn get_client( - req: HttpRequest, id: web::Path, pool: web::Data, - redis: web::Data, - session_queue: web::Data, ) -> Result { - let clients = get_clients_inner(&[id.into_inner()], req, pool, redis, session_queue).await?; + let clients = get_clients_inner(&[id.into_inner()], pool).await?; if let Some(client) = clients.into_iter().next() { Ok(HttpResponse::Ok().json(client)) } else { @@ -114,11 +113,8 @@ pub async fn get_client( #[get("apps")] pub async fn get_clients( - req: HttpRequest, info: web::Query, pool: web::Data, - redis: web::Data, - session_queue: web::Data, ) -> Result { let ids: Vec<_> = info .ids @@ -126,7 +122,7 @@ pub async fn get_clients( .map(|id| parse_base62(id).map(ApiOAuthClientId)) .collect::>()?; - let clients = get_clients_inner(&ids, req, pool, redis, session_queue).await?; + let clients = get_clients_inner(&ids, pool).await?; Ok(HttpResponse::Ok().json(clients)) } @@ -583,26 +579,10 @@ async fn edit_redirects( pub async fn get_clients_inner( ids: &[ApiOAuthClientId], - req: HttpRequest, pool: web::Data, - redis: web::Data, - session_queue: web::Data, ) -> Result, ApiError> { - let current_user = get_user_from_headers( - &req, - &**pool, - &redis, - &session_queue, - Some(&[Scopes::SESSION_ACCESS]), - ) - .await? - .1; - let ids: Vec = ids.iter().map(|i| (*i).into()).collect(); let clients = OAuthClient::get_many(&ids, &**pool).await?; - clients - .iter() - .validate_all_authorized(Some(¤t_user))?; Ok(clients.into_iter().map(|c| c.into()).collect_vec()) } diff --git a/tests/oauth_clients.rs b/tests/oauth_clients.rs index 75257a69c..7bed86d56 100644 --- a/tests/oauth_clients.rs +++ b/tests/oauth_clients.rs @@ -112,21 +112,6 @@ async fn get_oauth_client_for_client_creator_succeeds() { .await; } -#[actix_rt::test] -async fn get_oauth_client_for_unrelated_user_fails() { - with_test_environment(None, |env: TestEnvironment| async move { - let DummyOAuthClientAlpha { client_id, .. } = env.dummy.oauth_client_alpha.clone(); - - let resp = env - .api - .get_oauth_client(client_id.clone(), FRIEND_USER_PAT) - .await; - - assert_status!(&resp, StatusCode::UNAUTHORIZED); - }) - .await; -} - #[actix_rt::test] async fn can_delete_oauth_client() { with_test_environment(None, |env: TestEnvironment| async move {