Skip to content

Commit ebc9a6c

Browse files
committed
Allow for potential duplicates; return Set
1 parent 7615c63 commit ebc9a6c

6 files changed

Lines changed: 70 additions & 54 deletions

File tree

lib/whimsy/asf/mail.rb

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,46 +3,54 @@
33
module ASF
44
# Convenience functions related to emails or mailing lists.
55
class Mail
6-
# return a Hash containing complete list of all known emails, and the
7-
# ASF::Person that is associated with that email.
8-
def self.list
9-
begin
10-
return @list.to_h if @list
11-
rescue NoMethodError, WeakRef::RefError
12-
end
6+
# return a hash containing down-cased email names, together with a Set of people with whom
7+
# they are associated. In almost all cases there is only a single associated person.
8+
# The emails are sourced from LDAP, and optionally members.txt and iclas.txt
9+
def self.listall
10+
# Note: no point currently caching the list in memory, as this method is only used by cgi scripts
1311

14-
list = {}
12+
list = Hash.new{|h,k| h[k] = Set.new} # this creates a default Proc, which we remove later
1513

1614
# load info from LDAP
17-
people = ASF::Person.preload(['mail', 'asf-altEmail'])
15+
people = ASF::Person.preload(['mail', 'asf-altEmail', 'cn'])
1816
people.each do |person|
1917
(person.mail + person.alt_email).each do |mail|
20-
list[mail.downcase] = person
18+
list[mail.downcase] << person # there may be more that one person associated with a single email
2119
end
2220
end
2321

2422
# load all member emails in one pass
2523
ASF::Member.each do |id, text|
2624
Member.emails(text).each do |mail|
27-
list[mail.downcase] ||= Person.find(id)
25+
list[mail.downcase] << Person.find(id) # this should find one of the pre-loads
2826
end
2927
end
3028

3129
# load all ICLA emails in one pass
3230
ASF::ICLA.each do |icla|
3331
person = Person.find(icla.id)
3432
icla.emails.each do |email|
35-
list[email.downcase] ||= person
33+
list[email.downcase] << person
3634
end
3735
next if icla.noId?
3836

39-
list["#{icla.id.downcase}@apache.org"] ||= person
37+
list["#{icla.id.downcase}@apache.org"] << person # is this needed?
4038
end
4139

42-
@list = WeakRef.new(list)
40+
list.default_proc = nil # no longer create an empty set when a key is missing
4341
list
4442
end
4543

44+
# Allow for trailing +- suffix in emails.
45+
# e.g.
46+
# username-test@apache.org => username@apache.org
47+
# username+test@gmail.com => username@gmail.com
48+
def self.remove_email_suffix(email)
49+
# TODO: may need to tighten this to avoid ambiguities
50+
# e.g. selectively apply '-xxx' or '+xxx' removal, depending on domain
51+
email.downcase.sub(/[-+]\w+@/,'@') # drop suffix
52+
end
53+
4654
# return a list of people ids, their public-name, whether they are an ASF member, and email addresses
4755
def self.people_mails
4856
member_statuses = ASF::Member.member_statuses # cache the statuses. TODO: should be done in ASF.Member

www/board/subscriptions.cgi

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,18 +65,21 @@ _html do
6565
end
6666

6767
ids = []
68-
maillist = ASF::Mail.list
69-
subscribers.each do |line|
70-
person = maillist[line.downcase]
71-
person ||= maillist[line.downcase.sub(/\+\w+@/,'@')]
72-
if person
73-
id = person.id
74-
id = '*notinavail*' if id == 'notinavail'
68+
maillist = ASF::Mail.listall
69+
subscribers.each do |email|
70+
people = maillist[email.downcase] # email may match more than one person
71+
people ||= maillist[ASF::Mail.remove_email_suffix(email)]
72+
if people
73+
people.each do |person|
74+
id = person.id
75+
id = '*notinavail*' if id == 'notinavail'
76+
ids << [id, person, email]
77+
end
7578
else
7679
person = ASF::Person.find('notinavail')
7780
id = '*missing*'
81+
ids << [id, person, email]
7882
end
79-
ids << [id, person, line]
8083
end
8184

8285
_table_.table do

www/members/moderator_checks.cgi

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,14 @@ _html do
3434
_h2 'DRAFT - List moderators whose email addresses are not recognised'
3535
_p 'If the domain is @apache.org, the email is most likely a typo'
3636
_p 'In other cases, perhaps the email is not registered'
37-
_p do
38-
_b 'Emails are matched exactly - case is treated significant, even for domains'
39-
end
4037
}
4138
) do
4239
lists, _time = ASF::MLIST.list_moderators(nil)
43-
emails = ASF::Mail.list
40+
emails = ASF::Mail.listall
4441
unknown = Hash.new { |h, k| h[k] = []}
4542
lists.each do |lid, mods|
4643
mods.each do |mod|
47-
unknown[mod] << lid unless MODERATORS.include? mod or emails[mod] or private_mod(lid, mod)
44+
unknown[mod] << lid unless MODERATORS.include? mod or emails[mod.downcase] or private_mod(lid, mod)
4845
end
4946
end
5047

