Replaces actix with axum for web, allows us to use socket.io and gives us access to the tower ecosystem of middleware breaks compatibility with our current websocket implementation, needs to be reimplemented for socket.io
149 lines
4.1 KiB
Rust
149 lines
4.1 KiB
Rust
//! `/api/v1/guilds/{uuid}` Specific server endpoints
|
|
|
|
use std::sync::Arc;
|
|
|
|
use axum::{
|
|
Json, Router,
|
|
extract::{Multipart, Path, State},
|
|
http::StatusCode,
|
|
response::IntoResponse,
|
|
routing::{get, patch, post},
|
|
};
|
|
use axum_extra::{
|
|
TypedHeader,
|
|
headers::{Authorization, authorization::Bearer},
|
|
};
|
|
use bytes::Bytes;
|
|
use uuid::Uuid;
|
|
|
|
mod channels;
|
|
mod invites;
|
|
mod members;
|
|
mod roles;
|
|
|
|
use crate::{
|
|
AppState,
|
|
api::v1::auth::check_access_token,
|
|
error::Error,
|
|
objects::{Guild, Member, Permissions},
|
|
utils::global_checks,
|
|
};
|
|
|
|
pub fn router() -> Router<Arc<AppState>> {
|
|
Router::new()
|
|
// Servers
|
|
.route("/", get(get_guild))
|
|
.route("/", patch(edit))
|
|
// Channels
|
|
.route("/channels", get(channels::get))
|
|
.route("/channels", post(channels::create))
|
|
// Roles
|
|
.route("/roles", get(roles::get))
|
|
.route("/roles", post(roles::create))
|
|
.route("/roles/{role_uuid}", get(roles::uuid::get))
|
|
// Invites
|
|
.route("/invites", get(invites::get))
|
|
.route("/invites", post(invites::create))
|
|
// Members
|
|
.route("/members", get(members::get))
|
|
}
|
|
|
|
/// `GET /api/v1/guilds/{uuid}` DESCRIPTION
|
|
///
|
|
/// requires auth: yes
|
|
///
|
|
/// ### Response Example
|
|
/// ```
|
|
/// json!({
|
|
/// "uuid": "5ba61ec7-5f97-43e1-89a5-d4693c155612",
|
|
/// "name": "My first server!",
|
|
/// "description": "This is a cool and nullable description!",
|
|
/// "icon": "https://nullable-url/path/to/icon.png",
|
|
/// "owner_uuid": "155d2291-fb23-46bd-a656-ae7c5d8218e6",
|
|
/// "roles": [
|
|
/// {
|
|
/// "uuid": "be0e4da4-cf73-4f45-98f8-bb1c73d1ab8b",
|
|
/// "guild_uuid": "5ba61ec7-5f97-43e1-89a5-d4693c155612",
|
|
/// "name": "Cool people",
|
|
/// "color": 15650773,
|
|
/// "is_above": c7432f1c-f4ad-4ad3-8216-51388b6abb5b,
|
|
/// "permissions": 0
|
|
/// }
|
|
/// {
|
|
/// "uuid": "c7432f1c-f4ad-4ad3-8216-51388b6abb5b",
|
|
/// "guild_uuid": "5ba61ec7-5f97-43e1-89a5-d4693c155612",
|
|
/// "name": "Equally cool people",
|
|
/// "color": 16777215,
|
|
/// "is_above": null,
|
|
/// "permissions": 0
|
|
/// }
|
|
/// ],
|
|
/// "member_count": 20
|
|
/// });
|
|
/// ```
|
|
pub async fn get_guild(
|
|
State(app_state): State<Arc<AppState>>,
|
|
Path(guild_uuid): Path<Uuid>,
|
|
TypedHeader(auth): TypedHeader<Authorization<Bearer>>,
|
|
) -> Result<impl IntoResponse, Error> {
|
|
let mut conn = app_state.pool.get().await?;
|
|
|
|
let uuid = check_access_token(auth.token(), &mut conn).await?;
|
|
|
|
global_checks(&app_state, uuid).await?;
|
|
|
|
Member::check_membership(&mut conn, uuid, guild_uuid).await?;
|
|
|
|
let guild = Guild::fetch_one(&mut conn, guild_uuid).await?;
|
|
|
|
Ok((StatusCode::OK, Json(guild)))
|
|
}
|
|
|
|
/// `PATCH /api/v1/guilds/{uuid}` change guild settings
|
|
///
|
|
/// requires auth: yes
|
|
pub async fn edit(
|
|
State(app_state): State<Arc<AppState>>,
|
|
Path(guild_uuid): Path<Uuid>,
|
|
TypedHeader(auth): TypedHeader<Authorization<Bearer>>,
|
|
mut multipart: Multipart,
|
|
) -> Result<impl IntoResponse, Error> {
|
|
let mut conn = app_state.pool.get().await?;
|
|
|
|
let uuid = check_access_token(auth.token(), &mut conn).await?;
|
|
|
|
global_checks(&app_state, uuid).await?;
|
|
|
|
let member = Member::check_membership(&mut conn, uuid, guild_uuid).await?;
|
|
|
|
member
|
|
.check_permission(&app_state, Permissions::ManageGuild)
|
|
.await?;
|
|
|
|
let mut guild = Guild::fetch_one(&mut conn, guild_uuid).await?;
|
|
|
|
let mut icon: Option<Bytes> = None;
|
|
|
|
while let Some(field) = multipart.next_field().await.unwrap() {
|
|
let name = field
|
|
.name()
|
|
.ok_or(Error::BadRequest("Field has no name".to_string()))?;
|
|
|
|
if name == "icon" {
|
|
icon = Some(field.bytes().await?);
|
|
}
|
|
}
|
|
|
|
if let Some(icon) = icon {
|
|
guild
|
|
.set_icon(
|
|
&app_state.bunny_storage,
|
|
&mut conn,
|
|
app_state.config.bunny.cdn_url.clone(),
|
|
icon,
|
|
)
|
|
.await?;
|
|
}
|
|
|
|
Ok(StatusCode::OK)
|
|
}
|