mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add warning prompt for untrusted auth servers, move some auth code into
This commit is contained in:
parent
403deecc6d
commit
8ef1251dc2
31
Cargo.lock
generated
31
Cargo.lock
generated
@ -144,6 +144,16 @@ dependencies = [
|
||||
"uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "auth-common"
|
||||
version = "0.1.0"
|
||||
source = "git+https://gitlab.com/veloren/auth.git?rev=f3445fc1dca55f09205bdbe8ad038db60fea442b#f3445fc1dca55f09205bdbe8ad038db60fea442b"
|
||||
dependencies = [
|
||||
"rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "authc"
|
||||
version = "1.0.0"
|
||||
@ -157,6 +167,19 @@ dependencies = [
|
||||
"uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "authc"
|
||||
version = "1.0.0"
|
||||
source = "git+https://gitlab.com/veloren/auth.git?rev=f3445fc1dca55f09205bdbe8ad038db60fea442b#f3445fc1dca55f09205bdbe8ad038db60fea442b"
|
||||
dependencies = [
|
||||
"auth-common 0.1.0 (git+https://gitlab.com/veloren/auth.git?rev=f3445fc1dca55f09205bdbe8ad038db60fea442b)",
|
||||
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "0.1.7"
|
||||
@ -3863,6 +3886,7 @@ dependencies = [
|
||||
name = "veloren-client"
|
||||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"authc 1.0.0 (git+https://gitlab.com/veloren/auth.git?rev=f3445fc1dca55f09205bdbe8ad038db60fea442b)",
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -3878,7 +3902,7 @@ dependencies = [
|
||||
name = "veloren-common"
|
||||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"authc 1.0.0 (git+https://gitlab.com/veloren/auth.git?rev=7c1abde83f0ea7d83b0e7c655fac82eb9bb3d7ad)",
|
||||
"authc 1.0.0 (git+https://gitlab.com/veloren/auth.git?rev=f3445fc1dca55f09205bdbe8ad038db60fea442b)",
|
||||
"bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -3910,7 +3934,7 @@ dependencies = [
|
||||
name = "veloren-server"
|
||||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"authc 1.0.0 (git+https://gitlab.com/veloren/auth.git?rev=7c1abde83f0ea7d83b0e7c655fac82eb9bb3d7ad)",
|
||||
"authc 1.0.0 (git+https://gitlab.com/veloren/auth.git?rev=f3445fc1dca55f09205bdbe8ad038db60fea442b)",
|
||||
"chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -3978,7 +4002,6 @@ dependencies = [
|
||||
"rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rodio 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"specs 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -4450,7 +4473,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum atom 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3c86699c3f02778ec07158376991c8f783dd1f2f95c579ffaf0738dc984b2fe2"
|
||||
"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
|
||||
"checksum auth-common 0.1.0 (git+https://gitlab.com/veloren/auth.git?rev=7c1abde83f0ea7d83b0e7c655fac82eb9bb3d7ad)" = "<none>"
|
||||
"checksum auth-common 0.1.0 (git+https://gitlab.com/veloren/auth.git?rev=f3445fc1dca55f09205bdbe8ad038db60fea442b)" = "<none>"
|
||||
"checksum authc 1.0.0 (git+https://gitlab.com/veloren/auth.git?rev=7c1abde83f0ea7d83b0e7c655fac82eb9bb3d7ad)" = "<none>"
|
||||
"checksum authc 1.0.0 (git+https://gitlab.com/veloren/auth.git?rev=f3445fc1dca55f09205bdbe8ad038db60fea442b)" = "<none>"
|
||||
"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
|
||||
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
||||
"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea"
|
||||
|
@ -15,3 +15,4 @@ log = "0.4.8"
|
||||
specs = "0.15.1"
|
||||
vek = { version = "0.9.9", features = ["serde"] }
|
||||
hashbrown = { version = "0.6.2", features = ["rayon", "serde", "nightly"] }
|
||||
authc = { git = "https://gitlab.com/veloren/auth.git", rev = "f3445fc1dca55f09205bdbe8ad038db60fea442b" }
|
||||
|
@ -1,3 +1,4 @@
|
||||
use authc::AuthClientError;
|
||||
use common::net::PostError;
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -9,10 +10,16 @@ pub enum Error {
|
||||
TooManyPlayers,
|
||||
InvalidAuth,
|
||||
AlreadyLoggedIn,
|
||||
AuthClientError(AuthClientError),
|
||||
AuthServerNotTrusted,
|
||||
//TODO: InvalidAlias,
|
||||
Other(String),
|
||||
}
|
||||
|
||||
impl From<PostError> for Error {
|
||||
fn from(err: PostError) -> Self { Error::Network(err) }
|
||||
fn from(err: PostError) -> Self { Self::Network(err) }
|
||||
}
|
||||
|
||||
impl From<AuthClientError> for Error {
|
||||
fn from(err: AuthClientError) -> Self { Self::AuthClientError(err) }
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ impl Client {
|
||||
);
|
||||
}
|
||||
|
||||
log::error!("Auth Server: {:?}", server_info.auth_provider);
|
||||
log::info!("Auth Server: {:?}", server_info.auth_provider);
|
||||
|
||||
// Initialize `State`
|
||||
let mut state = State::default();
|
||||
@ -174,10 +174,33 @@ impl Client {
|
||||
}
|
||||
|
||||
/// Request a state transition to `ClientState::Registered`.
|
||||
pub fn register(&mut self, player: comp::Player, password: String) -> Result<(), Error> {
|
||||
self.postbox
|
||||
.send_message(ClientMsg::Register { player, password });
|
||||
pub fn register(
|
||||
&mut self,
|
||||
player: comp::Player,
|
||||
password: String,
|
||||
mut auth_trusted: impl FnMut(&str) -> bool,
|
||||
) -> Result<(), Error> {
|
||||
// Authentication
|
||||
let token_or_username = match &self.server_info.auth_provider {
|
||||
Some(addr) => {
|
||||
// Query whether this is a trusted auth server
|
||||
if auth_trusted(&addr) {
|
||||
authc::AuthClient::new(addr)
|
||||
.sign_in(&player.alias, &password)?
|
||||
.serialize()
|
||||
} else {
|
||||
return Err(Error::AuthServerNotTrusted);
|
||||
}
|
||||
},
|
||||
None => player.alias.clone(),
|
||||
};
|
||||
|
||||
self.postbox.send_message(ClientMsg::Register {
|
||||
player,
|
||||
token_or_username,
|
||||
});
|
||||
self.client_state = ClientState::Pending;
|
||||
|
||||
loop {
|
||||
match self.postbox.next_message() {
|
||||
Some(ServerMsg::StateAnswer(Err((RequestStateError::Denied, _)))) => {
|
||||
|
@ -33,7 +33,7 @@ crossbeam = "=0.7.2"
|
||||
notify = "5.0.0-pre.1"
|
||||
indexmap = "1.3.0"
|
||||
sum_type = "0.2.0"
|
||||
authc = { git = "https://gitlab.com/veloren/auth.git", rev = "7c1abde83f0ea7d83b0e7c655fac82eb9bb3d7ad" }
|
||||
authc = { git = "https://gitlab.com/veloren/auth.git", rev = "f3445fc1dca55f09205bdbe8ad038db60fea442b" }
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.3"
|
||||
|
@ -5,7 +5,7 @@ use vek::*;
|
||||
pub enum ClientMsg {
|
||||
Register {
|
||||
player: comp::Player,
|
||||
password: String,
|
||||
token_or_username: String,
|
||||
},
|
||||
Character {
|
||||
name: String,
|
||||
|
@ -31,4 +31,4 @@ prometheus = "0.7"
|
||||
prometheus-static-metric = "0.2"
|
||||
rouille = "3.0.0"
|
||||
portpicker = { git = "https://github.com/wusyong/portpicker-rs", branch = "fix_ipv6" }
|
||||
authc = { git = "https://gitlab.com/veloren/auth.git", rev = "7c1abde83f0ea7d83b0e7c655fac82eb9bb3d7ad" }
|
||||
authc = { git = "https://gitlab.com/veloren/auth.git", rev = "f3445fc1dca55f09205bdbe8ad038db60fea442b" }
|
||||
|
@ -3,16 +3,6 @@ use common::msg::ServerError;
|
||||
use hashbrown::HashMap;
|
||||
use std::str::FromStr;
|
||||
|
||||
fn contains_value(map: &HashMap<String, String>, value: &str) -> bool {
|
||||
let mut contains = false;
|
||||
for ev in map.values() {
|
||||
if value == ev {
|
||||
contains = true;
|
||||
}
|
||||
}
|
||||
contains
|
||||
}
|
||||
|
||||
fn derive_uuid(username: &str) -> Uuid {
|
||||
let mut state: [u8; 16] = [
|
||||
52, 17, 19, 239, 52, 17, 19, 239, 52, 17, 19, 239, 52, 17, 19, 239,
|
||||
@ -35,7 +25,7 @@ fn derive_uuid(username: &str) -> Uuid {
|
||||
}
|
||||
|
||||
pub struct AuthProvider {
|
||||
accounts: HashMap<String, String>,
|
||||
accounts: HashMap<Uuid, String>,
|
||||
auth_server: Option<AuthClient>,
|
||||
}
|
||||
|
||||
@ -61,12 +51,12 @@ impl AuthProvider {
|
||||
log::info!("Validating '{}' token.", &username_or_token);
|
||||
if let Ok(token) = AuthToken::from_str(&username_or_token) {
|
||||
match srv.validate(token) {
|
||||
Ok(id) => {
|
||||
if contains_value(&self.accounts, &id.to_string()) {
|
||||
Ok(uuid) => {
|
||||
if self.accounts.contains_key(&uuid) {
|
||||
return Err(ServerError::AlreadyLoggedIn);
|
||||
}
|
||||
let username = srv.uuid_to_username(id.clone())?;
|
||||
self.accounts.insert(username, id.to_string());
|
||||
let username = srv.uuid_to_username(uuid.clone())?;
|
||||
self.accounts.insert(uuid, username);
|
||||
Ok(true)
|
||||
},
|
||||
Err(e) => Err(ServerError::from(e)),
|
||||
@ -77,10 +67,12 @@ impl AuthProvider {
|
||||
},
|
||||
// Username is expected
|
||||
None => {
|
||||
if !self.accounts.contains_key(&username_or_token) {
|
||||
log::info!("New User '{}'", username_or_token);
|
||||
let uuid = derive_uuid(&username_or_token);
|
||||
self.accounts.insert(username_or_token, uuid.to_string());
|
||||
// Assume username was provided
|
||||
let username = username_or_token;
|
||||
let uuid = derive_uuid(&username);
|
||||
if !self.accounts.contains_key(&uuid) {
|
||||
log::info!("New User '{}'", username);
|
||||
self.accounts.insert(uuid, username);
|
||||
Ok(true)
|
||||
} else {
|
||||
Err(ServerError::AlreadyLoggedIn)
|
||||
|
@ -123,9 +123,12 @@ impl<'a> System<'a> for Sys {
|
||||
ClientState::Pending => {},
|
||||
},
|
||||
// Valid player
|
||||
ClientMsg::Register { player, password } if player.is_valid() => {
|
||||
ClientMsg::Register {
|
||||
player,
|
||||
token_or_username,
|
||||
} if player.is_valid() => {
|
||||
if !accounts
|
||||
.query(password.clone())
|
||||
.query(token_or_username.clone())
|
||||
.expect("Handle this error!")
|
||||
{
|
||||
// TODO: Graceful error handling!
|
||||
|
@ -60,7 +60,6 @@ cpal = "0.10"
|
||||
crossbeam = "=0.7.2"
|
||||
hashbrown = { version = "0.6.2", features = ["rayon", "serde", "nightly"] }
|
||||
chrono = "0.4.9"
|
||||
rust-argon2 = "0.5"
|
||||
bincode = "1.2"
|
||||
deunicode = "1.0"
|
||||
uvth = "3.1.1"
|
||||
|
@ -1,6 +1,6 @@
|
||||
use client::{error::Error as ClientError, Client};
|
||||
use common::{comp, net::PostError};
|
||||
use crossbeam::channel::{unbounded, Receiver, TryRecvError};
|
||||
use crossbeam::channel::{unbounded, Receiver, Sender, TryRecvError};
|
||||
use std::{
|
||||
net::ToSocketAddrs,
|
||||
sync::{
|
||||
@ -15,21 +15,26 @@ use std::{
|
||||
pub enum Error {
|
||||
// Error parsing input string or error resolving host name.
|
||||
BadAddress(std::io::Error),
|
||||
// Parsing/host name resolution successful but could not connect.
|
||||
#[allow(dead_code)]
|
||||
ConnectionFailed(ClientError),
|
||||
// Parsing/host name resolution successful but there was an error within the client.
|
||||
ClientError(ClientError),
|
||||
// Parsing yielded an empty iterator (specifically to_socket_addrs()).
|
||||
NoAddress,
|
||||
InvalidAuth,
|
||||
ClientCrashed,
|
||||
ServerIsFull,
|
||||
}
|
||||
|
||||
pub enum Msg {
|
||||
IsAuthTrusted(String),
|
||||
Done(Result<Client, Error>),
|
||||
}
|
||||
|
||||
pub struct AuthTrust(String, bool);
|
||||
|
||||
// Used to asynchronously parse the server address, resolve host names,
|
||||
// and create the client (which involves establishing a connection to the
|
||||
// server).
|
||||
pub struct ClientInit {
|
||||
rx: Receiver<Result<Client, Error>>,
|
||||
rx: Receiver<Msg>,
|
||||
trust_tx: Sender<AuthTrust>,
|
||||
cancel: Arc<AtomicBool>,
|
||||
}
|
||||
impl ClientInit {
|
||||
@ -41,6 +46,7 @@ impl ClientInit {
|
||||
let (server_address, default_port, prefer_ipv6) = connection_args;
|
||||
|
||||
let (tx, rx) = unbounded();
|
||||
let (trust_tx, trust_rx) = unbounded();
|
||||
let cancel = Arc::new(AtomicBool::new(false));
|
||||
let cancel2 = Arc::clone(&cancel);
|
||||
|
||||
@ -68,35 +74,20 @@ impl ClientInit {
|
||||
{
|
||||
match Client::new(socket_addr, player.view_distance) {
|
||||
Ok(mut client) => {
|
||||
// Authentication
|
||||
let username_or_token = match &client.server_info.auth_provider
|
||||
if let Err(err) =
|
||||
client.register(player.clone(), password, |auth_server| {
|
||||
let _ = tx
|
||||
.send(Msg::IsAuthTrusted(auth_server.to_string()));
|
||||
trust_rx
|
||||
.recv()
|
||||
.map(|AuthTrust(server, trust)| {
|
||||
trust && &server == auth_server
|
||||
})
|
||||
.unwrap_or(false)
|
||||
})
|
||||
{
|
||||
Some(addr) => {
|
||||
let auth_client = authc::AuthClient::new(addr);
|
||||
// TODO: PROMPT USER INCASE OF THE AUTH SERVER BEING
|
||||
// UNKNOWN!
|
||||
log::error!(
|
||||
"Logging in with '{}', '{}'.",
|
||||
&player.alias,
|
||||
&password
|
||||
);
|
||||
match auth_client.sign_in(&player.alias, &password) {
|
||||
Ok(token) => token.serialize(),
|
||||
// TODO: Properly deal with it
|
||||
Err(e) => panic!(
|
||||
"Failed to sign in to auth server '{}'! {}",
|
||||
addr, e
|
||||
),
|
||||
}
|
||||
},
|
||||
None => player.alias.clone(),
|
||||
};
|
||||
|
||||
if let Err(ClientError::InvalidAuth) =
|
||||
client.register(player.clone(), username_or_token.clone())
|
||||
{
|
||||
last_err = Some(Error::InvalidAuth);
|
||||
break;
|
||||
last_err = Some(Error::ClientError(err));
|
||||
break 'tries;
|
||||
}
|
||||
let _ = tx.send(Ok(client));
|
||||
return;
|
||||
@ -109,20 +100,11 @@ impl ClientInit {
|
||||
},
|
||||
// Assume the connection failed and try again soon
|
||||
ClientError::Network(_) => {},
|
||||
ClientError::TooManyPlayers => {
|
||||
last_err = Some(Error::ServerIsFull);
|
||||
// Non-connection error, stop attempts
|
||||
err => {
|
||||
last_err = Some(Error::ClientError(err));
|
||||
break 'tries;
|
||||
},
|
||||
ClientError::InvalidAuth => {
|
||||
last_err = Some(Error::InvalidAuth);
|
||||
break 'tries;
|
||||
},
|
||||
// TODO: Handle errors?
|
||||
_ => panic!(
|
||||
"Unexpected non-network error when creating client: \
|
||||
{:?}",
|
||||
err
|
||||
),
|
||||
}
|
||||
},
|
||||
}
|
||||
@ -130,29 +112,38 @@ impl ClientInit {
|
||||
thread::sleep(Duration::from_secs(5));
|
||||
}
|
||||
// Parsing/host name resolution successful but no connection succeeded.
|
||||
let _ = tx.send(Err(last_err.unwrap_or(Error::NoAddress)));
|
||||
let _ = tx.send(Msg::Done(Err(last_err.unwrap_or(Error::NoAddress))));
|
||||
},
|
||||
Err(err) => {
|
||||
// Error parsing input string or error resolving host name.
|
||||
let _ = tx.send(Err(Error::BadAddress(err)));
|
||||
let _ = tx.send(Msg::Done(Err(Error::BadAddress(err))));
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
ClientInit { rx, cancel }
|
||||
ClientInit {
|
||||
rx,
|
||||
trust_tx,
|
||||
cancel,
|
||||
}
|
||||
}
|
||||
|
||||
/// Poll if the thread is complete.
|
||||
/// Returns None if the thread is still running, otherwise returns the
|
||||
/// Result of client creation.
|
||||
pub fn poll(&self) -> Option<Result<Client, Error>> {
|
||||
pub fn poll(&self) -> Option<Msg> {
|
||||
match self.rx.try_recv() {
|
||||
Ok(result) => Some(result),
|
||||
Ok(msg) => Some(msg),
|
||||
Err(TryRecvError::Empty) => None,
|
||||
Err(TryRecvError::Disconnected) => Some(Err(Error::ClientCrashed)),
|
||||
Err(TryRecvError::Disconnected) => Some(Msg::Done(Err(Error::ClientCrashed))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Report trust status of auth server
|
||||
pub fn auth_trust(&self, auth_server: String, trusted: bool) {
|
||||
let _ = self.trust_tx.send(AuthTrust(auth_server, trusted));
|
||||
}
|
||||
|
||||
pub fn cancel(&mut self) { self.cancel.store(true, Ordering::Relaxed); }
|
||||
}
|
||||
|
||||
|
@ -8,9 +8,9 @@ use crate::{
|
||||
window::Event,
|
||||
Direction, GlobalState, PlayState, PlayStateResult,
|
||||
};
|
||||
use client_init::{ClientInit, Error as InitError};
|
||||
use client_init::{ClientInit, Error as InitError, Msg as InitMsg};
|
||||
use common::{assets::load_expect, clock::Clock, comp};
|
||||
use log::warn;
|
||||
use log::{error, warn};
|
||||
#[cfg(feature = "singleplayer")]
|
||||
use std::time::Duration;
|
||||
use ui::{Event as MainMenuEvent, MainMenuUi};
|
||||
@ -73,19 +73,39 @@ impl PlayState for MainMenuState {
|
||||
std::rc::Rc::new(std::cell::RefCell::new(client)),
|
||||
)));
|
||||
},
|
||||
Some(Err(err)) => {
|
||||
Some(InitMsg::Done(Err(err))) => {
|
||||
client_init = None;
|
||||
global_state.info_message = Some(
|
||||
match err {
|
||||
InitError::BadAddress(_) | InitError::NoAddress => "Server not found",
|
||||
InitError::InvalidAuth => "Invalid credentials",
|
||||
InitError::ServerIsFull => "Server is full",
|
||||
InitError::ConnectionFailed(_) => "Connection failed",
|
||||
InitError::ClientError(err) => match err {
|
||||
client::Error::InvalidAuth => "Invalid credentials",
|
||||
client::Error::TooManyPlayers => "Server is full",
|
||||
client::Error::AuthServerNotTrusted => "Auth server not trusted",
|
||||
_ => {
|
||||
error!("Error when trying to connect: {:?}", err);
|
||||
"Connection Failed"
|
||||
},
|
||||
},
|
||||
InitError::ClientCrashed => "Client crashed",
|
||||
}
|
||||
.to_string(),
|
||||
);
|
||||
},
|
||||
Some(InitMsg::IsAuthTrusted(auth_server)) => {
|
||||
if global_state
|
||||
.settings
|
||||
.networking
|
||||
.trusted_auth_servers
|
||||
.contains(&auth_server)
|
||||
{
|
||||
// Can't fail since we just polled it, it must be Some
|
||||
client_init.as_ref().unwrap().auth_trust(auth_server, true);
|
||||
} else {
|
||||
// Show warning that auth server is not trusted and prompt for approval
|
||||
self.main_menu_ui.auth_trust_prompt(auth_server);
|
||||
}
|
||||
},
|
||||
None => {},
|
||||
}
|
||||
|
||||
@ -140,6 +160,19 @@ impl PlayState for MainMenuState {
|
||||
MainMenuEvent::DisclaimerClosed => {
|
||||
global_state.settings.show_disclaimer = false
|
||||
},
|
||||
MainMenuEvent::AuthServerTrust(auth_server, trust) => {
|
||||
if trust {
|
||||
global_state
|
||||
.settings
|
||||
.networking
|
||||
.trusted_auth_servers
|
||||
.insert(auth_server.clone());
|
||||
global_state.settings.save_to_file_warn();
|
||||
}
|
||||
client_init
|
||||
.as_ref()
|
||||
.map(|init| init.auth_trust(auth_server, trust));
|
||||
},
|
||||
}
|
||||
}
|
||||
let localized_strings = load_expect::<VoxygenLocalization>(&i18n_asset_key(
|
||||
@ -200,12 +233,7 @@ fn attempt_login(
|
||||
*client_init = Some(ClientInit::new(
|
||||
(server_address, server_port, false),
|
||||
player,
|
||||
{
|
||||
password
|
||||
/*let salt = b"staticsalt_zTuGkGvybZIjZbNUDtw15";
|
||||
let config = Config::default();
|
||||
argon2::hash_encoded(password.as_bytes(), salt, &config).unwrap()*/
|
||||
},
|
||||
{ password },
|
||||
));
|
||||
}
|
||||
} else {
|
||||
|
@ -68,7 +68,9 @@ widget_ids! {
|
||||
// Info Window
|
||||
info_frame,
|
||||
info_text,
|
||||
info_bottom
|
||||
info_bottom,
|
||||
// Auth Trust Prompt
|
||||
button_add_auth_trust,
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,16 +124,17 @@ pub enum Event {
|
||||
Quit,
|
||||
Settings,
|
||||
DisclaimerClosed,
|
||||
AuthServerTrust(String, bool),
|
||||
}
|
||||
|
||||
pub enum PopupType {
|
||||
Error,
|
||||
ConnectionInfo,
|
||||
AuthTrustPrompt(String),
|
||||
}
|
||||
|
||||
pub struct PopupData {
|
||||
msg: String,
|
||||
button_text: String,
|
||||
popup_type: PopupType,
|
||||
}
|
||||
|
||||
@ -261,27 +264,51 @@ impl MainMenuUi {
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.set(self.ids.version, ui_widgets);
|
||||
// Popup (Error/Info)
|
||||
if let Some(popup_data) = &self.popup {
|
||||
let text = Text::new(&popup_data.msg)
|
||||
.rgba(1.0, 1.0, 1.0, if self.connect { fade_msg } else { 1.0 })
|
||||
|
||||
// Popup (Error/Info/AuthTrustPrompt)
|
||||
let mut change_popup = None;
|
||||
if let Some(PopupData { msg, popup_type }) = &self.popup {
|
||||
let text = Text::new(msg)
|
||||
.rgba(
|
||||
1.0,
|
||||
1.0,
|
||||
1.0,
|
||||
if let PopupType::ConnectionInfo = popup_type {
|
||||
fade_msg
|
||||
} else {
|
||||
1.0
|
||||
},
|
||||
)
|
||||
.font_id(self.fonts.cyri.conrod_id);
|
||||
Rectangle::fill_with([65.0 * 6.0, 140.0], color::TRANSPARENT)
|
||||
let (frame_w, frame_h) = if let PopupType::AuthTrustPrompt(_) = popup_type {
|
||||
(65.0 * 8.0, 300.0)
|
||||
} else {
|
||||
(65.0 * 6.0, 140.0)
|
||||
};
|
||||
let error_bg = Rectangle::fill_with([frame_w, frame_h], color::TRANSPARENT)
|
||||
.rgba(0.1, 0.1, 0.1, if self.connect { 0.0 } else { 1.0 })
|
||||
.parent(ui_widgets.window)
|
||||
.up_from(self.ids.banner_top, 15.0)
|
||||
.set(self.ids.login_error_bg, ui_widgets);
|
||||
.parent(ui_widgets.window);
|
||||
if let PopupType::AuthTrustPrompt(_) = popup_type {
|
||||
error_bg.middle_of(ui_widgets.window)
|
||||
} else {
|
||||
error_bg.up_from(self.ids.banner_top, 15.0)
|
||||
}
|
||||
.set(self.ids.login_error_bg, ui_widgets);
|
||||
Image::new(self.imgs.info_frame)
|
||||
.w_h(65.0 * 6.0, 140.0)
|
||||
.w_h(frame_w, frame_h)
|
||||
.color(Some(Color::Rgba(
|
||||
1.0,
|
||||
1.0,
|
||||
1.0,
|
||||
if self.connect { 0.0 } else { 1.0 },
|
||||
if let PopupType::ConnectionInfo = popup_type {
|
||||
0.0
|
||||
} else {
|
||||
1.0
|
||||
},
|
||||
)))
|
||||
.middle_of(self.ids.login_error_bg)
|
||||
.set(self.ids.error_frame, ui_widgets);
|
||||
if self.connect {
|
||||
if let PopupType::ConnectionInfo = popup_type {
|
||||
text.mid_top_with_margin_on(self.ids.error_frame, 10.0)
|
||||
.font_id(self.fonts.alkhemi.conrod_id)
|
||||
.bottom_left_with_margins_on(ui_widgets.window, 60.0, 60.0)
|
||||
@ -289,6 +316,7 @@ impl MainMenuUi {
|
||||
.set(self.ids.login_error, ui_widgets);
|
||||
} else {
|
||||
text.mid_top_with_margin_on(self.ids.error_frame, 10.0)
|
||||
.w(frame_w - 10.0 * 2.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(25))
|
||||
.set(self.ids.login_error, ui_widgets);
|
||||
@ -296,7 +324,7 @@ impl MainMenuUi {
|
||||
if Button::image(self.imgs.button)
|
||||
.w_h(100.0, 30.0)
|
||||
.mid_bottom_with_margin_on(
|
||||
if self.connect {
|
||||
if let PopupType::ConnectionInfo = popup_type {
|
||||
ui_widgets.window
|
||||
} else {
|
||||
self.ids.login_error_bg
|
||||
@ -306,22 +334,55 @@ impl MainMenuUi {
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label_y(Relative::Scalar(2.0))
|
||||
.label(&popup_data.button_text)
|
||||
.label(match popup_type {
|
||||
PopupType::Error => "Okay",
|
||||
PopupType::ConnectionInfo => "Cancel",
|
||||
PopupType::AuthTrustPrompt(_) => "Cancel",
|
||||
})
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.label_font_size(self.fonts.cyri.scale(15))
|
||||
.label_color(TEXT_COLOR)
|
||||
.set(self.ids.button_ok, ui_widgets)
|
||||
.was_clicked()
|
||||
{
|
||||
match popup_data.popup_type {
|
||||
match &popup_type {
|
||||
PopupType::Error => (),
|
||||
PopupType::ConnectionInfo => {
|
||||
events.push(Event::CancelLoginAttempt);
|
||||
},
|
||||
_ => (),
|
||||
PopupType::AuthTrustPrompt(auth_server) => {
|
||||
events.push(Event::AuthServerTrust(auth_server.clone(), false));
|
||||
},
|
||||
};
|
||||
self.popup = None;
|
||||
};
|
||||
change_popup = Some(None);
|
||||
}
|
||||
|
||||
if let PopupType::AuthTrustPrompt(auth_server) = popup_type {
|
||||
if Button::image(self.imgs.button)
|
||||
.w_h(100.0, 30.0)
|
||||
.right_from(self.ids.button_ok, 10.0)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label_y(Relative::Scalar(2.0))
|
||||
.label("Add")
|
||||
.label_font_id(self.fonts.cyri)
|
||||
.label_font_size(15)
|
||||
.label_color(TEXT_COLOR)
|
||||
.set(self.ids.button_add_auth_trust, ui_widgets)
|
||||
.was_clicked()
|
||||
{
|
||||
events.push(Event::AuthServerTrust(auth_server.clone(), true));
|
||||
change_popup = Some(Some(PopupData {
|
||||
msg: "Connecting...".to_string(),
|
||||
popup_type: PopupType::ConnectionInfo,
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(p) = change_popup {
|
||||
self.popup = p;
|
||||
}
|
||||
|
||||
if !self.connect {
|
||||
Image::new(self.imgs.banner)
|
||||
.w_h(65.0 * 6.0, 100.0 * 6.0)
|
||||
@ -461,8 +522,6 @@ impl MainMenuUi {
|
||||
}
|
||||
}
|
||||
// Password
|
||||
// TODO: Why isn't it showing up?
|
||||
// Password
|
||||
Rectangle::fill_with([320.0, 50.0], color::rgba(0.0, 0.0, 0.0, 0.97))
|
||||
.down_from(self.ids.usrnm_bg, 30.0)
|
||||
.set(self.ids.passwd_bg, ui_widgets);
|
||||
@ -686,6 +745,18 @@ impl MainMenuUi {
|
||||
events
|
||||
}
|
||||
|
||||
pub fn auth_trust_prompt(&mut self, auth_server: String) {
|
||||
self.popup = Some(PopupData {
|
||||
msg: format!(
|
||||
"Warning: The server you are trying to connect to has provided this \
|
||||
authentication server addresss:\n\n{}\n\nbut it is not in your list of trusted \
|
||||
authentication servers.",
|
||||
&auth_server
|
||||
),
|
||||
popup_type: PopupType::AuthTrustPrompt(auth_server),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn show_info(&mut self, msg: String, button_text: String) {
|
||||
self.popup = Some(PopupData {
|
||||
msg,
|
||||
|
@ -7,6 +7,7 @@ use crate::{
|
||||
};
|
||||
use directories::{ProjectDirs, UserDirs};
|
||||
use glutin::{MouseButton, VirtualKeyCode};
|
||||
use hashbrown::HashSet;
|
||||
use log::warn;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::{fs, io::prelude::*, path::PathBuf};
|
||||
@ -157,6 +158,7 @@ pub struct NetworkingSettings {
|
||||
pub password: String,
|
||||
pub servers: Vec<String>,
|
||||
pub default_server: usize,
|
||||
pub trusted_auth_servers: HashSet<String>,
|
||||
}
|
||||
|
||||
impl Default for NetworkingSettings {
|
||||
@ -166,6 +168,10 @@ impl Default for NetworkingSettings {
|
||||
password: String::default(),
|
||||
servers: vec!["server.veloren.net".to_string()],
|
||||
default_server: 0,
|
||||
trusted_auth_servers: ["https://auth.veloren.net"]
|
||||
.iter()
|
||||
.map(|s| s.to_string())
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user