rubynas 0.1.0.pre.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. data/.gitignore +23 -0
  2. data/.gitmodules +3 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +4 -0
  6. data/Gemfile.lock +196 -0
  7. data/Guardfile +8 -0
  8. data/LICENSE.txt +7 -0
  9. data/Procfile +2 -0
  10. data/README.md +151 -0
  11. data/Rakefile +14 -0
  12. data/Vagrantfile +99 -0
  13. data/bin/rubynas +63 -0
  14. data/config.ru +5 -0
  15. data/doc/README_FOR_APP +2 -0
  16. data/doc/macosx_shares.png +0 -0
  17. data/doc/shares_overview.png +0 -0
  18. data/lib/rubynas.rb +35 -0
  19. data/lib/rubynas/apis/group_api.rb +51 -0
  20. data/lib/rubynas/apis/system_information_api.rb +13 -0
  21. data/lib/rubynas/apis/user_api.rb +85 -0
  22. data/lib/rubynas/apis/volume_api.rb +50 -0
  23. data/lib/rubynas/config.rb +63 -0
  24. data/lib/rubynas/db/migrate/20130302164415_devise_create_users.rb +46 -0
  25. data/lib/rubynas/db/migrate/20130322143040_create_volumes.rb +10 -0
  26. data/lib/rubynas/db/migrate/20130331102556_create_shared_folders.rb +10 -0
  27. data/lib/rubynas/db/migrate/20130331103034_create_shared_folder_services.rb +11 -0
  28. data/lib/rubynas/installers/base_installer.rb +70 -0
  29. data/lib/rubynas/installers/debian_installer.rb +199 -0
  30. data/lib/rubynas/installers/ubuntu_installer.rb +2 -0
  31. data/lib/rubynas/installers/ubuntu_precise_installer.rb +2 -0
  32. data/lib/rubynas/models/.gitkeep +0 -0
  33. data/lib/rubynas/models/ldap_group.rb +21 -0
  34. data/lib/rubynas/models/ldap_org_unit.rb +13 -0
  35. data/lib/rubynas/models/ldap_user.rb +31 -0
  36. data/lib/rubynas/models/shared_folder.rb +32 -0
  37. data/lib/rubynas/models/shared_folder_service.rb +15 -0
  38. data/lib/rubynas/models/volume.rb +16 -0
  39. data/lib/rubynas/services/afp_share_service.rb +9 -0
  40. data/lib/rubynas/services/service.rb +4 -0
  41. data/lib/rubynas/services/share_service.rb +3 -0
  42. data/lib/rubynas/version.rb +3 -0
  43. data/rubynas.gemspec +69 -0
  44. data/rubynas.ini +24 -0
  45. data/sandbox/ldap/base.ldif +50 -0
  46. data/sandbox/ldap/data/.gitkeep +0 -0
  47. data/sandbox/ldap/data/dc=rubynas,dc=com.ldif +14 -0
  48. data/sandbox/ldap/local.schema +6 -0
  49. data/sandbox/ldap/schema/README +80 -0
  50. data/sandbox/ldap/schema/apple.schema +1727 -0
  51. data/sandbox/ldap/schema/apple_auxillary.schema +20 -0
  52. data/sandbox/ldap/schema/collective.ldif +48 -0
  53. data/sandbox/ldap/schema/collective.schema +190 -0
  54. data/sandbox/ldap/schema/corba.ldif +42 -0
  55. data/sandbox/ldap/schema/corba.schema +239 -0
  56. data/sandbox/ldap/schema/core.ldif +591 -0
  57. data/sandbox/ldap/schema/core.schema +610 -0
  58. data/sandbox/ldap/schema/cosine.ldif +200 -0
  59. data/sandbox/ldap/schema/cosine.schema +2571 -0
  60. data/sandbox/ldap/schema/duaconf.ldif +83 -0
  61. data/sandbox/ldap/schema/duaconf.schema +261 -0
  62. data/sandbox/ldap/schema/dyngroup.ldif +71 -0
  63. data/sandbox/ldap/schema/dyngroup.schema +91 -0
  64. data/sandbox/ldap/schema/fmserver.schema +60 -0
  65. data/sandbox/ldap/schema/inetorgperson.ldif +69 -0
  66. data/sandbox/ldap/schema/inetorgperson.schema +155 -0
  67. data/sandbox/ldap/schema/java.ldif +59 -0
  68. data/sandbox/ldap/schema/java.schema +403 -0
  69. data/sandbox/ldap/schema/krb5-kdc.schema +134 -0
  70. data/sandbox/ldap/schema/microsoft.ext.schema +5383 -0
  71. data/sandbox/ldap/schema/microsoft.schema +4835 -0
  72. data/sandbox/ldap/schema/microsoft.std.schema +480 -0
  73. data/sandbox/ldap/schema/misc.ldif +45 -0
  74. data/sandbox/ldap/schema/misc.schema +75 -0
  75. data/sandbox/ldap/schema/netinfo.schema +240 -0
  76. data/sandbox/ldap/schema/nis.ldif +120 -0
  77. data/sandbox/ldap/schema/nis.schema +241 -0
  78. data/sandbox/ldap/schema/openldap.ldif +88 -0
  79. data/sandbox/ldap/schema/openldap.schema +54 -0
  80. data/sandbox/ldap/schema/pmi.ldif +123 -0
  81. data/sandbox/ldap/schema/pmi.schema +464 -0
  82. data/sandbox/ldap/schema/ppolicy.ldif +75 -0
  83. data/sandbox/ldap/schema/ppolicy.schema +531 -0
  84. data/sandbox/ldap/schema/samba.schema +179 -0
  85. data/sandbox/ldap/slapd.conf +99 -0
  86. data/spec/apis/group_api_spec.rb +97 -0
  87. data/spec/apis/system_information_api_spec.rb +27 -0
  88. data/spec/apis/user_api_spec.rb +113 -0
  89. data/spec/apis/volume_api_spec.rb +98 -0
  90. data/spec/factories/ldap_group.rb +16 -0
  91. data/spec/factories/ldap_users.rb +24 -0
  92. data/spec/factories/shared_folder_services.rb +9 -0
  93. data/spec/factories/shared_folders.rb +15 -0
  94. data/spec/factories/users.rb +8 -0
  95. data/spec/factories/volumes.rb +10 -0
  96. data/spec/installer/base_installer_spec.rb +35 -0
  97. data/spec/installer/debian_installer_spec.rb +86 -0
  98. data/spec/models/ldap_group_spec.rb +21 -0
  99. data/spec/models/ldap_org_unit_spec.rb +19 -0
  100. data/spec/models/ldap_user_spec.rb +19 -0
  101. data/spec/models/shared_folder_service_spec.rb +25 -0
  102. data/spec/models/shared_folder_spec.rb +27 -0
  103. data/spec/models/volume_spec.rb +5 -0
  104. data/spec/services/afp_share_service_spec.rb +5 -0
  105. data/spec/services/service_spec.rb +5 -0
  106. data/spec/services/share_service_spec.rb +5 -0
  107. data/spec/spec_helper.rb +30 -0
  108. data/spec/support/db_cleaner.rb +16 -0
  109. data/spec/support/factory_girl.rb +7 -0
  110. data/spec/support/logger.rb +1 -0
  111. data/spec/support/rack-test.rb +6 -0
  112. metadata +633 -0
