20 changed files with 540 additions and 6 deletions
-
12SystemDataBackendLdap.rb
-
91controllers/system_data.rb
-
10database.rb
-
13database/base.rb
-
3database/factory.rb
-
53database/ldap.rb
-
0loader/user.rb
-
197mappers/ldap.rb
-
16model.rb
-
9model/base.rb
-
14model/group.rb
-
7model/interface.rb
-
17model/mail_account.rb
-
18model/mail_alias_person.rb
-
17model/mail_alias_role.rb
-
11model/site.rb
-
24model/system_data.rb
-
19model/user.rb
-
10sd_admin.rb
-
5test_dummy2.rb
@ -0,0 +1,91 @@ |
|||
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 |
|||
@ -0,0 +1,10 @@ |
|||
module SdAdmin::Database |
|||
class Ldap |
|||
require 'database/base.rb' |
|||
require 'net/ldap' |
|||
|
|||
include Enumerable |
|||
end |
|||
|
|||
require 'database/ldap' |
|||
end |
|||
@ -0,0 +1,13 @@ |
|||
class SdAdmin::Database::Base |
|||
|
|||
def initialize |
|||
@data = Hash.new |
|||
end |
|||
|
|||
def _create(data) |
|||
end |
|||
|
|||
def _read(id) |
|||
end |
|||
|
|||
end |
|||
@ -0,0 +1,3 @@ |
|||
class SdAdmin::Database::Factory |
|||
|
|||
end |
|||
@ -0,0 +1,53 @@ |
|||
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,197 @@ |
|||
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 |
|||
@ -0,0 +1,16 @@ |
|||
module SdAdmin::Model |
|||
module Interface |
|||
end |
|||
|
|||
class Base |
|||
require 'model/interface' |
|||
require 'database' |
|||
include SdAdmin::Model::Interface |
|||
end |
|||
|
|||
class User < Base |
|||
end |
|||
|
|||
require 'model/base' |
|||
require 'model/user' |
|||
end |
|||
@ -0,0 +1,9 @@ |
|||
class SdAdmin::Model::Base |
|||
attr_reader :backend |
|||
|
|||
def initialize(backend) |
|||
@backend = SdAdmin::Database::Ldap.new |
|||
@backend = backend if backend |
|||
end |
|||
|
|||
end |
|||
@ -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 |
|||
@ -0,0 +1,7 @@ |
|||
module SdAdmin::Model::Interface |
|||
|
|||
def all |
|||
Hash[self.backend.map{|key,entry| [key, entry]}] |
|||
end |
|||
|
|||
end |
|||
@ -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 |
|||
@ -0,0 +1,18 @@ |
|||
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 |
|||
@ -0,0 +1,17 @@ |
|||
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 |
|||
@ -0,0 +1,11 @@ |
|||
require 'SystemData' |
|||
|
|||
class Site < SystemData |
|||
attr_accessor :name |
|||
|
|||
def initialize(args = {}) |
|||
super(args) |
|||
|
|||
@name = args[:name] |
|||
end |
|||
end |
|||
@ -0,0 +1,24 @@ |
|||
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 |
|||
@ -0,0 +1,19 @@ |
|||
class SdAdmin::Model::User |
|||
attr_accessor :name, :pass, :uid, :gid, :shell, :home |
|||
|
|||
def initialize(args={}, backend=nil) |
|||
super(backend) |
|||
|
|||
@backend.base_dn = 'ou=user,o=system,dc=weird-web-workers,dc=org' |
|||
@backend.filter = '(objectClass=posixAccount)' |
|||
|
|||
@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 |
|||
@ -0,0 +1,10 @@ |
|||
module SdAdmin |
|||
module Model |
|||
end |
|||
|
|||
module Database |
|||
end |
|||
|
|||
require 'model' |
|||
require 'database' |
|||
end |
|||
@ -0,0 +1,5 @@ |
|||
require 'sd_admin' |
|||
|
|||
user = SdAdmin::Model::User.new |
|||
|
|||
puts user.all.inspect |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue