Skip to content

Commit 413e06b

Browse files
author
Jay Martin
committed
Merge commit '69f5ca907b16806533663f3f95cecaec0af46caf'
# By Jessica B. Hamrick # Via Jessica B. Hamrick * commit '69f5ca907b16806533663f3f95cecaec0af46caf': Add dashboard parameters to enable dashboard authentication
2 parents 6f08354 + 69f5ca9 commit 413e06b

File tree

2 files changed

+67
-2
lines changed

2 files changed

+67
-2
lines changed

psiturk/dashboard_server.py

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import experiment_server_controller as control
99
from amt_services import MTurkServices
1010
from db import db_session
11+
from functools import wraps
1112

1213
config = PsiturkConfig()
1314

@@ -17,6 +18,45 @@
1718
template_folder=os.path.join(os.path.dirname(__file__), "templates_dashboard"),
1819
static_folder=os.path.join(os.path.dirname(__file__), "static_dashboard"))
1920

21+
22+
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
23+
# Authentication functions
24+
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
25+
26+
def check_auth(username, password):
27+
"""This function is called to check if a username /
28+
password combination is valid.
29+
"""
30+
true_user = config.get('Dashboard Parameters', 'login_username')
31+
true_pass = config.get('Dashboard Parameters', 'login_pw')
32+
return username == true_user and password == true_pass
33+
34+
35+
def authenticate():
36+
"""Sends a 401 response that enables basic auth"""
37+
return Response(
38+
'Could not verify your access level for that URL.\n'
39+
'You have to login with proper credentials', 401,
40+
{'WWW-Authenticate': 'Basic realm="Login Required"'})
41+
42+
43+
def requires_auth(f):
44+
@wraps(f)
45+
def decorated(*args, **kwargs):
46+
auth = request.authorization
47+
if not auth or not check_auth(auth.username, auth.password):
48+
return authenticate()
49+
return f(*args, **kwargs)
50+
51+
# don't require authorization if there is no username or password
52+
# defined
53+
true_user = config.get('Dashboard Parameters', 'login_username')
54+
true_pass = config.get('Dashboard Parameters', 'login_pw')
55+
if true_user == '' or true_pass == '':
56+
return f
57+
else:
58+
return decorated
59+
2060
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2161
# Some supporting classes needed by the dashboard_server
2262
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -42,13 +82,15 @@ def __str__(self):
4282
# Routes for handling dashboard interactivity
4383
#----------------------------------------------
4484
@app.route('/dashboard', methods=['GET'])
85+
@requires_auth
4586
def dashboard():
4687
"""
4788
Serves dashboard.
4889
"""
4990
return render_template('dashboard.html')
5091

5192
@app.route('/dashboard_model', methods=['GET', 'POST'])
93+
@requires_auth
5294
def dashboard_model():
5395
"""
5496
Sync for dashboard model.
@@ -68,6 +110,7 @@ def dashboard_model():
68110
return render_template('dashboard.html')
69111

70112
@app.route('/at_a_glance_model', methods=['GET'])
113+
@requires_auth
71114
def at_a_glance_model():
72115
"""
73116
Sync for dashboard at-a-glance pane.
@@ -82,6 +125,7 @@ def at_a_glance_model():
82125
return jsonify(error="unable to access aws")
83126

84127
@app.route('/verify_aws_login', methods=['POST'])
128+
@requires_auth
85129
def verify_aws():
86130
"""
87131
Verifies current aws login keys are valid
@@ -93,6 +137,7 @@ def verify_aws():
93137
return jsonify(aws_accnt=is_valid)
94138

95139
@app.route('/mturk_services', methods=['POST'])
140+
@requires_auth
96141
def turk_services():
97142
"""
98143
"""
@@ -115,6 +160,7 @@ def turk_services():
115160
return jsonify(error="psiTurk failed to recognize your request.")
116161

117162
@app.route('/get_log', methods=['POST'])
163+
@requires_auth
118164
def get_log():
119165
"""
120166
provides an jsonified interface to the log file in the dashbaord
@@ -124,6 +170,7 @@ def get_log():
124170
return jsonify(error="did not specify the log level correctly")
125171

126172
@app.route('/get_hits', methods=['GET'])
173+
@requires_auth
127174
def get_hits():
128175
"""
129176
provides an jsonified collection of active hits
@@ -132,6 +179,7 @@ def get_hits():
132179
return jsonify(hits=services.get_active_hits())
133180

134181
@app.route('/get_workers', methods=['GET'])
182+
@requires_auth
135183
def get_workers():
136184
"""
137185
provides an jsonified collection of workers pending review
@@ -140,6 +188,7 @@ def get_workers():
140188
return jsonify(workers=services.get_workers())
141189

