diff --git a/examples/boxxy.rs b/examples/boxxy.rs index 522524f8..5f940171 100644 --- a/examples/boxxy.rs +++ b/examples/boxxy.rs @@ -1,6 +1,7 @@ -#[macro_use] extern crate boxxy; -extern crate sn0int; +#[macro_use] +extern crate boxxy; extern crate env_logger; +extern crate sn0int; fn stage1(sh: &mut boxxy::Shell, _args: Vec) -> Result<(), boxxy::Error> { shprintln!(sh, "[*] starting stage1"); @@ -14,8 +15,6 @@ fn main() { println!("stage1 activate sandbox"); - let toolbox = boxxy::Toolbox::new().with(vec![ - ("stage1", stage1), - ]); + let toolbox = boxxy::Toolbox::new().with(vec![("stage1", stage1)]); boxxy::Shell::new(toolbox).run() } diff --git a/examples/maxmind.rs b/examples/maxmind.rs index 026949b9..04c1cb20 100644 --- a/examples/maxmind.rs +++ b/examples/maxmind.rs @@ -7,9 +7,9 @@ use structopt::StructOpt; #[derive(Debug, StructOpt)] pub enum Args { - #[structopt(name="asn")] + #[structopt(name = "asn")] Asn(AsnArgs), - #[structopt(name="geoip")] + #[structopt(name = "geoip")] GeoIP(GeoIPArgs), } @@ -47,7 +47,6 @@ impl GeoIPArgs { } } - fn run() -> Result<()> { let args = Args::from_args(); debug!("{:?}", args); diff --git a/examples/spinners.rs b/examples/spinners.rs index d5265afa..c62a65fe 100644 --- a/examples/spinners.rs +++ b/examples/spinners.rs @@ -1,21 +1,20 @@ +use sn0int::term::{Spinner, StackedSpinners, SPINNERS}; use std::thread; use std::time::Duration; -use sn0int::term::{SPINNERS, Spinner, StackedSpinners}; use structopt::StructOpt; - #[derive(Debug, StructOpt)] pub enum Args { - #[structopt(name="single")] + #[structopt(name = "single")] Single(Single), - #[structopt(name="stacked")] + #[structopt(name = "stacked")] Stacked(Stacked), } #[derive(Debug, StructOpt)] pub struct Single { idx: usize, - #[structopt(long="ticks", default_value="100")] + #[structopt(long = "ticks", default_value = "100")] ticks: usize, } @@ -33,8 +32,7 @@ impl Single { } #[derive(Debug, StructOpt)] -pub struct Stacked { -} +pub struct Stacked {} impl Stacked { fn run(&self) { diff --git a/sn0int-common/src/id.rs b/sn0int-common/src/id.rs index 0ab9bdc3..d7ffdad5 100644 --- a/sn0int-common/src/id.rs +++ b/sn0int-common/src/id.rs @@ -1,11 +1,10 @@ use crate::errors::*; use nom; -use serde::{de, Serialize, Serializer, Deserialize, Deserializer}; +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; use std::fmt; use std::result; use std::str::FromStr; - #[inline(always)] fn valid_char(c: char) -> bool { nom::character::is_alphanumeric(c as u8) || c == '-' @@ -20,15 +19,15 @@ pub fn valid_name(name: &str) -> Result<()> { } fn module(s: &str) -> nom::IResult<&str, ModuleID> { - let (input, (author, _, name)) = nom::sequence::tuple(( - token, - nom::bytes::complete::tag("/"), - token, - ))(s)?; - Ok((input, ModuleID { - author: author.to_string(), - name: name.to_string(), - })) + let (input, (author, _, name)) = + nom::sequence::tuple((token, nom::bytes::complete::tag("/"), token))(s)?; + Ok(( + input, + ModuleID { + author: author.to_string(), + name: name.to_string(), + }, + )) } #[inline] @@ -52,8 +51,8 @@ impl FromStr for ModuleID { type Err = Error; fn from_str(s: &str) -> Result { - let (trailing, module) = module(s) - .map_err(|err| format_err!("Failed to parse module id: {:?}", err))?; + let (trailing, module) = + module(s).map_err(|err| format_err!("Failed to parse module id: {:?}", err))?; if !trailing.is_empty() { bail!("Trailing data in module id"); } @@ -72,7 +71,8 @@ impl Serialize for ModuleID { impl<'de> Deserialize<'de> for ModuleID { fn deserialize(deserializer: D) -> result::Result - where D: Deserializer<'de> + where + D: Deserializer<'de>, { let s = String::deserialize(deserializer)?; FromStr::from_str(&s).map_err(de::Error::custom) @@ -86,10 +86,13 @@ mod tests { #[test] fn verify_valid() { let result = ModuleID::from_str("kpcyrd/foo").expect("parse"); - assert_eq!(result, ModuleID { - author: "kpcyrd".to_string(), - name: "foo".to_string(), - }); + assert_eq!( + result, + ModuleID { + author: "kpcyrd".to_string(), + name: "foo".to_string(), + } + ); } #[test] diff --git a/sn0int-common/src/lib.rs b/sn0int-common/src/lib.rs index cd307566..752613f9 100644 --- a/sn0int-common/src/lib.rs +++ b/sn0int-common/src/lib.rs @@ -1,12 +1,15 @@ -#[macro_use] extern crate serde_derive; -#[macro_use] extern crate failure; -#[macro_use] extern crate nom; +#[macro_use] +extern crate serde_derive; +#[macro_use] +extern crate failure; +#[macro_use] +extern crate nom; pub mod api; pub mod errors; pub use crate::errors::*; -pub mod metadata; pub mod id; +pub mod metadata; pub use crate::id::*; pub use rocket_failure_errors::StrictApiResponse as ApiResponse; diff --git a/sn0int-common/src/metadata.rs b/sn0int-common/src/metadata.rs index 860a3a48..5a5a50df 100644 --- a/sn0int-common/src/metadata.rs +++ b/sn0int-common/src/metadata.rs @@ -2,7 +2,6 @@ use crate::errors::*; use std::str::FromStr; - #[derive(Debug, PartialEq, Clone)] pub enum EntryType { Description, @@ -143,8 +142,7 @@ impl FromStr for Metadata { type Err = Error; fn from_str(code: &str) -> Result { - let (_, lines) = metalines(code) - .map_err(|_| format_err!("Failed to parse header"))?; + let (_, lines) = metalines(code).map_err(|_| format_err!("Failed to parse header"))?; let mut data = NewMetadata::default(); @@ -173,16 +171,20 @@ pub struct NewMetadata<'a> { impl<'a> NewMetadata<'a> { fn try_from(self) -> Result { - let description = self.description.ok_or_else(|| format_err!("Description is required"))?; - let version = self.version.ok_or_else(|| format_err!("Version is required"))?; + let description = self + .description + .ok_or_else(|| format_err!("Description is required"))?; + let version = self + .version + .ok_or_else(|| format_err!("Version is required"))?; let source = match self.source { Some(x) => Some(x.parse()?), _ => None, }; - let keyring_access = self.keyring_access.into_iter() - .map(String::from) - .collect(); - let license = self.license.ok_or_else(|| format_err!("License is required"))?; + let keyring_access = self.keyring_access.into_iter().map(String::from).collect(); + let license = self + .license + .ok_or_else(|| format_err!("License is required"))?; let license = license.parse()?; Ok(Metadata { @@ -219,55 +221,71 @@ mod tests { #[test] fn verify_simple() { - let metadata = Metadata::from_str(r#"-- Description: Hello world, this is my description + let metadata = Metadata::from_str( + r#"-- Description: Hello world, this is my description -- Version: 1.0.0 -- Source: domains -- License: WTFPL -"#).expect("parse"); - assert_eq!(metadata, Metadata { - description: "Hello world, this is my description".to_string(), - version: "1.0.0".to_string(), - license: License::WTFPL, - source: Some(Source::Domains), - keyring_access: Vec::new(), - }); +"#, + ) + .expect("parse"); + assert_eq!( + metadata, + Metadata { + description: "Hello world, this is my description".to_string(), + version: "1.0.0".to_string(), + license: License::WTFPL, + source: Some(Source::Domains), + keyring_access: Vec::new(), + } + ); } #[test] fn verify_no_source() { - let metadata = Metadata::from_str(r#"-- Description: Hello world, this is my description + let metadata = Metadata::from_str( + r#"-- Description: Hello world, this is my description -- Version: 1.0.0 -- License: WTFPL -"#).expect("parse"); - assert_eq!(metadata, Metadata { - description: "Hello world, this is my description".to_string(), - version: "1.0.0".to_string(), - license: License::WTFPL, - source: None, - keyring_access: Vec::new(), - }); +"#, + ) + .expect("parse"); + assert_eq!( + metadata, + Metadata { + description: "Hello world, this is my description".to_string(), + version: "1.0.0".to_string(), + license: License::WTFPL, + source: None, + keyring_access: Vec::new(), + } + ); } #[test] fn verify_require_license() { - let metadata = Metadata::from_str(r#"-- Description: Hello world, this is my description + let metadata = Metadata::from_str( + r#"-- Description: Hello world, this is my description -- Version: 1.0.0 -- Source: domains -"#); +"#, + ); assert!(metadata.is_err()); } #[test] fn verify_require_opensource_license() { - let metadata = Metadata::from_str(r#"-- Description: Hello world, this is my description + let metadata = Metadata::from_str( + r#"-- Description: Hello world, this is my description -- Version: 1.0.0 -- Source: domains -- License: Proprietary -"#); +"#, + ); assert!(metadata.is_err()); } diff --git a/sn0int-registry/examples/dummy-gen.rs b/sn0int-registry/examples/dummy-gen.rs index 61ab41d6..b7577cef 100644 --- a/sn0int-registry/examples/dummy-gen.rs +++ b/sn0int-registry/examples/dummy-gen.rs @@ -1,22 +1,23 @@ -#[macro_use] extern crate failure; +#[macro_use] +extern crate failure; -use sn0int_common::metadata::Metadata; -use semver::Version; -use sn0int_registry::db::wait_for_db; +use diesel::Connection; use diesel::PgConnection; use dotenv::dotenv; +use semver::Version; +use sn0int_common::metadata::Metadata; +use sn0int_registry::db::wait_for_db; +use sn0int_registry::errors::*; use sn0int_registry::models::*; -use diesel::Connection; use std::env; -use sn0int_registry::errors::*; fn insert(connection: &PgConnection, user: &str, name: &str, code: &str) -> Result<()> { - let metadata = code.parse::() + let metadata = code + .parse::() .context("Failed to parse module metadata")?; let version = metadata.version.clone(); - Version::parse(&version) - .context("Version is invalid")?; + Version::parse(&version).context("Version is invalid")?; connection.transaction::<_, Error, _>(|| { let module = Module::update_or_create(&user, &name, &metadata, &connection) @@ -28,8 +29,9 @@ fn insert(connection: &PgConnection, user: &str, name: &str, code: &str) -> Resu if release.code != code { bail!("Version number already in use") } - }, - None => module.add_version(&version, &code, &connection) + } + None => module + .add_version(&version, &code, &connection) .context("Failed to add release")?, } println!("[+] added {}/{}", module.author, module.name); @@ -38,15 +40,17 @@ fn insert(connection: &PgConnection, user: &str, name: &str, code: &str) -> Resu }) } - fn run() -> Result<()> { dotenv().ok(); - let database_url = env::var("DATABASE_URL") - .context("DATABASE_URL must be set")?; + let database_url = env::var("DATABASE_URL").context("DATABASE_URL must be set")?; let connection = wait_for_db(&database_url, 5)?; - insert(&connection, "kpcyrd", "ctlogs", r#"-- Description: Query certificate transparency logs to discover subdomains + insert( + &connection, + "kpcyrd", + "ctlogs", + r#"-- Description: Query certificate transparency logs to discover subdomains -- Version: 0.5.0 -- Source: domains -- License: GPL-3.0 @@ -72,16 +76,22 @@ function run(arg) certs = json_decode(resp['text']) if last_err() then return end -"#)?; - - insert(&connection, "dead", "module", r#"-- Description: TODO your description here +"#, + )?; + + insert( + &connection, + "dead", + "module", + r#"-- Description: TODO your description here -- Version: 0.1.0 -- License: GPL-3.0 function run() -- TODO your code here end -"#)?; +"#, + )?; let dead = Module::find("dead", "module", &connection)?; dead.redirect(&"kpcyrd/ctlogs".parse().unwrap(), &connection)?; diff --git a/sn0int-registry/src/assets.rs b/sn0int-registry/src/assets.rs index 9d94dfb1..b0efb72b 100644 --- a/sn0int-registry/src/assets.rs +++ b/sn0int-registry/src/assets.rs @@ -1,6 +1,5 @@ use blake2::{Blake2b, Digest}; - pub static FAVICON: &[u8] = include_bytes!("../assets/favicon.ico"); pub static STYLESHEET: &[u8] = include_bytes!("../assets/style.css"); pub static JAVASCRIPT: &[u8] = include_bytes!("../assets/script.js"); @@ -9,18 +8,30 @@ pub static SOCIAL_CARD: &[u8] = include_bytes!("../assets/social-card.png"); pub static JAVASCRIPT_CLIPBOARD: &[u8] = include_bytes!("../assets/clipboard.min.js"); pub static FA_STYLESHEET: &[u8] = include_bytes!("../assets/fontawesome/css/all.min.css"); -pub static FA_BRANDS_400_SVG: &[u8] = include_bytes!("../assets/fontawesome/webfonts/fa-brands-400.svg"); -pub static FA_BRANDS_400_TTF: &[u8] = include_bytes!("../assets/fontawesome/webfonts/fa-brands-400.ttf"); -pub static FA_BRANDS_400_WOFF: &[u8] = include_bytes!("../assets/fontawesome/webfonts/fa-brands-400.woff"); -pub static FA_BRANDS_400_WOFF2: &[u8] = include_bytes!("../assets/fontawesome/webfonts/fa-brands-400.woff2"); -pub static FA_REGULAR_400_SVG: &[u8] = include_bytes!("../assets/fontawesome/webfonts/fa-regular-400.svg"); -pub static FA_REGULAR_400_TTF: &[u8] = include_bytes!("../assets/fontawesome/webfonts/fa-regular-400.ttf"); -pub static FA_REGULAR_400_WOFF: &[u8] = include_bytes!("../assets/fontawesome/webfonts/fa-regular-400.woff"); -pub static FA_REGULAR_400_WOFF2: &[u8] = include_bytes!("../assets/fontawesome/webfonts/fa-regular-400.woff2"); -pub static FA_SOLID_900_SVG: &[u8] = include_bytes!("../assets/fontawesome/webfonts/fa-solid-900.svg"); -pub static FA_SOLID_900_TTF: &[u8] = include_bytes!("../assets/fontawesome/webfonts/fa-solid-900.ttf"); -pub static FA_SOLID_900_WOFF: &[u8] = include_bytes!("../assets/fontawesome/webfonts/fa-solid-900.woff"); -pub static FA_SOLID_900_WOFF2: &[u8] = include_bytes!("../assets/fontawesome/webfonts/fa-solid-900.woff2"); +pub static FA_BRANDS_400_SVG: &[u8] = + include_bytes!("../assets/fontawesome/webfonts/fa-brands-400.svg"); +pub static FA_BRANDS_400_TTF: &[u8] = + include_bytes!("../assets/fontawesome/webfonts/fa-brands-400.ttf"); +pub static FA_BRANDS_400_WOFF: &[u8] = + include_bytes!("../assets/fontawesome/webfonts/fa-brands-400.woff"); +pub static FA_BRANDS_400_WOFF2: &[u8] = + include_bytes!("../assets/fontawesome/webfonts/fa-brands-400.woff2"); +pub static FA_REGULAR_400_SVG: &[u8] = + include_bytes!("../assets/fontawesome/webfonts/fa-regular-400.svg"); +pub static FA_REGULAR_400_TTF: &[u8] = + include_bytes!("../assets/fontawesome/webfonts/fa-regular-400.ttf"); +pub static FA_REGULAR_400_WOFF: &[u8] = + include_bytes!("../assets/fontawesome/webfonts/fa-regular-400.woff"); +pub static FA_REGULAR_400_WOFF2: &[u8] = + include_bytes!("../assets/fontawesome/webfonts/fa-regular-400.woff2"); +pub static FA_SOLID_900_SVG: &[u8] = + include_bytes!("../assets/fontawesome/webfonts/fa-solid-900.svg"); +pub static FA_SOLID_900_TTF: &[u8] = + include_bytes!("../assets/fontawesome/webfonts/fa-solid-900.ttf"); +pub static FA_SOLID_900_WOFF: &[u8] = + include_bytes!("../assets/fontawesome/webfonts/fa-solid-900.woff"); +pub static FA_SOLID_900_WOFF2: &[u8] = + include_bytes!("../assets/fontawesome/webfonts/fa-solid-900.woff2"); lazy_static! { pub static ref ASSET_REV: String = { diff --git a/sn0int-registry/src/auth.rs b/sn0int-registry/src/auth.rs index 660eaf39..43dd1fcc 100644 --- a/sn0int-registry/src/auth.rs +++ b/sn0int-registry/src/auth.rs @@ -1,13 +1,15 @@ +use crate::github; use diesel::pg::PgConnection; use oauth2::basic::BasicClient; use oauth2::prelude::*; -use oauth2::{AuthUrl, AuthorizationCode, ClientId, ClientSecret, CsrfToken, RedirectUrl, TokenUrl, TokenResponse}; -use crate::github; +use oauth2::{ + AuthUrl, AuthorizationCode, ClientId, ClientSecret, CsrfToken, RedirectUrl, TokenResponse, + TokenUrl, +}; use sn0int_registry::errors::*; use sn0int_registry::models::AuthToken; -use url::Url; use std::env; - +use url::Url; pub struct Authenticator { client: BasicClient, @@ -15,9 +17,9 @@ pub struct Authenticator { impl Authenticator { pub fn new(client_id: String, client_secret: String, redirect_url: Url) -> Authenticator { - let auth_url = AuthUrl::new( + let auth_url = AuthUrl::new( Url::parse("https://github.com/login/oauth/authorize") - .expect("Invalid authorization endpoint URL") + .expect("Invalid authorization endpoint URL"), ); let token_url = TokenUrl::new( @@ -29,25 +31,18 @@ impl Authenticator { let client_secret = ClientSecret::new(client_secret); // Set up the config for the Github OAuth2 process. - let client = BasicClient::new( - client_id, - Some(client_secret), - auth_url, Some(token_url) - ) - .set_redirect_url(RedirectUrl::new(redirect_url)); + let client = BasicClient::new(client_id, Some(client_secret), auth_url, Some(token_url)) + .set_redirect_url(RedirectUrl::new(redirect_url)); - Authenticator { - client, - } + Authenticator { client } } pub fn from_env() -> Result { - let client_id = env::var("GITHUB_CLIENT_ID") - .context("GITHUB_CLIENT_ID is not set")?; - let client_secret = env::var("GITHUB_CLIENT_SECRET") - .context("GITHUB_CLIENT_SECRET is not set")?; - let redirect_url = env::var("OAUTH_REDIRECT_URL") - .context("OAUTH_REDIRECT_URL is not set")?; + let client_id = env::var("GITHUB_CLIENT_ID").context("GITHUB_CLIENT_ID is not set")?; + let client_secret = + env::var("GITHUB_CLIENT_SECRET").context("GITHUB_CLIENT_SECRET is not set")?; + let redirect_url = + env::var("OAUTH_REDIRECT_URL").context("OAUTH_REDIRECT_URL is not set")?; let redirect_url = redirect_url.parse()?; Ok(Authenticator::new(client_id, client_secret, redirect_url)) } @@ -61,7 +56,9 @@ impl Authenticator { // TODO: csrf check - let response = self.client.exchange_code(code) + let response = self + .client + .exchange_code(code) .context("Github authentication failed")?; let access_token = response.access_token(); @@ -69,11 +66,14 @@ impl Authenticator { let user = github::get_username(&access_token)?; - AuthToken::create(&AuthToken { - id: state, - author: user, - access_token, - }, connection)?; + AuthToken::create( + &AuthToken { + id: state, + author: user, + access_token, + }, + connection, + )?; Ok(()) } diff --git a/sn0int-registry/src/auth2.rs b/sn0int-registry/src/auth2.rs index 6b17bfaf..97b38ac1 100644 --- a/sn0int-registry/src/auth2.rs +++ b/sn0int-registry/src/auth2.rs @@ -1,19 +1,17 @@ -use sn0int_registry::errors::*; -use sn0int_registry::models::AuthToken; -use sn0int_registry::db::Connection; +use crate::github; use rocket::http::Status; -use rocket::{Request, Outcome}; use rocket::request::{self, FromRequest}; -use crate::github; - +use rocket::{Outcome, Request}; +use sn0int_registry::db::Connection; +use sn0int_registry::errors::*; +use sn0int_registry::models::AuthToken; pub struct AuthHeader(String); impl AuthHeader { pub fn verify(&self, connection: &Connection) -> Result { let session = AuthToken::read(&self.0, &connection)?; - github::get_username(&session.access_token) - .map_err(Error::from) + github::get_username(&session.access_token).map_err(Error::from) } } diff --git a/sn0int-registry/src/db.rs b/sn0int-registry/src/db.rs index ec4fb1ed..e8b3d25d 100644 --- a/sn0int-registry/src/db.rs +++ b/sn0int-registry/src/db.rs @@ -1,15 +1,14 @@ use crate::errors::*; -use std::io; -use std::thread; -use std::time::Duration; -use std::ops::Deref; -use diesel::Connection as ConnectionTrait; use diesel::pg::PgConnection; use diesel::r2d2; +use diesel::Connection as ConnectionTrait; use rocket::http::Status; use rocket::request::{self, FromRequest}; -use rocket::{Request, State, Outcome}; - +use rocket::{Outcome, Request, State}; +use std::io; +use std::ops::Deref; +use std::thread; +use std::time::Duration; type ManagedPgConn = r2d2::ConnectionManager; type Pool = r2d2::Pool; @@ -32,7 +31,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for Connection { let pool = request.guard::>()?; match pool.get() { Ok(conn) => Outcome::Success(Connection(conn)), - Err(_) => Outcome::Failure((Status::ServiceUnavailable, ())) + Err(_) => Outcome::Failure((Status::ServiceUnavailable, ())), } } } diff --git a/sn0int-registry/src/github.rs b/sn0int-registry/src/github.rs index dff5f6e9..08d60d12 100644 --- a/sn0int-registry/src/github.rs +++ b/sn0int-registry/src/github.rs @@ -1,16 +1,18 @@ -use sn0int_registry::errors::*; use reqwest; +use sn0int_registry::errors::*; pub fn get_username(oauth_token: &str) -> Result { let client = reqwest::Client::new(); - let mut resp = client.get("https://api.github.com/user") + let mut resp = client + .get("https://api.github.com/user") .header("Authorization", format!("token {}", oauth_token)) .send() .context("Failed to check access_token")? .error_for_status() .context("Github returned http error")?; - let data = resp.json::() + let data = resp + .json::() .context("Failed to deserialize github reply")?; Ok(data.login) @@ -19,6 +21,6 @@ pub fn get_username(oauth_token: &str) -> Result { #[derive(Debug, Deserialize)] struct GithubUser { login: String, - #[serde(rename="type")] + #[serde(rename = "type")] user_type: String, } diff --git a/sn0int-registry/src/lib.rs b/sn0int-registry/src/lib.rs index 2fbbd92c..21afedd1 100644 --- a/sn0int-registry/src/lib.rs +++ b/sn0int-registry/src/lib.rs @@ -1,7 +1,11 @@ -#[macro_use] extern crate diesel; -#[macro_use] extern crate diesel_migrations; -#[macro_use] extern crate failure; -#[macro_use] extern crate serde_derive; +#[macro_use] +extern crate diesel; +#[macro_use] +extern crate diesel_migrations; +#[macro_use] +extern crate failure; +#[macro_use] +extern crate serde_derive; pub mod db; pub mod errors; diff --git a/sn0int-registry/src/main.rs b/sn0int-registry/src/main.rs index d1c4fff7..6138e78f 100644 --- a/sn0int-registry/src/main.rs +++ b/sn0int-registry/src/main.rs @@ -2,24 +2,32 @@ #![warn(unused_extern_crates)] #![feature(proc_macro_hygiene, decl_macro)] -#[macro_use] extern crate rocket; -#[macro_use] extern crate rocket_contrib; -#[macro_use] extern crate rocket_failure; -#[macro_use] extern crate serde_derive; -#[macro_use] extern crate log; -#[macro_use] extern crate maplit; -#[macro_use] extern crate lazy_static; -#[macro_use] extern crate failure; +#[macro_use] +extern crate rocket; +#[macro_use] +extern crate rocket_contrib; +#[macro_use] +extern crate rocket_failure; +#[macro_use] +extern crate serde_derive; +#[macro_use] +extern crate log; +#[macro_use] +extern crate maplit; +#[macro_use] +extern crate lazy_static; +#[macro_use] +extern crate failure; +use dotenv::dotenv; use rocket::fairing::AdHoc; use rocket::http::Header; use rocket_contrib::json::{Json, JsonValue}; use rocket_contrib::templates::Template; -use dotenv::dotenv; -use std::env; -use sn0int_registry::errors::*; use sn0int_registry::db; +use sn0int_registry::errors::*; +use std::env; pub mod assets; pub mod auth; @@ -27,7 +35,6 @@ pub mod auth2; pub mod github; pub mod routes; - #[catch(400)] fn bad_request() -> Json { Json(json!({ @@ -52,11 +59,9 @@ fn internal_error() -> Json { fn run() -> Result<()> { dotenv().ok(); - let database_url = env::var("DATABASE_URL") - .context("DATABASE_URL must be set")?; + let database_url = env::var("DATABASE_URL").context("DATABASE_URL must be set")?; - db::setup_db(&database_url, 60) - .context("Failed to setup db")?; + db::setup_db(&database_url, 60).context("Failed to setup db")?; rocket::ignite() .manage(db::init(&database_url)) diff --git a/sn0int-registry/src/models.rs b/sn0int-registry/src/models.rs index 9fc95065..51f1c60b 100644 --- a/sn0int-registry/src/models.rs +++ b/sn0int-registry/src/models.rs @@ -1,17 +1,16 @@ use crate::errors::*; -use diesel::prelude::*; +use crate::schema::*; use diesel::pg::PgConnection; +use diesel::prelude::*; use diesel::sql_types::BigInt; use diesel_full_text_search::{plainto_tsquery, TsQueryExtensions}; -use crate::schema::*; +use sn0int_common::metadata::Metadata; +use sn0int_common::ModuleID; use std::collections::HashMap; use std::time::SystemTime; -use sn0int_common::ModuleID; -use sn0int_common::metadata::Metadata; - #[derive(AsChangeset, Serialize, Deserialize, Queryable, Insertable)] -#[table_name="auth_tokens"] +#[table_name = "auth_tokens"] pub struct AuthToken { pub id: String, pub author: String, @@ -27,21 +26,22 @@ impl AuthToken { } pub fn read(id: &str, connection: &PgConnection) -> Result { - auth_tokens::table.find(id) + auth_tokens::table + .find(id) .first::(connection) .map_err(Error::from) } pub fn read_opt(id: &str, connection: &PgConnection) -> Result> { - auth_tokens::table.find(id) + auth_tokens::table + .find(id) .first::(connection) .optional() .map_err(Error::from) } pub fn delete(id: &str, connection: &PgConnection) -> Result<()> { - diesel::delete(auth_tokens::table.find(id)) - .execute(connection)?; + diesel::delete(auth_tokens::table.find(id)).execute(connection)?; Ok(()) } } @@ -70,7 +70,7 @@ pub const ALL_MODULE_COLUMNS: AllModuleColumns = ( ); #[derive(AsChangeset, Identifiable, Queryable, Serialize, PartialEq, Debug)] -#[table_name="modules"] +#[table_name = "modules"] pub struct Module { pub id: i32, pub author: String, @@ -92,55 +92,69 @@ impl Module { } pub fn find(author: &str, name: &str, connection: &PgConnection) -> Result { - modules::table.filter(modules::columns::author.eq(author)) - .filter(modules::columns::name.eq(name)) - .select(ALL_MODULE_COLUMNS) - .first::(connection) - .map_err(Error::from) + modules::table + .filter(modules::columns::author.eq(author)) + .filter(modules::columns::name.eq(name)) + .select(ALL_MODULE_COLUMNS) + .first::(connection) + .map_err(Error::from) } pub fn find_opt(author: &str, name: &str, connection: &PgConnection) -> Result> { - modules::table.filter(modules::columns::author.eq(author)) - .filter(modules::columns::name.eq(name)) - .select(ALL_MODULE_COLUMNS) - .first::(connection) - .optional() - .map_err(Error::from) + modules::table + .filter(modules::columns::author.eq(author)) + .filter(modules::columns::name.eq(name)) + .select(ALL_MODULE_COLUMNS) + .first::(connection) + .optional() + .map_err(Error::from) } - pub fn update_or_create(author: &str, name: &str, metadata: &Metadata, connection: &PgConnection) -> Result { + pub fn update_or_create( + author: &str, + name: &str, + metadata: &Metadata, + connection: &PgConnection, + ) -> Result { let description = metadata.description.as_str(); let source = metadata.source.as_ref().map(|x| x.group_as_str()); match Self::find_opt(author, name, connection)? { - Some(module) => diesel::update(modules::table.filter(modules::columns::id.eq(module.id))) - .set(&BumpModule { - description: Some(description), - redirect: Some(None), - }) - .returning(ALL_MODULE_COLUMNS) - .get_result(connection) - .map_err(Error::from), - None => Self::create(&NewModule { - author, - name, - description, - latest: None, - source, - redirect: None, - }, connection), + Some(module) => { + diesel::update(modules::table.filter(modules::columns::id.eq(module.id))) + .set(&BumpModule { + description: Some(description), + redirect: Some(None), + }) + .returning(ALL_MODULE_COLUMNS) + .get_result(connection) + .map_err(Error::from) + } + None => Self::create( + &NewModule { + author, + name, + description, + latest: None, + source, + redirect: None, + }, + connection, + ), } } pub fn id(id: i32, connection: &PgConnection) -> Result { - modules::table.find(id) + modules::table + .find(id) .select(ALL_MODULE_COLUMNS) .first::(connection) .map_err(Error::from) } pub fn id_opt(id: i32, connection: &PgConnection) -> Result> { - modules::table.find(id) + modules::table + .find(id) .select(ALL_MODULE_COLUMNS) .first::(connection) .optional() @@ -148,17 +162,19 @@ impl Module { } pub fn delete(id: i32, connection: &PgConnection) -> Result<()> { - diesel::delete(modules::table.find(id)) - .execute(connection)?; + diesel::delete(modules::table.find(id)).execute(connection)?; Ok(()) } pub fn add_version(&self, version: &str, code: &str, connection: &PgConnection) -> Result<()> { - let _release = Release::create(&NewRelease { - module_id: self.id, - version, - code, - }, connection)?; + let _release = Release::create( + &NewRelease { + module_id: self.id, + version, + code, + }, + connection, + )?; diesel::update(modules::table.filter(modules::columns::id.eq(self.id))) .set(modules::columns::latest.eq(version)) @@ -178,7 +194,18 @@ impl Module { pub fn search(query: &str, connection: &PgConnection) -> Result> { let q = plainto_tsquery(query); - let x: Vec<(i32, String, String, String, Option, bool, Option, Option, i64)> = modules::table.select(( + let x: Vec<( + i32, + String, + String, + String, + Option, + bool, + Option, + Option, + i64, + )> = modules::table + .select(( modules::id, modules::author, modules::name, @@ -198,35 +225,49 @@ impl Module { )) .load(connection)?; - Ok(x.into_iter().map(|(id, author, name, description, latest, featured, source, redirect, downloads)| ( - Module { - id, - author, - name, - description, - latest, - featured, - source, - redirect, - }, - downloads, - )).collect()) + Ok(x.into_iter() + .map( + |(id, author, name, description, latest, featured, source, redirect, downloads)| { + ( + Module { + id, + author, + name, + description, + latest, + featured, + source, + redirect, + }, + downloads, + ) + }, + ) + .collect()) } pub fn quickstart(connection: &PgConnection) -> Result> { modules::table .select(ALL_MODULE_COLUMNS) .filter(modules::featured) - .order(( - modules::author.asc(), - modules::name.asc(), - )) + .order((modules::author.asc(), modules::name.asc())) .load(connection) .map_err(Error::from) } pub fn start_page(connection: &PgConnection) -> Result>> { - let x: Vec<(i32, String, String, String, Option, bool, Option, Option, i64)> = modules::table.select(( + let x: Vec<( + i32, + String, + String, + String, + Option, + bool, + Option, + Option, + i64, + )> = modules::table + .select(( modules::id, modules::author, modules::name, @@ -286,7 +327,7 @@ impl Module { } #[derive(Insertable)] -#[table_name="modules"] +#[table_name = "modules"] pub struct NewModule<'a> { author: &'a str, name: &'a str, @@ -297,7 +338,7 @@ pub struct NewModule<'a> { } #[derive(AsChangeset)] -#[table_name="modules"] +#[table_name = "modules"] pub struct BumpModule<'a> { description: Option<&'a str>, redirect: Option>, @@ -305,7 +346,7 @@ pub struct BumpModule<'a> { #[derive(AsChangeset, Identifiable, Queryable, Associations, Serialize, PartialEq, Debug)] #[belongs_to(Module)] -#[table_name="releases"] +#[table_name = "releases"] pub struct Release { pub id: i32, pub module_id: i32, @@ -331,36 +372,43 @@ impl Release { } pub fn find(module_id: i32, version: &str, connection: &PgConnection) -> Result { - releases::table.filter(releases::columns::module_id.eq(module_id)) - .filter(releases::columns::version.eq(version)) - .first::(connection) - .map_err(Error::from) + releases::table + .filter(releases::columns::module_id.eq(module_id)) + .filter(releases::columns::version.eq(version)) + .first::(connection) + .map_err(Error::from) } - pub fn try_find(module_id: i32, version: &str, connection: &PgConnection) -> Result> { - releases::table.filter(releases::columns::module_id.eq(module_id)) - .filter(releases::columns::version.eq(version)) - .first::(connection) - .optional() - .map_err(Error::from) + pub fn try_find( + module_id: i32, + version: &str, + connection: &PgConnection, + ) -> Result> { + releases::table + .filter(releases::columns::module_id.eq(module_id)) + .filter(releases::columns::version.eq(version)) + .first::(connection) + .optional() + .map_err(Error::from) } pub fn id(id: i32, connection: &PgConnection) -> Result { - releases::table.find(id) + releases::table + .find(id) .first::(connection) .map_err(Error::from) } pub fn id_opt(id: i32, connection: &PgConnection) -> Result> { - releases::table.find(id) + releases::table + .find(id) .first::(connection) .optional() .map_err(Error::from) } pub fn delete(id: i32, connection: &PgConnection) -> Result<()> { - diesel::delete(releases::table.find(id)) - .execute(connection)?; + diesel::delete(releases::table.find(id)).execute(connection)?; Ok(()) } @@ -381,14 +429,16 @@ impl Release { pub fn downloads(connection: &PgConnection) -> Result { releases::table - .select(diesel::dsl::sql::("coalesce(sum(releases.downloads), 0) AS sum")) + .select(diesel::dsl::sql::( + "coalesce(sum(releases.downloads), 0) AS sum", + )) .first(connection) .map_err(Error::from) } } #[derive(Insertable)] -#[table_name="releases"] +#[table_name = "releases"] pub struct NewRelease<'a> { module_id: i32, version: &'a str, diff --git a/sn0int-registry/src/routes/api.rs b/sn0int-registry/src/routes/api.rs index e060c1d3..fd92682d 100644 --- a/sn0int-registry/src/routes/api.rs +++ b/sn0int-registry/src/routes/api.rs @@ -1,7 +1,4 @@ -use sn0int_registry::errors::*; use crate::auth2::AuthHeader; -use sn0int_registry::db; -use sn0int_registry::models::*; use diesel::Connection; use rocket::request::Form; use rocket_contrib::json::Json; @@ -9,9 +6,11 @@ use semver::Version; use sn0int_common::api::*; use sn0int_common::id; use sn0int_common::metadata::Metadata; +use sn0int_registry::db; +use sn0int_registry::errors::*; +use sn0int_registry::models::*; use std::time::UNIX_EPOCH; - #[get("/quickstart")] pub fn quickstart(connection: db::Connection) -> ApiResult>> { let modules = Module::quickstart(&connection)?; @@ -20,15 +19,13 @@ pub fn quickstart(connection: db::Connection) -> ApiResult ApiResult> { - let time = Release::latest(&connection)? - .map(|x| { - x.published.duration_since(UNIX_EPOCH) - .expect("Time went backwards") - .as_secs() - }); - let latest = LatestResponse { - time, - }; + let time = Release::latest(&connection)?.map(|x| { + x.published + .duration_since(UNIX_EPOCH) + .expect("Time went backwards") + .as_secs() + }); + let latest = LatestResponse { time }; Ok(ApiResponse::Success(latest)) } @@ -38,11 +35,15 @@ pub struct Search { } #[get("/search?")] -pub fn search(q: Form, connection: db::Connection) -> ApiResult>> { +pub fn search( + q: Form, + connection: db::Connection, +) -> ApiResult>> { info!("Searching: {:?}", q.q); let modules = Module::search(&q.q, &connection)?; - let modules = modules.into_iter() + let modules = modules + .into_iter() .flat_map(|(module, downloads)| { Ok::<_, ()>(SearchResponse { author: module.author, @@ -58,8 +59,12 @@ pub fn search(q: Form, connection: db::Connection) -> ApiResult/", format="application/json")] -pub fn info(author: String, name: String, connection: db::Connection) -> ApiResult> { +#[get("/info//", format = "application/json")] +pub fn info( + author: String, + name: String, + connection: db::Connection, +) -> ApiResult> { info!("Querying {:?}/{:?}", author, name); let module = Module::find(&author, &name, &connection) .not_found() @@ -80,8 +85,13 @@ pub fn info(author: String, name: String, connection: db::Connection) -> ApiResu })) } -#[get("/dl///", format="application/json")] -pub fn download(author: String, name: String, version: String, connection: db::Connection) -> ApiResult> { +#[get("/dl///", format = "application/json")] +pub fn download( + author: String, + name: String, + version: String, + connection: db::Connection, +) -> ApiResult> { info!("Downloading {:?}/{:?} ({:?})", author, name, version); let module = Module::find(&author, &name, &connection) .not_found() @@ -102,9 +112,15 @@ pub fn download(author: String, name: String, version: String, connection: db::C })) } -#[post("/publish/", format="application/json", data="")] -pub fn publish(name: String, upload: Json, session: AuthHeader, connection: db::Connection) -> ApiResult> { - let user = session.verify(&connection) +#[post("/publish/", format = "application/json", data = "")] +pub fn publish( + name: String, + upload: Json, + session: AuthHeader, + connection: db::Connection, +) -> ApiResult> { + let user = session + .verify(&connection) .bad_request() .public_context("Invalid auth token")?; @@ -115,7 +131,9 @@ pub fn publish(name: String, upload: Json, session: AuthHeader, .bad_request() .public_context("Module name is invalid")?; - let metadata = upload.code.parse::() + let metadata = upload + .code + .parse::() .bad_request() .public_context("Failed to parse module metadata")?; @@ -134,8 +152,9 @@ pub fn publish(name: String, upload: Json, session: AuthHeader, if release.code != upload.code { bad_request!("Version number already in use") } - }, - None => module.add_version(&version, &upload.code, &connection) + } + None => module + .add_version(&version, &upload.code, &connection) .private_context("Failed to add release")?, } @@ -150,11 +169,13 @@ pub fn publish(name: String, upload: Json, session: AuthHeader, } #[get("/whoami")] -pub fn whoami(session: AuthHeader, connection: db::Connection) -> ApiResult> { - let user = session.verify(&connection) +pub fn whoami( + session: AuthHeader, + connection: db::Connection, +) -> ApiResult> { + let user = session + .verify(&connection) .bad_request() .public_context("Invalid auth token")?; - Ok(ApiResponse::Success(WhoamiResponse { - user, - })) + Ok(ApiResponse::Success(WhoamiResponse { user })) } diff --git a/sn0int-registry/src/routes/assets.rs b/sn0int-registry/src/routes/assets.rs index 21d2fe96..f7f1f3d9 100644 --- a/sn0int-registry/src/routes/assets.rs +++ b/sn0int-registry/src/routes/assets.rs @@ -1,7 +1,6 @@ use crate::assets::*; -use rocket::http::{ContentType, Status}; use rocket::http::hyper::header::{CacheControl, CacheDirective}; - +use rocket::http::{ContentType, Status}; #[derive(Responder)] pub struct CachableResponder { @@ -54,7 +53,10 @@ pub fn style(rev: String) -> Result { #[get("/assets//script.js")] pub fn javascript(rev: String) -> Result { if rev == *ASSET_REV { - Ok(CachableResponder::immutable(JAVASCRIPT, ContentType::JavaScript)) + Ok(CachableResponder::immutable( + JAVASCRIPT, + ContentType::JavaScript, + )) } else { Err(Status::NotFound) } @@ -68,7 +70,10 @@ pub fn social_card() -> CachableResponder { #[get("/assets//clipboard.min.js")] pub fn javascript_clipboard(rev: String) -> Result { if rev == *ASSET_REV { - Ok(CachableResponder::immutable(JAVASCRIPT_CLIPBOARD, ContentType::JavaScript)) + Ok(CachableResponder::immutable( + JAVASCRIPT_CLIPBOARD, + ContentType::JavaScript, + )) } else { Err(Status::NotFound) } @@ -77,7 +82,10 @@ pub fn javascript_clipboard(rev: String) -> Result { #[get("/assets//fontawesome/css/all.min.css")] pub fn fontawesome_style(rev: String) -> Result { if rev == *ASSET_REV { - Ok(CachableResponder::immutable(FA_STYLESHEET, ContentType::CSS)) + Ok(CachableResponder::immutable( + FA_STYLESHEET, + ContentType::CSS, + )) } else { Err(Status::NotFound) } @@ -86,7 +94,7 @@ pub fn fontawesome_style(rev: String) -> Result { #[get("/assets//fontawesome/webfonts/")] pub fn fontawesome_font(rev: String, font: String) -> Result { if rev != *ASSET_REV { - return Err(Status::NotFound) + return Err(Status::NotFound); } let (content_type, bytes) = match font.as_str() { diff --git a/sn0int-registry/src/routes/auth.rs b/sn0int-registry/src/routes/auth.rs index 7b2a2138..25293d65 100644 --- a/sn0int-registry/src/routes/auth.rs +++ b/sn0int-registry/src/routes/auth.rs @@ -1,34 +1,40 @@ -use sn0int_registry::errors::*; +use crate::assets::ASSET_REV; use crate::auth::Authenticator; -use sn0int_registry::db; use rocket::request::Form; use rocket::response::Redirect; use rocket_contrib::templates::Template; -use crate::assets::ASSET_REV; use serde_json::{self, Value}; - +use sn0int_registry::db; +use sn0int_registry::errors::*; #[get("/?")] pub fn get(auth: Form) -> Template { let auth = auth.into_inner(); let mut auth = serde_json::to_value(&auth).expect("OAuth serialization failed"); if let Value::Object(ref mut map) = auth { - map.insert("ASSET_REV".to_string(), Value::String(ASSET_REV.to_string())); + map.insert( + "ASSET_REV".to_string(), + Value::String(ASSET_REV.to_string()), + ); } Template::render("auth-confirm", auth) } -#[post("/", data="")] +#[post("/", data = "")] pub fn post(auth: Form, connection: db::Connection) -> ApiResult