added validation to the required subscription parameters

This commit is contained in:
Gonçalo Valério 2019-06-30 21:19:26 +01:00
parent 567201d362
commit c90438d667
4 changed files with 436 additions and 295 deletions

582
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,3 @@
pub fn create_subscription() {} use url::form_urlencoded::Parse;
pub fn remove_subscription() {} pub fn handle_subscription(data: Parse) {}

View File

@ -1,14 +1,15 @@
use actions::{create_subscription, remove_subscription}; use actions::handle_subscription;
use actix_web::{http, web, HttpRequest, HttpResponse}; use actix_web::{http, web, HttpRequest, HttpResponse};
use askama::Template; use askama::Template;
use url::form_urlencoded; use url::form_urlencoded;
use utils::{validate_parsed_data, AppState}; use utils::{validate_parsed_data, AppState};
use std::collections::HashMap;
#[derive(Template)] #[derive(Template)]
#[template(path = "index.html")] #[template(path = "index.html")]
struct IndexView; struct IndexView;
pub fn index(state: web::Data<AppState>, _req: HttpRequest) -> HttpResponse { pub fn index(_state: web::Data<AppState>, _req: HttpRequest) -> HttpResponse {
HttpResponse::Ok() HttpResponse::Ok()
.content_type("text/html") .content_type("text/html")
.body(IndexView.render().unwrap()) .body(IndexView.render().unwrap())
@ -18,15 +19,23 @@ pub fn hub(state: web::Data<AppState>, _req: HttpRequest, params: String) -> Htt
let log = &state.log; let log = &state.log;
info!(log, "Received Request"); info!(log, "Received Request");
debug!(log, "Content: {}", params); debug!(log, "Content: {}", params);
let parsed_data = form_urlencoded::parse(params.as_bytes());
if !validate_parsed_data(parsed_data) { let parsed_data = form_urlencoded::parse(params.as_bytes());
let mut parameters = HashMap::new();
for (key, value) in parsed_data {
parameters.insert(key.to_string(), value.to_string());
}
if !validate_parsed_data(parameters) {
return HttpResponse::Ok() return HttpResponse::Ok()
.status(http::StatusCode::from_u16(400).unwrap()) .status(http::StatusCode::BAD_REQUEST)
.finish(); .finish();
} }
HttpResponse::Ok().body("Hello World!") handle_subscription(parsed_data);
return HttpResponse::Ok()
.status(http::StatusCode::ACCEPTED)
.finish();
} }
#[cfg(test)] #[cfg(test)]
@ -54,7 +63,7 @@ mod tests {
} }
#[test] #[test]
fn test_hub() { fn test_hub_no_parameters() {
let _sys = System::new("rusty-hub-test"); let _sys = System::new("rusty-hub-test");
let addr = SyncArbiter::start(1, || { let addr = SyncArbiter::start(1, || {
DbExecutor(SqliteConnection::establish("test.db").unwrap()) DbExecutor(SqliteConnection::establish("test.db").unwrap())
@ -72,4 +81,85 @@ mod tests {
); );
assert_eq!(resp.status(), http::StatusCode::BAD_REQUEST); assert_eq!(resp.status(), http::StatusCode::BAD_REQUEST);
} }
#[test]
fn test_hub_invalid_callback() {
let _sys = System::new("rusty-hub-test");
let addr = SyncArbiter::start(1, || {
DbExecutor(SqliteConnection::establish("test.db").unwrap())
});
let data = web::Data::new(AppState {
log: setup_logging(),
db: addr.clone(),
});
let resp = hub(
data,
test::TestRequest::post().to_http_request(),
"hub.mode=subscribe&hub.callback=none&hub.topic=http://example.com".to_string(),
);
assert_eq!(resp.status(), http::StatusCode::BAD_REQUEST);
}
#[test]
fn test_hub_invalid_topic() {
let _sys = System::new("rusty-hub-test");
let addr = SyncArbiter::start(1, || {
DbExecutor(SqliteConnection::establish("test.db").unwrap())
});
let data = web::Data::new(AppState {
log: setup_logging(),
db: addr.clone(),
});
let resp = hub(
data,
test::TestRequest::post().to_http_request(),
"hub.mode=subscribe&hub.callback=http://example.com&hub.topic=none".to_string(),
);
assert_eq!(resp.status(), http::StatusCode::BAD_REQUEST);
}
#[test]
fn test_hub_invalid_mode() {
let _sys = System::new("rusty-hub-test");
let addr = SyncArbiter::start(1, || {
DbExecutor(SqliteConnection::establish("test.db").unwrap())
});
let data = web::Data::new(AppState {
log: setup_logging(),
db: addr.clone(),
});
let resp = hub(
data,
test::TestRequest::post().to_http_request(),
"hub.mode=none&hub.callback=http://example.com&hub.topic=http://other.com".to_string(),
);
assert_eq!(resp.status(), http::StatusCode::BAD_REQUEST);
}
#[test]
fn test_hub_subscribe_success() {
let _sys = System::new("rusty-hub-test");
let addr = SyncArbiter::start(1, || {
DbExecutor(SqliteConnection::establish("test.db").unwrap())
});
let data = web::Data::new(AppState {
log: setup_logging(),
db: addr.clone(),
});
let resp = hub(
data,
test::TestRequest::post().to_http_request(),
"hub.mode=subscribe&hub.callback=http://example.com&hub.topic=http://other.com"
.to_string(),
);
assert_eq!(resp.status(), http::StatusCode::ACCEPTED);
}
} }

View File

@ -1,7 +1,9 @@
use actix::{Actor, Addr, SyncContext}; use actix::{Actor, Addr, SyncContext};
use diesel::prelude::*; use diesel::prelude::*;
use slog::Drain; use slog::Drain;
use url::form_urlencoded::Parse;
use std::collections::HashMap;
use url::Url;
pub struct DbExecutor(pub SqliteConnection); pub struct DbExecutor(pub SqliteConnection);
@ -21,6 +23,39 @@ pub fn setup_logging() -> slog::Logger {
slog::Logger::root(drain, o!()) slog::Logger::root(drain, o!())
} }
pub fn validate_parsed_data(data: Parse) -> bool { pub fn validate_parsed_data(parameters: HashMap<String,String>) -> bool {
false let callback;
let mode;
let topic;
match parameters.get("hub.callback") {
Some(value) => callback = value,
None => return false,
};
match parameters.get("hub.mode") {
Some(value) => mode = value,
None => return false,
};
match parameters.get("hub.topic") {
Some(value) => topic = value,
None => return false,
};
if mode != &"subscribe" && mode != &"unsubscribe" {
debug!(setup_logging(), "Invalid Method: {}", mode);
return false;
}
match Url::parse(callback) {
Ok(value) => debug!(setup_logging(), "Valid Callback: {}", value),
Err(_) => return false,
}
match Url::parse(topic) {
Ok(value) => debug!(setup_logging(), "Valid Topic: {}", value),
Err(_) => return false,
}
true
} }