From d7a3f878c984040f478064f7ddabe0bfbfa13d8e Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Thu, 28 Apr 2011 12:44:00 +0200 Subject: [PATCH] initial checkin - nothings final This is the first checkin for some experiments with net-ldap to create an admin tool for my ldap database (user, groups, domains, mail-aliases and mail-accounts) The final tool should make it ease to add, modify and delete each of these with either a terminal- or a webinterface. --- .gitignore | 1 + Group.rb | 14 +++++++ MailAccount.rb | 17 ++++++++ MailAlias.rb | 17 ++++++++ Site.rb | 9 +++++ SystemData.rb | 16 ++++++++ SystemDataBackend.rb | 84 ++++++++++++++++++++++++++++++++++++++++ SystemDataBackendLdap.rb | 84 ++++++++++++++++++++++++++++++++++++++++ User.rb | 16 ++++++++ test_dummy.rb | 46 ++++++++++++++++++++++ 10 files changed, 304 insertions(+) create mode 100644 .gitignore create mode 100644 Group.rb create mode 100644 MailAccount.rb create mode 100644 MailAlias.rb create mode 100644 Site.rb create mode 100644 SystemData.rb create mode 100644 SystemDataBackend.rb create mode 100644 SystemDataBackendLdap.rb create mode 100644 User.rb create mode 100644 test_dummy.rb diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a01ee28 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.*.swp diff --git a/Group.rb b/Group.rb new file mode 100644 index 0000000..e607420 --- /dev/null +++ b/Group.rb @@ -0,0 +1,14 @@ +require 'SystemData' + +class Group < SystemData + attr_accessor :name, :gid, :members + + def initialize(args = {}) + super(args) + + @name = args[:name] + @gid = args[:gid] + @members = args[:members] + @members = Array.new if @members.nil? + end +end diff --git a/MailAccount.rb b/MailAccount.rb new file mode 100644 index 0000000..a6ec9fd --- /dev/null +++ b/MailAccount.rb @@ -0,0 +1,17 @@ +require 'SystemData' + +class MailAccount < SystemData + attr_accessor :mail, :mailbox + + def initialize(args = {}) + super(args) + + @mail = args[:mail] + @home = args[:home] + @mailbox = args[:mailbox] + end + + def site + @mail.sub(/.*@/, '') + end +end diff --git a/MailAlias.rb b/MailAlias.rb new file mode 100644 index 0000000..b7f4c9c --- /dev/null +++ b/MailAlias.rb @@ -0,0 +1,17 @@ +require 'SystemData' + +class MailAlias < SystemData + attr_accessor :mail, :maildrop, :user + + def initialize(args = {}) + super(args) + + @mail = args[:mail] + @maildrop = args[:maildrop] + @user = args[:user] + end + + def site + @mail.sub(/.*@/, '') + end +end diff --git a/Site.rb b/Site.rb new file mode 100644 index 0000000..313166a --- /dev/null +++ b/Site.rb @@ -0,0 +1,9 @@ +require 'SystemData' + +class Site < SystemData + attr_accessor :name, :mailAccounts, :mailAliases + + def initialize(args = {}) + @name = args[:name] + end +end diff --git a/SystemData.rb b/SystemData.rb new file mode 100644 index 0000000..79fe4a4 --- /dev/null +++ b/SystemData.rb @@ -0,0 +1,16 @@ +class SystemData + attr_reader :id + + def initialize(args = {}) + @backend = args[:backend] + @id = args[:id] + end + + def save + if @id + @backend.update(self) + else + @backend.insert(self) + end + end +end diff --git a/SystemDataBackend.rb b/SystemDataBackend.rb new file mode 100644 index 0000000..75df516 --- /dev/null +++ b/SystemDataBackend.rb @@ -0,0 +1,84 @@ +require 'User' +require 'Group' +require 'Site' +require 'MailAlias' +require 'MailAccount' + +class SystemDataBackend + + def initialize(backend) + @backend = backend + @data = Hash.new + end + + def users + load(:user) + end + + def groups + load(:group) + end + + def sites + load(:site) + end + + def mailAliases + load(:mailAlias) + end + + def mailAccounts + load(:mailAccount) + end + + def userByName(name) + users.find{|user| user.name == name} + end + + def groupByName(name) + groups.find{|group| group.name == name} + end + + def siteByName(name) + sites.find{|site| site.name == name} + end + + def usersInGroup(group) + case + when group.members.instance_of?(Array): + Hash[group.members.map{|uid| [uid, userByName(uid)] if userByName(uid)}] + when goup.members.nil?: + {} + else + {group.members => userByName(group.members)} if userByName(group.members) + end + end + + def mailAliasesBySite(site) + mailAliases.find_all{|mail| mail.site == site.name} + end + + def mailAccountsBySite(site) + mailAccounts.find_all{|mail| mail.site == site.name} + end + + private + + def load(kind) + load!(kind) if ! @data[kind] + @data[kind] + end + + def load!(kind) + @data[kind] = Array.new + class_str = kind.to_s + class_str[0] = class_str[0..0].capitalize + + @backend.load(kind) do |data| + @data[kind].push( + eval(class_str + '.new(data)') + ) + end + end + +end diff --git a/SystemDataBackendLdap.rb b/SystemDataBackendLdap.rb new file mode 100644 index 0000000..5b28818 --- /dev/null +++ b/SystemDataBackendLdap.rb @@ -0,0 +1,84 @@ +require 'active_support/secure_random' +require 'net/ldap' + +class SystemDataBackendLdap + + LDAP_USER_MAP = { + :uid => :name, + :userpassword => :pass, + :uidnumber => :uid, + :gidnumber => :gid, + :loginshell => :shell, + :homedirectory => :home + } + + LDAP_GROUP_MAP = { + :cn => :name, + :gidnumber => :gid, + :memberuid => :members + } + + LDAP_SITE_MAP = {:o => :name} + + LDAP_MAP = { + :user => LDAP_USER_MAP, + :group => LDAP_GROUP_MAP, + :site => LDAP_SITE_MAP + } + + LDAP_FILTER = { + :user => Net::LDAP::Filter::eq('objectClass', 'posixAccount'), + :group => Net::LDAP::Filter::eq('objectClass', 'posixGroup'), + :site => Net::LDAP::Filter::eq('objectClass', 'organization') & + (~Net::LDAP::Filter::eq('o', 'hosting')), + :mailAlias => Net::LDAP::Filter::eq('objectClass', 'mailAlias'), + :mailAccount => Net::LDAP::Filter::eq('objectClass', 'mailAccount') + } + + + def initialize(host, port, baseDn, args={}) + @baseDn = baseDn + @systemDn = 'o=system,' + @baseDn + @hostingDn = 'o=hosting,' + @baseDn + + @systemDn = args[:systemDn] if args[:systemDn] + @hostingDn = args[:hostingDn] if args[:hostingDn] + + @ldap = Net::LDAP.new(:host => host, :port => port) + @ldapData = Hash.new + end + + def load!(kind) + @ldapData[kind] = @ldap.search( + :base => ldapBase(kind), + :filter => LDAP_FILTER[kind] + ) + end + + def load(kind) + load!(kind) if ! @ldapData[kind] + + @ldapData[kind].each do |data| + map = { :dn => :id } + map.merge!(LDAP_MAP[kind]) if LDAP_MAP[kind] + + ydata = { :backend => self } + + data.each do |key,value| + ydata.merge!({ map[key] || key => value.size==1?value[0]:value.to_a }) + end + + yield ydata + end + end + + private + + def ldapBase(kind) + case(kind) + when :user, :group: @systemDn + when :site, :mailAlias, :mailAccount: @hostingDn + end + end + +end diff --git a/User.rb b/User.rb new file mode 100644 index 0000000..68bb781 --- /dev/null +++ b/User.rb @@ -0,0 +1,16 @@ +require 'SystemData' + +class User < SystemData + attr_accessor :name, :pass, :uid, :gid, :shell, :home + + def initialize(args = {}) + super(args) + + @name = args[:name] + @pass = args[:pass] + @uid = args[:uid] + @gid = args[:gid] + @shell = args[:shell] + @home = args[:home] + end +end diff --git a/test_dummy.rb b/test_dummy.rb new file mode 100644 index 0000000..963fa28 --- /dev/null +++ b/test_dummy.rb @@ -0,0 +1,46 @@ +require 'SystemDataBackend' +require 'SystemDataBackendLdap' + +backend = SystemDataBackend.new( + SystemDataBackendLdap.new('host.one.virtual', 389, 'dc=weird-web-workers,dc=org') +) + +backend.users.each do |user| + puts 'user: '+user.name+','+user.uid+','+user.gid+','+user.home +end + +puts + +backend.groups.each do |group| + members = backend.usersInGroup(group) + + puts 'group: '+group.name+','+group.gid + puts ' members:' + group.members.each do |name| + print ' ' + name + ': ' + print members[name].uid + ', ' + members[name].home if members[name] + puts + end + puts +end + +backend.sites.each do |site| + puts 'site: ' + site.name + puts ' MailAliases:' + backend.mailAliasesBySite(site).each{|account| puts ' ' + account.mail} + puts + puts ' MailAccounts:' + backend.mailAccountsBySite(site).each{|account| puts ' ' + account.mail} + puts +end + +backend.mailAliases.each do |mailAlias| + puts 'mailAlias: '+mailAlias.mail.inspect+','+mailAlias.maildrop.inspect +end + +puts + +backend.mailAccounts.each do |mailAccount| + puts 'mailAccount: '+mailAccount.mail.inspect+','+mailAccount.mailbox.inspect +end +