Commit 666ae5b6fd8823340081c236abe54007fb7540fd

Authored by Georg GH. Hopp
Committed by Georg Hopp
1 parent 4790392a

heavy restructuring

implemented new design
1 -require 'SystemData'  
2 -  
3 -class Group < SystemData  
4 - attr_accessor :name, :gid, :members  
5 -  
6 - def initialize(args = {})  
7 - super(args)  
8 -  
9 - @name = args[:name]  
10 - @gid = args[:gid]  
11 - @members = args[:members]  
12 - @members = Array.new if @members.nil?  
13 - end  
14 -end  
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  
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  
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  
1 -require 'SystemData'  
2 -  
3 -class Site < SystemData  
4 - attr_accessor :name  
5 -  
6 - def initialize(args = {})  
7 - super(args)  
8 -  
9 - @name = args[:name]  
10 - end  
11 -end  
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  
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  
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  
1 -require 'SystemData'  
2 -  
3 -class User < SystemData  
4 - attr_accessor :name, :pass, :uid, :gid, :shell, :home  
5 -  
6 - def initialize(args = {})  
7 - super(args)  
8 -  
9 - @name = args[:name]  
10 - @pass = args[:pass]  
11 - @uid = args[:uid]  
12 - @gid = args[:gid]  
13 - @shell = args[:shell]  
14 - @home = args[:home]  
15 - @shadowmax = args[:shadowmax]  
16 - @shadowwarning = args[:shadowwarning]  
17 - end  
18 -end  
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  
1 -module SdAdmin::Database  
2 - class Ldap  
3 - require 'database/base.rb'  
4 - require 'net/ldap'  
5 -  
6 - include Enumerable  
7 - end  
8 -  
9 - require 'database/ldap'  
10 -end  
1 -class SdAdmin::Database::Base  
2 -  
3 - def initialize  
4 - @data = Hash.new  
5 - end  
6 -  
7 - def _create(data)  
8 - end  
9 -  
10 - def _read(id)  
11 - end  
12 -  
13 -end  
1 -class SdAdmin::Database::Factory  
2 -  
3 -end  
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  
No preview for this file type
  1 +was wir haben.
  2 +
  3 +- verschiedene Model (user, group, mailAccount, mailALias, etc.)
  4 +- diese koennen in verschiedenen Datenquellen liegen
  5 +- die Datenquellen werden mit verschiedenen Abfragesprachen abgefragt.
  6 +- das entsprechende Model bestimmt welche Daten abgefragt werden.
  7 +- die Datenquelle bestimmt wie diese Daten abgefragt werden.
  8 +
  9 + Konflikt: bei ldap laesst sich das wie nur schwer von dem was abgefragt
  10 +werden soll trennen.
  11 +
  12 + Moegliche Loesung: eine Factory, die ueber die Klasse des Models und
  13 +die Klasse der Datenbank eine solche konkrete Datenbank initialisiert.
  14 +
  15 + Variation: anstatt eine factory zu bauen koennte man eine generische
  16 + Datenbankklasse bauen die eine Klassenmethode bekommt ueber die mit
  17 + dem reingegebenen Model dann eine Instanz erzeugt wird.
  18 +
  19 + Problem: Die Datenbankklasse muss dann Initialisierungsinformationen
  20 +zu den entsprechenden Models kennen. (Implementierungsdetail)
  21 +Um die Datenbankklasse generisch zu halten sollte diese Information
  22 +woanders her kommen, allerdings nicht aus dem Model, da dann wiederum
  23 +die Model Implementierungsdetails der Datenbankklasse kennen muessen.
  24 +
  25 + Evtl.: laesst sich was ueber Name conventions machen. Sauberer scheint
  26 +mir aber zu sein das es zu jeder Datenbankklasse eine Konfigurationsdatei
  27 +gibt in der man die Eckdaten fuer die Abfragen der einzelnen Model
  28 +konfigurieren kann.
  29 +
  30 + ein yaml koennte evtl. so aussehen: (ldap.yml)
  31 +
  32 + ldap: # => wenn es pro Datenbank ne eigenen datei gibt ist das nicht noetig
  33 + host: host.one.virtual
  34 + port: 389
  35 + queries:
  36 + User:
  37 + baseDn: ou=user,o=system,dc=weird-web-workers,dc=org
  38 + filter: (objectClass=posixAccount)
  39 + Group:
  40 + baseDn: ou=group,o=system,dc=weird-web-workers,dc=org
  41 + filter: (objectClass=posixGroup)
  42 +
  43 + ...
  44 +
  45 + alternativ zu einer Datei koennte man eine Mapping Datei zu jeder Kombination
  46 +aus Model und Datenbanktyp anlegen...diese waeren schoen klein schnell gelesen
  47 +und geschrieben.
  48 +
  49 + Dateistruktur:
  50 +
  51 + - model - user.rb
  52 + - group.rb
  53 + - site.rb
  54 + - mailalias_role.rb
  55 + - mailalias_person.rb
  56 + - mailaccount.rb
  57 + - data - ldap.rb
  58 + - data - config - ldap.yml
  59 + - adapter - ldap.rb
  60 + - config - ldap - user.yml
  61 + - group.yml
  62 + - site.yml
  63 + - mailalias_role.yml
  64 + - mailalias_person.yml
  65 + - mailaccount.yml
  66 +
  1 +module DsAdmin
  2 + DsAdmin.autoload(:Model, 'model')
  3 + DsAdmin.autoload(:Storage, 'storage')
  4 +end
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  
1 -module SdAdmin::Model  
2 - module Interface  
3 - end 1 +module DsAdmin::Model
  2 + include Enumerable
