Skip to content

Commit

Permalink
saves jwt to localStorage
Browse files Browse the repository at this point in the history
  • Loading branch information
Almaju committed Feb 28, 2024
1 parent 244027b commit 0191bf5
Show file tree
Hide file tree
Showing 15 changed files with 141 additions and 66 deletions.
25 changes: 25 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 10 additions & 6 deletions auth/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,26 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
base64 = "0.21.7"
chrono = { version = "0.4.33", features = ["serde"] }
forgen = { path = "../forgen" }
futures = { version = "0.3.30", optional = true }
gloo-net = { version = "0.5.0", optional = true }
gloo-storage = { version = "0.3.0", optional = true }
hmac = { version = "0.12.1", optional = true }
jwt = { version = "0.16.0", optional = true }
mongodb = { version = "2.8.0", optional = true }
mongodb = { version = "2.8.0", features = ["bson-uuid-1"], optional = true }
regex = "1.10.3"
reqwest = { version = "0.11", features = ["json"], optional = true }
serde = "1.0.196"
serde = { version = "1.0.196", features = ["derive"] }
serde_json = { version = "1.0.113", optional = true }
serde_urlencoded = { version = "0.7.1", optional = true }
sha2 = "0.10.8"
tokio = { version = "1.0", features = ["full"], optional = true }
urlencoding = { version = "2.1.3", optional = true }
uuid = { version = "1.7.0", features = ["serde", "v4"] }
web-sys = { version = "0.3.68", features = ["Document", "Location", "Url", "UrlSearchParams", "Window"], optional = true }
wasm-bindgen-futures = { version = "0.4.41", optional = true }
web-sys = { version = "0.3.68", features = ["Document", "Location", "Request", "Url", "UrlSearchParams", "Window"], optional = true }
yew = { git = "https://github.com/yewstack/yew/", optional = true }

[dev-dependencies]
Expand All @@ -30,10 +34,10 @@ serde_json = "1.0.113"
tokio = { version = "1.0", features = ["full"] }

[features]
default = ["jwt"]
default = []
jwt = ["dep:hmac", "dep:jwt"]
linkedin = ["dep:reqwest", "dep:serde_urlencoded"]
mongodb = ["dep:futures", "dep:mongodb"]
mongodb = ["dep:futures", "dep:mongodb", "dep:serde_json"]
tokio = ["dep:tokio"]
web_sys = ["dep:web-sys"]
web_sys = ["dep:gloo-net", "dep:gloo-storage", "dep:wasm-bindgen-futures", "dep:web-sys"]
yew = ["dep:yew"]
21 changes: 5 additions & 16 deletions auth/src/application/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,9 @@ use crate::domain::{
Error, Event, Message, State,
};
use forgen::*;
use serde::Deserialize;

#[derive(Deserialize)]
pub enum Command {
Register(Register),
Login(Login),
#[cfg(feature = "linkedin")]
ConnectLinkedIn(ConnectLinkedIn),
ProjectUser(ProjectUser),
}
use serde::{Deserialize, Serialize};

#[derive(Deserialize)]
#[derive(Serialize, Deserialize)]
pub struct Register {
pub email: Email,
pub password: Password,
Expand Down Expand Up @@ -74,7 +65,7 @@ where
// }
// }

#[derive(Deserialize)]
#[derive(Serialize, Deserialize)]
pub struct Login {
pub email: Email,
pub password: Password,
Expand Down Expand Up @@ -117,14 +108,12 @@ where
}
}

#[cfg(feature = "linkedin")]
#[derive(Deserialize)]
#[derive(Serialize, Deserialize)]
pub struct ConnectLinkedIn {
pub code: String,
pub transaction_id: Option<TransactionId>,
}

#[cfg(feature = "linkedin")]
#[async_trait]
impl<R> Execute<R> for ConnectLinkedIn
where
Expand Down Expand Up @@ -167,7 +156,7 @@ where
}
}

