diff --git a/src/data/mod.rs b/src/data/mod.rs
index 1f3815b..df381b0 100644
--- a/src/data/mod.rs
+++ b/src/data/mod.rs
@@ -5,7 +5,7 @@ pub use data::command::Command;
 pub use data::config::Config;
 pub use data::message::Message;
 pub use data::response::Response;
-pub use data::user::User;
+pub use data::user::{AccessLevel, User};
 
 pub mod kinds {
     //! Trait definitions of appropriate Writers and Buffers for use with this library.
diff --git a/src/data/user.rs b/src/data/user.rs
index 9f5772a..991d5e2 100644
--- a/src/data/user.rs
+++ b/src/data/user.rs
@@ -7,11 +7,11 @@ use std::str::FromStr;
 #[deriving(Clone, Show)]
 pub struct User {
     /// The user's nickname.
+    /// This is the only detail used in determining the equality of two users.
     name: String,
-    /// The user's access level.
-    /// For simplicity, this is not used to determine the equality of two users.
-    /// That is a user is equal if and only if their nickname is the same.
-    access_level: AccessLevel,
+    /// The user's highest access level.
+    highest_access_level: AccessLevel,
+    access_levels: Vec<AccessLevel>,
 }
 
 impl User {
@@ -25,7 +25,12 @@ impl User {
             } else {
                 name[1..].into_string()
             },
-            access_level: rank.unwrap(),
+            highest_access_level: rank.unwrap(),
+            access_levels: if let Some(AccessLevel::Member) = rank {
+                vec![rank.unwrap()]
+            } else {
+                vec![rank.unwrap(), AccessLevel::Member]
+            }
         }
     }
 
@@ -35,27 +40,57 @@ impl User {
         self.name[]
     }
 
-    /// Gets the user's access level.
+    /// Gets the user's highest access level.
     #[experimental]