4 3
5 - class Base  
6 - require 'model/interface'  
7 - require 'database'  
8 - include SdAdmin::Model::Interface  
9 - end 4 + DsAdmin::Model.autoload(:User, 'model/user')
  5 + DsAdmin::Model.autoload(:Group, 'model/group')
  6 + DsAdmin::Model.autoload(:Site, 'model/site')
  7 + DsAdmin::Model.autoload(:MailAliasRole, 'model/mail_alias_role')
  8 + DsAdmin::Model.autoload(:MailAliasPerson, 'model/mail_alias_person')
  9 + DsAdmin::Model.autoload(:MailAccount, 'model/mail_account')
10 10
11 - class User < Base  
12 - end 11 + def (DsAdmin::Model).storage=(storage)
  12 + @@storage = storage
  13 + end
13 14
14 - require 'model/base'  
15 - require 'model/user' 15 + def (DsAdmin::Model).storage
  16 + @@storage
  17 + end
  18 +
  19 + attr_accessor :id
  20 +
  21 + def initialize(args = {})
  22 + @id = args[:id] if args[:id]
  23 + end
  24 +
  25 + def all
  26 + @@storage.config.model = self
  27 +
  28 + @@storage.map do |data|
  29 + self.class.new(data)
  30 + end
  31 + end
  32 +
  33 + def each(&block)
  34 + all.each(&block)
  35 + end
  36 +
  37 + def load(id)
  38 + self.class.new(_load(id))
  39 + end
  40 +
  41 + def load!(id)
  42 + initialize(_load(id))
  43 + end
  44 +
  45 + def save
  46 + @id = @storage.create_id(self) unless @id
  47 + @storage.write(self)
  48 + end
  49 +
  50 + def update
  51 + @storage.write(self)
  52 + end
  53 +
  54 + def to_sym
  55 + self.class.to_s.to_sym
  56 + end
  57 +
  58 + protected
  59 + def _load(id)
  60 + data = @@storage.find {|data| data[:id] == id}
  61 + throw "unknown id (#{id})" unless data
  62 + data
  63 + end
16 end 64 end
1 -class SdAdmin::Model::Base  
2 - attr_reader :backend  
3 -  
4 - def initialize(backend)  
5 - @backend = SdAdmin::Database::Ldap.new  
6 - @backend = backend if backend  
7 - end  
8 -  
9 -end  
1 -require 'SystemData' 1 +class DsAdmin::Model::Group
  2 + include DsAdmin::Model
2 3
3 -class Group < SystemData  
4 attr_accessor :name, :gid, :members 4 attr_accessor :name, :gid, :members
5 - 5 +
6 def initialize(args = {}) 6 def initialize(args = {})
7 - super(args) 7 + return if args.empty?
  8 + super(args)
