Skip to content

Commit

Permalink
Split Users trait into Users and Groups traits
Browse files Browse the repository at this point in the history
It was getting crowded in there! Not only are two groups of six easier to manage than one group of twelve, but the groups functions didn't actually have anything to do with users...
  • Loading branch information
ogham committed Jan 15, 2016
1 parent aa94ee8 commit 052cf24
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 86 deletions.
2 changes: 1 addition & 1 deletion examples/example.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
extern crate users;
use users::{Users, OSUsers};
use users::{Users, Groups, OSUsers};

fn main() {
let cache = OSUsers::empty_cache();
Expand Down
78 changes: 41 additions & 37 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
//! methods on it. For example:
//!
//! ```rust
//! use users::{Users, OSUsers};
//! use users::{Users, Groups, OSUsers};
//! let mut cache = OSUsers::empty_cache();
//! let uid = cache.get_current_uid();
//! let user = cache.get_user_by_uid(uid).unwrap();
Expand All @@ -89,7 +89,7 @@
//! And again, a complete example:
//!
//! ```rust
//! use users::{Users, OSUsers};
//! use users::{Users, Groups, OSUsers};
//! let mut cache = OSUsers::empty_cache();
//! let group = cache.get_group_by_name("admin").expect("No such group 'admin'!");
//! println!("The '{}' group has the ID {}", group.name, group.gid);
Expand Down Expand Up @@ -127,43 +127,47 @@ pub mod mock;
pub mod os;
pub use os::OSUsers;

/// The trait for the `OSUsers` object.
/// Trait for producers of users.
pub trait Users {

/// Return a User object if one exists for the given user ID; otherwise, return None.
/// Returns a User if one exists for the given user ID; otherwise, returns None.
fn get_user_by_uid(&self, uid: uid_t) -> Option<Arc<User>>;

/// Return a User object if one exists for the given username; otherwise, return None.
/// Returns a User if one exists for the given username; otherwise, returns None.
fn get_user_by_name(&self, username: &str) -> Option<Arc<User>>;

/// Return a Group object if one exists for the given group ID; otherwise, return None.
fn get_group_by_gid(&self, gid: gid_t) -> Option<Arc<Group>>;

/// Return a Group object if one exists for the given groupname; otherwise, return None.
fn get_group_by_name(&self, group_name: &str) -> Option<Arc<Group>>;

/// Return the user ID for the user running the process.
/// Returns the user ID for the user running the process.
fn get_current_uid(&self) -> uid_t;

/// Return the username of the user running the process.
/// Returns the username of the user running the process.
fn get_current_username(&self) -> Option<Arc<String>>;

/// Return the group ID for the user running the process.
/// Returns the effective user id.
fn get_effective_uid(&self) -> uid_t;

/// Returns the effective username.
fn get_effective_username(&self) -> Option<Arc<String>>;
}

/// Trait for producers of groups.
pub trait Groups {

/// Returns a Group object if one exists for the given group ID; otherwise, returns None.
fn get_group_by_gid(&self, gid: gid_t) -> Option<Arc<Group>>;

/// Returns a Group object if one exists for the given groupname; otherwise, returns None.
fn get_group_by_name(&self, group_name: &str) -> Option<Arc<Group>>;

/// Returns the group ID for the user running the process.
fn get_current_gid(&self) -> gid_t;

/// Return the group name of the user running the process.
/// Returns the group name of the user running the process.
fn get_current_groupname(&self) -> Option<Arc<String>>;

/// Return the effective user id.
fn get_effective_uid(&self) -> uid_t;

/// Return the effective group id.
/// Returns the effective group id.
fn get_effective_gid(&self) -> gid_t;

/// Return the effective username.
fn get_effective_username(&self) -> Option<Arc<String>>;

/// Return the effective group name.
/// Returns the effective group name.
fn get_effective_groupname(&self) -> Option<Arc<String>>;
}

Expand Down Expand Up @@ -225,8 +229,8 @@ extern {
fn setregid(rgid: gid_t, egid: gid_t) -> c_int;
}

#[derive(Clone)]
/// Information about a particular user.
#[derive(Clone)]
pub struct User {

/// This user's ID
Expand Down Expand Up @@ -312,12 +316,12 @@ unsafe fn members(groups: *const *const c_char) -> Vec<String> {
}


/// Return a User object if one exists for the given user ID; otherwise, return None.
/// Returns a User object if one exists for the given user ID; otherwise, return None.
pub fn get_user_by_uid(uid: uid_t) -> Option<User> {
unsafe { passwd_to_user(getpwuid(uid)) }
}

/// Return a User object if one exists for the given username; otherwise, return None.
/// Returns a User object if one exists for the given username; otherwise, return None.
pub fn get_user_by_name(username: &str) -> Option<User> {
let username_c = CString::new(username);

Expand All @@ -330,12 +334,12 @@ pub fn get_user_by_name(username: &str) -> Option<User> {
unsafe { passwd_to_user(getpwnam(username_c.unwrap().as_ptr())) }
}

/// Return a Group object if one exists for the given group ID; otherwise, return None.
/// Returns a Group object if one exists for the given group ID; otherwise, return None.
pub fn get_group_by_gid(gid: gid_t) -> Option<Group> {
unsafe { struct_to_group(getgrgid(gid)) }
}

/// Return a Group object if one exists for the given groupname; otherwise, return None.
/// Returns a Group object if one exists for the given groupname; otherwise, return None.
pub fn get_group_by_name(group_name: &str) -> Option<Group> {
let group_name_c = CString::new(group_name);

Expand All @@ -348,51 +352,51 @@ pub fn get_group_by_name(group_name: &str) -> Option<Group> {
unsafe { struct_to_group(getgrnam(group_name_c.unwrap().as_ptr())) }
}

/// Return the user ID for the user running the process.
/// Returns the user ID for the user running the process.
pub fn get_current_uid() -> uid_t {
unsafe { getuid() }
}

/// Return the username of the user running the process.
/// Returns the username of the user running the process.
pub fn get_current_username() -> Option<String> {
let uid = get_current_uid();
get_user_by_uid(uid).map(|u| Arc::try_unwrap(u.name).unwrap())
}

/// Return the user ID for the effective user running the process.
/// Returns the user ID for the effective user running the process.
pub fn get_effective_uid() -> uid_t {
unsafe { geteuid() }
}

/// Return the username of the effective user running the process.
/// Returns the username of the effective user running the process.
pub fn get_effective_username() -> Option<String> {
let uid = get_effective_uid();
get_user_by_uid(uid).map(|u| Arc::try_unwrap(u.name).unwrap())
}

/// Return the group ID for the user running the process.
/// Returns the group ID for the user running the process.
pub fn get_current_gid() -> gid_t {
unsafe { getgid() }
}

/// Return the groupname of the user running the process.
/// Returns the groupname of the user running the process.
pub fn get_current_groupname() -> Option<String> {
let gid = get_current_gid();
get_group_by_gid(gid).map(|g| Arc::try_unwrap(g.name).unwrap())
}

/// Return the group ID for the effective user running the process.
/// Returns the group ID for the effective user running the process.
pub fn get_effective_gid() -> gid_t {
unsafe { getegid() }
}

/// Return the groupname of the effective user running the process.
/// Returns the groupname of the effective user running the process.
pub fn get_effective_groupname() -> Option<String> {
let gid = get_effective_gid();
get_group_by_gid(gid).map(|g| Arc::try_unwrap(g.name).unwrap())
}

/// Set current user for the running process, requires root priviledges.
/// Sets current user for the running process, requires root priviledges.
pub fn set_current_uid(uid: uid_t) -> IOResult<()> {
match unsafe { setuid(uid) } {
0 => Ok(()),
Expand Down
32 changes: 17 additions & 15 deletions src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
//! print_current_username(&mut actual_users);
//! ```
pub use super::{Users, User, Group};
pub use super::{Users, Groups, User, Group};
use std::collections::HashMap;
use std::sync::Arc;
use libc::{uid_t, gid_t};
Expand Down Expand Up @@ -96,36 +96,38 @@ impl Users for MockUsers {
self.users.values().find(|u| &*u.name == username).cloned()
}

fn get_group_by_gid(&self, gid: gid_t) -> Option<Arc<Group>> {
self.groups.get(&gid).cloned()
fn get_current_uid(&self) -> uid_t {
self.uid
}

fn get_group_by_name(&self, group_name: &str) -> Option<Arc<Group>> {
self.groups.values().find(|g| &*g.name == group_name).cloned()
fn get_current_username(&self) -> Option<Arc<String>> {
self.users.get(&self.uid).map(|u| u.name.clone())
}

fn get_current_uid(&self) -> uid_t {
fn get_effective_uid(&self) -> uid_t {
self.uid
}

fn get_current_username(&self) -> Option<Arc<String>> {
fn get_effective_username(&self) -> Option<Arc<String>> {
self.users.get(&self.uid).map(|u| u.name.clone())
}
}

fn get_current_gid(&self) -> uid_t {
self.uid
impl Groups for MockUsers {
fn get_group_by_gid(&self, gid: gid_t) -> Option<Arc<Group>> {
self.groups.get(&gid).cloned()
}

fn get_current_groupname(&self) -> Option<Arc<String>> {
self.groups.get(&self.uid).map(|u| u.name.clone())
fn get_group_by_name(&self, group_name: &str) -> Option<Arc<Group>> {
self.groups.values().find(|g| &*g.name == group_name).cloned()
}

fn get_effective_uid(&self) -> uid_t {
fn get_current_gid(&self) -> uid_t {
self.uid
}

fn get_effective_username(&self) -> Option<Arc<String>> {
self.users.get(&self.uid).map(|u| u.name.clone())
fn get_current_groupname(&self) -> Option<Arc<String>> {
self.groups.get(&self.uid).map(|u| u.name.clone())
}

fn get_effective_gid(&self) -> uid_t {
Expand All @@ -139,7 +141,7 @@ impl Users for MockUsers {

#[cfg(test)]
mod test {
use super::{Users, User, Group, MockUsers};
use super::{Users, Groups, User, Group, MockUsers};
use std::sync::Arc;

#[test]
Expand Down
68 changes: 35 additions & 33 deletions src/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::HashMap;
use std::sync::Arc;

use super::{User, Group, Users};
use super::{User, Groups, Group, Users};


/// A producer of user and group instances that caches every result.
Expand Down Expand Up @@ -174,6 +174,40 @@ impl Users for OSUsers {
}
}

fn get_current_uid(&self) -> uid_t {
match self.uid.get() {
Some(uid) => uid,
None => {
let uid = super::get_current_uid();
self.uid.set(Some(uid));
uid
}
}
}

fn get_current_username(&self) -> Option<Arc<String>> {
let uid = self.get_current_uid();
self.get_user_by_uid(uid).map(|u| u.name.clone())
}

fn get_effective_uid(&self) -> uid_t {
match self.euid.get() {
Some(uid) => uid,
None => {
let uid = super::get_effective_uid();
self.euid.set(Some(uid));
uid
}
}
}

fn get_effective_username(&self) -> Option<Arc<String>> {
let uid = self.get_effective_uid();
self.get_user_by_uid(uid).map(|u| u.name.clone())
}
}

impl Groups for OSUsers {
fn get_group_by_gid(&self, gid: gid_t) -> Option<Arc<Group>> {
let mut groups_forward = self.groups.forward.borrow_mut();

Expand Down Expand Up @@ -235,22 +269,6 @@ impl Users for OSUsers {
}
}

fn get_current_uid(&self) -> uid_t {
match self.uid.get() {
Some(uid) => uid,
None => {
let uid = super::get_current_uid();
self.uid.set(Some(uid));
uid
}
}
}

fn get_current_username(&self) -> Option<Arc<String>> {
let uid = self.get_current_uid();
self.get_user_by_uid(uid).map(|u| u.name.clone())
}

fn get_current_gid(&self) -> gid_t {
match self.gid.get() {
Some(gid) => gid,
Expand Down Expand Up @@ -282,20 +300,4 @@ impl Users for OSUsers {
let gid = self.get_effective_gid();
self.get_group_by_gid(gid).map(|g| g.name.clone())
}

fn get_effective_uid(&self) -> uid_t {
match self.euid.get() {
Some(uid) => uid,
None => {
let uid = super::get_effective_uid();
self.euid.set(Some(uid));
uid
}
}
}

fn get_effective_username(&self) -> Option<Arc<String>> {
let uid = self.get_effective_uid();
self.get_user_by_uid(uid).map(|u| u.name.clone())
}
}

0 comments on commit 052cf24

Please sign in to comment.