-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from daystram/dev
- Loading branch information
Showing
44 changed files
with
1,354 additions
and
231 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
HOST=localhost | ||
PORT=9090 | ||
ENVIRONMENT=development | ||
|
||
OAUTH_ISSUER=https://ratify.daystram.com | ||
CLIENT_SECRET=ratify_client_secret | ||
|
||
REDIS_HOST=localhost | ||
REDIS_PORT=6379 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
pub const VARIANT_SNIPPET: &str = "snippet"; | ||
pub const VARIANT_URL: &str = "url"; | ||
|
||
pub const HASH_LENGTH: usize = 8; |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
pub mod middlewares; | ||
pub mod v1; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
use crate::app::{ | ||
constants, | ||
datatransfers::{ | ||
auth::TokenInfo, | ||
cut::{CreateResponse, Cut}, | ||
}, | ||
handlers, Module, | ||
}; | ||
use crate::core::error::HandlerErrorKind; | ||
use actix_web::{get, post, web, HttpRequest, HttpResponse, Responder}; | ||
|
||
#[get("/{id}")] | ||
pub async fn get_cut_raw(m: web::Data<Module>, req: HttpRequest) -> impl Responder { | ||
let id: String = req.match_info().query("id").parse().unwrap(); | ||
match handlers::cut::get_one(m, id) { | ||
Ok(cut) => match cut.variant.as_str() { | ||
constants::VARIANT_SNIPPET => HttpResponse::Ok().body(cut.data), | ||
constants::VARIANT_URL => HttpResponse::TemporaryRedirect() | ||
.header("Location", cut.data) | ||
.finish(), | ||
_ => HttpResponse::NotFound().finish(), | ||
}, | ||
Err(e) => match e.kind { | ||
HandlerErrorKind::CutNotFoundError => HttpResponse::NotFound().finish(), | ||
_ => HttpResponse::InternalServerError().body(format!("{:?}", e)), | ||
}, | ||
} | ||
} | ||
|
||
#[get("/{id}")] | ||
pub async fn get_cut(m: web::Data<Module>, req: HttpRequest) -> impl Responder { | ||
let id: String = req.match_info().query("id").parse().unwrap(); | ||
match handlers::cut::get_one(m, id) { | ||
Ok(cut) => HttpResponse::Ok().json(cut), | ||
Err(e) => match e.kind { | ||
HandlerErrorKind::CutNotFoundError => HttpResponse::NotFound().finish(), | ||
_ => HttpResponse::InternalServerError().body(format!("{:?}", e)), | ||
}, | ||
} | ||
} | ||
|
||
#[post("")] | ||
pub async fn post_snippet_create( | ||
m: web::Data<Module>, | ||
cut: web::Json<Cut>, | ||
req: HttpRequest, | ||
) -> impl Responder { | ||
let user: TokenInfo = match handlers::auth::authorize(&m, &req).await { | ||
Ok(resp) => resp, | ||
Err(e) => match e.kind { | ||
HandlerErrorKind::UnauthorizedError => return HttpResponse::Unauthorized().finish(), | ||
_ => return HttpResponse::InternalServerError().finish(), | ||
}, | ||
}; | ||
match cut.variant.as_str() { | ||
constants::VARIANT_SNIPPET => (), | ||
constants::VARIANT_URL => (), | ||
_ => return HttpResponse::BadRequest().finish(), | ||
}; | ||
match handlers::cut::insert(m, user.sub, cut.0) { | ||
Ok(hash) => HttpResponse::Ok().json(CreateResponse { hash: hash }), | ||
Err(e) => HttpResponse::InternalServerError().body(format!("{:?}", e)), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
pub mod cut; | ||
pub mod ping; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
use actix_web::{get, HttpResponse, Responder}; | ||
|
||
#[get("")] | ||
pub async fn get_ping() -> impl Responder { | ||
HttpResponse::Ok().body("Pong!") | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
use serde::{Deserialize, Serialize}; | ||
|
||
#[derive(Debug, Serialize, Deserialize)] | ||
pub struct TokenInfo { | ||
pub active: bool, | ||
#[serde(default)] | ||
pub sub: String, | ||
#[serde(default)] | ||
pub client_id: String, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
use serde::{Deserialize, Serialize}; | ||
|
||
#[derive(Debug, Serialize, Deserialize)] | ||
pub struct Cut { | ||
pub name: String, | ||
#[serde(skip)] | ||
pub owner: String, | ||
pub variant: String, | ||
pub metadata: String, | ||
pub data: String, | ||
#[serde(skip_deserializing)] | ||
pub created_at: u64, | ||
} | ||
|
||
#[derive(Debug, Serialize, Deserialize)] | ||
pub struct CreateResponse { | ||
pub hash: String, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
pub mod auth; | ||
pub mod cut; |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
use crate::app::{datatransfers::auth::TokenInfo, Module}; | ||
use crate::core::error::{HandlerError, HandlerErrorKind}; | ||
use actix_web::{client::Client, web, HttpRequest}; | ||
|
||
pub async fn authorize(m: &web::Data<Module>, req: &HttpRequest) -> Result<TokenInfo, HandlerError> { | ||
let access_token: &str = match req.headers().get("Authorization") { | ||
Some(header_value) => match header_value.to_str() { | ||
Ok(access_token) => access_token.strip_prefix("Bearer ").unwrap_or_else(|| access_token), | ||
Err(_) => return Err(HandlerErrorKind::GeneralError.into()), | ||
}, | ||
_ => return Err(HandlerErrorKind::UnauthorizedError.into()), | ||
}; | ||
match Client::default() | ||
.post(format!("{}/oauth/introspect", m.config.oauth_issuer)) | ||
.header("Content-Type", "application/x-www-form-urlencoded") | ||
.send_body(format!( | ||
"token={}&client_id={}&client_secret={}&token_type_hint=access_token", | ||
access_token, m.config.client_id, m.config.client_secret | ||
)) | ||
.await | ||
{ | ||
Ok(mut res) => match res.json::<TokenInfo>().await { | ||
Ok(token_info) => match token_info.active { | ||
true => Ok(token_info), | ||
false => Err(HandlerErrorKind::UnauthorizedError.into()), | ||
}, | ||
Err(_) => Err(HandlerErrorKind::UnauthorizedError.into()), | ||
}, | ||
Err(_) => Err(HandlerErrorKind::GeneralError.into()), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
use crate::app::{constants::HASH_LENGTH, datatransfers::cut::Cut, Module}; | ||
use crate::core::error::{HandlerError, HandlerErrorKind}; | ||
use crate::utils::hash; | ||
use actix_web::web; | ||
use r2d2_redis::redis::Commands; | ||
use std::{ | ||
collections::HashMap, | ||
time::{SystemTime, UNIX_EPOCH}, | ||
}; | ||
|
||
pub fn get_one(m: web::Data<Module>, id: String) -> Result<Cut, HandlerError> { | ||
let rd = &mut m.rd_pool.get()?; | ||
match rd.hgetall::<String, HashMap<String, String>>(id) { | ||
Ok(res) => { | ||
if res.is_empty() { | ||
return Err(HandlerErrorKind::CutNotFoundError.into()); | ||
} | ||
Ok(Cut { | ||
name: res | ||
.get("name") | ||
.ok_or(HandlerErrorKind::CutNotFoundError)? | ||
.to_string(), | ||
owner: res | ||
.get("owner") | ||
.ok_or(HandlerErrorKind::CutNotFoundError)? | ||
.to_string(), | ||
variant: res | ||
.get("variant") | ||
.ok_or(HandlerErrorKind::CutNotFoundError)? | ||
.to_string(), | ||
metadata: res | ||
.get("metadata") | ||
.ok_or(HandlerErrorKind::CutNotFoundError)? | ||
.to_string(), | ||
data: res | ||
.get("data") | ||
.ok_or(HandlerErrorKind::CutNotFoundError)? | ||
.to_string(), | ||
created_at: res | ||
.get("created_at") | ||
.ok_or(HandlerErrorKind::CutNotFoundError)? | ||
.parse()?, | ||
}) | ||
} | ||
Err(e) => Err(e.into()), | ||
} | ||
} | ||
|
||
pub fn insert( | ||
m: web::Data<Module>, | ||
user_subject: String, | ||
cut: Cut, | ||
) -> Result<String, HandlerError> { | ||
let rd = &mut m.rd_pool.get()?; | ||
let hash: String = hash::generate(HASH_LENGTH).into(); | ||
let created_at = match SystemTime::now().duration_since(UNIX_EPOCH) { | ||
Ok(duration) => duration.as_secs(), | ||
Err(_) => return Err(HandlerErrorKind::GeneralError.into()), | ||
}; | ||
match rd.hset_multiple::<String, &str, String, String>( | ||
hash.clone(), | ||
&[ | ||
("name", cut.name), | ||
("owner", user_subject), | ||
("variant", cut.variant), | ||
("metadata", cut.metadata), | ||
("data", cut.data), | ||
("created_at", created_at.to_string()), | ||
], | ||
) { | ||
Ok(_) => Ok(hash), | ||
Err(e) => Err(e.into()), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
pub mod auth; | ||
pub mod cut; |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
use crate::core::config; | ||
use actix_web::{middleware::Logger, App, HttpServer}; | ||
use r2d2::Pool; | ||
use r2d2_redis::RedisConnectionManager; | ||
|
||
pub mod constants; | ||
pub mod controllers; | ||
pub mod datatransfers; | ||
pub mod handlers; | ||
pub mod router; | ||
|
||
pub struct Module { | ||
pub config: config::AppConfig, | ||
pub rd_pool: r2d2::Pool<RedisConnectionManager>, | ||
} | ||
|
||
pub async fn start() -> std::io::Result<()> { | ||
// init AppConfig | ||
let config = config::init(); | ||
|
||
// init Redis | ||
let rd_manager = RedisConnectionManager::new(format!( | ||
"redis://{}:{}/", | ||
config.redis_host, config.redis_port | ||
)) | ||
.unwrap(); | ||
let rd_pool = Pool::builder().max_size(15).build(rd_manager).unwrap(); | ||
log::info!("[INIT] Redis initialized!"); | ||
|
||
// run server | ||
HttpServer::new(move || { | ||
App::new() | ||
.data(Module { | ||
config: config.clone(), | ||
rd_pool: rd_pool.clone(), | ||
}) | ||
.wrap(Logger::default()) | ||
.configure(router::init) | ||
}) | ||
.bind(format!( | ||
"{}:{}", | ||
std::env::var("HOST").expect("HOST is required"), | ||
std::env::var("PORT").expect("PORT is required") | ||
))? | ||
.run() | ||
.await | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
use crate::app::controllers::v1; | ||
use actix_web::web; | ||
|
||
pub fn init(app: &mut web::ServiceConfig) { | ||
app.service(web::scope("/raw").service(v1::cut::get_cut_raw)) | ||
.service( | ||
web::scope("/api/v1") | ||
.service(web::scope("/ping").service(v1::ping::get_ping)) | ||
.service( | ||
web::scope("/cut") | ||
.service(v1::cut::get_cut) | ||
.service(v1::cut::post_snippet_create), | ||
), | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
use std::env; | ||
|
||
#[derive(Clone)] | ||
pub struct AppConfig { | ||
pub oauth_issuer: String, | ||
pub client_id: String, | ||
pub client_secret: String, | ||
pub redis_host: String, | ||
pub redis_port: String, | ||
} | ||
|
||
pub fn init() -> AppConfig { | ||
return AppConfig { | ||
oauth_issuer: env::var("OAUTH_ISSUER").expect("OAUTH_ISSUER is required"), | ||
client_id: env::var("CLIENT_ID").expect("CLIENT_ID is required"), | ||
client_secret: env::var("CLIENT_SECRET").expect("CLIENT_SECRET is required"), | ||
redis_host: env::var("REDIS_HOST").expect("REDIS_HOST is required"), | ||
redis_port: env::var("REDIS_PORT").expect("REDIS_PORT is required"), | ||
}; | ||
} |
Oops, something went wrong.