changeset 3:b42c4bfe57c7

server: Use a "preamble" object in the POST to auth.
author Paul Fisher <paul@pfish.zone>
date Sun, 29 Sep 2019 11:52:48 -0400
parents cda47993a193
children e7c8dcc5fc15
files weather_server/server.py
diffstat 1 files changed, 18 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/weather_server/server.py	Sun Sep 29 01:18:18 2019 -0400
+++ b/weather_server/server.py	Sun Sep 29 11:52:48 2019 -0400
@@ -1,5 +1,6 @@
 import bson
 import flask
+import hmac
 
 from . import common
 from . import locations
@@ -21,28 +22,25 @@
     @app.route('/_submit', methods=['POST'])
     def submit():
         req = flask.request
-        target = req.args.get('location')
-        if not target:
-            flask.abort(404)
-        try:
-            target_loc, logger = locs.get(target)
-        except KeyError:
-            flask.abort(404)
-
-        password = req.args.get('password')
-        if password != target_loc.password:
-            flask.abort(401)
-
         reader = bson.decode_file_iter(
             req.stream, codec_options=common.BSON_OPTIONS)
-        entries = [
-            types.Reading.from_now(
-                sample_time=item['sample_time'],
-                temp_c=item['temp_c'],
-                rh_pct=item['rh_pct'],
-            )
-            for item in reader
-        ]
+        try:
+            preamble = next(reader)
+            loc_name = preamble['location']
+            password = str(preamble['password'])
+            loc, logger = locs.get(loc_name)
+            if not hmac.compare_digest(password, loc.password):
+                flask.abort(400)
+            entries = [
+                types.Reading.from_now(
+                    sample_time=item['sample_time'],
+                    temp_c=item['temp_c'],
+                    rh_pct=item['rh_pct'],
+                )
+                for item in reader
+            ]
+        except (KeyError, bson.InvalidBSON):
+            flask.abort(400)
         logger.write_rows(entries)
         return flask.jsonify({'status': 'OK'})