Skip to content

Commit

Permalink
/guilds endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
banocean committed Jan 15, 2024
1 parent 1a86d98 commit d29bd2e
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 17 deletions.
6 changes: 6 additions & 0 deletions src/database/redis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,10 @@ impl RedisConnection {
connection.zincr(path, user_id.to_string(), count).await
}

#[cfg(feature = "api")]
pub async fn check_guild(&self, id: Id<GuildMarker>) -> Result<bool, RedisError> {
let count: u8 = self.client.get_async_connection()
.await?.exists(format!("guilds.{id}")).await?;
Ok(count == 1)
}
}
9 changes: 3 additions & 6 deletions src/server/authorize.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
use std::convert::Infallible;
use std::fmt::Display;
use ed25519_dalek::Verifier;
use ed25519_dalek::{PublicKey, Signature};
use std::str::FromStr;
use futures_util::{StreamExt, TryFutureExt, TryStreamExt};
use warp::Filter;
use warp::hyper::body::Bytes;
use warp::path::Exact;
use warp::reject::Reject;
use crate::server::error::{MapErrorIntoInternalRejection, Rejection};
use crate::server::error::Rejection;
use crate::{err, reject, with_value};

pub fn verify_signature(
Expand Down Expand Up @@ -44,7 +40,8 @@ pub fn filter(public_key: PublicKey)
}

async fn f(public_key: PublicKey, timestamp: String, signature: String, body: Bytes) -> Result<(), warp::Rejection> {
let body = String::from_utf8(body.to_vec()).map_rejection()?;
let body = String::from_utf8(body.to_vec())
.map_err(|_| reject!(Rejection::BodyNotConvertableToString))?;

if !verify_signature(
public_key,
Expand Down
30 changes: 20 additions & 10 deletions src/server/error.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,36 @@
use std::convert::Infallible;
use std::fmt::{Debug, Display, Formatter, Pointer, Write};
use std::fmt::{Debug, Display, Formatter, Write};
use reqwest::StatusCode;
use warp::reject::Reject;
use warp::Reply;

#[derive(Debug)]
pub enum Rejection {
#[cfg(feature = "http-interactions")]
BodyNotConvertableToString,
#[cfg(feature = "http-interactions")]
InvalidSignature,
#[cfg(feature = "api")]
InvalidCode,
#[cfg(feature = "api")]
Unauthorized,
#[cfg(feature = "api")]
Internal(anyhow::Error)
}

impl Display for Rejection {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
#[cfg(feature = "http-interactions")]
Rejection::BodyNotConvertableToString => f.write_str("Cannot convert bytes from body into utf8 encoded string"),
#[cfg(feature = "http-interactions")]
Rejection::InvalidSignature => f.write_str("Couldn't verify signature"),
#[cfg(feature = "api")]
Rejection::InvalidCode => f.write_str("Invalid `code` was provided"),
Rejection::Internal(err) => std::fmt::Display::fmt(&err, f)
#[cfg(feature = "api")]
Rejection::Unauthorized => f.write_str("Invalid authorization data provided"),
#[cfg(feature = "api")]
Rejection::Internal(err) => std::fmt::Display::fmt(&err, f),
}?;
Ok(())
}
Expand All @@ -41,11 +53,10 @@ macro_rules! reject {
}

pub trait MapErrorIntoInternalRejection<T> {

fn map_rejection(self) -> Result<T, warp::Rejection>;

}

#[cfg(feature = "api")]
impl<T, E: Into<anyhow::Error>> MapErrorIntoInternalRejection<T> for Result<T, E> where Self: Sized {
fn map_rejection(self) -> Result<T, warp::Rejection> {
self.map_err(|err| reject!(Rejection::Internal(err.into())))
Expand All @@ -54,18 +65,17 @@ impl<T, E: Into<anyhow::Error>> MapErrorIntoInternalRejection<T> for Result<T, E

impl Reject for Rejection {}

// impl Reply for Rejection {
// fn into_response(self) -> Response {
// handle_rejection(self)
// }
// }

pub async fn handle_rejection(rejection: warp::Rejection) -> Result<impl Reply, Infallible> {
Ok(if let Some(rejection) = rejection.find::<Rejection>() {
warp::reply::with_status(rejection.to_string(), match rejection {
#[cfg(feature = "http-interactions")]
Rejection::BodyNotConvertableToString => StatusCode::BAD_REQUEST,
#[cfg(feature = "http-interactions")]
Rejection::InvalidSignature => StatusCode::BAD_REQUEST,
#[cfg(feature = "api")]
Rejection::InvalidCode => StatusCode::BAD_REQUEST,
#[cfg(feature = "api")]
Rejection::Unauthorized => StatusCode::UNAUTHORIZED,
_ => StatusCode::INTERNAL_SERVER_ERROR
})
} else {
Expand Down
Empty file added src/server/routes/guilds/_id.rs
Empty file.
29 changes: 29 additions & 0 deletions src/server/routes/guilds/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use std::sync::Arc;
use futures_util::future::join_all;
use warp::{Filter, Reply};
use crate::context::Context;
use crate::{response_type, with_value};
use crate::server::error::MapErrorIntoInternalRejection;
use crate::server::session::{Authenticator, AuthorizationInformation, authorize_user, Sessions};

mod _id;

pub fn list(context: Arc<Context>, authenticator: Arc<Authenticator>, sessions: Arc<Sessions>) -> response_type!() {
let with_context = with_value!(context);

warp::get()
.and(warp::path("guilds"))
.and(authorize_user(authenticator, sessions))
.and(with_context)
.and_then(run)
}

async fn run(
info: Arc<AuthorizationInformation>,
context: Arc<Context>
) -> Result<impl Reply, warp::Rejection> {
let guilds = info.http.current_user_guilds()
.await.map_rejection()?.model().await.map_rejection()?;
// join_all(guilds.map(|guild| context.redis.)
Ok(warp::reply::json(&guilds))
}
4 changes: 3 additions & 1 deletion src/server/routes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::response_type;
mod interactions;
#[cfg(feature = "api")]
mod login;
mod guilds;

#[cfg(feature = "api")]
mod users {
Expand All @@ -26,7 +27,7 @@ pub fn get_all_routes(

#[cfg(feature = "http-interactions")]
let filter = filter.or(interactions::filter(
discord_http, context, public_key
discord_http, context.to_owned(), public_key
));

#[cfg(feature = "api")]
Expand All @@ -41,6 +42,7 @@ pub fn get_all_routes(
let filter = filter
.or(login::login(authenticator.to_owned(), sessions.to_owned()))
.or(users::me::run(authenticator.to_owned(), sessions.to_owned()))
.or(guilds::list(context, authenticator, sessions));

filter
}

0 comments on commit d29bd2e

Please sign in to comment.