Commit 77f3f376544384b8ac52a1bc7b84c34183129f7c

Authored by Georg GH. Hopp
Committed by Georg Hopp
1 parent a4818bf1

add functionality for create, update, delete

@@ -13,6 +13,8 @@ @@ -13,6 +13,8 @@
13 - 'posixAccount' 13 - 'posixAccount'
14 - 'shadowAccount' 14 - 'shadowAccount'
15 15
  16 + :dnPat: "uid=#{:name}"
  17 +
16 :map: 18 :map:
17 :uid: :name 19 :uid: :name
18 :userpassword: :pass 20 :userpassword: :pass
@@ -28,6 +30,8 @@ @@ -28,6 +30,8 @@
28 30
29 :objectClass: 'posixGroup' 31 :objectClass: 'posixGroup'
30 32
  33 + :dnPat: "cn=#{:name}"
  34 +
31 :map: 35 :map:
32 :cn: :name 36 :cn: :name
33 :gidnumber: :gid 37 :gidnumber: :gid
@@ -40,6 +44,8 @@ @@ -40,6 +44,8 @@
40 44
41 :objectClass: 'organization' 45 :objectClass: 'organization'
42 46
  47 + :dnPat: "o=#{:name}"
  48 +
43 :map: 49 :map:
44 :o: :name 50 :o: :name
45 51
@@ -52,6 +58,8 @@ @@ -52,6 +58,8 @@
52 - 'organizationalRole' 58 - 'organizationalRole'
53 - 'MailAlias' 59 - 'MailAlias'
54 60
  61 + :dnPat: "cn=#{:user},o=#{:mail|sub(/.*@/, '')}"
  62 +
55 :map: 63 :map:
56 :cn: :user 64 :cn: :user
57 65
@@ -64,6 +72,8 @@ @@ -64,6 +72,8 @@
64 - 'person' 72 - 'person'
65 - 'MailAlias' 73 - 'MailAlias'
66 74
  75 + :dnPat: "mail=#{:mail},o=#{:mail|sub(/.*@/, '')}"
  76 +
67 :map: 77 :map:
68 :sn: :surname 78 :sn: :surname
69 :cn: :name 79 :cn: :name
@@ -77,6 +87,8 @@ @@ -77,6 +87,8 @@
77 - 'person' 87 - 'person'
78 - 'MailAccount' 88 - 'MailAccount'
79 89
  90 + :dnPat: "mail=#{:mail},o=#{:mail|sub(/.*@/, '')}"
  91 +
80 :map: 92 :map:
81 :homedirectory: :home 93 :homedirectory: :home
82 94
@@ -50,13 +50,19 @@ module DsAdmin::Model @@ -50,13 +50,19 @@ module DsAdmin::Model
50 # always has to be stored back into @id 50 # always has to be stored back into @id
51 # 51 #
52 def save 52 def save
53 - @id = @storage.write(self) 53 + @id = @@storage.write(self)
54 end 54 end
55 55
56 def config_key 56 def config_key
57 self.class.to_s.to_sym 57 self.class.to_s.to_sym
58 end 58 end
59 59
  60 + def to_h
  61 + Hash[instance_variables.map do |var|
  62 + [var[1...var.size].to_sym, instance_variable_get(var)]
  63 + end]
  64 + end
  65 +
60 protected 66 protected
61 def _load(id) 67 def _load(id)
62 @@storage.config.model = self 68 @@storage.config.model = self
@@ -7,13 +7,19 @@ class DsAdmin::Model::User @@ -7,13 +7,19 @@ class DsAdmin::Model::User
7 return if args.empty? 7 return if args.empty?
8 super(args) 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] 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 + @shadowlastchange = args[:shadowlastchange]
  19 + end
  20 +
  21 + def save
  22 + @shadowlastchange = (Time::now.to_i/60/60/24).to_s
  23 + super
18 end 24 end
19 end 25 end
@@ -16,4 +16,12 @@ class DsAdmin::Storage::Config @@ -16,4 +16,12 @@ class DsAdmin::Storage::Config
16 def map(storage) 16 def map(storage)
17 @config[storage.config_key][@model.config_key][:map] 17 @config[storage.config_key][@model.config_key][:map]
18 end 18 end
  19 +
  20 + def object_class(storage)
  21 + @config[storage.config_key][@model.config_key][:objectClass]
  22 + end
  23 +
  24 + def dn_pat(storage)
  25 + @config[storage.config_key][@model.config_key][:dnPat]
  26 + end
