37 changed files with 296 additions and 993 deletions
-
14Group.rb
-
17MailAccount.rb
-
18MailAliasPerson.rb
-
17MailAliasRole.rb
-
11Site.rb
-
24SystemData.rb
-
91SystemDataBackend.rb
-
197SystemDataBackendLdap.rb
-
18User.rb
-
91controllers/system_data.rb
-
10database.rb
-
13database/base.rb
-
3database/factory.rb
-
53database/ldap.rb
-
BINdocs/development/mystuff.dia
-
66docs/development/was.txt
-
4ds_admin.rb
-
0loader/user.rb
-
197mappers/ldap.rb
-
66model.rb
-
9model/base.rb
-
8model/group.rb
-
7model/interface.rb
-
5model/mail_account.rb
-
5model/mail_alias_person.rb
-
5model/mail_alias_role.rb
-
5model/site.rb
-
24model/system_data.rb
-
12model/user.rb
-
10sd_admin.rb
-
37storage.rb
-
21storage/config.rb
-
34storage/ldap.rb
-
3storage/mysql.rb
-
123test_dummy.rb
-
5test_dummy2.rb
-
38tester.rb
@ -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 |
|
||||
@ -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 |
|
||||
@ -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 |
|
||||
@ -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 |
|
||||
@ -1,11 +0,0 @@ |
|||||
require 'SystemData' |
|
||||
|
|
||||
class Site < SystemData |
|
||||
attr_accessor :name |
|
||||
|
|
||||
def initialize(args = {}) |
|
||||
super(args) |
|
||||
|
|
||||
@name = args[:name] |
|
||||
end |
|
||||
end |
|
||||
@ -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 |
|
||||
@ -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 |
|
||||
@ -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 |
|
||||
@ -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 |
|
||||
@ -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 |
|
||||
@ -1,10 +0,0 @@ |
|||||
module SdAdmin::Database |
|
||||
class Ldap |
|
||||
require 'database/base.rb' |
|
||||
require 'net/ldap' |
|
||||
|
|
||||
include Enumerable |
|
||||
end |
|
||||
|
|
||||
require 'database/ldap' |
|
||||
end |
|
||||
@ -1,13 +0,0 @@ |
|||||
class SdAdmin::Database::Base |
|
||||
|
|
||||
def initialize |
|
||||
@data = Hash.new |
|
||||
end |
|
||||
|
|
||||
def _create(data) |
|
||||
end |
|
||||
|
|
||||
def _read(id) |
|
||||
end |
|
||||
|
|
||||
end |
|
||||
@ -1,3 +0,0 @@ |
|||||
class SdAdmin::Database::Factory |
|
||||
|
|
||||
end |
|
||||
@ -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 |
|
||||
@ -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 |
||||
|
|
||||
@ -0,0 +1,4 @@ |
|||||
|
module DsAdmin |
||||
|
DsAdmin.autoload(:Model, 'model') |
||||
|
DsAdmin.autoload(:Storage, 'storage') |
||||
|
end |
||||
@ -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 |
|
||||
@ -1,16 +1,64 @@ |
|||||
module SdAdmin::Model |
|
||||
module Interface |
|
||||
|
module DsAdmin::Model |
||||
|
include Enumerable |
||||
|
|
||||
|
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') |
||||
|
|
||||
|
def (DsAdmin::Model).storage=(storage) |
||||
|
@@storage = storage |
||||
|
end |
||||
|
|
||||
|
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 |
end |
||||
|
|
||||
class Base |
|
||||
require 'model/interface' |
|
||||
require 'database' |
|
||||
include SdAdmin::Model::Interface |
|
||||
|
def load!(id) |
||||
|
initialize(_load(id)) |
||||
end |
end |
||||
|
|
||||
class User < Base |
|
||||
|
def save |
||||
|
@id = @storage.create_id(self) unless @id |
||||
|
@storage.write(self) |
||||
end |
end |
||||
|
|
||||
require 'model/base' |
|
||||
require 'model/user' |
|
||||
|
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 |
end |
||||
@ -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 |
|
||||
@ -1,14 +1,14 @@ |
|||||
require 'SystemData' |
|
||||
|
class DsAdmin::Model::Group |
||||
|
include DsAdmin::Model |
||||
|
|
||||
class Group < SystemData |
|
||||
attr_accessor :name, :gid, :members |
attr_accessor :name, :gid, :members |
||||
|
|
||||
def initialize(args = {}) |
def initialize(args = {}) |
||||
|
return if args.empty? |
||||
super(args) |
super(args) |
||||
|
|
||||
@name = args[:name] |
@name = args[:name] |
||||
@gid = args[:gid] |
@gid = args[:gid] |
||||
@members = args[:members] |
|
||||
@members = Array.new if @members.nil? |
|
||||
|
@members = args[:members] ? args[:members] : Array.new |
||||
end |
end |
||||
end |
end |
||||
@ -1,7 +0,0 @@ |
|||||
module SdAdmin::Model::Interface |
|
||||
|
|
||||
def all |
|
||||
Hash[self.backend.map{|key,entry| [key, entry]}] |
|
||||
end |
|
||||
|
|
||||
end |
|
||||
@ -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 |
|
||||
@ -1,10 +0,0 @@ |
|||||
module SdAdmin |
|
||||
module Model |
|
||||
end |
|
||||
|
|
||||
module Database |
|
||||
end |
|
||||
|
|
||||
require 'model' |
|
||||
require 'database' |
|
||||
end |
|
||||
@ -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 |
||||
@ -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 |
||||
@ -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 |
||||
@ -0,0 +1,3 @@ |
|||||
|
class DsAdmin::Storage::Mysql |
||||
|
include DsAdmin::Storage |
||||
|
end |
||||
@ -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}` |
|
||||
@ -1,5 +0,0 @@ |
|||||
require 'sd_admin' |
|
||||
|
|
||||
user = SdAdmin::Model::User.new |
|
||||
|
|
||||
puts user.all.inspect |
|
||||
@ -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 |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue