Skip to content

Commit

Permalink
Automatic login on game start;
Browse files Browse the repository at this point in the history
Empty password support;
Pass login mode to profile window;
Cache pools only if assets were synced;
  • Loading branch information
makscee committed Jan 12, 2024
1 parent 29e0372 commit c81a9ec
Show file tree
Hide file tree
Showing 10 changed files with 223 additions and 75 deletions.
64 changes: 49 additions & 15 deletions server/src/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,30 @@ pub struct User {
#[unique]
pub name: String,
identities: Vec<Identity>,
pass_hash: String,
pass_hash: Option<String>,
online: bool,
last_login: Timestamp,
}

#[spacetimedb(reducer)]
fn register_empty(ctx: ReducerContext) -> Result<(), String> {
User::clear_identity(&ctx.sender);
let user = User {
id: 0,
identities: vec![ctx.sender],
name: format!("user#{}", User::iter().count()),
pass_hash: None,
online: false,
last_login: Timestamp::UNIX_EPOCH,
};
User::insert(user)?;
Ok(())
}

#[spacetimedb(reducer)]
fn register(ctx: ReducerContext, name: String, pass: String) -> Result<(), String> {
let name = User::validate_name(name)?;
let pass_hash = User::hash_pass(pass)?;
let pass_hash = Some(User::hash_pass(pass)?);
User::clear_identity(&ctx.sender);
User::insert(User {
id: 0,
Expand All @@ -37,9 +52,17 @@ fn login(ctx: ReducerContext, name: String, pass: String) -> Result<(), String>
let mut user = User::filter_by_name(&name)
.context("User not found")
.map_err(|e| e.to_string())?;
if user.pass_hash.is_none() {
return Err("No password set for user".to_owned());
}
if !user.check_pass(pass) {
Err("Wrong password".to_owned())
} else {
if let Ok(mut user) = User::find_by_identity(&ctx.sender) {
user.online = false;
user.remove_identity(&ctx.sender);
User::update_by_id(&user.id.clone(), user);
}
if !user.identities.contains(&ctx.sender) {
User::clear_identity(&ctx.sender);
user.identities.push(ctx.sender);
Expand All @@ -50,16 +73,19 @@ fn login(ctx: ReducerContext, name: String, pass: String) -> Result<(), String>
}

#[spacetimedb(reducer)]
pub fn login_by_identity(ctx: ReducerContext, name: String) -> Result<(), String> {
let user = User::filter_by_name(&name)
.context("User not found")
.map_err(|e| e.to_string())?;
if !user.identities.contains(&ctx.sender) {
Err("Identity not connected to user name".to_string())
} else {
user.login();
Ok(())
}
fn login_by_identity(ctx: ReducerContext) -> Result<(), String> {
let user = User::find_by_identity(&ctx.sender)?;
user.login();
Ok(())
}

#[spacetimedb(reducer)]
fn logout(ctx: ReducerContext) -> Result<(), String> {
let mut user = User::find_by_identity(&ctx.sender)?;
user.online = false;
user.remove_identity(&ctx.sender);
User::update_by_id(&user.id.clone(), user);
Ok(())
}

#[spacetimedb(reducer)]
Expand All @@ -79,7 +105,7 @@ fn set_password(ctx: ReducerContext, old_pass: String, new_pass: String) -> Resu
if !user.check_pass(old_pass) {
return Err("Old password did not match".to_owned());
}
let pass_hash = User::hash_pass(new_pass)?;
let pass_hash = Some(User::hash_pass(new_pass)?);
User::update_by_id(&user.id, User { pass_hash, ..user });
Ok(())
} else {
Expand Down Expand Up @@ -107,7 +133,11 @@ impl User {
}

fn check_pass(&self, pass: String) -> bool {
bcrypt::verify(pass, &self.pass_hash)
if let Some(hash) = &self.pass_hash {
bcrypt::verify(pass, hash)
} else {
true
}
}

fn hash_pass(pass: String) -> Result<String, String> {
Expand All @@ -129,8 +159,12 @@ impl User {

fn clear_identity(identity: &Identity) {
if let Ok(mut user) = User::find_by_identity(identity) {
user.identities.retain(|i| !i.eq(identity));
user.remove_identity(identity);
User::update_by_id(&user.id.clone(), user);
}
}

fn remove_identity(&mut self, identity: &Identity) {
self.identities.retain(|i| !i.eq(identity));
}
}
20 changes: 9 additions & 11 deletions src/module_bindings/login_by_identity_reducer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,34 @@ use spacetimedb_sdk::{
};

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct LoginByIdentityArgs {
pub name: String,
}
pub struct LoginByIdentityArgs {}

impl Reducer for LoginByIdentityArgs {
const REDUCER_NAME: &'static str = "login_by_identity";
}

#[allow(unused)]
pub fn login_by_identity(name: String) {
LoginByIdentityArgs { name }.invoke();
pub fn login_by_identity() {
LoginByIdentityArgs {}.invoke();
}

#[allow(unused)]
pub fn on_login_by_identity(
mut __callback: impl FnMut(&Identity, Option<Address>, &Status, &String) + Send + 'static,
mut __callback: impl FnMut(&Identity, Option<Address>, &Status) + Send + 'static,
) -> ReducerCallbackId<LoginByIdentityArgs> {
LoginByIdentityArgs::on_reducer(move |__identity, __addr, __status, __args| {
let LoginByIdentityArgs { name } = __args;
__callback(__identity, __addr, __status, name);
let LoginByIdentityArgs {} = __args;
__callback(__identity, __addr, __status);
})
}

#[allow(unused)]
pub fn once_on_login_by_identity(
__callback: impl FnOnce(&Identity, Option<Address>, &Status, &String) + Send + 'static,
__callback: impl FnOnce(&Identity, Option<Address>, &Status) + Send + 'static,
) -> ReducerCallbackId<LoginByIdentityArgs> {
LoginByIdentityArgs::once_on_reducer(move |__identity, __addr, __status, __args| {
let LoginByIdentityArgs { name } = __args;
__callback(__identity, __addr, __status, name);
let LoginByIdentityArgs {} = __args;
__callback(__identity, __addr, __status);
})
}

Expand Down
50 changes: 50 additions & 0 deletions src/module_bindings/logout_reducer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD.

#[allow(unused)]
use spacetimedb_sdk::{
anyhow::{anyhow, Result},
identity::Identity,
reducer::{Reducer, ReducerCallbackId, Status},
sats::{de::Deserialize, ser::Serialize},
spacetimedb_lib,
table::{TableIter, TableType, TableWithPrimaryKey},
Address,
};

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct LogoutArgs {}

impl Reducer for LogoutArgs {
const REDUCER_NAME: &'static str = "logout";
}

#[allow(unused)]
pub fn logout() {
LogoutArgs {}.invoke();
}

#[allow(unused)]
pub fn on_logout(
mut __callback: impl FnMut(&Identity, Option<Address>, &Status) + Send + 'static,
) -> ReducerCallbackId<LogoutArgs> {
LogoutArgs::on_reducer(move |__identity, __addr, __status, __args| {
let LogoutArgs {} = __args;
__callback(__identity, __addr, __status);
})
}

#[allow(unused)]
pub fn once_on_logout(
__callback: impl FnOnce(&Identity, Option<Address>, &Status) + Send + 'static,
) -> ReducerCallbackId<LogoutArgs> {
LogoutArgs::once_on_reducer(move |__identity, __addr, __status, __args| {
let LogoutArgs {} = __args;
__callback(__identity, __addr, __status);
})
}

#[allow(unused)]
pub fn remove_on_logout(id: ReducerCallbackId<LogoutArgs>) {
LogoutArgs::remove_on_reducer(id);
}
8 changes: 8 additions & 0 deletions src/module_bindings/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ pub mod global_tower;
pub mod house;
pub mod login_by_identity_reducer;
pub mod login_reducer;
pub mod logout_reducer;
pub mod register_empty_reducer;
pub mod register_reducer;
pub mod set_name_reducer;
pub mod set_password_reducer;
Expand Down Expand Up @@ -59,6 +61,8 @@ pub use global_tower::*;
pub use house::*;
pub use login_by_identity_reducer::*;
pub use login_reducer::*;
pub use logout_reducer::*;
pub use register_empty_reducer::*;
pub use register_reducer::*;
pub use set_name_reducer::*;
pub use set_password_reducer::*;
Expand All @@ -85,7 +89,9 @@ pub enum ReducerEvent {
GiveRight(give_right_reducer::GiveRightArgs),
Login(login_reducer::LoginArgs),
LoginByIdentity(login_by_identity_reducer::LoginByIdentityArgs),
Logout(logout_reducer::LogoutArgs),
Register(register_reducer::RegisterArgs),
RegisterEmpty(register_empty_reducer::RegisterEmptyArgs),
SetName(set_name_reducer::SetNameArgs),
SetPassword(set_password_reducer::SetPasswordArgs),
StartRun(start_run_reducer::StartRunArgs),
Expand Down Expand Up @@ -186,7 +192,9 @@ match &function_call.reducer[..] {
"give_right" => _reducer_callbacks.handle_event_of_type::<give_right_reducer::GiveRightArgs, ReducerEvent>(event, _state, ReducerEvent::GiveRight),
"login" => _reducer_callbacks.handle_event_of_type::<login_reducer::LoginArgs, ReducerEvent>(event, _state, ReducerEvent::Login),
"login_by_identity" => _reducer_callbacks.handle_event_of_type::<login_by_identity_reducer::LoginByIdentityArgs, ReducerEvent>(event, _state, ReducerEvent::LoginByIdentity),
"logout" => _reducer_callbacks.handle_event_of_type::<logout_reducer::LogoutArgs, ReducerEvent>(event, _state, ReducerEvent::Logout),
"register" => _reducer_callbacks.handle_event_of_type::<register_reducer::RegisterArgs, ReducerEvent>(event, _state, ReducerEvent::Register),
"register_empty" => _reducer_callbacks.handle_event_of_type::<register_empty_reducer::RegisterEmptyArgs, ReducerEvent>(event, _state, ReducerEvent::RegisterEmpty),
"set_name" => _reducer_callbacks.handle_event_of_type::<set_name_reducer::SetNameArgs, ReducerEvent>(event, _state, ReducerEvent::SetName),
"set_password" => _reducer_callbacks.handle_event_of_type::<set_password_reducer::SetPasswordArgs, ReducerEvent>(event, _state, ReducerEvent::SetPassword),
"start_run" => _reducer_callbacks.handle_event_of_type::<start_run_reducer::StartRunArgs, ReducerEvent>(event, _state, ReducerEvent::StartRun),
Expand Down
50 changes: 50 additions & 0 deletions src/module_bindings/register_empty_reducer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD.

#[allow(unused)]
use spacetimedb_sdk::{
anyhow::{anyhow, Result},
identity::Identity,
reducer::{Reducer, ReducerCallbackId, Status},
sats::{de::Deserialize, ser::Serialize},
spacetimedb_lib,
table::{TableIter, TableType, TableWithPrimaryKey},
Address,
};

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct RegisterEmptyArgs {}

impl Reducer for RegisterEmptyArgs {
const REDUCER_NAME: &'static str = "register_empty";
}

#[allow(unused)]
pub fn register_empty() {
RegisterEmptyArgs {}.invoke();
}

#[allow(unused)]
pub fn on_register_empty(
mut __callback: impl FnMut(&Identity, Option<Address>, &Status) + Send + 'static,
) -> ReducerCallbackId<RegisterEmptyArgs> {
RegisterEmptyArgs::on_reducer(move |__identity, __addr, __status, __args| {
let RegisterEmptyArgs {} = __args;
__callback(__identity, __addr, __status);
})
}

#[allow(unused)]
pub fn once_on_register_empty(
__callback: impl FnOnce(&Identity, Option<Address>, &Status) + Send + 'static,
) -> ReducerCallbackId<RegisterEmptyArgs> {
RegisterEmptyArgs::once_on_reducer(move |__identity, __addr, __status, __args| {
let RegisterEmptyArgs {} = __args;
__callback(__identity, __addr, __status);
})
}

#[allow(unused)]
pub fn remove_on_register_empty(id: ReducerCallbackId<RegisterEmptyArgs>) {
RegisterEmptyArgs::remove_on_reducer(id);
}
4 changes: 2 additions & 2 deletions src/module_bindings/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub struct User {
pub id: u64,
pub name: String,
pub identities: Vec<Identity>,
pub pass_hash: String,
pub pass_hash: Option<String>,
pub online: bool,
pub last_login: u64,
}
Expand Down Expand Up @@ -48,7 +48,7 @@ impl User {
Self::filter(|row| row.identities == identities)
}
#[allow(unused)]
pub fn filter_by_pass_hash(pass_hash: String) -> TableIter<Self> {
pub fn filter_by_pass_hash(pass_hash: Option<String>) -> TableIter<Self> {
Self::filter(|row| row.pass_hash == pass_hash)
}
#[allow(unused)]
Expand Down
Loading

0 comments on commit c81a9ec

Please sign in to comment.