Commit 4790392a5fc1ade75630ba6d34ede6f77ec97e75

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

start fiddling around for a good structure

... ... @@ -75,7 +75,7 @@
75 75 def load!(kind)
76 76 @ldapData[kind] = Hash.new if ! @ldapData[kind]
77 77
78   - @ldapData[kind][:internal] = @ldap.search(
  78 + @ldapData[kind][:int] = @ldap.search(
79 79 :base => ldapBase(kind),
80 80 :filter => Net::LDAP::Filter::construct(LDAP_FILTER[kind])
81 81 )
... ... @@ -84,7 +84,7 @@
84 84 def load(kind)
85 85 load!(kind) if ! @ldapData[kind]
86 86
87   - @ldapData[kind][:external] = @ldapData[kind][:internal].map do |data|
  87 + @ldapData[kind][:ext] = @ldapData[kind][:int].map do |data|
88 88 map = { :dn => :id }
89 89 map.merge!(LDAP_MAP[kind]) if LDAP_MAP[kind]
90 90
... ... @@ -93,16 +93,16 @@
93 93 ydata.merge!({ map[key] || key => value.size==1?value[0]:value.to_a })
94 94 end
95 95 ydata
96   - end if ! @ldapData[kind][:external] && @ldapData[kind][:internal]
  96 + end if ! @ldapData[kind][:ext] && @ldapData[kind][:int]
97 97
98   - @ldapData[kind][:external].each{|ydata| yield ydata} if @ldapData[kind][:external]
  98 + @ldapData[kind][:ext].each{|ydata| yield ydata} if @ldapData[kind][:ext]
99 99 end
100 100
101 101 def update(kind, data)
102 102 map = {}
103 103 map.merge!(LDAP_MAP[kind].invert) if LDAP_MAP[kind]
104 104
105   - odata = @ldapData[kind][:external].find{|edata| edata[:id] == data[:id]}
  105 + odata = @ldapData[kind][:ext].find{|edata| edata[:id] == data[:id]}
106 106
107 107 data.each do |key,value|
108 108 pat_key = map[key] ? map[key] : key
... ... @@ -136,7 +136,7 @@
136 136 def replace(kind, data)
137 137 puts 'INFO: do replace'
138 138 puts '----------------'
139   - odata = @ldapData[kind][:external].find{|edata| edata[:id] == data[:id]}
  139 + odata = @ldapData[kind][:ext].find{|edata| edata[:id] == data[:id]}
140 140 delete(odata)
141 141 puts
142 142 insert(kind, data)
... ...
  1 +require 'User'
  2 +require 'Group'
  3 +require 'Site'
  4 +require 'MailAliasRole'
  5 +require 'MailAliasPerson'
  6 +require 'MailAccount'
  7 +
  8 +class SystemDataBackend
  9 +
  10 + def initialize(backend)
  11 + @backend = backend
  12 + @data = Hash.new
  13 + end
  14 +
  15 + def users
  16 + load(:User)
  17 + end
  18 +
  19 + def groups
  20 + load(:Group)
  21 + end
  22 +
  23 + def sites
  24 + load(:Site)
  25 + end
  26 +
  27 + def mailAliasRoles
  28 + load(:MailAliasRole)
  29 + end
  30 +
  31 + def mailAliasPeople
  32 + load(:MailAliasPerson)
  33 + end
  34 +
  35 + def mailAccounts
  36 + load(:MailAccount)
  37 + end
  38 +
  39 + def userByName(name)
  40 + users.find{|user| user.name == name}
  41 + end
  42 +
  43 + def groupByName(name)
  44 + groups.find{|group| group.name == name}
  45 + end
  46 +
  47 + def siteByName(name)
  48 + sites.find{|site| site.name == name}
  49 + end
  50 +
  51 + def usersInGroup(group)
  52 + case
  53 + when group.members.instance_of?(Array):
  54 + Hash[group.members.map{|uid| [uid, userByName(uid)] if userByName(uid)}]
  55 + when goup.members.nil?:
  56 + {}
  57 + else
  58 + {group.members => userByName(group.members)} if userByName(group.members)
  59 + end
  60 + end
  61 +
  62 + def mailAliasRolesBySite(site)
  63 + mailAliasRoles.find_all{|mail| mail.site == site.name}
  64 + end
  65 +
  66 + def mailAliasPeopleBySite(site)
  67 + mailAliasPeople.find_all{|mail| mail.site == site.name}
  68 + end
  69 +
  70 + def mailAccountsBySite(site)
  71 + mailAccounts.find_all{|mail| mail.site == site.name}
  72 + end
  73 +
  74 + private
  75 +
  76 + def load(kind)
  77 + load!(kind) if ! @data[kind]
  78 + @data[kind]
  79 + end
  80 +
  81 + def load!(kind)
  82 + @data[kind] = Array.new
  83 + @backend.load(kind) do |data|
  84 + data[:backend] = @backend
  85 + @data[kind].push(
  86 + eval(kind.to_s + '.new(data)')
  87 + )
  88 + end
  89 + end
  90 +
  91 +end
... ...
  1 +module SdAdmin::Database
  2 + class Ldap
  3 + require 'database/base.rb'
  4 + require 'net/ldap'
  5 +
  6 + include Enumerable
  7 + end
  8 +
  9 + require 'database/ldap'
  10 +end
... ...
  1 +class SdAdmin::Database::Base
  2 +
  3 + def initialize
  4 + @data = Hash.new
  5 + end
  6 +
  7 + def _create(data)
  8 + end
  9 +
  10 + def _read(id)
  11 + end
  12 +
  13 +end
... ...
  1 +class SdAdmin::Database::Factory
  2 +
  3 +end
... ...
  1 +class SdAdmin::Database::Ldap
  2 + attr_writer :base_dn, :mapper
  3 +
  4 + def initialize(args = {})
  5 + @con = {:host => 'host.one.virtual', :port => 389}
  6 +
  7 + @con[:host] = args[:host] if args[:host]
  8 + @con[:port] = args[:port] if args[:port]
  9 +
  10 + @base_dn = args[:base_dn] if args[:base_dn]
  11 +
  12 + @ldap = Net::LDAP.new(@con)
  13 + filter = args[:filter] if args[:filter]
  14 + end
  15 +
  16 + def filter=(filter)
  17 + @filter = Net::LDAP::Filter::construct(filter)
  18 + end
  19 +
  20 + def each
  21 + _load.each{|key,entry| puts "DEBUG: #{key}"; yield key,entry}
  22 + end
  23 +
  24 + def [](id)
  25 + _load[id]
  26 + end
  27 +
  28 + def []=(id, data)
  29 + end
  30 +
  31 + def insert(data)
  32 + end
  33 +
  34 + def delete(id)
  35 + end
  36 +
  37 + private
  38 +
  39 + def _load!
  40 + @data = Hash.new
  41 + @ldap.search(:base => @base_dn, :filter => @filter) do |entry|
  42 + attributes = Hash.new
  43 + entry.each{|attr,value| attributes.merge!({attr => value})}
  44 + @data.merge!({attributes[:dn][0] => attributes})
  45 + end
  46 + end
  47 +
  48 + def _load
  49 + _load! if ! @data
  50 + @data
  51 + end
  52 +
  53 +end
... ...
  1 + require 'active_support/secure_random'
  2 + require 'net/ldap'
  3 +
  4 + class SystemDataBackendLdap
  5 +
  6 + LDAP_USER_MAP = {
  7 + :uid => :name,
  8 + :userpassword => :pass,
  9 + :uidnumber => :uid,
  10 + :gidnumber => :gid,
  11 + :loginshell => :shell,
  12 + :homedirectory => :home
  13 + }
  14 +
  15 + LDAP_GROUP_MAP = {
  16 + :cn => :name,
  17 + :gidnumber => :gid,
  18 + :memberuid => :members
  19 + }
  20 +
  21 + LDAP_MAILALIASPERSON_MAP = {
  22 + :sn => :surname,
  23 + :cn => :name
  24 + }
  25 +
  26 + LDAP_MAP = {
  27 + :User => LDAP_USER_MAP,
  28 + :Group => LDAP_GROUP_MAP,
  29 + :Site => { :o => :name },
  30 + :MailAliasRole => { :cn => :user },
  31 + :MailAliasPerson => LDAP_MAILALIASPERSON_MAP,
  32 + :mailAccount => { :homedirectory => :home }
  33 + }
  34 +
  35 + LDAP_FILTER = {
  36 + :User => '(objectClass=posixAccount)',
  37 + :Group => '(objectClass=posixGroup)',
  38 + :Site => '(&(objectClass=organization)(!(o=hosting)))',
  39 + :MailAliasRole => '(&(objectClass=MailAlias)(objectClass=organizationalrole))',
  40 + :MailAliasPerson => '(&(objectClass=MailAlias)(objectClass=person))',
  41 + :MailAccount => '(objectClass=mailAccount)'
  42 + }
  43 +
  44 + LDAP_OBJECTCLASS = {
  45 + :User => [ 'account', 'posixAccount', 'shadowAccount' ],
  46 + :Group => 'posixGroup',
  47 + :Site => 'organization',
  48 + :MailAliasRole => [ 'organizationalRole', 'MailAlias' ],
  49 + :MailAliasPerson => [ 'person', 'MailAlias' ],
  50 + :MailAccount => [ 'person', 'MailAccount' ]
  51 + }
  52 +
  53 + LDAP_LAMBDA_USER = lambda do |entry|
  54 + entry[:cn] = entry[:uid]
  55 + entry[:shadowlastchange] = (Time::now.to_i/60/60/24).to_s
  56 + entry[:replace] += ['shadowreplace'] if entry[:replace]
  57 + end
  58 +
  59 + LDAP_LAMBDA = {
  60 + :User => LDAP_LAMBDA_USER
  61 + }
  62 +
  63 + def initialize(host, port, baseDn, args={})
  64 + @baseDn = baseDn
  65 + @systemDn = 'o=system,' + @baseDn
  66 + @hostingDn = 'o=hosting,' + @baseDn
  67 +
  68 + @systemDn = args[:systemDn] if args[:systemDn]
  69 + @hostingDn = args[:hostingDn] if args[:hostingDn]
  70 +
  71 + @ldap = Net::LDAP.new(:host => host, :port => port)
  72 + @ldapData = Hash.new
  73 + end
  74 +
  75 + def load!(kind)
  76 + @ldapData[kind] = Hash.new if ! @ldapData[kind]
  77 +
  78 + @ldapData[kind][:int] = @ldap.search(
  79 + :base => ldapBase(kind),
  80 + :filter => Net::LDAP::Filter::construct(LDAP_FILTER[kind])
  81 + )
  82 + end
  83 +
  84 + def load(kind)
  85 + load!(kind) if ! @ldapData[kind]
  86 +
  87 + @ldapData[kind][:ext] = @ldapData[kind][:int].map do |data|
  88 + map = { :dn => :id }
  89 + map.merge!(LDAP_MAP[kind]) if LDAP_MAP[kind]
  90 +
  91 + ydata = {}
  92 + data.each do |key,value|
  93 + ydata.merge!({ map[key] || key => value.size==1?value[0]:value.to_a })
  94 + end
  95 + ydata
  96 + end if ! @ldapData[kind][:ext] && @ldapData[kind][:int]
  97 +
  98 + @ldapData[kind][:ext].each{|ydata| yield ydata} if @ldapData[kind][:ext]
  99 + end
  100 +
  101 + def update(kind, data)
  102 + map = {}
  103 + map.merge!(LDAP_MAP[kind].invert) if LDAP_MAP[kind]
  104 +
  105 + odata = @ldapData[kind][:ext].find{|edata| edata[:id] == data[:id]}
  106 +
  107 + data.each do |key,value|
  108 + pat_key = map[key] ? map[key] : key
  109 + if odata[:id] =~ /(^|, *)#{pat_key.to_s}=([^, ]+)/ && $2 != value
  110 + return replace(kind, data)
  111 + end
  112 + end
  113 +
  114 + entry = Net::LDAP::Entry.new(data[:id])
  115 + data = data.find_all{|key,value| value != odata[key]}
  116 + data.delete(:id)
  117 +
  118 + replace = Array.new
  119 + data.each do |key,value|
  120 + key = map[key] if map[key]
  121 + replace.push(key.to_s)
  122 + entry[key] = value
  123 + end
  124 +
  125 + if replace.empty?
  126 + puts 'INFO: no changes'
  127 + else
  128 + entry[:changetype] = 'modify'
  129 + entry[:replace] = replace
  130 + LDAP_LAMBDA[kind].call(entry) if LDAP_LAMBDA[kind]
  131 +
  132 + puts entry.to_ldif
  133 + end
  134 + end
  135 +
  136 + def replace(kind, data)
  137 + puts 'INFO: do replace'
  138 + puts '----------------'
  139 + odata = @ldapData[kind][:ext].find{|edata| edata[:id] == data[:id]}
  140 + delete(odata)
  141 + puts
  142 + insert(kind, data)
  143 + puts '----------------'
  144 + end
  145 +
  146 + def delete(data)
  147 + entry = Net::LDAP::Entry.new(data[:id])
  148 + entry[:changetype] = 'delete'
  149 +
  150 + puts entry.to_ldif
  151 + end
  152 +
  153 + def insert(kind, data)
  154 + map = {}
  155 + map.merge!(LDAP_MAP[kind].invert) if LDAP_MAP[kind]
  156 +
  157 + data.delete(:id)
  158 + entry = Net::LDAP::Entry.new(ldapDn(kind, data))
  159 + entry[:changetype] = 'add'
  160 + entry[:objectclass] = LDAP_OBJECTCLASS[kind]
  161 +
  162 + data.each do |key,value|
  163 + key = map[key] if map[key]
  164 + entry[key] = value
  165 + end
  166 + LDAP_LAMBDA[kind].call(entry) if LDAP_LAMBDA[kind]
  167 +
  168 + puts entry.to_ldif
  169 + end
  170 +
  171 + private
  172 +
  173 + def ldapBase(kind)
  174 + case(kind)
  175 + when :User, :Group: @systemDn
  176 + when :Site, :MailAliasRole, :MailAliasPerson, :MailAccount: @hostingDn
  177 + end
  178 + end
  179 +
  180 + def ldapDn(kind, data)
  181 + case(kind)
  182 + when :User
  183 + "uid=#{data[:name]},ou=user,#{ldapBase(kind)}"
  184 + when :Group
  185 + "cn=#{data[:name]},ou=group,#{ldapBase(kind)}"
  186 + when :Site
  187 + "o=#{data[:name]},#{ldapBase(kind)}"
  188 + when :MailAliasRole
  189 + "cn=#{data[:user]},o=#{data[:mail].sub(/.*@/, '')},#{ldapBase(kind)}"
  190 + when :MailAliasPerson
  191 + "mail=#{data[:mail]},o=#{data[:mail].sub(/.*@/, '')},#{ldapBase(kind)}"
  192 + when :MailAccount
  193 + "mail=#{data[:mail]},o=#{data[:mail].sub(/.*@/, '')},#{ldapBase(kind)}"
  194 + end
  195 + end
  196 +
  197 +end
... ...
  1 +module SdAdmin::Model
  2 + module Interface
  3 + end
  4 +
  5 + class Base
  6 + require 'model/interface'
  7 + require 'database'
  8 + include SdAdmin::Model::Interface
  9 + end
  10 +
  11 + class User < Base
  12 + end
  13 +
  14 + require 'model/base'
  15 + require 'model/user'
  16 +end
... ...
  1 +class SdAdmin::Model::Base
  2 + attr_reader :backend
  3 +
  4 + def initialize(backend)
  5 + @backend = SdAdmin::Database::Ldap.new
  6 + @backend = backend if backend
  7 + end
  8 +
  9 +end
... ...
  1 +require 'SystemData'
  2 +
  3 +class Group < SystemData
  4 + attr_accessor :name, :gid, :members
  5 +
  6 + def initialize(args = {})
  7 + super(args)
  8 +
  9 + @name = args[:name]
  10 + @gid = args[:gid]
  11 + @members = args[:members]
  12 + @members = Array.new if @members.nil?
  13 + end
  14 +end
... ...
  1 +module SdAdmin::Model::Interface
  2 +
  3 + def all
  4 + Hash[self.backend.map{|key,entry| [key, entry]}]
  5 + end
  6 +
  7 +end
... ...
  1 +require 'SystemData'
  2 +
  3 +class MailAccount < SystemData
  4 + attr_accessor :mail, :mailbox
  5 +
  6 + def initialize(args = {})
  7 + super(args)
  8 +
  9 + @mail = args[:mail]
  10 + @home = args[:home]
  11 + @mailbox = args[:mailbox]
  12 + end
  13 +
  14 + def site
  15 + @mail.sub(/.*@/, '')
  16 + end
  17 +end
... ...
  1 +require 'SystemData'
  2 +
  3 +class MailAliasPerson < SystemData
  4 + attr_accessor :mail, :maildrop, :surname, :name
  5 +
  6 + def initialize(args = {})
  7 + super(args)
  8 +
  9 + @mail = args[:mail]
  10 + @maildrop = args[:maildrop]
  11 + @surname = args[:surname]
  12 + @name = args[:name]
  13 + end
  14 +
  15 + def site
  16 + @mail.sub(/.*@/, '')
  17 + end
  18 +end
... ...
  1 +require 'SystemData'
  2 +
  3 +class MailAliasRole < SystemData
  4 + attr_accessor :mail, :maildrop, :user
  5 +
  6 + def initialize(args = {})
  7 + super(args)
  8 +
  9 + @mail = args[:mail]
  10 + @maildrop = args[:maildrop]
  11 + @user = args[:user]
  12 + end
  13 +
  14 + def site
  15 + @mail.sub(/.*@/, '')
  16 + end
  17 +end
... ...
  1 +require 'SystemData'
  2 +
  3 +class Site < SystemData
  4 + attr_accessor :name
  5 +
  6 + def initialize(args = {})
  7 + super(args)
  8 +
  9 + @name = args[:name]
  10 + end
  11 +end
... ...
  1 +class SystemData
  2 + attr_reader :id
  3 +
  4 + def initialize(args = {})
  5 + @backend = args[:backend]
  6 + @id = args[:id]
  7 + end
  8 +
  9 + def save
  10 + kind = self.class.to_s.to_sym
  11 +
  12 + if @id
  13 + @backend.update(kind, to_h)
  14 + else
  15 + @backend.insert(kind, to_h)
  16 + end
  17 + end
  18 +
  19 + def to_h
  20 + Hash[instance_variables.map do |var|
  21 + [var[1...var.size].to_sym, eval(var)] if var != '@backend'
  22 + end]
  23 + end
  24 +end
... ...
  1 +class SdAdmin::Model::User
  2 + attr_accessor :name, :pass, :uid, :gid, :shell, :home
  3 +
  4 + def initialize(args={}, backend=nil)
  5 + super(backend)
  6 +
  7 + @backend.base_dn = 'ou=user,o=system,dc=weird-web-workers,dc=org'
  8 + @backend.filter = '(objectClass=posixAccount)'
  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]
  18 + end
  19 +end
... ...
  1 +module SdAdmin
  2 + module Model
  3 + end
  4 +
  5 + module Database
  6 + end
  7 +
  8 + require 'model'
  9 + require 'database'
  10 +end
... ...
  1 +require 'sd_admin'
  2 +
  3 +user = SdAdmin::Model::User.new
  4 +
  5 +puts user.all.inspect
... ...
Please register or login to post a comment