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 super::Event;
|
||||||
use crate::{
|
use crate::{
|
||||||
auth_provider::AuthProvider, client::Client, persistence, state_ext::StateExt, Server,
|
client::Client, login_provider::LoginProvider, persistence, state_ext::StateExt, Server,
|
||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
comp,
|
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)))
|
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
|
// And send a disconnected message
|
||||||
if let Some(player) = state.ecs().read_storage::<Player>().get(entity) {
|
if let Some(player) = state.ecs().read_storage::<Player>().get(entity) {
|
||||||
let mut accounts = state.ecs().write_resource::<AuthProvider>();
|
let mut login_provider = state.ecs().write_resource::<LoginProvider>();
|
||||||
accounts.logout(player.uuid());
|
login_provider.logout(player.uuid());
|
||||||
|
|
||||||
let msg = comp::ChatType::Offline.server_msg(format!("[{}] went offline.", &player.alias));
|
let msg = comp::ChatType::Offline.server_msg(format!("[{}] went offline.", &player.alias));
|
||||||
state.notify_registered_clients(msg);
|
state.notify_registered_clients(msg);
|
||||||
|
@ -3,13 +3,13 @@
|
|||||||
#![feature(drain_filter, option_zip)]
|
#![feature(drain_filter, option_zip)]
|
||||||
|
|
||||||
pub mod alias_validator;
|
pub mod alias_validator;
|
||||||
pub mod auth_provider;
|
|
||||||
pub mod chunk_generator;
|
pub mod chunk_generator;
|
||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod cmd;
|
pub mod cmd;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod events;
|
pub mod events;
|
||||||
pub mod input;
|
pub mod input;
|
||||||
|
pub mod login_provider;
|
||||||
pub mod metrics;
|
pub mod metrics;
|
||||||
pub mod persistence;
|
pub mod persistence;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
@ -22,10 +22,10 @@ pub use crate::{error::Error, events::Event, input::Input, settings::ServerSetti
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
alias_validator::AliasValidator,
|
alias_validator::AliasValidator,
|
||||||
auth_provider::AuthProvider,
|
|
||||||
chunk_generator::ChunkGenerator,
|
chunk_generator::ChunkGenerator,
|
||||||
client::{Client, RegionSubscription},
|
client::{Client, RegionSubscription},
|
||||||
cmd::ChatCommandExt,
|
cmd::ChatCommandExt,
|
||||||
|
login_provider::LoginProvider,
|
||||||
state_ext::StateExt,
|
state_ext::StateExt,
|
||||||
sys::sentinel::{DeletedEntities, TrackedComps},
|
sys::sentinel::{DeletedEntities, TrackedComps},
|
||||||
};
|
};
|
||||||
@ -99,10 +99,9 @@ impl Server {
|
|||||||
let mut state = State::default();
|
let mut state = State::default();
|
||||||
state.ecs_mut().insert(settings.clone());
|
state.ecs_mut().insert(settings.clone());
|
||||||
state.ecs_mut().insert(EventBus::<ServerEvent>::default());
|
state.ecs_mut().insert(EventBus::<ServerEvent>::default());
|
||||||
state.ecs_mut().insert(AuthProvider::new(
|
state
|
||||||
settings.auth_server_address.clone(),
|
.ecs_mut()
|
||||||
settings.whitelist.clone(),
|
.insert(LoginProvider::new(settings.auth_server_address.clone()));
|
||||||
));
|
|
||||||
state.ecs_mut().insert(Tick(0));
|
state.ecs_mut().insert(Tick(0));
|
||||||
state.ecs_mut().insert(ChunkGenerator::new());
|
state.ecs_mut().insert(ChunkGenerator::new());
|
||||||
state
|
state
|
||||||
|
@ -15,33 +15,64 @@ fn derive_uuid(username: &str) -> Uuid {
|
|||||||
Uuid::from_slice(&state.to_be_bytes()).unwrap()
|
Uuid::from_slice(&state.to_be_bytes()).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AuthProvider {
|
pub struct LoginProvider {
|
||||||
accounts: HashMap<Uuid, String>,
|
accounts: HashMap<Uuid, String>,
|
||||||
auth_server: Option<AuthClient>,
|
auth_server: Option<AuthClient>,
|
||||||
whitelist: Vec<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AuthProvider {
|
impl LoginProvider {
|
||||||
pub fn new(auth_addr: Option<String>, whitelist: Vec<String>) -> Self {
|
pub fn new(auth_addr: Option<String>) -> Self {
|
||||||
let auth_server = match auth_addr {
|
let auth_server = match auth_addr {
|
||||||
Some(addr) => Some(AuthClient::new(addr)),
|
Some(addr) => Some(AuthClient::new(addr)),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
AuthProvider {
|
Self {
|
||||||
accounts: HashMap::new(),
|
accounts: HashMap::new(),
|
||||||
auth_server,
|
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) {
|
pub fn logout(&mut self, uuid: Uuid) {
|
||||||
if self.accounts.remove(&uuid).is_none() {
|
if self.accounts.remove(&uuid).is_none() {
|
||||||
error!(?uuid, "Attempted to logout user that is not logged in.");
|
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
|
// Based on whether auth server is provided or not we expect an username or
|
||||||
// token
|
// token
|
||||||
match &self.auth_server {
|
match &self.auth_server {
|
||||||
@ -49,36 +80,19 @@ impl AuthProvider {
|
|||||||
Some(srv) => {
|
Some(srv) => {
|
||||||
info!(?username_or_token, "Validating token");
|
info!(?username_or_token, "Validating token");
|
||||||
// Parse 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()))?;
|
.map_err(|e| RegisterError::AuthError(e.to_string()))?;
|
||||||
// Validate token
|
// Validate token
|
||||||
let uuid = srv.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)?;
|
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))
|
Ok((username, uuid))
|
||||||
},
|
},
|
||||||
// Username is expected
|
// Username is expected
|
||||||
None => {
|
None => {
|
||||||
// Assume username was provided
|
// Assume username was provided
|
||||||
let username = username_or_token;
|
let username = username_or_token;
|
||||||
let uuid = derive_uuid(&username);
|
let uuid = derive_uuid(username);
|
||||||
if !self.accounts.contains_key(&uuid) {
|
Ok((username.to_string(), uuid))
|
||||||
info!(?username, "New User");
|
|
||||||
self.accounts.insert(uuid, username.clone());
|
|
||||||
Ok((username, uuid))
|
|
||||||
} else {
|
|
||||||
Err(RegisterError::AlreadyLoggedIn)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
use super::SysTimer;
|
use super::SysTimer;
|
||||||
use crate::{
|
use crate::{
|
||||||
alias_validator::AliasValidator, auth_provider::AuthProvider, client::Client,
|
alias_validator::AliasValidator, client::Client, login_provider::LoginProvider,
|
||||||
persistence::character::CharacterLoader, ServerSettings, CLIENT_TIMEOUT,
|
persistence::character::CharacterLoader, ServerSettings, CLIENT_TIMEOUT,
|
||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
@ -45,7 +45,7 @@ impl Sys {
|
|||||||
force_updates: &ReadStorage<'_, ForceUpdate>,
|
force_updates: &ReadStorage<'_, ForceUpdate>,
|
||||||
stats: &mut WriteStorage<'_, Stats>,
|
stats: &mut WriteStorage<'_, Stats>,
|
||||||
chat_modes: &ReadStorage<'_, ChatMode>,
|
chat_modes: &ReadStorage<'_, ChatMode>,
|
||||||
accounts: &mut WriteExpect<'_, AuthProvider>,
|
login_provider: &mut WriteExpect<'_, LoginProvider>,
|
||||||
block_changes: &mut Write<'_, BlockChange>,
|
block_changes: &mut Write<'_, BlockChange>,
|
||||||
admin_list: &ReadExpect<'_, AdminList>,
|
admin_list: &ReadExpect<'_, AdminList>,
|
||||||
admins: &mut WriteStorage<'_, Admin>,
|
admins: &mut WriteStorage<'_, Admin>,
|
||||||
@ -86,7 +86,8 @@ impl Sys {
|
|||||||
view_distance,
|
view_distance,
|
||||||
token_or_username,
|
token_or_username,
|
||||||
} => {
|
} => {
|
||||||
let (username, uuid) = match accounts.query(token_or_username.clone()) {
|
let (username, uuid) =
|
||||||
|
match login_provider.try_login(&token_or_username, &settings.whitelist) {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
client.error_state(RequestStateError::RegisterDenied(err));
|
client.error_state(RequestStateError::RegisterDenied(err));
|
||||||
break Ok(());
|
break Ok(());
|
||||||
@ -411,7 +412,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
ReadStorage<'a, ForceUpdate>,
|
ReadStorage<'a, ForceUpdate>,
|
||||||
WriteStorage<'a, Stats>,
|
WriteStorage<'a, Stats>,
|
||||||
ReadStorage<'a, ChatMode>,
|
ReadStorage<'a, ChatMode>,
|
||||||
WriteExpect<'a, AuthProvider>,
|
WriteExpect<'a, LoginProvider>,
|
||||||
Write<'a, BlockChange>,
|
Write<'a, BlockChange>,
|
||||||
ReadExpect<'a, AdminList>,
|
ReadExpect<'a, AdminList>,
|
||||||
WriteStorage<'a, Admin>,
|
WriteStorage<'a, Admin>,
|
||||||
|
Loading…
Reference in New Issue
Block a user