mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
fix #660; Admins should join even if they aren't on whitelist
This commit is contained in:
parent
c903e27160
commit
f7a3a622e5
@ -1,6 +1,6 @@
|
||||
use super::Event;
|
||||
use crate::{
|
||||
auth_provider::AuthProvider, client::Client, persistence, state_ext::StateExt, Server,
|
||||
client::Client, login_provider::LoginProvider, persistence, state_ext::StateExt, Server,
|
||||
};
|
||||
use common::{
|
||||
comp,
|
||||
@ -68,11 +68,11 @@ pub fn handle_client_disconnect(server: &mut Server, entity: EcsEntity) -> Event
|
||||
state.notify_registered_clients(ServerMsg::PlayerListUpdate(PlayerListUpdate::Remove(*uid)))
|
||||
}
|
||||
|
||||
// Make sure to remove the player from the logged in list. (See AuthProvider)
|
||||
// Make sure to remove the player from the logged in list. (See LoginProvider)
|
||||
// And send a disconnected message
|
||||
if let Some(player) = state.ecs().read_storage::<Player>().get(entity) {
|
||||
let mut accounts = state.ecs().write_resource::<AuthProvider>();
|
||||
accounts.logout(player.uuid());
|
||||
let mut login_provider = state.ecs().write_resource::<LoginProvider>();
|
||||
login_provider.logout(player.uuid());
|
||||
|
||||
let msg = comp::ChatType::Offline.server_msg(format!("[{}] went offline.", &player.alias));
|
||||
state.notify_registered_clients(msg);
|
||||
|
@ -3,13 +3,13 @@
|
||||
#![feature(drain_filter, option_zip)]
|
||||
|
||||
pub mod alias_validator;
|
||||
pub mod auth_provider;
|
||||
pub mod chunk_generator;
|
||||
pub mod client;
|
||||
pub mod cmd;
|
||||
pub mod error;
|
||||
pub mod events;
|
||||
pub mod input;
|
||||
pub mod login_provider;
|
||||
pub mod metrics;
|
||||
pub mod persistence;
|
||||
pub mod settings;
|
||||
@ -22,10 +22,10 @@ pub use crate::{error::Error, events::Event, input::Input, settings::ServerSetti
|
||||
|
||||
use crate::{
|
||||
alias_validator::AliasValidator,
|
||||
auth_provider::AuthProvider,
|
||||
chunk_generator::ChunkGenerator,
|
||||
client::{Client, RegionSubscription},
|
||||
cmd::ChatCommandExt,
|
||||
login_provider::LoginProvider,
|
||||
state_ext::StateExt,
|
||||
sys::sentinel::{DeletedEntities, TrackedComps},
|
||||
};
|
||||
@ -99,10 +99,9 @@ impl Server {
|
||||
let mut state = State::default();
|
||||
state.ecs_mut().insert(settings.clone());
|
||||
state.ecs_mut().insert(EventBus::<ServerEvent>::default());
|
||||
state.ecs_mut().insert(AuthProvider::new(
|
||||
settings.auth_server_address.clone(),
|
||||
settings.whitelist.clone(),
|
||||
));
|
||||
state
|
||||
.ecs_mut()
|
||||
.insert(LoginProvider::new(settings.auth_server_address.clone()));
|
||||
state.ecs_mut().insert(Tick(0));
|
||||
state.ecs_mut().insert(ChunkGenerator::new());
|
||||
state
|
||||
|
@ -15,33 +15,64 @@ fn derive_uuid(username: &str) -> Uuid {
|
||||
Uuid::from_slice(&state.to_be_bytes()).unwrap()
|
||||
}
|
||||
|
||||
pub struct AuthProvider {
|
||||
pub struct LoginProvider {
|
||||
accounts: HashMap<Uuid, String>,
|
||||
auth_server: Option<AuthClient>,
|
||||
whitelist: Vec<String>,
|
||||
}
|
||||
|
||||
impl AuthProvider {
|
||||
pub fn new(auth_addr: Option<String>, whitelist: Vec<String>) -> Self {
|
||||
impl LoginProvider {
|
||||
pub fn new(auth_addr: Option<String>) -> Self {
|
||||
let auth_server = match auth_addr {
|
||||
Some(addr) => Some(AuthClient::new(addr)),
|
||||
None => None,
|
||||
};
|
||||
|
||||
AuthProvider {
|
||||
Self {
|
||||
accounts: HashMap::new(),
|
||||
auth_server,
|
||||
whitelist,
|
||||
}
|
||||
}
|
||||
|
||||
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(RegisterError::AlreadyLoggedIn);
|
||||
}
|
||||
info!(?username, "New User");
|
||||
self.accounts.insert(uuid, username);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn logout(&mut self, uuid: Uuid) {
|
||||
if self.accounts.remove(&uuid).is_none() {
|
||||
error!(?uuid, "Attempted to logout user that is not logged in.");
|
||||
};
|
||||
}
|
||||
|
||||
pub fn query(&mut self, username_or_token: String) -> Result<(String, Uuid), RegisterError> {
|
||||
pub fn try_login(
|
||||
&mut self,
|
||||
username_or_token: &str,
|
||||
whitelist: &[String],
|
||||
) -> Result<(String, Uuid), RegisterError> {
|
||||
self
|
||||
// resolve user information
|
||||
.query(username_or_token)
|
||||
// if found, check name against whitelist or if user is admin
|
||||
.and_then(|(username, uuid)| {
|
||||
// user can only join if he is admin, the whitelist is empty (everyone can join)
|
||||
// or his name is in the whitelist
|
||||
if !whitelist.is_empty() && !whitelist.contains(&username) {
|
||||
return Err(RegisterError::NotOnWhitelist);
|
||||
}
|
||||
|
||||
// add the user to self.accounts
|
||||
self.login(uuid, username.clone())?;
|
||||
|
||||
Ok((username, uuid))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn query(&mut self, username_or_token: &str) -> Result<(String, Uuid), RegisterError> {
|
||||
// Based on whether auth server is provided or not we expect an username or
|
||||
// token
|
||||
match &self.auth_server {
|
||||
@ -49,36 +80,19 @@ impl AuthProvider {
|
||||
Some(srv) => {
|
||||
info!(?username_or_token, "Validating token");
|
||||
// Parse token
|
||||
let token = AuthToken::from_str(&username_or_token)
|
||||
let token = AuthToken::from_str(username_or_token)
|
||||
.map_err(|e| RegisterError::AuthError(e.to_string()))?;
|
||||
// Validate token
|
||||
let uuid = srv.validate(token)?;
|
||||
// Check if already logged in
|
||||
if self.accounts.contains_key(&uuid) {
|
||||
return Err(RegisterError::AlreadyLoggedIn);
|
||||
}
|
||||
let username = srv.uuid_to_username(uuid)?;
|
||||
// Check if player is in whitelist
|
||||
if self.whitelist.len() > 0 && !self.whitelist.contains(&username) {
|
||||
return Err(RegisterError::NotOnWhitelist);
|
||||
}
|
||||
|
||||
// Log in
|
||||
self.accounts.insert(uuid, username.clone());
|
||||
Ok((username, uuid))
|
||||
},
|
||||
// Username is expected
|
||||
None => {
|
||||
// Assume username was provided
|
||||
let username = username_or_token;
|
||||
let uuid = derive_uuid(&username);
|
||||
if !self.accounts.contains_key(&uuid) {
|
||||
info!(?username, "New User");
|
||||
self.accounts.insert(uuid, username.clone());
|
||||
Ok((username, uuid))
|
||||
} else {
|
||||
Err(RegisterError::AlreadyLoggedIn)
|
||||
}
|
||||
let uuid = derive_uuid(username);
|
||||
Ok((username.to_string(), uuid))
|
||||
},
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
use super::SysTimer;
|
||||
use crate::{
|
||||
alias_validator::AliasValidator, auth_provider::AuthProvider, client::Client,
|
||||
alias_validator::AliasValidator, client::Client, login_provider::LoginProvider,
|
||||
persistence::character::CharacterLoader, ServerSettings, CLIENT_TIMEOUT,
|
||||
};
|
||||
use common::{
|
||||
@ -45,7 +45,7 @@ impl Sys {
|
||||
force_updates: &ReadStorage<'_, ForceUpdate>,
|
||||
stats: &mut WriteStorage<'_, Stats>,
|
||||
chat_modes: &ReadStorage<'_, ChatMode>,
|
||||
accounts: &mut WriteExpect<'_, AuthProvider>,
|
||||
login_provider: &mut WriteExpect<'_, LoginProvider>,
|
||||
block_changes: &mut Write<'_, BlockChange>,
|
||||
admin_list: &ReadExpect<'_, AdminList>,
|
||||
admins: &mut WriteStorage<'_, Admin>,
|
||||
@ -86,13 +86,14 @@ impl Sys {
|
||||
view_distance,
|
||||
token_or_username,
|
||||
} => {
|
||||
let (username, uuid) = match accounts.query(token_or_username.clone()) {
|
||||
Err(err) => {
|
||||
client.error_state(RequestStateError::RegisterDenied(err));
|
||||
break Ok(());
|
||||
},
|
||||
Ok((username, uuid)) => (username, uuid),
|
||||
};
|
||||
let (username, uuid) =
|
||||
match login_provider.try_login(&token_or_username, &settings.whitelist) {
|
||||
Err(err) => {
|
||||
client.error_state(RequestStateError::RegisterDenied(err));
|
||||
break Ok(());
|
||||
},
|
||||
Ok((username, uuid)) => (username, uuid),
|
||||
};
|
||||
|
||||
let vd =
|
||||
view_distance.map(|vd| vd.min(settings.max_view_distance.unwrap_or(vd)));
|
||||
@ -411,7 +412,7 @@ impl<'a> System<'a> for Sys {
|
||||
ReadStorage<'a, ForceUpdate>,
|
||||
WriteStorage<'a, Stats>,
|
||||
ReadStorage<'a, ChatMode>,
|
||||
WriteExpect<'a, AuthProvider>,
|
||||
WriteExpect<'a, LoginProvider>,
|
||||
Write<'a, BlockChange>,
|
||||
ReadExpect<'a, AdminList>,
|
||||
WriteStorage<'a, Admin>,
|
||||
|
Loading…
Reference in New Issue
Block a user