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,63 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
4
+ require 'rubynas'
5
+ require 'rubynas/version'
6
+
7
+ case ARGV.first
8
+ when 'migrate'
9
+ puts 'Migration of the database'
10
+ path = File.expand_path('../../lib/rubynas/db/migrate', __FILE__)
11
+ ActiveRecord::Migrator.migrate path
12
+
13
+ # In the production environment should the root volume always be available
14
+ unless Volume.find_by_name_and_path("System Volume", "/")
15
+ Volume.create(name: "System Volume", path: "/")
16
+ end
17
+
18
+ # Setup default account and structure if they don't exist in the repository
19
+ LdapOrgUnit.find_or_create('users')
20
+ LdapOrgUnit.find_or_create('groups')
21
+ LdapUser.find_or_create_admin
22
+ LdapGroup.find_or_create_administrators
23
+ when 'server'
24
+ require 'rack'
25
+ require 'puma'
26
+ require 'rack/handler/puma'
27
+ require 'dnssd'
28
+ require 'rubynas/version'
29
+ $0 = 'rubynas'
30
+
31
+ options = {
32
+ :Host => '0.0.0.0',
33
+ :Port => (ENV['PORT'] || 5100).to_i,
34
+ :Threads => '0:16',
35
+ :Verbose => false
36
+ }
37
+
38
+ text_record = DNSSD::TextRecord.new 'Version' => Rubynas::VERSION,
39
+ 'Path' => '/api'
40
+ name = 'rubynas'
41
+ type = '_rubynas._tcp'
42
+ domain = host = nil
43
+ port = options[:Port]
44
+ DNSSD.register name, type, domain, port, text_record
45
+
46
+ Rack::Handler::Puma.run(Rubynas::Application, options) do |server|
47
+ [:INT, :TERM].each { |sig| trap(sig) { server.stop } }
48
+ end
49
+ when 'install'
50
+ if File.exist?('/etc/lsb-release')
51
+ data = Hash[File.read('/etc/lsb-release').lines.map do |line|
52
+ line.chomp.split("=")
53
+ end]
54
+ klass_name = data['DISTRIB_ID'].capitalize
55
+ klass_name << data['DISTRIB_CODENAME'].capitalize
56
+ klass_name << "Installer"
57
+ Kernel.const_get(klass_name).new('rubynas.com', 'admin', 'secret').run
58
+ else
59
+ puts "System unknown! Can't install"
60
+ end
61
+ else
62
+ puts "usage: #{$0} <migrate|server|install>"
63
+ end
@@ -0,0 +1,5 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+ $LOAD_PATH.unshift(File.expand_path('../lib/', __FILE__))
3
+ require 'rubynas'
4
+
5
+ run Rubynas::Application
@@ -0,0 +1,2 @@
1
+ Use this README file to introduce your application and point to useful places in the API for learning more.
2
+ Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries.
Binary file
Binary file
@@ -0,0 +1,35 @@
1
+ require 'logger'
2
+ require 'inifile'
3
+ require 'active_ldap'
4
+ require 'active_record'
5
+ require 'active_record/errors'
6
+ require 'lumberjack'
7
+ require 'lumberjack_syslog_device'
8
+ require 'netatalk-config'
9
+ require 'grape'
10
+ require 'grape-entity'
11
+ require 'active_support'
12
+ require 'active_support/dependencies'
13
+ require 'vmstat'
14
+
15
+ %w(apis models services installers).each do |dir|
16
+ path = File.expand_path("../rubynas/#{dir}", __FILE__)
17
+ ActiveSupport::Dependencies.autoload_paths.unshift(path)
18
+ end
19
+
20
+ module Rubynas
21
+ class <<self
22
+ attr_accessor :logger
23
+ end
24
+
25
+ Application = Rack::Builder.new do
26
+ map "/api" do
27
+ map("/users") { run ::UserApi }
28
+ map("/groups") { run ::GroupApi }
29
+ map("/volumes") { run ::VolumeApi }
30
+ map("/system") { run ::SystemInformationApi }
31
+ end
32
+ end
33
+ end
34
+
35
+ require 'rubynas/config'
@@ -0,0 +1,51 @@
1
+ class GroupApi < Grape::API
2
+ format :json
3
+
4
+ rescue_from ActiveLdap::EntryNotFound do |e|
5
+ Rack::Response.new([e.inspect], 404)
6
+ end
7
+
8
+ class Group < Grape::Entity
9
+ expose :common_name, documentation: { type: String, desc: 'Group name' }
10
+ expose :gid_number,
11
+ documentation: { type: Integer, desc: 'ID of the group' }
12
+ end
13
+
14
+ desc 'Returns the list of groups in the ldap', {
15
+ :object_fields => GroupApi::Group.documentation
16
+ }
17
+ get '/' do
18
+ present LdapGroup.all, with: GroupApi::Group
19
+ end
20
+
21
+ desc 'Return a single group'
22
+ get '/:cn' do
23
+ present LdapGroup.find(params[:cn]), with: GroupApi::Group
24
+ end
25
+
26
+ desc 'Delete the passed group'
27
+ delete '/:cn' do
28
+ LdapGroup.find(params.delete(:cn)).destroy
29
+ ''
30
+ end
31
+
32
+ desc 'Add a new group'
33
+ params do
34
+ requires :common_name, type: String
35
+ requires :gid_number, type: Fixnum
36
+ end
37
+ post '/' do
38
+ LdapGroup.create(params)
39
+ ''
40
+ end
41
+
42
+ desc 'Update a group completely'
43
+ params do
44
+ requires :common_name, type: String
45
+ requires :gid_number, type: Fixnum
46
+ end
47
+ put '/:cn' do
48
+ LdapGroup.find(params.delete(:cn)).update_attributes(params)
49
+ ''
50
+ end
51
+ end
@@ -0,0 +1,13 @@
1
+ class SystemInformationApi < Grape::API
2
+ format :json
3
+
4
+ desc 'resturns vmstat data'
5
+ get '/vmstat' do
6
+ present Vmstat.snapshot
7
+ end
8
+
9
+ desc 'returns disk related information'
10
+ get '/disk' do
11
+ present Vmstat.disk('/' + params[:path].to_s)
12
+ end
13
+ end
@@ -0,0 +1,85 @@
1
+ class UserApi < Grape::API
2
+ format :json
3
+
4
+ rescue_from ActiveLdap::EntryNotFound do |error|
5
+ Rack::Response.new({
6
+ 'status' => 404,
7
+ 'message' => error.message
8
+ }.to_json, 404)
9
+ end
10
+
11
+ class User < Grape::Entity
12
+ expose :common_name, documentation: { type: String, desc: 'Full name' }
13
+ expose :given_name, documentation: { type: String, desc: 'Firstname' }
14
+ expose :surname, documentation: { type: String, desc: 'Lastname' }
15
+ expose :uid, documentation: { type: String, desc: 'Login name' }
16
+ expose :home_directory,
17
+ documentation: { type: String, desc: 'Path to the user home' }
18
+ expose :gid_number,
19
+ documentation: { type: Integer, desc: 'ID of the group' }
20
+ expose :uid_number, documentation: { type: Integer, desc: 'ID of the user' }
21
+ expose :mail, documentation: { type: String, desc: 'E-Mail address' }
22
+ expose :login_shell, documentation: { type: String, desc: 'The shell used for ssh login' }
23
+ end
24
+
25
+ desc 'Returns the list of users in the ldap', {
26
+ :object_fields => UserApi::User.documentation
27
+ }
28
+ get '/' do
29
+ present LdapUser.all, with: UserApi::User
30
+ end
31
+
32
+ desc 'Returns a template for new users', {
33
+ :object_fields => UserApi::User.documentation
34
+ }
35
+ get '/template' do
36
+ next_uid_number = LdapUser.all.map(&:uid_number).max.to_i + 1
37
+ next_uid_number = 1000 if next_uid_number < 1000
38
+ { uid_number: next_uid_number,
39
+ gid_number: 1000,
40
+ home_directory: '/home/' }
41
+ end
42
+
43
+ desc 'Adds new user to the ldap'
44
+ params do
45
+ requires :common_name
46
+ requires :given_name
47
+ requires :surname
48
+ requires :uid
49
+ requires :home_directory
50
+ requires :gid_number
51
+ requires :uid_number
52
+ requires :password
53
+ requires :mail
54
+ requires :login_shell
55
+ end
56
+ post '/' do
57
+ password = ActiveLdap::UserPassword.sha(params.delete(:password))
58
+ user = LdapUser.create(params.merge(:userPassword => password))
59
+ present user, with: UserAPI::User
60
+ end
61
+
62
+ desc 'Request single user', {
63
+ :object_fields => UserApi::User.documentation
64
+ }
65
+ get '/:cn' do
66
+ present LdapUser.find(params[:cn]), with: UserApi::User
67
+ end
68
+
69
+ desc 'Update the user data in the ldap'
70
+ put '/:cn' do
71
+ user = LdapUser.find(params.delete(:cn))
72
+ if params[:password]
73
+ password = ActiveLdap::UserPassword.sha(params.delete(:password))
74
+ params.merge!(:userPassword => password)
75
+ end
76
+ user.update_attributes(params)
77
+ present user, with: UserAPI::User
78
+ end
79
+
80
+ desc 'Delete user'
81
+ delete '/:cn' do
82
+ LdapUser.find(params.delete(:cn)).destroy
83
+ Rack::Response.new([], 204)
84
+ end
85
+ end
@@ -0,0 +1,50 @@
1
+ class VolumeApi < Grape::API
2
+ format :json
3
+
4
+ rescue_from ActiveRecord::RecordNotFound do |e|
5
+ Rack::Response.new([e.inspect], 404)
6
+ end
7
+
8
+ class Volume < Grape::Entity
9
+ expose :id, documentation: { type: String, desc: 'volume unique id' }
10
+ expose :name, documentation: { type: String, desc: 'name of the volume' }
11
+ expose :path, documentation: { type: String, desc: 'path of the volume' }
12
+ expose :capacity, documentation: { type: String, desc: 'capacity in bytes' }
13
+ expose :usage, documentation: { type: Float, desc: 'usage in percent' }
14
+ end
15
+
16
+ desc 'Returns the list of volumes', {
17
+ :object_fields => ::VolumeApi::Volume.documentation
18
+ }
19
+ get '/' do
20
+ present ::Volume.all, with: ::VolumeApi::Volume
21
+ end
22
+
23
+ desc 'Return the requested volume', {
24
+ :object_fields => ::VolumeApi::Volume.documentation
25
+ }
26
+ params do
27
+ requires :id, type: Fixnum
28
+ end
29
+ get '/:id' do
30
+ present ::Volume.find(params[:id]), with: ::VolumeApi::Volume
31
+ end
32
+
33
+ desc 'Update the volume with the passed id'
34
+ put '/:id' do
35
+ data = { name: params[:name], path: params[:path] }
36
+ ::Volume.find(params.delete(:id)).update_attributes!(data)
37
+ end
38
+
39
+ desc 'Create new volume', {
40
+ :object_fields => ::VolumeApi::Volume.documentation
41
+ }
42
+ post '/' do
43
+ ::Volume.create name: params[:name], path: params[:path]
44
+ end
45
+
46
+ desc 'Delete a volume'
47
+ delete '/:id' do
48
+ ::Volume.find(params.delete(:id)).destroy
49
+ end
50
+ end
@@ -0,0 +1,63 @@
1
+ module Rubynas
2
+ class Config
3
+ # @param [String] path the path to the configuration
4
+ def self.use(path)
5
+ new(path).configure
6
+ end
7
+
8
+ def initialize(path)
9
+ @path = path
10
+ @ini = IniFile.load(path, :encoding => 'utf-8')
11
+ end
12
+
13
+ def configure
14
+ configure_logger
15
+ configure_active_ldap
16
+ configure_active_record
17
+ end
18
+
19
+ def configure_logger
20
+ section = @ini['Server']
21
+ if section['syslog'] == 'true'
22
+ facility = Syslog::LOG_LOCAL0 | Syslog::LOG_CONS
23
+ device = Lumberjack::SyslogDevice.new facility: facility
24
+ Rubynas.logger = Lumberjack::Logger.new device, progname: "rubynas"
25
+ else
26
+ Rubynas.logger = Logger.new(STDOUT)
27
+ end
28
+ end
29
+
30
+ def configure_active_record
31
+ section = @ini['Database']
32
+ ActiveRecord::Base.establish_connection(
33
+ :adapter => 'sqlite3',
34
+ :database => section['path'],
35
+ :timeout => (section['timeout'] || 5000).to_i,
36
+ :pool => (section['pool'] || 5).to_i
37
+ )
38
+ end
39
+
40
+ def configure_active_ldap
41
+ section = @ini['Ldap']
42
+ ActiveLdap::Base.setup_connection(
43
+ :host => section['host'],
44
+ :port => section['port'],
45
+ :base => section['base'],
46
+ :logger => Rubynas.logger,
47
+ :bind_dn => section['bind_dn'],
48
+ :password_block => Proc.new { section['password'] },
49
+ :allow_anonymous => false,
50
+ :try_sasl => false
51
+ )
52
+ end
53
+ end
54
+ end
55
+
56
+ # Regular usage
57
+ if File.exist?('/etc/rubynas.ini')
58
+ Rubynas::Config.use('/etc/rubynas.ini')
59
+
60
+ # Local testing usage
61
+ elsif File.exist?('rubynas.ini')
62
+ Rubynas::Config.use('rubynas.ini')
63
+ end
@@ -0,0 +1,46 @@
1
+ class DeviseCreateUsers < ActiveRecord::Migration
2
+ def change
3
+ create_table(:users) do |t|
4
+ ## Database authenticatable
5
+ t.string :email, :null => false, :default => ""
6
+ t.string :encrypted_password, :null => false, :default => ""
7
+
8
+ ## Recoverable
9
+ t.string :reset_password_token
10
+ t.datetime :reset_password_sent_at
11
+
12
+ ## Rememberable
13
+ t.datetime :remember_created_at
14
+
15
+ ## Trackable
16
+ t.integer :sign_in_count, :default => 0
17
+ t.datetime :current_sign_in_at
18
+ t.datetime :last_sign_in_at
19
+ t.string :current_sign_in_ip
20
+ t.string :last_sign_in_ip
21
+
22
+ ## Confirmable
23
+ # t.string :confirmation_token
24
+ # t.datetime :confirmed_at
25
+ # t.datetime :confirmation_sent_at
26
+ # t.string :unconfirmed_email # Only if using reconfirmable
27
+
28
+ ## Lockable
29
+ # t.integer :failed_attempts, :default => 0 # Only if lock strategy is :failed_attempts
30
+ # t.string :unlock_token # Only if unlock strategy is :email or :both
31
+ # t.datetime :locked_at
32
+
33
+ ## Token authenticatable
34
+ # t.string :authentication_token
35
+
36
+
37
+ t.timestamps
38
+ end
39
+
40
+ add_index :users, :email, :unique => true
41
+ add_index :users, :reset_password_token, :unique => true
42
+ # add_index :users, :confirmation_token, :unique => true
43
+ # add_index :users, :unlock_token, :unique => true
44
+ # add_index :users, :authentication_token, :unique => true
45
+ end
46
+ end
@@ -0,0 +1,10 @@
1
+ class CreateVolumes < ActiveRecord::Migration
2
+ def change
3
+ create_table :volumes do |t|
4
+ t.string :name
5
+ t.string :path
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ class CreateSharedFolders < ActiveRecord::Migration
2
+ def change
3
+ create_table :shared_folders do |t|
4
+ t.string :name
5
+ t.string :path
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end