diff options
Diffstat (limited to 'rust/src')
-rw-r--r-- | rust/src/auth.rs | 20 | ||||
-rw-r--r-- | rust/src/bin/fatcat-auth.rs | 39 | ||||
-rw-r--r-- | rust/src/bin/fatcat-export.rs | 18 | ||||
-rw-r--r-- | rust/src/lib.rs | 26 |
4 files changed, 54 insertions, 49 deletions
diff --git a/rust/src/auth.rs b/rust/src/auth.rs index 0fe21ebe..450a19d6 100644 --- a/rust/src/auth.rs +++ b/rust/src/auth.rs @@ -40,22 +40,24 @@ pub struct AuthConfectionary { } impl AuthConfectionary { - pub fn new(location: String, identifier: String, key: Vec<u8>) -> AuthConfectionary { + pub fn new(location: String, identifier: String, key_base64: String) -> Result<AuthConfectionary> { + let key = BASE64.decode(key_base64.as_bytes())?; let mut root_keys = HashMap::new(); root_keys.insert(identifier.clone(), key.clone()); - AuthConfectionary { + Ok(AuthConfectionary { location: location, identifier: identifier, key: key, root_keys: root_keys, - } + }) } pub fn new_dummy() -> AuthConfectionary { AuthConfectionary::new( "test.fatcat.wiki".to_string(), "dummy".to_string(), - DUMMY_KEY.to_vec()) + BASE64.encode(DUMMY_KEY), + ).unwrap() } pub fn create_token(&self, editor_id: FatCatId, expires: Option<DateTime<Utc>>) -> Result<String> { @@ -180,7 +182,15 @@ impl AuthConfectionary { } } -pub fn revoke_tokens(conn: &DbConn, editor_id: FatCatId) -> Result<()>{ +pub fn create_key() -> String { + let mut key: Vec<u8> = vec![0; 32]; + for v in key.iter_mut() { + *v = rand::random() + } + BASE64.encode(&key) +} + +pub fn revoke_tokens(conn: &DbConn, editor_id: FatCatId) -> Result<()> { diesel::update(editor::table.filter(editor::id.eq(&editor_id.to_uuid()))) .set(editor::auth_epoch.eq(Utc::now())) .execute(conn)?; diff --git a/rust/src/bin/fatcat-auth.rs b/rust/src/bin/fatcat-auth.rs index 5a8f0f98..3240964f 100644 --- a/rust/src/bin/fatcat-auth.rs +++ b/rust/src/bin/fatcat-auth.rs @@ -14,12 +14,8 @@ extern crate serde_json; extern crate uuid; use clap::{App, SubCommand}; -use dotenv::dotenv; -use std::env; use diesel::prelude::*; -use diesel::r2d2::ConnectionManager; -use fatcat::ConnectionPool; use fatcat::errors::*; use fatcat::api_helpers::FatCatId; use std::str::FromStr; @@ -31,18 +27,6 @@ use std::str::FromStr; //use std::io::{BufReader, BufWriter}; -/// Instantiate a new API server with a pooled database connection -// TODO: copypasta from fatcat-export -pub fn database_worker_pool() -> Result<ConnectionPool> { - dotenv().ok(); - let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); - let manager = ConnectionManager::<PgConnection>::new(database_url); - let pool = diesel::r2d2::Pool::builder() - .build(manager) - .expect("Failed to create database pool."); - Ok(pool) -} - fn run() -> Result<()> { let m = App::new("fatcat-auth") .version(env!("CARGO_PKG_VERSION")) @@ -66,7 +50,7 @@ fn run() -> Result<()> { .about("Creates a new auth token (macaroon) for the given editor") .args_from_usage( "<editor-id> 'id of the editor (fatcatid, not username)' - --env-format 'outputs in a format that shells can source'" + --env-format 'outputs in a format that shells can source'" // TODO ) ) .subcommand( @@ -77,6 +61,13 @@ fn run() -> Result<()> { ) ) .subcommand( + SubCommand::with_name("create-key") + .about("Creates a new auth secret key (aka, root/signing key for tokens)") + .args_from_usage( + "--env-format 'outputs in a format that shells can source'" // TODO + ) + ) + .subcommand( SubCommand::with_name("revoke-tokens") .about("Resets auth_epoch for a single editor (invalidating all existing tokens)") .args_from_usage( @@ -89,8 +80,18 @@ fn run() -> Result<()> { ) .get_matches(); - let db_conn = database_worker_pool()?.get().expect("database pool"); - let confectionary = fatcat::auth::AuthConfectionary::new_dummy(); + // First, the commands with no db or confectionary needed + match m.subcommand() { + ("create-key", Some(_subm)) => { + println!("{}", fatcat::auth::create_key()); + return Ok(()) + }, + _ => (), + } + + // Then the ones that do + let db_conn = fatcat::database_worker_pool()?.get().expect("database pool"); + let confectionary = fatcat::env_confectionary()?; match m.subcommand() { ("list-editors", Some(_subm)) => { fatcat::auth::print_editors(&db_conn)?; diff --git a/rust/src/bin/fatcat-export.rs b/rust/src/bin/fatcat-export.rs index ec66ed4c..e1b930fc 100644 --- a/rust/src/bin/fatcat-export.rs +++ b/rust/src/bin/fatcat-export.rs @@ -17,15 +17,10 @@ extern crate serde_json; extern crate uuid; use clap::{App, Arg}; -use dotenv::dotenv; -use std::env; -use diesel::prelude::*; -use diesel::r2d2::ConnectionManager; use fatcat::api_entity_crud::*; use fatcat::api_helpers::*; use fatcat::errors::*; -use fatcat::ConnectionPool; use fatcat_api_spec::models::*; use std::str::FromStr; use uuid::Uuid; @@ -59,17 +54,6 @@ struct IdentRow { redirect_id: Option<FatCatId>, } -/// Instantiate a new API server with a pooled database connection -pub fn database_worker_pool() -> Result<ConnectionPool> { - dotenv().ok(); - let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); - let manager = ConnectionManager::<PgConnection>::new(database_url); - let pool = diesel::r2d2::Pool::builder() - .build(manager) - .expect("Failed to create database pool."); - Ok(pool) -} - macro_rules! generic_loop_work { ($fn_name:ident, $entity_model:ident) => { fn $fn_name( @@ -183,7 +167,7 @@ pub fn do_export( entity_type: ExportEntityType, redirects: bool, ) -> Result<()> { - let db_pool = database_worker_pool()?; + let db_pool = fatcat::database_worker_pool()?; let buf_input = BufReader::new(std::io::stdin()); let (row_sender, row_receiver) = channel::bounded(CHANNEL_BUFFER_LEN); let (output_sender, output_receiver) = channel::bounded(CHANNEL_BUFFER_LEN); diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 983645d8..233f8642 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -93,20 +93,29 @@ use dotenv::dotenv; use iron::middleware::AfterMiddleware; use iron::{Request, Response}; use std::env; +use auth::AuthConfectionary; #[cfg(feature = "postgres")] embed_migrations!("../migrations/"); pub type ConnectionPool = diesel::r2d2::Pool<ConnectionManager<diesel::pg::PgConnection>>; -/// Establish a direct database connection. Not currently used, but could be helpful for -/// single-threaded tests or utilities. -pub fn establish_connection() -> PgConnection { +/// Instantiate a new API server with a pooled database connection +pub fn database_worker_pool() -> Result<ConnectionPool> { dotenv().ok(); - let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); - PgConnection::establish(&database_url) - .unwrap_or_else(|_| panic!("Error connecting to {}", database_url)) + let manager = ConnectionManager::<PgConnection>::new(database_url); + let pool = diesel::r2d2::Pool::builder() + .build(manager) + .expect("Failed to create database pool."); + Ok(pool) +} + +pub fn env_confectionary() -> Result<AuthConfectionary> { + let auth_location = env::var("AUTH_LOCATION").expect("AUTH_LOCATION must be set"); + let auth_key = env::var("AUTH_SECRET_KEY").expect("AUTH_SECRET_KEY must be set"); + let auth_key_ident = env::var("AUTH_KEY_IDENT").expect("AUTH_KEY_IDENT must be set"); + AuthConfectionary::new(auth_location, auth_key_ident, auth_key) } /// Instantiate a new API server with a pooled database connection @@ -117,7 +126,7 @@ pub fn server() -> Result<api_server::Server> { let pool = diesel::r2d2::Pool::builder() .build(manager) .expect("Failed to create database pool."); - let confectionary = auth::AuthConfectionary::new_dummy(); + let confectionary = env_confectionary()?; Ok(api_server::Server { db_pool: pool, auth_confectionary: confectionary }) } @@ -126,7 +135,8 @@ pub fn test_server() -> Result<api_server::Server> { let database_url = env::var("TEST_DATABASE_URL").expect("TEST_DATABASE_URL must be set"); env::set_var("DATABASE_URL", database_url); - let server = server()?; + let mut server = server()?; + server.auth_confectionary = AuthConfectionary::new_dummy(); let conn = server.db_pool.get().expect("db_pool error"); // run migrations; revert latest (dummy data); re-run latest |