blob: 55e7a9bd1c8d552664bff91996898ca99abd34b3 [file] [log] [blame]
require 'socket'
require 'net/http'
require 'pathname'
# Validates and prepares invitations
# Called from invite.js.rb POST
# expects the following variables to be set:
# @pmc
# @iclaemail
# @iclaname
# @votelink
# @noticelink
# returns the following keys:
# error
# focus
# token
# pmcEmail
# userEmail
# invitation
# find pmc and user information
# all ppmcs are also pmcs but not all pmcs are ppmcs
pmc = ASF::Committee.find(@pmc)
ppmc = ASF::Podling.find(@pmc)
pmc_type = if ppmc and ppmc.status == 'current' then 'PPMC' else 'PMC' end
user = ASF::Person.find(env.user)
# prototype mail text
prototype_contributor =
"Based on your contributions to #{pmc.name}, you are invited to submit an ICLA
to The Apache Software Foundation, using the following form. Please see
http://apache.org/licenses for details.
"
prototype_committer =
"Congratulations! The #{pmc.name} #{pmc_type} hereby offers you committer privileges
to the #{pmc.name} project.
You can read more about what the expectations are for committers here:
http://www.apache.org/dev/committers.html#committer-responsibilities
These privileges are offered on the understanding that you'll use them
reasonably and with common sense. We like to work on trust rather than
unnecessary constraints.
Being a committer enables you to more easily make changes without needing to
go through the patch submission process.
Being a committer does not require you to participate any more than you already
do, but it does tend to make one even more committed ;-) You will probably find
that you spend more time here.
"
prototype_pmc =
"You are also invited to become a member of the #{pmc.name} PMC.
Being a PMC member enables you to help guide the direction of the project.
You can read more about what the expectations are for PMC members here:
http://www.apache.org/dev/pmc.html#audience
"
prototype_ppmc =
"You are also invited to become a member of the #{pmc.name} PPMC.
Being a PPMC member enables you to help guide the direction of the project.
You can read more about what the expectations are for PPMC members here:
https://incubator.apache.org/guides/ppmc.html
"
prototype_committer_or_pmc =
"Of course, you can decline and instead remain as a contributor, participating
as you do now.
This personal invitation is a chance for you to accept or decline in private.
Either way, please let us know in reply to the private@ address only.
"
# validate email address
if ASF::Person.find_by_email(@iclaemail)
_error "ICLA already on file for #{@iclaemail}"
_focus :iclaemail
return # no point in continuing
end
begin
Socket.getaddrinfo(@iclaemail[/@(.*)/, 1].untaint, 'smtp')
rescue
_error 'Invalid domain name in email address'
_focus :iclaemail
return # no point in continuing
end
# validate vote link
if @votelink and not @votelink.empty?
# verify that the link refers to lists.apache.org message on the project list
if not @votelink=~ /.*lists\.apache\.org.*/
_error "Please link to a message via lists.apache.org"
return # no point in continuing
end
if not @votelink=~ /.*#{pmc.mail_list}(\.incubator)?\.apache\.org.*/
_error "Please link to the [RESULT][VOTE] message sent to the private list."
return # no point in continuing
end
# attempt to fetch the page
if @votelink =~ /^https?:/i
uri = URI.parse(@votelink)
http = Net::HTTP.new(uri.host.untaint, uri.port)
if uri.scheme == 'https'
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
request = Net::HTTP::Head.new(uri.request_uri.untaint)
response = http.request(request)
unless response.code.to_i < 400
_error "HTTP status #{response.code} for #{@votelink}"
_focus :votelink
return # no point in continuing
end
else
_error 'Only http(s) links are accepted for vote links'
_focus :votelink
return # no point in continuing
end
end
# validate notice link
if @noticelink and not @noticelink.empty?
# verify that the link refers to lists.apache.org message on the proper list
if not @noticelink=~ /.*lists\.apache\.org.*/
_error "Please link to a message via lists.apache.org"
return # no point in continuing
end
if pmc_type == 'PMC' and not @noticelink=~ /.*board@apache\.org.*/
_error "Please link to the NOTICE message sent to the board list."
return # no point in continuing
end
if pmc_type == 'PPMC' and not @noticelink=~ /.*private@incubator\.apache\.org.*/
_error "Please link to the NOTICE message sent to the incubator private list."
return # no point in continuing
end
# attempt to fetch the page
if @noticelink =~ /^https?:/i
uri = URI.parse(@noticelink)
http = Net::HTTP.new(uri.host.untaint, uri.port)
if uri.scheme == 'https'
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
request = Net::HTTP::Head.new(uri.request_uri.untaint)
response = http.request(request)
unless response.code.to_i < 400
_error "HTTP status #{response.code} for #{@noticelink}"
_focus :noticelink
return # no point in continuing
end
else
_error 'Only http(s) links are accepted for notice links'
_focus :noticelink
return # no point in continuing
end
end
# add user and pmc emails to the response
_userEmail "#{user.public_name} <#{user.mail.first}>" if user
_pmcEmail "private@#{pmc.mail_list}.apache.org" if pmc
# generate an invitation token
token = Digest::MD5.hexdigest(@iclaemail)[0..15]
path = Pathname.new(env['REQUEST_URI']) + "../../form?token=#{token}"
scheme = env['rack.url_scheme'] || 'https'
link = "#{scheme}://#{env['HTTP_HOST']}#{path}"
# add token and invitation to the response
_token token
_invitation %{Dear #{@iclaname},
#{prototype_contributor if @votelink.empty?}\
#{prototype_committer if not @votelink.empty?}\
#{prototype_pmc if not @noticelink.empty? and (pmc_type == 'PMC')}\
#{prototype_ppmc if not @noticelink.empty? and (pmc_type == 'PPMC')}\
#{prototype_committer_or_pmc if not @votelink.empty?}
Click on this link to accept:
#{link}
Regards,
#{user.public_name if user}
On behalf of the #{pmc.display_name} project
}