move already-logged-in check to register

This commit is contained in:
aljazerzen 2021-03-26 11:19:50 +01:00
parent 0ea102dc9c
commit 0c8448517e
2 changed files with 33 additions and 49 deletions

View File

@ -43,19 +43,6 @@ impl PendingLogin {
impl Component for PendingLogin { impl Component for PendingLogin {
type Storage = IdvStorage<Self>; type Storage = IdvStorage<Self>;
} }
#[derive(Debug)]
pub enum LoginError {
AlreadyLoggedIn(Uuid, String),
RegisterError(RegisterError),
}
impl From<RegisterError> for LoginError {
fn from(inner: RegisterError) -> LoginError {
LoginError::RegisterError(inner)
}
}
pub struct LoginProvider { pub struct LoginProvider {
runtime: Arc<Runtime>, runtime: Arc<Runtime>,
accounts: HashMap<Uuid, String>, accounts: HashMap<Uuid, String>,
@ -86,11 +73,7 @@ impl LoginProvider {
} }
} }
fn login(&mut self, uuid: Uuid, username: String) -> Result<(), LoginError> { fn login(&mut self, uuid: Uuid, username: String) -> Result<(), RegisterError> {
// make sure that the user is not logged in already
if self.accounts.contains_key(&uuid) {
return Err(LoginError::AlreadyLoggedIn(uuid, username));
}
info!(?username, "New User"); info!(?username, "New User");
self.accounts.insert(uuid, username); self.accounts.insert(uuid, username);
Ok(()) Ok(())
@ -133,7 +116,7 @@ impl LoginProvider {
admins: &HashSet<Uuid>, admins: &HashSet<Uuid>,
whitelist: &HashSet<Uuid>, whitelist: &HashSet<Uuid>,
banlist: &HashMap<Uuid, BanRecord>, banlist: &HashMap<Uuid, BanRecord>,
) -> Option<Result<(String, Uuid), LoginError>> { ) -> Option<Result<(String, Uuid), RegisterError>> {
match pending.pending_r.try_recv() { match pending.pending_r.try_recv() {
Ok(Err(e)) => Some(Err(e.into())), Ok(Err(e)) => Some(Err(e.into())),
Ok(Ok((username, uuid))) => { Ok(Ok((username, uuid))) => {

View File

@ -1,4 +1,9 @@
use crate::{EditableSettings, client::Client, login_provider::{LoginError, LoginProvider, PendingLogin}, metrics::PlayerMetrics}; use crate::{
client::Client,
login_provider::{LoginProvider, PendingLogin},
metrics::PlayerMetrics,
EditableSettings,
};
use common::{ use common::{
comp::{Admin, Player, Stats}, comp::{Admin, Player, Stats},
event::{EventBus, ServerEvent}, event::{EventBus, ServerEvent},
@ -125,43 +130,39 @@ impl<'a> System<'a> for Sys {
finished_pending.push(entity); finished_pending.push(entity);
trace!(?r, "pending login returned"); trace!(?r, "pending login returned");
match r { match r {
Err(LoginError::RegisterError(e)) => { Err(e) => {
client.send(ServerRegisterAnswer::Err(e))?; client.send(ServerRegisterAnswer::Err(e))?;
return Ok(()); return Ok(());
}
Err(LoginError::AlreadyLoggedIn(uuid, ref username)) => {
if let Some((old_entity, old_client, _)) =
(&entities, &clients, &players)
.join()
.find(|(_, _, old_player)| old_player.uuid() == uuid)
{
// Remove old client
server_event_bus
.emit_now(ServerEvent::ClientDisconnect(old_entity));
let _ = old_client.send(ServerGeneral::Disconnect(
DisconnectReason::Kicked(String::from(
"You have logged in from another location.",
)),
));
// We can't login the new client right now as the
// removal of the old client and player occurs later in
// the tick, so we instead setup the new login to be
// processed in the next tick
// Create "fake" successful pending auth and mark it to
// be inserted into pending_logins at the end of this
// run
retries.push((
entity,
PendingLogin::new_success(username.to_string(), uuid),
));
}
return Ok(());
}, },
Ok((username, uuid)) => (username, uuid), Ok((username, uuid)) => (username, uuid),
} }
}, },
}; };
// Check if user is already logged-in
if let Some((old_entity, old_client, _)) = (&entities, &clients, &players)
.join()
.find(|(_, _, old_player)| old_player.uuid() == uuid)
{
// Remove old client
server_event_bus.emit_now(ServerEvent::ClientDisconnect(old_entity));
let _ = old_client.send(ServerGeneral::Disconnect(DisconnectReason::Kicked(
String::from("You have logged in from another location."),
)));
// We can't login the new client right now as the
// removal of the old client and player occurs later in
// the tick, so we instead setup the new login to be
// processed in the next tick
// Create "fake" successful pending auth and mark it to
// be inserted into pending_logins at the end of this
// run
retries.push((
entity,
PendingLogin::new_success(username.to_string(), uuid),
));
return Ok(());
}
let player = Player::new(username, uuid); let player = Player::new(username, uuid);
let is_admin = editable_settings.admins.contains(&uuid); let is_admin = editable_settings.admins.contains(&uuid);