diff --git a/AobaClient/build.rs b/AobaClient/build.rs index 17a0c39..53c244b 100644 --- a/AobaClient/build.rs +++ b/AobaClient/build.rs @@ -8,8 +8,13 @@ fn main() -> Result<(), Box> { .build_server(false) .build_client(true) .compile_protos( - &["../AobaServer/Proto/Aoba.proto", "../AobaServer/Proto/Auth.proto"], - &["../AobaServer/Proto/"], + &[ + "../AobaServer/Proto/Aoba.proto", + "../AobaServer/Proto/Auth.proto", + "../AobaServer/Proto/Metrics.proto", + "../AobaServer/Proto/Types.proto", + ], + &["../AobaServer/"], )?; forward_env(); Ok(()) diff --git a/AobaClient/src/components/metrics_token.rs b/AobaClient/src/components/metrics_token.rs new file mode 100644 index 0000000..ffae89b --- /dev/null +++ b/AobaClient/src/components/metrics_token.rs @@ -0,0 +1,25 @@ +use dioxus::prelude::*; + +use crate::rpc::get_metrics_rpc_client; + +#[component] +pub fn MetricsToken() -> Element { + let token = use_resource(async move || { + let response = get_metrics_rpc_client().get_token(()).await; + + if let Ok(d) = response { + let jwt = d.into_inner(); + return jwt.token; + } + return "".to_string(); + }); + + let token_value = token.cloned().unwrap_or("".to_string()); + + return rsx! { + pre { + class: "codeSelect", + "{token_value}" + } + }; +} diff --git a/AobaClient/src/components/mod.rs b/AobaClient/src/components/mod.rs index 15a1320..3793b05 100644 --- a/AobaClient/src/components/mod.rs +++ b/AobaClient/src/components/mod.rs @@ -1,11 +1,13 @@ pub mod basic; mod media_grid; mod media_item; +mod metrics_token; mod navbar; mod notif; mod search; pub use media_grid::*; pub use media_item::*; +pub use metrics_token::*; pub use navbar::*; pub use notif::*; pub use search::*; diff --git a/AobaClient/src/components/navbar.rs b/AobaClient/src/components/navbar.rs index eb4997c..f55063e 100644 --- a/AobaClient/src/components/navbar.rs +++ b/AobaClient/src/components/navbar.rs @@ -1,5 +1,3 @@ -use std::env; - use dioxus::prelude::*; use crate::{Route, contexts::AuthContext, env::APP_VERSION}; diff --git a/AobaClient/src/rpc.rs b/AobaClient/src/rpc.rs index d65edf6..ee442f3 100644 --- a/AobaClient/src/rpc.rs +++ b/AobaClient/src/rpc.rs @@ -1,19 +1,22 @@ use std::sync::RwLock; -use aoba::{aoba_rpc_client::AobaRpcClient, auth_rpc_client::AuthRpcClient}; +use aoba::aoba_rpc_client::AobaRpcClient; use tonic::service::{Interceptor, interceptor::InterceptedService}; use tonic_web_wasm_client::Client; -use crate::RPC_HOST; +use crate::{ + RPC_HOST, + rpc::aoba::{auth_rpc_client::AuthRpcClient, metrics_rpc_client::MetricsRpcClient}, +}; pub mod aoba { tonic::include_proto!("aoba"); - tonic::include_proto!("aoba.auth"); } static RPC_CLIENT: RpcConnection = RpcConnection { aoba: RwLock::new(None), auth: RwLock::new(None), + metrics: RwLock::new(None), jwt: RwLock::new(None), }; @@ -21,6 +24,7 @@ static RPC_CLIENT: RpcConnection = RpcConnection { pub struct RpcConnection { aoba: RwLock>>>, auth: RwLock>>, + metrics: RwLock>>>, jwt: RwLock>, } @@ -35,12 +39,19 @@ impl RpcConnection { return self.auth.read().unwrap().clone().unwrap(); } + pub fn get_metrics_client(&self) -> MetricsRpcClient> { + self.ensure_client(); + return self.metrics.read().unwrap().clone().unwrap(); + } + fn ensure_client(&self) { if self.aoba.read().unwrap().is_none() { let wasm_client = Client::new(RPC_HOST.into()); 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())); + *self.metrics.write().unwrap() = + Some(MetricsRpcClient::with_interceptor(wasm_client.clone(), AuthInterceptor)); } } } @@ -66,6 +77,9 @@ pub fn get_auth_rpc_client() -> AuthRpcClient { return RPC_CLIENT.get_auth_client(); } +pub fn get_metrics_rpc_client() -> MetricsRpcClient> { + return RPC_CLIENT.get_metrics_client(); +} pub fn login(jwt: String) { *RPC_CLIENT.jwt.write().unwrap() = Some(jwt); } diff --git a/AobaClient/src/views/settings.rs b/AobaClient/src/views/settings.rs index 1c6b774..d03da58 100644 --- a/AobaClient/src/views/settings.rs +++ b/AobaClient/src/views/settings.rs @@ -1,6 +1,6 @@ use dioxus::prelude::*; -use crate::rpc::get_rpc_client; +use crate::{components::MetricsToken, rpc::get_rpc_client}; #[component] pub fn Settings() -> Element { @@ -27,5 +27,6 @@ pub fn Settings() -> Element { div { pre { class: "codeSelect", "{d}" } } + MetricsToken { } } } diff --git a/AobaServer/AobaServer.csproj b/AobaServer/AobaServer.csproj index c72ec02..64b9f2a 100644 --- a/AobaServer/AobaServer.csproj +++ b/AobaServer/AobaServer.csproj @@ -35,6 +35,7 @@ + diff --git a/AobaServer/Program.cs b/AobaServer/Program.cs index 93f3c9c..93fe3bd 100644 --- a/AobaServer/Program.cs +++ b/AobaServer/Program.cs @@ -153,6 +153,9 @@ app.MapObserability(); app.MapGrpcService() .RequireAuthorization() .RequireCors("RPC"); +app.MapGrpcService() + .RequireAuthorization() + .RequireCors("RPC"); app.MapGrpcService() .AllowAnonymous() .RequireCors("RPC"); diff --git a/AobaServer/Proto/Aoba.proto b/AobaServer/Proto/Aoba.proto index 04b86c8..6013df8 100644 --- a/AobaServer/Proto/Aoba.proto +++ b/AobaServer/Proto/Aoba.proto @@ -3,6 +3,7 @@ import "google/protobuf/empty.proto"; option csharp_namespace = "Aoba.RPC"; package aoba; +import "Proto/Types.proto"; service AobaRpc { rpc GetMedia (Id) returns (MediaResponse); @@ -13,73 +14,3 @@ service AobaRpc { rpc GetShareXDestination(google.protobuf.Empty) returns (ShareXResponse); } -message PageFilter { - optional int32 page = 1; - optional int32 pageSize = 2; - optional string query = 3; -} - -message Id { - string value = 1; -} - -message MediaResponse { - oneof result { - MediaModel value = 1; - google.protobuf.Empty empty = 2; - } -} - -message ListResponse { - repeated MediaModel items = 1; - Pagination pagination = 2; -} - -message Pagination { - int32 page = 1; - int32 pageSize = 2; - int64 totalPages = 3; - int64 totalItems = 4; - optional string query = 5; -} - -message UserResponse { - oneof userResult { - UserModel user = 1; - google.protobuf.Empty empty = 2; - } -} - -message UserModel { - Id id = 1; - string username = 2; - string email = 3; - bool isAdmin = 4; -} - - -message MediaModel { - Id id = 1; - string fileName = 2; - MediaType mediaType = 3; - string ext = 4; - int32 viewCount = 5; - Id owner = 6; - string thumbUrl = 7; -} - -enum MediaType { - Image = 0; - Audio = 1; - Video = 2; - Text = 3; - Code = 4; - Raw = 5; -} - -message ShareXResponse { - oneof dstResult { - string destination = 1; - string error = 2; - } -} diff --git a/AobaServer/Proto/Auth.proto b/AobaServer/Proto/Auth.proto index 9b47da9..c409c05 100644 --- a/AobaServer/Proto/Auth.proto +++ b/AobaServer/Proto/Auth.proto @@ -1,33 +1,12 @@ syntax = "proto3"; option csharp_namespace = "Aoba.RPC.Auth"; -package aoba.Auth; +package aoba; + +import "Proto/Types.proto"; service AuthRpc { rpc Login(Credentials) returns (LoginResponse); rpc LoginPasskey(PassKeyPayload) returns (LoginResponse); } -message Credentials{ - string user = 1; - string password = 2; -} - -message PassKeyPayload { - -} - -message Jwt{ - string token = 1; -} - -message LoginResponse{ - oneof result { - Jwt jwt = 1; - LoginError error = 2; - } -} - -message LoginError{ - string message = 1; -} \ No newline at end of file diff --git a/AobaServer/Proto/Metrics.proto b/AobaServer/Proto/Metrics.proto index 6e227dc..bf56afd 100644 --- a/AobaServer/Proto/Metrics.proto +++ b/AobaServer/Proto/Metrics.proto @@ -1,12 +1,12 @@ syntax = "proto3"; option csharp_namespace = "Aoba.RPC.Metrics"; -package aoba.Metrics; +package aoba; -import "Proto/Auth.proto"; import "google/protobuf/empty.proto"; +import "Proto/Types.proto"; -service Metrics { - rpc GetToken(google.protobuf.Empty) returns (Auth.Jwt); +service MetricsRpc { + rpc GetToken(google.protobuf.Empty) returns (Jwt); } \ No newline at end of file diff --git a/AobaServer/Proto/Types.proto b/AobaServer/Proto/Types.proto new file mode 100644 index 0000000..41e441e --- /dev/null +++ b/AobaServer/Proto/Types.proto @@ -0,0 +1,101 @@ +syntax = "proto3"; + +option csharp_namespace = "Aoba.RPC"; +package aoba; +import "google/protobuf/empty.proto"; + +message Credentials{ + string user = 1; + string password = 2; +} + +message PassKeyPayload { + +} + + +message Jwt{ + string token = 1; +} + +message LoginResponse{ + oneof result { + Jwt jwt = 1; + LoginError error = 2; + } +} + +message LoginError{ + string message = 1; +} + +message PageFilter { + optional int32 page = 1; + optional int32 pageSize = 2; + optional string query = 3; +} + +message Id { + string value = 1; +} + +message MediaResponse { + oneof result { + MediaModel value = 1; + google.protobuf.Empty empty = 2; + } +} + +message ListResponse { + repeated MediaModel items = 1; + Pagination pagination = 2; +} + +message Pagination { + int32 page = 1; + int32 pageSize = 2; + int64 totalPages = 3; + int64 totalItems = 4; + optional string query = 5; +} + +message UserResponse { + oneof userResult { + UserModel user = 1; + google.protobuf.Empty empty = 2; + } +} + +message UserModel { + Id id = 1; + string username = 2; + string email = 3; + bool isAdmin = 4; +} + + +message MediaModel { + Id id = 1; + string fileName = 2; + MediaType mediaType = 3; + string ext = 4; + int32 viewCount = 5; + Id owner = 6; + string thumbUrl = 7; +} + +enum MediaType { + Image = 0; + Audio = 1; + Video = 2; + Text = 3; + Code = 4; + Raw = 5; +} + +message ShareXResponse { + oneof dstResult { + string destination = 1; + string error = 2; + } +} diff --git a/AobaServer/Services/AobaAuthService.cs b/AobaServer/Services/AobaAuthService.cs index b77febd..8861cb7 100644 --- a/AobaServer/Services/AobaAuthService.cs +++ b/AobaServer/Services/AobaAuthService.cs @@ -9,15 +9,13 @@ using AobaServer.Utils; using Grpc.Core; using Microsoft.AspNetCore.Authorization; -using Microsoft.IdentityModel.Tokens; +using Aoba.RPC; -using System.IdentityModel.Tokens.Jwt; namespace AobaServer.Services; -public class AobaAuthService(AccountsService accountsService, AuthInfo authInfo) : Aoba.RPC.Auth.AuthRpc.AuthRpcBase +public class AobaAuthService(AccountsService accountsService, AuthInfo authInfo) : AuthRpc.AuthRpcBase { - [AllowAnonymous] public override async Task Login(Credentials request, ServerCallContext context) { var user = await accountsService.VerifyLoginAsync(request.User, request.Password, context.CancellationToken); @@ -32,7 +30,7 @@ public class AobaAuthService(AccountsService accountsService, AuthInfo authInfo) var token = user.GetToken(authInfo); return new LoginResponse { - Jwt = new Jwt + Jwt = new () { Token = token } diff --git a/AobaServer/Services/MetricsRpcService.cs b/AobaServer/Services/MetricsRpcService.cs index b4d71fb..31e8e38 100644 --- a/AobaServer/Services/MetricsRpcService.cs +++ b/AobaServer/Services/MetricsRpcService.cs @@ -12,7 +12,7 @@ using System.IdentityModel.Tokens.Jwt; namespace AobaServer.Services; -public class MetricsRpcService(AuthConfigService authConfig): Aoba.RPC.Metrics.Metrics.MetricsBase +public class MetricsRpcService(AuthConfigService authConfig): Aoba.RPC.Metrics.MetricsRpc.MetricsRpcBase { [AllowAnonymous] public override async Task GetToken(Empty request, ServerCallContext context)