work
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
use crate::ClientEvent;
|
||||
use dashmap::DashMap;
|
||||
use openworm::net::{
|
||||
AccountCreated, ClientMsg, ClientMsgInst, ClientRequestMsg, CreateAccount, RecvHandler,
|
||||
RequestId, SERVER_NAME, ServerMsg, ServerRespMsg, SkipServerVerification, recv_uni, send_uni,
|
||||
ClientMsg, ClientRequestMsg, CreateAccount, CreateAccountResp, RecvHandler, RequestId,
|
||||
SERVER_NAME, ServerMsg, ServerRespMsg, SkipServerVerification, recv_uni, send_uni,
|
||||
};
|
||||
use quinn::{
|
||||
ClientConfig, Connection, Endpoint, IdleTimeout, TransportConfig,
|
||||
@@ -79,10 +79,10 @@ pub trait RequestMsg: Into<ClientMsg> {
|
||||
}
|
||||
|
||||
impl RequestMsg for CreateAccount {
|
||||
type Result = AccountCreated;
|
||||
type Result = CreateAccountResp;
|
||||
|
||||
fn result(msg: ServerMsg) -> Option<Self::Result> {
|
||||
if let ServerMsg::AccountCreated(res) = msg {
|
||||
if let ServerMsg::CreateAccount(res) = msg {
|
||||
Some(res)
|
||||
} else {
|
||||
None
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use openworm::net::CreateAccount;
|
||||
use openworm::net::{CreateAccount, CreateAccountResp};
|
||||
|
||||
use crate::net::{self, ConnectInfo};
|
||||
|
||||
@@ -81,6 +81,15 @@ pub fn create_account(rsc: &mut Rsc) -> WeakWidget {
|
||||
else {
|
||||
return fail("failed to create account");
|
||||
};
|
||||
let id = match resp {
|
||||
CreateAccountResp::Ok { id } => id,
|
||||
CreateAccountResp::UsernameExists => {
|
||||
return fail("username already exists");
|
||||
}
|
||||
CreateAccountResp::InvalidToken => {
|
||||
return fail("invalid account token");
|
||||
}
|
||||
};
|
||||
println!("account created!!!!");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,6 +11,7 @@ pub const DB_VERSION: u64 = 0;
|
||||
#[derive(Clone)]
|
||||
pub struct Db {
|
||||
db: Database,
|
||||
pub account_tokens: DbMap<String, ServerPerms>,
|
||||
pub msgs: DbMap<MsgId, Msg>,
|
||||
pub users: DbMap<UserId, User>,
|
||||
pub usernames: DbMap<String, UserId>,
|
||||
@@ -23,6 +24,7 @@ pub type ImageId = ImageIdV0;
|
||||
pub type User = UserV0;
|
||||
pub type Msg = MsgV0;
|
||||
pub type ChannelInfo = ChannelV0;
|
||||
pub type ServerPerms = ServerPermsV0;
|
||||
|
||||
impl Db {
|
||||
pub fn open(path: impl AsRef<Path>) -> Db {
|
||||
@@ -34,10 +36,11 @@ impl Db {
|
||||
panic!("non matching db version! (auto update in the future)");
|
||||
}
|
||||
} else {
|
||||
println!("no previous db found, creating new");
|
||||
println!("no previous db found, creating new version {DB_VERSION}");
|
||||
info.insert("version", &DB_VERSION);
|
||||
}
|
||||
Db {
|
||||
account_tokens: DbMap::open("account_token", &db),
|
||||
msgs: DbMap::open("msg", &db),
|
||||
users: DbMap::open("user", &db),
|
||||
usernames: DbMap::open("username", &db),
|
||||
|
||||
@@ -46,6 +46,14 @@ impl<K: Key<Output = K>, V: Encode + DecodeOwned> DbMap<K, V> {
|
||||
Some(bitcode::decode(&v).unwrap())
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.keyspace.approximate_len()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = (K, V)> {
|
||||
self.db.read_tx().iter(self)
|
||||
}
|
||||
@@ -129,6 +137,12 @@ impl WriteTx {
|
||||
self.0.get(&map.keyspace, k).unwrap().is_some()
|
||||
}
|
||||
|
||||
pub fn remove<K: Key<Output = K>, V: DecodeOwned>(&mut self, map: &DbMap<K, V>, k: K) -> Option<V> {
|
||||
let k = Slice::new(k.to_bytes().as_ref());
|
||||
let v = self.0.take(&map.keyspace, k).unwrap()?;
|
||||
Some(bitcode::decode(&v).unwrap())
|
||||
}
|
||||
|
||||
// TODO: K2 IS NOT A SAFE ABSTRACTION!! need to have KeyLike which has key assoc type
|
||||
pub fn insert<K: Key<Output = K>, K2: Key<Output = K> + ?Sized, V: Encode>(
|
||||
&mut self,
|
||||
|
||||
@@ -3,12 +3,20 @@ pub type MsgIdV0 = i128;
|
||||
pub type ChannelIdV0 = u64;
|
||||
pub type ImageIdV0 = u64;
|
||||
|
||||
#[derive(Clone, Copy, bitcode::Encode, bitcode::Decode)]
|
||||
pub struct ServerPermsV0(u32);
|
||||
impl ServerPermsV0 {
|
||||
pub const NONE: Self = Self(0);
|
||||
pub const ACCOUNT_TOKENS: Self = Self(1 << 0);
|
||||
}
|
||||
|
||||
#[derive(bitcode::Encode, bitcode::Decode)]
|
||||
pub struct UserV0 {
|
||||
pub username: String,
|
||||
pub password_hash: String,
|
||||
pub pfp: Option<ImageIdV0>,
|
||||
pub bio: String,
|
||||
pub server_perms: ServerPermsV0,
|
||||
}
|
||||
|
||||
#[derive(bitcode::Encode, bitcode::Decode)]
|
||||
@@ -21,3 +29,9 @@ pub struct ChannelV0 {
|
||||
pub name: String,
|
||||
pub desc: String,
|
||||
}
|
||||
|
||||
impl ServerPermsV0 {
|
||||
pub fn contains(&self, other: Self) -> bool {
|
||||
(self.0 & other.0) == other.0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
mod db;
|
||||
mod net;
|
||||
|
||||
use crate::db::{Db, Msg, User};
|
||||
use crate::db::{Db, Msg, ServerPerms, User};
|
||||
use clap::Parser;
|
||||
use net::{ClientSender, ConAccepter, listen};
|
||||
use openworm::{
|
||||
net::{
|
||||
AccountCreated, ClientMsg, ClientRequestMsg, CreateAccount, DisconnectReason, LoadMsg,
|
||||
ClientMsg, ClientRequestMsg, CreateAccount, CreateAccountResp, DisconnectReason, LoadMsg,
|
||||
RecvHandler, ServerError, ServerMsg, install_crypto_provider,
|
||||
},
|
||||
rsc::DataDir,
|
||||
};
|
||||
use rand::distr::{Alphanumeric, SampleString};
|
||||
use scrypt::{
|
||||
Scrypt,
|
||||
password_hash::{PasswordHasher, SaltString, rand_core::OsRng},
|
||||
@@ -48,6 +49,10 @@ pub async fn run_server(port: u16) {
|
||||
count: 0.into(),
|
||||
db: db.clone(),
|
||||
};
|
||||
if db.users.is_empty() {
|
||||
let token = account_token(&db, ServerPerms::ACCOUNT_TOKENS);
|
||||
println!("no users found, token for admin: {token}");
|
||||
}
|
||||
let (endpoint, handle) = listen(port, path, handler);
|
||||
let _ = ctrl_c().await;
|
||||
println!("stopping server");
|
||||
@@ -57,6 +62,12 @@ pub async fn run_server(port: u16) {
|
||||
endpoint.wait_idle().await;
|
||||
}
|
||||
|
||||
pub fn account_token(db: &Db, perms: ServerPerms) -> String {
|
||||
let token = Alphanumeric.sample_string(&mut rand::rng(), 16);
|
||||
db.account_tokens.insert(&token, &perms);
|
||||
token
|
||||
}
|
||||
|
||||
type ClientId = u64;
|
||||
|
||||
struct ServerListener {
|
||||
@@ -94,9 +105,7 @@ struct ClientHandler {
|
||||
}
|
||||
|
||||
impl RecvHandler<ClientRequestMsg> for ClientHandler {
|
||||
async fn connect(&self) -> () {
|
||||
println!("connected: {:?}", self.send.remote().ip());
|
||||
}
|
||||
async fn connect(&self) -> () {}
|
||||
async fn msg(&self, req: ClientRequestMsg) {
|
||||
let msg = ClientMsg::from(req.msg);
|
||||
let replier = self.send.replier(req.id);
|
||||
@@ -173,8 +182,13 @@ impl RecvHandler<ClientRequestMsg> for ClientHandler {
|
||||
let mut id;
|
||||
loop {
|
||||
let mut tx = self.db.write_tx();
|
||||
let Some(perms) = tx.remove(&self.db.account_tokens, token.to_string()) else {
|
||||
let _ = replier.send(CreateAccountResp::InvalidToken).await;
|
||||
println!("invalid token: {:?}", self.send.remote());
|
||||
return;
|
||||
};
|
||||
if tx.has_key(&self.db.usernames, username.clone()) {
|
||||
let _ = replier.send(ServerError::UsernameTaken).await;
|
||||
let _ = replier.send(CreateAccountResp::UsernameExists).await;
|
||||
return;
|
||||
}
|
||||
id = rand::random();
|
||||
@@ -189,6 +203,7 @@ impl RecvHandler<ClientRequestMsg> for ClientHandler {
|
||||
password_hash: hash.clone(),
|
||||
bio: String::new(),
|
||||
pfp: None,
|
||||
server_perms: perms,
|
||||
},
|
||||
);
|
||||
tx.insert(&self.db.usernames, username, &id);
|
||||
@@ -198,7 +213,7 @@ impl RecvHandler<ClientRequestMsg> for ClientHandler {
|
||||
}
|
||||
println!("account created: \"{username}\"");
|
||||
*self.state.write().await = ClientState::Authed(id);
|
||||
let _ = replier.send(AccountCreated {}).await;
|
||||
let _ = replier.send(CreateAccountResp::Ok { id }).await;
|
||||
} // ClientMsgType::Login { username, password } => {
|
||||
// let Some(id) = self.db.usernames.get(&username) else {
|
||||
// let _ = self.send.send(ServerError::UnknownUsername).await;
|
||||
@@ -221,7 +236,6 @@ impl RecvHandler<ClientRequestMsg> for ClientHandler {
|
||||
}
|
||||
|
||||
async fn disconnect(&self, reason: DisconnectReason) -> () {
|
||||
println!("disconnected: {:?}", self.send.remote().ip());
|
||||
match reason {
|
||||
DisconnectReason::Closed | DisconnectReason::Timeout => (),
|
||||
DisconnectReason::Other(e) => println!("connection issue: {e}"),
|
||||
|
||||
@@ -26,7 +26,7 @@ impl From<ClientMsgInst> for ClientMsg {
|
||||
impl From<ServerMsg> for ServerMsgInst {
|
||||
fn from(value: ServerMsg) -> Self {
|
||||
match value {
|
||||
ServerMsg::AccountCreated(v) => Self::AccountCreatedV0(v),
|
||||
ServerMsg::CreateAccount(v) => Self::CreateAccountV0(v),
|
||||
ServerMsg::LoadMsg(v) => Self::LoadMsgV0(v),
|
||||
ServerMsg::LoadMsgs(v) => Self::LoadMsgsV0(v),
|
||||
ServerMsg::ServerError(v) => Self::ServerErrorV0(v),
|
||||
@@ -37,7 +37,7 @@ impl From<ServerMsg> for ServerMsgInst {
|
||||
impl From<ServerMsgInst> for ServerMsg {
|
||||
fn from(value: ServerMsgInst) -> Self {
|
||||
match value {
|
||||
ServerMsgInst::AccountCreatedV0(v) => Self::AccountCreated(v),
|
||||
ServerMsgInst::CreateAccountV0(v) => Self::CreateAccount(v),
|
||||
ServerMsgInst::LoadMsgV0(v) => Self::LoadMsg(v),
|
||||
ServerMsgInst::LoadMsgsV0(v) => Self::LoadMsgs(v),
|
||||
ServerMsgInst::ServerErrorV0(v) => Self::ServerError(v),
|
||||
|
||||
@@ -11,7 +11,7 @@ pub enum ClientMsgInst {
|
||||
#[repr(u32)]
|
||||
#[derive(Debug, bitcode::Encode, bitcode::Decode)]
|
||||
pub enum ServerMsgInst {
|
||||
AccountCreatedV0(AccountCreatedV0) = 0,
|
||||
CreateAccountV0(CreateAccountRespV0) = 0,
|
||||
LoadMsgV0(LoadMsgV0) = 1,
|
||||
LoadMsgsV0(Vec<LoadMsgV0>) = 2,
|
||||
ServerErrorV0(ServerErrorV0) = 3,
|
||||
@@ -28,7 +28,11 @@ pub struct CreateAccountV0 {
|
||||
}
|
||||
|
||||
#[derive(Debug, bitcode::Encode, bitcode::Decode)]
|
||||
pub struct AccountCreatedV0 {}
|
||||
pub enum CreateAccountRespV0 {
|
||||
Ok { id: UserIdV0 },
|
||||
UsernameExists,
|
||||
InvalidToken,
|
||||
}
|
||||
|
||||
#[derive(Debug, bitcode::Encode, bitcode::Decode)]
|
||||
pub struct LoginKeyV0(Vec<u8>);
|
||||
@@ -64,7 +68,4 @@ pub struct LoadMsgV0 {
|
||||
#[derive(Debug, bitcode::Encode, bitcode::Decode)]
|
||||
pub enum ServerErrorV0 {
|
||||
NotLoggedIn,
|
||||
UnknownUsername,
|
||||
InvalidPassword,
|
||||
UsernameTaken,
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ pub enum ClientMsg {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ServerMsg {
|
||||
AccountCreated(AccountCreated),
|
||||
CreateAccount(CreateAccountResp),
|
||||
LoadMsg(LoadMsg),
|
||||
LoadMsgs(Vec<LoadMsg>),
|
||||
ServerError(ServerError),
|
||||
@@ -20,7 +20,7 @@ pub type SendMsg = SendMsgV0;
|
||||
pub type LoadMsg = LoadMsgV0;
|
||||
pub type ServerError = ServerErrorV0;
|
||||
pub type CreateAccount = CreateAccountV0;
|
||||
pub type AccountCreated = AccountCreatedV0;
|
||||
pub type CreateAccountResp = CreateAccountRespV0;
|
||||
pub type UserId = UserIdV0;
|
||||
|
||||
impl From<CreateAccount> for ClientMsg {
|
||||
@@ -41,8 +41,8 @@ impl From<LoadMsg> for ServerMsg {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AccountCreated> for ServerMsg {
|
||||
fn from(value: AccountCreated) -> Self {
|
||||
Self::AccountCreated(value)
|
||||
impl From<CreateAccountResp> for ServerMsg {
|
||||
fn from(value: CreateAccountResp) -> Self {
|
||||
Self::CreateAccount(value)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user