Streamlined grpc auth

Added ShareX Destiation on client
This commit is contained in:
2025-05-21 22:07:57 -04:00
parent acd30750a9
commit 7061b4c313
14 changed files with 155 additions and 46 deletions

View File

@@ -21,3 +21,8 @@ input[type="text"] {
border-radius: 20px;
}
}
textarea {
min-height: 200px;
min-width: 500px;
}

View File

@@ -30,6 +30,7 @@ body {
#content {
grid-area: Content;
overflow-x: hidden;
padding: 10px;
/* margin-left: $navBarSize; */
}
@@ -106,3 +107,11 @@ form {
align-self: center;
}
}
.codeSelect {
line-break: anywhere;
white-space: pre-wrap;
background-color: $featureColor;
padding: 5px;
user-select: all;
}

View File

@@ -1,9 +1,8 @@
use dioxus::prelude::*;
use tonic::{IntoRequest, Request};
use tonic::IntoRequest;
use crate::{
components::MediaItem,
contexts::AuthContext,
rpc::{aoba::PageFilter, get_rpc_client},
};
@@ -35,18 +34,9 @@ impl Into<PageFilter> for MediaGridProps {
#[component]
pub fn MediaGrid(props: MediaGridProps) -> Element {
let jwt = use_context::<AuthContext>().jwt;
let media_result = use_resource(use_reactive!(|(props, jwt)| async move {
let media_result = use_resource(use_reactive!(|(props)| async move {
let mut client = get_rpc_client();
let mut req = Request::new(props.into());
let token = if jwt.cloned().is_some() {
jwt.unwrap()
} else {
"".into()
};
req.metadata_mut()
.insert("authorization", format!("Bearer {token}").parse().unwrap());
let result = client.list_media(req).await;
let result = client.list_media(props.into_request()).await;
return result.expect("Failed to load media").into_inner();
}));

View File

@@ -1,6 +1,8 @@
use dioxus::signals::{Signal, Writable};
use web_sys::window;
use crate::rpc::{login, logout};
#[derive(Clone, Copy, Default)]
pub struct AuthContext {
pub jwt: Signal<Option<String>>,
@@ -11,12 +13,14 @@ impl AuthContext {
self.jwt.set(Some(token.clone()));
let local_storage = window().unwrap().local_storage().unwrap().unwrap();
_ = local_storage.set_item("token", token.as_str());
login(token.clone());
}
pub fn logout(&mut self) {
self.jwt.set(None);
let local_storage = window().unwrap().local_storage().unwrap().unwrap();
_ = local_storage.remove_item("token");
logout();
}
pub fn new() -> Self {
@@ -25,17 +29,14 @@ impl AuthContext {
match local_storage.get_item("token") {
Ok(value) => {
if let Some(jwt) = value {
println!("jwt");
login(jwt.clone());
return AuthContext {
jwt: Signal::new(Some(jwt)),
};
}
return AuthContext::default();
}
Err(_) => {
println!("err");
AuthContext::default()
}
Err(_) => AuthContext::default(),
}
}
}

View File

@@ -1,6 +1,6 @@
use dioxus::prelude::*;
use crate::{components::Navbar, contexts::AuthContext, views::Login, Route};
use crate::{Route, components::Navbar, contexts::AuthContext, views::Login};
#[component]
pub fn MainLayout() -> Element {
@@ -12,6 +12,9 @@ pub fn MainLayout() -> Element {
return rsx! {
Navbar {}
Outlet::<Route> {}
div{
id: "content",
Outlet::<Route> {}
}
};
}

View File

@@ -1,6 +1,7 @@
use std::sync::RwLock;
use aoba::{aoba_rpc_client::AobaRpcClient, auth_rpc_client::AuthRpcClient};
use tonic::service::{Interceptor, interceptor::InterceptedService};
use tonic_web_wasm_client::Client;
use crate::HOST;
@@ -13,16 +14,18 @@ pub mod aoba {
static RPC_CLIENT: RpcConnection = RpcConnection {
aoba: RwLock::new(None),
auth: RwLock::new(None),
jwt: RwLock::new(None),
};
#[derive(Default)]
pub struct RpcConnection {
aoba: RwLock<Option<AobaRpcClient<Client>>>,
aoba: RwLock<Option<AobaRpcClient<InterceptedService<Client, AuthInterceptor>>>>,
auth: RwLock<Option<AuthRpcClient<Client>>>,
jwt: RwLock<Option<String>>,
}
impl RpcConnection {
pub fn get_client(&self) -> AobaRpcClient<Client> {
pub fn get_client(&self) -> AobaRpcClient<InterceptedService<Client, AuthInterceptor>> {
self.ensure_client();
return self.aoba.read().unwrap().clone().unwrap();
}
@@ -35,16 +38,38 @@ impl RpcConnection {
fn ensure_client(&self) {
if self.aoba.read().unwrap().is_none() {
let wasm_client = Client::new(HOST.into());
*self.aoba.write().unwrap() = Some(AobaRpcClient::new(wasm_client.clone()));
let aoba_client = AobaRpcClient::with_interceptor(wasm_client.clone(), AuthInterceptor);
*self.aoba.write().unwrap() = Some(aoba_client);
*self.auth.write().unwrap() = Some(AuthRpcClient::new(wasm_client.clone()));
}
}
}
pub fn get_rpc_client() -> AobaRpcClient<Client> {
#[derive(Clone)]
pub struct AuthInterceptor;
impl Interceptor for AuthInterceptor {
fn call(&mut self, mut request: tonic::Request<()>) -> Result<tonic::Request<()>, tonic::Status> {
if let Some(jwt) = RPC_CLIENT.jwt.read().unwrap().clone() {
request
.metadata_mut()
.insert("authorization", format!("Bearer {jwt}").parse().unwrap());
}
return Ok(request);
}
}
pub fn get_rpc_client() -> AobaRpcClient<InterceptedService<Client, AuthInterceptor>> {
return RPC_CLIENT.get_client();
}
pub fn get_auth_rpc_client() -> AuthRpcClient<Client> {
return RPC_CLIENT.get_auth_client();
}
pub fn login(jwt: String) {
*RPC_CLIENT.jwt.write().unwrap() = Some(jwt);
}
pub fn logout() {
*RPC_CLIENT.jwt.write().unwrap() = None;
}

View File

@@ -6,12 +6,9 @@ pub fn Home() -> Element {
let query = use_signal(|| "".to_string());
rsx! {
div {
id: "content",
Search {
query: query
},
MediaGrid { query: query.cloned() }
}
Search {
query: query
},
MediaGrid { query: query.cloned() }
}
}

View File

@@ -1,6 +1,34 @@
use dioxus::prelude::*;
use crate::rpc::get_rpc_client;
#[component]
pub fn Settings() -> Element {
rsx! { "this is settings" }
let dst = use_resource(async move || {
let result = get_rpc_client().get_share_x_destination(()).await;
if let Ok(d) = result {
if let Some(r) = d.into_inner().dst_result {
return match r {
crate::rpc::aoba::share_x_response::DstResult::Destination(json) => json,
crate::rpc::aoba::share_x_response::DstResult::Error(err) => err,
};
}
return "No Result".to_string();
}
let err = result.err().unwrap();
let status = err.message();
return format!("Failed to load config: {status}").to_string();
});
let d = dst.cloned().unwrap_or("".to_string());
rsx! {
"this is settings"
div {
pre {
class: "codeSelect",
"test {d}"
}
}
}
}