-    pub fn access_level(&self) -> AccessLevel {
-        self.access_level
+    pub fn highest_access_level(&self) -> AccessLevel {
+        self.highest_access_level
+    }
+
+    /// Gets all the user's access levels.
+    #[experimental]
+    pub fn access_levels(&self) -> Vec<AccessLevel> {
+        self.access_levels.clone()
     }
 
     /// Updates the user's access level.
     #[unstable]
     pub fn update_access_level(&mut self, mode: &str) {
-        self.access_level = match mode {
-            "+q" => AccessLevel::Owner,
-            "-q" => AccessLevel::Member,
-            "+a" => AccessLevel::Admin,
-            "-a" => AccessLevel::Member,
-            "+o" => AccessLevel::Oper,
-            "-o" => AccessLevel::Member,
-            "+h" => AccessLevel::HalfOp,
-            "-h" => AccessLevel::Member,
-            "+v" => AccessLevel::Voice,
-            "-v" => AccessLevel::Member,
-            _ => self.access_level,
+        match mode {
+            "+q" => self.add_access_level(AccessLevel::Owner),
+            "-q" => self.sub_access_level(AccessLevel::Owner),
+            "+a" => self.add_access_level(AccessLevel::Admin),
+            "-a" => self.sub_access_level(AccessLevel::Admin),
+            "+o" => self.add_access_level(AccessLevel::Oper),
+            "-o" => self.sub_access_level(AccessLevel::Oper),
+            "+h" => self.add_access_level(AccessLevel::HalfOp),
+            "-h" => self.sub_access_level(AccessLevel::HalfOp),
+            "+v" => self.add_access_level(AccessLevel::Voice),
+            "-v" => self.sub_access_level(AccessLevel::Voice),
+            _    => {},
+       }
+    }
+
+    fn add_access_level(&mut self, level: AccessLevel) {
+        if level > self.highest_access_level() {
+            self.highest_access_level = level   
+        }
+        self.access_levels.push(level.clone())
+    }
+
+    fn sub_access_level(&mut self, level: AccessLevel) {
+        if let Some(n) = self.access_levels[].position_elem(&level) {
+            self.access_levels.swap_remove(n);
+        }
+        if level == self.highest_access_level() {
+            self.highest_access_level = {
+                let mut max = AccessLevel::Member;
+                for level in self.access_levels.iter() {
+                    if level > &max {
+                        max = level.clone()
+                    }
+                }
+                max
+            }
         }
     }
 }
@@ -84,6 +119,44 @@ pub enum AccessLevel {
     Member,
 }
 
+impl PartialOrd for AccessLevel {
+    fn partial_cmp(&self, other: &AccessLevel) -> Option<Ordering> {
+        if self == other { return Some(Equal) }
+        match self {
+            &AccessLevel::Owner => Some(Greater),
+            &AccessLevel::Admin => {
+                if other == &AccessLevel::Owner {
+                    Some(Less)
+                } else {
+                    Some(Greater)
+                }
+            },
+            &AccessLevel::Oper => {
+                if other == &AccessLevel::Owner || other == &AccessLevel::Admin {
+                    Some(Less)
+                } else {
+                    Some(Greater)
+                }
+            },
+            &AccessLevel::HalfOp => {
+                if other == &AccessLevel::Voice || other == &AccessLevel::Member {
+                    Some(Greater)
+                } else {
+                    Some(Less)
+                }
+            },
+            &AccessLevel::Voice => {
+                if other == &AccessLevel::Member {
+                    Some(Greater)
+                } else {
+                    Some(Less)
+                }
+            },
+            &AccessLevel::Member => Some(Less),
+        }    
+    }
+}
+
 impl FromStr for AccessLevel {
     fn from_str(s: &str) -> Option<AccessLevel> {
         if s.len() == 0 { Some(AccessLevel::Member) } else {
@@ -120,10 +193,11 @@ mod test {
         let user = User::new("~owner");
         let exp = User {
             name: format!("owner"),
-            access_level: Owner,
+            highest_access_level: Owner,
+            access_levels: vec![Owner, Member],
         };
         assert_eq!(user, exp);
-        assert_eq!(user.access_level, exp.access_level);
+        assert_eq!(user.highest_access_level, exp.highest_access_level);
     }
 
     #[test]
@@ -135,32 +209,59 @@ mod test {
     #[test]
     fn access_level() {
         let user = User::new("~owner");
-        assert_eq!(user.access_level(), Owner);
+        assert_eq!(user.highest_access_level(), Owner);
     }
 
     #[test]
     fn update_user_rank() {
         let mut user = User::new("user");
-        assert_eq!(user.access_level, Member);
+        assert_eq!(user.highest_access_level, Member);
         user.update_access_level("+q");
-        assert_eq!(user.access_level, Owner);
+        assert_eq!(user.highest_access_level, Owner);
         user.update_access_level("-q");
-        assert_eq!(user.access_level, Member);
+        assert_eq!(user.highest_access_level, Member);
         user.update_access_level("+a");
-        assert_eq!(user.access_level, Admin);
+        assert_eq!(user.highest_access_level, Admin);
         user.update_access_level("-a");
-        assert_eq!(user.access_level, Member);
+        assert_eq!(user.highest_access_level, Member);
         user.update_access_level("+o");
-        assert_eq!(user.access_level, Oper);
+        assert_eq!(user.highest_access_level, Oper);
         user.update_access_level("-o");
-        assert_eq!(user.access_level, Member);
+        assert_eq!(user.highest_access_level, Member);
         user.update_access_level("+h");
-        assert_eq!(user.access_level, HalfOp);
+        assert_eq!(user.highest_access_level, HalfOp);
         user.update_access_level("-h");
-        assert_eq!(user.access_level, Member);
+        assert_eq!(user.highest_access_level, Member);
         user.update_access_level("+v");
-        assert_eq!(user.access_level, Voice);
+        assert_eq!(user.highest_access_level, Voice);
         user.update_access_level("-v");
-        assert_eq!(user.access_level, Member);
+        assert_eq!(user.highest_access_level, Member);
+    }
+
+    #[test]
+    fn derank_user_in_full() {
+        let mut user = User::new("user");
+        user.update_access_level("+q");
+        user.update_access_level("+a");
+        user.update_access_level("+o");
+        user.update_access_level("+h");
+        user.update_access_level("+v");
+        assert_eq!(user.highest_access_level, Owner);
+        assert_eq!(user.access_levels, vec![Member, Owner, Admin, Oper, HalfOp, Voice]);
+        user.update_access_level("-h");
+        assert_eq!(user.highest_access_level, Owner);
+        assert_eq!(user.access_levels, vec![Member, Owner, Admin, Oper, Voice]);
+        user.update_access_level("-q");
+        assert_eq!(user.highest_access_level, Admin);
+        assert_eq!(user.access_levels, vec![Member, Voice, Admin, Oper]);
+        user.update_access_level("-a");
+        assert_eq!(user.highest_access_level, Oper);
+        assert_eq!(user.access_levels, vec![Member, Voice, Oper]);
+        user.update_access_level("-o");
+        assert_eq!(user.highest_access_level, Voice);
+        assert_eq!(user.access_levels, vec![Member, Voice]);
+        user.update_access_level("-v");
+        assert_eq!(user.highest_access_level, Member);
+        assert_eq!(user.access_levels, vec![Member]);
     }
 }
diff --git a/src/server/mod.rs b/src/server/mod.rs
index be37ec4..4961736 100644
--- a/src/server/mod.rs
+++ b/src/server/mod.rs
@@ -339,7 +339,7 @@ mod test {
 
     #[test]
     fn user_tracking_names_mode() {
-        let value = ":irc.test.net 353 test = #test :test ~owner &admin\r\n\
+        let value = ":irc.test.net 353 test = #test :+test ~owner &admin\r\n\
                      :test!test@test MODE #test +o test\r\n";
         let server = IrcServer::from_connection(test_config(), Connection::new(
             MemReader::new(value.as_bytes().to_vec()), NullWriter
@@ -349,7 +349,14 @@ mod test {
         }
         assert_eq!(server.list_users("#test").unwrap(),
         vec![User::new("@test"), User::new("~owner"), User::new("&admin")]);
-        assert_eq!(server.list_users("#test").unwrap()[0].access_level(),
-        User::new("@test").access_level());
+        let mut exp = User::new("@test");
+        exp.update_access_level("+v");
+        assert_eq!(server.list_users("#test").unwrap()[0].highest_access_level(),
+                   exp.highest_access_level());
+        // The following tests if the maintained user contains the same entries as what is expected
+        // but ignores the ordering of these entries.
+        let mut levels = server.list_users("#test").unwrap()[0].access_levels();
+        levels.retain(|l| exp.access_levels().contains(l));
+        assert_eq!(levels.len(), exp.access_levels().len()); 
     }
 }