142190
@app.route('/reject_worker', methods=['POST'])
191+
@requires_auth
143192
def reject_worker():
144193
if "assignmentId" in request.json:
145194
services = MTurkServices(config)
@@ -148,6 +197,7 @@ def reject_worker():
148197
return("Error: Missing assignment id")
149198

150199
@app.route('/approve_worker', methods=['POST'])
200+
@requires_auth
151201
def approve_worker():
152202
CREDITED = 5
153203
if "assignmentId" in request.json:
@@ -166,6 +216,7 @@ def approve_worker():
166216
return("Error: Missing assignment id")
167217

168218
@app.route('/is_port_available', methods=['POST'])
219+
@requires_auth
169220
def is_port_available_route():
170221
"""
171222
Check if port is available on localhost
@@ -180,6 +231,7 @@ def is_port_available_route():
180231
return "port check"
181232

182233
@app.route('/is_internet_available', methods=['GET'])
234+
@requires_auth
183235
def is_internet_on():
184236
try:
185237
response=urllib2.urlopen('http://www.google.com', timeout=1)
@@ -188,17 +240,20 @@ def is_internet_on():
188240
return "false"
189241

190242
@app.route("/server_status", methods=["GET"])
243+
@requires_auth
191244
def status():
192245
return(jsonify(state=server_controller.is_port_available()))
193246

194247
# this function appears unimplemented in the dashboard currently
195248
# @app.route("/participant_status", methods=["GET"])
249+
# @requires_auth
196250
# def participant_status():
197251
# database = Dashboard.Database()
198252
# status = database.get_participant_status()
199253
# return status
200254

201255
@app.route("/favicon.ico")
256+
@requires_auth
202257
def favicon():
203258
"""
204259
Serving a favicon
@@ -207,6 +262,7 @@ def favicon():
207262
return app.send_static_file('favicon.ico')
208263

209264
@app.route("/data/<filename>", methods=["GET"])
265+
@requires_auth
210266
def download_datafile(filename):
211267
if filename[-4:] != ".csv":
212268
raise Exception("/data received Invalid filename: %s" % filename)
@@ -231,6 +287,7 @@ def download_datafile(filename):
231287
return response
232288

233289
@app.route("/launch_log", methods=["GET"])
290+
@requires_auth
234291
def launch_log():
235292
logfilename = config.get('Server Parameters', 'logfile')
236293
if sys.platform == "darwin":
@@ -245,18 +302,21 @@ def launch_log():
245302
# routes for interfacing with ExperimentServerController
246303
#----------------------------------------------
247304
@app.route("/launch", methods=["GET"])
305+
@requires_auth
248306
def launch_experiment_server():
249307
server_controller.startup()
250308
return "Experiment Server launching..."
251309

252310
@app.route("/shutdown_dashboard", methods=["GET"])
311+
@requires_auth
253312
def shutdown_dashboard():
254313
print("Attempting to shut down.")
255314
#server_controller.shutdown() # Must do this; otherwise zombie server remains on dashboard port; not sure why
256315
request.environ.get('werkzeug.server.shutdown')()
257316
return("shutting down dashboard server...")
258317

259318
@app.route("/shutdown_psiturk", methods=["GET"]) ## TODO: Kill psiturk reference
319+
@requires_auth
260320
def shutdown_experiment_server():
261321
server_controller.shutdown()
262322
return("shutting down Experiment Server...")
@@ -289,6 +349,6 @@ def launch():
289349
port = config.getint('Server Parameters', 'port')
290350
print "Serving on ", "http://" + dashboard_ip + ":" + str(dashboard_port)
291351
app.run(debug=True, use_reloader=False, port=dashboard_port, host=dashboard_ip)
292-
352+
293353
if __name__ == "__main__":
294354
launch()

psiturk/psiturk_config.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ def set_serialized(self, config_model):
4545

4646
def write_default_config(self):
4747
sections = ['AWS Access', 'HIT Configuration', 'Database Parameters',
48-
'Server Parameters', 'Task Parameters']
48+
'Server Parameters', 'Task Parameters',
49+
'Dashboard Parameters']
4950
map(self.add_section, sections)
5051
# AWS Access Section
5152
self.set('AWS Access', 'aws_access_key_id', 'YourAccessKeyId')
@@ -84,3 +85,7 @@ def write_default_config(self):
8485
self.set('Task Parameters', 'num_conds', '1')
8586
self.set('Task Parameters', 'num_counters', '1')
8687
self.set('Task Parameters', 'use_debriefing', 'true')
88+
89+
# Dashboard Parameters
90+
self.set('Dashboard Parameters', 'login_username', '')
91+
self.set('Dashboard Parameters', 'login_pw', '')

0 commit comments

Comments
 (0)