etiquette/frontends/etiquette_flask/backend/endpoints/user_endpoints.py
Ethan Dalool 838982b6c3 Let login take username.
This cuts back on unnecessary sql selects.
2020-09-17 21:02:55 -07:00

116 lines
4.1 KiB
Python

import flask; from flask import request
import etiquette
from .. import common
from .. import decorators
from .. import jsonify
from .. import sessions
site = common.site
session_manager = common.session_manager
# Individual users #################################################################################
@site.route('/user/<username>')
def get_user_html(username):
user = common.P_user(username, response_type='html')
return common.render_template(request, 'user.html', user=user)
@site.route('/user/<username>.json')
def get_user_json(username):
user = common.P_user(username, response_type='json')
user = etiquette.jsonify.user(user)
return jsonify.make_json_response(user)
@site.route('/userid/<user_id>')
@site.route('/userid/<user_id>.json')
def get_user_id_redirect(user_id):
if request.url.endswith('.json'):
user = common.P_user_id(user_id, response_type='json')
else:
user = common.P_user_id(user_id, response_type='html')
url_from = '/userid/' + user_id
url_to = '/user/' + user.username
url = request.url.replace(url_from, url_to)
return flask.redirect(url)
# Login and logout #################################################################################
@site.route('/login', methods=['GET'])
def get_login():
response = common.render_template(
request,
'login.html',
min_username_length=common.P.config['user']['min_username_length'],
min_password_length=common.P.config['user']['min_password_length'],
)
return response
@site.route('/login', methods=['POST'])
@decorators.required_fields(['username', 'password'])
def post_login():
session = session_manager.get(request)
if session.user:
exc = etiquette.exceptions.AlreadySignedIn()
response = etiquette.jsonify.exception(exc)
return jsonify.make_json_response(response, status=403)
username = request.form['username']
password = request.form['password']
try:
# Consideration: Should the server hash the password to discourage
# information (user exists) leak via response time?
# Currently I think not, because they can check if the account
# page 404s anyway.
user = common.P.login(username=username, password=password)
except (etiquette.exceptions.NoSuchUser, etiquette.exceptions.WrongLogin):
exc = etiquette.exceptions.WrongLogin()
response = etiquette.jsonify.exception(exc)
return jsonify.make_json_response(response, status=422)
except etiquette.exceptions.FeatureDisabled as exc:
response = etiquette.jsonify.exception(exc)
return jsonify.make_json_response(response, status=400)
session = sessions.Session(request, user)
session_manager.add(session)
return jsonify.make_json_response({})
@site.route('/logout', methods=['POST'])
def logout():
session_manager.remove(request)
response = jsonify.make_json_response({})
return response
# User registration ################################################################################
@site.route('/register', methods=['GET'])
def get_register():
return flask.redirect('/login')
@site.route('/register', methods=['POST'])
@decorators.required_fields(['username', 'password_1', 'password_2'])
def post_register():
session = session_manager.get(request)
if session.user:
exc = etiquette.exceptions.AlreadySignedIn()
response = etiquette.jsonify.exception(exc)
return jsonify.make_json_response(response, status=403)
username = request.form['username']
display_name = request.form.get('display_name', None)
password_1 = request.form['password_1']
password_2 = request.form['password_2']
if password_1 != password_2:
response = {
'error_type': 'PASSWORDS_DONT_MATCH',
'error_message': 'Passwords do not match.',
}
return jsonify.make_json_response(response, status=422)
user = common.P.new_user(username, password_1, display_name=display_name, commit=True)
session = sessions.Session(request, user)
session_manager.add(session)
return jsonify.make_json_response({})