Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Increased code coverage #80

Merged
merged 14 commits into from
Jan 27, 2022
Merged
540 changes: 299 additions & 241 deletions Cargo.lock

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ tokio = { version = "1", features = ["full"] }
log = "0.4"
log4rs = "1"
hocon = "0.7"
sha2 = "0.9"
sha2 = "0.10"
hex = "0.4"
base64 = "0.13"
hyper-tls = "0.5"
Expand All @@ -36,10 +36,10 @@ rust-embed="6.3"
jemallocator = { version = "0.3", optional = true }

# deps for aws
aws-config = "0.2"
aws-sdk-rekognition = "0.2"
aws-sdk-s3 = "0.2"
aws-types = "0.2"
aws-config = "0.5.2"
aws-sdk-rekognition = "0.5.2"
aws-sdk-s3 = "0.5.2"
aws-types = "0.5.2"

# Overrides to address vulns
time = "0.3"
Expand Down
2 changes: 2 additions & 0 deletions dashboard-ui/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Image Proxy Admin Dashboard

**This UI is now deprecated and will be removed starting version 2.0**

This UI can be made available by running image proxy and accessing the /admin route. See [] for more information.

## `npm run start`
Expand Down
4 changes: 3 additions & 1 deletion src/db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use async_trait::async_trait;
use chrono::{DateTime, Utc};
use uuid::Uuid;

mod dummy_db;
mod postgres;

type GenericError = Box<dyn std::error::Error + Send + Sync>;
Expand Down Expand Up @@ -69,3 +68,6 @@ impl DatabaseFactory {
Ok(Box::new(db))
}
}

#[cfg(test)]
pub mod tests;
127 changes: 64 additions & 63 deletions src/db/dummy_db.rs → src/db/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ pub struct DummyDatabase {
moderation_store: Mutex<HashMap<String, DbModerationRow>>,
}

impl Default for DummyDatabase {
fn default() -> Self {
Self::new()
}
}

