app-MAIL-temp/app/api/views/auth_login.py

129 lines
3.7 KiB
Python
Raw Normal View History

2020-01-20 14:36:39 +01:00
from flask import g
from flask import jsonify, request
from flask_cors import cross_origin
from itsdangerous import Signer
2020-02-27 16:57:24 +01:00
from app import email_utils
2020-01-20 14:36:39 +01:00
from app.api.base import api_bp, verify_api_key
2020-02-27 16:57:24 +01:00
from app.config import (
EMAIL_DOMAIN,
MAX_NB_EMAIL_FREE_PLAN,
FLASK_SECRET,
DISABLE_REGISTRATION,
)
from app.email_utils import can_be_used_as_personal_email, email_already_used
2020-01-20 14:36:39 +01:00
from app.extensions import db
from app.log import LOG
2020-02-27 16:57:24 +01:00
from app.models import GenEmail, AliasUsedOn, User, ApiKey, SocialAuth
2020-01-20 14:36:39 +01:00
from app.utils import convert_to_id
2020-02-27 16:57:24 +01:00
import facebook
2020-01-20 14:36:39 +01:00
@api_bp.route("/auth/login", methods=["POST"])
@cross_origin()
def auth_login():
"""
Authenticate user
Input:
email
password
device: to create an ApiKey associated with this device
Output:
200 and user info containing:
{
name: "John Wick",
mfa_enabled: true,
mfa_key: "a long string",
api_key: "a long string"
}
"""
data = request.get_json()
if not data:
return jsonify(error="request body cannot be empty"), 400
email = data.get("email")
password = data.get("password")
device = data.get("device")
user = User.filter_by(email=email).first()
if not user or not user.check_password(password):
return jsonify(error="Email or password incorrect"), 400
elif not user.activated:
return jsonify(error="Account not activated"), 400
2020-02-27 16:26:29 +01:00
return jsonify(**auth_payload(user, device)), 200
2020-02-27 16:57:24 +01:00
@api_bp.route("/auth/facebook", methods=["POST"])
@cross_origin()
def auth_facebook():
"""
Authenticate user with Facebook
Input:
facebook_token: facebook access token
device: to create an ApiKey associated with this device
Output:
200 and user info containing:
{
name: "John Wick",
mfa_enabled: true,
mfa_key: "a long string",
api_key: "a long string"
}
"""
data = request.get_json()
if not data:
return jsonify(error="request body cannot be empty"), 400
facebook_token = data.get("facebook_token")
device = data.get("device")
graph = facebook.GraphAPI(access_token=facebook_token)
user_info = graph.get_object("me", fields="email,name")
email = user_info.get("email")
user = User.get_by(email=email)
if not user:
if DISABLE_REGISTRATION:
return jsonify(error="registration is closed"), 400
if not can_be_used_as_personal_email(email) or email_already_used(email):
return jsonify(error=f"cannot use {email} as personal inbox"), 400
LOG.d("create facebook user with %s", user_info)
user = User.create(email=email.lower(), name=user_info["name"], activated=True)
db.session.commit()
email_utils.send_welcome_email(user)
if not SocialAuth.get_by(user_id=user.id, social="facebook"):
SocialAuth.create(user_id=user.id, social="facebook")
db.session.commit()
return jsonify(**auth_payload(user, device)), 200
2020-02-27 16:26:29 +01:00
def auth_payload(user, device) -> dict:
2020-01-20 14:36:39 +01:00
ret = {
"name": user.name,
"mfa_enabled": user.enable_otp,
}
# do not give api_key, user can only obtain api_key after OTP verification
if user.enable_otp:
s = Signer(FLASK_SECRET)
ret["mfa_key"] = s.sign(str(user.id))
ret["api_key"] = None
2020-01-20 14:36:39 +01:00
else:
2020-02-05 12:05:26 +01:00
api_key = ApiKey.get_by(user_id=user.id, name=device)
if not api_key:
LOG.d("create new api key for %s and %s", user, device)
api_key = ApiKey.create(user.id, device)
db.session.commit()
ret["mfa_key"] = None
2020-01-20 14:36:39 +01:00
ret["api_key"] = api_key.code
2020-02-27 16:26:29 +01:00
return ret