stuff
This commit is contained in:
@@ -1,22 +0,0 @@
|
|||||||
use ed25519_dalek::SigningKey;
|
|
||||||
use rand::{
|
|
||||||
SeedableRng,
|
|
||||||
rngs::{StdRng, SysRng},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct Account {
|
|
||||||
device_key: SigningKey,
|
|
||||||
account_key: SigningKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Account {
|
|
||||||
pub fn new() -> Account {
|
|
||||||
let mut csprng = StdRng::try_from_rng(&mut SysRng).unwrap();
|
|
||||||
let device_key = SigningKey::generate(&mut csprng);
|
|
||||||
let account_key = SigningKey::generate(&mut csprng);
|
|
||||||
Account {
|
|
||||||
device_key,
|
|
||||||
account_key,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#![feature(async_fn_traits)]
|
#![feature(async_fn_traits)]
|
||||||
#![windows_subsystem = "windows"]
|
#![windows_subsystem = "windows"]
|
||||||
|
|
||||||
use crate::{data::ClientData, state::ClientState};
|
use crate::data::ClientData;
|
||||||
use iris::prelude::*;
|
use iris::prelude::*;
|
||||||
use openworm::net::{ServerMsg, install_crypto_provider};
|
use openworm::net::{ServerMsg, install_crypto_provider};
|
||||||
use winit::{
|
use winit::{
|
||||||
@@ -9,11 +9,10 @@ use winit::{
|
|||||||
window::WindowAttributes,
|
window::WindowAttributes,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod account;
|
|
||||||
mod data;
|
mod data;
|
||||||
mod debug;
|
mod debug;
|
||||||
mod net;
|
mod net;
|
||||||
mod state;
|
mod session;
|
||||||
mod ui;
|
mod ui;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -25,10 +24,8 @@ fn main() {
|
|||||||
pub struct Client {
|
pub struct Client {
|
||||||
ui_state: DefaultUiState,
|
ui_state: DefaultUiState,
|
||||||
data: ClientData,
|
data: ClientData,
|
||||||
state: ClientState,
|
|
||||||
main_ui: WeakWidget<WidgetPtr>,
|
main_ui: WeakWidget<WidgetPtr>,
|
||||||
notif: WeakWidget<WidgetPtr>,
|
notif: WeakWidget<WidgetPtr>,
|
||||||
proxy: Proxy<ClientEvent>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Rsc = DefaultRsc<Client>;
|
pub type Rsc = DefaultRsc<Client>;
|
||||||
@@ -44,7 +41,7 @@ impl DefaultAppState for Client {
|
|||||||
fn new(
|
fn new(
|
||||||
mut ui_state: DefaultUiState,
|
mut ui_state: DefaultUiState,
|
||||||
rsc: &mut DefaultRsc<Self>,
|
rsc: &mut DefaultRsc<Self>,
|
||||||
proxy: Proxy<Self::Event>,
|
_: Proxy<Self::Event>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let notif = WidgetPtr::default().add(rsc);
|
let notif = WidgetPtr::default().add(rsc);
|
||||||
let main_ui = WidgetPtr::default().add(rsc);
|
let main_ui = WidgetPtr::default().add(rsc);
|
||||||
@@ -68,10 +65,8 @@ impl DefaultAppState for Client {
|
|||||||
Self {
|
Self {
|
||||||
ui_state,
|
ui_state,
|
||||||
data,
|
data,
|
||||||
state: Default::default(),
|
|
||||||
main_ui,
|
main_ui,
|
||||||
notif,
|
notif,
|
||||||
proxy,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,10 +84,6 @@ impl DefaultAppState for Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exit(&mut self, _rsc: &mut DefaultRsc<Self>, _render: &mut UiRenderState) {
|
|
||||||
self.state.exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn window_event(
|
fn window_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
event: WindowEvent,
|
event: WindowEvent,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use crate::ClientEvent;
|
use crate::ClientEvent;
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use openworm::net::{
|
use openworm::net::{
|
||||||
ClientMsg, ClientRequestMsg, CreateAccount, CreateAccountResp, Login, LoginResp, RecvHandler,
|
ClientMsg, ClientRequestMsg, RecvHandler, RequestId, RequestMsg, SERVER_NAME, ServerMsg,
|
||||||
RequestId, SERVER_NAME, ServerMsg, ServerRespMsg, SkipServerVerification, recv_uni, send_uni,
|
ServerRespMsg, SkipServerVerification, recv_uni, send_uni,
|
||||||
};
|
};
|
||||||
use quinn::{
|
use quinn::{
|
||||||
ClientConfig, Connection, Endpoint, IdleTimeout, TransportConfig,
|
ClientConfig, Connection, Endpoint, IdleTimeout, TransportConfig,
|
||||||
@@ -25,6 +25,7 @@ pub struct ConnectInfo {
|
|||||||
pub cert: Vec<u8>,
|
pub cert: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct NetHandle {
|
pub struct NetHandle {
|
||||||
send: UnboundedSender<NetCtrlMsg>,
|
send: UnboundedSender<NetCtrlMsg>,
|
||||||
}
|
}
|
||||||
@@ -75,35 +76,6 @@ impl NetHandle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RequestMsg: Into<ClientMsg> {
|
|
||||||
type Result;
|
|
||||||
fn result(msg: ServerMsg) -> Option<Self::Result>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RequestMsg for CreateAccount {
|
|
||||||
type Result = CreateAccountResp;
|
|
||||||
|
|
||||||
fn result(msg: ServerMsg) -> Option<Self::Result> {
|
|
||||||
if let ServerMsg::CreateAccountResp(res) = msg {
|
|
||||||
Some(res)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RequestMsg for Login {
|
|
||||||
type Result = LoginResp;
|
|
||||||
|
|
||||||
fn result(msg: ServerMsg) -> Option<Self::Result> {
|
|
||||||
if let ServerMsg::LoginResp(res) = msg {
|
|
||||||
Some(res)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn connection_cert(
|
async fn connection_cert(
|
||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
cert: CertificateDer<'_>,
|
cert: CertificateDer<'_>,
|
||||||
@@ -118,8 +90,7 @@ async fn connection_cert(
|
|||||||
let client_config = ClientConfig::new(Arc::new(
|
let client_config = ClientConfig::new(Arc::new(
|
||||||
QuicClientConfig::try_from(client_crypto).map_err(|e| e.to_string())?,
|
QuicClientConfig::try_from(client_crypto).map_err(|e| e.to_string())?,
|
||||||
));
|
));
|
||||||
let mut endpoint = quinn::Endpoint::client(SocketAddr::from_str("[::]:0").unwrap())
|
let mut endpoint = quinn::Endpoint::client(CLIENT_SOCKET).map_err(|e| e.to_string())?;
|
||||||
.map_err(|e| e.to_string())?;
|
|
||||||
endpoint.set_default_client_config(client_config);
|
endpoint.set_default_client_config(client_config);
|
||||||
let conn = endpoint
|
let conn = endpoint
|
||||||
.connect(addr, SERVER_NAME)
|
.connect(addr, SERVER_NAME)
|
||||||
|
|||||||
8
src/bin/client/session.rs
Normal file
8
src/bin/client/session.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use openworm::net::UserId;
|
||||||
|
|
||||||
|
use crate::net::NetHandle;
|
||||||
|
|
||||||
|
pub struct Session {
|
||||||
|
pub con: NetHandle,
|
||||||
|
pub user_id: UserId,
|
||||||
|
}
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
use crate::net::NetHandle;
|
|
||||||
use iris::prelude::*;
|
|
||||||
use openworm::net::LoadMsg;
|
|
||||||
use std::thread::JoinHandle;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct Connect {
|
|
||||||
pub handle: Option<JoinHandle<()>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Login {
|
|
||||||
pub handle: NetHandle,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct LoggedIn {
|
|
||||||
pub network: NetHandle,
|
|
||||||
pub msgs: Vec<LoadMsg>,
|
|
||||||
pub channel: Option<WeakWidget<Span>>,
|
|
||||||
pub username: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum ClientState {
|
|
||||||
Connect(Connect),
|
|
||||||
Login(Login),
|
|
||||||
LoggedIn(LoggedIn),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for ClientState {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::Connect(Default::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ClientState {
|
|
||||||
pub fn take(&mut self) -> Self {
|
|
||||||
std::mem::take(self)
|
|
||||||
}
|
|
||||||
pub fn exit(&mut self) {
|
|
||||||
let s = self.take();
|
|
||||||
match s {
|
|
||||||
ClientState::Connect(_) => (),
|
|
||||||
ClientState::Login(Login { handle }) => {
|
|
||||||
handle.exit();
|
|
||||||
}
|
|
||||||
ClientState::LoggedIn(state) => {
|
|
||||||
state.network.exit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
use openworm::net::{CreateAccount, CreateAccountResp, Login, LoginResp};
|
use openworm::net::{CreateAccount, CreateAccountResp, Login, LoginResp};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
session::Session,
|
||||||
data::{AccountInfo, ClientData, ServerInfo, ServerList},
|
data::{AccountInfo, ClientData, ServerInfo, ServerList},
|
||||||
net::{ConnectInfo, NetHandle},
|
net::{ConnectInfo, NetHandle},
|
||||||
};
|
};
|
||||||
@@ -53,7 +54,7 @@ pub fn start(rsc: &mut Rsc, data: &ClientData) -> WeakWidget {
|
|||||||
rsc[ctx.notif].inner = Some(werror(&reason, rsc));
|
rsc[ctx.notif].inner = Some(werror(&reason, rsc));
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
let net = match NetHandle::connect(
|
let con = match NetHandle::connect(
|
||||||
async |msg| {
|
async |msg| {
|
||||||
println!("msg recv :joy:");
|
println!("msg recv :joy:");
|
||||||
},
|
},
|
||||||
@@ -70,7 +71,7 @@ pub fn start(rsc: &mut Rsc, data: &ClientData) -> WeakWidget {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let Ok(resp) = net
|
let Ok(resp) = con
|
||||||
.request(Login {
|
.request(Login {
|
||||||
username: account.username.clone(),
|
username: account.username.clone(),
|
||||||
password: password.clone(),
|
password: password.clone(),
|
||||||
@@ -79,7 +80,7 @@ pub fn start(rsc: &mut Rsc, data: &ClientData) -> WeakWidget {
|
|||||||
else {
|
else {
|
||||||
return fail("failed to create account");
|
return fail("failed to create account");
|
||||||
};
|
};
|
||||||
let id = match resp {
|
let user_id = match resp {
|
||||||
LoginResp::Ok { id } => id,
|
LoginResp::Ok { id } => id,
|
||||||
LoginResp::UnknownUsername => {
|
LoginResp::UnknownUsername => {
|
||||||
return fail("unknown username");
|
return fail("unknown username");
|
||||||
@@ -88,8 +89,9 @@ pub fn start(rsc: &mut Rsc, data: &ClientData) -> WeakWidget {
|
|||||||
return fail("invalid password");
|
return fail("invalid password");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let session = Session { con, user_id };
|
||||||
ctx.update(move |ctx, rsc| {
|
ctx.update(move |ctx, rsc| {
|
||||||
main_view(rsc).set_ptr(ctx.main_ui, rsc);
|
main_view(rsc, session).set_ptr(ctx.main_ui, rsc);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -148,7 +150,7 @@ pub fn create_account(rsc: &mut Rsc) -> WeakWidget {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
keyring::use_native_store(true).unwrap();
|
keyring::use_native_store(true).unwrap();
|
||||||
let net = match NetHandle::connect(
|
let con = match NetHandle::connect(
|
||||||
async |msg| {
|
async |msg| {
|
||||||
println!("msg recv :joy:");
|
println!("msg recv :joy:");
|
||||||
},
|
},
|
||||||
@@ -165,7 +167,7 @@ pub fn create_account(rsc: &mut Rsc) -> WeakWidget {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let Ok(resp) = net
|
let Ok(resp) = con
|
||||||
.request(CreateAccount {
|
.request(CreateAccount {
|
||||||
username: username.clone(),
|
username: username.clone(),
|
||||||
password: password.clone(),
|
password: password.clone(),
|
||||||
@@ -175,7 +177,7 @@ pub fn create_account(rsc: &mut Rsc) -> WeakWidget {
|
|||||||
else {
|
else {
|
||||||
return fail("failed to create account");
|
return fail("failed to create account");
|
||||||
};
|
};
|
||||||
let id = match resp {
|
let user_id = match resp {
|
||||||
CreateAccountResp::Ok { id } => id,
|
CreateAccountResp::Ok { id } => id,
|
||||||
CreateAccountResp::UsernameExists => {
|
CreateAccountResp::UsernameExists => {
|
||||||
return fail("username already exists");
|
return fail("username already exists");
|
||||||
@@ -184,8 +186,9 @@ pub fn create_account(rsc: &mut Rsc) -> WeakWidget {
|
|||||||
return fail("invalid account token");
|
return fail("invalid account token");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let session = Session { con, user_id };
|
||||||
ctx.update(move |ctx, rsc| {
|
ctx.update(move |ctx, rsc| {
|
||||||
main_view(rsc).set_ptr(ctx.main_ui, rsc);
|
main_view(rsc, session).set_ptr(ctx.main_ui, rsc);
|
||||||
ctx.data.create_account(
|
ctx.data.create_account(
|
||||||
ServerInfo { cert_hex },
|
ServerInfo { cert_hex },
|
||||||
AccountInfo { url, username },
|
AccountInfo { url, username },
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
use crate::Rsc;
|
use crate::{Rsc, session::Session};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@@ -9,24 +9,25 @@ pub const SIZE: u32 = 20;
|
|||||||
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
|
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
pub enum MainView {
|
pub enum MainView {
|
||||||
Channel,
|
Channel,
|
||||||
|
Friends,
|
||||||
Server,
|
Server,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main_view(rsc: &mut Rsc) -> WeakWidget {
|
pub fn main_view(rsc: &mut Rsc, session: Session) -> WeakWidget {
|
||||||
let mut view = WidgetSelector::new(MainView::Channel, channel::view(rsc));
|
let mut view = WidgetSelector::new(MainView::Channel, channel::view(rsc));
|
||||||
view.set(MainView::Server, server::view(rsc));
|
view.set(MainView::Server, server::view(rsc, &session));
|
||||||
let view = view.add(rsc);
|
let view = view.add(rsc);
|
||||||
(top_bar(rsc, view), view).span(Dir::DOWN).add(rsc)
|
let [channel, friends, server] = tabs(
|
||||||
}
|
|
||||||
|
|
||||||
pub fn top_bar(rsc: &mut Rsc, view: WeakWidget<WidgetSelector<MainView>>) -> WeakWidget {
|
|
||||||
let [channel, server] = tabs(
|
|
||||||
rsc,
|
rsc,
|
||||||
view,
|
view,
|
||||||
[("channel", MainView::Channel), ("server", MainView::Server)],
|
[
|
||||||
|
("channel", MainView::Channel),
|
||||||
|
("friends", MainView::Friends),
|
||||||
|
("server", MainView::Server),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
rect(Color::BLACK.alpha(150))
|
let top_bar = rect(Color::BLACK.alpha(150))
|
||||||
.height(50)
|
.height(50)
|
||||||
.foreground((channel, server).span(Dir::RIGHT))
|
.foreground((channel, friends, server).span(Dir::RIGHT));
|
||||||
.add(rsc)
|
(top_bar, view).span(Dir::DOWN).add(rsc)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ pub fn hint_text(msg: impl Into<String>) -> TextBuilder<Rsc> {
|
|||||||
wtext(msg).size(20).color(Color::GRAY)
|
wtext(msg).size(20).color(Color::GRAY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn large_hint_text(msg: impl Into<String>) -> TextBuilder<Rsc> {
|
||||||
|
wtext(msg).size(30).color(Color::GRAY)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn field(default: &str, hint: &str, rsc: &mut Rsc) -> WeakWidget<TextEdit> {
|
pub fn field(default: &str, hint: &str, rsc: &mut Rsc) -> WeakWidget<TextEdit> {
|
||||||
wtext(default)
|
wtext(default)
|
||||||
.editable(EditMode::SingleLine)
|
.editable(EditMode::SingleLine)
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
use openworm::net::RequestUsers;
|
||||||
|
|
||||||
|
use crate::session::Session;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
|
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
@@ -6,9 +10,9 @@ enum View {
|
|||||||
User,
|
User,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view(rsc: &mut Rsc) -> StrongWidget {
|
pub fn view(rsc: &mut Rsc, session: &Session) -> StrongWidget {
|
||||||
let mut view = WidgetSelector::new(View::Info, info(rsc));
|
let mut view = WidgetSelector::new(View::Info, info(rsc));
|
||||||
view.set(View::User, users(rsc));
|
view.set(View::User, users(rsc, session));
|
||||||
let view = view.add(rsc);
|
let view = view.add(rsc);
|
||||||
let [info, server] = tabs(rsc, view, [("info", View::Info), ("users", View::User)]);
|
let [info, server] = tabs(rsc, view, [("info", View::Info), ("users", View::User)]);
|
||||||
|
|
||||||
@@ -23,6 +27,36 @@ fn info(rsc: &mut Rsc) -> StrongWidget {
|
|||||||
wtext("server info").center_text().add_strong(rsc)
|
wtext("server info").center_text().add_strong(rsc)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn users(rsc: &mut Rsc) -> StrongWidget {
|
fn users(rsc: &mut Rsc, session: &Session) -> StrongWidget {
|
||||||
wtext("users").center_text().add_strong(rsc)
|
let ptr = WidgetPtr::new(
|
||||||
|
large_hint_text("loading users...")
|
||||||
|
.center_text()
|
||||||
|
.width(rest(1))
|
||||||
|
.add_strong(rsc),
|
||||||
|
)
|
||||||
|
.add(rsc);
|
||||||
|
let con = session.con.clone();
|
||||||
|
rsc.events.register(ptr, Draw, move |_, rsc| {
|
||||||
|
let con = con.clone();
|
||||||
|
rsc.spawn_task(async move |mut ctx| {
|
||||||
|
let Ok(resp) = con.request(RequestUsers).await else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
ctx.update(move |_, rsc| {
|
||||||
|
let mut span = Span::empty(Dir::DOWN);
|
||||||
|
for user in resp.users {
|
||||||
|
let thing = (
|
||||||
|
wtext(user.id.to_string()).size(20),
|
||||||
|
wtext(user.username).size(20),
|
||||||
|
)
|
||||||
|
.span(Dir::RIGHT)
|
||||||
|
.gap(30)
|
||||||
|
.pad(15);
|
||||||
|
span.push(thing.add_strong(rsc));
|
||||||
|
}
|
||||||
|
span.set_ptr(ptr, rsc);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
ptr.upgrade(rsc)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ pub struct ServerPermsV0(u32);
|
|||||||
impl ServerPermsV0 {
|
impl ServerPermsV0 {
|
||||||
pub const NONE: Self = Self(0);
|
pub const NONE: Self = Self(0);
|
||||||
pub const ACCOUNT_TOKENS: Self = Self(1 << 0);
|
pub const ACCOUNT_TOKENS: Self = Self(1 << 0);
|
||||||
|
pub const ALL: Self = Self(u32::MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(bitcode::Encode, bitcode::Decode)]
|
#[derive(bitcode::Encode, bitcode::Decode)]
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ use net::{ClientSender, ConAccepter, listen};
|
|||||||
use openworm::{
|
use openworm::{
|
||||||
net::{
|
net::{
|
||||||
ClientMsg, ClientRequestMsg, CreateAccount, CreateAccountResp, DisconnectReason, LoadMsg,
|
ClientMsg, ClientRequestMsg, CreateAccount, CreateAccountResp, DisconnectReason, LoadMsg,
|
||||||
Login, LoginResp, RecvHandler, ServerError, ServerMsg, install_crypto_provider,
|
Login, LoginResp, RecvHandler, RequestUsersResp, ServerError, ServerMsg, ServerUser,
|
||||||
|
install_crypto_provider,
|
||||||
},
|
},
|
||||||
rsc::DataDir,
|
rsc::DataDir,
|
||||||
};
|
};
|
||||||
@@ -49,7 +50,7 @@ pub async fn run_server(port: u16) {
|
|||||||
db: db.clone(),
|
db: db.clone(),
|
||||||
};
|
};
|
||||||
if db.users.is_empty() {
|
if db.users.is_empty() {
|
||||||
let token = account_token(&db, ServerPerms::ACCOUNT_TOKENS);
|
let token = account_token(&db, ServerPerms::ALL);
|
||||||
println!("no users found, token for admin: {token}");
|
println!("no users found, token for admin: {token}");
|
||||||
}
|
}
|
||||||
let (endpoint, handle) = listen(port, &dir.path, handler);
|
let (endpoint, handle) = listen(port, &dir.path, handler);
|
||||||
@@ -231,6 +232,27 @@ impl RecvHandler<ClientRequestMsg> for ClientHandler {
|
|||||||
*self.state.write().await = ClientState::Authed(id);
|
*self.state.write().await = ClientState::Authed(id);
|
||||||
let _ = replier.send(LoginResp::Ok { id }).await;
|
let _ = replier.send(LoginResp::Ok { id }).await;
|
||||||
}
|
}
|
||||||
|
ClientMsg::RequestUsers(_) => {
|
||||||
|
if self
|
||||||
|
.db
|
||||||
|
.users
|
||||||
|
.get(&self.id)
|
||||||
|
.is_some_and(|u| !u.server_perms.contains(ServerPerms::ALL))
|
||||||
|
{
|
||||||
|
let _ = replier.send(ServerError::NoPermission).await;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let users: Vec<_> = self
|
||||||
|
.db
|
||||||
|
.users
|
||||||
|
.iter()
|
||||||
|
.map(|(id, u)| ServerUser {
|
||||||
|
id,
|
||||||
|
username: u.username,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let _ = replier.send(RequestUsersResp { users }).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ impl From<ClientMsg> for ClientMsgInst {
|
|||||||
ClientMsg::RequestMsgs => Self::RequestMsgsV0,
|
ClientMsg::RequestMsgs => Self::RequestMsgsV0,
|
||||||
ClientMsg::SendMsg(v) => Self::SendMsgV0(v),
|
ClientMsg::SendMsg(v) => Self::SendMsgV0(v),
|
||||||
ClientMsg::Login(v) => Self::LoginV0(v),
|
ClientMsg::Login(v) => Self::LoginV0(v),
|
||||||
|
ClientMsg::RequestUsers(v) => Self::RequestUsersV0(v),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -21,6 +22,7 @@ impl From<ClientMsgInst> for ClientMsg {
|
|||||||
ClientMsgInst::RequestMsgsV0 => Self::RequestMsgs,
|
ClientMsgInst::RequestMsgsV0 => Self::RequestMsgs,
|
||||||
ClientMsgInst::SendMsgV0(v) => Self::SendMsg(v),
|
ClientMsgInst::SendMsgV0(v) => Self::SendMsg(v),
|
||||||
ClientMsgInst::LoginV0(v) => Self::Login(v),
|
ClientMsgInst::LoginV0(v) => Self::Login(v),
|
||||||
|
ClientMsgInst::RequestUsersV0(v) => Self::RequestUsers(v),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,6 +35,7 @@ impl From<ServerMsg> for ServerMsgInst {
|
|||||||
ServerMsg::LoadMsgs(v) => Self::LoadMsgsV0(v),
|
ServerMsg::LoadMsgs(v) => Self::LoadMsgsV0(v),
|
||||||
ServerMsg::ServerError(v) => Self::ServerErrorV0(v),
|
ServerMsg::ServerError(v) => Self::ServerErrorV0(v),
|
||||||
ServerMsg::LoginResp(v) => Self::LoginRespV0(v),
|
ServerMsg::LoginResp(v) => Self::LoginRespV0(v),
|
||||||
|
ServerMsg::RequestUsersResp(v) => Self::RequestUsersRespV0(v),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,6 +48,7 @@ impl From<ServerMsgInst> for ServerMsg {
|
|||||||
ServerMsgInst::LoadMsgsV0(v) => Self::LoadMsgs(v),
|
ServerMsgInst::LoadMsgsV0(v) => Self::LoadMsgs(v),
|
||||||
ServerMsgInst::ServerErrorV0(v) => Self::ServerError(v),
|
ServerMsgInst::ServerErrorV0(v) => Self::ServerError(v),
|
||||||
ServerMsgInst::LoginRespV0(v) => Self::LoginResp(v),
|
ServerMsgInst::LoginRespV0(v) => Self::LoginResp(v),
|
||||||
|
ServerMsgInst::RequestUsersRespV0(v) => Self::RequestUsersResp(v),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ pub enum ClientMsgInst {
|
|||||||
LoginV0(LoginV0) = 1,
|
LoginV0(LoginV0) = 1,
|
||||||
RequestMsgsV0 = 2,
|
RequestMsgsV0 = 2,
|
||||||
SendMsgV0(SendMsgV0) = 3,
|
SendMsgV0(SendMsgV0) = 3,
|
||||||
|
RequestUsersV0(RequestUsersV0) = 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
@@ -17,6 +18,7 @@ pub enum ServerMsgInst {
|
|||||||
LoadMsgV0(LoadMsgV0) = 2,
|
LoadMsgV0(LoadMsgV0) = 2,
|
||||||
LoadMsgsV0(Vec<LoadMsgV0>) = 3,
|
LoadMsgsV0(Vec<LoadMsgV0>) = 3,
|
||||||
ServerErrorV0(ServerErrorV0) = 4,
|
ServerErrorV0(ServerErrorV0) = 4,
|
||||||
|
RequestUsersRespV0(RequestUsersRespV0) = 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type UserIdV0 = u64;
|
pub type UserIdV0 = u64;
|
||||||
@@ -48,6 +50,20 @@ pub enum LoginRespV0 {
|
|||||||
InvalidPassword,
|
InvalidPassword,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, bitcode::Encode, bitcode::Decode)]
|
||||||
|
pub struct RequestUsersV0;
|
||||||
|
|
||||||
|
#[derive(Debug, bitcode::Encode, bitcode::Decode)]
|
||||||
|
pub struct RequestUsersRespV0 {
|
||||||
|
pub users: Vec<ServerUserV0>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, bitcode::Encode, bitcode::Decode)]
|
||||||
|
pub struct ServerUserV0 {
|
||||||
|
pub id: UserIdV0,
|
||||||
|
pub username: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, bitcode::Encode, bitcode::Decode)]
|
#[derive(Debug, bitcode::Encode, bitcode::Decode)]
|
||||||
pub struct LoginKeyV0(Vec<u8>);
|
pub struct LoginKeyV0(Vec<u8>);
|
||||||
impl LoginKeyV0 {
|
impl LoginKeyV0 {
|
||||||
@@ -86,4 +102,5 @@ pub struct LoadMsgV0 {
|
|||||||
#[derive(Debug, bitcode::Encode, bitcode::Decode)]
|
#[derive(Debug, bitcode::Encode, bitcode::Decode)]
|
||||||
pub enum ServerErrorV0 {
|
pub enum ServerErrorV0 {
|
||||||
NotLoggedIn,
|
NotLoggedIn,
|
||||||
|
NoPermission,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
mod conversion;
|
mod conversion;
|
||||||
mod data;
|
pub mod data;
|
||||||
mod msg;
|
mod msg;
|
||||||
mod no_cert;
|
mod no_cert;
|
||||||
mod request;
|
mod request;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use super::data::*;
|
use super::data;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ClientMsg {
|
pub enum ClientMsg {
|
||||||
@@ -6,6 +6,7 @@ pub enum ClientMsg {
|
|||||||
Login(Login),
|
Login(Login),
|
||||||
RequestMsgs,
|
RequestMsgs,
|
||||||
SendMsg(SendMsg),
|
SendMsg(SendMsg),
|
||||||
|
RequestUsers(RequestUsers),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -15,17 +16,23 @@ pub enum ServerMsg {
|
|||||||
LoadMsg(LoadMsg),
|
LoadMsg(LoadMsg),
|
||||||
LoadMsgs(Vec<LoadMsg>),
|
LoadMsgs(Vec<LoadMsg>),
|
||||||
ServerError(ServerError),
|
ServerError(ServerError),
|
||||||
|
RequestUsersResp(RequestUsersResp),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type LoginKey = LoginKeyV0;
|
// TODO: a ton of this should really just be macros :sob:
|
||||||
pub type SendMsg = SendMsgV0;
|
|
||||||
pub type LoadMsg = LoadMsgV0;
|
pub use data::CreateAccountRespV0 as CreateAccountResp;
|
||||||
pub type ServerError = ServerErrorV0;
|
pub use data::CreateAccountV0 as CreateAccount;
|
||||||
pub type CreateAccount = CreateAccountV0;
|
pub use data::LoadMsgV0 as LoadMsg;
|
||||||
pub type CreateAccountResp = CreateAccountRespV0;
|
pub use data::LoginKeyV0 as LoginKey;
|
||||||
pub type Login = LoginV0;
|
pub use data::LoginRespV0 as LoginResp;
|
||||||
pub type LoginResp = LoginRespV0;
|
pub use data::LoginV0 as Login;
|
||||||
pub type UserId = UserIdV0;
|
pub use data::RequestUsersRespV0 as RequestUsersResp;
|
||||||
|
pub use data::RequestUsersV0 as RequestUsers;
|
||||||
|
pub use data::SendMsgV0 as SendMsg;
|
||||||
|
pub use data::ServerErrorV0 as ServerError;
|
||||||
|
pub use data::ServerUserV0 as ServerUser;
|
||||||
|
pub use data::UserIdV0 as UserId;
|
||||||
|
|
||||||
impl From<CreateAccount> for ClientMsg {
|
impl From<CreateAccount> for ClientMsg {
|
||||||
fn from(value: CreateAccount) -> Self {
|
fn from(value: CreateAccount) -> Self {
|
||||||
@@ -39,6 +46,12 @@ impl From<Login> for ClientMsg {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<RequestUsers> for ClientMsg {
|
||||||
|
fn from(value: RequestUsers) -> Self {
|
||||||
|
Self::RequestUsers(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<ServerError> for ServerMsg {
|
impl From<ServerError> for ServerMsg {
|
||||||
fn from(value: ServerError) -> Self {
|
fn from(value: ServerError) -> Self {
|
||||||
Self::ServerError(value)
|
Self::ServerError(value)
|
||||||
@@ -62,3 +75,9 @@ impl From<LoginResp> for ServerMsg {
|
|||||||
Self::LoginResp(value)
|
Self::LoginResp(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<RequestUsersResp> for ServerMsg {
|
||||||
|
fn from(value: RequestUsersResp) -> Self {
|
||||||
|
Self::RequestUsersResp(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
|
use super::*;
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
|
|
||||||
use crate::net::{ClientMsgInst, ServerMsgInst};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, bitcode::Encode, bitcode::Decode)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, bitcode::Encode, bitcode::Decode)]
|
||||||
pub struct RequestId(NonZeroU32);
|
pub struct RequestId(NonZeroU32);
|
||||||
|
|
||||||
@@ -30,3 +29,44 @@ pub struct ServerRespMsg {
|
|||||||
pub id: Option<RequestId>,
|
pub id: Option<RequestId>,
|
||||||
pub msg: ServerMsgInst,
|
pub msg: ServerMsgInst,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait RequestMsg: Into<ClientMsg> {
|
||||||
|
type Result;
|
||||||
|
fn result(msg: ServerMsg) -> Option<Self::Result>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RequestMsg for CreateAccount {
|
||||||
|
type Result = CreateAccountResp;
|
||||||
|
|
||||||
|
fn result(msg: ServerMsg) -> Option<Self::Result> {
|
||||||
|
if let ServerMsg::CreateAccountResp(res) = msg {
|
||||||
|
Some(res)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RequestMsg for Login {
|
||||||
|
type Result = LoginResp;
|
||||||
|
|
||||||
|
fn result(msg: ServerMsg) -> Option<Self::Result> {
|
||||||
|
if let ServerMsg::LoginResp(res) = msg {
|
||||||
|
Some(res)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RequestMsg for RequestUsers {
|
||||||
|
type Result = RequestUsersResp;
|
||||||
|
|
||||||
|
fn result(msg: ServerMsg) -> Option<Self::Result> {
|
||||||
|
if let ServerMsg::RequestUsersResp(res) = msg {
|
||||||
|
Some(res)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user