From 697d4a52d9673a173c372806a0a7b1603e6c5269 Mon Sep 17 00:00:00 2001
From: aljazerzen <aljaz@calms.eu>
Date: Thu, 1 Apr 2021 16:37:13 +0200
Subject: [PATCH] login trim username, improve validation, social ordering

---
 common/src/comp/player.rs       | 29 +++++++++++++++++++++++++----
 server/src/cmd.rs               |  4 ++--
 voxygen/src/hud/social.rs       |  4 ++--
 voxygen/src/menu/main/mod.rs    | 27 ++++++++++++++-------------
 voxygen/src/menu/main/ui/mod.rs |  2 +-
 5 files changed, 44 insertions(+), 22 deletions(-)

diff --git a/common/src/comp/player.rs b/common/src/comp/player.rs
index 17a1a07b4b..3e1dbdcb12 100644
--- a/common/src/comp/player.rs
+++ b/common/src/comp/player.rs
@@ -14,15 +14,21 @@ pub struct Player {
 impl Player {
     pub fn new(alias: String, uuid: Uuid) -> Self { Self { alias, uuid } }
 
-    pub fn is_valid(&self) -> bool { Self::alias_is_valid(&self.alias) }
+    pub fn is_valid(&self) -> bool { Self::alias_validate(&self.alias).is_ok() }
 
-    pub fn alias_is_valid(alias: &str) -> bool {
+    pub fn alias_validate(alias: &str) -> Result<(), AliasError> {
         // TODO: Expose auth name validation and use it here.
         // See https://gitlab.com/veloren/auth/-/blob/master/server/src/web.rs#L20
-        alias
+        if !alias
             .chars()
             .all(|c| c.is_alphanumeric() || c == '_' || c == '-')
-            && alias.len() <= MAX_ALIAS_LEN
+        {
+            Err(AliasError::ForbiddenCharacters)
+        } else if alias.len() > MAX_ALIAS_LEN {
+            Err(AliasError::TooLong)
+        } else {
+            Ok(())
+        }
     }
 
     /// Not to be confused with uid
@@ -38,3 +44,18 @@ pub struct Respawn;
 impl Component for Respawn {
     type Storage = NullStorage<Self>;
 }
+
+pub enum AliasError {
+    ForbiddenCharacters,
+    TooLong,
+}
+
+impl ToString for AliasError {
+    fn to_string(&self) -> String {
+        match *self {
+            AliasError::ForbiddenCharacters => "Alias contains illegal characters.",
+            AliasError::TooLong => "Alias is too long.",
+        }
+        .to_string()
+    }
+}
diff --git a/server/src/cmd.rs b/server/src/cmd.rs
index 3d0d3db1e9..9c3407132b 100644
--- a/server/src/cmd.rs
+++ b/server/src/cmd.rs
@@ -751,11 +751,11 @@ fn handle_alias(
         return;
     }
     if let Ok(alias) = scan_fmt!(&args, &action.arg_fmt(), String) {
-        if !comp::Player::alias_is_valid(&alias) {
+        if let Err(error) = comp::Player::alias_validate(&alias) {
             // Prevent silly aliases
             server.notify_client(
                 client,
-                ServerGeneral::server_msg(ChatType::CommandError, "Invalid alias."),
+                ServerGeneral::server_msg(ChatType::CommandError, error.to_string()),
             );
             return;
         }
diff --git a/voxygen/src/hud/social.rs b/voxygen/src/hud/social.rs
index df7865b392..ee7e6b7a39 100644
--- a/voxygen/src/hud/social.rs
+++ b/voxygen/src/hud/social.rs
@@ -386,8 +386,8 @@ impl<'a> Widget for Social<'a> {
                 player
                     .character
                     .as_ref()
-                    .map(|character| &character.name)
-                    .unwrap_or(&player.player_alias)
+                    .map(|character| character.name.to_lowercase())
+                    .unwrap_or_else(|| player.player_alias.to_string())
             });
             for (i, (&uid, player_info)) in player_list.into_iter().enumerate() {
                 let hide_username = true;
diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs
index 47d014be4f..a8186acb7e 100644
--- a/voxygen/src/menu/main/mod.rs
+++ b/voxygen/src/menu/main/mod.rs
@@ -340,18 +340,19 @@ fn attempt_login(
     client_init: &mut Option<ClientInit>,
     runtime: Option<Arc<runtime::Runtime>>,
 ) {
-    if comp::Player::alias_is_valid(&username) {
-        // Don't try to connect if there is already a connection in progress.
-        if client_init.is_none() {
-            *client_init = Some(ClientInit::new(
-                connection_args,
-                username,
-                Some(settings.graphics.view_distance),
-                password,
-                runtime,
-            ));
-        }
-    } else {
-        *info_message = Some("Invalid username".to_string());
+    if let Err(err) = comp::Player::alias_validate(&username) {
+        *info_message = Some(err.to_string());
+        return;
+    }
+
+    // Don't try to connect if there is already a connection in progress.
+    if client_init.is_none() {
+        *client_init = Some(ClientInit::new(
+            connection_args,
+            username,
+            Some(settings.graphics.view_distance),
+            password,
+            runtime,
+        ));
     }
 }
diff --git a/voxygen/src/menu/main/ui/mod.rs b/voxygen/src/menu/main/ui/mod.rs
index 25e331cb3b..761cc8a77c 100644
--- a/voxygen/src/menu/main/ui/mod.rs
+++ b/voxygen/src/menu/main/ui/mod.rs
@@ -354,7 +354,7 @@ impl Controls {
                 };
 
                 events.push(Event::LoginAttempt {
-                    username: self.login_info.username.clone(),
+                    username: self.login_info.username.trim().to_string(),
                     password: self.login_info.password.clone(),
                     server_address: self.login_info.server.clone(),
                 });