simple-unix-users 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +40 -0
- data/Rakefile +1 -0
- data/lib/simple-unix-users.rb +22 -0
- data/lib/simple-unix-users/user.rb +40 -0
- data/lib/simple-unix-users/users.rb +78 -0
- data/lib/simple-unix-users/version.rb +3 -0
- data/simple-unix-users.gemspec +23 -0
- data/spec/simple-unix-users/passwd-sample +38 -0
- data/spec/simple-unix-users/user_spec.rb +41 -0
- data/spec/simple-unix-users/users_spec.rb +79 -0
- metadata +62 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Keith R. Bennett
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# SimpleUnixUsers
|
2
|
+
|
3
|
+
Reads and parses user information from /etc/passwd or a specified
|
4
|
+
filespec, and provides simple operations on the collection of users,
|
5
|
+
and individual users.
|
6
|
+
|
7
|
+
This code was written as an example of something Ruby could be useful
|
8
|
+
for when administering a Unix system.
|
9
|
+
|
10
|
+
It's just a starting point, and lacks necessary error checking and
|
11
|
+
polish.
|
12
|
+
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Add this line to your application's Gemfile:
|
17
|
+
|
18
|
+
gem 'simple-unix-users'
|
19
|
+
|
20
|
+
And then execute:
|
21
|
+
|
22
|
+
$ bundle
|
23
|
+
|
24
|
+
Or install it yourself as:
|
25
|
+
|
26
|
+
$ gem install simple-unix-users
|
27
|
+
:w
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
require 'simple-unix-users'
|
33
|
+
|
34
|
+
users = Users.new
|
35
|
+
# or
|
36
|
+
users = Users.new('my-test-passwd-file')
|
37
|
+
```
|
38
|
+
|
39
|
+
Then you can use the services provided by the Users and User classes.
|
40
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "simple-unix-users/version"
|
2
|
+
|
3
|
+
if /darwin/ === RUBY_PLATFORM
|
4
|
+
$stderr.puts "
|
5
|
+
|
6
|
+
A message from the simple-unix-users gem...
|
7
|
+
|
8
|
+
Although simple-unix-users will read a passwd file on Mac OS,
|
9
|
+
it is not guaranteed to work correctly. In addition, according to the Mac's
|
10
|
+
/etc/passwd file:
|
11
|
+
|
12
|
+
# Note that this file is consulted directly only when the system is running
|
13
|
+
# in single-user mode. At other times this information is provided by
|
14
|
+
# Open Directory.
|
15
|
+
|
16
|
+
"
|
17
|
+
end
|
18
|
+
|
19
|
+
module SimpleUnixUsers
|
20
|
+
require_relative 'simple-unix-users/user'
|
21
|
+
require_relative 'simple-unix-users/users'
|
22
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# This class is for illustrative purposes and lacks necessary error handling.
|
2
|
+
|
3
|
+
# Stores state, and provides some useful behavior, relating to a given user.
|
4
|
+
class User
|
5
|
+
|
6
|
+
attr_accessor :name, :dummy_pw, :uid, :gid, :personal_data, :home_dir, :shell
|
7
|
+
|
8
|
+
NULL_SHELL = '/bin/false'
|
9
|
+
NULL_HOME_DIR = '/nonexistent'
|
10
|
+
|
11
|
+
def initialize(line)
|
12
|
+
@name, @dummy_pw, @uid, @gid, p_data, @home_dir, @shell = line.chomp.split(':')
|
13
|
+
@personal_data = p_data.split(',')
|
14
|
+
end
|
15
|
+
|
16
|
+
def uid_number
|
17
|
+
uid.to_i
|
18
|
+
end
|
19
|
+
|
20
|
+
def gid_number
|
21
|
+
gid.to_i
|
22
|
+
end
|
23
|
+
|
24
|
+
def home_dir_size_in_mb
|
25
|
+
`du -sm #{home_dir}`.to_i
|
26
|
+
end
|
27
|
+
|
28
|
+
def has_shell?
|
29
|
+
shell != NULL_SHELL
|
30
|
+
end
|
31
|
+
|
32
|
+
def has_home_dir?
|
33
|
+
home_dir != NULL_HOME_DIR
|
34
|
+
end
|
35
|
+
|
36
|
+
def groups
|
37
|
+
`groups #{name}`.chomp.split(':').last.strip.split(' ')
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require_relative 'user'
|
2
|
+
|
3
|
+
# This class is for illustrative purposes and lacks necessary error handling.
|
4
|
+
|
5
|
+
# Manages a collection of users (instances of class 'User'),
|
6
|
+
# optionally loaded from /etc/passwd.
|
7
|
+
class Users < Array
|
8
|
+
|
9
|
+
# Reads the user information from the passwd file, and returns
|
10
|
+
# a Users instance.
|
11
|
+
def self.from_passwd_file(filespec = '/etc/passwd')
|
12
|
+
file_lines = File.readlines(filespec)
|
13
|
+
non_comment_lines = file_lines.reject { |line| /^#/ === line }
|
14
|
+
Users.new(non_comment_lines)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Constructor; takes an array of passwd-formatted lines, or
|
18
|
+
# User instances, or any combination thereof.
|
19
|
+
def initialize(array)
|
20
|
+
array.each do |element|
|
21
|
+
user = element.is_a?(String) ? User.new(element) : element
|
22
|
+
self << user
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Methods that will return arrays of field objects (e.g. names).
|
27
|
+
def names; self.map(&:name) end
|
28
|
+
def uids; self.map(&:uid) end
|
29
|
+
def gids; self.map(&:gid) end
|
30
|
+
def personal_datas; self.map(&:personal_data) end
|
31
|
+
def home_dirs; self.map(&:home_dir) end
|
32
|
+
def shells; self.map(&:shell) end
|
33
|
+
|
34
|
+
def uid_numbers; self.map(&:uid_number) end
|
35
|
+
def gid_numbers; self.map(&:gid_number) end
|
36
|
+
|
37
|
+
# Returns a new instance of Users containing only those users
|
38
|
+
# whose shell is not '/bin/false'.
|
39
|
+
def having_shell
|
40
|
+
Users.new(select { |user| user.has_shell? })
|
41
|
+
end
|
42
|
+
|
43
|
+
def having_shell_of(shell)
|
44
|
+
Users.new(select { |user| user.shell == shell })
|
45
|
+
end
|
46
|
+
|
47
|
+
def not_having_shell
|
48
|
+
Users.new(self - having_shell)
|
49
|
+
end
|
50
|
+
|
51
|
+
def having_home_dir
|
52
|
+
Users.new(select { |user| user.has_home_dir? })
|
53
|
+
end
|
54
|
+
|
55
|
+
def not_having_home_dir
|
56
|
+
Users.new(select { |user| ! user.has_home_dir? })
|
57
|
+
# or, less efficiently: Users.new(self - having_home_dir)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns a new Users instance consisting only of
|
61
|
+
# those users having the specified group id.
|
62
|
+
def having_gid(gid)
|
63
|
+
gid = (gid.is_a?(Fixnum) ? gid.to_s : gid)
|
64
|
+
filtered_array = (select { |user| user.gid == gid })
|
65
|
+
Users.new(filtered_array)
|
66
|
+
end
|
67
|
+
|
68
|
+
def find_by_name(name)
|
69
|
+
detect { |user| user.name == name }
|
70
|
+
end
|
71
|
+
|
72
|
+
def find_by_uid(uid)
|
73
|
+
uid = uid.is_a?(String) ? uid : uid.to_s
|
74
|
+
detect { |user| user.uid == uid }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'simple-unix-users/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "simple-unix-users"
|
8
|
+
gem.version = SimpleUnixUsers::VERSION
|
9
|
+
gem.authors = ["Keith R. Bennett"]
|
10
|
+
gem.email = ["keithrbennett@gmail.com"]
|
11
|
+
gem.description = %q{
|
12
|
+
Reads and parses user information from /etc/passwd or a specified
|
13
|
+
filespec, and provides simple operations on the collection of users,
|
14
|
+
and individual users.
|
15
|
+
}
|
16
|
+
gem.summary = %q{Manages Unix user information based on the content of /etc/passwd.}
|
17
|
+
gem.homepage = "https://github.com/keithrbennett/simple-unix-users"
|
18
|
+
|
19
|
+
gem.files = `git ls-files`.split($/)
|
20
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
21
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
22
|
+
gem.require_paths = ["lib"]
|
23
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
root:x:0:0:root:/root:/bin/bash
|
2
|
+
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
|
3
|
+
bin:x:2:2:bin:/bin:/bin/sh
|
4
|
+
sys:x:3:3:sys:/dev:/bin/sh
|
5
|
+
sync:x:4:65534:sync:/bin:/bin/sync
|
6
|
+
games:x:5:60:games:/usr/games:/bin/sh
|
7
|
+
man:x:6:12:man:/var/cache/man:/bin/sh
|
8
|
+
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
|
9
|
+
mail:x:8:8:mail:/var/mail:/bin/sh
|
10
|
+
news:x:9:9:news:/var/spool/news:/bin/sh
|
11
|
+
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
|
12
|
+
proxy:x:13:13:proxy:/bin:/bin/sh
|
13
|
+
www-data:x:33:33:www-data:/var/www:/bin/sh
|
14
|
+
backup:x:34:34:backup:/var/backups:/bin/sh
|
15
|
+
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
|
16
|
+
irc:x:39:39:ircd:/var/run/ircd:/bin/sh
|
17
|
+
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
|
18
|
+
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
|
19
|
+
libuuid:x:100:101::/var/lib/libuuid:/bin/sh
|
20
|
+
syslog:x:101:103::/home/syslog:/bin/false
|
21
|
+
messagebus:x:102:105::/var/run/dbus:/bin/false
|
22
|
+
colord:x:103:108:colord colour management daemon,,,:/var/lib/colord:/bin/false
|
23
|
+
whoopsie:x:105:114::/nonexistent:/bin/false
|
24
|
+
avahi-autoipd:x:106:117:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/bin/false
|
25
|
+
avahi:x:107:118:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/bin/false
|
26
|
+
usbmux:x:108:46:usbmux daemon,,,:/home/usbmux:/bin/false
|
27
|
+
kernoops:x:109:65534:Kernel Oops Tracking Daemon,,,:/:/bin/false
|
28
|
+
pulse:x:110:119:PulseAudio daemon,,,:/var/run/pulse:/bin/false
|
29
|
+
rtkit:x:111:122:RealtimeKit,,,:/proc:/bin/false
|
30
|
+
speech-dispatcher:x:112:29:Speech Dispatcher,,,:/var/run/speech-dispatcher:/bin/sh
|
31
|
+
hplip:x:113:7:HPLIP system user,,,:/var/run/hplip:/bin/false
|
32
|
+
saned:x:114:123::/home/saned:/bin/false
|
33
|
+
haldaemon:x:115:125:Hardware abstraction layer,,,:/var/run/hald:/bin/false
|
34
|
+
mdm:x:116:128:MDM Display Manager:/var/lib/mdm:/bin/false
|
35
|
+
kbennett:x:1000:1000:Keith Bennett,,,:/home/kbennett:/usr/bin/zsh
|
36
|
+
sshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin
|
37
|
+
mysql:x:117:129:MySQL Server,,,:/nonexistent:/bin/false
|
38
|
+
postgres:x:118:130:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
|
3
|
+
require_relative '../../lib/simple-unix-users/user'
|
4
|
+
|
5
|
+
describe User do
|
6
|
+
|
7
|
+
subject { User.new( 'kbennett:x:1000:1000:Keith Bennett,,,:/home/kbennett:/usr/bin/zsh') }
|
8
|
+
|
9
|
+
it 'should create correctly from the passwd line' do
|
10
|
+
subject.class.should == User
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should create fields correctly' do
|
14
|
+
subject.name.should == 'kbennett'
|
15
|
+
subject.uid.should == '1000'
|
16
|
+
subject.gid.should == '1000'
|
17
|
+
subject.personal_data.first.should == 'Keith Bennett'
|
18
|
+
subject.home_dir.should == '/home/kbennett'
|
19
|
+
subject.shell.should == '/usr/bin/zsh'
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should detect an existing home correctly' do
|
23
|
+
subject.has_home_dir?.should be_true
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should detect a nonexistent home correctly' do
|
27
|
+
subject.home_dir = User::NULL_HOME_DIR
|
28
|
+
subject.has_home_dir?.should be_false
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should calculate uid_number correctly' do
|
32
|
+
subject.uid_number.should == subject.uid.to_i
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should calculate gid_number correctly' do
|
36
|
+
subject.gid_number.should == subject.gid.to_i
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
|
3
|
+
require_relative '../../lib/simple-unix-users/users.rb'
|
4
|
+
|
5
|
+
describe Users do
|
6
|
+
|
7
|
+
subject { Users.from_passwd_file(File.join(File.dirname(__FILE__), 'passwd-sample')) }
|
8
|
+
|
9
|
+
it 'should load a list of users' do
|
10
|
+
subject.should be_a Array
|
11
|
+
subject.should_not be_empty
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should return a list of names for the names function' do
|
15
|
+
names = subject.names.sort
|
16
|
+
names.sort.uniq.size.should > 1
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should be able to get uids as numbers' do
|
20
|
+
uid_numbers = subject.uid_numbers
|
21
|
+
uid_numbers.should_not be_empty
|
22
|
+
uid_numbers.first.should be_a(Fixnum)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should be able to get gids as numbers' do
|
26
|
+
gid_numbers = subject.gid_numbers
|
27
|
+
gid_numbers.should_not be_empty
|
28
|
+
gid_numbers.first.should be_a(Fixnum)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should be able to get the field objects arrays' do
|
32
|
+
[:names, :uids, :gids, :personal_datas, :home_dirs, :shells].each do |field|
|
33
|
+
array = subject.send(field)
|
34
|
+
array.size.should == subject.size
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should calculate having_shell correctly' do
|
39
|
+
num_with_shell = subject.inject(0) do |num, user|
|
40
|
+
num += 1 if user.has_shell?
|
41
|
+
num
|
42
|
+
end
|
43
|
+
subject.having_shell.size.should == num_with_shell
|
44
|
+
subject.not_having_shell.size.should == (subject.size - num_with_shell)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should correctly include users in having_shell_of' do
|
48
|
+
first_user = subject.first
|
49
|
+
subject.having_shell_of(first_user.shell).should include(first_user)
|
50
|
+
subject.having_shell_of('ja;ksdfja;sdfkajsdf;k').should_not include(first_user)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should correctly include users in having_home and not_having_home' do
|
54
|
+
user_with_home_dir = subject.detect { |user| user.has_home_dir? }
|
55
|
+
subject.having_home_dir.should include(user_with_home_dir)
|
56
|
+
subject.not_having_home_dir.should_not include(user_with_home_dir)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should correctly find users with having_gid' do
|
60
|
+
first_gid = subject.first.gid
|
61
|
+
having_first_gid = subject.having_gid(first_gid)
|
62
|
+
having_first_gid.should include(subject.first)
|
63
|
+
|
64
|
+
first_user_with_different_gid = subject.detect { |user| user.gid != first_gid }
|
65
|
+
having_first_gid.should_not include(first_user_with_different_gid)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should find_by_name correctly' do
|
69
|
+
last_user = subject.last
|
70
|
+
subject.find_by_name(last_user.name).should == last_user
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should find_by_uid correctly' do
|
74
|
+
last_user = subject.last
|
75
|
+
subject.find_by_uid(last_user.uid).should == last_user
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple-unix-users
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Keith R. Bennett
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-11-15 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: ! "\nReads and parses user information from /etc/passwd or a specified\nfilespec,
|
15
|
+
and provides simple operations on the collection of users,\nand individual users.\n "
|
16
|
+
email:
|
17
|
+
- keithrbennett@gmail.com
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .gitignore
|
23
|
+
- Gemfile
|
24
|
+
- LICENSE.txt
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- lib/simple-unix-users.rb
|
28
|
+
- lib/simple-unix-users/user.rb
|
29
|
+
- lib/simple-unix-users/users.rb
|
30
|
+
- lib/simple-unix-users/version.rb
|
31
|
+
- simple-unix-users.gemspec
|
32
|
+
- spec/simple-unix-users/passwd-sample
|
33
|
+
- spec/simple-unix-users/user_spec.rb
|
34
|
+
- spec/simple-unix-users/users_spec.rb
|
35
|
+
homepage: https://github.com/keithrbennett/simple-unix-users
|
36
|
+
licenses: []
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
requirements: []
|
54
|
+
rubyforge_project:
|
55
|
+
rubygems_version: 1.8.24
|
56
|
+
signing_key:
|
57
|
+
specification_version: 3
|
58
|
+
summary: Manages Unix user information based on the content of /etc/passwd.
|
59
|
+
test_files:
|
60
|
+
- spec/simple-unix-users/passwd-sample
|
61
|
+
- spec/simple-unix-users/user_spec.rb
|
62
|
+
- spec/simple-unix-users/users_spec.rb
|