-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
178 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
#!/usr/bin/env ruby | ||
$LOAD_PATH.unshift '/srv/whimsy/lib' | ||
|
||
require 'wunderbar' | ||
require 'whimsy/asf/config' | ||
require 'whimsy/asf/svn' | ||
|
||
module ASF | ||
# Handle subscribe and unsubscribe requests | ||
# | ||
# This is a two part process (so the request can be shown to the user before committing if required) | ||
# user = ASF::Person.new(person) | ||
# request = ASF::Subreq.create_request(user, email, list) | ||
# ASF::Subreq.queue_request(reqtype, request, wunderbar, options) | ||
module Subreq | ||
FORMAT_NUMBER = 3 # json format number | ||
|
||
# Create the request hash | ||
# Params: | ||
# user: ASF::Person instance | ||
# email: the email to unsubscribe | ||
# list: listname@domain | ||
# Returns: hash suitable for saving as a JSON file | ||
def self.create_request(user, email, list) | ||
{ | ||
version: FORMAT_NUMBER, | ||
availid: user.id, | ||
addr: email, | ||
listkey: list, | ||
member_p: user.asf_member?, # does not appear to be used | ||
chair_p: ASF.pmc_chairs.include?(user), # does not appear to be used | ||
} | ||
end | ||
|
||
# Queue the update request | ||
# Params: | ||
# - reqtype: 'sub'|'unsub' | ||
# - request: hash generated by create_request | ||
# - wbar: wunderbar context (or nil) | ||
# - credentials: has containing credentials; may also contain options, e.g. verbose: true | ||
def self.queue_request(reqtype, request, wbar, credentials) | ||
raise Exception.new("Unexpected reqtype: #{reqtype}") unless %w{sub unsub}.include? reqtype | ||
|
||
queue_url = ASF::SVN.svnpath!('subreq') # only this URL is defined | ||
queue_url.sub! '/subreq', '/unsubreq' if reqtype == 'unsub' | ||
|
||
# subreq/unsubreq now accept name@dom | ||
# Keep the key for the file name | ||
list = request[:listkey] | ||
listkey = ASF::Mail.listdom2listkey(list) | ||
userid = request[:availid] | ||
|
||
content = JSON.pretty_generate(request) + "\n" | ||
|
||
# Each user can only (un)subscribe once to each list in each timeslot | ||
fn = "#{userid}-#{listkey}.json" | ||
|
||
Dir.mktmpdir do |tmpdir| | ||
|
||
if wbar | ||
ASF::SVN.svn_!('checkout', [queue_url, tmpdir], wbar, credentials) | ||
else | ||
ASF::SVN.svn!('checkout', [queue_url, tmpdir], credentials) | ||
end | ||
path = File.join(tmpdir, fn) | ||
if File.exist? path | ||
File.write(path, content) # overwrite | ||
else | ||
File.write(path, content) # new | ||
ASF::SVN.svn('add', path) | ||
end | ||
|
||
if reqtype == 'unsub' | ||
message = "#{list} -= #{userid}" | ||
else | ||
message = "#{list} += #{userid}" | ||
end | ||
|
||
options = credentials.merge({msg: message}) | ||
if wbar | ||
ASF::SVN.svn_!('commit', path, wbar, options) | ||
else | ||
ASF::SVN.svn!('commit', path, options) | ||
end | ||
end | ||
return nil | ||
end | ||
end | ||
end | ||
|
||
if __FILE__ == $0 | ||
list = ARGV.shift or raise Exception.new('need list') | ||
person = ARGV.shift or raise Exception.new('need id') | ||
email = ARGV.shift or raise Exception.new('need email') | ||
dryrun = ARGV.shift != 'nodryrun' | ||
require 'whimsy/asf' | ||
user = ASF::Person.new(person) | ||
request = ASF::Subreq.create_request(user, email, list) | ||
puts request | ||
rc,err = ASF::Subreq.queue_request('unsub', request, nil, {dryrun: dryrun, verbose: true}) | ||
puts rc | ||
p err | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
# get entry for @userid | ||
require 'wunderbar' | ||
|
||
user = ASF::Person.find(@userid) | ||
entry = user.members_txt(true) | ||
raise Exception.new("Unable to find member entry for #{@userid}") unless entry | ||
|
@@ -56,55 +57,79 @@ | |
[ASF::Member.normalize(text), extra] | ||
end | ||
|
||
############### INCOMPLETE ####################### | ||
# elsif @action == 'withdraw' # process withdrawal request (secretary only) | ||
# # TODO | ||
# # update LDAP - remove from members | ||
# # unsubscribe from member only mailing lists: | ||
# # - compare subscriptions against ASF::Mail.cansub | ||
# Tempfile.create('withdraw') do |tempfile| | ||
# ASF::SVN.multiUpdate_ members_txt, message, env, _ do |text| | ||
# extra = [] | ||
# # remove user's entry | ||
# unless text.sub! entry, '' # e.g. if the workspace was out of date | ||
# raise Exception.new('Failed to remove existing entry -- try refreshing') | ||
# end | ||
# # save the entry to the archive | ||
# File.write(tempfile, entry) | ||
# tempfile.close | ||
# extra << ['put' , tempfile.path, ASF::SVN.svnpath!('withdrawn', 'archive', "#{@userid}.txt")] | ||
|
||
# # Find matching request for the id | ||
# pathname, basename = ASF::WithdrawalRequestFiles.findpath(@userid, env) | ||
# unless pathname | ||
# raise Exception.new("Failed to find withdrawal pending file for #{@userid}") | ||
# end | ||
|
||
# # Move the request from pending - this should also work for directories | ||
# extra << ['mv', pathname, ASF::SVN.svnpath!('withdrawn', basename)] | ||
# [ASF::Member.normalize(text), extra] | ||
# end | ||
# ASF::WithdrawalRequestFiles.refreshnames(true, env) # update the listing if successful | ||
# ASF::Mail.configure | ||
# mail = Mail.new do | ||
# from '[email protected]' | ||
# to "#{USERNAME}<#{USERMAIL}>" | ||
# subject "Acknowledgement of membership withdrawal from #{USERNAME}" | ||
# text_part do | ||
# body <<~EOD | ||
# The membership withdrawal request that was registered for you has now been actioned. | ||
# Your details have been removed from the membership roster. | ||
# You have also been unsubscribed from members-only private email lists. | ||
elsif @action == 'withdraw' # process withdrawal request (secretary only) | ||
require 'whimsy/asf/subreq' | ||
|
||
# TODO | ||
# Check members.md for entry and report - how? | ||
|
||
# unsubscribe from member only mailing lists: | ||
all_mail = user.all_mail # their known emails | ||
pmc_chair = ASF.pmc_chairs.include?(user) | ||
# to which (P)PMCs do they belong? | ||
ldap_pmcs = user.committees.map(&:mail_list) | ||
ldap_pmcs += user.podlings.map(&:mail_list) | ||
# What are their subscriptions? | ||
subs = ASF::MLIST.subscriptions(all_mail)[:subscriptions] | ||
subs += ASF::MLIST.digests(all_mail)[:digests] | ||
# Check subscriptions for readability | ||
subs.each do |list, email| | ||
unless ASF::Mail.canread(list, false, pmc_chair, ldap_pmcs) | ||
request = ASF::Subreq.create_request(user, email, list) | ||
ASF::Subreq.queue_request('unsub', request, nil, {env: env}) | ||
end | ||
end | ||
# remove from LDAP member group | ||
ASF::LDAP.bind(env.user, env.password) do | ||
ASF::Group['member'].remove(user) | ||
end | ||
|
||
# Remove from members.txt | ||
Tempfile.create('withdraw') do |tempfile| | ||
ASF::SVN.multiUpdate_ members_txt, message, env, _, {verbose: true} do |text| | ||
extra = [] | ||
# remove user's entry | ||
unless text.sub! entry, '' # e.g. if the workspace was out of date | ||
raise Exception.new('Failed to remove existing entry -- try refreshing') | ||
end | ||
# save the entry to the archive | ||
File.write(tempfile, entry) | ||
tempfile.close | ||
extra << ['put' , tempfile.path, ASF::SVN.svnpath!('withdrawn', 'archive', "#{@userid}.txt")] | ||
|
||
# Find matching request for the id | ||
pathname, basename = ASF::WithdrawalRequestFiles.findpath(@userid, env) | ||
unless pathname | ||
raise Exception.new("Failed to find withdrawal pending file for #{@userid}") | ||
end | ||
|
||
# Move the request from pending - this should also work for directories | ||
extra << ['mv', pathname, ASF::SVN.svnpath!('withdrawn', basename)] | ||
[ASF::Member.normalize(text), extra] | ||
end | ||
ASF::WithdrawalRequestFiles.refreshnames(true, env) # update the listing if successful | ||
|
||
# Send confirmation email | ||
ASF::Mail.configure | ||
mail = Mail.new do | ||
from '[email protected]' | ||
to "#{USERNAME}<#{USERMAIL}>" | ||
subject "Acknowledgement of membership withdrawal from #{USERNAME}" | ||
text_part do | ||
body <<~EOD | ||
The membership withdrawal request that was registered for you has now been actioned. | ||
Your details have been removed from the membership roster. | ||
You have also been unsubscribed from members-only private email lists. | ||
# Warm Regards, | ||
Warm Regards, | ||
# Secretary, Apache Software Foundation | ||
# [email protected] | ||
# EOD | ||
# end | ||
# end | ||
# mail.deliver! | ||
# end | ||
Secretary, Apache Software Foundation | ||
[email protected] | ||
EOD | ||
end | ||
end | ||
mail.deliver! | ||
end | ||
|
||
elsif @action == 'rescind_withdrawal' # Secretary only | ||
pathname, _basename = ASF::WithdrawalRequestFiles.findpath(@userid, env) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters