@smbcloud / cli / commits / 17bcc3c

Manage apps

Seto Elkahfi committed May 6, 2023 at 17:39 UTC 17bcc3c2fef1460977cf4104dbc0e122bfc18827
20 files changed +1048 -140
Cargo.lock
+58 -9
@@ -40,19 +40,30 @@ checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"
40
41 [[package]]
42 name = "app-fun"
43 -version = "0.1.0"
43 +version = "0.3.2"
44 dependencies = [
45 "anyhow",
46 + "async-trait",
47 "clap",
48 "console",
49 "dialoguer",
50 + "dirs",
51 + "home",
52 + "log",
53 + "maybe-async",
54 + "reqwest",
55 + "serde",
56 + "serde_json",
57 "smbpndk-model",
58 + "smbpndk-networking",
59 + "smbpndk-utils",
60 "spinners",
61 + "thiserror",
62 ]
63
64 [[package]]
65 name = "app-oten"
55 -version = "0.1.0"
66 +version = "0.3.2"
67 dependencies = [
68 "anyhow",
69 "async-trait",
@@ -75,11 +86,49 @@ dependencies = [
86
87 [[package]]
88 name = "app-pkt"
78 -version = "0.1.0"
89 +version = "0.3.2"
90 +dependencies = [
91 + "anyhow",
92 + "async-trait",
93 + "clap",
94 + "console",
95 + "dialoguer",
96 + "dirs",
97 + "home",
98 + "log",
99 + "maybe-async",
100 + "reqwest",
101 + "serde",
102 + "serde_json",
103 + "smbpndk-model",
104 + "smbpndk-networking",
105 + "smbpndk-utils",
106 + "spinners",
107 + "thiserror",
108 +]
109
110 [[package]]
111 name = "app-rdb"
82 -version = "0.1.0"
112 +version = "0.3.2"
113 +dependencies = [
114 + "anyhow",
115 + "async-trait",
116 + "clap",
117 + "console",
118 + "dialoguer",
119 + "dirs",
120 + "home",
121 + "log",
122 + "maybe-async",
123 + "reqwest",
124 + "serde",
125 + "serde_json",
126 + "smbpndk-model",
127 + "smbpndk-networking",
128 + "smbpndk-utils",
129 + "spinners",
130 + "thiserror",
131 +]
132
133 [[package]]
134 name = "async-trait"
@@ -1265,7 +1314,7 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
1314
1315 [[package]]
1316 name = "smbpndk-cli"
1268 -version = "0.2.2"
1317 +version = "0.3.2"
1318 dependencies = [
1319 "anyhow",
1320 "app-fun",
@@ -1300,7 +1349,7 @@ dependencies = [
1349
1350 [[package]]
1351 name = "smbpndk-model"
1303 -version = "0.1.0"
1352 +version = "0.3.2"
1353 dependencies = [
1354 "chrono",
1355 "serde",
@@ -1310,7 +1359,7 @@ dependencies = [
1359
1360 [[package]]
1361 name = "smbpndk-networking"
1313 -version = "0.1.0"
1362 +version = "0.3.2"
1363 dependencies = [
1364 "anyhow",
1365 "async-trait",
@@ -1327,7 +1376,7 @@ dependencies = [
1376
1377 [[package]]
1378 name = "smbpndk-networking-project"
1330 -version = "0.1.0"
1379 +version = "0.3.2"
1380 dependencies = [
1381 "anyhow",
1382 "async-trait",
@@ -1345,7 +1394,7 @@ dependencies = [
1394
1395 [[package]]
1396 name = "smbpndk-utils"
1348 -version = "0.1.0"
1397 +version = "0.3.2"
1398 dependencies = [
1399 "anyhow",
1400 "dirs",
app-fun/Cargo.toml
+12 -1
@@ -13,8 +13,19 @@ readme = "../README.md"
13
14 [dependencies]
15 anyhow = "1.0.58"
16 +async-trait = { version = "0.1.51", optional = true }
17 clap = { version = "4.1.6", features = ["derive"] }
18 console = "0.15.0"
19 dialoguer = "0.10.4"
19 -smbpndk-model = { path = "../smbpndk-model" }
20 +dirs = "4.0.0"
21 +home = "0.5.4"
22 +log = "0.4.14"
23 +maybe-async = { version = "0.2", features = ["is_sync"] }
24 +reqwest = { version = "0.11", features = ["json"] }
25 +serde = { version = "1", features = ["derive"] }
26 +serde_json = "1.0.82"
27 +smbpndk-model = { version = "0.3", path = "../smbpndk-model" }
28 +smbpndk-networking = { version = "0.3", path = "../smbpndk-networking" }
29 +smbpndk-utils = { version = "0.3", path = "../smbpndk-utils" }
30 spinners = "4.1.0"
31 +thiserror = "1.0.29"
app-fun/src/handler.rs
+143 -41
@@ -1,74 +1,176 @@
1 -use crate::cli::Commands;
2 -use anyhow::Result;
1 +use crate::{cli::Commands, create_fun_app, delete_fun_app, get_fun_app, get_fun_apps};
2 +use anyhow::{anyhow, Result};
3 use console::style;
4 -use smbpndk_model::CommandResult;
4 +use dialoguer::{theme::ColorfulTheme, Confirm, Input};
5 +use smbpndk_model::{AppCreate, CommandResult};
6 +use smbpndk_utils::{get_config, write_config};
7 use spinners::Spinner;
8
9 pub async fn process_fun_app(commands: Commands) -> Result<CommandResult> {
10 match commands {
11 Commands::New {} => {
12 + let app_name = Input::<String>::with_theme(&ColorfulTheme::default())
13 + .with_prompt("App name")
14 + .interact()
15 + .unwrap();
16 + let description = Input::<String>::with_theme(&ColorfulTheme::default())
17 + .with_prompt("Description")
18 + .interact()
19 + .unwrap();
20 +
21 let spinner = Spinner::new(
22 spinners::Spinners::SimpleDotsScrolling,
12 - style("Creating a Fun app...").green().bold().to_string(),
23 + style("Creating an fun app...").green().bold().to_string(),
24 );
14 - Ok(CommandResult {
15 - spinner,
16 - symbol: "".to_owned(),
17 - msg: "".to_owned(),
25 +
26 + match create_fun_app(AppCreate {
27 + name: app_name.clone(),
28 + description: description.clone(),
29 })
30 + .await
31 + {
32 + Ok(_) => Ok(CommandResult {
33 + spinner,
34 + symbol: "✅".to_owned(),
35 + msg: format!("An fun app created: {app_name}."),
36 + }),
37 + Err(e) => {
38 + println!("Error: {e:#?}");
39 + Ok(CommandResult {
40 + spinner,
41 + symbol: "😩".to_owned(),
42 + msg: format!("Failed to create an fun app: {app_name}."),
43 + })
44 + }
45 + }
46 }
47 Commands::List {} => {
48 let spinner = Spinner::new(
49 spinners::Spinners::SimpleDotsScrolling,
23 - style("Listing Fun apps...").green().bold().to_string(),
50 + style("Loading...").green().bold().to_string(),
51 );
25 - Ok(CommandResult {
26 - spinner,
27 - symbol: "".to_owned(),
28 - msg: "".to_owned(),
29 - })
52 + match get_fun_apps().await {
53 + Ok(fun_apps) => {
54 + println!("fun_apps: {fun_apps:#?}");
55 + println!(
56 + "{0: <10} | {1: <30} | {2: <10} | {3: <10}",
57 + "ID", "Name", "Created at", "Updated at"
58 + );
59 + for project in fun_apps {
60 + let id = project.id.split('-').collect::<Vec<&str>>()[0].to_owned();
61 + let created_at = project.created_at.date_naive();
62 + let updated_at = project.updated_at.date_naive();
63 + println!(
64 + "{0: <10} | {1: <30} | {2: <10} | {3: <10}",
65 + id, project.name, created_at, updated_at
66 + );
67 + }
68 + Ok(CommandResult {
69 + spinner,
70 + symbol: "✅".to_owned(),
71 + msg: "Showing all fun apps.".to_owned(),
72 + })
73 + }
74 + Err(e) => {
75 + println!("Error: {e:#?}");
76 + Ok(CommandResult {
77 + spinner,
78 + symbol: "😩".to_owned(),
79 + msg: "Failed to get all fun apps.".to_owned(),
80 + })
81 + }
82 + }
83 }
84 Commands::Show { id } => {
85 let spinner = Spinner::new(
86 spinners::Spinners::SimpleDotsScrolling,
34 - style(format!("Showing Fun app {id}..."))
35 - .green()
36 - .bold()
37 - .to_string(),
87 + style("Loading...").green().bold().to_string(),
88 );
39 - Ok(CommandResult {
40 - spinner,
41 - symbol: "".to_owned(),
42 - msg: "".to_owned(),
43 - })
89 + match get_fun_app(&id).await {
90 + Ok(_) => Ok(CommandResult {
91 + spinner,
92 + symbol: "✅".to_owned(),
93 + msg: "Showing fun app.".to_owned(),
94 + }),
95 + Err(e) => {
96 + println!("Error: {e:#?}");
97 + Ok(CommandResult {
98 + spinner,
99 + symbol: "😩".to_owned(),
100 + msg: "Failed to get an fun app.".to_owned(),
101 + })
102 + }
103 + }
104 }
105 Commands::Delete { id } => {
106 let spinner = Spinner::new(
107 spinners::Spinners::SimpleDotsScrolling,
48 - style(format!("Deleting Fun app {id}..."))
49 - .green()
50 - .bold()
51 - .to_string(),
108 + style("Loading...").green().bold().to_string(),
109 );
53 - Ok(CommandResult {
54 - spinner,
55 - symbol: "".to_owned(),
56 - msg: "".to_owned(),
57 - })
110 + match delete_fun_app(id).await {
111 + Ok(_) => Ok(CommandResult {
112 + spinner,
113 + symbol: "✅".to_owned(),
114 + msg: "Delete fun app succeed.".to_owned(),
115 + }),
116 + Err(e) => {
117 + println!("Error: {e:#?}");
118 + Ok(CommandResult {
119 + spinner,
120 + symbol: "😩".to_owned(),
121 + msg: "Failed to delete fun app.".to_owned(),
122 + })
123 + }
124 + }
125 }
126 Commands::Use { id } => {
127 + let mut spinner = Spinner::new(
128 + spinners::Spinners::SimpleDotsScrolling,
129 + style("Checking config file...").green().bold().to_string(),
130 + );
131 +
132 + let fun_app = get_fun_app(&id).await?;
133 + let mut config = get_config().await?;
134 +
135 + if let Some(fun_app) = config.current_fun_app {
136 + if fun_app.id != id {
137 + spinner.stop_with_message("Found a config.".to_string());
138 + let yes = Confirm::new()
139 + .with_prompt(format!(
140 + "Will change active fun_app to {}. Do you want to continue?",
141 + &id
142 + ))
143 + .interact()?;
144 + if !yes {
145 + let spinner = Spinner::new(
146 + spinners::Spinners::SimpleDotsScrolling,
147 + style("Cancelling operation...").green().bold().to_string(),
148 + );
149 + return Ok(CommandResult {
150 + spinner,
151 + symbol: "✅".to_owned(),
152 + msg: "Operation cancelled.".to_string(),
153 + });
154 + }
155 + }
156 + }
157 +
158 + config.current_fun_app = Some(fun_app);
159 let spinner = Spinner::new(
160 spinners::Spinners::SimpleDotsScrolling,
62 - style(format!("Using Fun app {id}..."))
63 - .green()
64 - .bold()
65 - .to_string(),
161 + style("Saving config...").green().bold().to_string(),
162 );
67 - Ok(CommandResult {
68 - spinner,
69 - symbol: "".to_owned(),
70 - msg: "".to_owned(),
71 - })
163 + match write_config(config) {
164 + Ok(_) => Ok(CommandResult {
165 + spinner,
166 + symbol: "✅".to_owned(),
167 + msg: format!("Using fun_app: {:?}", &id),
168 + }),
169 + Err(_) => {
170 + let error = anyhow!("Failed while writing config.");
171 + Err(error)
172 + }
173 + }
174 }
175 }
176 }
app-fun/src/lib.rs
+85
@@ -1,2 +1,87 @@
1 pub mod cli;
2 pub mod handler;
3 +
4 +use anyhow::{anyhow, Result};
5 +use log::debug;
6 +use reqwest::Client;
7 +use smbpndk_model::{AppCreate, Fun};
8 +use smbpndk_networking::{constants::BASE_URL, get_token};
9 +
10 +async fn get_fun_apps() -> Result<Vec<Fun>> {
11 + // Get current token
12 + let token = get_token().await?;
13 +
14 + let response = Client::new()
15 + .get([BASE_URL, "v1/fun_apps"].join(""))
16 + .header("Authorization", token)
17 + .send()
18 + .await?;
19 +
20 + match response.status() {
21 + reqwest::StatusCode::OK => {
22 + let fun_apps: Vec<Fun> = response.json().await?;
23 + Ok(fun_apps)
24 + }
25 + _ => Err(anyhow!("Failed to fetch fun apps.")),
26 + }
27 +}
28 +
29 +async fn get_fun_app(id: &str) -> Result<Fun> {
30 + // Get current token
31 + let token = get_token().await?;
32 +
33 + let response = Client::new()
34 + .get([BASE_URL, "v1/fun_apps/", id].join(""))
35 + .header("Authorization", token)
36 + .send()
37 + .await?;
38 +
39 + match response.status() {
40 + reqwest::StatusCode::OK => {
41 + let fun_app: Fun = response.json().await?;
42 + println!("Auth app requested: {fun_app:#?}");
43 + Ok(fun_app)
44 + }
45 + _ => Err(anyhow!(format!("Failed to find an fun app with id: {id}."))),
46 + }
47 +}
48 +
49 +async fn delete_fun_app(id: String) -> Result<()> {
50 + // Get current token
51 + let token = get_token().await?;
52 +
53 + let response = Client::new()
54 + .delete([BASE_URL, "v1/fun_apps/", &id].join(""))
55 + .header("Authorization", token)
56 + .send()
57 + .await?;
58 +
59 + match response.status() {
60 + reqwest::StatusCode::OK => {
61 + debug!("Project deleted.");
62 + Ok(())
63 + }
64 + _ => Err(anyhow!("Failed to delete an fun app.")),
65 + }
66 +}
67 +
68 +async fn create_fun_app(fun_app: AppCreate) -> Result<Fun> {
69 + // Get current token
70 + let token = get_token().await?;
71 +
72 + let response = Client::new()
73 + .post([BASE_URL, "v1/fun_apps"].join(""))
74 + .json(&fun_app)
75 + .header("Authorization", token)
76 + .send()
77 + .await?;
78 +
79 + match response.status() {
80 + reqwest::StatusCode::CREATED => {
81 + let fun_app: Fun = response.json().await?;
82 + println!("Project created: {fun_app:#?}");
83 + Ok(fun_app)
84 + }
85 + _ => Err(anyhow!("Failed to create an fun app.")),
86 + }
87 +}
app-oten/src/handler.rs
+26 -26
@@ -1,12 +1,12 @@
1 -use crate::{cli::Commands, create_auth_app, delete_auth_app, get_auth_app, get_auth_apps};
1 +use crate::{cli::Commands, create_oten_app, delete_oten_app, get_oten_app, get_oten_apps};
2 use anyhow::{anyhow, Result};
3 use console::style;
4 use dialoguer::{theme::ColorfulTheme, Confirm, Input};
5 -use smbpndk_model::{AuthAppCreate, CommandResult};
5 +use smbpndk_model::{AppCreate, CommandResult};
6 use smbpndk_utils::{get_config, write_config};
7 use spinners::Spinner;
8
9 -pub async fn process_auth_app(commands: Commands) -> Result<CommandResult> {
9 +pub async fn process_oten_app(commands: Commands) -> Result<CommandResult> {
10 match commands {
11 Commands::New {} => {
12 let app_name = Input::<String>::with_theme(&ColorfulTheme::default())
@@ -20,10 +20,10 @@ pub async fn process_auth_app(commands: Commands) -> Result<CommandResult> {
20
21 let spinner = Spinner::new(
22 spinners::Spinners::SimpleDotsScrolling,
23 - style("Creating an auth app...").green().bold().to_string(),
23 + style("Creating an Oten app...").green().bold().to_string(),
24 );
25
26 - match create_auth_app(AuthAppCreate {
26 + match create_oten_app(AppCreate {
27 name: app_name.clone(),
28 description: description.clone(),
29 })
@@ -32,14 +32,14 @@ pub async fn process_auth_app(commands: Commands) -> Result<CommandResult> {
32 Ok(_) => Ok(CommandResult {
33 spinner,
34 symbol: "✅".to_owned(),
35 - msg: format!("An auth app created: {app_name}."),
35 + msg: format!("An oten app created: {app_name}."),
36 }),
37 Err(e) => {
38 println!("Error: {e:#?}");
39 Ok(CommandResult {
40 spinner,
41 symbol: "😩".to_owned(),
42 - msg: format!("Failed to create an auth app: {app_name}."),
42 + msg: format!("Failed to create an oten app: {app_name}."),
43 })
44 }
45 }
@@ -49,15 +49,15 @@ pub async fn process_auth_app(commands: Commands) -> Result<CommandResult> {
49 spinners::Spinners::SimpleDotsScrolling,
50 style("Loading...").green().bold().to_string(),
51 );
52 - match get_auth_apps().await {
53 - Ok(auth_apps) => {
54 - println!("auth_apps: {auth_apps:#?}");
52 + match get_oten_apps().await {
53 + Ok(oten_apps) => {
54 + println!("oten_apps: {oten_apps:#?}");
55 println!(
56 "{0: <10} | {1: <30} | {2: <10} | {3: <10}",
57 "ID", "Name", "Created at", "Updated at"
58 );
59 - for project in auth_apps {
60 - let id = project.id.split("-").collect::<Vec<&str>>()[0].to_owned();
59 + for project in oten_apps {
60 + let id = project.id.split('-').collect::<Vec<&str>>()[0].to_owned();
61 let created_at = project.created_at.date_naive();
62 let updated_at = project.updated_at.date_naive();
63 println!(
@@ -68,7 +68,7 @@ pub async fn process_auth_app(commands: Commands) -> Result<CommandResult> {
68 Ok(CommandResult {
69 spinner,
70 symbol: "✅".to_owned(),
71 - msg: "Showing all auth apps.".to_owned(),
71 + msg: "Showing all oten apps.".to_owned(),
72 })
73 }
74 Err(e) => {
@@ -76,7 +76,7 @@ pub async fn process_auth_app(commands: Commands) -> Result<CommandResult> {
76 Ok(CommandResult {
77 spinner,
78 symbol: "😩".to_owned(),
79 - msg: "Failed to get all auth apps.".to_owned(),
79 + msg: "Failed to get all oten apps.".to_owned(),
80 })
81 }
82 }
@@ -86,18 +86,18 @@ pub async fn process_auth_app(commands: Commands) -> Result<CommandResult> {
86 spinners::Spinners::SimpleDotsScrolling,
87 style("Loading...").green().bold().to_string(),
88 );
89 - match get_auth_app(&id).await {
89 + match get_oten_app(&id).await {
90 Ok(_) => Ok(CommandResult {
91 spinner,
92 symbol: "✅".to_owned(),
93 - msg: "Showing auth app.".to_owned(),
93 + msg: "Showing oten app.".to_owned(),
94 }),
95 Err(e) => {
96 println!("Error: {e:#?}");
97 Ok(CommandResult {
98 spinner,
99 symbol: "😩".to_owned(),
100 - msg: "Failed to get an auth app.".to_owned(),
100 + msg: "Failed to get an oten app.".to_owned(),
101 })
102 }
103 }
@@ -107,18 +107,18 @@ pub async fn process_auth_app(commands: Commands) -> Result<CommandResult> {
107 spinners::Spinners::SimpleDotsScrolling,
108 style("Loading...").green().bold().to_string(),
109 );
110 - match delete_auth_app(id).await {
110 + match delete_oten_app(id).await {
111 Ok(_) => Ok(CommandResult {
112 spinner,
113 symbol: "✅".to_owned(),
114 - msg: "Delete auth app succeed.".to_owned(),
114 + msg: "Delete oten app succeed.".to_owned(),
115 }),
116 Err(e) => {
117 println!("Error: {e:#?}");
118 Ok(CommandResult {
119 spinner,
120 symbol: "😩".to_owned(),
121 - msg: "Failed to delete auth app.".to_owned(),
121 + msg: "Failed to delete oten app.".to_owned(),
122 })
123 }
124 }
@@ -129,15 +129,15 @@ pub async fn process_auth_app(commands: Commands) -> Result<CommandResult> {
129 style("Checking config file...").green().bold().to_string(),
130 );
131
132 - let auth_app = get_auth_app(&id).await?;
132 + let oten_app = get_oten_app(&id).await?;
133 let mut config = get_config().await?;
134
135 - if let Some(auth_app) = config.current_auth_app {
136 - if auth_app.id != id {
135 + if let Some(oten_app) = config.current_oten_app {
136 + if oten_app.id != id {
137 spinner.stop_with_message("Found a config.".to_string());
138 let yes = Confirm::new()
139 .with_prompt(format!(
140 - "Will change active auth_app to {}. Do you want to continue?",
140 + "Will change active oten_app to {}. Do you want to continue?",
141 &id
142 ))
143 .interact()?;
@@ -155,7 +155,7 @@ pub async fn process_auth_app(commands: Commands) -> Result<CommandResult> {
155 }
156 }
157
158 - config.current_auth_app = Some(auth_app);
158 + config.current_oten_app = Some(oten_app);
159 let spinner = Spinner::new(
160 spinners::Spinners::SimpleDotsScrolling,
161 style("Saving config...").green().bold().to_string(),
@@ -164,7 +164,7 @@ pub async fn process_auth_app(commands: Commands) -> Result<CommandResult> {
164 Ok(_) => Ok(CommandResult {
165 spinner,
166 symbol: "✅".to_owned(),
167 - msg: format!("Using auth_app: {:?}", &id),
167 + msg: format!("Using oten_app: {:?}", &id),
168 }),
169 Err(_) => {
170 let error = anyhow!("Failed while writing config.");
app-oten/src/lib.rs
+22 -22
@@ -4,56 +4,56 @@ pub mod handler;
4 use anyhow::{anyhow, Result};
5 use log::debug;
6 use reqwest::Client;
7 -use smbpndk_model::{AuthApp, AuthAppCreate};
7 +use smbpndk_model::{AppCreate, Oten};
8 use smbpndk_networking::{constants::BASE_URL, get_token};
9
10 -async fn get_auth_apps() -> Result<Vec<AuthApp>> {
10 +async fn get_oten_apps() -> Result<Vec<Oten>> {
11 // Get current token
12 let token = get_token().await?;
13
14 let response = Client::new()
15 - .get([BASE_URL, "v1/auth_apps"].join(""))
15 + .get([BASE_URL, "v1/oten_apps"].join(""))
16 .header("Authorization", token)
17 .send()
18 .await?;
19
20 match response.status() {
21 reqwest::StatusCode::OK => {
22 - let auth_apps: Vec<AuthApp> = response.json().await?;
23 - Ok(auth_apps)
22 + let oten_apps: Vec<Oten> = response.json().await?;
23 + Ok(oten_apps)
24 }
25 - _ => Err(anyhow!("Failed to fetch auth apps.")),
25 + _ => Err(anyhow!("Failed to fetch oten apps.")),
26 }
27 }
28
29 -async fn get_auth_app(id: &str) -> Result<AuthApp> {
29 +async fn get_oten_app(id: &str) -> Result<Oten> {
30 // Get current token
31 let token = get_token().await?;
32
33 let response = Client::new()
34 - .get([BASE_URL, "v1/auth_apps/", id].join(""))
34 + .get([BASE_URL, "v1/oten_apps/", id].join(""))
35 .header("Authorization", token)
36 .send()
37 .await?;
38
39 match response.status() {
40 reqwest::StatusCode::OK => {
41 - let auth_app: AuthApp = response.json().await?;
42 - println!("Auth app requested: {auth_app:#?}");
43 - Ok(auth_app)
41 + let oten_app: Oten = response.json().await?;
42 + println!("Auth app requested: {oten_app:#?}");
43 + Ok(oten_app)
44 }
45 _ => Err(anyhow!(format!(
46 - "Failed to find an auth app with id: {id}."
46 + "Failed to find an oten app with id: {id}."
47 ))),
48 }
49 }
50
51 -async fn delete_auth_app(id: String) -> Result<()> {
51 +async fn delete_oten_app(id: String) -> Result<()> {
52 // Get current token
53 let token = get_token().await?;
54
55 let response = Client::new()
56 - .delete([BASE_URL, "v1/auth_apps/", &id].join(""))
56 + .delete([BASE_URL, "v1/oten_apps/", &id].join(""))
57 .header("Authorization", token)
58 .send()
59 .await?;
@@ -63,27 +63,27 @@ async fn delete_auth_app(id: String) -> Result<()> {
63 debug!("Project deleted.");
64 Ok(())
65 }
66 - _ => Err(anyhow!("Failed to delete an auth app.")),
66 + _ => Err(anyhow!("Failed to delete an oten app.")),
67 }
68 }
69
70 -async fn create_auth_app(auth_app: AuthAppCreate) -> Result<AuthApp> {
70 +async fn create_oten_app(oten_app: AppCreate) -> Result<Oten> {
71 // Get current token
72 let token = get_token().await?;
73
74 let response = Client::new()
75 - .post([BASE_URL, "v1/auth_apps"].join(""))
76 - .json(&auth_app)
75 + .post([BASE_URL, "v1/oten_apps"].join(""))
76 + .json(&oten_app)
77 .header("Authorization", token)
78 .send()
79 .await?;
80
81 match response.status() {
82 reqwest::StatusCode::CREATED => {
83 - let auth_app: AuthApp = response.json().await?;
84 - println!("Project created: {auth_app:#?}");
85 - Ok(auth_app)
83 + let oten_app: Oten = response.json().await?;
84 + println!("Project created: {oten_app:#?}");
85 + Ok(oten_app)
86 }
87 - _ => Err(anyhow!("Failed to create an auth app.")),
87 + _ => Err(anyhow!("Failed to create an oten app.")),
88 }
89 }
app-pkt/Cargo.toml
+17
@@ -12,3 +12,20 @@ categories = ["command-line-utilities", "command-line-interface", "cryptography:
12 readme = "../README.md"
13
14 [dependencies]
15 +anyhow = "1.0.58"
16 +async-trait = { version = "0.1.51", optional = true }
17 +clap = { version = "4.1.6", features = ["derive"] }
18 +console = "0.15.0"
19 +dialoguer = "0.10.4"
20 +dirs = "4.0.0"
21 +home = "0.5.4"
22 +log = "0.4.14"
23 +maybe-async = { version = "0.2", features = ["is_sync"] }
24 +reqwest = { version = "0.11", features = ["json"] }
25 +serde = { version = "1", features = ["derive"] }
26 +serde_json = "1.0.82"
27 +smbpndk-model = { version = "0.3", path = "../smbpndk-model" }
28 +smbpndk-networking = { version = "0.3", path = "../smbpndk-networking" }
29 +smbpndk-utils = { version = "0.3", path = "../smbpndk-utils" }
30 +spinners = "4.1.0"
31 +thiserror = "1.0.29"
app-pkt/src/cli.rs new
+30
@@ -0,0 +1,30 @@
1 +use clap::Subcommand;
2 +
3 +#[derive(Subcommand)]
4 +pub enum Commands {
5 + #[clap(about = "Add new auth app.")]
6 + New {},
7 +
8 + #[clap(about = "List all your auth apps.")]
9 + List {},
10 +
11 + #[clap(about = "Show detail of a auth app.")]
12 + Show {
13 + /// Project Id
14 + #[clap(short, long, required = true)]
15 + id: String,
16 + },
17 +
18 + #[clap(about = "Delete a auth app.")]
19 + Delete {
20 + /// Project name
21 + #[clap(short, long, required = true)]
22 + id: String,
23 + },
24 +
25 + #[clap(about = "Use auth app for current CLI session.")]
26 + Use {
27 + #[clap(short, long, required = true)]
28 + id: String,
29 + },
30 +}
app-pkt/src/handler.rs new
+176
@@ -0,0 +1,176 @@
1 +use crate::{cli::Commands, create_pkt_app, delete_pkt_app, get_pkt_app, get_pkt_apps};
2 +use anyhow::{anyhow, Result};
3 +use console::style;
4 +use dialoguer::{theme::ColorfulTheme, Confirm, Input};
5 +use smbpndk_model::{AppCreate, CommandResult};
6 +use smbpndk_utils::{get_config, write_config};
7 +use spinners::Spinner;
8 +
9 +pub async fn process_pkt_app(commands: Commands) -> Result<CommandResult> {
10 + match commands {
11 + Commands::New {} => {
12 + let app_name = Input::<String>::with_theme(&ColorfulTheme::default())
13 + .with_prompt("App name")
14 + .interact()
15 + .unwrap();
16 + let description = Input::<String>::with_theme(&ColorfulTheme::default())
17 + .with_prompt("Description")
18 + .interact()
19 + .unwrap();
20 +
21 + let spinner = Spinner::new(
22 + spinners::Spinners::SimpleDotsScrolling,
23 + style("Creating a Pkt app...").green().bold().to_string(),
24 + );
25 +
26 + match create_pkt_app(AppCreate {
27 + name: app_name.clone(),
28 + description: description.clone(),
29 + })
30 + .await
31 + {
32 + Ok(_) => Ok(CommandResult {
33 + spinner,
34 + symbol: "✅".to_owned(),
35 + msg: format!("Pkt app created: {app_name}."),
36 + }),
37 + Err(e) => {
38 + println!("Error: {e:#?}");
39 + Ok(CommandResult {
40 + spinner,
41 + symbol: "😩".to_owned(),
42 + msg: format!("Failed to create a Pkt app: {app_name}."),
43 + })
44 + }
45 + }
46 + }
47 + Commands::List {} => {
48 + let spinner = Spinner::new(
49 + spinners::Spinners::SimpleDotsScrolling,
50 + style("Loading...").green().bold().to_string(),
51 + );
52 + match get_pkt_apps().await {
53 + Ok(apps) => {
54 + println!("apps: {apps:#?}");
55 + println!(
56 + "{0: <10} | {1: <30} | {2: <10} | {3: <10}",
57 + "ID", "Name", "Created at", "Updated at"
58 + );
59 + for project in apps {
60 + let id = project.id.split('-').collect::<Vec<&str>>()[0].to_owned();
61 + let created_at = project.created_at.date_naive();
62 + let updated_at = project.updated_at.date_naive();
63 + println!(
64 + "{0: <10} | {1: <30} | {2: <10} | {3: <10}",
65 + id, project.name, created_at, updated_at
66 + );
67 + }
68 + Ok(CommandResult {
69 + spinner,
70 + symbol: "✅".to_owned(),
71 + msg: "Showing all Pkt apps.".to_owned(),
72 + })
73 + }
74 + Err(e) => {
75 + println!("Error: {e:#?}");
76 + Ok(CommandResult {
77 + spinner,
78 + symbol: "😩".to_owned(),
79 + msg: "Failed to get all Pkt apps.".to_owned(),
80 + })
81 + }
82 + }
83 + }
84 + Commands::Show { id } => {
85 + let spinner = Spinner::new(
86 + spinners::Spinners::SimpleDotsScrolling,
87 + style("Loading...").green().bold().to_string(),
88 + );
89 + match get_pkt_app(&id).await {
90 + Ok(_) => Ok(CommandResult {
91 + spinner,
92 + symbol: "✅".to_owned(),
93 + msg: "Showing Pkt app.".to_owned(),
94 + }),
95 + Err(e) => {
96 + println!("Error: {e:#?}");
97 + Ok(CommandResult {
98 + spinner,
99 + symbol: "😩".to_owned(),
100 + msg: "Failed to get an Pkt app.".to_owned(),
101 + })
102 + }
103 + }
104 + }
105 + Commands::Delete { id } => {
106 + let spinner = Spinner::new(
107 + spinners::Spinners::SimpleDotsScrolling,
108 + style("Loading...").green().bold().to_string(),
109 + );
110 + match delete_pkt_app(id).await {
111 + Ok(_) => Ok(CommandResult {
112 + spinner,
113 + symbol: "✅".to_owned(),
114 + msg: "Delete Pkt app succeed.".to_owned(),
115 + }),
116 + Err(e) => {
117 + println!("Error: {e:#?}");
118 + Ok(CommandResult {
119 + spinner,
120 + symbol: "😩".to_owned(),
121 + msg: "Failed to delete Pkt app.".to_owned(),
122 + })
123 + }
124 + }
125 + }
126 + Commands::Use { id } => {
127 + let mut spinner = Spinner::new(
128 + spinners::Spinners::SimpleDotsScrolling,
129 + style("Checking config file...").green().bold().to_string(),
130 + );
131 +
132 + let pkt_app = get_pkt_app(&id).await?;
133 + let mut config = get_config().await?;
134 +
135 + if let Some(pkt) = config.current_pkt_app {
136 + if pkt.id != id {
137 + spinner.stop_with_message("Found a config.".to_string());
138 + let yes = Confirm::new()
139 + .with_prompt(format!(
140 + "Will change active Pkt app to {}. Do you want to continue?",
141 + &id
142 + ))
143 + .interact()?;
144 + if !yes {
145 + let spinner = Spinner::new(
146 + spinners::Spinners::SimpleDotsScrolling,
147 + style("Cancelling operation...").green().bold().to_string(),
148 + );
149 + return Ok(CommandResult {
150 + spinner,
151 + symbol: "✅".to_owned(),
152 + msg: "Operation cancelled.".to_string(),
153 + });
154 + }
155 + }
156 + }
157 +
158 + config.current_pkt_app = Some(pkt_app);
159 + let spinner = Spinner::new(
160 + spinners::Spinners::SimpleDotsScrolling,
161 + style("Saving config...").green().bold().to_string(),
162 + );
163 + match write_config(config) {
164 + Ok(_) => Ok(CommandResult {
165 + spinner,
166 + symbol: "✅".to_owned(),
167 + msg: format!("Using Pkt app: {:?}", &id),
168 + }),
169 + Err(_) => {
170 + let error = anyhow!("Failed while writing config.");
171 + Err(error)
172 + }
173 + }
174 + }
175 + }
176 +}
app-pkt/src/lib.rs
+82 -9
@@ -1,14 +1,87 @@
1 -pub fn add(left: usize, right: usize) -> usize {
2 - left + right
1 +pub mod cli;
2 +pub mod handler;
3 +
4 +use anyhow::{anyhow, Result};
5 +use log::debug;
6 +use reqwest::Client;
7 +use smbpndk_model::{AppCreate, Pkt};
8 +use smbpndk_networking::{constants::BASE_URL, get_token};
9 +
10 +async fn get_pkt_apps() -> Result<Vec<Pkt>> {
11 + // Get current token
12 + let token = get_token().await?;
13 +
14 + let response = Client::new()
15 + .get([BASE_URL, "v1/pkt_apps"].join(""))
16 + .header("Authorization", token)
17 + .send()
18 + .await?;
19 +
20 + match response.status() {
21 + reqwest::StatusCode::OK => {
22 + let apps: Vec<Pkt> = response.json().await?;
23 + Ok(apps)
24 + }
25 + _ => Err(anyhow!("Failed to fetch Pkt apps.")),
26 + }
27 +}
28 +
29 +async fn get_pkt_app(id: &str) -> Result<Pkt> {
30 + // Get current token
31 + let token = get_token().await?;
32 +
33 + let response = Client::new()
34 + .get([BASE_URL, "v1/pkt_apps/", id].join(""))
35 + .header("Authorization", token)
36 + .send()
37 + .await?;
38 +
39 + match response.status() {
40 + reqwest::StatusCode::OK => {
41 + let auth_app: Pkt = response.json().await?;
42 + println!("Pkt app requested: {auth_app:#?}");
43 + Ok(auth_app)
44 + }
45 + _ => Err(anyhow!(format!("Failed to find an Pkt app with id: {id}."))),
46 + }
47 +}
48 +
49 +async fn delete_pkt_app(id: String) -> Result<()> {
50 + // Get current token
51 + let token = get_token().await?;
52 +
53 + let response = Client::new()
54 + .delete([BASE_URL, "v1/pkt_apps/", &id].join(""))
55 + .header("Authorization", token)
56 + .send()
57 + .await?;
58 +
59 + match response.status() {
60 + reqwest::StatusCode::OK => {
61 + debug!("App deleted.");
62 + Ok(())
63 + }
64 + _ => Err(anyhow!("Failed to delete an Pkt app.")),
65 + }
66 }
67
5 -#[cfg(test)]
6 -mod tests {
7 - use super::*;
68 +async fn create_pkt_app(app: AppCreate) -> Result<Pkt> {
69 + // Get current token
70 + let token = get_token().await?;
71 +
72 + let response = Client::new()
73 + .post([BASE_URL, "v1/pkt_apps"].join(""))
74 + .json(&app)
75 + .header("Authorization", token)
76 + .send()
77 + .await?;
78
9 - #[test]
10 - fn it_works() {
11 - let result = add(2, 2);
12 - assert_eq!(result, 4);
79 + match response.status() {
80 + reqwest::StatusCode::CREATED => {
81 + let app: Pkt = response.json().await?;
82 + println!("App created: {app:#?}");
83 + Ok(app)
84 + }
85 + _ => Err(anyhow!("Failed to create an Pkt app.")),
86 }
87 }
app-rdb/Cargo.toml
+17
@@ -12,3 +12,20 @@ categories = ["command-line-utilities", "command-line-interface", "cryptography:
12 readme = "../README.md"
13
14 [dependencies]
15 +anyhow = "1.0.58"
16 +async-trait = { version = "0.1.51", optional = true }
17 +clap = { version = "4.1.6", features = ["derive"] }
18 +console = "0.15.0"
19 +dialoguer = "0.10.4"
20 +dirs = "4.0.0"
21 +home = "0.5.4"
22 +log = "0.4.14"
23 +maybe-async = { version = "0.2", features = ["is_sync"] }
24 +reqwest = { version = "0.11", features = ["json"] }
25 +serde = { version = "1", features = ["derive"] }
26 +serde_json = "1.0.82"
27 +smbpndk-model = { version = "0.3", path = "../smbpndk-model" }
28 +smbpndk-networking = { version = "0.3", path = "../smbpndk-networking" }
29 +smbpndk-utils = { version = "0.3", path = "../smbpndk-utils" }
30 +spinners = "4.1.0"
31 +thiserror = "1.0.29"
app-rdb/src/cli.rs new
+30
@@ -0,0 +1,30 @@
1 +use clap::Subcommand;
2 +
3 +#[derive(Subcommand)]
4 +pub enum Commands {
5 + #[clap(about = "Add new auth app.")]
6 + New {},
7 +
8 + #[clap(about = "List all your auth apps.")]
9 + List {},
10 +
11 + #[clap(about = "Show detail of a auth app.")]
12 + Show {
13 + /// Project Id
14 + #[clap(short, long, required = true)]
15 + id: String,
16 + },
17 +
18 + #[clap(about = "Delete a auth app.")]
19 + Delete {
20 + /// Project name
21 + #[clap(short, long, required = true)]
22 + id: String,
23 + },
24 +
25 + #[clap(about = "Use auth app for current CLI session.")]
26 + Use {
27 + #[clap(short, long, required = true)]
28 + id: String,
29 + },
30 +}
app-rdb/src/handler.rs new
+176
@@ -0,0 +1,176 @@
1 +use crate::{cli::Commands, create_rdb_app, delete_rdb_app, get_rdb_app, get_rdb_apps};
2 +use anyhow::{anyhow, Result};
3 +use console::style;
4 +use dialoguer::{theme::ColorfulTheme, Confirm, Input};
5 +use smbpndk_model::{AppCreate, CommandResult};
6 +use smbpndk_utils::{get_config, write_config};
7 +use spinners::Spinner;
8 +
9 +pub async fn process_rdb_app(commands: Commands) -> Result<CommandResult> {
10 + match commands {
11 + Commands::New {} => {
12 + let app_name = Input::<String>::with_theme(&ColorfulTheme::default())
13 + .with_prompt("App name")
14 + .interact()
15 + .unwrap();
16 + let description = Input::<String>::with_theme(&ColorfulTheme::default())
17 + .with_prompt("Description")
18 + .interact()
19 + .unwrap();
20 +
21 + let spinner = Spinner::new(
22 + spinners::Spinners::SimpleDotsScrolling,
23 + style("Creating a Pkt app...").green().bold().to_string(),
24 + );
25 +
26 + match create_rdb_app(AppCreate {
27 + name: app_name.clone(),
28 + description: description.clone(),
29 + })
30 + .await
31 + {
32 + Ok(_) => Ok(CommandResult {
33 + spinner,
34 + symbol: "✅".to_owned(),
35 + msg: format!("A Pkt app created: {app_name}."),
36 + }),
37 + Err(e) => {
38 + println!("Error: {e:#?}");
39 + Ok(CommandResult {
40 + spinner,
41 + symbol: "😩".to_owned(),
42 + msg: format!("Failed to create a Pkt app: {app_name}."),
43 + })
44 + }
45 + }
46 + }
47 + Commands::List {} => {
48 + let spinner = Spinner::new(
49 + spinners::Spinners::SimpleDotsScrolling,
50 + style("Loading...").green().bold().to_string(),
51 + );
52 + match get_rdb_apps().await {
53 + Ok(apps) => {
54 + println!("Rdb apps: {apps:#?}");
55 + println!(
56 + "{0: <10} | {1: <30} | {2: <10} | {3: <10}",
57 + "ID", "Name", "Created at", "Updated at"
58 + );
59 + for project in apps {
60 + let id = project.id.split('-').collect::<Vec<&str>>()[0].to_owned();
61 + let created_at = project.created_at.date_naive();
62 + let updated_at = project.updated_at.date_naive();
63 + println!(
64 + "{0: <10} | {1: <30} | {2: <10} | {3: <10}",
65 + id, project.name, created_at, updated_at
66 + );
67 + }
68 + Ok(CommandResult {
69 + spinner,
70 + symbol: "✅".to_owned(),
71 + msg: "Showing all auth apps.".to_owned(),
72 + })
73 + }
74 + Err(e) => {
75 + println!("Error: {e:#?}");
76 + Ok(CommandResult {
77 + spinner,
78 + symbol: "😩".to_owned(),
79 + msg: "Failed to get all auth apps.".to_owned(),
80 + })
81 + }
82 + }
83 + }
84 + Commands::Show { id } => {
85 + let spinner = Spinner::new(
86 + spinners::Spinners::SimpleDotsScrolling,
87 + style("Loading...").green().bold().to_string(),
88 + );
89 + match get_rdb_app(&id).await {
90 + Ok(_) => Ok(CommandResult {
91 + spinner,
92 + symbol: "✅".to_owned(),
93 + msg: "Showing auth app.".to_owned(),
94 + }),
95 + Err(e) => {
96 + println!("Error: {e:#?}");
97 + Ok(CommandResult {
98 + spinner,
99 + symbol: "😩".to_owned(),
100 + msg: "Failed to get an auth app.".to_owned(),
101 + })
102 + }
103 + }
104 + }
105 + Commands::Delete { id } => {
106 + let spinner = Spinner::new(
107 + spinners::Spinners::SimpleDotsScrolling,
108 + style("Loading...").green().bold().to_string(),
109 + );
110 + match delete_rdb_app(id).await {
111 + Ok(_) => Ok(CommandResult {
112 + spinner,
113 + symbol: "✅".to_owned(),
114 + msg: "Delete auth app succeed.".to_owned(),
115 + }),
116 + Err(e) => {
117 + println!("Error: {e:#?}");
118 + Ok(CommandResult {
119 + spinner,
120 + symbol: "😩".to_owned(),
121 + msg: "Failed to delete auth app.".to_owned(),
122 + })
123 + }
124 + }
125 + }
126 + Commands::Use { id } => {
127 + let mut spinner = Spinner::new(
128 + spinners::Spinners::SimpleDotsScrolling,
129 + style("Checking config file...").green().bold().to_string(),
130 + );
131 +
132 + let rdb_app = get_rdb_app(&id).await?;
133 + let mut config = get_config().await?;
134 +
135 + if let Some(rdb_app) = config.current_rdb_app {
136 + if rdb_app.id != id {
137 + spinner.stop_with_message("Found a config.".to_string());
138 + let yes = Confirm::new()
139 + .with_prompt(format!(
140 + "Will change active Pkt app to {}. Do you want to continue?",
141 + &id
142 + ))
143 + .interact()?;
144 + if !yes {
145 + let spinner = Spinner::new(
146 + spinners::Spinners::SimpleDotsScrolling,
147 + style("Cancelling operation...").green().bold().to_string(),
148 + );
149 + return Ok(CommandResult {
150 + spinner,
151 + symbol: "✅".to_owned(),
152 + msg: "Operation cancelled.".to_string(),
153 + });
154 + }
155 + }
156 + }
157 +
158 + config.current_rdb_app = Some(rdb_app);
159 + let spinner = Spinner::new(
160 + spinners::Spinners::SimpleDotsScrolling,
161 + style("Saving config...").green().bold().to_string(),
162 + );
163 + match write_config(config) {
164 + Ok(_) => Ok(CommandResult {
165 + spinner,
166 + symbol: "✅".to_owned(),
167 + msg: format!("Using Pkt app: {:?}", &id),
168 + }),
169 + Err(_) => {
170 + let error = anyhow!("Failed while writing config.");
171 + Err(error)
172 + }
173 + }
174 + }
175 + }
176 +}
app-rdb/src/lib.rs
+82 -9
@@ -1,14 +1,87 @@
1 -pub fn add(left: usize, right: usize) -> usize {
2 - left + right
1 +pub mod cli;
2 +pub mod handler;
3 +
4 +use anyhow::{anyhow, Result};
5 +use log::debug;
6 +use reqwest::Client;
7 +use smbpndk_model::{AppCreate, Rdb};
8 +use smbpndk_networking::{constants::BASE_URL, get_token};
9 +
10 +async fn get_rdb_apps() -> Result<Vec<Rdb>> {
11 + // Get current token
12 + let token = get_token().await?;
13 +
14 + let response = Client::new()
15 + .get([BASE_URL, "v1/rdb_apps"].join(""))
16 + .header("Authorization", token)
17 + .send()
18 + .await?;
19 +
20 + match response.status() {
21 + reqwest::StatusCode::OK => {
22 + let apps: Vec<Rdb> = response.json().await?;
23 + Ok(apps)
24 + }
25 + _ => Err(anyhow!("Failed to fetch Rdb apps.")),
26 + }
27 +}
28 +
29 +async fn get_rdb_app(id: &str) -> Result<Rdb> {
30 + // Get current token
31 + let token = get_token().await?;
32 +
33 + let response = Client::new()
34 + .get([BASE_URL, "v1/rdb_apps/", id].join(""))
35 + .header("Authorization", token)
36 + .send()
37 + .await?;
38 +
39 + match response.status() {
40 + reqwest::StatusCode::OK => {
41 + let app: Rdb = response.json().await?;
42 + println!("Rdb app requested: {app:#?}");
43 + Ok(app)
44 + }
45 + _ => Err(anyhow!(format!("Failed to find an Rdb app with id: {id}."))),
46 + }
47 +}
48 +
49 +async fn delete_rdb_app(id: String) -> Result<()> {
50 + // Get current token
51 + let token = get_token().await?;
52 +
53 + let response = Client::new()
54 + .delete([BASE_URL, "v1/rdb_apps/", &id].join(""))
55 + .header("Authorization", token)
56 + .send()
57 + .await?;
58 +
59 + match response.status() {
60 + reqwest::StatusCode::OK => {
61 + debug!("Project deleted.");
62 + Ok(())
63 + }
64 + _ => Err(anyhow!("Failed to delete an Rdb app.")),
65 + }
66 }
67
5 -#[cfg(test)]
6 -mod tests {
7 - use super::*;
68 +async fn create_rdb_app(app: AppCreate) -> Result<Rdb> {
69 + // Get current token
70 + let token = get_token().await?;
71 +
72 + let response = Client::new()
73 + .post([BASE_URL, "v1/rdb_apps"].join(""))
74 + .json(&app)
75 + .header("Authorization", token)
76 + .send()
77 + .await?;
78
9 - #[test]
10 - fn it_works() {
11 - let result = add(2, 2);
12 - assert_eq!(result, 4);
79 + match response.status() {
80 + reqwest::StatusCode::CREATED => {
81 + let app: Rdb = response.json().await?;
82 + println!("Project created: {app:#?}");
83 + Ok(app)
84 + }
85 + _ => Err(anyhow!("Failed to create an Rdb app.")),
86 }
87 }
smbpndk-cli/src/cli/mod.rs
+20 -13
@@ -20,32 +20,39 @@ pub enum Commands {
20 command: account::cli::Commands,
21 },
22
23 - #[clap(about = "Manage your projects. Add, delete, edit. Need authentication.")]
23 + #[clap(about = "Manage your projects. Add, show, delete, edit. Need authentication.")]
24 Project {
25 #[clap(subcommand)]
26 command: project::cli::Commands,
27 },
28
29 - #[clap(about = "Manage your Oten authentication app. Add, delete, edit. Need authentication.")]
29 + #[clap(
30 + about = "Manage your Oten authentication app. Add, show, delete, edit. Need authentication."
31 + )]
32 Oten {
33 #[clap(subcommand)]
34 command: app_oten::cli::Commands,
35 },
34 - // Function
36 +
37 + #[clap(
38 + about = "Manage your Fun serverless app. Add, show, delete, edit. Need authentication."
39 + )]
40 Fun {
41 #[clap(subcommand)]
42 command: app_fun::cli::Commands,
43 },
39 - // Package
40 - /*
41 - PktApp {
44 +
45 + #[clap(
46 + about = "Manage your Pkt package manager app. Add, show, delete, edit. Need authentication."
47 + )]
48 + Pkt {
49 #[clap(subcommand)]
43 - command: pkt_app::cli::Commands,
44 - }, */
45 - // Relational database
46 - /*
47 - RdbApp {
50 + command: app_pkt::cli::Commands,
51 + },
52 +
53 + #[clap(about = "Manage your Rdb database app. Add, show, delete, edit. Need authentication.")]
54 + Rdb {
55 #[clap(subcommand)]
49 - command: rdb_app::cli::Commands,
50 - }, */
56 + command: app_rdb::cli::Commands,
57 + },
58 }
smbpndk-cli/src/main.rs
+6 -2
@@ -1,6 +1,8 @@
1 use anyhow::{anyhow, Result};
2 use app_fun::handler::process_fun_app;
3 -use app_oten::{self, handler::process_auth_app};
3 +use app_oten::handler::process_oten_app;
4 +use app_pkt::handler::process_pkt_app;
5 +use app_rdb::handler::process_rdb_app;
6 use clap::Parser;
7 use console::style;
8 use dotenv::dotenv;
@@ -103,7 +105,9 @@ async fn run() -> Result<CommandResult> {
105 match cli.command {
106 Commands::Account { command } => process_account(command).await,
107 Commands::Project { command } => process_project(command).await,
106 - Commands::Oten { command } => process_auth_app(command).await,
108 + Commands::Oten { command } => process_oten_app(command).await,
109 Commands::Fun { command } => process_fun_app(command).await,
110 + Commands::Pkt { command } => process_pkt_app(command).await,
111 + Commands::Rdb { command } => process_rdb_app(command).await,
112 }
113 }
smbpndk-cli/src/project/mod.rs
+5 -2
@@ -131,7 +131,10 @@ pub async fn process_project(commands: Commands) -> Result<CommandResult> {
131
132 let config = Config {
133 current_project: Some(project),
134 - current_auth_app: None,
134 + current_oten_app: None,
135 + current_fun_app: None,
136 + current_pkt_app: None,
137 + current_rdb_app: None,
138 };
139
140 let spinner = Spinner::new(
@@ -144,7 +147,7 @@ pub async fn process_project(commands: Commands) -> Result<CommandResult> {
147 let mut file = OpenOptions::new()
148 .create(true)
149 .write(true)
147 - .open([path.to_str().unwrap(), "/.smb/config.json"].join(""))?;
150 + .open([path.to_str().unwrap(), "/.smb/config"].join(""))?;
151 let json = serde_json::to_string(&config)?;
152 file.write_all(json.as_bytes())?;
153
smbpndk-model/src/lib.rs
+40 -4
@@ -6,7 +6,7 @@ mod ar_date_format {
6 use chrono::{DateTime, TimeZone, Utc};
7 use serde::{self, Deserialize, Deserializer, Serializer};
8
9 - const FORMAT: &'static str = "%Y-%m-%dT%H:%M:%S%.f%#z";
9 + const FORMAT: &str = "%Y-%m-%dT%H:%M:%S%.f%#z";
10
11 // The signature of a serialize_with function must follow the pattern:
12 //
@@ -47,7 +47,7 @@ pub struct CommandResult {
47 }
48
49 #[derive(Serialize, Deserialize, Debug)]
50 -pub struct AuthApp {
50 +pub struct Oten {
51 pub id: String,
52 pub secret: Option<String>,
53 pub name: String,
@@ -58,7 +58,40 @@ pub struct AuthApp {
58 }
59
60 #[derive(Serialize, Deserialize, Debug)]
61 -pub struct AuthAppCreate {
61 +pub struct Fun {
62 + pub id: String,
63 + pub secret: Option<String>,
64 + pub name: String,
65 + #[serde(with = "ar_date_format")]
66 + pub created_at: DateTime<Utc>,
67 + #[serde(with = "ar_date_format")]
68 + pub updated_at: DateTime<Utc>,
69 +}
70 +
71 +#[derive(Serialize, Deserialize, Debug)]
72 +pub struct Pkt {
73 + pub id: String,
74 + pub secret: Option<String>,
75 + pub name: String,
76 + #[serde(with = "ar_date_format")]
77 + pub created_at: DateTime<Utc>,
78 + #[serde(with = "ar_date_format")]
79 + pub updated_at: DateTime<Utc>,
80 +}
81 +
82 +#[derive(Serialize, Deserialize, Debug)]
83 +pub struct Rdb {
84 + pub id: String,
85 + pub secret: Option<String>,
86 + pub name: String,
87 + #[serde(with = "ar_date_format")]
88 + pub created_at: DateTime<Utc>,
89 + #[serde(with = "ar_date_format")]
90 + pub updated_at: DateTime<Utc>,
91 +}
92 +
93 +#[derive(Serialize, Deserialize, Debug)]
94 +pub struct AppCreate {
95 pub name: String,
96 pub description: String,
97 }
@@ -66,7 +99,10 @@ pub struct AuthAppCreate {
99 #[derive(Deserialize, Debug, Serialize)]
100 pub struct Config {
101 pub current_project: Option<Project>,
69 - pub current_auth_app: Option<AuthApp>,
102 + pub current_oten_app: Option<Oten>,
103 + pub current_fun_app: Option<Fun>,
104 + pub current_pkt_app: Option<Pkt>,
105 + pub current_rdb_app: Option<Rdb>,
106 }
107
108 #[derive(Deserialize, Debug, Serialize)]
smbpndk-networking/src/lib.rs
+13
@@ -2,6 +2,7 @@ pub mod constants;
2
3 use anyhow::{anyhow, Result};
4 use log::debug;
5 +use smbpndk_model::Config;
6
7 pub async fn get_token() -> Result<String> {
8 if let Some(mut path) = dirs::home_dir() {
@@ -14,3 +15,15 @@ pub async fn get_token() -> Result<String> {
15 Err(anyhow!("Failed to get home directory."))
16 }
17 }
18 +
19 +pub async fn get_config() -> Result<Config> {
20 + match dirs::home_dir() {
21 + Some(mut path) => {
22 + path.push(".smb/config");
23 + let config = std::fs::read_to_string(path)?;
24 + let config: Config = serde_json::from_str(&config)?;
25 + Ok(config)
26 + }
27 + None => Err(anyhow!("Failed to get home directory.")),
28 + }
29 +}
smbpndk-utils/src/lib.rs
+8 -2
@@ -25,7 +25,10 @@ pub async fn get_config() -> Result<Config> {
25 if !path.exists() {
26 let config = Config {
27 current_project: None,
28 - current_auth_app: None,
28 + current_oten_app: None,
29 + current_fun_app: None,
30 + current_pkt_app: None,
31 + current_rdb_app: None,
32 };
33 return Ok(config);
34 }
@@ -43,7 +46,10 @@ pub async fn get_config() -> Result<Config> {
46 None => {
47 let config = Config {
48 current_project: None,
46 - current_auth_app: None,
49 + current_oten_app: None,
50 + current_fun_app: None,
51 + current_pkt_app: None,
52 + current_rdb_app: None,
53 };
54 Ok(config)
55 }