diary/ldap_record.rb

183 lines
4.4 KiB
Ruby

# SPDX-License-Identifier: Apache-2.0
# Copyright (C) 2021 OKTET Labs Ltd. All rights reserved.
#
# Class LdapRecord for Diary Management Application.
#
require_relative 'ldap_cache'
require 'net/smtp'
class LdapRecord
@@connection = nil
@@cache = {}
attr_reader :id
def LdapRecord.setup(args)
raise "Invalid parameters" unless args.is_a? Hash
raise "LDAP server is not specified" unless args[:host]
@@ldap = LDAP::Conn.new(args[:host], args[:port] || LDAP::LDAP_PORT)
if args[:ver] == 3
@@ldap.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3)
end
if args[:binddn] != ""
@@ldap.bind(args[:binddn], args[:bindpw])
end
#@@ldap.bind # Bind is optional for LDAPv3
raise "LDAP tree root is not specified" unless args[:root]
raise "LDAP key attribute is not specified" unless args[:key]
@@connection = LDAP::Cache.new(@@ldap, args[:root],
LDAP::LDAP_SCOPE_SUBTREE, args[:key])
end
def initialize(id)
raise "LDAP connection is not established" if not @@connection
@id = id
@@cache[id] = self
@attributes = @@connection[id]
end
def LdapRecord.find(id)
# entry = @@cache[id] || (exists?(id) ? new(id) : nil)
# entry = nil if (entry && !entry.valid?)
# entry
return @@cache[id] if valid?(@@cache[id])
exists?(id) ? new(id) : nil
end
def LdapRecord.valid?(entry)
entry != nil
end
def LdapRecord.find_or_create(id)
@@cache[id] || new(id)
end
def LdapRecord.exists?(id)
@@connection[id] != nil
end
def LdapRecord.find_by_filter(filter)
@@connection.list(filter, "uid").collect { |x| find(x[0]) }.find_all { |x| x }
end
def method_missing(method, *args)
@attributes ? @attributes[method.to_s] : nil
end
end
class Person < LdapRecord
MAX_LENGTH = 30
attr_reader :organization
def initialize(id)
super(id)
@organization = Organization.find_by_name(self.o)
end
def Person.exists?(id)
super(id) && @@connection[id]["objectClass"] == "inetOrgPerson"
end
def Person.valid?(entry)
super(entry) && entry.objectClass == "inetOrgPerson"
end
def Person.set_local(o_name, ou_name)
@@local_o = o_name
@@local_ou = ou_name
end
def to_s
self.cn || @id
end
def to_html
if not self.cn
e(:span, :style => "color:red"){ @id }
elsif self.mail
e(:a, :href => "mailto:" + self.mail){ self.cn }
else
e(:span){ self.cn }
end
end
def local?
self.o == @@local_o
end
def employee?
local? and self.ou == @@local_ou
end
def customer?
self.o != nil and not local?
end
def Person.find_by_org(org_name)
find_by_filter("(&(o=#{org_name})(objectClass=inetOrgPerson))")
end
def <=>(rhs)
if self.cn
rhs.cn ? self.cn <=> rhs.cn : -1
else
rhs.cn ? 1 : @id <=> rhs.id
end
end
end
class Organization < LdapRecord
def to_s
self.o || @id
end
def to_html
if not self.o
e(:span, :style => "color:red"){ @id }
else
e(:span){ self.o }
end
end
def Organization.exists?(id)
super(id) && @@connection[id]["objectClass"] == "organization"
end
def Organization.valid?(entry)
super(entry) && entry.objectClass == "organization"
end
def Organization.all
find_by_filter("(objectClass=organization)")
end
def Organization.find_by_name(name)
return nil unless name.is_a? String
res = find_by_filter("(&(o=#{name})(objectClass=organization))")
res ? res[0] : nil
end
def <=>(rhs)
if self.o
rhs.o ? self.o <=> rhs.o : -1
else
rhs.o ? 1 : @id <=> rhs.id
end
end
end
class Notifier
def notify(who, message)
raise "No such person \"#{who.to_s}\"" if not who.is_a? Person
msg = "From: Diary Management Application <#{DiaryEnv::SMTP_FROM}>\n" +
"To: #{who.cn} <#{who.mail}>\n" +
"Subject: Diary Management\n" +
"\n" + message
Net::SMTP.start(DiaryEnv::SMTP_HOST) do |smtp|
smtp.send_message msg, DiaryEnv::SMTP_FROM, who.mail.untaint
end
end
end