commit 953a2b4d0942a3ca69d941dc031485db21de1106
Author: Marc Dequènes (Duck) <Duck@DuckCorp.org>
Date:   Tue Oct 20 19:42:43 2009 +0200

    [evol/fix] fixed creation hooks call, hooks->plugins with hooks and simplified hooks, added plugin parameters in config and updated aspect/fs

diff --git a/conf/ldap_shadows/shadows/MilkyPond/aspects/fs.conf b/conf/ldap_shadows/shadows/MilkyPond/aspects/fs.conf
index 10d632c..b20e98f 100644
--- a/conf/ldap_shadows/shadows/MilkyPond/aspects/fs.conf
+++ b/conf/ldap_shadows/shadows/MilkyPond/aspects/fs.conf
@@ -13,3 +13,9 @@ relations:
     object: group
     many: uniqueMember
     foreign_key: dn
+plugin:
+  min_uid: 10000
+  max_uid: 65535
+  step_uid: 100
+  default_group: dc-users
+  default_home_base: '/home'
diff --git a/conf/ldap_shadows/shadows/MilkyPond/hooks/aspects/fs.rb b/conf/ldap_shadows/shadows/MilkyPond/hooks/aspects/fs.rb
deleted file mode 100644
index 00c4e17..0000000
--- a/conf/ldap_shadows/shadows/MilkyPond/hooks/aspects/fs.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-
-# TODO: should be in the configuration file, so find a way to get these parameters
-MIN_UID = 10000
-MAX_UID = 65535
-STEP_UID = 100
-DEFAULT_GROUP = 'dc-users'
-
-def self.hook_before_create(shadow, item)
-  hook_common(shadow, item)
-end
-
-def self.hook_before_modify(shadow, item)
-  hook_common(shadow, item)
-end
-
-def self.hook_common(shadow, item)
-  unless item.attribute_present?('gidNumber')
-    item.primaryGroup = shadow.get_object(:group).find(:first, DEFAULT_GROUP)
-  end
-
-  if item.attribute_present?('uidNumber')
-    user = ActiveLdap::Base.find(:first, :scope => :sub, :filter => "(&(objectClass=posixAccount)(uidNumber=#{item.uidNumber}))", :attributes => ['uidNumber'])
-    unless user.nil? or user.dn == item.dn
-      raise_error "UID already used by another item"
-    end
-  else
-    users = ActiveLdap::Base.find(:all, :scope => :sub, :filter => "(&(objectClass=posixAccount)(uidNumber=*))", :attributes => ['uidNumber'])
-    uidnumbers =  users.collect {|user| user.uidNumber }
-
-    avail_uidnumber = nil
-    min_uidn = MIN_UID
-    max_uidn = [min_uidn + STEP_UID, MAX_UID].min
-    while avail_uidnumber.nil?
-      avail = (min_uidn..max_uidn).to_a - uidnumbers
-      unless avail.empty?
-        avail_uidnumber = avail.first
-        break
-      end
-      min_uidn = max_uidn
-      max_uidn = [min_uidn + STEP_UID, MAX_UID].min
-    end
-
-    if avail_uidnumber.nil?
-      raise_error "Available UID range is depleted."
-    else
-      item.uidNumber = avail_uidnumber
-    end
-  end
-
-  unless item.attribute_present?('homeDirectory')
-    item.homeDirectory = "/home/" + item.uid
-  end
-end
diff --git a/conf/ldap_shadows/shadows/MilkyPond/hooks/objects/individual.rb b/conf/ldap_shadows/shadows/MilkyPond/hooks/objects/individual.rb
deleted file mode 100644
index 652126f..0000000
--- a/conf/ldap_shadows/shadows/MilkyPond/hooks/objects/individual.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-
-def self.hook_before_create(shadow, item)
-  unless item.attribute_present?('cn')
-    cn = item.surname || ""
-    cn = item.givenName + " " + cn if item.givenName
-    item.cn = cn
-  end
-end
-
diff --git a/conf/ldap_shadows/shadows/MilkyPond/plugins/aspects/fs.rb b/conf/ldap_shadows/shadows/MilkyPond/plugins/aspects/fs.rb
new file mode 100644
index 0000000..e6dfe6c
--- /dev/null
+++ b/conf/ldap_shadows/shadows/MilkyPond/plugins/aspects/fs.rb
@@ -0,0 +1,56 @@
+
+def self.hook_before_create(item)
+  hook_common(item)
+end
+
+def self.hook_before_modify(item)
+  hook_common(item)
+end
+
+def self.hook_common(item)
+  pconfig_default = {
+    :default_group     => 'users',
+    :min_uid           => 1000,
+    :max_uid           => 65535,
+    :step_uid          => 100,
+    :default_home_base => "/home"
+  }
+  pconfig = pconfig_default.merge(self.parameters[:plugin])
+
+  unless item.attribute_present?('gidNumber')
+    item.primaryGroup = item.class.shadow.get_object(:group).find(:first, pconfig[:default_group])
+  end
+
+  if item.attribute_present?('uidNumber')
+    user = ActiveLdap::Base.find(:first, :scope => :sub, :filter => "(&(objectClass=posixAccount)(uidNumber=#{item.uidNumber}))", :attributes => ['uidNumber'])
+    unless user.nil? or user.dn == item.dn
+      raise_error "UID already used by another item"
+    end
+  else
+    users = ActiveLdap::Base.find(:all, :scope => :sub, :filter => "(&(objectClass=posixAccount)(uidNumber=*))", :attributes => ['uidNumber'])
+    uidnumbers =  users.collect {|user| user.uidNumber }
+
+    avail_uidnumber = nil
+    min_uidn = pconfig[:min_uid]
+    max_uidn = [min_uidn + pconfig[:step_uid], pconfig[:max_uid]].min
+    while avail_uidnumber.nil?
+      avail = (min_uidn..max_uidn).to_a - uidnumbers
+      unless avail.empty?
+        avail_uidnumber = avail.first
+        break
+      end
+      min_uidn = max_uidn
+      max_uidn = [min_uidn + pconfig[:step_uid], pconfig[:max_uid]].min
+    end
+
+    if avail_uidnumber.nil?
+      raise_error "Available UID range is depleted."
+    else
+      item.uidNumber = avail_uidnumber
+    end
+  end
+
+  unless item.attribute_present?('homeDirectory')
+    item.homeDirectory = File.join(pconfig[:default_home_base], item.uid)
+  end
+end
diff --git a/conf/ldap_shadows/shadows/MilkyPond/plugins/objects/individual.rb b/conf/ldap_shadows/shadows/MilkyPond/plugins/objects/individual.rb
new file mode 100644
index 0000000..4bc7a6e
--- /dev/null
+++ b/conf/ldap_shadows/shadows/MilkyPond/plugins/objects/individual.rb
@@ -0,0 +1,9 @@
+
+def self.hook_before_create(item)
+  unless item.attribute_present?('cn')
+    cn = item.surname || ""
+    cn = item.givenName + " " + cn if item.givenName
+    item.cn = cn
+  end
+end
+
diff --git a/data/ldap_shadows/schema/aspect.yaml b/data/ldap_shadows/schema/aspect.yaml
index b41f3b0..e66b2ff 100644
--- a/data/ldap_shadows/schema/aspect.yaml
+++ b/data/ldap_shadows/schema/aspect.yaml
@@ -38,4 +38,8 @@ mapping:
           "foreign_key": {type: str, required: true}
           "many": {type: str}
           "primary_key": {type: str}
