Skip to content

Commit

Permalink
fix: oauth apps only allowed to be created in the web (#260)
Browse files Browse the repository at this point in the history
  • Loading branch information
sagojez authored Feb 26, 2025
1 parent ec58628 commit 5068d4d
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 86 deletions.
4 changes: 2 additions & 2 deletions cli/src/domain/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ pub const URL_PROVIDED_IS_INVALID: &str = "URL provided is invalid";
pub const FORM_VALIDATION_FAILED: &str = "Form validation failed";

// Suggestions
pub const RUN_PICA_CONFIGURATION_SUG: &str =
"Run `pica configure` to createa a configuration file.";
pub const RUN_PICA_CONFIGURATION_SUG: &str = "Run `pica login` to create a configuration file.";
pub const CHECK_INTERNET_CONNECTION_SUG: &str = "Check your internet connection and try again";
pub const CHECK_PARAMETERS_SUG: &str = "Check the parameters and try again";
pub const CHECK_LIMIT_SUG: &str = "Try with a smaller limit";
Expand All @@ -30,6 +29,7 @@ pub const CHECK_AVAILABLE_CONN_DEFS_SUG: &str =

// Instructions
pub const GO_TO_URL: &str = "Go to the following url: ";
pub const GO_TO_TERMINAL: &str = "Please continue in the terminal. Happy hacking!";

// Metadata
pub const ABOUT: &str = "Build performant, high-converting native integrations with a few lines of code. By unlocking more integrations, you can onboard more customers and expand app usage, overnight.";
130 changes: 56 additions & 74 deletions cli/src/service/command.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use super::{Server, handle_response, readline};
use super::{Server, handle_response, open_browser, readline};
use crate::{
algebra::Handler,
domain::{
ABOUT, AppContext, CHECK_AVAILABLE_CONN_DEFS_SUG, CHECK_LIMIT_SUG,
CONN_DEF_NOT_FOUND_MESSAGE_ERR, CONNECTION_NOT_FOUND_MESSAGE_ERR, CliConfig, DEFAULT_LIMIT,
FORM_VALIDATION_FAILED, GO_TO_URL, HEADER_SECRET_KEY, LIMIT_GREATER_THAN_EXPECTED,
FORM_VALIDATION_FAILED, HEADER_SECRET_KEY, LIMIT_GREATER_THAN_EXPECTED,
RUN_LIST_COMMANDS_SUG, ReadResponse, Step, URL_PROVIDED_IS_INVALID,
},
};
Expand All @@ -16,9 +16,9 @@ use entities::{
use serde::Deserialize;
use serde_json::{Value, json};
use std::{
collections::HashMap,
collections::{HashMap, HashSet},
fmt::{Display, Formatter},
time::Duration,
hash::RandomState,
};
use tabled::{Table, settings::Style};
use url::Url;
Expand All @@ -44,8 +44,8 @@ impl Pica {
pub enum Command {
/// Manage connections via the CLI.
Connection(Connection),
/// Configure the CLI. It truncates the configuration file and creates a new one.
Configure {
/// Configures the CLI. It truncates the configuration file and creates a new one.
Login {
/// Base url of the API
#[arg(short, long)]
base: Option<String>,
Expand Down Expand Up @@ -138,7 +138,7 @@ impl Display for Environment {
impl Handler<AppContext, Command, Event> for Pica {
async fn load(&self) -> Result<AppContext, PicaError> {
match self.command() {
Command::Configure { base, api } => {
Command::Login { base, api } => {
Server::start(base.clone(), api.clone()).await?;

Ok(AppContext::new(CliConfig::load()))
Expand All @@ -149,7 +149,7 @@ impl Handler<AppContext, Command, Event> for Pica {

async fn validate(&self, ctx: &AppContext) -> Result<Unit, PicaError> {
match &self.command {
Command::Configure { base, api } => {
Command::Login { base, api } => {
if let Some(base) = base {
Url::parse(base).map_err(|e| {
ctx.printer().stderr::<Pica>(
Expand Down Expand Up @@ -196,38 +196,62 @@ impl Handler<AppContext, Command, Event> for Pica {

async fn run(&self, ctx: &AppContext) -> Result<Unit, PicaError> {
match &self.command {
Command::Configure { .. } => Ok(()),
Command::Login { .. } => Ok(()),
Command::Connection(Connection { command }) => match command {
ConnectionCommand::Create { platform, web, env } => {
let secret = match env {
Environment::Sandbox => ctx.config().keys().sandbox(),
Environment::Production => ctx.config().keys().production(),
};
let url = format!(
"{}/public/v1/event-links/create-embed-token",
ctx.config().server().api()
);

let embed_defs = handle_response::<EmbedTokenSlim>(
ctx.http()
.post(url)
.json(&json!({}))
.header(HEADER_SECRET_KEY, secret)
.send()
.await,
ctx.printer(),
)
.await?;

let platforms: HashSet<String, RandomState> = HashSet::from_iter(
embed_defs
.link_settings
.connected_platforms
.iter()
.map(|c| c.r#type.clone()),
);

match platform {
Some(platform) => {
if *web {
// https://development.picaos.com/connections#create
let url = format!(
"{}/connections#create={}",
ctx.config().server().base(),
platform
);
Some(platform) if platforms.contains(platform) => {
let url = format!(
"{}/v1/public/connection-definitions?platform={}",
ctx.config().server().api(),
platform
);

ctx.printer()
.stdout(&(GO_TO_URL.to_string() + url.as_str()));
let conn_def = handle_response::<ReadResponse<ConnectionDefinition>>(
ctx.http().get(url).send().await,
ctx.printer(),
)
.await?;
let conn_def = conn_def.rows().first();

tokio::time::sleep(Duration::from_secs(1)).await;
} else {
if *web || conn_def.is_some_and(|cd| cd.is_oauth()) {
let url = format!(
"{}/v1/public/connection-definitions?platform={}",
ctx.config().server().api(),
"{}/connections#open={}",
ctx.config().server().base(),
platform
);

match handle_response::<ReadResponse<ConnectionDefinition>>(
ctx.http().get(url).send().await,
ctx.printer(),
)
.await?
.rows()
.first()
{
open_browser(ctx.printer(), url.to_string());
} else {
match conn_def {
Some(conn_def) => {
let steps = Step::from(conn_def);

Expand Down Expand Up @@ -261,28 +285,6 @@ impl Handler<AppContext, Command, Event> for Pica {
},
)?;

let secret = match env {
Environment::Sandbox => ctx.config().keys().sandbox(),
Environment::Production => {
ctx.config().keys().production()
}
};
let url = format!(
"{}/public/v1/event-links/create-embed-token",
ctx.config().server().api()
);

let embed_defs = handle_response::<EmbedTokenSlim>(
ctx.http()
.post(url)
.json(&json!({}))
.header(HEADER_SECRET_KEY, secret)
.send()
.await,
ctx.printer(),
)
.await?;

let link_token = embed_defs.link_settings.event_inc_token;

let url = format!(
Expand Down Expand Up @@ -326,27 +328,7 @@ impl Handler<AppContext, Command, Event> for Pica {
}
}
}
None => {
let secret = match env {
Environment::Sandbox => ctx.config().keys().sandbox(),
Environment::Production => ctx.config().keys().production(),
};
let url = format!(
"{}/public/v1/event-links/create-embed-token",
ctx.config().server().api()
);

let embed_defs = handle_response::<EmbedTokenSlim>(
ctx.http()
.post(url)
.json(&json!({}))
.header(HEADER_SECRET_KEY, secret)
.send()
.await,
ctx.printer(),
)
.await?;

_ => {
ctx.printer().stdout(CHECK_AVAILABLE_CONN_DEFS_SUG);

ctx.printer().stdout(
Expand Down
26 changes: 25 additions & 1 deletion cli/src/service/helper.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::{Pica, Printer};
use crate::domain::{CHECK_INTERNET_CONNECTION_SUG, CHECK_PARAMETERS_SUG};
use crate::domain::{CHECK_INTERNET_CONNECTION_SUG, CHECK_PARAMETERS_SUG, GO_TO_URL};
use clap::error::ErrorKind;
use entities::{InternalError, PicaError};
use reqwest::{Error as ReqwestError, Response};
Expand Down Expand Up @@ -48,3 +48,27 @@ pub fn readline() -> Result<String, PicaError> {

Ok(buffer)
}

pub fn open_browser(printer: &Printer, url: String) {
#[cfg(target_os = "macos")]
let result = std::process::Command::new("open")
.arg(url.as_str())
.spawn()
.and_then(|mut a| a.wait());

#[cfg(target_os = "windows")]
let result = std::process::Command::new("explorer")
.arg(url.as_str())
.spawn()
.and_then(|mut a| a.wait());

#[cfg(target_os = "linux")]
let result = std::process::Command::new("xdg-open")
.arg(url.as_str())
.spawn()
.and_then(|mut a| a.wait());

if result.is_err() {
printer.stdout(&(GO_TO_URL.to_string() + url.as_str()));
}
}
17 changes: 9 additions & 8 deletions cli/src/service/server.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use crate::{
domain::Server as ConfigServer,
domain::{
CHECK_PORT_FOR_SERVER_SUG, CliConfig, DEFAULT_API, DEFAULT_BASE, GO_TO_URL, Http, Keys,
RUN_PICA_CONNECTION_LIST_SUG,
CHECK_PORT_FOR_SERVER_SUG, CliConfig, DEFAULT_API, DEFAULT_BASE, GO_TO_TERMINAL, Http,
Keys, RUN_PICA_CONNECTION_LIST_SUG, Server as ConfigServer,
},
service::{Pica, Printer},
service::{Pica, Printer, open_browser},
};
use axum::{Router, extract::Query, routing::get};
use axum::{Router, extract::Query, response::Html, routing::get};
use clap::error::ErrorKind;
use entities::{InternalError, PicaError, Unit};
use reqwest::Client;
Expand Down Expand Up @@ -86,7 +85,9 @@ impl Server {
InternalError::io_err(&format!("{e}"), None)
})?;

printer.stdout(&(GO_TO_URL.to_string() + &url));
open_browser(&printer, url.to_string());

// printer.stdout(&(GO_TO_URL.to_string() + &url));

let server = axum::serve(listener, router);
let server_handle = tokio::spawn(async move {
Expand Down Expand Up @@ -139,7 +140,7 @@ impl Server {
printer: Printer,
base_url: Option<String>,
api_url: Option<String>,
) -> Result<Unit, PicaError> {
) -> Result<Html<String>, PicaError> {
let url = format!(
"{}/auth/github",
api_url.clone().unwrap_or(DEFAULT_API.to_string())
Expand Down Expand Up @@ -196,6 +197,6 @@ impl Server {

printer.stdout(RUN_PICA_CONNECTION_LIST_SUG);

Ok(())
Ok(Html(format!("<p>{}</p>", GO_TO_TERMINAL)))
}
}
4 changes: 4 additions & 0 deletions entities/src/domain/connection/connection_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ pub struct ModelSorting {
}

impl ConnectionDefinition {
pub fn is_oauth(&self) -> bool {
self.settings.oauth
}

pub fn to_connection_type(&self) -> super::ConnectionType {
match self.r#type {
ConnectionDefinitionType::Api => ConnectionType::Api {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ impl Settings {
#[serde(rename_all = "camelCase")]
#[tabled(rename_all = "PascalCase")]
pub struct ConnectedPlatformSlim {
#[tabled(rename = "platform")]
#[tabled(rename = "Platform")]
pub r#type: String,
pub title: String,
pub connection_definition_id: Id,
Expand Down

0 comments on commit 5068d4d

Please sign in to comment.