8 9
9 @name = args[:name] 10 @name = args[:name]
10 @gid = args[:gid] 11 @gid = args[:gid]
11 - @members = args[:members]  
12 - @members = Array.new if @members.nil? 12 + @members = args[:members] ? args[:members] : Array.new
13 end 13 end
14 end 14 end
1 -module SdAdmin::Model::Interface  
2 -  
3 - def all  
4 - Hash[self.backend.map{|key,entry| [key, entry]}]  
5 - end  
6 -  
7 -end  
1 -require 'SystemData' 1 +class DsAdmin::Model::MailAccount
  2 + include DsAdmin::Model
2 3
3 -class MailAccount < SystemData  
4 attr_accessor :mail, :mailbox 4 attr_accessor :mail, :mailbox
5 5
6 def initialize(args = {}) 6 def initialize(args = {})
  7 + return if args.empty?
7 super(args) 8 super(args)
8 9
9 @mail = args[:mail] 10 @mail = args[:mail]
1 -require 'SystemData' 1 +class DsAdmin::Model::MailAliasPerson
  2 + include DsAdmin::Model
2 3
3 -class MailAliasPerson < SystemData  
4 attr_accessor :mail, :maildrop, :surname, :name 4 attr_accessor :mail, :maildrop, :surname, :name
5 5
6 def initialize(args = {}) 6 def initialize(args = {})
  7 + return if args.empty?
7 super(args) 8 super(args)
8 9
9 @mail = args[:mail] 10 @mail = args[:mail]
1 -require 'SystemData' 1 +class DsAdmin::Model::MailAliasRole
  2 + include DsAdmin::Model
2 3
3 -class MailAliasRole < SystemData  
4 attr_accessor :mail, :maildrop, :user 4 attr_accessor :mail, :maildrop, :user
5 5
6 def initialize(args = {}) 6 def initialize(args = {})
  7 + return if args.empty?
7 super(args) 8 super(args)
8 9
9 @mail = args[:mail] 10 @mail = args[:mail]
1 -require 'SystemData' 1 +class DsAdmin::Model::Site
  2 + include DsAdmin::Model
2 3
3 -class Site < SystemData  
4 attr_accessor :name 4 attr_accessor :name
5 5
6 def initialize(args = {}) 6 def initialize(args = {})
  7 + return if args.empty?
7 super(args) 8 super(args)
8 9
9 @name = args[:name] 10 @name = args[:name]
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  
1 -class SdAdmin::Model::User  
2 - attr_accessor :name, :pass, :uid, :gid, :shell, :home 1 +class DsAdmin::Model::User
  2 + include DsAdmin::Model
3 3
4 - def initialize(args={}, backend=nil)  
5 - super(backend) 4 + attr_accessor :name, :pass, :uid, :gid, :shell, :home
6 5
7 - @backend.base_dn = 'ou=user,o=system,dc=weird-web-workers,dc=org'  
8 - @backend.filter = '(objectClass=posixAccount)' 6 + def initialize(args = {})
  7 + return if args.empty?
  8 + super(args)
