This commit is contained in:
Aleksandr 2025-12-14 03:25:23 +03:00
parent 7583f7e557
commit 8d3c25b59d
34 changed files with 373 additions and 196 deletions

View file

@ -2,14 +2,14 @@ use viendesu_core::errors::AuxResult;
use super::*;
impl AuthenticationMut for Hidden<'_> {
impl Authentication for HttpClient {
async fn authenticate(&mut self, session: session::Token) -> AuxResult<()> {
self.0.session = Some(session);
self.session = Some(session);
Ok(())
}
fn clear(&mut self) {
self.0.session = None;
self.session = None;
}
}

View file

@ -4,15 +4,13 @@ use viendesu_core::requests::authors::{create, get, update};
use crate::requests::authors as requests;
impl AuthorsRef for Hidden<'_> {
impl Authors for HttpClient {
fn get(&mut self) -> impl CallStep<get::Args, Ok = get::Ok, Err = get::Err> {
self.do_call(Method::GET, |get::Args { author }| {
(format_compact!("/authors/{author}"), requests::Get {})
})
}
}
impl AuthorsMut for Hidden<'_> {
fn create(&mut self) -> impl CallStep<create::Args, Ok = create::Ok, Err = create::Err> {
self.do_call(
Method::POST,

View file

@ -4,13 +4,11 @@ use viendesu_core::requests::boards::{create, delete, edit, get};
use crate::requests::boards as requests;
impl BoardsRef for Hidden<'_> {
impl Boards for HttpClient {
fn get(&mut self) -> impl CallStep<get::Args, Ok = get::Ok, Err = get::Err> {
self.do_call(Method::GET, todo::<_, requests::Get>())
}
}
impl BoardsMut for Hidden<'_> {
fn create(&mut self) -> impl CallStep<create::Args, Ok = create::Ok, Err = create::Err> {
self.do_call(Method::POST, todo::<_, requests::Create>())
}

View file

@ -7,7 +7,7 @@ use viendesu_core::{
use crate::requests::games as requests;
impl GamesRef for Hidden<'_> {
impl Games for HttpClient {
fn get(&mut self) -> impl CallStep<get::Args, Ok = get::Ok, Err = get::Err> {
self.do_call(Method::GET, |get::Args { game }| match game {
Selector::Id(id) => (format_compact!("/games/{}", id.to_str()), requests::Get {}),
@ -45,9 +45,7 @@ impl GamesRef for Hidden<'_> {
},
)
}
}
impl GamesMut for Hidden<'_> {
fn create(&mut self) -> impl CallStep<create::Args, Ok = create::Ok, Err = create::Err> {
self.do_call(
Method::POST,

View file

@ -4,13 +4,11 @@ use viendesu_core::requests::messages::{delete, edit, get, post};
use crate::requests::messages as requests;
impl MessagesRef for Hidden<'_> {
impl Messages for HttpClient {
fn get(&mut self) -> impl CallStep<get::Args, Ok = get::Ok, Err = get::Err> {
self.do_call(Method::GET, todo::<_, requests::Get>())
}
}
impl MessagesMut for Hidden<'_> {
fn post(&mut self) -> impl CallStep<post::Args, Ok = post::Ok, Err = post::Err> {
self.do_call(Method::POST, todo::<_, requests::Post>())
}

View file

@ -10,14 +10,8 @@ use viendesu_core::{
errors::{self, Aux},
requests::Response,
service::{
CallStep, Session, SessionMaker,
authors::{AuthorsMut, AuthorsRef},
authz::AuthenticationMut,
boards::{BoardsMut, BoardsRef},
games::{GamesMut, GamesRef},
messages::{MessagesMut, MessagesRef},
threads::{ThreadsMut, ThreadsRef},
users::{UsersMut, UsersRef},
CallStep, Session, SessionMaker, authors::Authors, authz::Authentication, boards::Boards,
games::Games, messages::Messages, threads::Threads, users::Users,
},
types::session,
};
@ -57,30 +51,10 @@ where
}
}
struct Hidden<'a>(&'a mut HttpClient);
fn todo<C, O>() -> impl Send + Sync + FnMut(C) -> (CompactString, O) {
|_| todo!()
}
impl<'t> Hidden<'t> {
fn do_call<'this, P>(&'this mut self, method: Method, map_payload: P) -> DoRequest<'this, P> {
DoRequest {
client: self.0,
method,
map_payload,
}
}
}
macro_rules! fwd {
($($method:ident -> $Ret:ident;)*) => {$(
fn $method(&mut self) -> impl $Ret {
Hidden(self)
}
)*};
}
pub struct HttpClient {
options: Arc<ClientOptions>,
client: reqwest::Client,
@ -88,6 +62,14 @@ pub struct HttpClient {
}
impl HttpClient {
fn do_call<'this, P>(&'this mut self, method: Method, map_payload: P) -> DoRequest<'this, P> {
DoRequest {
client: self,
method,
map_payload,
}
}
async fn do_request<R>(
&self,
method: Method,
@ -150,21 +132,6 @@ impl HttpClient {
}
}
impl Session for HttpClient {
fwd! {
users -> UsersRef;
users_mut -> UsersMut;
authors -> AuthorsRef;
authors_mut -> AuthorsMut;
games -> GamesRef;
games_mut -> GamesMut;
boards -> BoardsMut;
threads -> ThreadsMut;
messages -> MessagesMut;
authentication_mut -> AuthenticationMut;
}
}
pub struct ClientOptions {
pub format: Format,
pub endpoint: String,
@ -179,12 +146,12 @@ pub struct HttpService {
impl SessionMaker for HttpService {
type Session = HttpClient;
async fn make_session(&self) -> errors::AuxResult<Self::Session> {
Ok(HttpClient {
async fn make_session(&self) -> errors::AuxResult<Session<Self::Session>> {
Ok(Session::new(HttpClient {
options: Arc::clone(&self.options),
client: self.inner.clone(),
session: None,
})
}))
}
}

View file

@ -4,7 +4,7 @@ use viendesu_core::requests::threads::{create, delete, edit, get, search};
use crate::requests::threads as requests;
impl ThreadsRef for Hidden<'_> {
impl Threads for HttpClient {
fn get(&mut self) -> impl CallStep<get::Args, Ok = get::Ok, Err = get::Err> {
self.do_call(Method::GET, todo::<_, requests::Get>())
}
@ -12,9 +12,7 @@ impl ThreadsRef for Hidden<'_> {
fn search(&mut self) -> impl CallStep<search::Args, Ok = search::Ok, Err = search::Err> {
self.do_call(Method::POST, todo::<_, requests::Search>())
}
}
impl ThreadsMut for Hidden<'_> {
fn delete(&mut self) -> impl CallStep<delete::Args, Ok = delete::Ok, Err = delete::Err> {
self.do_call(Method::DELETE, todo::<_, requests::Delete>())
}

View file

@ -8,7 +8,7 @@ use viendesu_core::requests::users::{
use crate::requests::users as requests;
impl UsersRef for Hidden<'_> {
impl Users for HttpClient {
fn get(&mut self) -> impl CallStep<get::Args, Ok = get::Ok, Err = get::Err> {
self.do_call(Method::GET, |get::Args { user }| match user {
Some(u) => (format_compact!("/users/{u}"), requests::Get {}),
@ -23,9 +23,7 @@ impl UsersRef for Hidden<'_> {
("/users/check_auth".into(), requests::CheckAuth {})
})
}
}
impl UsersMut for Hidden<'_> {
fn begin_auth(
&mut self,
) -> impl CallStep<begin_auth::Args, Ok = begin_auth::Ok, Err = begin_auth::Err> {

View file

@ -0,0 +1,19 @@
use eva::data;
use crate::requests::status_code;
use viendesu_core::{errors, requests::files as reqs};
#[data]
pub struct GetInfo {}
impl_req!(GetInfo => [reqs::get_info::Ok; reqs::get_info::Err]);
status_code::direct!(reqs::get_info::Ok => OK);
status_code::map!(reqs::get_info::Err => [NotFound]);
const _: () = {
use errors::files::*;
use status_code::direct;
direct!(NotFound => NOT_FOUND);
};

View file

@ -32,3 +32,6 @@ pub mod games;
pub mod boards;
pub mod messages;
pub mod threads;
pub mod files;
pub mod uploads;

View file

@ -0,0 +1,57 @@
use std::num::NonZeroU64;
use eva::data;
use crate::requests::status_code;
use viendesu_core::{errors, requests::uploads as reqs, types::file};
#[data]
pub struct ListPending {}
impl_req!(ListPending => [reqs::list_pending::Ok; reqs::list_pending::Err]);
status_code::direct!(reqs::list_pending::Ok => OK);
status_code::map!(reqs::list_pending::Err => []);
#[data]
pub struct Start {
pub file_name: Option<file::BaseName>,
pub hash: file::Hash,
pub class: file::ClassKind,
pub size: NonZeroU64,
}
impl_req!(Start => [reqs::start::Ok; reqs::start::Err]);
status_code::direct!(reqs::start::Ok => CREATED);
status_code::map!(reqs::start::Err => [QuotaExceeded, SimUpQuotaExceeded]);
#[data]
pub struct Finish {}
impl_req!(Finish => [reqs::finish::Ok; reqs::finish::Err]);
status_code::direct!(reqs::finish::Ok => OK);
status_code::map!(reqs::finish::Err => [
HashMismatch,
NotFound,
Overuploading,
ConcurrentUploadInProgress,
]);
#[data]
pub struct Abort {}
impl_req!(Abort => [reqs::abort::Ok; reqs::abort::Err]);
status_code::direct!(reqs::abort::Ok => OK);
status_code::map!(reqs::abort::Err => [NotFound]);
const _: () = {
use errors::uploads::*;
use status_code::direct;
direct!(ConcurrentUploadInProgress => BAD_REQUEST);
direct!(NotFound => NOT_FOUND);
direct!(QuotaExceeded => TOO_MANY_REQUESTS);
direct!(SimUpQuotaExceeded => TOO_MANY_REQUESTS);
direct!(Overuploading => BAD_REQUEST);
direct!(HashMismatch => BAD_REQUEST);
};

View file

@ -11,17 +11,14 @@ use axum::{
use viendesu_core::{
errors as core_errors,
service::{Session, SessionOf, authz::AuthenticationMut},
service::{Session, SessionOf, authz::Authentication as _},
};
use crate::{
format::Format,
server::{
State, Types,
context::{Context, load_args},
request::{ServerRequest, extract},
response,
},
use crate::server::{
State, Types,
context::{Context, load_args},
request::{ServerRequest, extract},
response,
};
struct Inner<R: ServerRequest, Cx> {
@ -130,7 +127,7 @@ impl<R: ServerRequest, M, T: Types, Cx: MakeContext<R>> FinishedHandler<R, M, T,
.map_err(|e| response::err(resp_format, e))?
{
session
.authentication_mut()
.authz()
.authenticate(token)
.await
.map_err(|e| response::err(resp_format, e))?;
@ -246,7 +243,7 @@ where
}
pub trait MakeRequest<T: Types, R: ServerRequest>:
Send + Sync + 'static + Fn(SessionOf<T::Service>, Context<R>) -> Self::HFut
Send + Sync + 'static + Fn(Session<SessionOf<T::Service>>, Context<R>) -> Self::HFut
{
type HFut: Fut<Output = core_errors::Result<R::Response, R::Error>>
+ Captures<SessionOf<T::Service>>;
@ -254,7 +251,7 @@ pub trait MakeRequest<T: Types, R: ServerRequest>:
impl<T, R, F, H> MakeRequest<T, R> for H
where
H: Send + Sync + 'static + Fn(SessionOf<T::Service>, Context<R>) -> F,
H: Send + Sync + 'static + Fn(Session<SessionOf<T::Service>>, Context<R>) -> F,
F: Fut<Output = core_errors::Result<R::Response, R::Error>> + Captures<SessionOf<T::Service>>,
T: Types,
R: ServerRequest,

View file

@ -5,7 +5,7 @@ use eva::{
use eyre::Context;
use viendesu_core::{
errors::AuxResult,
service::{Service, SessionMaker, SessionOf},
service::{IsService, Session, SessionMaker, SessionOf},
};
use tokio::net;
@ -22,7 +22,7 @@ mod response;
mod routes;
pub trait Types: Send + Sync + 'static {
type Service: Service + Clone;
type Service: IsService + Clone;
}
pub async fn serve(
@ -73,7 +73,7 @@ struct State<T: Types> {
}
impl<T: Types> State<T> {
async fn make_session(&self) -> AuxResult<SessionOf<T::Service>> {
self.service.make_session().await
async fn make_session(&self) -> AuxResult<Session<SessionOf<T::Service>>> {
Ok(self.service.make_session().await?)
}
}

View file

@ -5,14 +5,11 @@ use crate::server::{
};
use viendesu_core::{
service::{
CallStep, Session, SessionOf as SessionOfService,
users::{UsersMut, UsersRef},
},
service::{CallStep, Session, SessionOf as SessionOfService},
types::user,
};
type SessionOf<T> = SessionOfService<<T as Types>::Service>;
type SessionOf<T> = Session<SessionOfService<<T as Types>::Service>>;
pub fn make<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
router
@ -30,8 +27,11 @@ fn users<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
use crate::requests::users::{
BeginAuth, CheckAuth, ConfirmSignUp, FinishAuth, Get, SignIn, SignUp, Update,
};
use viendesu_core::requests::users::{
begin_auth, check_auth, confirm_sign_up, finish_auth, get, sign_in, sign_up, update,
use viendesu_core::{
requests::users::{
begin_auth, check_auth, confirm_sign_up, finish_auth, get, sign_in, sign_up, update,
},
service::users::Users,
};
fn convert_update(u: Update) -> update::Update {
@ -64,7 +64,7 @@ fn users<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
"/begin-auth",
post(async |mut session: SessionOf<T>, ctx: Ctx<BeginAuth>| {
session
.users_mut()
.users()
.begin_auth()
.call(begin_auth::Args {
method: ctx.request.method,
@ -78,7 +78,7 @@ fn users<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
async |mut session: SessionOf<T>, mut ctx: Ctx<FinishAuth>| {
let auth_session: user::AuthSessionId = ctx.path().await?;
session
.users_mut()
.users()
.finish_auth()
.call(finish_auth::Args { auth_session })
.await
@ -101,7 +101,7 @@ fn users<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
"/sign_in",
post(async |mut session: SessionOf<T>, ctx: Ctx<SignIn>| {
session
.users_mut()
.users()
.sign_in()
.call(sign_in::Args {
nickname: ctx.request.nickname,
@ -120,7 +120,7 @@ fn users<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
display_name,
} = ctx.request;
session
.users_mut()
.users()
.sign_up()
.call(sign_up::Args {
nickname,
@ -136,7 +136,7 @@ fn users<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
patch(async |mut session: SessionOf<T>, mut ctx: Ctx<Update>| {
let user: user::Selector = ctx.path().await?;
session
.users_mut()
.users()
.update()
.call(update::Args {
user: Some(user),
@ -149,7 +149,7 @@ fn users<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
"/me",
patch(async |mut session: SessionOf<T>, ctx: Ctx<Update>| {
session
.users_mut()
.users()
.update()
.call(update::Args {
user: None,
@ -164,7 +164,7 @@ fn users<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
async |mut session: SessionOf<T>, mut ctx: Ctx<ConfirmSignUp>| {
let (user, token) = ctx.path().await?;
session
.users_mut()
.users()
.confirm_sign_up()
.call(confirm_sign_up::Args { user, token })
.await
@ -173,12 +173,20 @@ fn users<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
)
}
fn uploads<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
use crate::requests::uploads::{Abort, Finish, ListPending, Start};
use viendesu_core::requests::uploads::{abort, finish, list_pending, start};
router
}
fn authors<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
use crate::requests::authors::{Create, Get, Update};
use viendesu_core::{
requests::authors::{create, get, update},
service::authors::{AuthorsMut as _, AuthorsRef as _},
service::authors::Authors,
types::author,
};
@ -193,7 +201,7 @@ fn authors<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
owner,
} = ctx.request;
session
.authors_mut()
.authors()
.create()
.call(create::Args {
title,
@ -226,7 +234,7 @@ fn authors<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
} = ctx.request;
session
.authors_mut()
.authors()
.update()
.call(update::Args {
author,
@ -248,7 +256,7 @@ fn games<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
use viendesu_core::{
requests::games::{create, get, search, update},
service::games::{GamesMut as _, GamesRef as _},
service::games::Games,
types::{author, game},
};
@ -266,7 +274,7 @@ fn games<T: Types>(router: RouterScope<T>) -> RouterScope<T> {
release_date,
} = ctx.request;
session
.games_mut()
.games()
.create()
.call(create::Args {
title,