summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorEmīls Piņķis <emils@mullvad.net>2018-10-15 16:07:21 +0100
committerEmīls Piņķis <emils@mullvad.net>2018-10-23 10:44:05 +0100
commitc0632541d77a22e543d1549e5569a25c4d040d7e (patch)
tree9e5f27c603d6a0d75fede50a608d59613aa8515a
parentbef533403920cfc08a9f705cbbc1b5c27f6e6517 (diff)
downloadmullvadvpn-c0632541d77a22e543d1549e5569a25c4d040d7e.tar.xz
mullvadvpn-c0632541d77a22e543d1549e5569a25c4d040d7e.zip
Added auth_failed module to mullvad-types
-rw-r--r--Cargo.lock2
-rw-r--r--mullvad-types/Cargo.toml2
-rw-r--r--mullvad-types/src/auth_failed.rs103
-rw-r--r--mullvad-types/src/lib.rs6
4 files changed, 113 insertions, 0 deletions
diff --git a/Cargo.lock b/Cargo.lock
index fb18677e07..b518ba0a83 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1044,8 +1044,10 @@ version = "0.1.0"
dependencies = [
"chrono 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"mullvad-paths 0.1.0",
+ "regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/mullvad-types/Cargo.toml b/mullvad-types/Cargo.toml
index 74d5645859..0f67cb1eb7 100644
--- a/mullvad-types/Cargo.toml
+++ b/mullvad-types/Cargo.toml
@@ -12,6 +12,8 @@ serde = "1.0"
serde_json = "1.0"
error-chain = "0.12"
log = "0.4"
+regex = "1"
+lazy_static = "1.1.0"
talpid-types = { path = "../talpid-types" }
mullvad-paths = { path = "../mullvad-paths" }
diff --git a/mullvad-types/src/auth_failed.rs b/mullvad-types/src/auth_failed.rs
new file mode 100644
index 0000000000..d53de2d136
--- /dev/null
+++ b/mullvad-types/src/auth_failed.rs
@@ -0,0 +1,103 @@
+use regex::Regex;
+
+#[derive(Debug)]
+pub struct AuthFailed {
+ reason: AuthFailedInner,
+}
+
+#[derive(Debug)]
+enum AuthFailedInner {
+ InvalidAccount,
+ ExpiredAccount,
+ TooManyConnectons,
+ Unknown(String, String),
+}
+
+// These strings should match up with gui/packages/desktop/src/renderer/lib/auth-failure.js
+const INVALID_ACCOUNT_MSG: &str = "You've logged in with an account number that is not valid. Please log out and try another one.";
+const EXPIRED_ACCOUNT_MSG: &str = "You have no more VPN time left on this account. Please log in on our website to buy more credit.";
+const TOO_MANY_CONNECTIONS_MSG: &str = "This account has too many simultaneous connections. Disconnect another device or try connecting again shortly.";
+
+impl AuthFailedInner {
+ fn from_str(input: &str) -> AuthFailedInner {
+ use self::AuthFailedInner::*;
+ match parse_string(input) {
+ Some(("INVALID_ACCOUNT", _)) => InvalidAccount,
+ Some(("EXPIRED_ACCOUNT", _)) => ExpiredAccount,
+ Some(("TOO_MANY_CONNECTIONS", _)) => TooManyConnectons,
+ Some((unknown_reason, message)) => {
+ warn!(
+ "Received AUTH_FAILED message with unknown reason: {}",
+ input
+ );
+ Unknown(unknown_reason.to_string(), message.to_string())
+ }
+ None => {
+ warn!("Received invalid AUTH_FAILED message: {}", input);
+ Unknown("UNKNOWN".to_string(), input.to_string())
+ }
+ }
+ }
+}
+
+impl AuthFailed {
+ pub fn from_str(reason: &str) -> AuthFailed {
+ AuthFailed {
+ reason: AuthFailedInner::from_str(reason),
+ }
+ }
+}
+
+impl ::std::fmt::Display for AuthFailed {
+ fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+ use self::AuthFailedInner::*;
+ match self.reason {
+ InvalidAccount => write!(f, "{}", INVALID_ACCOUNT_MSG),
+ ExpiredAccount => write!(f, "{}", EXPIRED_ACCOUNT_MSG),
+ TooManyConnectons => write!(f, "{}", TOO_MANY_CONNECTIONS_MSG),
+ Unknown(_, ref reason) => write!(f, "{}", reason),
+ }
+ }
+}
+
+// Expects to take a string like "[INVALID_ACCOUNT] This is not a valid Mullvad account".
+// The example input string would be split into:
+// * "INVALID_ACCOUNT" - the ID of the failure reason.
+// * "This is not a valid Mullvad account" - the human readable message of the failure reason.
+// In the case that the message has preceeding whitespace, it will be trimmed.
+fn parse_string<'a>(reason: &'a str) -> Option<(&'a str, &'a str)> {
+ lazy_static! {
+ static ref REASON_REGEX: Regex = Regex::new(r"^\[(\w+)\]\s*(.*)$").unwrap();
+ }
+ let captures = REASON_REGEX.captures(reason)?;
+ let reason = captures.get(1).map(|m| m.as_str())?;
+ let message = captures.get(2).map(|m| m.as_str())?;
+ Some((reason, message))
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_parsing() {
+ let tests = vec![
+ (Some(("INVALID_ACCOUNT", "This is not a valid Mullvad account" )),
+ "[INVALID_ACCOUNT] This is not a valid Mullvad account"),
+ (Some(("EXPIRED_ACCOUNT", "This account has no time left")),
+ "[EXPIRED_ACCOUNT] This account has no time left"),
+ (Some(("TOO_MANY_CONNECTIONS", "This Mullvad account is already used by the maximum number of simultaneous connections")),
+ "[TOO_MANY_CONNECTIONS] This Mullvad account is already used by the maximum number of simultaneous connections"),
+ (None, "[Incomplete String"),
+ (Some(("REASON_REASON", "")), "[REASON_REASON]"),
+ (Some(("REASON_REASON", "A")), "[REASON_REASON]A"),
+ (None, "incomplete]"),
+ (None, ""),
+ ];
+
+ for (expected_output, input) in tests.iter() {
+ assert_eq!(*expected_output, parse_string(input));
+ }
+ }
+
+}
diff --git a/mullvad-types/src/lib.rs b/mullvad-types/src/lib.rs
index ff7628b9ad..749da41353 100644
--- a/mullvad-types/src/lib.rs
+++ b/mullvad-types/src/lib.rs
@@ -7,6 +7,7 @@
//! the License, or (at your option) any later version.
extern crate chrono;
+extern crate regex;
extern crate serde;
#[macro_use]
extern crate serde_derive;
@@ -20,7 +21,12 @@ extern crate log;
#[macro_use]
extern crate error_chain;
+#[macro_use]
+extern crate lazy_static;
+
+
pub mod account;
+pub mod auth_failed;
pub mod location;
pub mod relay_constraints;
pub mod relay_list;