commit 591ec1a28b9af67269f9b79f3c6aa7853283833b
Author: Marc Dequenes <duck@Orfeo.duckcorp.org>
Date:   Tue Feb 17 13:43:32 2009 +0100

    [evol] add abstraction level above LDAP layer #2 + cleanup + indent

diff --git a/postman b/postman
index 1e9a76f..e03f0fc 100755
--- a/postman
+++ b/postman
@@ -6,9 +6,6 @@
 
 $: << "./lib"
 
-$KCODE = 'UTF8'
-require 'jcode'
-require 'log4r'
 require 'net/imap'
 require 'tmail'
 require 'tmail_extra'
@@ -20,15 +17,33 @@ require 'active_ldap'
 require 'shellwords'
 require 'cyborghood/base'
 
-logger = Log4r::Logger.new('test')
-logger.outputters = Log4r::StderrOutputter.new('')
-logger.level = Log4r::WARN
-#logger.level = Log4r::DEBUG
-
 class LdapPerson < ActiveLdap::Base
   ldap_mapping :dn_attribute => 'uid', :prefix => '', :classes => ['person', 'extInetOrgPerson']
 end
 
+class Person < Delegator
+  attr_reader :ldap
+
+  def self.find_by_fingerprint(fingerprint)
+    list = LdapPerson.find(:all, :attribute => 'keyFingerPrint', :value => fingerprint)
+    case list.size
+    when 0
+      nil
+    when 1
+      person = allocate
+      person.instance_variable_set("@ldap", list.first)
+      person
+    else
+      logger.warn "Multiple users match in database, so i guess there is a mistake. It is safer to skip..."
+      nil
+    end
+  end
+
+  def __getobj__
+    @ldap
+  end
+end
+
 class LdapDnsDomain < ActiveLdap::Base
   ldap_mapping :dn_attribute => 'cn', :prefix => '', :classes => ['genericDomain']
 
@@ -41,10 +56,11 @@ class LdapDnsDomain < ActiveLdap::Base
 end
 
 class DnsDomain < Delegator
-  attr_reader :name
+  attr_reader :ldap, :name
 
   def initialize(name)
-    raise "invalid zone name" unless self.is_valid?(name)
+    @name = name
+    raise "invalid zone name" unless self.is_valid?
 
     # may not exist (if creating a new one)
     begin
@@ -58,17 +74,29 @@ class DnsDomain < Delegator
     name =~ /^[a-z0-9.-]+\.[a-z]{2,4}$/
   end
 
-  def is_valid?(name)
-    self.class.is_valid?(name)
+  def is_valid?
+    self.class.is_valid?(@name)
   end
 
-  def managed?
+  def hosted?
     not @ldap.nil?
   end
 
+  def managed_by?(user)
+    @ldap.managers.include? user.ldap.dn
+  end
+
   def __getobj__
     @ldap
   end
+
+  def self.find_by_manager(user)
+    list = LdapDnsDomain.find(:all, :attribute => 'manager', :value => user.ldap.dn)
+    list.collect do |l_dom|
+      domain = allocate
+      domain.instance_variable_set("@ldap", l_dom)
+    end
+  end
 end
 
 #Socket.gethostname
@@ -108,30 +136,30 @@ class CommandParser
     when "DNS"
       case cmdline.shift.upcase
       when "INFO"
-	if cmdline.empty?
-          list = LdapDnsDomain.find(:all, :attribute => 'manager', :value => user.dn)
-	  logger.info "User is manager of the following zones: " + list.collect{|z| z.cn }.join(", ")
-	else
-	  ok = false
-	end
+        if cmdline.empty?
+          list = DnsDomain.find_by_manager(user)
+          logger.info "User is manager of the following zones: " + list.collect{|z| z.cn }.sort.join(", ")
+        else
+          ok = false
+        end
       when "GET"
         case cmdline.shift.upcase
         when "ZONE"
           zone = cmdline.shift.downcase
