Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

Commit

Permalink
Fix payouts desync (#890)
Browse files Browse the repository at this point in the history
* Fix payouts desync

* fix tests + user payouts req
  • Loading branch information
Geometrically authored Mar 12, 2024
1 parent e2ffeab commit f8f0371
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 54 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 12 additions & 6 deletions src/queue/payouts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<i64, Decimal> = HashMap::new();
for (id, project) in projects_map {
if let Some(value) = &multipliers.values.get(&(id as u64)) {
let project_multiplier: Decimal =
Expand All @@ -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);
}
Expand All @@ -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?;

Expand Down
46 changes: 13 additions & 33 deletions src/routes/v3/oauth_clients.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -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;
Expand Down Expand Up @@ -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(&current_user))?;

let response = clients
.into_iter()
Expand All @@ -98,13 +100,10 @@ pub async fn get_user_clients(

#[get("app/{id}")]
pub async fn get_client(
req: HttpRequest,
id: web::Path<ApiOAuthClientId>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
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 {
Expand All @@ -114,19 +113,16 @@ pub async fn get_client(

#[get("apps")]
pub async fn get_clients(
req: HttpRequest,
info: web::Query<GetOAuthClientsRequest>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
let ids: Vec<_> = info
.ids
.iter()
.map(|id| parse_base62(id).map(ApiOAuthClientId))
.collect::<Result<_, _>>()?;

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))
}
Expand Down Expand Up @@ -583,26 +579,10 @@ async fn edit_redirects(

pub async fn get_clients_inner(
ids: &[ApiOAuthClientId],
req: HttpRequest,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<Vec<models::oauth_clients::OAuthClient>, ApiError> {
let current_user = get_user_from_headers(
&req,
&**pool,
&redis,
&session_queue,
Some(&[Scopes::SESSION_ACCESS]),
)
.await?
.1;

let ids: Vec<OAuthClientId> = ids.iter().map(|i| (*i).into()).collect();
let clients = OAuthClient::get_many(&ids, &**pool).await?;
clients
.iter()
.validate_all_authorized(Some(&current_user))?;

Ok(clients.into_iter().map(|c| c.into()).collect_vec())
}
15 changes: 0 additions & 15 deletions tests/oauth_clients.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ApiV3>| 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<ApiV3>| async move {
Expand Down

0 comments on commit f8f0371

Please sign in to comment.