You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@whimsical.apache.org by ru...@apache.org on 2017/04/01 22:46:46 UTC
[whimsy] branch master updated: prep for final testing
This is an automated email from the ASF dual-hosted git repository.
rubys pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/whimsy.git
The following commit(s) were added to refs/heads/master by this push:
new 290bb79 prep for final testing
290bb79 is described below
commit 290bb7956266b1ded4a856a9599a6d32a44701fa
Author: Sam Ruby <ru...@intertwingly.net>
AuthorDate: Sat Apr 1 18:46:35 2017 -0400
prep for final testing
---
www/secmail/templates/mem.erb | 8 +-
www/secmail/views/actions/memapp.json.rb | 242 +++++++++++++++++++++++++++++++
www/secmail/views/forms/memapp.js.rb | 47 +++++-
3 files changed, 282 insertions(+), 15 deletions(-)
diff --git a/www/secmail/templates/mem.erb b/www/secmail/templates/mem.erb
index aed6045..dcd9df2 100644
--- a/www/secmail/templates/mem.erb
+++ b/www/secmail/templates/mem.erb
@@ -1,10 +1,4 @@
-to: <%= @realname.inspect %> <<%= @memail %>>
-from: <%= @from %>
-cc: secretary@apache.org
-bcc: <%= @bcc %>
-subject: Your ASF Membership Application
-
-Dear <%= @realname %>,
+Dear <%= @fullname %>,
This message acknowledges receipt of your membership application, which has been filed in the Apache Software Foundation records.
diff --git a/www/secmail/views/actions/memapp.json.rb b/www/secmail/views/actions/memapp.json.rb
new file mode 100644
index 0000000..b4b4059
--- /dev/null
+++ b/www/secmail/views/actions/memapp.json.rb
@@ -0,0 +1,242 @@
+#
+# File an membership application:
+# - add files to documents/member_apps
+# - add entry to foundation/members.txt
+# - update memapp-received.txt
+# - respond to original email
+#
+
+# extract message
+message = Mailbox.find(@message)
+
+# extract file extension
+fileext = File.extname(@selected).downcase if @signature.empty?
+
+# verify that a membership form under that name doesn't already exist
+if "#@filename#{fileext}" =~ /\w[-\w]*\.?\w*/
+ form = "#{ASF::SVN['private/documents/member_apps']}/#@filename#{fileext}"
+ if File.exist? form.untaint
+ _warn "documents/member_apps/#@filename#{fileext} already exists"
+ end
+end
+
+# obtain per-user information
+_personalize_email(env.user)
+
+# initialize commit message
+@document = "Membership Application for #{@fullname}"
+
+########################################################################
+# document/member_apps #
+########################################################################
+
+# write attachment (+ signature, if present) to the documents/member_apps
+# directory
+task "svn commit documents/member_apps/#@filename#{fileext}" do
+ form do
+ _input value: @selected, name: 'selected'
+
+ if @signature and not @signature.empty?
+ _input value: @signature, name: 'signature'
+ end
+ end
+
+ complete do |dir|
+ # checkout empty directory
+ svn 'checkout', '--depth', 'empty',
+ 'https://svn.apache.org/repos/private/documents/member_apps',
+ "#{dir}/member_apps"
+
+ # create/add file(s)
+ dest = message.write_svn("#{dir}/member_apps", @filename, @selected,
+ @signature)
+
+ # Show files to be added
+ svn 'status', "#{dir}/member_apps"
+
+ # commit changes
+ svn 'commit', "#{dir}/member_apps/#{@filename}#{fileext}", '-m', @document
+ end
+end
+
+########################################################################
+# members.txt #
+########################################################################
+
+# insert entry into members.txt
+task "svn commit foundation/members.txt" do
+ # construct line to be inserted
+ @entry = [
+ "#{@fullname}",
+ "#{@addr.gsub(/^/,' ').gsub(/\r/,'')}",
+ (" #{@country}" unless @country.empty?),
+ " Email: #{@email}",
+ (" Tel: #{@tele}" unless @tele.empty?),
+ (" Fax: #{@fax}" unless @fax.empty?),
+ " Forms on File: ASF Membership Application",
+ " Avail ID: #{@availid}"
+ ].compact.join("\n") + "\n"
+
+ form do
+ _textarea @entry, name: 'entry', rows: @entry.split("\n").length
+ end
+
+ complete do |dir|
+ # checkout empty foundation directory
+ svn 'checkout', '--depth', 'empty',
+ 'https://svn.apache.org/repos/private/foundation', "#{dir}/foundation"
+
+ # retrieve members.txt
+ dest = "#{dir}/foundation/members.txt"
+ svn 'update', dest
+
+ # update members.txt
+ pattern = /^Active.*?^=+\n+(.*?)^Emeritus/m
+ members_txt = open(dest).read
+ data = members_txt.scan(pattern).flatten.first
+ members = data.split(/^\s+\*\)\s+/)
+ members.shift
+ members.push @entry
+ members_txt[pattern,1] = " *) " + members.join("\n *) ")
+ members_txt[/We now number (\d+) active members\./,1] = members.length.to_s
+ File.write(dest, ASF::Member.sort(members_txt))
+
+ # show the changes
+ svn 'diff', dest
+
+ # commit changes
+ svn 'commit', dest, '-m', @document
+ end
+end
+
+########################################################################
+# update cn=member,ou=groups,dc=apache,dc=org #
+########################################################################
+
+task "update cn=member,ou=groups,dc=apache,dc=org in LDAP" do
+ form do
+ _input value: @availid, name: 'availid'
+ end
+
+ complete do
+ ldap = ASF.init_ldap(true)
+ ldap.bind("uid=#{env.user.untaint},ou=people,dc=apache,dc=org",
+ env.password.untaint)
+
+ ldap.modify "cn=#{member},ou=groups,dc=apache,dc=org",
+ [LDAP.mod(LDAP::LDAP_MOD_ADD, 'memberUid', [@availid])]
+
+ _pre "add member: #{ldap.err2string(ldap.err)} (#{ldap.err})",
+ class: (ldap.err == 0 ? '_stdout' : '_stderr')
+
+ ldap.unbind
+ end
+end
+
+########################################################################
+# subscribe to members@apache.org #
+########################################################################
+
+task "subscribe to members@apache.org" do
+ user = ASF::Person.find(@availid)
+ vars = {
+ version: 3, # This must match http://s.apache.org/008
+ availid: @availid,
+ addr: @email,
+ listkey: 'members',
+ member_p: true,
+ chair_p: ASF.pmc_chairs.include?(user),
+ }
+ @subreq = JSON.pretty_generate(vars) + "\n"
+
+ form do
+ _textarea @subreq, name: 'subreq', rows: @subreq.split("\n").length
+ end
+
+ complete do |dir|
+ # determine file name
+ fn = "#{@availid}-members-#{Time.now.strftime '%Y%m%d-%H%M%S-%L'}.json"
+ fn.untaint if @availid =~ /^\w[-.\w]+$/
+
+ # checkout empty directory
+ svn 'checkout', '--depth', 'empty',
+ "https://svn.apache.org/repos/infra/infrastructure/trunk/subreq",
+ "#{dir}/subreq"
+
+ # write out subscription request
+ File.write "#{dir}/subreq/#{fn}", @subreq
+ Kernel.system 'svn', 'add', "#{dir}/subreq/#{fn}"
+
+ # Show changes
+ svn 'diff', "#{dir}/subreq"
+
+ # commit changes
+ svn 'commit', "#{dir}/subreq", '-m', @document
+ end
+end
+
+########################################################################
+# update memapp-received.txt #
+########################################################################
+
+task "svn commit memapp-received.text" do
+ meetings = ASF::SVN['private/foundation/Meetings']
+ file = Dir["#{meetings}/2*/memapp-received.txt"].sort.last.untaint
+ received = File.read(file)
+ if received =~ /^no\s+\w+\s+\w+\s+\w+\s+#{@availid}\s/
+ received[/^(no )\s+\w+\s+\w+\s+\w+\s+#{@availid}\s/,1] = 'yes'
+ end
+ received[/(no )\s+\w+\s+\w+\s+#{@availid}\s/,1] = 'yes'
+ received[/(no )\s+\w+\s+#{@availid}\s/,1] = 'yes'
+ received[/(no )\s+#{@availid}\s/,1] = 'yes'
+ @line = received[/.*\s#{@availid}\s.*/]
+
+ form do
+ _input value: @line, name: 'line'
+ end
+
+ complete do |dir|
+ # checkout empty directory
+ meeting = file.split('/')[-2]
+ svn 'checkout', '--depth', 'empty',
+ "https://svn.apache.org/repos/private/foundation/Meetings/#{meeting}",
+ "#{dir}/#{meeting}"
+
+ # create/add file(s)
+ received = File.read("#{dir}/#{meeting}/memapp-received.txt")
+ received[/.*\s#{@availid}\s.*/] = @line
+ File.write("#{dir}/#{meeting}/memapp-received.txt", received)
+
+ # Show changes
+ svn 'diff', ""#{dir}/#{meeting}"
+
+ # commit changes
+ svn 'commit', "#{dir}/#{meeting}/memapp-received.txt", '-m', @document
+ end
+end
+
+########################################################################
+# email submitter #
+########################################################################
+
+# send confirmation email
+task "email #@email" do
+ # build mail from template
+ mail = message.reply(
+ subject: @document,
+ from: @from,
+ to: "#{@fullname.inspect} <#{@email}>",
+ cc: 'secretary@apache.org',
+ body: template('mem.erb')
+ )
+
+ # echo email
+ form do
+ _message mail.to_s
+ end
+
+ # deliver mail
+ complete do
+ mail.deliver!
+ end
+end
diff --git a/www/secmail/views/forms/memapp.js.rb b/www/secmail/views/forms/memapp.js.rb
index a00e84c..6e2bddd 100644
--- a/www/secmail/views/forms/memapp.js.rb
+++ b/www/secmail/views/forms/memapp.js.rb
@@ -1,6 +1,7 @@
class MemApp < React
def initialize
@received = []
+ @filed = false
@disabled = true
end
@@ -9,6 +10,7 @@ class MemApp < React
_form method: 'post', action: '../../tasklist/memapp', target: 'content' do
_input type: 'hidden', name: 'message'
+ _input type: 'hidden', name: 'selected'
_input type: 'hidden', name: 'signature', value: @@signature
_table.form do
@@ -33,7 +35,8 @@ class MemApp < React
_label 'Full Name', for: 'fullname'
end
_td do
- _input type: :text, name: 'fullname', id: 'fullname', value: @name
+ _input type: :text, name: 'fullname', id: 'fullname', value: @name,
+ disabled: @filed
end
end
@@ -42,7 +45,7 @@ class MemApp < React
_label 'Address', for: 'addr'
end
_td do
- _textarea rows: 5, name: 'addr', id: 'addr'
+ _textarea rows: 5, name: 'addr', id: 'addr', disabled: @filed
end
end
@@ -51,7 +54,8 @@ class MemApp < React
_label 'Country', for: 'country'
end
_td do
- _input type: :text, name: 'country', id: 'country'
+ _input type: :text, name: 'country', id: 'country',
+ disabled: @filed
end
end
@@ -60,7 +64,7 @@ class MemApp < React
_label 'Telephone', for: 'tele'
end
_td do
- _input type: :text, name: 'tele', id: 'tele'
+ _input type: :text, name: 'tele', id: 'tele', disabled: @filed
end
end
@@ -69,7 +73,7 @@ class MemApp < React
_label 'Fax', for: 'fax'
end
_td do
- _input type: :text, name: 'fax', id: 'fax'
+ _input type: :text, name: 'fax', id: 'fax', disabled: @filed
end
end
@@ -78,7 +82,8 @@ class MemApp < React
_label 'E-Mail', for: 'email'
end
_td do
- _input type: :email, name: 'email', id: 'email', value: @email
+ _input type: :email, name: 'email', id: 'email', value: @email,
+ disabled: @filed
end
end
@@ -88,7 +93,7 @@ class MemApp < React
end
_td do
_input type: :text, name: 'filename', id: 'filename',
- value: @filename
+ value: @filename, disabled: @filed
end
end
end
@@ -97,15 +102,27 @@ class MemApp < React
end
end
- # on initial display, default email and fetch memapp-received.txt
+ # on initial display, wire up form, default email and fetch
+ # memapp-received.txt
def componentDidMount()
+ # wire up form
+ jQuery('form')[0].addEventListener('submit', self.file)
+ jQuery('input[name=message]').val(window.parent.location.pathname)
+ jQuery('input[name=selected]').val(@@selected)
+
+ # default email
@email = @@headers.from
+ # fetch memapp-received information
jQuery.getJSON('../../memapp.json') do |result|
@received = result.received
end
+
+ # watch for status updates
+ window.addEventListener 'message', self.status_update
end
+ # when id is selected, default full name and filename
def setid(event)
id = event.target.value
@received.each do |line|
@@ -116,4 +133,18 @@ class MemApp < React
end
end
end
+
+ # handle membership application form submission
+ def file(event)
+ setTimeout 0 do
+ @disabled = true
+ @filed = true
+ end
+ end
+
+ # when tasks complete (or are aborted) reset form
+ def status_update(event)
+ @disabled = false
+ @filed = false
+ end
end
--
To stop receiving notification emails like this one, please contact
['"commits@whimsical.apache.org" <co...@whimsical.apache.org>'].