103 lines
3.8 KiB
Python
103 lines
3.8 KiB
Python
import json
|
|
|
|
from flask import request, redirect, render_template, g, abort, make_response, flash, jsonify, session
|
|
|
|
from roc_fnb.util import log, base64_encode, base64_decode
|
|
from roc_fnb.website.server.decorators import require_user, logger_request_bindings
|
|
from roc_fnb.website.database import InvitationClaimed, InvitationNotFound
|
|
from roc_fnb.website.models.user import User
|
|
|
|
|
|
def setup_user_routes(app, db):
|
|
@app.post('/login')
|
|
@logger_request_bindings(log)
|
|
def submit_login(log):
|
|
form = request.json
|
|
log.info('user attempting login', name=form.get('name'))
|
|
user = db.get_user_by_name(form['name'])
|
|
if not user.check_password(form['password']):
|
|
log.warn('incorrect password submitted', name=form['name'])
|
|
abort(401) # unauthorized
|
|
session['user'] = json.dumps(user.public_fields)
|
|
return jsonify(status='OK')
|
|
|
|
@app.get('/login')
|
|
def render_login_page():
|
|
if getattr(g, 'user', None):
|
|
log.debug('user is already logged in', user=g.user)
|
|
return redirect('/me')
|
|
return render_template('login.html')
|
|
|
|
@app.get('/me')
|
|
@require_user()
|
|
def get_profile():
|
|
return render_template('profile.html', user=g.user)
|
|
|
|
@app.get('/invite')
|
|
@require_user(admin=True)
|
|
def create_invite():
|
|
"""
|
|
Two handlers in one: JSON and HTML.
|
|
|
|
First, a user-agent (browser) makes a request for /invite, and gets the
|
|
rendered HTML page. Then they click a button which sends a request
|
|
specifically asking for a JSON reply. The invitation is created and
|
|
returned in a JSON document.
|
|
|
|
This allows a user to generate more than one invitation code per visit
|
|
to the page and avoids accidentally creating an invite code on page load.
|
|
"""
|
|
if request.headers['Accept'] == 'application/json':
|
|
invite = base64_encode(db.invite_new_user(g.user))
|
|
log.info('new invitation created', inviter=g.user, invitation_code=invite)
|
|
return jsonify(invite=invite, status='OK')
|
|
return render_template(
|
|
'new_invite.html', user=g.user, app_hostname=g.app_hostname
|
|
)
|
|
|
|
@app.post('/new-user')
|
|
def create_new_user():
|
|
decoded_invite_code = base64_decode(request.json['invite_code'])
|
|
invitee = User.create(
|
|
request.json['email'], request.json['name'],
|
|
request.json['password']
|
|
)
|
|
try:
|
|
db.store_new_invitee(decoded_invite_code, invitee)
|
|
log.info('new user created', user=invitee, invite_code=request.json['invite_code'])
|
|
except InvitationClaimed as err:
|
|
response = make_response(
|
|
json.dumps(
|
|
{
|
|
'type':
|
|
'InvitationClaimed',
|
|
'invite_code':
|
|
base64_encode(err.invitation['invite_code']),
|
|
'message':
|
|
str(err)
|
|
}
|
|
)
|
|
)
|
|
response.headers['Content-Type'] = 'application/json'
|
|
response.status_code = 401
|
|
abort(response)
|
|
except InvitationNotFound as err:
|
|
r = make_response(
|
|
json.dumps(
|
|
{
|
|
'type': 'InvitationNotFound',
|
|
'invite_code': err.invitation_code,
|
|
'message': str(err)
|
|
}
|
|
)
|
|
)
|
|
response.headers['Content-Type'] = 'application/json'
|
|
response.status_code = 404
|
|
abort(response)
|
|
session['user'] = json.dumps(invitee.public_fields)
|
|
return jsonify(status='OK')
|
|
|
|
@app.get('/new-user')
|
|
def render_signup_page():
|
|
return render_template('sign-up.html')
|