Skip to content

Instantly share code, notes, and snippets.

@lxdlam
Created August 2, 2021 12:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lxdlam/796f7b733226f67798cd81375413e0af to your computer and use it in GitHub Desktop.
Save lxdlam/796f7b733226f67798cd81375413e0af to your computer and use it in GitHub Desktop.
[package]
name = "playground"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = { version = "1.9", features = ["full"] }
thiserror = "1.0"
warp = "0.3"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
jsonwebtoken = "7.2"
use serde::{Serialize, Deserialize};
use jsonwebtoken::{decode, DecodingKey, Validation};
use warp::{Filter, Rejection, reject};
use warp::http::StatusCode;
use std::convert::Infallible;
#[derive(Debug, Serialize, Deserialize)]
struct Claim {
exp: usize,
user_id: usize,
}
#[derive(Debug)]
enum Role {
Admin(String),
User(usize),
Unknown,
}
#[derive(Debug)]
struct Context {
role: Role,
token: String,
}
#[derive(Debug)]
struct Unauthorized;
impl reject::Reject for Unauthorized {}
#[tokio::main]
async fn main() {
let route = warp::path("api").and(extract_context()).and_then(|ctx: Context| async move {
match ctx.role {
Role::Unknown => Err(warp::reject::custom(Unauthorized)),
_ => Ok(ctx),
}
}).map(|ctx: Context| {
println!("{:?}", ctx);
warp::reply::with_status("Welcome to otogame", StatusCode::OK)
}).recover(|err: Rejection| async move {
if let Some(_) = err.find::<Unauthorized>() {
Ok::<_, Infallible>(warp::reply::with_status("UNAUTHORIZED", StatusCode::UNAUTHORIZED))
} else {
Ok::<_, Infallible>(warp::reply::with_status("INTERNAL_SERVER_ERROR", StatusCode::INTERNAL_SERVER_ERROR))
}
});
warp::serve(route).run(([127, 0, 0, 1], 3030)).await;
}
fn extract_context() -> impl Filter<Extract=(Context, ), Error=Rejection> + Copy {
warp::header::<String>("Authorization").map(|token: String| {
if token.starts_with("admin") {
if let Some(name) = token.split("-").skip(1).next() {
return Context {
role: Role::Admin(String::from(name)),
token: "".to_string(),
};
}
} else {
if let Ok(jwt) = decode::<Claim>(&token, &DecodingKey::from_secret("".as_ref()), &Validation::default()) {
return Context {
role: Role::User(jwt.claims.user_id),
token: token.clone(),
};
}
}
Context {
role: Role::Unknown,
token: "".to_string(),
}
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment