fixes for ekim's comments

pull/73/head^2
Christopher Usher 5 years ago
parent 689101b1ee
commit 86477fae13

@ -55,7 +55,7 @@ CREATE TABLE IF NOT EXISTS events (
error TEXT, error TEXT,
video_id TEXT, video_id TEXT,
video_link TEXT CHECK (state != 'DONE' OR video_link IS NOT NULL), video_link TEXT CHECK (state != 'DONE' OR video_link IS NOT NULL),
editor TEXT CHECK (state = 'UNEDITED' OR editor IS NOT NULL), editor TEXT,
edit_time TIMESTAMP CHECK (state = 'UNEDITED' OR editor IS NOT NULL), edit_time TIMESTAMP CHECK (state = 'UNEDITED' OR editor IS NOT NULL),
upload_time TIMESTAMP CHECK (state != 'DONE' OR upload_time IS NOT NULL) upload_time TIMESTAMP CHECK (state != 'DONE' OR upload_time IS NOT NULL)

@ -58,6 +58,8 @@
"http://wubloader.codegunner.com/" "http://wubloader.codegunner.com/"
], ],
authentication:: true, // set to false to disable auth in thrimshim
// Connection args for the database. // Connection args for the database.
// If database is defined in this config, host and port should be postgres:5432. // If database is defined in this config, host and port should be postgres:5432.
db_args:: { db_args:: {
@ -176,8 +178,7 @@
command: [ command: [
"--backdoor-port", std.toString($.backdoor_port), "--backdoor-port", std.toString($.backdoor_port),
$.db_connect, $.db_connect,
// "--no-authentication", //uncomment to run thrimshim without authentication ] + if $.authentication then [] else ["--no-authentication"],
],
// Mount the segments directory at /mnt // Mount the segments directory at /mnt
volumes: ["%s:/mnt" % $.segments_path], volumes: ["%s:/mnt" % $.segments_path],
// If the application crashes, restart it. // If the application crashes, restart it.

@ -16,8 +16,8 @@ from psycopg2 import sql
from common import database, PromLogCountsHandler, install_stacksampler from common import database, PromLogCountsHandler, install_stacksampler
from common.flask_stats import request_stats, after_request from common.flask_stats import request_stats, after_request
from google.oauth2 import id_token import google.oauth2.id_token
from google.auth.transport import requests import google.auth.transport.requests
psycopg2.extras.register_uuid() psycopg2.extras.register_uuid()
app = flask.Flask('thrimshim') app = flask.Flask('thrimshim')
@ -41,51 +41,48 @@ def cors(app):
def authenticate(f): def auth_wrapper(f):
"""Authenticate a token against the database. """Authenticate a token against the database.
Reference: https://developers.google.com/identity/sign-in/web/backend-auth""" Reference: https://developers.google.com/identity/sign-in/web/backend-auth"""
@wraps(f) @wraps(f)
def decorated_function(*args, **kwargs): def decorated_function(*args, **kwargs):
if flask.request.method == 'POST': if app.no_authentication:
if app.no_authentication: return f(*args, editor='NOT_AUTH', **kwargs)
return f(*args, editor='NOT_AUTH', **kwargs)
try:
userToken = flask.request.json['token'] userToken = flask.request.json['token']
# check whether token is valid except (KeyError, TypeError):
try: return 'User token required', 401
idinfo = id_token.verify_oauth2_token(userToken, requests.Request(), None) # check whether token is valid
if idinfo['iss'] not in ['accounts.google.com', 'https://accounts.google.com']: try:
raise ValueError('Wrong issuer.') idinfo = google.oauth2.id_token.verify_oauth2_token(userToken, google.auth.transport.requests.Request(), None)
except ValueError: if idinfo['iss'] not in ['accounts.google.com', 'https://accounts.google.com']:
return 'Invalid token. Access denied.', 403 raise ValueError('Wrong issuer.')
except ValueError:
# check whether user is in the database return 'Invalid token. Access denied.', 403
email = idinfo['email']
conn = app.db_manager.get_conn() # check whether user is in the database
results = database.query(conn, """ email = idinfo['email'].lower()
SELECT email conn = app.db_manager.get_conn()
FROM editors results = database.query(conn, """
WHERE email = %s""", email) SELECT email
row = results.fetchone() FROM editors
if row is None: WHERE lower(email) = %s""", email)
return 'Unknown user. Access denied.', 403 row = results.fetchone()
if row is None:
return f(*args, editor=email, **kwargs) return 'Unknown user. Access denied.', 403
return f(*args, editor=email, **kwargs)
else:
return f(*args, **kwargs)
return decorated_function return decorated_function
@app.route('/thrimshim/auth-test', methods=['GET', 'POST']) @app.route('/thrimshim/auth-test', methods=['POST'])
@request_stats @request_stats
@authenticate @auth_wrapper
def test(editor=None): def test(editor=None):
if flask.request.method == 'POST': return json.dumps(editor)
return json.dumps(editor)
else:
return "Hello World!"
@app.route('/metrics') @app.route('/metrics')
@request_stats @request_stats
@ -115,17 +112,9 @@ def get_all_rows():
logging.info('All rows fetched') logging.info('All rows fetched')
return json.dumps(rows) return json.dumps(rows)
@app.route('/thrimshim/<uuid:ident>', methods=['GET', 'POST'])
@app.route('/thrimshim/<uuid:ident>', methods=['GET'])
@request_stats @request_stats
@authenticate
def thrimshim(ident, editor=None):
"""Comunicate between Thrimbletrimmer and the Wubloader database."""
if flask.request.method == 'POST':
row = flask.request.json
return update_row(ident, row, editor)
else:
return get_row(ident)
def get_row(ident): def get_row(ident):
"""Gets the row from the database with id == ident.""" """Gets the row from the database with id == ident."""
conn = app.db_manager.get_conn() conn = app.db_manager.get_conn()
@ -149,7 +138,11 @@ def get_row(ident):
logging.info('Row {} fetched'.format(ident)) logging.info('Row {} fetched'.format(ident))
return json.dumps(response) return json.dumps(response)
def update_row(ident, new_row, editor): @app.route('/thrimshim/<uuid:ident>', methods=['POST'])
@request_stats
@auth_wrapper
def update_row(ident, editor=None):
new_row = flask.request.json
"""Updates row of database with id = ident with the edit columns in """Updates row of database with id = ident with the edit columns in
new_row.""" new_row."""
@ -226,11 +219,11 @@ def update_row(ident, new_row, editor):
@app.route('/thrimshim/manual-link/<uuid:ident>', methods=['POST']) @app.route('/thrimshim/manual-link/<uuid:ident>', methods=['POST'])
@request_stats @request_stats
@authenticate @auth_wrapper
def manual_link(ident, editor=None): def manual_link(ident, editor=None):
"""Manually set a video_link if the state is 'UNEDITED' or 'DONE' and the """Manually set a video_link if the state is 'UNEDITED' or 'DONE' and the
upload_location is 'manual'.""" upload_location is 'manual'."""
link = flask.request.json link = flask.request.json['link']
conn = app.db_manager.get_conn() conn = app.db_manager.get_conn()
results = database.query(conn, """ results = database.query(conn, """
SELECT id, state, upload_location SELECT id, state, upload_location
@ -245,7 +238,7 @@ def manual_link(ident, editor=None):
results = database.query(conn, """ results = database.query(conn, """
UPDATE events UPDATE events
SET state='DONE', upload_location = 'manual', video_link = %s, SET state='DONE', upload_location = 'manual', video_link = %s,
editor = %s, edit_time = %s, upload_time = %s editor = %s, edit_time = %s, upload_time = %s
WHERE id = %s AND (state = 'UNEDITED' OR (state = 'DONE' AND WHERE id = %s AND (state = 'UNEDITED' OR (state = 'DONE' AND
upload_location = 'manual'))""", link, editor, now, now, ident) upload_location = 'manual'))""", link, editor, now, now, ident)
logging.info("Row {} video_link set to {}".format(ident, link)) logging.info("Row {} video_link set to {}".format(ident, link))
@ -254,7 +247,7 @@ def manual_link(ident, editor=None):
@app.route('/thrimshim/reset/<uuid:ident>', methods=['POST']) @app.route('/thrimshim/reset/<uuid:ident>', methods=['POST'])
@request_stats @request_stats
@authenticate @auth_wrapper
def reset_row(ident, editor=None): def reset_row(ident, editor=None):
"""Clear state and video_link columns and reset state to 'UNEDITED'.""" """Clear state and video_link columns and reset state to 'UNEDITED'."""
conn = app.db_manager.get_conn() conn = app.db_manager.get_conn()

Loading…
Cancel
Save