Skip to content

Commit 432620a

Browse files
authored
Merge pull request #181 from AdExNetwork/issue-177-auth-middleware
Issue #177 auth middleware
2 parents be51e01 + 872edbc commit 432620a

File tree

9 files changed

+418
-23
lines changed

9 files changed

+418
-23
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

adapter/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ primitives = {path = "../primitives"}
1010
futures-preview = {version = "=0.3.0-alpha.19"}
1111
# Time handling
1212
chrono = "0.4"
13-
time = "0.1.42"
1413
# To/From Hex
1514
hex = "0.3.2"
1615
serde = {version = "^1.0", features = ['derive']}

primitives/src/adapter.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::channel_validator::ChannelValidator;
22
use crate::{Channel, DomainError, ValidatorId};
3+
use serde::{Deserialize, Serialize};
34
use std::collections::HashMap;
45
use std::convert::From;
56
use std::error::Error;
@@ -53,7 +54,7 @@ pub struct KeystoreOptions {
5354
pub keystore_pwd: String,
5455
}
5556

56-
#[derive(Debug, Clone)]
57+
#[derive(Debug, Clone, Serialize, Deserialize)]
5758
pub struct Session {
5859
pub era: i64,
5960
pub uid: ValidatorId,

sentry/src/access.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ async fn apply_rule(
117117
Ok(format!(
118118
"adexRateLimit:{}:{}",
119119
hex::encode(channel.id),
120-
session.ip
120+
session.ip.as_ref().unwrap_or(&String::new())
121121
))
122122
}
123123
} else {
@@ -157,13 +157,25 @@ mod test {
157157
use primitives::event_submission::{RateLimit, Rule};
158158
use primitives::sentry::Event;
159159
use primitives::util::tests::prep_db::DUMMY_CHANNEL;
160-
use primitives::{Channel, EventSubmission};
160+
use primitives::{Channel, Config, EventSubmission};
161161

162162
use crate::db::redis_connection;
163163
use crate::Session;
164164

165165
use super::*;
166166

167+
async fn setup() -> (Config, SharedConnection) {
168+
let mut redis = redis_connection().await.expect("Couldn't connect to Redis");
169+
let config = configuration("development", None).expect("Failed to get dev configuration");
170+
171+
// run `FLUSHALL` to clean any leftovers of other tests
172+
let _ = redis::cmd("FLUSHALL")
173+
.query_async::<_, String>(&mut redis)
174+
.await;
175+
176+
(config, redis)
177+
}
178+
167179
fn get_channel(with_rule: Rule) -> Channel {
168180
let mut channel = DUMMY_CHANNEL.clone();
169181

@@ -184,8 +196,7 @@ mod test {
184196

185197
#[tokio::test]
186198
async fn session_uid_rate_limit() {
187-
let redis = redis_connection().await.expect("Couldn't connect to Redis");
188-
let config = configuration("development", None).expect("Failed to get dev configuration");
199+
let (config, redis) = setup().await;
189200

190201
let session = Session {
191202
era: 0,
@@ -219,8 +230,7 @@ mod test {
219230

220231
#[tokio::test]
221232
async fn ip_rate_limit() {
222-
let redis = redis_connection().await.expect("Couldn't connect to Redis");
223-
let config = configuration("development", None).expect("Failed to get dev configuration");
233+
let (config, redis) = setup().await;
224234

225235
let session = Session {
226236
era: 0,

sentry/src/lib.rs

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
#![deny(clippy::all)]
22
#![deny(rust_2018_idioms)]
33

4+
use crate::middleware::auth;
5+
use crate::middleware::cors::{cors, Cors};
46
use hyper::service::{make_service_fn, service_fn};
57
use hyper::{Body, Error, Method, Request, Response, Server, StatusCode};
68
use primitives::adapter::Adapter;
79
use primitives::Config;
10+
use redis::aio::SharedConnection;
811
use slog::{error, info, Logger};
912

13+
pub mod middleware {
14+
pub mod auth;
15+
pub mod cors;
16+
}
1017
pub mod routes {
1118
pub mod channel;
1219
pub mod cfg {
@@ -32,33 +39,57 @@ pub mod event_reducer;
3239

3340
pub struct Application<A: Adapter> {
3441
adapter: A,
35-
logger: slog::Logger,
42+
logger: Logger,
43+
redis: SharedConnection,
3644
_clustered: bool,
3745
port: u16,
3846
config: Config,
3947
}
4048

4149
impl<A: Adapter + 'static> Application<A> {
42-
pub fn new(adapter: A, config: Config, logger: Logger, clustered: bool, port: u16) -> Self {
50+
pub fn new(
51+
adapter: A,
52+
config: Config,
53+
logger: Logger,
54+
redis: SharedConnection,
55+
clustered: bool,
56+
port: u16,
57+
) -> Self {
4358
Self {
4459
adapter,
4560
config,
4661
logger,
62+
redis,
4763
_clustered: clustered,
4864
port,
4965
}
5066
}
5167

68+
/// Starts the `hyper` `Server`.
5269
pub async fn run(&self) {
5370
let addr = ([127, 0, 0, 1], self.port).into();
5471
info!(&self.logger, "Listening on port {}!", self.port);
5572

5673
let make_service = make_service_fn(move |_| {
5774
let adapter_config = (self.adapter.clone(), self.config.clone());
75+
let redis = self.redis.clone();
76+
let logger = self.logger.clone();
5877
async move {
5978
Ok::<_, Error>(service_fn(move |req| {
6079
let adapter_config = adapter_config.clone();
61-
async move { Ok::<_, Error>(handle_routing(req, adapter_config).await) }
80+
let redis = redis.clone();
81+
let logger = logger.clone();
82+
async move {
83+
Ok::<_, Error>(
84+
handle_routing(
85+
req,
86+
(&adapter_config.0, &adapter_config.1),
87+
redis,
88+
&logger,
89+
)
90+
.await,
91+
)
92+
}
6293
}))
6394
}
6495
});
@@ -88,19 +119,45 @@ where
88119

89120
async fn handle_routing(
90121
req: Request<Body>,
91-
(adapter, config): (impl Adapter, Config),
122+
(adapter, config): (&impl Adapter, &Config),
123+
redis: SharedConnection,
124+
logger: &Logger,
92125
) -> Response<Body> {
93-
match (req.uri().path(), req.method()) {
126+
let headers = match cors(&req) {
127+
Some(Cors::Simple(headers)) => headers,
128+
// if we have a Preflight, just return the response directly
129+
Some(Cors::Preflight(response)) => return response,
130+
None => Default::default(),
131+
};
132+
133+
let req = match auth::for_request(req, adapter, redis.clone()).await {
134+
Ok(req) => req,
135+
Err(error) => {
136+
error!(&logger, "{}", &error; "module" => "middleware-auth");
137+
138+
return map_response_error(ResponseError::BadRequest(error));
139+
}
140+
};
141+
142+
let mut response = match (req.uri().path(), req.method()) {
94143
("/cfg", &Method::GET) => crate::routes::cfg::return_config(&config),
95144
(route, _) if route.starts_with("/channel") => {
96145
crate::routes::channel::handle_channel_routes(req, adapter).await
97146
}
98147
_ => Err(ResponseError::NotFound),
99148
}
100-
.unwrap_or_else(|response_err| match response_err {
149+
.unwrap_or_else(map_response_error);
150+
151+
// extend the headers with the initial headers we have from CORS (if there are some)
152+
response.headers_mut().extend(headers);
153+
response
154+
}
155+
156+
fn map_response_error(error: ResponseError) -> Response<Body> {
157+
match error {
101158
ResponseError::NotFound => not_found(),
102159
ResponseError::BadRequest(error) => bad_request(error),
103-
})
160+
}
104161
}
105162

106163
pub fn not_found() -> Response<Body> {
@@ -110,8 +167,8 @@ pub fn not_found() -> Response<Body> {
110167
response
111168
}
112169

113-
pub fn bad_request(error: Box<dyn std::error::Error>) -> Response<Body> {
114-
let body = Body::from(format!("Bad Request: {}", error));
170+
pub fn bad_request(_: Box<dyn std::error::Error>) -> Response<Body> {
171+
let body = Body::from("Bad Request: try again later");
115172
let mut response = Response::new(body);
116173
let status = response.status_mut();
117174
*status = StatusCode::BAD_REQUEST;
@@ -123,5 +180,5 @@ pub fn bad_request(error: Box<dyn std::error::Error>) -> Response<Body> {
123180
pub struct Session {
124181
pub era: i64,
125182
pub uid: String,
126-
pub ip: String,
183+
pub ip: Option<String>,
127184
}

sentry/src/main.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@ use primitives::config::configuration;
99
use primitives::util::logging::{Async, PrefixedCompactFormat, TermDecorator};
1010
use primitives::util::tests::prep_db::{AUTH, IDS};
1111
use primitives::ValidatorId;
12+
use sentry::db::redis_connection;
1213
use sentry::Application;
1314
use slog::{o, Drain, Logger};
1415
use std::convert::TryFrom;
1516

1617
const DEFAULT_PORT: u16 = 8005;
1718

1819
#[tokio::main]
19-
async fn main() {
20+
async fn main() -> Result<(), Box<dyn std::error::Error>> {
2021
let cli = App::new("Sentry")
2122
.version("0.1")
2223
.arg(
@@ -96,19 +97,21 @@ async fn main() {
9697
};
9798

9899
let logger = logger();
100+
let redis = redis_connection().await?;
99101

100102
match adapter {
101103
AdapterTypes::EthereumAdapter(adapter) => {
102-
Application::new(*adapter, config, logger, clustered, port)
104+
Application::new(*adapter, config, logger, redis, clustered, port)
103105
.run()
104106
.await
105107
}
106108
AdapterTypes::DummyAdapter(adapter) => {
107-
Application::new(*adapter, config, logger, clustered, port)
109+
Application::new(*adapter, config, logger, redis, clustered, port)
108110
.run()
109111
.await
110112
}
111113
}
114+
Ok(())
112115
}
113116

114117
fn logger() -> Logger {

0 commit comments

Comments
 (0)