Commit 4790392a5fc1ade75630ba6d34ede6f77ec97e75
Committed by
Georg Hopp
1 parent
f4ba0f21
start fiddling around for a good structure
Showing
20 changed files
with
540 additions
and
6 deletions
| @@ -75,7 +75,7 @@ | @@ -75,7 +75,7 @@ | ||
| 75 | def load!(kind) | 75 | def load!(kind) |
| 76 | @ldapData[kind] = Hash.new if ! @ldapData[kind] | 76 | @ldapData[kind] = Hash.new if ! @ldapData[kind] |
| 77 | 77 | ||
| 78 | - @ldapData[kind][:internal] = @ldap.search( | 78 | + @ldapData[kind][:int] = @ldap.search( |
| 79 | :base => ldapBase(kind), | 79 | :base => ldapBase(kind), |
| 80 | :filter => Net::LDAP::Filter::construct(LDAP_FILTER[kind]) | 80 | :filter => Net::LDAP::Filter::construct(LDAP_FILTER[kind]) |
| 81 | ) | 81 | ) |
| @@ -84,7 +84,7 @@ | @@ -84,7 +84,7 @@ | ||
| 84 | def load(kind) | 84 | def load(kind) |
| 85 | load!(kind) if ! @ldapData[kind] | 85 | load!(kind) if ! @ldapData[kind] |
| 86 | 86 | ||
| 87 | - @ldapData[kind][:external] = @ldapData[kind][:internal].map do |data| | 87 | + @ldapData[kind][:ext] = @ldapData[kind][:int].map do |data| |
| 88 | map = { :dn => :id } | 88 | map = { :dn => :id } |
| 89 | map.merge!(LDAP_MAP[kind]) if LDAP_MAP[kind] | 89 | map.merge!(LDAP_MAP[kind]) if LDAP_MAP[kind] |
| 90 | 90 | ||
| @@ -93,16 +93,16 @@ | @@ -93,16 +93,16 @@ | ||
| 93 | ydata.merge!({ map[key] || key => value.size==1?value[0]:value.to_a }) | 93 | ydata.merge!({ map[key] || key => value.size==1?value[0]:value.to_a }) |
| 94 | end | 94 | end |
| 95 | ydata | 95 | ydata |
| 96 | - end if ! @ldapData[kind][:external] && @ldapData[kind][:internal] | 96 | + end if ! @ldapData[kind][:ext] && @ldapData[kind][:int] |
| 97 | 97 | ||
| 98 | - @ldapData[kind][:external].each{|ydata| yield ydata} if @ldapData[kind][:external] | 98 | + @ldapData[kind][:ext].each{|ydata| yield ydata} if @ldapData[kind][:ext] |
| 99 | end | 99 | end |
| 100 | 100 | ||
| 101 | def update(kind, data) | 101 | def update(kind, data) |
| 102 | map = {} | 102 | map = {} |
| 103 | map.merge!(LDAP_MAP[kind].invert) if LDAP_MAP[kind] | 103 | map.merge!(LDAP_MAP[kind].invert) if LDAP_MAP[kind] |
| 104 | 104 | ||
| 105 | - odata = @ldapData[kind][:external].find{|edata| edata[:id] == data[:id]} | 105 | + odata = @ldapData[kind][:ext].find{|edata| edata[:id] == data[:id]} |
| 106 | 106 | ||
| 107 | data.each do |key,value| | 107 | data.each do |key,value| |
| 108 | pat_key = map[key] ? map[key] : key | 108 | pat_key = map[key] ? map[key] : key |
| @@ -136,7 +136,7 @@ | @@ -136,7 +136,7 @@ | ||
| 136 | def replace(kind, data) | 136 | def replace(kind, data) |
| 137 | puts 'INFO: do replace' | 137 | puts 'INFO: do replace' |
| 138 | puts '----------------' | 138 | puts '----------------' |
| 139 | - odata = @ldapData[kind][:external].find{|edata| edata[:id] == data[:id]} | 139 | + odata = @ldapData[kind][:ext].find{|edata| edata[:id] == data[:id]} |
| 140 | delete(odata) | 140 | delete(odata) |
| 141 | puts | 141 | puts |
| 142 | insert(kind, data) | 142 | insert(kind, data) |
controllers/system_data.rb
0 → 100644
| 1 | +require 'User' | ||
| 2 | +require 'Group' | ||
| 3 | +require 'Site' | ||
| 4 | +require 'MailAliasRole' | ||
| 5 | +require 'MailAliasPerson' | ||
| 6 | +require 'MailAccount' | ||
| 7 | + | ||
| 8 | +class SystemDataBackend | ||
| 9 | + | ||
| 10 | + def initialize(backend) | ||
| 11 | + @backend = backend | ||
| 12 | + @data = Hash.new | ||
| 13 | + end | ||
| 14 | + | ||
| 15 | + def users | ||
| 16 | + load(:User) | ||
| 17 | + end | ||
| 18 | + | ||
| 19 | + def groups | ||
| 20 | + load(:Group) | ||
| 21 | + end | ||
| 22 | + | ||
| 23 | + def sites | ||
| 24 | + load(:Site) | ||
| 25 | + end | ||
| 26 | + | ||
| 27 | + def mailAliasRoles | ||
| 28 | + load(:MailAliasRole) | ||
| 29 | + end | ||
| 30 | + | ||
| 31 | + def mailAliasPeople | ||
| 32 | + load(:MailAliasPerson) | ||
| 33 | + end | ||
| 34 | + | ||
| 35 | + def mailAccounts | ||
| 36 | + load(:MailAccount) | ||
| 37 | + end | ||
| 38 | + | ||
| 39 | + def userByName(name) | ||
| 40 | + users.find{|user| user.name == name} | ||
| 41 | + end | ||
| 42 | + | ||
| 43 | + def groupByName(name) | ||
| 44 | + groups.find{|group| group.name == name} | ||
| 45 | + end | ||
| 46 | + | ||
| 47 | + def siteByName(name) | ||
| 48 | + sites.find{|site| site.name == name} | ||
| 49 | + end | ||
| 50 | + | ||
| 51 | + def usersInGroup(group) | ||
| 52 | + case | ||
| 53 | + when group.members.instance_of?(Array): | ||
| 54 | + Hash[group.members.map{|uid| [uid, userByName(uid)] if userByName(uid)}] | ||
| 55 | + when goup.members.nil?: | ||
| 56 | + {} | ||
| 57 | + else | ||
| 58 | + {group.members => userByName(group.members)} if userByName(group.members) | ||
| 59 | + end | ||
| 60 | + end | ||
| 61 | + | ||
| 62 | + def mailAliasRolesBySite(site) | ||
| 63 | + mailAliasRoles.find_all{|mail| mail.site == site.name} | ||
| 64 | + end | ||
| 65 | + | ||
| 66 | + def mailAliasPeopleBySite(site) | ||
| 67 | + mailAliasPeople.find_all{|mail| mail.site == site.name} | ||
| 68 | + end | ||
| 69 | + | ||
| 70 | + def mailAccountsBySite(site) | ||
| 71 | + mailAccounts.find_all{|mail| mail.site == site.name} | ||
| 72 | + end | ||
| 73 | + | ||
| 74 | + private | ||
| 75 | + | ||
| 76 | + def load(kind) | ||
| 77 | + load!(kind) if ! @data[kind] | ||
| 78 | + @data[kind] | ||
| 79 | + end | ||
| 80 | + | ||
| 81 | + def load!(kind) | ||
| 82 | + @data[kind] = Array.new | ||
| 83 | + @backend.load(kind) do |data| | ||
| 84 | + data[:backend] = @backend | ||
| 85 | + @data[kind].push( | ||
| 86 | + eval(kind.to_s + '.new(data)') | ||
| 87 | + ) | ||
| 88 | + end | ||
| 89 | + end | ||
| 90 | + | ||
| 91 | +end |
database.rb
0 → 100644
database/base.rb
0 → 100644
database/factory.rb
0 → 100644
database/ldap.rb
0 → 100644
| 1 | +class SdAdmin::Database::Ldap | ||
| 2 | + attr_writer :base_dn, :mapper | ||
| 3 | + | ||
| 4 | + def initialize(args = {}) | ||
| 5 | + @con = {:host => 'host.one.virtual', :port => 389} | ||
| 6 | + | ||
| 7 | + @con[:host] = args[:host] if args[:host] | ||
| 8 | + @con[:port] = args[:port] if args[:port] | ||
| 9 | + | ||
| 10 | + @base_dn = args[:base_dn] if args[:base_dn] | ||
| 11 | + | ||
| 12 | + @ldap = Net::LDAP.new(@con) | ||
| 13 | + filter = args[:filter] if args[:filter] | ||
| 14 | + end | ||
| 15 | + | ||
| 16 | + def filter=(filter) | ||
| 17 | + @filter = Net::LDAP::Filter::construct(filter) | ||
| 18 | + end | ||
| 19 | + | ||
| 20 | + def each | ||
| 21 | + _load.each{|key,entry| puts "DEBUG: #{key}"; yield key,entry} | ||
| 22 | + end | ||
| 23 | + | ||
| 24 | + def [](id) | ||
| 25 | + _load[id] | ||
| 26 | + end | ||
| 27 | + | ||
| 28 | + def []=(id, data) | ||
| 29 | + end | ||
| 30 | + | ||
| 31 | + def insert(data) | ||
| 32 | + end | ||
| 33 | + | ||
| 34 | + def delete(id) | ||
| 35 | + end | ||
| 36 | + | ||
| 37 | + private | ||
| 38 | + | ||
| 39 | + def _load! | ||
| 40 | + @data = Hash.new | ||
| 41 | + @ldap.search(:base => @base_dn, :filter => @filter) do |entry| | ||
| 42 | + attributes = Hash.new | ||
| 43 | + entry.each{|attr,value| attributes.merge!({attr => value})} | ||
| 44 | + @data.merge!({attributes[:dn][0] => attributes}) | ||
| 45 | + end | ||
| 46 | + end | ||
| 47 | + | ||
| 48 | + def _load | ||
| 49 | + _load! if ! @data | ||
| 50 | + @data | ||
| 51 | + end | ||
| 52 | + | ||
| 53 | +end |
loader/user.rb
0 → 100644
mappers/ldap.rb
0 → 100644
| 1 | + require 'active_support/secure_random' | ||
| 2 | + require 'net/ldap' | ||
| 3 | + | ||
| 4 | + class SystemDataBackendLdap | ||
| 5 | + | ||
| 6 | + LDAP_USER_MAP = { | ||
| 7 | + :uid => :name, | ||
| 8 | + :userpassword => :pass, | ||
| 9 | + :uidnumber => :uid, | ||
| 10 | + :gidnumber => :gid, | ||
| 11 | + :loginshell => :shell, | ||
| 12 | + :homedirectory => :home | ||
| 13 | + } | ||
| 14 | + | ||
| 15 | + LDAP_GROUP_MAP = { | ||
| 16 | + :cn => :name, | ||
| 17 | + :gidnumber => :gid, | ||
| 18 | + :memberuid => :members | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + LDAP_MAILALIASPERSON_MAP = { | ||
| 22 | + :sn => :surname, | ||
| 23 | + :cn => :name | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + LDAP_MAP = { | ||
| 27 | + :User => LDAP_USER_MAP, | ||
| 28 | + :Group => LDAP_GROUP_MAP, | ||
| 29 | + :Site => { :o => :name }, | ||
| 30 | + :MailAliasRole => { :cn => :user }, | ||
| 31 | + :MailAliasPerson => LDAP_MAILALIASPERSON_MAP, | ||
| 32 | + :mailAccount => { :homedirectory => :home } | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + LDAP_FILTER = { | ||
| 36 | + :User => '(objectClass=posixAccount)', | ||
| 37 | + :Group => '(objectClass=posixGroup)', | ||
| 38 | + :Site => '(&(objectClass=organization)(!(o=hosting)))', | ||
| 39 | + :MailAliasRole => '(&(objectClass=MailAlias)(objectClass=organizationalrole))', | ||
| 40 | + :MailAliasPerson => '(&(objectClass=MailAlias)(objectClass=person))', | ||
| 41 | + :MailAccount => '(objectClass=mailAccount)' | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + LDAP_OBJECTCLASS = { | ||
| 45 | + :User => [ 'account', 'posixAccount', 'shadowAccount' ], | ||
| 46 | + :Group => 'posixGroup', | ||
| 47 | + :Site => 'organization', | ||
| 48 | + :MailAliasRole => [ 'organizationalRole', 'MailAlias' ], | ||
| 49 | + :MailAliasPerson => [ 'person', 'MailAlias' ], | ||
| 50 | + :MailAccount => [ 'person', 'MailAccount' ] | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + LDAP_LAMBDA_USER = lambda do |entry| | ||
| 54 | + entry[:cn] = entry[:uid] | ||
| 55 | + entry[:shadowlastchange] = (Time::now.to_i/60/60/24).to_s | ||
| 56 | + entry[:replace] += ['shadowreplace'] if entry[:replace] | ||
| 57 | + end | ||
| 58 | + | ||
| 59 | + LDAP_LAMBDA = { | ||
| 60 | + :User => LDAP_LAMBDA_USER | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + def initialize(host, port, baseDn, args={}) | ||
| 64 | + @baseDn = baseDn | ||
| 65 | + @systemDn = 'o=system,' + @baseDn | ||
| 66 | + @hostingDn = 'o=hosting,' + @baseDn | ||
| 67 | + | ||
| 68 | + @systemDn = args[:systemDn] if args[:systemDn] | ||
| 69 | + @hostingDn = args[:hostingDn] if args[:hostingDn] | ||
| 70 | + | ||
| 71 | + @ldap = Net::LDAP.new(:host => host, :port => port) | ||
| 72 | + @ldapData = Hash.new | ||
| 73 | + end | ||
| 74 | + | ||
| 75 | + def load!(kind) | ||
| 76 | + @ldapData[kind] = Hash.new if ! @ldapData[kind] | ||
| 77 | + | ||
| 78 | + @ldapData[kind][:int] = @ldap.search( | ||
| 79 | + :base => ldapBase(kind), | ||
| 80 | + :filter => Net::LDAP::Filter::construct(LDAP_FILTER[kind]) | ||
| 81 | + ) | ||
| 82 | + end | ||
| 83 | + | ||
| 84 | + def load(kind) | ||
| 85 | + load!(kind) if ! @ldapData[kind] | ||
| 86 | + | ||
| 87 | + @ldapData[kind][:ext] = @ldapData[kind][:int].map do |data| | ||
| 88 | + map = { :dn => :id } | ||
| 89 | + map.merge!(LDAP_MAP[kind]) if LDAP_MAP[kind] | ||
| 90 | + | ||
| 91 | + ydata = {} | ||
| 92 | + data.each do |key,value| | ||
| 93 | + ydata.merge!({ map[key] || key => value.size==1?value[0]:value.to_a }) | ||
| 94 | + end | ||
| 95 | + ydata | ||
| 96 | + end if ! @ldapData[kind][:ext] && @ldapData[kind][:int] | ||
| 97 | + | ||
| 98 | + @ldapData[kind][:ext].each{|ydata| yield ydata} if @ldapData[kind][:ext] | ||
| 99 | + end | ||
| 100 | + | ||
| 101 | + def update(kind, data) | ||
| 102 | + map = {} | ||
| 103 | + map.merge!(LDAP_MAP[kind].invert) if LDAP_MAP[kind] | ||
| 104 | + | ||
| 105 | + odata = @ldapData[kind][:ext].find{|edata| edata[:id] == data[:id]} | ||
| 106 | + | ||
| 107 | + data.each do |key,value| | ||
| 108 | + pat_key = map[key] ? map[key] : key | ||
| 109 | + if odata[:id] =~ /(^|, *)#{pat_key.to_s}=([^, ]+)/ && $2 != value | ||
| 110 | + return replace(kind, data) | ||
| 111 | + end | ||
| 112 | + end | ||
| 113 | + | ||
| 114 | + entry = Net::LDAP::Entry.new(data[:id]) | ||
| 115 | + data = data.find_all{|key,value| value != odata[key]} | ||
| 116 | + data.delete(:id) | ||
| 117 | + | ||
| 118 | + replace = Array.new | ||
| 119 | + data.each do |key,value| | ||
| 120 | + key = map[key] if map[key] | ||
| 121 | + replace.push(key.to_s) | ||
| 122 | + entry[key] = value | ||
| 123 | + end | ||
| 124 | + | ||
| 125 | + if replace.empty? | ||
| 126 | + puts 'INFO: no changes' | ||
| 127 | + else | ||
| 128 | + entry[:changetype] = 'modify' | ||
| 129 | + entry[:replace] = replace | ||
| 130 | + LDAP_LAMBDA[kind].call(entry) if LDAP_LAMBDA[kind] | ||
| 131 | + | ||
| 132 | + puts entry.to_ldif | ||
| 133 | + end | ||
| 134 | + end | ||
| 135 | + | ||
| 136 | + def replace(kind, data) | ||
| 137 | + puts 'INFO: do replace' | ||
| 138 | + puts '----------------' | ||
| 139 | + odata = @ldapData[kind][:ext].find{|edata| edata[:id] == data[:id]} | ||
| 140 | + delete(odata) | ||
| 141 | + puts | ||
| 142 | + insert(kind, data) | ||
| 143 | + puts '----------------' | ||
| 144 | + end | ||
| 145 | + | ||
| 146 | + def delete(data) | ||
| 147 | + entry = Net::LDAP::Entry.new(data[:id]) | ||
| 148 | + entry[:changetype] = 'delete' | ||
| 149 | + | ||
| 150 | + puts entry.to_ldif | ||
| 151 | + end | ||
| 152 | + | ||
| 153 | + def insert(kind, data) | ||
| 154 | + map = {} | ||
| 155 | + map.merge!(LDAP_MAP[kind].invert) if LDAP_MAP[kind] | ||
| 156 | + | ||
| 157 | + data.delete(:id) | ||
| 158 | + entry = Net::LDAP::Entry.new(ldapDn(kind, data)) | ||
| 159 | + entry[:changetype] = 'add' | ||
| 160 | + entry[:objectclass] = LDAP_OBJECTCLASS[kind] | ||
| 161 | + | ||
| 162 | + data.each do |key,value| | ||
| 163 | + key = map[key] if map[key] | ||
| 164 | + entry[key] = value | ||
| 165 | + end | ||
| 166 | + LDAP_LAMBDA[kind].call(entry) if LDAP_LAMBDA[kind] | ||
| 167 | + | ||
| 168 | + puts entry.to_ldif | ||
| 169 | + end | ||
| 170 | + | ||
| 171 | + private | ||
| 172 | + | ||
| 173 | + def ldapBase(kind) | ||
| 174 | + case(kind) | ||
| 175 | + when :User, :Group: @systemDn | ||
| 176 | + when :Site, :MailAliasRole, :MailAliasPerson, :MailAccount: @hostingDn | ||
| 177 | + end | ||
| 178 | + end | ||
| 179 | + | ||
| 180 | + def ldapDn(kind, data) | ||
| 181 | + case(kind) | ||
| 182 | + when :User | ||
| 183 | + "uid=#{data[:name]},ou=user,#{ldapBase(kind)}" | ||
| 184 | + when :Group | ||
| 185 | + "cn=#{data[:name]},ou=group,#{ldapBase(kind)}" | ||
| 186 | + when :Site | ||
| 187 | + "o=#{data[:name]},#{ldapBase(kind)}" | ||
| 188 | + when :MailAliasRole | ||
| 189 | + "cn=#{data[:user]},o=#{data[:mail].sub(/.*@/, '')},#{ldapBase(kind)}" | ||
| 190 | + when :MailAliasPerson | ||
| 191 | + "mail=#{data[:mail]},o=#{data[:mail].sub(/.*@/, '')},#{ldapBase(kind)}" | ||
| 192 | + when :MailAccount | ||
| 193 | + "mail=#{data[:mail]},o=#{data[:mail].sub(/.*@/, '')},#{ldapBase(kind)}" | ||
| 194 | + end | ||
| 195 | + end | ||
| 196 | + | ||
| 197 | +end |
model.rb
0 → 100644
model/base.rb
0 → 100644
model/group.rb
0 → 100644
model/interface.rb
0 → 100644
model/mail_account.rb
0 → 100644
| 1 | +require 'SystemData' | ||
| 2 | + | ||
| 3 | +class MailAccount < SystemData | ||
| 4 | + attr_accessor :mail, :mailbox | ||
| 5 | + | ||
| 6 | + def initialize(args = {}) | ||
| 7 | + super(args) | ||
| 8 | + | ||
| 9 | + @mail = args[:mail] | ||
| 10 | + @home = args[:home] | ||
| 11 | + @mailbox = args[:mailbox] | ||
| 12 | + end | ||
| 13 | + | ||
| 14 | + def site | ||
| 15 | + @mail.sub(/.*@/, '') | ||
| 16 | + end | ||
| 17 | +end |
model/mail_alias_person.rb
0 → 100644
| 1 | +require 'SystemData' | ||
| 2 | + | ||
| 3 | +class MailAliasPerson < SystemData | ||
| 4 | + attr_accessor :mail, :maildrop, :surname, :name | ||
| 5 | + | ||
| 6 | + def initialize(args = {}) | ||
| 7 | + super(args) | ||
| 8 | + | ||
| 9 | + @mail = args[:mail] | ||
| 10 | + @maildrop = args[:maildrop] | ||
| 11 | + @surname = args[:surname] | ||
| 12 | + @name = args[:name] | ||
| 13 | + end | ||
| 14 | + | ||
| 15 | + def site | ||
| 16 | + @mail.sub(/.*@/, '') | ||
| 17 | + end | ||
| 18 | +end |
model/mail_alias_role.rb
0 → 100644
| 1 | +require 'SystemData' | ||
| 2 | + | ||
| 3 | +class MailAliasRole < SystemData | ||
| 4 | + attr_accessor :mail, :maildrop, :user | ||
| 5 | + | ||
| 6 | + def initialize(args = {}) | ||
| 7 | + super(args) | ||
| 8 | + | ||
| 9 | + @mail = args[:mail] | ||
| 10 | + @maildrop = args[:maildrop] | ||
| 11 | + @user = args[:user] | ||
| 12 | + end | ||
| 13 | + | ||
| 14 | + def site | ||
| 15 | + @mail.sub(/.*@/, '') | ||
| 16 | + end | ||
| 17 | +end |
model/site.rb
0 → 100644
model/system_data.rb
0 → 100644
| 1 | +class SystemData | ||
| 2 | + attr_reader :id | ||
| 3 | + | ||
| 4 | + def initialize(args = {}) | ||
| 5 | + @backend = args[:backend] | ||
| 6 | + @id = args[:id] | ||
| 7 | + end | ||
| 8 | + | ||
| 9 | + def save | ||
| 10 | + kind = self.class.to_s.to_sym | ||
| 11 | + | ||
| 12 | + if @id | ||
| 13 | + @backend.update(kind, to_h) | ||
| 14 | + else | ||
| 15 | + @backend.insert(kind, to_h) | ||
| 16 | + end | ||
| 17 | + end | ||
| 18 | + | ||
| 19 | + def to_h | ||
| 20 | + Hash[instance_variables.map do |var| | ||
| 21 | + [var[1...var.size].to_sym, eval(var)] if var != '@backend' | ||
| 22 | + end] | ||
| 23 | + end | ||
| 24 | +end |
model/user.rb
0 → 100644
| 1 | +class SdAdmin::Model::User | ||
| 2 | + attr_accessor :name, :pass, :uid, :gid, :shell, :home | ||
| 3 | + | ||
| 4 | + def initialize(args={}, backend=nil) | ||
| 5 | + super(backend) | ||
| 6 | + | ||
| 7 | + @backend.base_dn = 'ou=user,o=system,dc=weird-web-workers,dc=org' | ||
| 8 | + @backend.filter = '(objectClass=posixAccount)' | ||
| 9 | + | ||
| 10 | + @name = args[:name] | ||
| 11 | + @pass = args[:pass] | ||
| 12 | + @uid = args[:uid] | ||
| 13 | + @gid = args[:gid] | ||
| 14 | + @shell = args[:shell] | ||
| 15 | + @home = args[:home] | ||
| 16 | + @shadowmax = args[:shadowmax] | ||
| 17 | + @shadowwarning = args[:shadowwarning] | ||
| 18 | + end | ||
| 19 | +end |
sd_admin.rb
0 → 100644
Please
register
or
login
to post a comment