This repository has been archived by the owner on Jul 25, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
analytics.rb
140 lines (117 loc) · 3.88 KB
/
analytics.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
require 'cgi'
require 'hmac-sha1'
# Accept the API key through the query string or the x-apikey header
def api_key
params[:apikey] || request.env['HTTP_X_APIKEY']
end
before do
# verify signature and parameters
if request.path_info =~ /^\/analytics\//
unless SunlightServices.verify params, config[:services][:shared_secret], config[:services][:api_name]
halt 403, 'Bad signature'
end
else
# Require an API key
unless ApiKey.allowed? api_key
halt 403, 'API key required, you can obtain one from http://services.sunlightlabs.com/accounts/register/'
end
# pre-processing on params
params[:sections] = (params[:sections] || '').split ','
end
end
after do
if request.path_info =~ /^\/api\//
# log hits
if params[:captures]
Hit.create(
:sections => params[:sections],
:method => params[:captures][0],
:format => params[:captures][1],
:key => api_key,
:query_string => request.query_string,
:user_agent => request.env['HTTP_USER_AGENT'],
:ip_address => request.env['REMOTE_ADDR'],
:query_hash => request.env['rack.request.query_hash']
)
end
end
end
post '/analytics/create_key/' do
begin
ApiKey.create! :key => params[:key],
:email => params[:email],
:status => params[:status]
rescue
halt 403, "Could not create key, duplicate key or email"
end
end
post '/analytics/update_key/' do
if key = ApiKey.first(:conditions => {:key => params[:key]})
begin
key.update_attributes! :email => params[:email], :status => params[:status]
rescue
halt 403, "Could not update key, errors: #{key.errors.full_messages.join ', '}"
end
else
halt 404, 'Could not locate api key by the given key'
end
end
post '/analytics/update_key_by_email/' do
if key = ApiKey.first(:conditions => {:email => params[:email]})
begin
key.update_attributes! :key => params[:key], :status => params[:status]
rescue
halt 403, "Could not update key, errors: #{key.errors.full_messages.join ', '}"
end
else
halt 404, 'Could not locate api key by the given email'
end
end
class SunlightServices
def self.report(key, endpoint, calls, date, api, shared_secret)
url = URI.parse "http://services.sunlightlabs.com/analytics/report_calls/"
params = {:key => key, :endpoint => endpoint, :date => date, :api => api, :calls => calls}
signature = signature_for params, shared_secret
Net::HTTP.post_form url, params.merge(:signature => signature)
end
def self.verify(params, shared_secret, api_name)
return false unless params[:key] and params[:email] and params[:status]
return false unless params[:api] == api_name
given_signature = params.delete 'signature'
signature = signature_for params, shared_secret
signature == given_signature
end
def self.signature_for(params, shared_secret)
HMAC::SHA1.hexdigest shared_secret, signature_string(params)
end
def self.signature_string(params)
params.keys.map(&:to_s).sort.map do |key|
"#{key}=#{CGI.escape((params[key] || params[key.to_sym]).to_s)}"
end.join '&'
end
end
class ApiKey
include MongoMapper::Document
key :key, String, :required => true, :unique => true, :index => true
key :email, String, :required => true, :unique => true, :index => true
key :status, String, :required => true, :index => true
timestamps!
def self.allowed?(key)
ApiKey.exists? :key => key, :status => 'A'
end
end
class Hit
include MongoMapper::Document
timestamps!
ensure_index :created_at
ensure_index :method
ensure_index :key
ensure_index :sections
ensure_index :format
ensure_index :user_agent
ensure_index :ip_address
ensure_index "query_hash.bill_id"
ensure_index "query_hash.roll_id"
ensure_index "query_hash.bioguide_id"
ensure_index "query_hash.govtrack_id"
end