+  "plugin":
+    type: map
+    mapping:
+      =: {type: any}
 
diff --git a/data/ldap_shadows/schema/object.yaml b/data/ldap_shadows/schema/object.yaml
index 78967ae..8b2599a 100644
--- a/data/ldap_shadows/schema/object.yaml
+++ b/data/ldap_shadows/schema/object.yaml
@@ -6,8 +6,7 @@ mapping:
     required: true
     name: ObjectMapping
     mapping:
-      =:
-        type: any
+      =: {type: any}
   "presentation":
     type: map
     mapping:
@@ -40,4 +39,8 @@ mapping:
           "foreign_key": {type: str, required: true}
           "many": {type: str}
           "primary_key": {type: str}
+  "plugin":
+    type: map
+    mapping:
+      =: {type: any}
 
diff --git a/lib/ldap_shadows/config.rb b/lib/ldap_shadows/config.rb
index 8af9519..ef93f8a 100644
--- a/lib/ldap_shadows/config.rb
+++ b/lib/ldap_shadows/config.rb
@@ -78,7 +78,7 @@ module LdapShadows
       config = File.read(config_file)
 
       shadow = Shadow.new(shadow_name)
-      # register early (needed to load hooks)
+      # register early (needed to load plugins)
       @shadows[shadow_name] = {
         :config_path => shadow_config_path,
         :shadow => shadow
@@ -138,7 +138,7 @@ module LdapShadows
       s_info = get_shadow_info(shadow_name)
       return nil if s_info.nil?
 
-      filename = File.join(s_info[:config_path], "hooks", type.pluralize, hook_name.to_s.downcase + ".rb")
+      filename = File.join(s_info[:config_path], "plugins", type.pluralize, hook_name.to_s.downcase + ".rb")
       return nil unless File.exists?(filename)
 
       File.read(filename)
diff --git a/lib/ldap_shadows/elements.rb b/lib/ldap_shadows/elements.rb
index badc0c2..8f2b4a4 100644
--- a/lib/ldap_shadows/elements.rb
+++ b/lib/ldap_shadows/elements.rb
@@ -30,12 +30,12 @@ module LdapShadows
         def cast_relations; end
 
         # default empty hooks
-        def hook_before_create(shadow, item); end
-        def hook_before_modify(shadow, item); end
-        def hook_before_delete(shadow, item); end
-        def hook_after_create(shadow, item); end
-        def hook_after_modify(shadow, item); end
-        def hook_after_delete(shadow, item); end
+        def hook_before_create(item); end
+        def hook_before_modify(item); end
+        def hook_before_delete(item); end
+        def hook_after_create(item); end
+        def hook_after_modify(item); end
+        def hook_after_delete(item); end
 
         protected
 
diff --git a/lib/ldap_shadows/elements/object.rb b/lib/ldap_shadows/elements/object.rb
index 237f4fd..7a5a1c4 100755
--- a/lib/ldap_shadows/elements/object.rb
+++ b/lib/ldap_shadows/elements/object.rb
@@ -645,15 +645,23 @@ module Elements
       after_delete_jobs
     end
 
-    protected
+    # cannot override create_or_update() because of alias chaining
+    def save
+      before_save_jobs
+      r = super
+      after_save_jobs
+      r
+    end
 
-    def create_or_update
+    def save!
       before_save_jobs
       r = super
       after_save_jobs
       r
     end
 
+    protected
+
     def before_save_jobs
       check_hooks_before(:save)
       check_missing_attributes
@@ -668,14 +676,15 @@ module Elements
       case action
       when :save
         if self.new_entry?
-          self.class.hook_before_create(self.class.shadow, self)
+          self.class.hook_before_create(self)
         else
-          self.class.hook_before_modify(self.class.shadow, self)
+          self.class.hook_before_modify(self)
         end
       when :delete
-        self.class.hook_before_delete(self.class.shadow, self)
+        self.class.hook_before_delete(self)
       end
 
+      # TODO: move this in the LdapAspect class
       self.aspects.each do |aspect|
         aklass = self.class.shadow.get_aspect(aspect)
         next if aklass.nil?
@@ -683,12 +692,12 @@ module Elements
         case action
         when :save
           if self.new_entry?
-            aklass.hook_before_create(self.class.shadow, self)
+            aklass.hook_before_create(self)
           else
-            aklass.hook_before_modify(self.class.shadow, self)
+            aklass.hook_before_modify(self)
           end
         when :delete
-          aklass.hook_before_delete(self.class.shadow, self)
+          aklass.hook_before_delete(self)
         end
       end
     end
@@ -732,24 +741,25 @@ module Elements
         case action
         when :save
           if self.new_entry?
-            aklass.hook_after_create(self.class.shadow, self)
+            aklass.hook_after_create(self)
           else
-            aklass.hook_after_modify(self.class.shadow, self)
+            aklass.hook_after_modify(self)
           end
         when :delete
-          aklass.hook_after_delete(self.class.shadow, self)
+          aklass.hook_after_delete(self)
         end
       end
 
+      # TODO: move this in the LdapAspect class
       case action
       when :save
         if self.new_entry?
-          self.class.hook_after_create(self.class.shadow, self)
+          self.class.hook_after_create(self)
         else
-          self.class.hook_after_modify(self.class.shadow, self)
+          self.class.hook_after_modify(self)
         end
       when :delete
-        self.class.hook_after_delete(self.class.shadow, self)
+        self.class.hook_after_delete(self)
       end
     end
 