impl DummyDatabase {
#[allow(dead_code)]
pub fn new() -> Self {
DummyDatabase {
report_store: Mutex::new(HashMap::new()),
Expand Down Expand Up @@ -98,67 +103,63 @@ impl DatabaseProvider for DummyDatabase {
}
}

#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_moderation_fns() {
let db = DummyDatabase::new();
let url = "http://localhost/test.png".to_string();
let result = db.get_moderation_result(&[url.clone()]).await.unwrap();
assert_eq!(result.len(), 0);

let _ = db
.add_moderation_result(
url.as_str(),
ModerationService::Unknown,
true,
&[ModerationCategories::Alcohol],
)
.await;
let result = db.get_moderation_result(&[url.clone()]).await.unwrap();
assert_eq!(result.len(), 1);
let row = result.get(0).unwrap();
assert!(row.blocked);
assert_eq!(row.categories[0], ModerationCategories::Alcohol);
assert_eq!(row.url, url);
assert_eq!(row.provider, ModerationService::Unknown);

let _ = db
.update_moderation_result(
url.as_str(),
ModerationService::Unknown,
true,
&[ModerationCategories::Alcohol, ModerationCategories::Drugs],
)
.await;

let result = db.get_moderation_result(&[url.clone()]).await.unwrap();
assert_eq!(result.len(), 1);
let row = result.get(0).unwrap();
assert!(row.blocked);
assert_eq!(row.categories.len(), 2);
assert_eq!(row.categories[0], ModerationCategories::Alcohol);
assert_eq!(row.categories[1], ModerationCategories::Drugs);
assert_eq!(row.url, url);
assert_eq!(row.provider, ModerationService::Unknown);
}
#[tokio::test]
async fn test_dummy_database_moderation_fns() {
let db = DummyDatabase::new();
let url = "http://localhost/test.png".to_string();
let result = db.get_moderation_result(&[url.clone()]).await.unwrap();
assert_eq!(result.len(), 0);

let _ = db
.add_moderation_result(
url.as_str(),
ModerationService::Unknown,
true,
&[ModerationCategories::Alcohol],
)
.await;
let result = db.get_moderation_result(&[url.clone()]).await.unwrap();
assert_eq!(result.len(), 1);
let row = result.get(0).unwrap();
assert!(row.blocked);
assert_eq!(row.categories[0], ModerationCategories::Alcohol);
assert_eq!(row.url, url);
assert_eq!(row.provider, ModerationService::Unknown);

let _ = db
.update_moderation_result(
url.as_str(),
ModerationService::Unknown,
true,
&[ModerationCategories::Alcohol, ModerationCategories::Drugs],
)
.await;

let result = db.get_moderation_result(&[url.clone()]).await.unwrap();
assert_eq!(result.len(), 1);
let row = result.get(0).unwrap();
assert!(row.blocked);
assert_eq!(row.categories.len(), 2);
assert_eq!(row.categories[0], ModerationCategories::Alcohol);
assert_eq!(row.categories[1], ModerationCategories::Drugs);
assert_eq!(row.url, url);
assert_eq!(row.provider, ModerationService::Unknown);
}

#[tokio::test]
async fn test_report_fns() {
let db = DummyDatabase::new();
let url = "http://localhost/test.png".to_string();
let id = Uuid::new_v4();
let result = db.get_reports().await.unwrap();
assert_eq!(result.len(), 0);

let _ = db
.add_report(&id, url.as_str(), &[ModerationCategories::Alcohol])
.await;
let result = db.get_reports().await.unwrap();
assert_eq!(result.len(), 1);
let row = result.get(0).unwrap();
assert_eq!(row.url, url);
assert_eq!(row.categories[0], ModerationCategories::Alcohol);
}
#[tokio::test]
async fn test_dummy_database_report_fns() {
let db = DummyDatabase::new();
let url = "http://localhost/test.png".to_string();
let id = Uuid::new_v4();
let result = db.get_reports().await.unwrap();
assert_eq!(result.len(), 0);

let _ = db
.add_report(&id, url.as_str(), &[ModerationCategories::Alcohol])
.await;
let result = db.get_reports().await.unwrap();
assert_eq!(result.len(), 1);
let row = result.get(0).unwrap();
assert_eq!(row.url, url);
assert_eq!(row.categories[0], ModerationCategories::Alcohol);
}
7 changes: 2 additions & 5 deletions src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use image::{self, GenericImageView};
use log::{debug, error};
use uuid::Uuid;

#[derive(Clone)]
pub struct Document {
pub id: Uuid,
pub content_type: String,
Expand Down Expand Up @@ -77,10 +78,6 @@ impl Document {
}

pub fn to_url(&self) -> String {
format!(
"data:{};base64,{}",
self.content_type,
encode(self.bytes.to_vec())
)
format!("data:{};base64,{}", self.content_type, encode(&self.bytes))
}
}
63 changes: 58 additions & 5 deletions src/http/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,22 @@ pub struct HttpClientWrapper {
}

impl HttpClientWrapper {
pub fn new(
client: Box<dyn HttpClientProvider + Send + Sync>,
ipfs_config: Host,
uri_filters: Vec<Box<dyn UriFilter + Send + Sync>>,
) -> Self {
assert!(
!uri_filters.is_empty(),
"No URI filters configured. This cannot be correct, check code."
);
HttpClientWrapper {
client,
ipfs_config,
uri_filters,
}
}

fn to_uri(&self, url: &str) -> Result<Uri, Errors> {
let uri = url.parse::<Uri>().map_err(|e| {
error!("Error parsing url={}, reason={}", url, e);
Expand Down Expand Up @@ -93,7 +109,7 @@ impl HttpClientWrapper {

pub async fn fetch(&self, req_id: &Uuid, url: &str) -> Result<Document, Errors> {
info!("Fetching document for id:{}, url:{}", req_id, url);
let uri = self.to_uri(&url.to_string())?;
let uri = self.to_uri(url)?;

let filter_results = self
.uri_filters
Expand Down Expand Up @@ -161,20 +177,57 @@ impl HttpClientFactory {
!uri_filters.is_empty(),
"No URI filters provided. This is insecure, check code. Exiting..."
);
HttpClientWrapper {
client: Box::new(HyperHttpClient::new(max_document_size, timeout)),
HttpClientWrapper::new(
Box::new(HyperHttpClient::new(max_document_size, timeout)),
ipfs_config,
uri_filters,
}
)
}
}

#[cfg(test)]
mod tests {
pub mod tests {
use std::{collections::HashMap, sync::Mutex};

use super::*;
use crate::dns::StandardDnsResolver;
use filters::private_network::PrivateNetworkFilter;

pub struct DummyHttpClient {
store: Mutex<HashMap<String, Document>>,
}

impl Default for DummyHttpClient {
fn default() -> Self {
Self::new()
}
}

impl DummyHttpClient {
pub fn new() -> Self {
DummyHttpClient {
store: Mutex::new(HashMap::new()),
}
}

pub fn set(&mut self, url: &str, document: Document) {
let mut store = self.store.lock().unwrap();
store.insert(url.to_string(), document);
}
}

#[async_trait]
impl HttpClientProvider for DummyHttpClient {
async fn fetch(&self, _: &Uuid, url: &Uri) -> Result<Document, StatusCode> {
let store = self.store.lock().unwrap();
let url = url.to_string();
match store.get(&url) {
Some(document) => Ok(document.clone()),
None => Err(404),
}
}
}

#[test]
fn test_to_uri_fn() {
let ipfs_config = Host {
Expand Down
Loading