aboutsummaryrefslogtreecommitdiff
path: root/crates/iam/src/main.rs
diff options
context:
space:
mode:
authorbenj <benj@rse8.com>2022-12-12 17:06:57 -0800
committerbenj <benj@rse8.com>2022-12-12 17:06:57 -0800
commit0920c4d4f30a3345870d385d5c6f3e0919228b56 (patch)
treef54668d91db469b7304758893a51b590c8f9b0de /crates/iam/src/main.rs
parent3a4de13528fc85dcbe6bc9055d97ba5cc87f5712 (diff)
downloadsecdiam-0920c4d4f30a3345870d385d5c6f3e0919228b56.tar
secdiam-0920c4d4f30a3345870d385d5c6f3e0919228b56.tar.gz
secdiam-0920c4d4f30a3345870d385d5c6f3e0919228b56.tar.bz2
secdiam-0920c4d4f30a3345870d385d5c6f3e0919228b56.tar.lz
secdiam-0920c4d4f30a3345870d385d5c6f3e0919228b56.tar.xz
secdiam-0920c4d4f30a3345870d385d5c6f3e0919228b56.tar.zst
secdiam-0920c4d4f30a3345870d385d5c6f3e0919228b56.zip
(oauth2 + email added): a mess that may or may not really work and needs to be refactored...
Diffstat (limited to 'crates/iam/src/main.rs')
-rw-r--r--crates/iam/src/main.rs108
1 files changed, 85 insertions, 23 deletions
diff --git a/crates/iam/src/main.rs b/crates/iam/src/main.rs
index c187380..85b3e37 100644
--- a/crates/iam/src/main.rs
+++ b/crates/iam/src/main.rs
@@ -2,10 +2,17 @@ mod api;
mod command;
mod util;
-use api::{AdminAction, Args, CliError, Command, CreateObject, GetObject, LinkObject, ListObject};
+use anyhow::bail;
+use api::{
+ AdminAction, AdminObject, Args, CliError, Command, CreateObject, DevObject, GetObject,
+ LinkObject, ListObject, Validation,
+};
use clap::Parser;
+use command::dev_oauth2_listen;
+use env_logger::Env;
use secd::{Secd, SecdError};
-use util::Result;
+use util::{error_detail, Result};
+use uuid::Uuid;
use crate::api::ValidationMethod;
@@ -15,8 +22,9 @@ const CONFIG_LOGIN_TEMPLATE: &str = "default_login.html";
const CONFIG_SIGNUP_TEMPLATE: &str = "default_signup.html";
const ISSUE_TRACKER_LOC: &str = "https://www.github.com/secdiam/iam";
-#[async_std::main]
+#[tokio::main]
async fn main() {
+ env_logger::init_from_env(Env::default().default_filter_or("debug"));
match exec().await {
Ok(Some(s)) => println!("{}", s),
Err(e) => {
@@ -30,10 +38,15 @@ async fn main() {
async fn exec() -> Result<Option<String>> {
let args = Args::parse();
Ok(match args.command {
- Command::Init { interactive } => admin(AdminAction::Init { interactive })
- .await
- .map_err(|_| CliError::AdminInitializationError)?,
- Command::Admin { action } => admin(action).await?,
+ Command::Init { interactive }
+ | Command::Admin {
+ action: AdminAction::Init { interactive },
+ } => {
+ command::admin_init(interactive)
+ .await
+ .map_err(|_| CliError::AdminInitializationError)?;
+ None
+ }
rest @ _ => {
let cfg = util::read_config(args.profile).map_err(|_| CliError::InvalidProfile)?;
@@ -48,8 +61,14 @@ async fn exec() -> Result<Option<String>> {
.map_err(|e| CliError::SecdInitializationFailure(e.to_string()))?;
match rest {
+ Command::Admin { action } => admin(&secd, action).await?,
Command::Create { object } => create(&secd, object).await?,
+ Command::Dev { object } => dev(object).await?,
Command::Get { object } => get(&secd, object).await?,
+ Command::Init { .. } => bail!(CliError::InternalError(error_detail(
+ "4a696b66-6231-4a2f-811c-4448a41473d2",
+ "Code path should be unreachable",
+ ))),
Command::Link { object, unlink } => link(&secd, object, unlink).await?,
Command::Ls {
object,
@@ -60,28 +79,30 @@ async fn exec() -> Result<Option<String>> {
Command::Repl => {
unimplemented!()
}
- _ => None,
}
}
})
}
-async fn admin(cmd: AdminAction) -> Result<Option<String>> {
+async fn admin(secd: &Secd, cmd: AdminAction) -> Result<Option<String>> {
Ok(match cmd {
AdminAction::Backend { action } => {
println!("do backend stuff!");
None
}
- AdminAction::Create { object } => {
- println!("do create!");
- None
- }
- AdminAction::Init { interactive } => {
- command::admin_init(interactive)
- .await
- .map_err(|_| CliError::AdminInitializationError)?;
- None
- }
+ AdminAction::Create { object } => match object {
+ AdminObject::Oauth2Provider {
+ provider,
+ client_id,
+ secret,
+ redirect_url,
+ } => {
+ secd.create_oauth_provider(&provider, client_id, secret, redirect_url)
+ .await?;
+ None
+ }
+ rest @ _ => unimplemented!(),
+ },
AdminAction::Seal => {
println!("do seal");
None
@@ -90,6 +111,9 @@ async fn admin(cmd: AdminAction) -> Result<Option<String>> {
println!("do unseal: {}", secret_key);
None
}
+ AdminAction::Init { .. } => {
+ panic!("Invariant violation: this path should be impossible")
+ }
})
}
async fn create(secd: &Secd, cmd: CreateObject) -> Result<Option<String>> {
@@ -130,19 +154,57 @@ async fn create(secd: &Secd, cmd: CreateObject) -> Result<Option<String>> {
.await
.map_err(|e| match e {
SecdError::InvalidCode => CliError::InvalidCode,
- _ => CliError::Unknown,
+ _ => CliError::InternalError(error_detail(
+ "17e5c226-5d7d-44a2-b3b5-be3ee958c252",
+ "An unknown error while exchanging a session",
+ )),
})?;
serde_json::to_string(&session).ok()
}
CreateObject::Validation { method, identity } => match method {
- ValidationMethod::Email { address } => {
- secd.create_validation_request(Some(&address)).await?;
- None
+ ValidationMethod::Email { address } => serde_json::to_string(&Validation {
+ validation_id: secd.create_validation_request_email(Some(&address)).await?,
+ note: Some("<secret code> sent to client".into()),
+ oauth_auth_url: None,
+ })
+ .ok(),
+
+ ValidationMethod::Oauth2 {
+ provider,
+ scope,
+ identity,
+ } => {
+ let redirect = secd
+ .create_validation_request_oauth(&provider, scope)
+ .await?
+ .to_string();
+ let validation_id = redirect
+ .split("state=")
+ .collect::<Vec<&str>>()
+ .last()
+ .map(|i| Uuid::parse_str(i).ok())
+ .flatten()
+ .unwrap();
+ serde_json::to_string(&Validation {
+ validation_id,
+ note: Some(
+ "<secret code> is retrieved by completing oauth flow in the browser".into(),
+ ),
+ oauth_auth_url: Some(redirect),
+ })
+ .ok()
}
_ => unimplemented!(),
},
})
}
+
+async fn dev(cmd: DevObject) -> Result<Option<String>> {
+ Ok(match cmd {
+ DevObject::Oauth2Server { port } => serde_json::to_string(&dev_oauth2_listen(port)?).ok(),
+ })
+}
+
async fn get(secd: &Secd, cmd: GetObject) -> Result<Option<String>> {
Ok(match cmd {
GetObject::ApiKey { public_key } => {