9 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 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 19 end
1 -module SdAdmin  
2 - module Model  
3 - end  
4 -  
5 - module Database  
6 - end  
7 -  
8 - require 'model'  
9 - require 'database'  
10 -end  
  1 +module DsAdmin::Storage
  2 + include Enumerable
  3 +
  4 + DsAdmin::Storage.autoload(:Ldap, 'storage/ldap')
  5 + DsAdmin::Storage.autoload(:Mysql, 'storage/mysql')
  6 + DsAdmin::Storage.autoload(:Config, 'storage/config')
  7 +
  8 + attr_accessor :config
  9 +
  10 + def initialize(config)
  11 + @config = config
  12 + end
  13 +
  14 + def each(&block)
  15 + read.each(&block)
  16 + end
  17 +
  18 + ##
  19 + # We don't need this....the 'id' is a storage id and as
  20 + # thus returned after successfully writing a new entry.
  21 + #
  22 + def create_id(model)
  23 + return "dummy id for #{model.inspect}"
  24 + end
  25 +
  26 + def read
  27 + throw "#{self.class}: read not implemented"
  28 + end
  29 +
  30 + def write(model)
  31 + throw "#{self.class}: write not implemented"
  32 + end
  33 +
  34 + def to_sym
  35 + self.class.to_s.to_sym
  36 + end
  37 +end
  1 +require 'yaml'
  2 +
  3 +class Test::Storage::Config
  4 + attr_accessor :model
  5 +
  6 + def initialize(yml_file)
  7 + @config = YAML.load_file(yml_file)
  8 + end
  9 +
  10 + def con(storage)
  11 + @config[storage.to_sym][:con]
  12 + end
  13 +
  14 + def query(storage)
  15 + @config[storage.to_sym][@model.to_sym][:query]
  16 + end
  17 +
  18 + def map(storage)
  19 + @config[storage.to_sym][@model.to_sym][:map]
  20 + end
  21 +end
  1 +require 'net/ldap'
  2 +
  3 +class DsAdmin::Storage::Ldap
  4 + include DsAdmin::Storage
  5 +
  6 + def initialize(config)
  7 + super(config)
  8 + @ldap = Net::LDAP.new(@config.con(self))
  9 + end
  10 +
  11 + def read
  12 + query = @config.query(self)
  13 +
  14 + ##
  15 + # two things.
  16 + # - create a hash from the ldap search result
  17 + # - map the id's from the ldap search resulte into id's used in
  18 + # the models. The mapping is read from the config.
  19 + #
  20 + foo = @ldap.search(query).map do |data|
  21 + map = { :dn => :id }
  22 + map.merge!(@config.map(self))
  23 +
  24 + remapped = Hash.new
  25 + data.each do |key,value|
  26 + key = map[key] || key
  27 + value = value.size==1 ? value[0] : value.to_a
  28 +
  29 + remapped.merge!({ key => value })
  30 + end
  31 + remapped
  32 + end
  33 + end
  34 +end
  1 +class DsAdmin::Storage::Mysql
  2 + include DsAdmin::Storage
  3 +end
