Skip to content

Commit

Permalink
Use session identifiers instead of IPs
Browse files Browse the repository at this point in the history
IP addresses are private information and not allowed to be be collected
under GDPR. Plus, schools with proxy servers would all show as the same
user which is undesirable.

Instead, generate a per-session identifier for each user and store that.
  • Loading branch information
rix0rrr committed Mar 15, 2020
1 parent cd526e1 commit 1f1e3ae
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 11 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,4 @@ logs.txt

#macos things
.DS_Store
.jsonbin.*
32 changes: 23 additions & 9 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
from datetime import datetime
from functools import wraps
import hedy
import json
import os
import requests
from flask import request
from datetime import datetime
import jsonbin
import logging
import os
import requests
import uuid

# app.py
from flask import Flask, request, jsonify, render_template
from flask import Flask, request, jsonify, render_template, session
from flask_compress import Compress

logging.basicConfig(
level=logging.DEBUG,
format='[%(asctime)s] %(levelname)-8s: %(message)s')

app = Flask(__name__, static_url_path='')

# Unique random key for sessions
app.config['SECRET_KEY'] = uuid.uuid4().hex

Compress(app)
logger = jsonbin.JsonBinLogger.from_env_vars()

Expand All @@ -41,7 +46,7 @@ def parse():
code = request.args.get("code", None)
level = request.args.get("level", None)

log_to_jsonbin(code, level)
log_to_jsonbin(session_id(), code, level)

# For debugging
print(f"got code {code}")
Expand All @@ -67,10 +72,10 @@ def parse():
return jsonify(response)


def log_to_jsonbin(code, level):
def log_to_jsonbin(session_id, code, level):
# log all info to jsonbin
data = {
'ip': request.remote_addr,
'session': session_id,
'date': str(datetime.now()),
'level': level,
'code': code
Expand All @@ -84,6 +89,8 @@ def log_to_jsonbin(code, level):
@app.route('/index.html', methods=['GET'])
@app.route('/', methods=['GET'])
def index():
session_id() # Run this for the side effect of generating a session ID

level = request.args.get("level", 1)
level = int(level)
lang = requested_lang()
Expand Down Expand Up @@ -135,7 +142,14 @@ def error():
def internal_error(exception):
import traceback
print(traceback.format_exc())
return "500 error caught"
return "<h1>500 Internal Server Error</h1>"


def session_id():
"""Returns or sets the current session ID."""
if 'session_id' not in session:
session['session_id'] = uuid.uuid4().hex
return session['session_id']


def requested_lang():
Expand Down
52 changes: 52 additions & 0 deletions fetch_jsonbin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import requests
import os
import sys
import json

def main():
"""Fetch and print the contents of the logging collection in jsonbin.io
FIXME: This could/should be doing queries, but for now we just list everything.
"""
key = os.getenv('JSONBIN_SECRET_KEY')
collection = os.getenv('JSONBIN_COLLECTION_ID')

if key is None or collection is None:
raise RuntimeError('Set JSONBIN_SECRET_KEY and JSONBIN_COLLECTION_ID if you want to log (disabled for now)')

progress = sys.stderr

headers = {'secret-key': key}

progress.write('Listing collection... (this may take a while)\n')
list_response = requests.get(jb_url(f'/e/collection/{collection}/all-bins'), headers=headers)
listing = json.loads(list_response.text)
if not listing['success']:
raise RuntimeError('Server error: ' + listing['message'])

bins = []

progress.write(f'{len(listing["records"])} bins found\n')

for record in listing['records']:
progress.write('.')
progress.flush()
bin = json.loads(requests.get(jb_url(f'/b/' + record['id']), headers=headers).text)
bins.append(bin)
progress.write('\n')
progress.flush()

# Sort by sessions and date
bins.sort(key=lambda b: (b.get('session', ''), b.get('date', '')))

# Print all
for bin in bins:
print(json.dumps(bin))


def jb_url(url):
return 'https://api.jsonbin.io' + url


if __name__ == '__main__':
main()
16 changes: 14 additions & 2 deletions jsonbin.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import threading
import os
import json
import queue
import requests
import logging
Expand Down Expand Up @@ -48,12 +49,23 @@ def _run(self):
obj = self.queue.get()

try:
requests.post('https://api.jsonbin.io/b', json=obj, headers={
response = requests.post('https://api.jsonbin.io/b', json=obj, headers={
'Content-Type': 'application/json',
'secret-key': self.secret_key,
'collection-id': self.collection_id,
})
logger.info('Posted to jsonbin.')

# Try to read the response as JSON
try:
resp = json.loads(response.text)

if resp['success']:
logger.info('Posted to jsonbin')
else:
logger.warning('Posting to jsonbin failed: ' + resp['message'])
except Exception as e:
# Not JSON or no success field
logger.warning(f'Posting to jsonbin failed: {response.text}')
except Exception as e:
logger.exception(f'Error posting to jsonbin.')

Expand Down

0 comments on commit 1f1e3ae

Please sign in to comment.