Skip to content

Commit

Permalink
Merge pull request e-mission#801 from shankari/support_aggregate_call…
Browse files Browse the repository at this point in the history
…_auth

Support various auth policies for aggregate calls as well
  • Loading branch information
shankari authored Mar 17, 2021
2 parents 5ab4602 + 2889172 commit 0ea0e8f
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 13 deletions.
4 changes: 3 additions & 1 deletion conf/net/api/webserver.conf.sample
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
"port" : "8080",
"__comment": "1 hour = 60 min = 60 * 60 sec",
"timeout" : "3600",
"auth": "skip"
"auth": "skip",
"__comment": "Options are no_auth, user_only, never",
"aggregate_call_auth": "no_auth"
}
}
55 changes: 43 additions & 12 deletions emission/net/api/cfc_webapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
socket_timeout = config_data["server"]["timeout"]
log_base_dir = config_data["paths"]["log_base_dir"]
auth_method = config_data["server"]["auth"]
aggregate_call_auth = config_data["server"]["aggregate_call_auth"]

BaseRequest.MEMFILE_MAX = 1024 * 1024 * 1024 # Allow the request size to be 1G
# to accomodate large section sizes
Expand Down Expand Up @@ -132,12 +133,21 @@ def server_templates(filepath):
logging.debug("static filepath = %s" % filepath)
return static_file(filepath, "%s/%s" % (static_path, "templates"))

# Backward compat to handle older clients
# Remove in 2023 after everybody has upgraded
# We used to use the presence or absence of the "user" field
# to determine whether this was an aggregate call or not
# now we expect the client to fill it in
def _fill_aggregate_backward_compat(request):
if 'aggregate' not in request.json:
# Aggregate if there is no user
# no aggregate if there is a user
request.json["aggregate"] = ('user' not in request.json)

@post("/result/heatmap/pop.route/<time_type>")
def getPopRoute(time_type):
if 'user' in request.json:
user_uuid = getUUID(request)
else:
user_uuid = None
_fill_aggregate_backward_compat(request)
user_uuid = get_user_or_aggregate_auth(request)

if 'from_local_date' in request.json and 'to_local_date' in request.json:
start_time = request.json['from_local_date']
Expand All @@ -160,10 +170,8 @@ def getPopRoute(time_type):

@post("/result/heatmap/incidents/<time_type>")
def getStressMap(time_type):
if 'user' in request.json:
user_uuid = getUUID(request)
else:
user_uuid = None
_fill_aggregate_backward_compat(request)
user_uuid = get_user_or_aggregate_auth(request)

# modes = request.json['modes']
# hardcode modes to None because we currently don't store
Expand Down Expand Up @@ -330,10 +338,9 @@ def getUserProfile():

@post('/result/metrics/<time_type>')
def summarize_metrics(time_type):
if 'user' in request.json:
user_uuid = getUUID(request)
else:
user_uuid = None
_fill_aggregate_backward_compat(request)
user_uuid = get_user_or_aggregate_auth(request)

start_time = request.json['start_time']
end_time = request.json['end_time']
freq_name = request.json['freq']
Expand Down Expand Up @@ -465,6 +472,30 @@ def after_request():
# This should only be used by createUserProfile since we may not have a UUID
# yet. All others should use the UUID.

def _get_uuid_bool_wrapper(request):
try:
getUUID(request)
return True
except:
return False

def get_user_or_aggregate_auth(request):
# If this is not an aggregate call, returns the uuid
# If this is an aggregate call, returns None if the call is valid, otherwise aborts
# we only support aggregates on a subset of calls, so we don't need the
# `inHeader` parameter to `getUUID`
aggregate_call_map = {
"no_auth": lambda r: None,
"user_only": lambda r: None if _get_uuid_bool_wrapper(request) else abort(403, "aggregations only available to users"),
"never": lambda r: abort(404, "Aggregate calls not supported")
}
if request.json["aggregate"] == False:
logging.debug("User specific call, returning UUID")
return getUUID(request)
else:
logging.debug(f"Aggregate call, checking {aggregate_call_auth} policy")
return aggregate_call_map[aggregate_call_auth](request)

def getUUID(request, inHeader=False):
try:
retUUID = enaa.getUUID(request, auth_method, inHeader)
Expand Down

0 comments on commit 0ea0e8f

Please sign in to comment.