diff --git a/src/api/v1/servers/mod.rs b/src/api/v1/servers/mod.rs index 9a933f7..2cdd2e0 100644 --- a/src/api/v1/servers/mod.rs +++ b/src/api/v1/servers/mod.rs @@ -1,4 +1,4 @@ -use actix_web::{error, post, web, Error, HttpRequest, HttpResponse, Scope}; +use actix_web::{error, post, web, Error, HttpResponse, Scope}; use futures::StreamExt; use log::error; use serde::{Deserialize, Serialize}; @@ -7,10 +7,11 @@ use std::time::{SystemTime, UNIX_EPOCH}; mod uuid; -use crate::{api::v1::auth::check_access_token, utils::get_auth_header, Data}; +use crate::{api::v1::auth::check_access_token, Data}; #[derive(Deserialize)] struct Request { + access_token: String, name: String, description: Option, } @@ -37,25 +38,8 @@ pub fn web() -> Scope { } #[post("")] -pub async fn res(req: HttpRequest, mut payload: web::Payload, data: web::Data) -> Result { - let headers = req.headers(); - - let auth_header = get_auth_header(headers); - - if let Err(error) = auth_header { - return Ok(error) - } - - let authorized = check_access_token(auth_header.unwrap(), &data.pool).await; - - if let Err(error) = authorized { - return Ok(error) - } - - let uuid = authorized.unwrap(); - +pub async fn res(mut payload: web::Payload, data: web::Data) -> Result { let mut body = web::BytesMut::new(); - while let Some(chunk) = payload.next().await { let chunk = chunk?; // limit max size of in-memory payload @@ -67,6 +51,14 @@ pub async fn res(req: HttpRequest, mut payload: web::Payload, data: web::Data(&body)?; + let authorized = check_access_token(request.access_token, &data.pool).await; + + if let Err(error) = authorized { + return Ok(error) + } + + let uuid = authorized.unwrap(); + let guild_uuid = Uuid::now_v7(); let row = sqlx::query(&format!("INSERT INTO guilds (uuid, owner_uuid, name, description) VALUES ('{}', '{}', $1, $2)", guild_uuid, uuid)) diff --git a/src/api/v1/servers/uuid/mod.rs b/src/api/v1/servers/uuid/mod.rs index 022f0da..02ad3a1 100644 --- a/src/api/v1/servers/uuid/mod.rs +++ b/src/api/v1/servers/uuid/mod.rs @@ -1,13 +1,19 @@ -use actix_web::{get, web, Error, HttpRequest, HttpResponse, Scope}; +use actix_web::{error, post, web, Error, HttpResponse, Scope}; +use futures::StreamExt; use log::error; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use sqlx::FromRow; use uuid::Uuid; use std::str::FromStr; mod channels; -use crate::{api::v1::auth::check_access_token, utils::get_auth_header, Data}; +use crate::{api::v1::auth::check_access_token, Data}; + +#[derive(Deserialize)] +struct Request { + access_token: String, +} #[derive(Serialize)] struct Response { @@ -29,25 +35,31 @@ struct Role { permissions: i64, } +const MAX_SIZE: usize = 262_144; + pub fn web() -> Scope { web::scope("/") .service(res) .service(channels::web()) } -#[get("{uuid}")] -pub async fn res(req: HttpRequest, path: web::Path<(Uuid,)>, data: web::Data) -> Result { - let headers = req.headers(); - - let auth_header = get_auth_header(headers); - - if let Err(error) = auth_header { - return Ok(error) +#[post("{uuid}")] +pub async fn res(mut payload: web::Payload, path: web::Path<(Uuid,)>, data: web::Data) -> Result { + let mut body = web::BytesMut::new(); + while let Some(chunk) = payload.next().await { + let chunk = chunk?; + // limit max size of in-memory payload + if (body.len() + chunk.len()) > MAX_SIZE { + return Err(error::ErrorBadRequest("overflow")); + } + body.extend_from_slice(&chunk); } let guild_uuid = path.into_inner().0; - let authorized = check_access_token(auth_header.unwrap(), &data.pool).await; + let request = serde_json::from_slice::(&body)?; + + let authorized = check_access_token(request.access_token, &data.pool).await; if let Err(error) = authorized { return Ok(error)