@@ -0,0 +1,11 @@
1
+ class CreateSharedFolderServices < ActiveRecord::Migration
2
+ def change
3
+ create_table :shared_folder_services do |t|
4
+ t.references :shared_folder
5
+ t.string :service_class
6
+ t.text :options
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,70 @@
1
+ require 'resolv'
2
+ require 'foreman'
3
+ require 'foreman/cli'
4
+
5
+ class BaseInstaller
6
+ ROOT_USER_ID = 0
7
+
8
+ class InstallError < StandardError; end
9
+ class ConfigurationError < InstallError; end
10
+ class PackageError < InstallError; end
11
+
12
+ INSTALL_ORDER = [ :prepare_install, :configure_ldap, :install_ldap,
13
+ :configure_pam_auth, :install_pam_auth, :configure_app,
14
+ :install_app ]
15
+
16
+ attr_reader :domain, :admin, :password
17
+
18
+ # @param [String] domain the domain for the rubynas like 'rubynas.com'
19
+ # @param [String] admin the admin user for the ldap
20
+ # @param [String] password the admin user password
21
+ def initialize(domain, admin, password)
22
+ @domain = domain
23
+ @admin = admin
24
+ @password = password
25
+ end
26
+
27
+ # @return [Array<String>] a list of domain parts
28
+ def domain_parts
29
+ @domain_parts ||= Resolv::DNS::Name.create(domain).to_a.map(&:to_s)
30
+ end
31
+
32
+ # @return [String]
33
+ def ldap_base
34
+ domain_parts.map { |s| "dc=#{s}" }.join(",")
35
+ end
36
+
37
+ # @return [String]
38
+ def admin_ldap_dn
39
+ "cn=#{admin},#{ldap_base}"
40
+ end
41
+
42
+ # @return [Boolean] if the current user is root
43
+ def root?
44
+ Process.uid == ROOT_USER_ID
45
+ end
46
+
47
+ def log(line)
48
+ STDOUT.puts line
49
+ Rubynas.logger.info "[#{self.class.name}] #{line}"
50
+ end
51
+
52
+ # Path to the rubynas executable
53
+ # @return [String]
54
+ def rubynas
55
+ File.expand_path('../../../../bin/rubynas', __FILE__)
56
+ end
57
+
58
+ # Executes the installation
59
+ def run
60
+ log "Start install of #{Rubynas::VERSION}"
61
+ INSTALL_ORDER.each do |method|
62
+ send(method) if respond_to? method
63
+ end
64
+ rescue InstallError => ex
65
+ log "Error: #{ex}"
66
+ raise ex
67
+ ensure
68
+ log "Installation ended"
69
+ end
70
+ end
@@ -0,0 +1,199 @@
1
+ require 'etc'
2
+ require 'tempfile'
3
+ require 'fileutils'
4
+
5
+ class DebianInstaller < BaseInstaller
6
+ include FileUtils
7
+
8
+ def prepare_install
9
+ log "Updating the package repository"
10
+ unless system('apt-get update')
11
+ raise InstallError, "Failed to update the package repository"
12
+ end
13
+ end
14
+
15
+ def install(*packages)
16
+ log "Installing #{packages.join(', ')}"
17
+ ENV['DEBIAN_FRONTEND'] = 'noninteractive'
18
+ unless system("apt-get install -y #{packages.join(' ')}")
19
+ raise PackageError, "Failed to install packages #{packages.join(", ")}"
20
+ end
21
+ end
22
+
23
+ def restart_service(service)
24
+ log "Start service rubynas"
25
+ unless system('service rubynas restart')
26
+ raise InstallError, "Failed to start service"
27
+ end
28
+ end
29
+
30
+ def debconf(category, key, type, value)
31
+ case type
32
+ when :password, :string, :select
33
+ value = value.to_s
34
+ when :boolean
35
+ value = value ? true : false
36
+ when :multiselect
37
+ value = value.join(', ')
38
+ end
39
+
40
+ IO.popen("debconf-set-selections", 'w') do |io|
41
+ io.write "'#{category}' '#{key}' #{type} '#{value}'"
42
+ end
43
+ log "Configuring #{category} - #{key}"
44
+ unless $?.exited?
45
+ raise ConfigurationError, "Failed to configure #{category} (#{key})"
46
+ end
47
+ end
48
+
49
+ # Returns the ruby executable
50
+ def ruby
51
+ "ruby1.9.3 -S"
52
+ end
53
+
54
+ def configure_ldap
55
+ log 'Configure LDAP'
56
+ debconf 'slapd', 'slapd/internal/generated_adminpw', :password, @password
57
+ debconf 'slapd', 'slapd/password2', :password, @password
58
+ debconf 'slapd', 'slapd/internal/adminpw', :password, @password
59
+ debconf 'slapd', 'slapd/password1', :password, @password
60
+ debconf 'slapd', 'slapd/allow_ldap_v2', :boolean, true
61
+ debconf 'slapd', 'slapd/invalid_config', :boolean, true
62
+ debconf 'slapd', 'shared/organization', :string, @domain
63
+ debconf 'slapd', 'slapd/no_configuration', :boolean, false
64
+ debconf 'slapd', 'slapd/move_old_database', :boolean, true
65
+ debconf 'slapd', 'slapd/dump_database_destdir', :string,
66
+ '/var/backups/slapd-VERSION'
67
+ debconf 'slapd', 'slapd/purge_database', :boolean, true
68
+ debconf 'slapd', 'slapd/domain', :string, @domain
69
+ debconf 'slapd', 'slapd/backend', :string, 'HDB'
70
+ end
71
+
72
+ def install_ldap
73
+ install 'ldap-utils', 'slapd'
74
+ end
75
+
76
+ def configure_pam_auth
77
+ log 'Configure ldap with pam (authentication)'
78
+ debconf 'libnss-ldapd', 'libnss-ldapd/nsswitch', :multiselect,
79
+ [:passwd, :group, :shadow]
80
+ debconf 'libpam-ldapd', 'libpam-ldapd/enable_shadow', :boolean, true
81
+ debconf 'libnss-ldapd', 'libnss-ldapd/clean_nsswitch', :boolean, false
82
+
83
+ log 'Configure the authentication daemon for ldap and pam auth'
84
+ debconf 'nslcd', 'nslcd/ldap-starttls', :boolean, false
85
+ debconf 'nslcd', 'nslcd/ldap-sasl-krb5-ccname', :string,
86
+ '/var/run/nslcd/nslcd.tkt'
87
+ debconf 'nslcd', 'nslcd/ldap-auth-type', :select, 'none'
88
+ debconf 'nslcd', 'nslcd/ldap-uris', :string, 'ldapi:///'
89
+ debconf 'nslcd', 'nslcd/ldap-base', :string, ldap_base
90
+ debconf 'nslcd', 'nslcd/ldap-binddn', :string, admin_ldap_dn
91
+ debconf 'nslcd', 'nslcd/ldap-bindpw', :password, @password
92
+ end
93
+
94
+ def install_pam_auth
95
+ install 'libnss-ldapd', 'libpam-ldapd', 'nslcd'
96
+ end
97
+
98
+ def install_app
99
+ create_rubynas_user
100
+ create_directories
101
+ create_configuration
102
+ create_upstart_script
103
+ migrate_database
104
+ restart_service :rubynas
105
+ end
106
+
107
+ private
108
+
109
+ def create_rubynas_user
110
+ begin
111
+ Etc.getpwnam('rubynas')
112
+ rescue ArgumentError => ex
113
+ log "Create rubynas user"
114
+ system 'useradd rubynas --system --no-create-home'
115
+ end
116
+ end
117
+
118
+ def create_directories
119
+ log "Create directories"
120
+ mkdir_p '/var/lib/rubynas/'
121
+ end
122
+
123
+ def create_configuration
124
+ if File.exist? '/etc/rubynas.ini'
125
+ log "The configuration rubynas.ini already exist!"
126
+ else
127
+ log "Create rubynas.ini"
128
+ File.open('/etc/rubynas.ini', 'w') do |f|
129
+ config = <<-CONF
130
+ ;
131
+ ; This is the configuration file for local development and testing.
132
+ ;
133
+
134
+ ; Configuration for the sqlite3 database
135
+ [Database]
136
+ path = %s
137
+ timeout = 5000
138
+ pool = 5
139
+
140
+ ; Configuration for the ldap server that is used for authentication,
141
+ ; user and group management
142
+ [Ldap]
143
+ host = 127.0.0.1
144
+ port = 389
145
+ base = "%s"
146
+ bind_dn = "%s"
147
+ password = %s
148
+
149
+ ; Server related configuration
150
+ [Server]
151
+ ; if syslog set to false it will be logged to stdout
152
+ syslog = true
153
+ ; NOTHING HERE YET
154
+ CONF
155
+ f.puts config.gsub(/^\s+/, "") % [
156
+ db_path,
157
+ ldap_base,
158
+ admin_ldap_dn,
159
+ password
160
+ ]
161
+ end
162
+ end
163
+ end
164
+
165
+ def create_upstart_script
166
+ # Create a rubynas upstart script
167
+ Tempfile.open('env') do |fe|
168
+ %w(GEM_HOME GEM_PATH PATH).each do |name|
169
+ fe.puts "#{name}=#{ENV[name]}" if ENV[name]
170
+ end
171
+ fe.flush
172
+
173
+ Tempfile.open('Procfile') do |fp|
174
+ fp.puts "api: exec #{ruby} #{rubynas} server"
175
+ fp.close
176
+
177
+ Foreman::CLI.start [
178
+ 'export', '--app', 'rubynas', '--env', fe.path,
179
+ '--procfile', fp.path, 'upstart', '/etc/init'
180
+ ]
181
+ end
182
+ end
183
+ end
184
+
185
+ def migrate_database
186
+ log "Migrate the database"
187
+ unless system("#{ruby} #{rubynas} migrate")
188
+ raise InstallError, "Failed to migrate the database"
189
+ end
190
+
191
+ log "Allow access to database by rubynas user"
192
+ user = Etc.getpwnam('rubynas')
193
+ chown user.uid, user.gid, db_path
194
+ end
195
+
196
+ def db_path
197
+ '/var/lib/rubynas/sqlite3.db'
198
+ end
199
+ end
@@ -0,0 +1,2 @@
1
+ class UbuntuInstaller < DebianInstaller
2
+ end
@@ -0,0 +1,2 @@
1
+ class UbuntuPreciseInstaller < UbuntuInstaller
2
+ end
File without changes
@@ -0,0 +1,21 @@
1
+ class LdapGroup < ActiveLdap::Base
2
+ ldap_mapping :dn_attribute => 'cn', :prefix => 'ou=groups',
3
+ :classes => ['top', 'posixGroup']
4
+
5
+ # Associate with primary belonged users
6
+ has_many :primary_members, :foreign_key => 'gidNumber',
7
+ :class_name => "LdapUser", :primary_key => 'gidNumber'
8
+
9
+ # Associate with all belonged users
10
+ has_many :members, :wrap => "memberUid",
11
+ :class_name => "LdapUser", :primary_key => 'uid'
12
+
13
+ # Creates or finds the admin group. The common name has to be 'Administrators'
14
+ # @return [LdapGroup]
15
+ def self.find_or_create_administrators
16
+ group = LdapGroup.find('Administrators') rescue nil
17
+ group ||= LdapGroup.create :common_name => "Administrators",
18
+ :gid_number => 0
19
+ group
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ class LdapOrgUnit < ActiveLdap::Base
2
+ ldap_mapping dn_attribute: "ou", :classes => ['organizationalUnit'],
3
+ :scope => :sub, :prefix => ""
4
+
5
+ # Creates or finds a unit by name
6
+ # @param [String] name the name of the unit (ou) to find or create
7
+ # @return [LdapOrgUnit]
8
+ def self.find_or_create(name)
9
+ unit = LdapOrgUnit.find(name) rescue nil
10
+ unit ||= LdapOrgUnit.create(:ou => name)
11
+ unit
12
+ end
13
+ end
@@ -0,0 +1,31 @@
1
+ class LdapUser < ActiveLdap::Base
2
+ ldap_mapping :dn_attribute => 'cn', :scope => :one,
3
+ :prefix => 'ou=users', :classes => [
4
+ 'inetOrgPerson', 'organizationalPerson', 'person',
5
+ 'posixAccount', 'top'
6
+ ]
7
+
8
+ # Associate with primary belonged group
9
+ belongs_to :primary_group, :primary_key => 'gidNumber',
10
+ :class_name => 'LdapGroup'
11
+
12
+ # Associate with all belonged groups
13
+ belongs_to :groups, :primary_key => 'uid', :many => 'memberUid',
14
+ :class_name => 'LdapGroup'
15
+
16
+ # Creates or finds the admin user. The common name has to be 'Admin'
17
+ # @return [LdapUser]
18
+ def self.find_or_create_admin
19
+ user = LdapUser.find('Admin') rescue nil
20
+ user ||= LdapUser.create(
21
+ :common_name => "Admin",
22
+ :mail => "admin@rubynas.com",
23
+ :home_directory => "/root",
24
+ :uid => "admin",
25
+ :surname => "Admin",
26
+ :uid_number => 0,
27
+ :gid_number => 0,
28
+ :user_password => ActiveLdap::UserPassword.sha("secret"))
29
+ user
30
+ end
31
+ end
@@ -0,0 +1,32 @@
1
+ class SharedFolder < ActiveRecord::Base
2
+ attr_accessible :name, :path
3
+ has_many :shared_folder_services
4
+ validates_presence_of :name, :path
5
+
6
+ validate :path_exists
7
+
8
+ # Converts the shared folder path to path object
9
+ # @returns [Pathname]
10
+ def pathname
11
+ Pathname.new(path)
12
+ end
13
+
14
+ # Validate if the path is given and is really a directory
15
+ def path_exists
16
+ if path
17
+ errors.add(:path, "Path dosn't exist") unless pathname.exist?
18
+ errors.add(:path, "Path isn't a directory") unless pathname.directory?
19
+ end
20
+ end
21
+
22
+ # Searches for the shared folder service that is identified by the given
23
+ # service class.
24
+ # @param [Class, String] service_class a klass like AfpShareService
25
+ # @return [SharedFolderService, nil] the service configuration or nil if
26
+ # no confiuration was found
27
+ def [](service_class)
28
+ if service = shared_folder_services.where(service_class: service_class).first
29
+ service.options
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,15 @@
1
+ class SharedFolderService < ActiveRecord::Base
2
+ attr_accessible :options, :service_class, :shared_folder
3
+ belongs_to :shared_folder
4
+ serialize :options
5
+
6
+ validates_presence_of :service_class, :shared_folder_id
7
+
8
+ # @return [Class] a service class
9
+ def service_class
10
+ if service_class = read_attribute("service_class")
11
+ service_class = service_class.constantize if service_class.is_a?(String)
12
+ service_class
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ class Volume < ActiveRecord::Base
2
+ attr_accessible :name, :path
3
+
4
+ def capacity
5
+ disk.block_size * disk.total_blocks
6
+ end
7
+
8
+ def usage
9
+ used_bytes = (disk.total_blocks - disk.free_blocks) * disk.block_size
10
+ used_bytes / capacity.to_f * 100
11
+ end
12
+
13
+ def disk
14
+ Vmstat.disk(path)
15
+ end
16
+ end
@@ -0,0 +1,9 @@
1
+ class AfpShareService < ShareService
2
+ service_name :netatalk
3
+
4
+ def update!
5
+ if AfpServiceConfiguration.update
6
+ restart # supplied by base class
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,4 @@
1
+ class Service
2
+ def self.service_name(name)
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ class ShareService < Service
2
+
3
+ end