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,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