www/members/subscriptions.cgi

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,20 +62,22 @@ _html do
6262

6363
members = ASF::Member.new.map {|id, text| ASF::Person.find(id)}
6464
ASF::Person.preload('cn', members)
65-
maillist = ASF::Mail.list
66-
65+
maillist = ASF::Mail.listall
6766
subscriptions = []
68-
subscribers.each do |line|
69-
person = maillist[line.downcase]
70-
person ||= maillist[line.downcase.sub(/[-+]\w+@/,'@')] # allow for trailing +- suffix
71-
if person
72-
id = person.id
73-
id = '*notinavail*' if id == 'notinavail'
67+
subscribers.each do |email|
68+
people = maillist[email.downcase]
69+
people ||= maillist[ASF::Mail.remove_email_suffix(email)]
70+
if people
71+
people.each do |person| # email may match more than one person
72+
id = person.id
73+
id = '*notinavail*' if id == 'notinavail'
74+
subscriptions << [id, person, email]
75+
end
7476
else
7577
person = ASF::Person.find('notinavail')
7678
id = '*missing*'
79+
subscriptions << [id, person, email]
7780
end
78-
subscriptions << [id, person, line]
7981
end
8082

8183
_table.table do

www/members/subscriptions2.cgi

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,20 +68,23 @@ _html do
6868
nonASFemails = []
6969
members = ASF::Member.new.map {|id, _text| ASF::Person.find(id)}
7070
ASF::Person.preload('cn', members)
71-
maillist = ASF::Mail.list
71+
maillist = ASF::Mail.listall
7272

7373
subscriptions = []
74-
subscribers.each do |line|
75-
person = maillist[line.downcase]
76-
person ||= maillist[line.downcase.sub(/[-+]\w+@/, '@')] # allow for trailing +- suffix
77-
if person
78-
id = person.id
79-
id = '*notinavail*' if id == 'notinavail'
74+
subscribers.each do |email|
75+
people = maillist[email.downcase]
76+
people ||= maillist[ASF::Mail.remove_email_suffix(email)]
77+
if people
78+
people.each do |person| # email may match more than one person
79+
id = person.id
80+
id = '*notinavail*' if id == 'notinavail'
81+
subscriptions << [id, person, email]
82+
end
8083
else
8184
person = ASF::Person.find('notinavail')
8285
id = '*missing*'
86+
subscriptions << [id, person, email]
8387
end
84-
subscriptions << [id, person, line]
8588
end
8689

8790
_table.table do

www/officers/subscriptioncheck.cgi

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ MEMBER_ANNOUNCE_OK = %w(board-chair@apache.org secretary@apache.org)
1919

2020
DEFAULT_LISTS = 'board,markpub,members,members-announce,members-notify,operations,press,trademarks,private@infra.apache.org'
2121
listnames = ENV['QUERY_STRING']
22-
listnames = DEFAULT_LISTS if listnames == ''
22+
listnames = DEFAULT_LISTS if listnames == '' or listnames.nil?
2323

2424
info_chairs = ASF::Committee.load_committee_info.group_by(&:chair)
2525
ldap_chairs = ASF.pmc_chairs
@@ -93,19 +93,22 @@ _html do
9393
_ "(updated #{modtime})"
9494
end
9595
subscribers -= MEMBER_ANNOUNCE_OK if listid == 'members-announce@apache.org'
96-
subscribers -= ['trademarks@gsuite.cloud.apache.org'] if listid = 'trademarks@apache.org'
97-
maillist = ASF::Mail.list
98-
subscribers.each do |line|
99-
person = maillist[line.downcase]
100-
person ||= maillist[line.downcase.sub(/\+\w+@/,'@')]
101-
if person
102-
id = person.id
103-
id = '*notinavail*' if id == 'notinavail'
96+
subscribers -= ['trademarks@gsuite.cloud.apache.org'] if listid == 'trademarks@apache.org'
97+
maillist = ASF::Mail.listall
98+
subscribers.each do |email|
99+
people = maillist[email.downcase]
100+
people ||= maillist[ASF::Mail.remove_email_suffix(email)]
101+
if people
102+
people.each do |person|
103+
id = person.id
104+
id = '*notinavail*' if id == 'notinavail'
105+
ids << [id, person, email]
106+
end
104107
else
105108
person = ASF::Person.find('notinavail')
106109
id = '*missing*'
110+
ids << [id, person, email]
107111
end
108-
ids << [id, person, line]
109112
end
110113
end
111114

0 commit comments

Comments
 (0)