blob: 442a3f074bb35c010e02b4c0b5017f8e145ed04b [file] [log] [blame]
#!/usr/bin/env ruby
#
# Server side router/controllers
#
require 'whimsy/asf'
require 'mail'
require 'tmpdir'
require 'wunderbar/sinatra'
require 'wunderbar/bootstrap/theme'
require 'wunderbar/vue'
require 'wunderbar/underscore'
require 'wunderbar/markdown'
require 'wunderbar/jquery/stupidtable'
require 'ruby2js/filter/functions'
require 'ruby2js/filter/require'
require_relative 'banner'
require_relative 'models'
disable :logging # suppress log of requests to stderr/error.log
ASF::Mail.configure
helpers do
def cssmtime
File.mtime('public/stylesheets/app.css').to_i
end
end
get '/' do
if env['REQUEST_URI'].end_with? '/'
@committers = ASF::Person.list
@committees = ASF::Committee.list
@members = ASF::Member.list.keys - ASF::Member.status.keys
@groups = Group.list
@podlings = ASF::Podling.to_h.values
_html :index
else
redirect to('/')
end
end
get '/committer/' do
_html :committers
end
get '/committer' do
redirect to('/committer/')
end
get '/committee/' do
@members = ASF::Member.list.keys
@committees = ASF::Committee.pmcs
_html :committees
end
get '/committee' do
redirect to('/committee/')
end
index = nil
index_time = nil
index_etag = nil
get '/committer/index.json' do
# recompute index if the data is 5 minutes old or older
index = nil if not index_time or Time.now-index_time >= 300
if not index
# bulk loading the mail information makes things go faster
mail = Hash[ASF::Mail.list.group_by(&:last).
map {|person, list| [person, list.map(&:first)]}]
# build a list of people, their public-names, and email addresses
index = ASF::Person.list.sort_by(&:id).map {|person|
result = {id: person.id, name: person.public_name, mail: mail[person]}
result[:member] = true if person.asf_member?
result
}.to_json
# cache
index_time = Time.now
index_etag = etag = Digest::MD5.hexdigest(index)
end
# send response
last_modified index_time
etag index_etag
content_type 'application/json', charset: 'UTF-8'
expires [index_time+300, Time.now+60].max
index
end
get '/committee/:name.json' do |name|
data = Committee.serialize(name, env)
pass unless data
_json data
end
get '/committee/:name' do |name|
@auth = Auth.info(env)
@committee = Committee.serialize(name, env)
pass unless @committee
_html :committee
end
get '/committer/:name.json' do |name|
data = Committer.serialize(name, env)
pass unless data
_json data
end
# make __self__ an alias for one's own page
get '/committer/__self__' do
redirect to("committer/#{env.user}")
end
get '/committer/:name' do |name|
@auth = Auth.info(env)
@committer = Committer.serialize(name, env)
pass unless @committer
_html :committer
end
post '/committer/:userid/:file' do |name, file|
_json :"actions/#{params[:file]}"
end
get '/group/:name.json' do |name|
_json Group.serialize(name)
end
get '/group/:name' do |name|
@auth = Auth.info(env)
@group = Group.serialize(name)
pass unless @group and not @group.empty?
_html :group
end
get '/group/' do
@groups = Group.list
@podlings = ASF::Podling.to_h
_html :groups
end
# member list
get '/members' do
_html :members
end
get '/members.json' do
_json Hash[ASF.members.map {|person| [person.id, person.public_name]}.sort]
end
# active podling list
get '/ppmc/' do
@projects = ASF::Project.list
@ppmcs = ASF::Podling.list.select {|podling| podling.status == 'current'}
_html :ppmcs
end
# individual podling info
get '/ppmc/:name.json' do |name|
_json PPMC.serialize(name, env)
end
post '/ppmc/:name/establish' do |name|
@name = name
@chair = params[:chair] || env.user
@description = params[:description]
_text :'ppmc/establish'
end
get '/ppmc/:name' do |name|
@auth = Auth.info(env)
user = ASF::Person.find(env.user)
@auth[:ipmc] = ASF::Committee.find('incubator').members.include? user
@ppmc = PPMC.serialize(name, env)
pass unless @ppmc
_html :ppmc
end
# complete podling list
get '/podlings' do
attic = ASF::SVN['asf/attic/site/xdocs/projects']
@attic = Dir["#{attic}/*.xml"].map {|file| File.basename(file, '.xml')}
@committees = ASF::Committee.list.map(&:id)
@podlings = ASF::Podling.list
_html :podlings
end
# posted actions
post '/actions/:file' do
_json :"actions/#{params[:file]}"
end
# attic issues
get '/attic/issues.json' do
_json Attic.issues
end
# overall organization chart
get '/orgchart/' do
@org = OrgChart.load
_html :orgchart
end
# individual duties
get '/orgchart/:name' do |name|
person = ASF::Person.find(env.user)
unless person.asf_member? or ASF.pmc_chairs.include? person
halt 401, "Not authorized\n"
end
@org = OrgChart.load
@role = @org[name]
@desc = OrgChart.desc
pass unless @role
@oversees = @org.select do |role, duties|
duties['info']['reports-to'].split(/[, ]+/).include? name
end
_html :duties
end
# for debugging purposes
get '/env' do
content_type 'text/plain'
asset = {
path: Wunderbar::Asset.path,
root: Wunderbar::Asset.root,
virtual: Wunderbar::Asset.virtual,
scripts: Wunderbar::Asset.scripts.map {|script|
source = script.options[:file]
{
path: script.path,
source: source,
mtime: source && File.mtime(source),
size: source && File.size(source),
}
},
stylesheets: Wunderbar::Asset.stylesheets.map {|stylesheet|
source = stylesheet.options[:file]
{
path: stylesheet.path,
source: source,
mtime: source && File.mtime(source),
size: source && File.size(source),
}
},
}
JSON.pretty_generate(env: env, ENV: ENV.to_h, asset: asset)
end
not_found do
@errors = env
_html :not_found
end
error do
@errors = env
_html :errors
end