@smbcloud / cli / commits / c19b481

Modular design in steroids

Seto Elkahfi committed Apr 16, 2023 at 11:00 UTC c19b481b404eea05fef88d089b49199608a13a20
20 files changed +285 -210
Cargo.lock
+47
@@ -1077,6 +1077,7 @@ dependencies = [
1077 "dirs",
1078 "dotenv",
1079 "home",
1080 + "log",
1081 "open",
1082 "regex",
1083 "reqwest",
@@ -1084,6 +1085,9 @@ dependencies = [
1085 "serde_json",
1086 "smbpndk-model",
1087 "smbpndk-networking",
1088 + "smbpndk-networking-auth-app",
1089 + "smbpndk-networking-project",
1090 + "smbpndk-utils",
1091 "spinners",
1092 "tokio",
1093 "tracing",
@@ -1117,6 +1121,49 @@ dependencies = [
1121 "thiserror",
1122 ]
1123
1124 +[[package]]
1125 +name = "smbpndk-networking-auth-app"
1126 +version = "0.1.0"
1127 +dependencies = [
1128 + "anyhow",
1129 + "async-trait",
1130 + "dirs",
1131 + "home",
1132 + "log",
1133 + "maybe-async",
1134 + "reqwest",
1135 + "serde",
1136 + "serde_json",
1137 + "smbpndk-model",
1138 + "smbpndk-networking",
1139 + "thiserror",
1140 +]
1141 +
1142 +[[package]]
1143 +name = "smbpndk-networking-project"
1144 +version = "0.1.0"
1145 +dependencies = [
1146 + "anyhow",
1147 + "async-trait",
1148 + "dirs",
1149 + "home",
1150 + "log",
1151 + "maybe-async",
1152 + "reqwest",
1153 + "serde",
1154 + "serde_json",
1155 + "smbpndk-model",
1156 + "smbpndk-networking",
1157 + "thiserror",
1158 +]
1159 +
1160 +[[package]]
1161 +name = "smbpndk-utils"
1162 +version = "0.1.0"
1163 +dependencies = [
1164 + "regex",
1165 +]
1166 +
1167 [[package]]
1168 name = "socket2"
1169 version = "0.4.7"
Cargo.toml
+4 -1
@@ -1,6 +1,9 @@
1 [workspace]
2 members = [
3 "smbpndk-networking",
4 + "smbpndk-networking-auth-app",
5 + "smbpndk-networking-project",
6 "smbpndk-cli",
5 - "smbpndk-model"
7 + "smbpndk-model",
8 + "smbpndk-utils"
9 ]
smbpndk-cli/Cargo.toml
+5
@@ -2,6 +2,7 @@
2 name = "smbpndk-cli"
3 version = "0.2.1"
4 edition = "2021"
5 +authors = ["Seto Elkahfi <hej@setoelkahfi.se>"]
6 description = "Command line tool for creating and managing SmbPndk resources."
7 license = "Apache-2.0"
8 repository = "https://github.com/smbpndk/smbpndk-cli"
@@ -25,11 +26,15 @@ dotenv = "0.15.0"
26 home = "0.5.4"
27 open = "4.0.1"
28 regex = "1.3.1"
29 +log = "0.4.14"
30 reqwest = { version = "0.11", features = ["json"] }
31 serde = { version = "1", features = ["derive"] }
32 serde_json = "1.0.82"
33 +smbpndk-networking-auth-app = { path = "../smbpndk-networking-auth-app" }
34 +smbpndk-networking-project = { path = "../smbpndk-networking-project" }
35 smbpndk-networking = { path = "../smbpndk-networking" }
36 smbpndk-model = { path = "../smbpndk-model" }
37 +smbpndk-utils = { path = "../smbpndk-utils" }
38 spinners = "4.1.0"
39 tokio = { version = "1.14.1", features = ["full"] }
40 tracing = { version = "0.1.35", features = ["log"] }
smbpndk-cli/src/account/forgot/mod.rs
+2 -1
@@ -4,9 +4,10 @@ use dialoguer::{theme::ColorfulTheme, Input, Password};
4 use reqwest::{Client, StatusCode};
5 use serde::{Deserialize, Serialize};
6 use smbpndk_networking::constants::BASE_URL;
7 +use smbpndk_utils::email_validation;
8 use spinners::Spinner;
9
9 -use crate::util::{email_validation, CommandResult};
10 +use crate::cli::CommandResult;
11
12 #[derive(Debug, Serialize)]
13 struct Args {
smbpndk-cli/src/account/login/process.rs
+5 -5
@@ -6,6 +6,7 @@ use std::{
6 use anyhow::{anyhow, Result};
7 use console::style;
8 use dialoguer::{theme::ColorfulTheme, Input, Password};
9 +use log::debug;
10 use reqwest::Client;
11 use serde::{Deserialize, Serialize};
12 use smbpndk_networking::constants::BASE_URL;
@@ -13,8 +14,7 @@ use spinners::Spinner;
14
15 use crate::{
16 account::model::{Data, Status, User},
16 - debug,
17 - util::CommandResult,
17 + cli::CommandResult,
18 };
19
20 pub struct LoginArgs {
@@ -82,10 +82,10 @@ async fn do_process_login(args: LoginArgs) -> Result<()> {
82 let headers = response.headers();
83 match headers.get("Authorization") {
84 Some(token) => {
85 - debug!(token.to_str()?);
85 + debug!("{}", token.to_str()?);
86 match home::home_dir() {
87 Some(path) => {
88 - debug!(path.to_str().unwrap());
88 + debug!("{}", path.to_str().unwrap());
89 create_dir_all(path.join(".smb"))?;
90 let mut file = OpenOptions::new()
91 .create(true)
@@ -121,7 +121,7 @@ pub async fn process_logout() -> Result<CommandResult> {
121 );
122 match home::home_dir() {
123 Some(path) => {
124 - debug!(path.to_str().unwrap());
124 + debug!("{}", path.to_str().unwrap());
125 fs::remove_file([path.to_str().unwrap(), "/.smb/token"].join(""))?;
126
127 Ok(CommandResult {
smbpndk-cli/src/account/signup/process.rs
+4 -4
@@ -9,6 +9,7 @@ use std::{
9 use anyhow::{anyhow, Result};
10 use console::{style, Term};
11 use dialoguer::{theme::ColorfulTheme, Input, Password, Select};
12 +use log::debug;
13 use regex::Regex;
14 use reqwest::{Client, StatusCode};
15 use serde::{Deserialize, Serialize};
@@ -18,8 +19,7 @@ use url_builder::URLBuilder;
19
20 use crate::{
21 account::model::{Data, Status, User},
21 - debug,
22 - util::CommandResult,
22 + cli::CommandResult,
23 };
24
25 use super::SignupMethod;
@@ -182,7 +182,7 @@ fn handle_connection(mut stream: TcpStream, tx: Sender<String>) {
182 debug!("Code sent to channel.");
183 }
184 Err(e) => {
185 - debug!("Failed to send code to channel: {e}", e);
185 + debug!("Failed to send code to channel: {e}");
186 }
187 }
188 ("HTTP/1.1 200 OK", "./src/account/hello.html")
@@ -279,7 +279,7 @@ async fn get_github_data(token: String) -> Result<CommandResult> {
279 spinner.stop_and_persist("✅", "Finished requesting GitHub data!".into());
280 debug!("Response: {:#?}", &response);
281 let mut emails: Vec<GithubEmail> = response.json().await?;
282 - debug!(&emails);
282 + debug!("{:#?}", &emails);
283 emails.retain(|e| !e.email.contains("@users.noreply.github.com"));
284
285 let email = select_github_emails(emails)?;
smbpndk-cli/src/auth_app/mod.rs
+18 -21
@@ -1,11 +1,12 @@
1 use std::{fs::OpenOptions, io::Write};
2
3 -use crate::{auth_app::cli::Commands, debug, util::CommandResult};
3 +use crate::{auth_app::cli::Commands, cli::CommandResult};
4 use anyhow::{anyhow, Result};
5 use console::style;
6 use dialoguer::{theme::ColorfulTheme, Input};
7 +use log::debug;
8 use smbpndk_model::{AuthAppCreate, Config};
8 -use smbpndk_networking::{create_auth_app, delete_auth_app, get_auth_app, get_auth_apps};
9 +use smbpndk_networking_auth_app::{create_auth_app, delete_auth_app, get_auth_app, get_auth_apps};
10 use spinners::Spinner;
11
12 pub(crate) mod cli;
@@ -13,8 +14,8 @@ pub(crate) mod cli;
14 pub async fn process_auth_app(commands: Commands) -> Result<CommandResult> {
15 match commands {
16 Commands::New {} => {
16 - let project_name = Input::<String>::with_theme(&ColorfulTheme::default())
17 - .with_prompt("Project name")
17 + let app_name = Input::<String>::with_theme(&ColorfulTheme::default())
18 + .with_prompt("App name")
19 .interact()
20 .unwrap();
21 let description = Input::<String>::with_theme(&ColorfulTheme::default())
@@ -24,11 +25,11 @@ pub async fn process_auth_app(commands: Commands) -> Result<CommandResult> {
25
26 let spinner = Spinner::new(
27 spinners::Spinners::SimpleDotsScrolling,
27 - style("Creating project...").green().bold().to_string(),
28 + style("Creating an auth app...").green().bold().to_string(),
29 );
30
31 match create_auth_app(AuthAppCreate {
31 - name: project_name.clone(),
32 + name: app_name.clone(),
33 description: description.clone(),
34 })
35 .await
@@ -36,14 +37,14 @@ pub async fn process_auth_app(commands: Commands) -> Result<CommandResult> {
37 Ok(_) => Ok(CommandResult {
38 spinner,
39 symbol: "✅".to_owned(),
39 - msg: format!("Creating a project {project_name}."),
40 + msg: format!("An auth app created: {app_name}."),
41 }),
42 Err(e) => {
43 println!("Error: {e:#?}");
44 Ok(CommandResult {
45 spinner,
45 - symbol: "❌".to_owned(),
46 - msg: format!("Failed to create a project {project_name}."),
46 + symbol: "😩".to_owned(),
47 + msg: format!("Failed to create an auth app: {app_name}."),
48 })
49 }
50 }
@@ -53,8 +54,6 @@ pub async fn process_auth_app(commands: Commands) -> Result<CommandResult> {
54 spinners::Spinners::SimpleDotsScrolling,
55 style("Loading...").green().bold().to_string(),
56 );
56 -
57 - // Get all
57 match get_auth_apps().await {
58 Ok(auth_apps) => {
59 println!("auth_apps: {auth_apps:#?}");
@@ -71,7 +70,7 @@ pub async fn process_auth_app(commands: Commands) -> Result<CommandResult> {
70 Ok(CommandResult {
71 spinner,
72 symbol: "✅".to_owned(),
74 - msg: "Showing all projects.".to_owned(),
73 + msg: "Showing all auth apps.".to_owned(),
74 })
75 }
76 Err(e) => {
@@ -89,19 +88,18 @@ pub async fn process_auth_app(commands: Commands) -> Result<CommandResult> {
88 spinners::Spinners::SimpleDotsScrolling,
89 style("Loading...").green().bold().to_string(),
90 );
92 - // Get Detail
91 match get_auth_app(id).await {
92 Ok(_) => Ok(CommandResult {
93 spinner,
94 symbol: "✅".to_owned(),
97 - msg: "Showing all projects.".to_owned(),
95 + msg: "Showing auth app.".to_owned(),
96 }),
97 Err(e) => {
98 println!("Error: {e:#?}");
99 Ok(CommandResult {
100 spinner,
103 - symbol: "❌".to_owned(),
104 - msg: "Failed to get all projects.".to_owned(),
101 + symbol: "😩".to_owned(),
102 + msg: "Failed to get an auth app.".to_owned(),
103 })
104 }
105 }
@@ -111,19 +109,18 @@ pub async fn process_auth_app(commands: Commands) -> Result<CommandResult> {
109 spinners::Spinners::SimpleDotsScrolling,
110 style("Loading...").green().bold().to_string(),
111 );
114 - // Get Detail
112 match delete_auth_app(id).await {
113 Ok(_) => Ok(CommandResult {
114 spinner,
115 symbol: "✅".to_owned(),
119 - msg: "Showing all projects.".to_owned(),
116 + msg: "Delete auth app succeed.".to_owned(),
117 }),
118 Err(e) => {
119 println!("Error: {e:#?}");
120 Ok(CommandResult {
121 spinner,
125 - symbol: "❌".to_owned(),
126 - msg: "Failed to get all projects.".to_owned(),
122 + symbol: "😩".to_owned(),
123 + msg: "Failed to delete auth app.".to_owned(),
124 })
125 }
126 }
@@ -142,7 +139,7 @@ pub async fn process_auth_app(commands: Commands) -> Result<CommandResult> {
139 );
140 match home::home_dir() {
141 Some(path) => {
145 - debug!(path.to_str().unwrap());
142 + debug!("{}", path.to_str().unwrap());
143 let mut file = OpenOptions::new()
144 .create(true)
145 .write(true)
smbpndk-cli/src/cli/mod.rs
+8 -1
@@ -1,7 +1,14 @@
1 use clap::{Parser, Subcommand};
2 +use spinners::Spinner;
3
4 use crate::{auth_app, projects};
5
6 +pub struct CommandResult {
7 + pub spinner: Spinner,
8 + pub symbol: String,
9 + pub msg: String,
10 +}
11 +
12 #[derive(Parser)]
13 #[clap(author, version, about)]
14 pub struct Cli {
@@ -27,7 +34,7 @@ pub enum Commands {
34 #[clap(about = "Manage your projects. Add, delete, edit. Need authentication.")]
35 Projects {
36 #[clap(subcommand)]
30 - command: projects::Commands,
37 + command: projects::cli::Commands,
38 },
39
40 #[clap(about = "Manage your AuthApp. Add, delete, edit. Need authentication.")]
smbpndk-cli/src/lib.rs
-1
@@ -2,4 +2,3 @@ pub mod account;
2 pub mod auth_app;
3 pub mod cli;
4 pub mod projects;
5 -pub mod util;
smbpndk-cli/src/main.rs
+1 -2
@@ -11,9 +11,8 @@ use smbpndk_cli::{
11 signup::process_signup,
12 },
13 auth_app::process_auth_app,
14 - cli::{Cli, Commands},
14 + cli::{Cli, CommandResult, Commands},
15 projects::process_projects,
16 - util::CommandResult,
16 };
17
18 use tracing::subscriber::set_global_default;
smbpndk-cli/src/projects/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 project.")]
6 + New {},
7 +
8 + #[clap(about = "List all your projects.")]
9 + List {},
10 +
11 + #[clap(about = "Show detail of a project.")]
12 + Show {
13 + /// Project Id
14 + #[clap(short, long, required = true)]
15 + id: String,
16 + },
17 +
18 + #[clap(about = "Delete a project.")]
19 + Delete {
20 + /// Project name
21 + #[clap(short, long, required = true)]
22 + id: String,
23 + },
24 +
25 + #[clap(about = "Use project for current CLI session.")]
26 + Use {
27 + #[clap(short, long, required = true)]
28 + id: String,
29 + },
30 +}
smbpndk-cli/src/projects/mod.rs
+9 -38
@@ -1,46 +1,17 @@
1 -mod crud;
2 -
3 -use std::{fs::OpenOptions, io::Write};
1 +pub mod cli;
2
3 use anyhow::{anyhow, Result};
6 -use clap::Subcommand;
4 use console::style;
5 use dialoguer::{theme::ColorfulTheme, Input};
6 +use log::debug;
7 use smbpndk_model::{Config, ProjectCreate};
8 +use smbpndk_networking_project::{create_project, delete_project, get_all, get_project};
9 use spinners::Spinner;
10 +use std::{fs::OpenOptions, io::Write};
11
12 -use crate::{debug, util::CommandResult};
13 -
14 -use self::crud::{create_project, delete_project, get_all, get_project};
15 -
16 -#[derive(Subcommand)]
17 -pub enum Commands {
18 - #[clap(about = "Add new project.")]
19 - New {},
20 -
21 - #[clap(about = "List all your projects.")]
22 - List {},
23 -
24 - #[clap(about = "Show detail of a project.")]
25 - Show {
26 - /// Project Id
27 - #[clap(short, long, required = true)]
28 - id: String,
29 - },
30 -
31 - #[clap(about = "Delete a project.")]
32 - Delete {
33 - /// Project name
34 - #[clap(short, long, required = true)]
35 - id: String,
36 - },
12 +use crate::cli::CommandResult;
13
38 - #[clap(about = "Use project for current CLI session.")]
39 - Use {
40 - #[clap(short, long, required = true)]
41 - id: String,
42 - },
43 -}
14 +use self::cli::Commands;
15
16 pub async fn process_projects(commands: Commands) -> Result<CommandResult> {
17 match commands {
@@ -74,7 +45,7 @@ pub async fn process_projects(commands: Commands) -> Result<CommandResult> {
45 println!("Error: {e:#?}");
46 Ok(CommandResult {
47 spinner,
77 - symbol: "❌".to_owned(),
48 + symbol: "😩".to_owned(),
49 msg: format!("Failed to create a project {project_name}."),
50 })
51 }
@@ -132,7 +103,7 @@ pub async fn process_projects(commands: Commands) -> Result<CommandResult> {
103 println!("Error: {e:#?}");
104 Ok(CommandResult {
105 spinner,
135 - symbol: "❌".to_owned(),
106 + symbol: "😩".to_owned(),
107 msg: "Failed to get all projects.".to_owned(),
108 })
109 }
@@ -169,7 +140,7 @@ pub async fn process_projects(commands: Commands) -> Result<CommandResult> {
140 );
141 match home::home_dir() {
142 Some(path) => {
172 - debug!(path.to_str().unwrap());
143 + debug!("{}", path.to_str().unwrap());
144 let mut file = OpenOptions::new()
145 .create(true)
146 .write(true)
smbpndk-cli/src/util.rs deleted
-37
@@ -1,37 +0,0 @@
1 -use regex::Regex;
2 -use spinners::Spinner;
3 -
4 -#[macro_export]
5 -macro_rules! debug {
6 - ($($e:expr),+) => {
7 - {
8 - #[cfg(debug_assertions)]
9 - {
10 - dbg!($($e),+)
11 - }
12 - #[cfg(not(debug_assertions))]
13 - {
14 - ($($e),+)
15 - }
16 - }
17 - };
18 -}
19 -
20 -pub struct CommandResult {
21 - pub spinner: Spinner,
22 - pub symbol: String,
23 - pub msg: String,
24 -}
25 -
26 -pub fn email_validation(input: &str) -> Result<(), &'static str> {
27 - let email_regex = Regex::new(
28 - r"^([a-z0-9_+]([a-z0-9_+.]*[a-z0-9_+])?)@([a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6})",
29 - )
30 - .unwrap();
31 -
32 - if email_regex.is_match(input) {
33 - Ok(())
34 - } else {
35 - Err("Username must be an email address")
36 - }
37 -}
smbpndk-networking-auth-app/Cargo.toml new
+20
@@ -0,0 +1,20 @@
1 +[package]
2 +name = "smbpndk-networking-auth-app"
3 +version = "0.1.0"
4 +edition = "2021"
5 +
6 +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7 +
8 +[dependencies]
9 +reqwest = { version = "0.11", features = ["json"] }
10 +serde = { version = "1", features = ["derive"] }
11 +serde_json = "1.0.82"
12 +thiserror = "1.0.29"
13 +async-trait = { version = "0.1.51", optional = true }
14 +log = "0.4.14"
15 +maybe-async = { version = "0.2", features = ["is_sync"] }
16 +home = "0.5.4"
17 +anyhow = "1.0.58"
18 +dirs = "4.0.0"
19 +smbpndk-networking = { path = "../smbpndk-networking" }
20 +smbpndk-model = { path = "../smbpndk-model" }
\ No newline at end of file
smbpndk-networking-auth-app/src/lib.rs new
+84
@@ -0,0 +1,84 @@
1 +use anyhow::{anyhow, Result};
2 +use log::debug;
3 +use reqwest::Client;
4 +use smbpndk_model::{AuthApp, AuthAppCreate};
5 +use smbpndk_networking::{constants::BASE_URL, get_token};
6 +
7 +pub async fn get_auth_apps() -> Result<Vec<AuthApp>> {
8 + // Get current token
9 + let token = get_token().await?;
10 +
11 + let response = Client::new()
12 + .get([BASE_URL, "v1/auth_apps"].join(""))
13 + .header("Authorization", token)
14 + .send()
15 + .await?;
16 +
17 + match response.status() {
18 + reqwest::StatusCode::OK => {
19 + let auth_apps: Vec<AuthApp> = response.json().await?;
20 + Ok(auth_apps)
21 + }
22 + _ => Err(anyhow!("Failed to fetch auth apps.")),
23 + }
24 +}
25 +
26 +pub async fn get_auth_app(id: String) -> Result<AuthApp> {
27 + // Get current token
28 + let token = get_token().await?;
29 +
30 + let response = Client::new()
31 + .get([BASE_URL, "v1/auth_apps/", &id].join(""))
32 + .header("Authorization", token)
33 + .send()
34 + .await?;
35 +
36 + match response.status() {
37 + reqwest::StatusCode::OK => {
38 + let auth_app: AuthApp = response.json().await?;
39 + println!("Project requested: {auth_app:#?}");
40 + Ok(auth_app)
41 + }
42 + _ => Err(anyhow!("Failed to request an auth app.")),
43 + }
44 +}
45 +
46 +pub async fn delete_auth_app(id: String) -> Result<()> {
47 + // Get current token
48 + let token = get_token().await?;
49 +
50 + let response = Client::new()
51 + .delete([BASE_URL, "v1/auth_apps/", &id].join(""))
52 + .header("Authorization", token)
53 + .send()
54 + .await?;
55 +
56 + match response.status() {
57 + reqwest::StatusCode::OK => {
58 + debug!("Project deleted.");
59 + Ok(())
60 + }
61 + _ => Err(anyhow!("Failed to delete an auth app.")),
62 + }
63 +}
64 +
65 +pub async fn create_auth_app(auth_app: AuthAppCreate) -> Result<AuthApp> {
66 + // Get current token
67 + let token = get_token().await?;
68 +
69 + let response = Client::new()
70 + .post([BASE_URL, "v1/auth_apps"].join(""))
71 + .json(&auth_app)
72 + .header("Authorization", token)
73 + .send()
74 + .await?;
75 +
76 + match response.status() {
77 + reqwest::StatusCode::CREATED => {
78 + let auth_app: AuthApp = response.json().await?;
79 + println!("Project created: {auth_app:#?}");
80 + Ok(auth_app)
81 + }
82 + _ => Err(anyhow!("Failed to create an auth app.")),
83 + }
84 +}
smbpndk-networking-project/Cargo.toml new
+20
@@ -0,0 +1,20 @@
1 +[package]
2 +name = "smbpndk-networking-project"
3 +version = "0.1.0"
4 +edition = "2021"
5 +
6 +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7 +
8 +[dependencies]
9 +reqwest = { version = "0.11", features = ["json"] }
10 +serde = { version = "1", features = ["derive"] }
11 +serde_json = "1.0.82"
12 +thiserror = "1.0.29"
13 +async-trait = { version = "0.1.51", optional = true }
14 +log = "0.4.14"
15 +maybe-async = { version = "0.2", features = ["is_sync"] }
16 +home = "0.5.4"
17 +anyhow = "1.0.58"
18 +dirs = "4.0.0"
19 +smbpndk-networking = { path = "../smbpndk-networking" }
20 +smbpndk-model = { path = "../smbpndk-model" }
\ No newline at end of file
smbpndk-networking-project/src/lib.rs renamed
+5 -17
@@ -1,5 +1,5 @@
1 -use crate::debug;
1 use anyhow::{anyhow, Result};
2 +use log::debug;
3 use reqwest::Client;
4
5 use smbpndk_model::{Project, ProjectCreate};
@@ -23,10 +23,7 @@ pub async fn get_all() -> Result<Vec<Project>> {
23 let projects: Vec<Project> = response.json().await?;
24 Ok(projects)
25 }
26 - _ => {
27 - debug!("Failed to get all projects.", response.status());
28 - Err(anyhow!("Failed to fetch projects."))
29 - }
26 + _ => Err(anyhow!("Failed to fetch projects.")),
27 }
28 }
29
@@ -47,10 +44,7 @@ pub async fn create_project(project: ProjectCreate) -> Result<Project> {
44 println!("Project created: {project:#?}");
45 Ok(project)
46 }
50 - _ => {
51 - debug!("Failed to create a project.", response.status());
52 - Err(anyhow!("Failed to create a project."))
53 - }
47 + _ => Err(anyhow!("Failed to create a project.")),
48 }
49 }
50
@@ -70,10 +64,7 @@ pub async fn get_project(id: String) -> Result<Project> {
64 println!("Project requested: {project:#?}");
65 Ok(project)
66 }
73 - _ => {
74 - debug!("Failed to request a project.", response.status());
75 - Err(anyhow!("Failed to request a project."))
76 - }
67 + _ => Err(anyhow!("Failed to request a project.")),
68 }
69 }
70
@@ -92,9 +83,6 @@ pub async fn delete_project(id: String) -> Result<()> {
83 debug!("Project deleted.");
84 Ok(())
85 }
95 - _ => {
96 - debug!("Failed to request a project.", response.status());
97 - Err(anyhow!("Failed to delete a project."))
98 - }
86 + _ => Err(anyhow!("Failed to delete a project.")),
87 }
88 }
smbpndk-networking/src/lib.rs
-82
@@ -1,10 +1,7 @@
1 pub mod constants;
2
3 use anyhow::{anyhow, Result};
4 -use constants::BASE_URL;
4 use log::debug;
6 -use reqwest::Client;
7 -use smbpndk_model::{AuthApp, AuthAppCreate};
5
6 pub async fn get_token() -> Result<String> {
7 if let Some(mut path) = dirs::home_dir() {
@@ -17,82 +14,3 @@ pub async fn get_token() -> Result<String> {
14 Err(anyhow!("Failed to get home directory."))
15 }
16 }
20 -
21 -pub async fn get_auth_apps() -> Result<Vec<AuthApp>> {
22 - // Get current token
23 - let token = get_token().await?;
24 -
25 - let response = Client::new()
26 - .get([BASE_URL, "v1/auth_apps"].join(""))
27 - .header("Authorization", token)
28 - .send()
29 - .await?;
30 -
31 - match response.status() {
32 - reqwest::StatusCode::OK => {
33 - let projects: Vec<AuthApp> = response.json().await?;
34 - Ok(projects)
35 - }
36 - _ => Err(anyhow!("Failed to fetch auth apps.")),
37 - }
38 -}
39 -
40 -pub async fn get_auth_app(id: String) -> Result<AuthApp> {
41 - // Get current token
42 - let token = get_token().await?;
43 -
44 - let response = Client::new()
45 - .get([BASE_URL, "v1/auth_apps/", &id].join(""))
46 - .header("Authorization", token)
47 - .send()
48 - .await?;
49 -
50 - match response.status() {
51 - reqwest::StatusCode::OK => {
52 - let project: AuthApp = response.json().await?;
53 - println!("Project requested: {project:#?}");
54 - Ok(project)
55 - }
56 - _ => Err(anyhow!("Failed to request an auth app.")),
57 - }
58 -}
59 -
60 -pub async fn delete_auth_app(id: String) -> Result<()> {
61 - // Get current token
62 - let token = get_token().await?;
63 -
64 - let response = Client::new()
65 - .delete([BASE_URL, "v1/auth_apps/", &id].join(""))
66 - .header("Authorization", token)
67 - .send()
68 - .await?;
69 -
70 - match response.status() {
71 - reqwest::StatusCode::OK => {
72 - debug!("Project deleted.");
73 - Ok(())
74 - }
75 - _ => Err(anyhow!("Failed to delete a project.")),
76 - }
77 -}
78 -
79 -pub async fn create_auth_app(auth_app: AuthAppCreate) -> Result<AuthApp> {
80 - // Get current token
81 - let token = get_token().await?;
82 -
83 - let response = Client::new()
84 - .post([BASE_URL, "v1/auth_apps"].join(""))
85 - .json(&auth_app)
86 - .header("Authorization", token)
87 - .send()
88 - .await?;
89 -
90 - match response.status() {
91 - reqwest::StatusCode::CREATED => {
92 - let project: AuthApp = response.json().await?;
93 - println!("Project created: {project:#?}");
94 - Ok(project)
95 - }
96 - _ => Err(anyhow!("Failed to create a project.")),
97 - }
98 -}
smbpndk-utils/Cargo.toml new
+9
@@ -0,0 +1,9 @@
1 +[package]
2 +name = "smbpndk-utils"
3 +version = "0.1.0"
4 +edition = "2021"
5 +
6 +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7 +
8 +[dependencies]
9 +regex = "1.3.1"
\ No newline at end of file
smbpndk-utils/src/lib.rs new
+14
@@ -0,0 +1,14 @@
1 +use regex::Regex;
2 +
3 +pub fn email_validation(input: &str) -> Result<(), &'static str> {
4 + let email_regex = Regex::new(
5 + r"^([a-z0-9_+]([a-z0-9_+.]*[a-z0-9_+])?)@([a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6})",
6 + )
7 + .unwrap();
8 +
9 + if email_regex.is_match(input) {
10 + Ok(())
11 + } else {
12 + Err("Username must be an email address")
13 + }
14 +}