From 4f4103dcc0ac7773ba85ad9f23ba40c945de4907 Mon Sep 17 00:00:00 2001 From: RobDavenport Date: Thu, 1 Feb 2024 23:11:53 +0900 Subject: [PATCH] move views around --- gamercade_app/src/app.rs | 94 +------------------------- gamercade_app/src/auth/auth_client.rs | 66 ++++++++---------- gamercade_app/src/auth/auth_state.rs | 13 ++-- gamercade_app/src/main.rs | 1 + gamercade_app/src/view/browsing.rs | 14 ++++ gamercade_app/src/view/login.rs | 55 +++++++++++++++ gamercade_app/src/view/mod.rs | 45 ++++++++++++ gamercade_app/src/view/sign_up.rs | 77 +++++++++++++++++++++ gamercade_interface/proto/auth.proto | 2 +- gamercade_interface/src/lib.rs | 25 +++++++ gamercade_interface/src/output/auth.rs | 4 +- 11 files changed, 255 insertions(+), 141 deletions(-) create mode 100644 gamercade_app/src/view/browsing.rs create mode 100644 gamercade_app/src/view/login.rs create mode 100644 gamercade_app/src/view/mod.rs create mode 100644 gamercade_app/src/view/sign_up.rs diff --git a/gamercade_app/src/app.rs b/gamercade_app/src/app.rs index 6be989ad..9a7e58fa 100644 --- a/gamercade_app/src/app.rs +++ b/gamercade_app/src/app.rs @@ -1,106 +1,18 @@ -use eframe::egui::{self, TextEdit, Ui}; +use eframe::egui::{self}; -use crate::auth::AuthClient; +use crate::{auth::AuthClient, view::ActiveView}; #[derive(Default)] pub struct App { auth_client: AuthClient, - username: String, - password: String, - email: String, - active_view: ActiveView, } -#[derive(Default)] -enum ActiveView { - #[default] - Login, - SignUp, - Browsing, -} - impl eframe::App for App { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { egui::CentralPanel::default().show(ctx, |ui| { - match self.active_view { - ActiveView::Login => self.draw_login(ui), - ActiveView::SignUp => self.draw_sign_up(ui), - ActiveView::Browsing => self.draw_browsing(ui), - }; - }); - } -} - -impl App { - fn draw_login(&mut self, ui: &mut Ui) { - ui.horizontal(|ui| { - ui.label("Username: "); - ui.text_edit_singleline(&mut self.username); - }); - - ui.horizontal(|ui| { - ui.label("Password: "); - let pw_entry = TextEdit::singleline(&mut self.password).password(true); - ui.add(pw_entry); - }); - - if ui.button("Sign Up").clicked() { - self.active_view = ActiveView::SignUp; - } - - if ui.button("Login").clicked() { - self.auth_client.try_login(&self.username, &self.password); - //TODO: Lock entries while waiting - //TODO: Show an animation thing - self.clear_text(); - } - - if ui.button("Login as Guest").clicked() { - println!("TODO: Login as guest!") - } - } - - fn draw_sign_up(&mut self, ui: &mut Ui) { - ui.horizontal(|ui| { - ui.label("Username: "); - ui.text_edit_singleline(&mut self.username); - }); - - ui.horizontal(|ui| { - ui.label("Email Address: "); - let email = TextEdit::singleline(&mut self.email); - ui.add(email); - }); - - ui.horizontal(|ui| { - ui.label("Password: "); - let pw_entry = TextEdit::singleline(&mut self.password).password(true); - ui.add(pw_entry); + self.active_view.draw(ui, &mut self.auth_client); }); - - if ui.button("Register").clicked() { - self.auth_client - .try_register(&self.username, &self.email, &self.password); - // TODO: Lock the entries while waiting... - // TODO: Show an animation thing... - self.clear_text(); - } - - if ui.button("Cancel").clicked() { - self.clear_text(); - self.active_view = ActiveView::Login; - } - } - - fn draw_browsing(&mut self, ui: &mut Ui) { - ui.label("Browsing"); - } - - fn clear_text(&mut self) { - self.username.clear(); - self.email.clear(); - self.password.clear(); } } diff --git a/gamercade_app/src/auth/auth_client.rs b/gamercade_app/src/auth/auth_client.rs index 737b3273..4c76b8fb 100644 --- a/gamercade_app/src/auth/auth_client.rs +++ b/gamercade_app/src/auth/auth_client.rs @@ -1,19 +1,19 @@ use std::sync::Arc; -use gamercade_interface::auth::{ - auth_service_client::AuthServiceClient, login_request::Provider, LoginRequest, - RefreshTokenRequest, SignUpRequest, -}; -use tokio::{ - select, - sync::{ - mpsc::{channel, Receiver, Sender}, - RwLock, +use gamercade_interface::{ + auth::{ + auth_service_client::AuthServiceClient, login_request::Provider, LoginRequest, + SignUpRequest, }, + Session, +}; +use tokio::sync::{ + mpsc::{channel, Receiver, Sender}, + RwLock, }; use tonic::transport::Channel; -use crate::{auth::auth_state::AuthToken, ips::AUTH_IP}; +use crate::ips::AUTH_IP; use super::auth_state::AuthState; @@ -25,7 +25,6 @@ pub struct AuthClient { pub enum AuthClientRequest { Login(LoginRequest), SignUp(SignUpRequest), - RefreshToken(RefreshTokenRequest), } impl Default for AuthClient { @@ -87,21 +86,18 @@ impl AuthTask { } } - async fn run(mut self) -> ! { + async fn run(mut self) { let mut client = AuthServiceClient::connect(AUTH_IP).await.unwrap(); - loop { - select! { - // Handle Requests - Some(request) = self.main_thread_receiver.recv() => { - match request { - AuthClientRequest::Login(login) => self.handle_login(&mut client, login).await, - AuthClientRequest::SignUp(signup) => self.handle_sign_up(&mut client, signup).await, - AuthClientRequest::RefreshToken(refresh) => self.handle_refresh(&mut client, refresh).await, - } - } + // Handle Requests + while let Some(request) = self.main_thread_receiver.recv().await { + match request { + AuthClientRequest::Login(login) => self.handle_login(&mut client, login).await, + AuthClientRequest::SignUp(signup) => self.handle_sign_up(&mut client, signup).await, } } + + println!("auth_client died."); } async fn handle_login( @@ -113,14 +109,16 @@ impl AuthTask { match client.login(request).await { Ok(response) => { let response = response.into_inner(); - let mut write = self.auth_state.write().await; - *write = AuthState::TokensHeld(AuthToken { - access_token: response.access_token, - refresh_token: response.refresh_token, - expires_at: response.expires_at, - }); - // TODO: Update the login page / move to browsing - println!("Logged in successfully: {:?}", write); + + if let Ok(session) = Session::try_from(response.session.as_slice()) { + let mut write = self.auth_state.write().await; + *write = AuthState::SessionHeld(session); + println!("Logged in successfully: {:?}", write); + // TODO: Update the login page / move to browsing + } else { + println!("Error parsing session from server") + // TODO: Handle this + } } Err(e) => { println!("{e}"); @@ -145,12 +143,4 @@ impl AuthTask { } } } - - async fn handle_refresh( - &mut self, - _client: &mut AuthServiceClient, - _request: RefreshTokenRequest, - ) { - todo!() - } } diff --git a/gamercade_app/src/auth/auth_state.rs b/gamercade_app/src/auth/auth_state.rs index 205e5ace..7522d5ec 100644 --- a/gamercade_app/src/auth/auth_state.rs +++ b/gamercade_app/src/auth/auth_state.rs @@ -1,16 +1,11 @@ +use gamercade_interface::Session; + #[derive(Default, Debug)] pub enum AuthState { // Default State #[default] Unauthorized, - // Holding Tokens - TokensHeld(AuthToken), -} - -#[derive(Debug)] -pub struct AuthToken { - pub access_token: String, - pub refresh_token: String, - pub expires_at: u64, + // Holding Session + SessionHeld(Session), } diff --git a/gamercade_app/src/main.rs b/gamercade_app/src/main.rs index f6488d9a..20c457b8 100644 --- a/gamercade_app/src/main.rs +++ b/gamercade_app/src/main.rs @@ -3,6 +3,7 @@ use eframe::egui; mod app; mod auth; mod ips; +mod view; #[tokio::main] async fn main() -> Result<(), eframe::Error> { diff --git a/gamercade_app/src/view/browsing.rs b/gamercade_app/src/view/browsing.rs new file mode 100644 index 00000000..ea19f747 --- /dev/null +++ b/gamercade_app/src/view/browsing.rs @@ -0,0 +1,14 @@ +use eframe::egui::Ui; + +use super::ActiveView; + +#[derive(Default)] +pub struct BrowsingView {} + +impl BrowsingView { + pub fn draw(&mut self, ui: &mut Ui) -> Option { + ui.label("Browsing"); + + None + } +} diff --git a/gamercade_app/src/view/login.rs b/gamercade_app/src/view/login.rs new file mode 100644 index 00000000..9674fff6 --- /dev/null +++ b/gamercade_app/src/view/login.rs @@ -0,0 +1,55 @@ +use eframe::egui::{TextEdit, Ui}; + +use crate::auth::AuthClient; + +use super::ActiveView; + +#[derive(Default)] +pub struct LoginView { + provider: String, + provider_kind: Provider, + password: String, +} + +#[derive(Default)] +enum Provider { + #[default] + Username, + Email, +} + +impl LoginView { + pub fn draw(&mut self, ui: &mut Ui, auth_client: &AuthClient) -> Option { + ui.horizontal(|ui| { + let text = match self.provider_kind { + Provider::Username => "Username: ", + Provider::Email => "Email: ", + }; + ui.label(text); + ui.text_edit_singleline(&mut self.provider); + }); + + ui.horizontal(|ui| { + ui.label("Password: "); + let pw_entry = TextEdit::singleline(&mut self.password).password(true); + ui.add(pw_entry); + }); + + if ui.button("Sign Up").clicked() { + return Some(ActiveView::sign_up()); + } + + if ui.button("Login").clicked() { + // TODO: Support email login too + auth_client.try_login(&self.provider, &self.password); + //TODO: Lock entries while waiting + //TODO: Show an animation thing + } + + if ui.button("Login as Guest").clicked() { + println!("TODO: Login as guest!") + } + + None + } +} diff --git a/gamercade_app/src/view/mod.rs b/gamercade_app/src/view/mod.rs new file mode 100644 index 00000000..87b4b73b --- /dev/null +++ b/gamercade_app/src/view/mod.rs @@ -0,0 +1,45 @@ +use eframe::egui::Ui; + +use crate::auth::AuthClient; + +use self::{browsing::BrowsingView, login::LoginView, sign_up::SignUpView}; + +mod browsing; +mod login; +mod sign_up; + +pub enum ActiveView { + Login(LoginView), + SignUp(SignUpView), + Browsing(BrowsingView), +} + +impl Default for ActiveView { + fn default() -> Self { + Self::login() + } +} + +impl ActiveView { + fn login() -> Self { + Self::Login(LoginView::default()) + } + + fn sign_up() -> Self { + Self::SignUp(SignUpView::default()) + } + + fn browsing() -> Self { + Self::Browsing(BrowsingView::default()) + } + + pub fn draw(&mut self, ui: &mut Ui, auth_client: &mut AuthClient) { + if let Some(next) = match self { + ActiveView::Login(view) => view.draw(ui, auth_client), + ActiveView::SignUp(view) => view.draw(ui, auth_client), + ActiveView::Browsing(view) => view.draw(ui), + } { + *self = next; + } + } +} diff --git a/gamercade_app/src/view/sign_up.rs b/gamercade_app/src/view/sign_up.rs new file mode 100644 index 00000000..c19868cb --- /dev/null +++ b/gamercade_app/src/view/sign_up.rs @@ -0,0 +1,77 @@ +use eframe::egui::{Button, TextEdit, Ui}; + +use crate::auth::AuthClient; + +use super::ActiveView; + +#[derive(Default)] +pub struct SignUpView { + username: String, + password: String, + password_confirm: String, + email: String, + email_confirm: String, +} + +impl SignUpView { + pub fn draw(&mut self, ui: &mut Ui, auth_client: &mut AuthClient) -> Option { + let mut email_equal = false; + let mut password_equal = false; + + ui.horizontal(|ui| { + ui.label("Username: "); + ui.text_edit_singleline(&mut self.username); + }); + + ui.horizontal(|ui| { + ui.label("Email Address: "); + let email = TextEdit::singleline(&mut self.email); + ui.add(email); + }); + + ui.horizontal(|ui| { + ui.label("Re-Enter Email Address: "); + let email = TextEdit::singleline(&mut self.email_confirm); + ui.add(email); + + if self.email != self.email_confirm { + ui.label("Email doesn't match."); + } else { + email_equal = true; + } + }); + + ui.horizontal(|ui| { + ui.label("Password: "); + let pw_entry = TextEdit::singleline(&mut self.password).password(true); + ui.add(pw_entry); + }); + + ui.horizontal(|ui| { + ui.label("Re-Enter Password: "); + let pw_entry = TextEdit::singleline(&mut self.password_confirm).password(true); + ui.add(pw_entry); + + if self.password != self.password_confirm { + ui.label("Password doesn't match."); + } else { + password_equal = true; + } + }); + + if ui + .add_enabled(email_equal && password_equal, Button::new("Register")) + .clicked() + { + auth_client.try_register(&self.username, &self.email, &self.password); + // TODO: Lock the entries while waiting... + // TODO: Show an animation thing... + } + + if ui.button("Cancel").clicked() { + Some(ActiveView::login()) + } else { + None + } + } +} diff --git a/gamercade_interface/proto/auth.proto b/gamercade_interface/proto/auth.proto index 26f7264f..3829b7bb 100644 --- a/gamercade_interface/proto/auth.proto +++ b/gamercade_interface/proto/auth.proto @@ -25,7 +25,7 @@ message LoginRequest { } message SessionResponse { - string session = 1; + bytes session = 1; } message UpdatePasswordRequest { diff --git a/gamercade_interface/src/lib.rs b/gamercade_interface/src/lib.rs index 37c5f1fe..2682615c 100644 --- a/gamercade_interface/src/lib.rs +++ b/gamercade_interface/src/lib.rs @@ -10,3 +10,28 @@ pub mod filter; pub const USERNAME_LENGTH_MIN: usize = 1; pub const USERNAME_LENGTH_MAX: usize = 32; + +#[derive(Debug)] +pub struct Session([u8; 16]); + +impl Session { + pub fn new(bytes: [u8; 16]) -> Self { + Self(bytes) + } +} + +impl Into> for Session { + fn into(self) -> Vec { + Vec::from(self.0) + } +} + +impl TryFrom<&[u8]> for Session { + type Error = &'static str; + + fn try_from(value: &[u8]) -> Result { + Ok(Self( + value.try_into().map_err(|_| "Error converting session.")?, + )) + } +} diff --git a/gamercade_interface/src/output/auth.rs b/gamercade_interface/src/output/auth.rs index 8721c797..24979bdf 100644 --- a/gamercade_interface/src/output/auth.rs +++ b/gamercade_interface/src/output/auth.rs @@ -30,8 +30,8 @@ pub mod login_request { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct SessionResponse { - #[prost(string, tag = "1")] - pub session: ::prost::alloc::string::String, + #[prost(bytes = "vec", tag = "1")] + pub session: ::prost::alloc::vec::Vec, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)]