From 666ae5b6fd8823340081c236abe54007fb7540fd Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Fri, 13 May 2011 06:25:51 +0200 Subject: [PATCH] heavy restructuring implemented new design --- Group.rb | 14 --- MailAccount.rb | 17 --- MailAliasPerson.rb | 18 ---- MailAliasRole.rb | 17 --- Site.rb | 11 -- SystemData.rb | 24 ----- SystemDataBackend.rb | 91 ---------------- SystemDataBackendLdap.rb | 197 ----------------------------------- User.rb | 18 ---- controllers/system_data.rb | 91 ---------------- database.rb | 10 -- database/base.rb | 13 --- database/factory.rb | 3 - database/ldap.rb | 53 ---------- docs/development/mystuff.dia | Bin 0 -> 2802 bytes docs/development/was.txt | 66 ++++++++++++ ds_admin.rb | 4 + loader/user.rb | 0 mappers/ldap.rb | 197 ----------------------------------- model.rb | 72 ++++++++++--- model/base.rb | 9 -- model/group.rb | 12 +-- model/interface.rb | 7 -- model/mail_account.rb | 5 +- model/mail_alias_person.rb | 5 +- model/mail_alias_role.rb | 5 +- model/site.rb | 5 +- model/system_data.rb | 24 ----- model/user.rb | 30 +++--- sd_admin.rb | 10 -- storage.rb | 37 +++++++ storage/config.rb | 21 ++++ storage/ldap.rb | 34 ++++++ storage/mysql.rb | 3 + test_dummy.rb | 123 ---------------------- test_dummy2.rb | 5 - tester.rb | 38 +++++++ 37 files changed, 296 insertions(+), 993 deletions(-) delete mode 100644 Group.rb delete mode 100644 MailAccount.rb delete mode 100644 MailAliasPerson.rb delete mode 100644 MailAliasRole.rb delete mode 100644 Site.rb delete mode 100644 SystemData.rb delete mode 100644 SystemDataBackend.rb delete mode 100644 SystemDataBackendLdap.rb delete mode 100644 User.rb delete mode 100644 controllers/system_data.rb delete mode 100644 database.rb delete mode 100644 database/base.rb delete mode 100644 database/factory.rb delete mode 100644 database/ldap.rb create mode 100644 docs/development/mystuff.dia create mode 100644 docs/development/was.txt create mode 100644 ds_admin.rb delete mode 100644 loader/user.rb delete mode 100644 mappers/ldap.rb delete mode 100644 model/base.rb delete mode 100644 model/interface.rb delete mode 100644 model/system_data.rb delete mode 100644 sd_admin.rb create mode 100644 storage.rb create mode 100644 storage/config.rb create mode 100644 storage/ldap.rb create mode 100644 storage/mysql.rb delete mode 100644 test_dummy.rb delete mode 100644 test_dummy2.rb create mode 100644 tester.rb diff --git a/Group.rb b/Group.rb deleted file mode 100644 index e607420..0000000 --- a/Group.rb +++ /dev/null @@ -1,14 +0,0 @@ -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 deleted file mode 100644 index a6ec9fd..0000000 --- a/MailAccount.rb +++ /dev/null @@ -1,17 +0,0 @@ -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/MailAliasPerson.rb b/MailAliasPerson.rb deleted file mode 100644 index e4308ce..0000000 --- a/MailAliasPerson.rb +++ /dev/null @@ -1,18 +0,0 @@ -require 'SystemData' - -class MailAliasPerson < SystemData - attr_accessor :mail, :maildrop, :surname, :name - - def initialize(args = {}) - super(args) - - @mail = args[:mail] - @maildrop = args[:maildrop] - @surname = args[:surname] - @name = args[:name] - end - - def site - @mail.sub(/.*@/, '') - end -end diff --git a/MailAliasRole.rb b/MailAliasRole.rb deleted file mode 100644 index c16b474..0000000 --- a/MailAliasRole.rb +++ /dev/null @@ -1,17 +0,0 @@ -require 'SystemData' - -class MailAliasRole < 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 deleted file mode 100644 index 133ccbe..0000000 --- a/Site.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'SystemData' - -class Site < SystemData - attr_accessor :name - - def initialize(args = {}) - super(args) - - @name = args[:name] - end -end diff --git a/SystemData.rb b/SystemData.rb deleted file mode 100644 index ec1652b..0000000 --- a/SystemData.rb +++ /dev/null @@ -1,24 +0,0 @@ -class SystemData - attr_reader :id - - def initialize(args = {}) - @backend = args[:backend] - @id = args[:id] - end - - def save - kind = self.class.to_s.to_sym - - if @id - @backend.update(kind, to_h) - else - @backend.insert(kind, to_h) - end - end - - def to_h - Hash[instance_variables.map do |var| - [var[1...var.size].to_sym, eval(var)] if var != '@backend' - end] - end -end diff --git a/SystemDataBackend.rb b/SystemDataBackend.rb deleted file mode 100644 index a53089f..0000000 --- a/SystemDataBackend.rb +++ /dev/null @@ -1,91 +0,0 @@ -require 'User' -require 'Group' -require 'Site' -require 'MailAliasRole' -require 'MailAliasPerson' -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 mailAliasRoles - load(:MailAliasRole) - end - - def mailAliasPeople - load(:MailAliasPerson) - 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 mailAliasRolesBySite(site) - mailAliasRoles.find_all{|mail| mail.site == site.name} - end - - def mailAliasPeopleBySite(site) - mailAliasPeople.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 - @backend.load(kind) do |data| - data[:backend] = @backend - @data[kind].push( - eval(kind.to_s + '.new(data)') - ) - end - end - -end diff --git a/SystemDataBackendLdap.rb b/SystemDataBackendLdap.rb deleted file mode 100644 index a660087..0000000 --- a/SystemDataBackendLdap.rb +++ /dev/null @@ -1,197 +0,0 @@ - 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_MAILALIASPERSON_MAP = { - :sn => :surname, - :cn => :name - } - - LDAP_MAP = { - :User => LDAP_USER_MAP, - :Group => LDAP_GROUP_MAP, - :Site => { :o => :name }, - :MailAliasRole => { :cn => :user }, - :MailAliasPerson => LDAP_MAILALIASPERSON_MAP, - :mailAccount => { :homedirectory => :home } - } - - LDAP_FILTER = { - :User => '(objectClass=posixAccount)', - :Group => '(objectClass=posixGroup)', - :Site => '(&(objectClass=organization)(!(o=hosting)))', - :MailAliasRole => '(&(objectClass=MailAlias)(objectClass=organizationalrole))', - :MailAliasPerson => '(&(objectClass=MailAlias)(objectClass=person))', - :MailAccount => '(objectClass=mailAccount)' - } - - LDAP_OBJECTCLASS = { - :User => [ 'account', 'posixAccount', 'shadowAccount' ], - :Group => 'posixGroup', - :Site => 'organization', - :MailAliasRole => [ 'organizationalRole', 'MailAlias' ], - :MailAliasPerson => [ 'person', 'MailAlias' ], - :MailAccount => [ 'person', 'MailAccount' ] - } - - LDAP_LAMBDA_USER = lambda do |entry| - entry[:cn] = entry[:uid] - entry[:shadowlastchange] = (Time::now.to_i/60/60/24).to_s - entry[:replace] += ['shadowreplace'] if entry[:replace] - end - - LDAP_LAMBDA = { - :User => LDAP_LAMBDA_USER - } - - 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] = Hash.new if ! @ldapData[kind] - - @ldapData[kind][:int] = @ldap.search( - :base => ldapBase(kind), - :filter => Net::LDAP::Filter::construct(LDAP_FILTER[kind]) - ) - end - - def load(kind) - load!(kind) if ! @ldapData[kind] - - @ldapData[kind][:ext] = @ldapData[kind][:int].map do |data| - map = { :dn => :id } - map.merge!(LDAP_MAP[kind]) if LDAP_MAP[kind] - - ydata = {} - data.each do |key,value| - ydata.merge!({ map[key] || key => value.size==1?value[0]:value.to_a }) - end - ydata - end if ! @ldapData[kind][:ext] && @ldapData[kind][:int] - - @ldapData[kind][:ext].each{|ydata| yield ydata} if @ldapData[kind][:ext] - end - - def update(kind, data) - map = {} - map.merge!(LDAP_MAP[kind].invert) if LDAP_MAP[kind] - - odata = @ldapData[kind][:ext].find{|edata| edata[:id] == data[:id]} - - data.each do |key,value| - pat_key = map[key] ? map[key] : key - if odata[:id] =~ /(^|, *)#{pat_key.to_s}=([^, ]+)/ && $2 != value - return replace(kind, data) - end - end - - entry = Net::LDAP::Entry.new(data[:id]) - data = data.find_all{|key,value| value != odata[key]} - data.delete(:id) - - replace = Array.new - data.each do |key,value| - key = map[key] if map[key] - replace.push(key.to_s) - entry[key] = value - end - - if replace.empty? - puts 'INFO: no changes' - else - entry[:changetype] = 'modify' - entry[:replace] = replace - LDAP_LAMBDA[kind].call(entry) if LDAP_LAMBDA[kind] - - puts entry.to_ldif - end - end - - def replace(kind, data) - puts 'INFO: do replace' - puts '----------------' - odata = @ldapData[kind][:ext].find{|edata| edata[:id] == data[:id]} - delete(odata) - puts - insert(kind, data) - puts '----------------' - end - - def delete(data) - entry = Net::LDAP::Entry.new(data[:id]) - entry[:changetype] = 'delete' - - puts entry.to_ldif - end - - def insert(kind, data) - map = {} - map.merge!(LDAP_MAP[kind].invert) if LDAP_MAP[kind] - - data.delete(:id) - entry = Net::LDAP::Entry.new(ldapDn(kind, data)) - entry[:changetype] = 'add' - entry[:objectclass] = LDAP_OBJECTCLASS[kind] - - data.each do |key,value| - key = map[key] if map[key] - entry[key] = value - end - LDAP_LAMBDA[kind].call(entry) if LDAP_LAMBDA[kind] - - puts entry.to_ldif - end - - private - - def ldapBase(kind) - case(kind) - when :User, :Group: @systemDn - when :Site, :MailAliasRole, :MailAliasPerson, :MailAccount: @hostingDn - end - end - - def ldapDn(kind, data) - case(kind) - when :User - "uid=#{data[:name]},ou=user,#{ldapBase(kind)}" - when :Group - "cn=#{data[:name]},ou=group,#{ldapBase(kind)}" - when :Site - "o=#{data[:name]},#{ldapBase(kind)}" - when :MailAliasRole - "cn=#{data[:user]},o=#{data[:mail].sub(/.*@/, '')},#{ldapBase(kind)}" - when :MailAliasPerson - "mail=#{data[:mail]},o=#{data[:mail].sub(/.*@/, '')},#{ldapBase(kind)}" - when :MailAccount - "mail=#{data[:mail]},o=#{data[:mail].sub(/.*@/, '')},#{ldapBase(kind)}" - end - end - -end diff --git a/User.rb b/User.rb deleted file mode 100644 index 6f55ccd..0000000 --- a/User.rb +++ /dev/null @@ -1,18 +0,0 @@ -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] - @shadowmax = args[:shadowmax] - @shadowwarning = args[:shadowwarning] - end -end diff --git a/controllers/system_data.rb b/controllers/system_data.rb deleted file mode 100644 index a53089f..0000000 --- a/controllers/system_data.rb +++ /dev/null @@ -1,91 +0,0 @@ -require 'User' -require 'Group' -require 'Site' -require 'MailAliasRole' -require 'MailAliasPerson' -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 mailAliasRoles - load(:MailAliasRole) - end - - def mailAliasPeople - load(:MailAliasPerson) - 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 mailAliasRolesBySite(site) - mailAliasRoles.find_all{|mail| mail.site == site.name} - end - - def mailAliasPeopleBySite(site) - mailAliasPeople.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 - @backend.load(kind) do |data| - data[:backend] = @backend - @data[kind].push( - eval(kind.to_s + '.new(data)') - ) - end - end - -end diff --git a/database.rb b/database.rb deleted file mode 100644 index 1db079c..0000000 --- a/database.rb +++ /dev/null @@ -1,10 +0,0 @@ -module SdAdmin::Database - class Ldap - require 'database/base.rb' - require 'net/ldap' - - include Enumerable - end - - require 'database/ldap' -end diff --git a/database/base.rb b/database/base.rb deleted file mode 100644 index 81cbc04..0000000 --- a/database/base.rb +++ /dev/null @@ -1,13 +0,0 @@ -class SdAdmin::Database::Base - - def initialize - @data = Hash.new - end - - def _create(data) - end - - def _read(id) - end - -end diff --git a/database/factory.rb b/database/factory.rb deleted file mode 100644 index 96ecacb..0000000 --- a/database/factory.rb +++ /dev/null @@ -1,3 +0,0 @@ -class SdAdmin::Database::Factory - -end diff --git a/database/ldap.rb b/database/ldap.rb deleted file mode 100644 index 2bbde01..0000000 --- a/database/ldap.rb +++ /dev/null @@ -1,53 +0,0 @@ -class SdAdmin::Database::Ldap - attr_writer :base_dn, :mapper - - def initialize(args = {}) - @con = {:host => 'host.one.virtual', :port => 389} - - @con[:host] = args[:host] if args[:host] - @con[:port] = args[:port] if args[:port] - - @base_dn = args[:base_dn] if args[:base_dn] - - @ldap = Net::LDAP.new(@con) - filter = args[:filter] if args[:filter] - end - - def filter=(filter) - @filter = Net::LDAP::Filter::construct(filter) - end - - def each - _load.each{|key,entry| puts "DEBUG: #{key}"; yield key,entry} - end - - def [](id) - _load[id] - end - - def []=(id, data) - end - - def insert(data) - end - - def delete(id) - end - - private - - def _load! - @data = Hash.new - @ldap.search(:base => @base_dn, :filter => @filter) do |entry| - attributes = Hash.new - entry.each{|attr,value| attributes.merge!({attr => value})} - @data.merge!({attributes[:dn][0] => attributes}) - end - end - - def _load - _load! if ! @data - @data - end - -end diff --git a/docs/development/mystuff.dia b/docs/development/mystuff.dia new file mode 100644 index 0000000000000000000000000000000000000000..b9cec43a575d6b6a9e280f0b6c001e46502f222b GIT binary patch literal 2802 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 literal 0 HcmV?d00001 diff --git a/docs/development/was.txt b/docs/development/was.txt new file mode 100644 index 0000000..1e3a97e --- /dev/null +++ b/docs/development/was.txt @@ -0,0 +1,66 @@ +was wir haben. + +- verschiedene Model (user, group, mailAccount, mailALias, etc.) +- diese koennen in verschiedenen Datenquellen liegen +- die Datenquellen werden mit verschiedenen Abfragesprachen abgefragt. +- das entsprechende Model bestimmt welche Daten abgefragt werden. +- die Datenquelle bestimmt wie diese Daten abgefragt werden. + + Konflikt: bei ldap laesst sich das wie nur schwer von dem was abgefragt +werden soll trennen. + + Moegliche Loesung: eine Factory, die ueber die Klasse des Models und +die Klasse der Datenbank eine solche konkrete Datenbank initialisiert. + + Variation: anstatt eine factory zu bauen koennte man eine generische + Datenbankklasse bauen die eine Klassenmethode bekommt ueber die mit + dem reingegebenen Model dann eine Instanz erzeugt wird. + + Problem: Die Datenbankklasse muss dann Initialisierungsinformationen +zu den entsprechenden Models kennen. (Implementierungsdetail) +Um die Datenbankklasse generisch zu halten sollte diese Information +woanders her kommen, allerdings nicht aus dem Model, da dann wiederum +die Model Implementierungsdetails der Datenbankklasse kennen muessen. + + Evtl.: laesst sich was ueber Name conventions machen. Sauberer scheint +mir aber zu sein das es zu jeder Datenbankklasse eine Konfigurationsdatei +gibt in der man die Eckdaten fuer die Abfragen der einzelnen Model +konfigurieren kann. + + ein yaml koennte evtl. so aussehen: (ldap.yml) + + ldap: # => wenn es pro Datenbank ne eigenen datei gibt ist das nicht noetig + host: host.one.virtual + port: 389 + queries: + User: + baseDn: ou=user,o=system,dc=weird-web-workers,dc=org + filter: (objectClass=posixAccount) + Group: + baseDn: ou=group,o=system,dc=weird-web-workers,dc=org + filter: (objectClass=posixGroup) + + ... + + alternativ zu einer Datei koennte man eine Mapping Datei zu jeder Kombination +aus Model und Datenbanktyp anlegen...diese waeren schoen klein schnell gelesen +und geschrieben. + + Dateistruktur: + + - model - user.rb + - group.rb + - site.rb + - mailalias_role.rb + - mailalias_person.rb + - mailaccount.rb + - data - ldap.rb + - data - config - ldap.yml + - adapter - ldap.rb + - config - ldap - user.yml + - group.yml + - site.yml + - mailalias_role.yml + - mailalias_person.yml + - mailaccount.yml + diff --git a/ds_admin.rb b/ds_admin.rb new file mode 100644 index 0000000..b6db539 --- /dev/null +++ b/ds_admin.rb @@ -0,0 +1,4 @@ +module DsAdmin + DsAdmin.autoload(:Model, 'model') + DsAdmin.autoload(:Storage, 'storage') +end diff --git a/loader/user.rb b/loader/user.rb deleted file mode 100644 index e69de29..0000000 diff --git a/mappers/ldap.rb b/mappers/ldap.rb deleted file mode 100644 index a660087..0000000 --- a/mappers/ldap.rb +++ /dev/null @@ -1,197 +0,0 @@ - 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_MAILALIASPERSON_MAP = { - :sn => :surname, - :cn => :name - } - - LDAP_MAP = { - :User => LDAP_USER_MAP, - :Group => LDAP_GROUP_MAP, - :Site => { :o => :name }, - :MailAliasRole => { :cn => :user }, - :MailAliasPerson => LDAP_MAILALIASPERSON_MAP, - :mailAccount => { :homedirectory => :home } - } - - LDAP_FILTER = { - :User => '(objectClass=posixAccount)', - :Group => '(objectClass=posixGroup)', - :Site => '(&(objectClass=organization)(!(o=hosting)))', - :MailAliasRole => '(&(objectClass=MailAlias)(objectClass=organizationalrole))', - :MailAliasPerson => '(&(objectClass=MailAlias)(objectClass=person))', - :MailAccount => '(objectClass=mailAccount)' - } - - LDAP_OBJECTCLASS = { - :User => [ 'account', 'posixAccount', 'shadowAccount' ], - :Group => 'posixGroup', - :Site => 'organization', - :MailAliasRole => [ 'organizationalRole', 'MailAlias' ], - :MailAliasPerson => [ 'person', 'MailAlias' ], - :MailAccount => [ 'person', 'MailAccount' ] - } - - LDAP_LAMBDA_USER = lambda do |entry| - entry[:cn] = entry[:uid] - entry[:shadowlastchange] = (Time::now.to_i/60/60/24).to_s - entry[:replace] += ['shadowreplace'] if entry[:replace] - end - - LDAP_LAMBDA = { - :User => LDAP_LAMBDA_USER - } - - 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] = Hash.new if ! @ldapData[kind] - - @ldapData[kind][:int] = @ldap.search( - :base => ldapBase(kind), - :filter => Net::LDAP::Filter::construct(LDAP_FILTER[kind]) - ) - end - - def load(kind) - load!(kind) if ! @ldapData[kind] - - @ldapData[kind][:ext] = @ldapData[kind][:int].map do |data| - map = { :dn => :id } - map.merge!(LDAP_MAP[kind]) if LDAP_MAP[kind] - - ydata = {} - data.each do |key,value| - ydata.merge!({ map[key] || key => value.size==1?value[0]:value.to_a }) - end - ydata - end if ! @ldapData[kind][:ext] && @ldapData[kind][:int] - - @ldapData[kind][:ext].each{|ydata| yield ydata} if @ldapData[kind][:ext] - end - - def update(kind, data) - map = {} - map.merge!(LDAP_MAP[kind].invert) if LDAP_MAP[kind] - - odata = @ldapData[kind][:ext].find{|edata| edata[:id] == data[:id]} - - data.each do |key,value| - pat_key = map[key] ? map[key] : key - if odata[:id] =~ /(^|, *)#{pat_key.to_s}=([^, ]+)/ && $2 != value - return replace(kind, data) - end - end - - entry = Net::LDAP::Entry.new(data[:id]) - data = data.find_all{|key,value| value != odata[key]} - data.delete(:id) - - replace = Array.new - data.each do |key,value| - key = map[key] if map[key] - replace.push(key.to_s) - entry[key] = value - end - - if replace.empty? - puts 'INFO: no changes' - else - entry[:changetype] = 'modify' - entry[:replace] = replace - LDAP_LAMBDA[kind].call(entry) if LDAP_LAMBDA[kind] - - puts entry.to_ldif - end - end - - def replace(kind, data) - puts 'INFO: do replace' - puts '----------------' - odata = @ldapData[kind][:ext].find{|edata| edata[:id] == data[:id]} - delete(odata) - puts - insert(kind, data) - puts '----------------' - end - - def delete(data) - entry = Net::LDAP::Entry.new(data[:id]) - entry[:changetype] = 'delete' - - puts entry.to_ldif - end - - def insert(kind, data) - map = {} - map.merge!(LDAP_MAP[kind].invert) if LDAP_MAP[kind] - - data.delete(:id) - entry = Net::LDAP::Entry.new(ldapDn(kind, data)) - entry[:changetype] = 'add' - entry[:objectclass] = LDAP_OBJECTCLASS[kind] - - data.each do |key,value| - key = map[key] if map[key] - entry[key] = value - end - LDAP_LAMBDA[kind].call(entry) if LDAP_LAMBDA[kind] - - puts entry.to_ldif - end - - private - - def ldapBase(kind) - case(kind) - when :User, :Group: @systemDn - when :Site, :MailAliasRole, :MailAliasPerson, :MailAccount: @hostingDn - end - end - - def ldapDn(kind, data) - case(kind) - when :User - "uid=#{data[:name]},ou=user,#{ldapBase(kind)}" - when :Group - "cn=#{data[:name]},ou=group,#{ldapBase(kind)}" - when :Site - "o=#{data[:name]},#{ldapBase(kind)}" - when :MailAliasRole - "cn=#{data[:user]},o=#{data[:mail].sub(/.*@/, '')},#{ldapBase(kind)}" - when :MailAliasPerson - "mail=#{data[:mail]},o=#{data[:mail].sub(/.*@/, '')},#{ldapBase(kind)}" - when :MailAccount - "mail=#{data[:mail]},o=#{data[:mail].sub(/.*@/, '')},#{ldapBase(kind)}" - end - end - -end diff --git a/model.rb b/model.rb index 37a1e26..607b03e 100644 --- a/model.rb +++ b/model.rb @@ -1,16 +1,64 @@ -module SdAdmin::Model - module Interface - end +module DsAdmin::Model + include Enumerable - class Base - require 'model/interface' - require 'database' - include SdAdmin::Model::Interface - end + DsAdmin::Model.autoload(:User, 'model/user') + DsAdmin::Model.autoload(:Group, 'model/group') + DsAdmin::Model.autoload(:Site, 'model/site') + DsAdmin::Model.autoload(:MailAliasRole, 'model/mail_alias_role') + DsAdmin::Model.autoload(:MailAliasPerson, 'model/mail_alias_person') + DsAdmin::Model.autoload(:MailAccount, 'model/mail_account') - class User < Base - end + def (DsAdmin::Model).storage=(storage) + @@storage = storage + end - require 'model/base' - require 'model/user' + def (DsAdmin::Model).storage + @@storage + end + + attr_accessor :id + + def initialize(args = {}) + @id = args[:id] if args[:id] + end + + def all + @@storage.config.model = self + + @@storage.map do |data| + self.class.new(data) + end + end + + def each(&block) + all.each(&block) + end + + def load(id) + self.class.new(_load(id)) + end + + def load!(id) + initialize(_load(id)) + end + + def save + @id = @storage.create_id(self) unless @id + @storage.write(self) + end + + def update + @storage.write(self) + end + + def to_sym + self.class.to_s.to_sym + end + + protected + def _load(id) + data = @@storage.find {|data| data[:id] == id} + throw "unknown id (#{id})" unless data + data + end end diff --git a/model/base.rb b/model/base.rb deleted file mode 100644 index 2569a41..0000000 --- a/model/base.rb +++ /dev/null @@ -1,9 +0,0 @@ -class SdAdmin::Model::Base - attr_reader :backend - - def initialize(backend) - @backend = SdAdmin::Database::Ldap.new - @backend = backend if backend - end - -end diff --git a/model/group.rb b/model/group.rb index e607420..b5fa3ed 100644 --- a/model/group.rb +++ b/model/group.rb @@ -1,14 +1,14 @@ -require 'SystemData' +class DsAdmin::Model::Group + include DsAdmin::Model -class Group < SystemData attr_accessor :name, :gid, :members - + def initialize(args = {}) - super(args) + return if args.empty? + super(args) @name = args[:name] @gid = args[:gid] - @members = args[:members] - @members = Array.new if @members.nil? + @members = args[:members] ? args[:members] : Array.new end end diff --git a/model/interface.rb b/model/interface.rb deleted file mode 100644 index 25de225..0000000 --- a/model/interface.rb +++ /dev/null @@ -1,7 +0,0 @@ -module SdAdmin::Model::Interface - - def all - Hash[self.backend.map{|key,entry| [key, entry]}] - end - -end diff --git a/model/mail_account.rb b/model/mail_account.rb index a6ec9fd..6f2113a 100644 --- a/model/mail_account.rb +++ b/model/mail_account.rb @@ -1,9 +1,10 @@ -require 'SystemData' +class DsAdmin::Model::MailAccount + include DsAdmin::Model -class MailAccount < SystemData attr_accessor :mail, :mailbox def initialize(args = {}) + return if args.empty? super(args) @mail = args[:mail] diff --git a/model/mail_alias_person.rb b/model/mail_alias_person.rb index e4308ce..d71b1f5 100644 --- a/model/mail_alias_person.rb +++ b/model/mail_alias_person.rb @@ -1,9 +1,10 @@ -require 'SystemData' +class DsAdmin::Model::MailAliasPerson + include DsAdmin::Model -class MailAliasPerson < SystemData attr_accessor :mail, :maildrop, :surname, :name def initialize(args = {}) + return if args.empty? super(args) @mail = args[:mail] diff --git a/model/mail_alias_role.rb b/model/mail_alias_role.rb index c16b474..b2e21d3 100644 --- a/model/mail_alias_role.rb +++ b/model/mail_alias_role.rb @@ -1,9 +1,10 @@ -require 'SystemData' +class DsAdmin::Model::MailAliasRole + include DsAdmin::Model -class MailAliasRole < SystemData attr_accessor :mail, :maildrop, :user def initialize(args = {}) + return if args.empty? super(args) @mail = args[:mail] diff --git a/model/site.rb b/model/site.rb index 133ccbe..bea8624 100644 --- a/model/site.rb +++ b/model/site.rb @@ -1,9 +1,10 @@ -require 'SystemData' +class DsAdmin::Model::Site + include DsAdmin::Model -class Site < SystemData attr_accessor :name def initialize(args = {}) + return if args.empty? super(args) @name = args[:name] diff --git a/model/system_data.rb b/model/system_data.rb deleted file mode 100644 index ec1652b..0000000 --- a/model/system_data.rb +++ /dev/null @@ -1,24 +0,0 @@ -class SystemData - attr_reader :id - - def initialize(args = {}) - @backend = args[:backend] - @id = args[:id] - end - - def save - kind = self.class.to_s.to_sym - - if @id - @backend.update(kind, to_h) - else - @backend.insert(kind, to_h) - end - end - - def to_h - Hash[instance_variables.map do |var| - [var[1...var.size].to_sym, eval(var)] if var != '@backend' - end] - end -end diff --git a/model/user.rb b/model/user.rb index 6b9f126..0fbb787 100644 --- a/model/user.rb +++ b/model/user.rb @@ -1,19 +1,19 @@ -class SdAdmin::Model::User - attr_accessor :name, :pass, :uid, :gid, :shell, :home +class DsAdmin::Model::User + include DsAdmin::Model - def initialize(args={}, backend=nil) - super(backend) + attr_accessor :name, :pass, :uid, :gid, :shell, :home - @backend.base_dn = 'ou=user,o=system,dc=weird-web-workers,dc=org' - @backend.filter = '(objectClass=posixAccount)' + def initialize(args = {}) + return if args.empty? + super(args) - @name = args[:name] - @pass = args[:pass] - @uid = args[:uid] - @gid = args[:gid] - @shell = args[:shell] - @home = args[:home] - @shadowmax = args[:shadowmax] - @shadowwarning = args[:shadowwarning] - end + @name = args[:name] + @pass = args[:pass] + @uid = args[:uid] + @gid = args[:gid] + @shell = args[:shell] + @home = args[:home] + @shadowmax = args[:shadowmax] + @shadowwarning = args[:shadowwarning] + end end diff --git a/sd_admin.rb b/sd_admin.rb deleted file mode 100644 index 30de395..0000000 --- a/sd_admin.rb +++ /dev/null @@ -1,10 +0,0 @@ -module SdAdmin - module Model - end - - module Database - end - - require 'model' - require 'database' -end diff --git a/storage.rb b/storage.rb new file mode 100644 index 0000000..dd36bb0 --- /dev/null +++ b/storage.rb @@ -0,0 +1,37 @@ +module DsAdmin::Storage + include Enumerable + + DsAdmin::Storage.autoload(:Ldap, 'storage/ldap') + DsAdmin::Storage.autoload(:Mysql, 'storage/mysql') + DsAdmin::Storage.autoload(:Config, 'storage/config') + + attr_accessor :config + + def initialize(config) + @config = config + end + + def each(&block) + read.each(&block) + end + + ## + # We don't need this....the 'id' is a storage id and as + # thus returned after successfully writing a new entry. + # + def create_id(model) + return "dummy id for #{model.inspect}" + end + + def read + throw "#{self.class}: read not implemented" + end + + def write(model) + throw "#{self.class}: write not implemented" + end + + def to_sym + self.class.to_s.to_sym + end +end diff --git a/storage/config.rb b/storage/config.rb new file mode 100644 index 0000000..dde315f --- /dev/null +++ b/storage/config.rb @@ -0,0 +1,21 @@ +require 'yaml' + +class Test::Storage::Config + attr_accessor :model + + def initialize(yml_file) + @config = YAML.load_file(yml_file) + end + + def con(storage) + @config[storage.to_sym][:con] + end + + def query(storage) + @config[storage.to_sym][@model.to_sym][:query] + end + + def map(storage) + @config[storage.to_sym][@model.to_sym][:map] + end +end diff --git a/storage/ldap.rb b/storage/ldap.rb new file mode 100644 index 0000000..fbbc661 --- /dev/null +++ b/storage/ldap.rb @@ -0,0 +1,34 @@ +require 'net/ldap' + +class DsAdmin::Storage::Ldap + include DsAdmin::Storage + + def initialize(config) + super(config) + @ldap = Net::LDAP.new(@config.con(self)) + end + + def read + query = @config.query(self) + + ## + # two things. + # - create a hash from the ldap search result + # - map the id's from the ldap search resulte into id's used in + # the models. The mapping is read from the config. + # + foo = @ldap.search(query).map do |data| + map = { :dn => :id } + map.merge!(@config.map(self)) + + remapped = Hash.new + data.each do |key,value| + key = map[key] || key + value = value.size==1 ? value[0] : value.to_a + + remapped.merge!({ key => value }) + end + remapped + end + end +end diff --git a/storage/mysql.rb b/storage/mysql.rb new file mode 100644 index 0000000..77220a5 --- /dev/null +++ b/storage/mysql.rb @@ -0,0 +1,3 @@ +class DsAdmin::Storage::Mysql + include DsAdmin::Storage +end diff --git a/test_dummy.rb b/test_dummy.rb deleted file mode 100644 index d098635..0000000 --- a/test_dummy.rb +++ /dev/null @@ -1,123 +0,0 @@ -require 'SystemDataBackend' -require 'SystemDataBackendLdap' - -ldap = SystemDataBackendLdap.new( - 'host.one.virtual', - 389, - 'dc=weird-web-workers,dc=org' -) -backend = SystemDataBackend.new(ldap) - -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 ' MailAliasRoles:' - backend.mailAliasRolesBySite(site).each{|account| puts ' ' + account.mail} - puts - puts ' MailAliasPeople:' - backend.mailAliasPeopleBySite(site).each{|account| puts ' ' + account.mail} - puts - puts ' MailAccounts:' - backend.mailAccountsBySite(site).each{|account| puts ' ' + account.mail} - puts -end - -backend.mailAliasRoles.each do |mailAlias| - puts 'mailAliasRole: '+mailAlias.mail.inspect+','+mailAlias.maildrop.inspect -end - -puts - -backend.mailAliasPeople.each do |mailAlias| - puts 'mailAliasPerson: '+mailAlias.mail.inspect+','+mailAlias.maildrop.inspect -end - -puts - -backend.mailAccounts.each do |mailAccount| - puts 'mailAccount: '+mailAccount.mail.inspect+','+mailAccount.mailbox.inspect -end - -puts - -georg = backend.userByName('georg') -georg.save - -puts - -georg.uid = 1001 -georg.save - -puts - -wheel = backend.groupByName('wheel') -wheel.save - -puts - -wheel.gid = 100 -wheel.save - -puts - -site = backend.siteByName('kommandozeilenchef.de') -site.save - -puts - -site.name = 'wumbaba.de' -site.save - -puts - -mail = MailAliasRole.new({ - :backend => ldap, - :mail => 'newrole@kommandozeilenchef.de', - :maildrop => 'newrole', - :user => 'newrole' -}) -mail.save - -puts - -mail = MailAliasPerson.new({ - :backend => ldap, - :mail => 'ohotte@kommandozeilenchef.de', - :maildrop => 'ohotte', - :name => 'Onkel Hotte', - :surname => 'Hotte' -}) -mail.save - -puts - -mail = MailAccount.new({ - :backend => ldap, - :mail => 'foobar@kommandozeilenchef.de', - :mailbox => 'kommandozeilenchef.de/foobar', - :home => '/var/spool/vmail/domains' -}) -mail.save - -puts -puts '=====================================' -# -o vsz/vsize -puts 'Memory useage: ' + `ps -o rss= -p #{Process.pid}` diff --git a/test_dummy2.rb b/test_dummy2.rb deleted file mode 100644 index 6fa5b7a..0000000 --- a/test_dummy2.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'sd_admin' - -user = SdAdmin::Model::User.new - -puts user.all.inspect diff --git a/tester.rb b/tester.rb new file mode 100644 index 0000000..9195f0a --- /dev/null +++ b/tester.rb @@ -0,0 +1,38 @@ +require 'ds_admin' + +config = DsAdmin::Storage::Config.new(File.dirname(__FILE__) + '/config/storage.yml') +DsAdmin::Model.storage = DsAdmin::Storage::Ldap.new(config) + +user = DsAdmin::Model::User.new +group = DsAdmin::Model::Group.new +site = DsAdmin::Model::Site.new +alias_role = DsAdmin::Model::MailAliasRole.new +alias_person = DsAdmin::Model::MailAliasPerson.new +account = DsAdmin::Model::MailAccount.new + +puts '=== DsAdmin each ===' +user.each {|user| puts user.inspect} +puts '---' +group.each {|group| puts group.inspect} +puts '---' +site.each {|site| puts site.inspect} +puts '---' +alias_role.each {|ma_role| puts ma_role.inspect} +puts '---' +alias_person.each {|ma_person| puts ma_person.inspect} +puts '---' +account.each {|macc| puts macc.inspect} + +puts +puts '=== DsAdmin Enumerable ===' +puts user.find {|user| user.uid == '1000'}.inspect +puts '---' +puts group.find {|group| group.gid == '10'}.inspect +puts '---' +puts site.find {|site| site.name == 'steffers.org'}.inspect +puts '---' +puts alias_role.find_all {|mar| mar.maildrop == 'abuse'}.inspect +puts '---' +puts alias_person.find {|map| map.mail == 'georg@steffers.org'}.inspect +puts '---' +puts account.find {|acc| acc.mail == 'drachenfrau@steffers.org'}.inspect