Completed #3 by taking advantage of new support for capabilities
protocol.
This commit is contained in:
parent
8b72503e7d
commit
afd14cb20a
2 changed files with 67 additions and 29 deletions
|
@ -18,19 +18,23 @@ impl User {
|
|||
/// Creates a new User.
|
||||
#[stable]
|
||||
pub fn new(name: &str) -> User {
|
||||
let rank = from_str(name);
|
||||
let ranks: Vec<_> = AccessLevelIterator::new(name).collect();
|
||||
User {
|
||||
name: if let Some(AccessLevel::Member) = rank {
|
||||
name.into_string()
|
||||
} else {
|
||||
name[1..].into_string()
|
||||
name: name[ranks.len()..].into_string(),
|
||||
access_levels: {
|
||||
let mut ranks = ranks.clone();
|
||||
ranks.push(AccessLevel::Member);
|
||||
ranks
|
||||
},
|
||||
highest_access_level: {
|
||||
let mut max = AccessLevel::Member;
|
||||
for rank in ranks.into_iter() {
|
||||
if rank > max {
|
||||
max = rank
|
||||
}
|
||||
}
|
||||
max
|
||||
},
|
||||
highest_access_level: rank.unwrap(),
|
||||
access_levels: if let Some(AccessLevel::Member) = rank {
|
||||
vec![rank.unwrap()]
|
||||
} else {
|
||||
vec![rank.unwrap(), AccessLevel::Member]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,19 +163,39 @@ impl PartialOrd for AccessLevel {
|
|||
|
||||
impl FromStr for AccessLevel {
|
||||
fn from_str(s: &str) -> Option<AccessLevel> {
|
||||
if s.len() == 0 { Some(AccessLevel::Member) } else {
|
||||
if s.len() == 0 { None } else {
|
||||
Some(match s.char_at(0) {
|
||||
'~' => AccessLevel::Owner,
|
||||
'&' => AccessLevel::Admin,
|
||||
'@' => AccessLevel::Oper,
|
||||
'%' => AccessLevel::HalfOp,
|
||||
'+' => AccessLevel::Voice,
|
||||
_ => AccessLevel::Member,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct AccessLevelIterator<'a> {
|
||||
value: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> AccessLevelIterator<'a> {
|
||||
pub fn new(value: &'a str) -> AccessLevelIterator<'a> {
|
||||
AccessLevelIterator { value: value }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator<AccessLevel> for AccessLevelIterator<'a> {
|
||||
fn next(&mut self) -> Option<AccessLevel> {
|
||||
let ret = from_str(self.value);
|
||||
if self.value.len() > 0 {
|
||||
self.value = self.value[1..];
|
||||
}
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{AccessLevel, User};
|
||||
|
@ -179,13 +203,13 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn access_level_from_str() {
|
||||
assert_eq!(from_str::<AccessLevel>("member").unwrap(), Member);
|
||||
assert!(from_str::<AccessLevel>("member").is_none());
|
||||
assert_eq!(from_str::<AccessLevel>("~owner").unwrap(), Owner);
|
||||
assert_eq!(from_str::<AccessLevel>("&admin").unwrap(), Admin);
|
||||
assert_eq!(from_str::<AccessLevel>("@oper").unwrap(), Oper);
|
||||
assert_eq!(from_str::<AccessLevel>("%halfop").unwrap(), HalfOp);
|
||||
assert_eq!(from_str::<AccessLevel>("+voice").unwrap(), Voice);
|
||||
assert_eq!(from_str::<AccessLevel>("").unwrap(), Member);
|
||||
assert!(from_str::<AccessLevel>("").is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -198,6 +222,21 @@ mod test {
|
|||
};
|
||||
assert_eq!(user, exp);
|
||||
assert_eq!(user.highest_access_level, exp.highest_access_level);
|
||||
assert_eq!(user.access_levels, exp.access_levels);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_user_complex() {
|
||||
let user = User::new("~&+user");
|
||||
let exp = User {
|
||||
name: format!("user"),
|
||||
highest_access_level: Owner,
|
||||
access_levels: vec![Owner, Admin, Voice, Member]
|
||||
};
|
||||
assert_eq!(user, exp);
|
||||
assert_eq!(user.highest_access_level, exp.highest_access_level);
|
||||
assert_eq!(user.access_levels, exp.access_levels);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -240,26 +279,21 @@ mod test {
|
|||
|
||||
#[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");
|
||||
let mut user = User::new("~&@%+user");
|
||||
assert_eq!(user.highest_access_level, Owner);
|
||||
assert_eq!(user.access_levels, vec![Member, Owner, Admin, Oper, HalfOp, Voice]);
|
||||
assert_eq!(user.access_levels, vec![Owner, Admin, Oper, HalfOp, Voice, Member]);
|
||||
user.update_access_level("-h");
|
||||
assert_eq!(user.highest_access_level, Owner);
|
||||
assert_eq!(user.access_levels, vec![Member, Owner, Admin, Oper, Voice]);
|
||||
assert_eq!(user.access_levels, vec![Owner, Admin, Oper, Member, Voice]);
|
||||
user.update_access_level("-q");
|
||||
assert_eq!(user.highest_access_level, Admin);
|
||||
assert_eq!(user.access_levels, vec![Member, Voice, Admin, Oper]);
|
||||
assert_eq!(user.access_levels, vec![Voice, Admin, Oper, Member]);
|
||||
user.update_access_level("-a");
|
||||
assert_eq!(user.highest_access_level, Oper);
|
||||
assert_eq!(user.access_levels, vec![Member, Voice, Oper]);
|
||||
assert_eq!(user.access_levels, vec![Voice, Member, Oper]);
|
||||
user.update_access_level("-o");
|
||||
assert_eq!(user.highest_access_level, Voice);
|
||||
assert_eq!(user.access_levels, vec![Member, Voice]);
|
||||
assert_eq!(user.access_levels, vec![Voice, Member]);
|
||||
user.update_access_level("-v");
|
||||
assert_eq!(user.highest_access_level, Member);
|
||||
assert_eq!(user.access_levels, vec![Member]);
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
|
||||
use std::io::IoResult;
|
||||
use data::{Command, Config, User};
|
||||
use data::command::Command::{INVITE, JOIN, KILL, MODE, NICK, NOTICE, KICK};
|
||||
use data::command::Command::{OPER, PONG, PRIVMSG, SAMODE, SANICK, TOPIC, USER};
|
||||
use data::Command::{CAP, INVITE, JOIN, KILL, MODE, NICK, NOTICE, KICK};
|
||||
use data::Command::{OPER, PONG, PRIVMSG, SAMODE, SANICK, TOPIC, USER};
|
||||
use data::command::CapSubCommand::{END, REQ};
|
||||
use data::kinds::{IrcReader, IrcWriter};
|
||||
use server::{Server, ServerIterator};
|
||||
|
||||
|
@ -43,6 +44,9 @@ impl<'a, T: IrcReader, U: IrcWriter> Wrapper<'a, T, U> {
|
|||
/// Sends a NICK and USER to identify.
|
||||
#[experimental]
|
||||
pub fn identify(&self) -> IoResult<()> {
|
||||
// We'll issue a CAP REQ for multi-prefix support to improve access level tracking.
|
||||
try!(self.server.send(CAP(REQ, Some("multi-prefix"))));
|
||||
try!(self.server.send(CAP(END, None))); // Then, send a CAP END to end the negotiation.
|
||||
try!(self.server.send(NICK(self.server.config().nickname[])));
|
||||
self.server.send(USER(self.server.config().username[], "0",
|
||||
self.server.config().realname[]))
|
||||
|
@ -165,7 +169,7 @@ mod test {
|
|||
wrapper.identify().unwrap();
|
||||
}
|
||||
assert_eq!(get_server_value(server)[],
|
||||
"NICK :test\r\nUSER test 0 * :test\r\n");
|
||||
"CAP REQ :multi-prefix\r\nCAP END\r\nNICK :test\r\nUSER test 0 * :test\r\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Add table
Reference in a new issue