rubynas 0.1.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
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