#[derive(Deserialize)]
#[derive(Serialize, Deserialize)]
pub struct ProjectUser {
pub events: Vec<Event>,
pub transaction_id: Option<TransactionId>,
Expand Down
18 changes: 14 additions & 4 deletions auth/src/application/port.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub trait EventStore {
async fn push(&self, events: &[Event]) -> Result<(), UnexpectedError>;
}

#[derive(Serialize)]
#[derive(Debug, Serialize, Deserialize)]
pub struct Jwt(pub String);

#[async_trait]
Expand All @@ -22,6 +22,13 @@ pub trait JwtPort {
async fn verify(&self, token: &Jwt) -> Result<User, UnexpectedError>;
}

#[async_trait]
#[delegate]
pub trait JwtStore {
async fn get(&self) -> Option<Jwt>;
async fn set(&self, jwt: &Jwt);
}

#[async_trait]
#[delegate]
pub trait LinkedInPort {
Expand Down Expand Up @@ -58,7 +65,7 @@ pub trait SignalPub {
async fn publish(&self, signal: Signal);
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)]
pub struct TransactionId(pub Uuid);

impl Default for TransactionId {
Expand All @@ -80,9 +87,12 @@ pub trait UserRepository {
async fn save(&self, projection: &User) -> Result<(), UnexpectedError>;
}

#[async_trait]
#[async_trait(?Send)]
#[delegate]
pub trait WebView {
fn get_query_param(&self, key: &str) -> Option<String>;
async fn push(&self, url: &str) -> Result<(), UnexpectedError>;
async fn open(&self, url: &str) -> Result<(), UnexpectedError>;
async fn post<T>(&self, url: &str, data: T) -> Result<Jwt, UnexpectedError>
where
T: Serialize;
}
47 changes: 27 additions & 20 deletions auth/src/application/presenter.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
use super::command::ConnectLinkedIn;
use super::port::*;
use forgen::*;

#[derive(Default, Clone, PartialEq)]
#[derive(Clone, Default, PartialEq)]
pub struct LoginForm {
email: String,
error: Option<String>,
password: String,
}

pub enum LoginAction {
Init,
#[cfg(feature = "linkedin")]
Init {
linkedin_api_url: Option<String>,
},
LoginWithLinkedIn {
client_id: String,
redirect_uri: String,
},
}

#[async_trait]
#[async_trait(?Send)]
impl<R> Reduce<R> for LoginForm
where
R: WebView,
R: JwtStore + WebView,
R: Send + Sync,
{
type Action = LoginAction;
Expand All @@ -29,27 +31,32 @@ where
let mut state = self.clone();

match action {
Self::Action::Init => {
let code = WebView::get_query_param(runtime, "code");
// if let Some(code) = code {
// let command = ConnectLinkedIn {
// code,
// transaction_id: None,
// };
// if let Err(error) = command.execute(runtime).await {
// self.error = Some(error.to_string());
// }
// }
panic!("code: {:?}", code);
Self::Action::Init { linkedin_api_url } => {
if let Some(linkedin_api_url) = linkedin_api_url {
if let Some(code) = WebView::get_query_param(runtime, "code") {
if let Ok(jwt) = WebView::post(
runtime,
&linkedin_api_url,
ConnectLinkedIn {
code,
transaction_id: None,
},
)
.await
{
info!("jwt: {}", &jwt.0);
JwtStore::set(runtime, &jwt).await;
}
}
}
}
#[cfg(feature = "linkedin")]
Self::Action::LoginWithLinkedIn {
client_id,
redirect_uri,
} => {
let url = format!("https://www.linkedin.com/oauth/v2/authorization?response_type={}&client_id={}&redirect_uri={}&scope={}", &"code", &client_id, &redirect_uri, "open_id,profile,email");
let url = format!("https://www.linkedin.com/oauth/v2/authorization?response_type={}&client_id={}&redirect_uri={}&scope={}", &"code", &client_id, &redirect_uri, "openid%20profile%20email");

if let Err(error) = WebView::push(runtime, &url).await {
if let Err(error) = WebView::open(runtime, &url).await {
state.error = Some(error.to_string());
}
}
Expand Down
4 changes: 2 additions & 2 deletions auth/src/domain/event.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use super::scalar::{Email, PasswordHash, UserId};
use serde::{Deserialize, Serialize};

#[derive(Clone, Deserialize, Serialize)]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "kind")]
pub enum Event {
Registered {
email: Email,
Expand All @@ -11,7 +12,6 @@ pub enum Event {
password_hash: PasswordHash,
user_id: UserId,
},
#[cfg(feature = "linkedin")]
LinkedInConnected {
access_token: String,
refresh_token: Option<String>,
Expand Down
1 change: 0 additions & 1 deletion auth/src/domain/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ pub enum Message {
email: Email,
password: Password,
},
#[cfg(feature = "linkedin")]
ConnectLinkedIn {
email: Email,
access_token: String,
Expand Down
2 changes: 1 addition & 1 deletion auth/src/domain/scalar/email.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use forgen::*;
use regex::Regex;
use serde::{Deserialize, Serialize};

#[derive(Clone, PartialEq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Email(#[serde(deserialize_with = "Email::deserialize")] String);

impl Email {
Expand Down
2 changes: 1 addition & 1 deletion auth/src/domain/scalar/password_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};

use super::password::Password;

#[derive(Clone, PartialEq, Deserialize, Serialize)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PasswordHash(pub [u8; 32]);

impl From<Password> for PasswordHash {
Expand Down
2 changes: 1 addition & 1 deletion auth/src/domain/scalar/user_id.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
use uuid::Uuid;

#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)]
pub struct UserId(pub Uuid);

impl UserId {
Expand Down
1 change: 0 additions & 1 deletion auth/src/domain/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ impl Dispatch for State {
Err(Error::InvalidPassword)
}
}
#[cfg(feature = "linkedin")]
Message::ConnectLinkedIn {
email,
access_token,
Expand Down
2 changes: 1 addition & 1 deletion auth/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ pub struct Runtime {
pub tokio: crate::services::tokio::Tokio,

#[cfg(feature = "web_sys")]
#[to(WebView)]
#[to(JwtStore, WebView)]
pub web_sys: crate::services::web_sys::WebSys,
}
Loading

0 comments on commit 0191bf5

Please sign in to comment.