19 end 27 end
@@ -17,18 +17,97 @@ class DsAdmin::Storage::Ldap @@ -17,18 +17,97 @@ class DsAdmin::Storage::Ldap
17 # - map the id's from the ldap search resulte into id's used in 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. 18 # the models. The mapping is read from the config.
19 # 19 #
20 - foo = @ldap.search(query).map do |data| 20 + @ldap.search(query).map do |data|
21 map = { :dn => :id } 21 map = { :dn => :id }
22 map.merge!(@config.map(self)) 22 map.merge!(@config.map(self))
23 23
  24 + remap(data, map)
  25 + end
  26 + end
  27 +
  28 + def write(model)
  29 + @config.model = model
  30 +
  31 + data = model.to_h
  32 + odata = read.find{|od| od[:id] == data[:id]}
  33 +
  34 + return create(data) unless odata
  35 +
  36 + update(odata, data)
  37 + end
  38 +
  39 + protected
  40 + def create(data)
  41 + map = @config.map(self).invert
  42 + scan_exp = /(^|, *)([^=]*=)(([^#][^,]*)|#\{([^|}]*)(\|([^}]*))?\})/
  43 +
  44 + dn = String.new
  45 + @config.dn_pat(self).scan(scan_exp) do |m|
  46 + val = m[3] if m[3]
  47 + val = data[m[4][1..m[4].length].to_sym] if m[4]
  48 + val = eval('"' + val + '".send ' + m[6]) if data && m[6]
  49 +
  50 + dn += m[0] + m[1] + val
  51 + end
  52 + dn += ',' + @config.query(self)[:base]
  53 +
  54 + data.delete(:id)
  55 +
  56 + entry = Net::LDAP::Entry.new(dn)
  57 + entry[:changetype] = 'add'
  58 + entry[:objectclass] = @config.object_class(self)
  59 + remap(data, @config.map(self).invert).each {|key,value| entry[key] = value}
  60 +
  61 + puts entry.to_ldif # TODO: make real writes
  62 + return dn
  63 + end
  64 +
  65 + def update(old, new)
  66 + new.delete(:id)
  67 + replace = remap(
  68 + new.find_all{|key,value| value != old[key]},
  69 + @config.map(self).invert
  70 + )
  71 +
  72 + ##
  73 + # if the given model already has an id;
  74 + #
  75 + # check if ldap dn has to be changed in order to
  76 + # reflect the attributes.
  77 + # if so, remove old entry
  78 + #
  79 + replace.each do |key,value|
  80 + if old[:id] =~ /(^|, *)#{key.to_s}=([^, ]+)/ && $2 != value
  81 + delete(old[:id])
  82 + return create(new)
  83 + end
  84 + end
  85 +
  86 + entry = Net::LDAP::Entry.new(old[:id])
  87 + entry[:changetype] = 'modify'
  88 + entry[:replace] = replace.keys
  89 + replace.each {|key,value| entry[key] = value }
  90 +
  91 + puts entry.to_ldif # TODO: make real writes
  92 + return old[:id]
  93 + end
  94 +
  95 + def delete(id)
  96 + entry = Net::LDAP::Entry.new(id)
  97 + entry[:changetype] = 'delete'
  98 +
  99 + puts entry.to_ldif # TODO: make real writes
  100 + return true
  101 + end
  102 +
  103 + def remap(data, map)
24 remapped = Hash.new 104 remapped = Hash.new
25 data.each do |key,value| 105 data.each do |key,value|
26 key = map[key] || key 106 key = map[key] || key
27 value = value.size==1 ? value[0] : value.to_a 107 value = value.size==1 ? value[0] : value.to_a
28 108
29 remapped.merge!({ key => value }) 109 remapped.merge!({ key => value })
30 - end 110 + end if data
31 remapped 111 remapped
32 - end  
33 end 112 end
34 end 113 end
@@ -117,4 +117,36 @@ account.load!('mail=drachenfrau@steffers.org,o=steffers.org,o=hosting,dc=weird-w @@ -117,4 +117,36 @@ account.load!('mail=drachenfrau@steffers.org,o=steffers.org,o=hosting,dc=weird-w
117 puts 'base: ' + account.inspect 117 puts 'base: ' + account.inspect
118 118
119 puts 119 puts
  120 +puts '=== Model#to_h ==='
  121 +puts user.to_h.inspect
  122 +puts 'base: ' + user.inspect
  123 +puts '---'
  124 +puts group.to_h.inspect
  125 +puts 'base: ' + group.inspect
  126 +puts '---'
  127 +puts site.to_h.inspect
  128 +puts 'base: ' + site.inspect
  129 +puts '---'
  130 +puts alias_role.to_h.inspect
  131 +puts 'base: ' + alias_role.inspect
  132 +puts '---'
  133 +puts alias_person.to_h.inspect
  134 +puts 'base: ' + alias_person.inspect
  135 +puts '---'
  136 +puts account.to_h.inspect
  137 +puts 'base: ' + account.inspect
  138 +
  139 +puts
  140 +puts '=== Storage#update ==='
  141 +user.home = '/home/user/foo'
  142 +puts 'returns: ' + user.save
  143 +puts 'base: ' + user.inspect
  144 +
  145 +puts
  146 +puts '=== Storage#update(replace[delete,create]) ==='
  147 +user.name = 'brad'
  148 +puts 'returns: ' + user.save
  149 +puts 'base: ' + user.inspect
  150 +
  151 +puts
120 puts 'Memory useage: ' + `ps -o rss= -p #{Process.pid}` 152 puts 'Memory useage: ' + `ps -o rss= -p #{Process.pid}`
Please register or login to post a comment