-	  dom = DnsDomain.new(zone)
-	  logger.info "User requesting zone content for '#{zone}'"
-	  if dom.managed?
-	    if dom.managers.include? user.dn
-	      logger.info "User is manager of the zone"
-	    else
-	      logger.info "User is not allowed to manage the zone"
-	    end
-	  else
-	    logger.info "Zone not managed"
-	  end
-	else
-	  ok = false
-	end
+          dom = DnsDomain.new(zone)
+          logger.info "User requesting zone content for '#{zone}'"
+          if dom.hosted?
+            if dom.managed_by? user
+              logger.info "User is manager of the zone"
+            else
+              logger.info "User is not allowed to manage the zone"
+            end
+          else
+            logger.info "Zone not hosted"
+          end
+        else
+          ok = false
+        end
       when "SET"
       else
         ok = false
@@ -182,47 +210,43 @@ module CyborgHood
         # unquote headers and transform into TMail object
         mail = TMail::Mail.parse(TMail::Unquoter.unquote_and_convert_to(msg, "UTF-8"))
 
-	logger.set_prefix()
+        logger.set_prefix()
         logger.debug "######################################"
-	logger.set_prefix("[#{mail.message_id}] ")
+        logger.set_prefix("[#{mail.message_id}] ")
         logger.info "#{mail.from_addrs} -> #{mail.to_addrs}: #{mail.subject}"
         # ignore mails not signed
-	unless mail.is_pgp_signed?
-	  logger.info "Mail not signed or not RFC3156 compliant"
+        unless mail.is_pgp_signed?
+          logger.info "Mail not signed or not RFC3156 compliant"
           next
-	end
+        end
 
         logger.debug "Proper signed content detected"
-	sig_check = mail.verify_pgp_signature()
+        sig_check = mail.verify_pgp_signature()
         if sig_check.status == 0
           logger.info "Mail content was properly signed by key #{sig_check.fingerprint}"
-      	  list = LdapPerson.find(:all, :attribute => 'keyFingerPrint', :value => sig_check.fingerprint)
-      	  case list.size
-      	  when 0
-      	    logger.info "Mail is from an unknown person"
-      	  when 1
-      	    user = list.first
-      	    logger.info "Mail is from user #{user.uid} (#{user.cn})"
+          user = Person.find_by_fingerprint(sig_check.fingerprint)
+          if user.nil?
+            logger.info "Mail is from an unknown person"
+          else
+            logger.info "Mail is from user #{user.uid} (#{user.cn})"
 
             signed_content = mail.pgp_signed_part()
-	    if signed_content.multipart?
-	      if signed_content.parts[0].content_type == "text/plain"
-	        command_txt = signed_content.parts[0].body
-		command_refs = signed_content.parts.collect{|p| p.dup }
-	      end
-	    else
-	      command_txt = signed_content.body if signed_content.content_type == "text/plain"
-	      command_refs = []
-	    end
-
-	    if command_txt
-      	      CommandParser.run(user, command_txt, command_refs)
-	    else
-	      logger.info "Mail does not contain a proper MIME part for commands"
-	    end
-      	  else
-      	    logger.warn "Multiple users match in database, so i guess there is a mistake. It is safer to skip..."
-      	  end
+            if signed_content.multipart?
+              if signed_content.parts[0].content_type == "text/plain"
+                command_txt = signed_content.parts[0].body
+                command_refs = signed_content.parts.collect{|p| p.dup }
+              end
+            else
+              command_txt = signed_content.body if signed_content.content_type == "text/plain"
+              command_refs = []
+            end
+
+            if command_txt
+              CommandParser.run(user, command_txt, command_refs)
+            else
+              logger.info "Mail does not contain a proper MIME part for commands"
+            end
+          end
         else
           logger.info "Mail content tampered or badly signed: " + sig_check.to_s
         end
@@ -245,4 +269,3 @@ trap('TERM') do
 end
 
 bot.run
-