1 -require 'SystemDataBackend'  
2 -require 'SystemDataBackendLdap'  
3 -  
4 -ldap = SystemDataBackendLdap.new(  
5 - 'host.one.virtual',  
6 - 389,  
7 - 'dc=weird-web-workers,dc=org'  
8 -)  
9 -backend = SystemDataBackend.new(ldap)  
10 -  
11 -backend.users.each do |user|  
12 - puts 'user: '+user.name+','+user.uid+','+user.gid+','+user.home  
13 -end  
14 -  
15 -puts  
16 -  
17 -backend.groups.each do |group|  
18 - members = backend.usersInGroup(group)  
19 -  
20 - puts 'group: '+group.name+','+group.gid  
21 - puts ' members:'  
22 - group.members.each do |name|  
23 - print ' ' + name + ': '  
24 - print members[name].uid + ', ' + members[name].home if members[name]  
25 - puts  
26 - end  
27 - puts  
28 -end  
29 -  
30 -backend.sites.each do |site|  
31 - puts 'site: ' + site.name  
32 - puts ' MailAliasRoles:'  
33 - backend.mailAliasRolesBySite(site).each{|account| puts ' ' + account.mail}  
34 - puts  
35 - puts ' MailAliasPeople:'  
36 - backend.mailAliasPeopleBySite(site).each{|account| puts ' ' + account.mail}  
37 - puts  
38 - puts ' MailAccounts:'  
39 - backend.mailAccountsBySite(site).each{|account| puts ' ' + account.mail}  
40 - puts  
41 -end  
42 -  
43 -backend.mailAliasRoles.each do |mailAlias|  
44 - puts 'mailAliasRole: '+mailAlias.mail.inspect+','+mailAlias.maildrop.inspect  
45 -end  
46 -  
47 -puts  
48 -  
49 -backend.mailAliasPeople.each do |mailAlias|  
50 - puts 'mailAliasPerson: '+mailAlias.mail.inspect+','+mailAlias.maildrop.inspect  
51 -end  
52 -  
53 -puts  
54 -  
55 -backend.mailAccounts.each do |mailAccount|  
56 - puts 'mailAccount: '+mailAccount.mail.inspect+','+mailAccount.mailbox.inspect  
57 -end  
58 -  
59 -puts  
60 -  
61 -georg = backend.userByName('georg')  
62 -georg.save  
63 -  
64 -puts  
65 -  
66 -georg.uid = 1001  
67 -georg.save  
68 -  
69 -puts  
70 -  
71 -wheel = backend.groupByName('wheel')  
72 -wheel.save  
73 -  
74 -puts  
75 -  
76 -wheel.gid = 100  
77 -wheel.save  
78 -  
79 -puts  
80 -  
81 -site = backend.siteByName('kommandozeilenchef.de')  
82 -site.save  
83 -  
84 -puts  
85 -  
86 -site.name = 'wumbaba.de'  
87 -site.save  
88 -  
89 -puts  
90 -  
91 -mail = MailAliasRole.new({  
92 - :backend => ldap,  
93 - :mail => 'newrole@kommandozeilenchef.de',  
94 - :maildrop => 'newrole',  
95 - :user => 'newrole'  
96 -})  
97 -mail.save  
98 -  
99 -puts  
100 -  
101 -mail = MailAliasPerson.new({  
102 - :backend => ldap,  
103 - :mail => 'ohotte@kommandozeilenchef.de',  
104 - :maildrop => 'ohotte',  
105 - :name => 'Onkel Hotte',  
106 - :surname => 'Hotte'  
107 -})  
108 -mail.save  
109 -  
110 -puts  
111 -  
112 -mail = MailAccount.new({  
113 - :backend => ldap,  
114 - :mail => 'foobar@kommandozeilenchef.de',  
115 - :mailbox => 'kommandozeilenchef.de/foobar',  
116 - :home => '/var/spool/vmail/domains'  
117 -})  
118 -mail.save  
119 -  
120 -puts  
121 -puts '====================================='  
122 -# -o vsz/vsize  
123 -puts 'Memory useage: ' + `ps -o rss= -p #{Process.pid}`  
1 -require 'sd_admin'  
2 -  
3 -user = SdAdmin::Model::User.new  
4 -  
5 -puts user.all.inspect  
  1 +require 'ds_admin'
  2 +
  3 +config = DsAdmin::Storage::Config.new(File.dirname(__FILE__) + '/config/storage.yml')
  4 +DsAdmin::Model.storage = DsAdmin::Storage::Ldap.new(config)
  5 +
  6 +user = DsAdmin::Model::User.new
  7 +group = DsAdmin::Model::Group.new
  8 +site = DsAdmin::Model::Site.new
  9 +alias_role = DsAdmin::Model::MailAliasRole.new
  10 +alias_person = DsAdmin::Model::MailAliasPerson.new
  11 +account = DsAdmin::Model::MailAccount.new
  12 +
  13 +puts '=== DsAdmin each ==='
  14 +user.each {|user| puts user.inspect}
  15 +puts '---'
  16 +group.each {|group| puts group.inspect}
  17 +puts '---'
  18 +site.each {|site| puts site.inspect}
  19 +puts '---'
  20 +alias_role.each {|ma_role| puts ma_role.inspect}
  21 +puts '---'
  22 +alias_person.each {|ma_person| puts ma_person.inspect}
  23 +puts '---'
  24 +account.each {|macc| puts macc.inspect}
  25 +
  26 +puts
  27 +puts '=== DsAdmin Enumerable ==='
  28 +puts user.find {|user| user.uid == '1000'}.inspect
  29 +puts '---'
  30 +puts group.find {|group| group.gid == '10'}.inspect
  31 +puts '---'
  32 +puts site.find {|site| site.name == 'steffers.org'}.inspect
  33 +puts '---'
  34 +puts alias_role.find_all {|mar| mar.maildrop == 'abuse'}.inspect
  35 +puts '---'
  36 +puts alias_person.find {|map| map.mail == 'georg@steffers.org'}.inspect
  37 +puts '---'
  38 +puts account.find {|acc| acc.mail == 'drachenfrau@steffers.org'}.inspect
Please register or login to post a comment