Streamlined grpc auth
Added ShareX Destiation on client
This commit is contained in:
@@ -21,3 +21,8 @@ input[type="text"] {
|
||||
border-radius: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
min-height: 200px;
|
||||
min-width: 500px;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}));
|
||||
|
||||
|
||||
@@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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> {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user