2020-05-21 11:20:27 +00:00
|
|
|
import flask
|
|
|
|
from flask import Blueprint, redirect, request
|
|
|
|
from flask import current_app, session
|
|
|
|
from flask import jsonify
|
|
|
|
from flask.helpers import make_response
|
|
|
|
from flask.templating import render_template
|
2022-02-19 22:16:13 +00:00
|
|
|
from flask.typing import ResponseReturnValue
|
2020-05-21 11:20:27 +00:00
|
|
|
|
|
|
|
from flask import Blueprint, render_template, request, url_for
|
2022-07-15 08:53:06 +00:00
|
|
|
from datetime import datetime
|
|
|
|
from typing import Optional, Any
|
2020-05-21 11:20:27 +00:00
|
|
|
import logging
|
2022-04-08 19:29:23 +00:00
|
|
|
import httpx
|
2022-07-15 08:53:06 +00:00
|
|
|
import secrets
|
2020-05-21 11:20:27 +00:00
|
|
|
|
2022-07-15 08:53:06 +00:00
|
|
|
from ..model import db, User
|
2022-02-19 22:16:13 +00:00
|
|
|
from ..hydra import hydra_service
|
2022-07-15 08:53:06 +00:00
|
|
|
from ..lenticular_services import lenticular_services
|
2022-02-19 22:16:13 +00:00
|
|
|
from ory_hydra_client.api.admin import introspect_o_auth_2_token
|
|
|
|
from ory_hydra_client.models import GenericError
|
2020-05-21 11:20:27 +00:00
|
|
|
|
|
|
|
|
|
|
|
api_views = Blueprint('api', __name__, url_prefix='/api')
|
|
|
|
|
2022-04-08 19:29:23 +00:00
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
2020-05-21 11:20:27 +00:00
|
|
|
|
|
|
|
@api_views.route('/users', methods=['GET'])
|
2022-02-19 22:16:13 +00:00
|
|
|
def user_list() -> ResponseReturnValue:
|
2022-04-08 19:29:23 +00:00
|
|
|
# if 'authorization' not in request.headers:
|
|
|
|
# return '', 403
|
|
|
|
# token = request.headers['authorization'].replace('Bearer ', '')
|
|
|
|
# token_info = introspect_o_auth_2_token.sync(_client=hydra_service.hydra_client)
|
2020-05-21 11:20:27 +00:00
|
|
|
|
2022-04-08 19:29:23 +00:00
|
|
|
# if token_info is None or isinstance(token_info, GenericError):
|
|
|
|
# return 'internal errror', 500
|
2022-02-19 22:16:13 +00:00
|
|
|
|
2022-04-08 19:29:23 +00:00
|
|
|
# if not isinstance(token_info.scope, str) or 'lc_i_userlist' not in token_info.scope.split(' '):
|
|
|
|
# return '', 403
|
2020-05-21 11:20:27 +00:00
|
|
|
|
2020-05-27 15:56:10 +00:00
|
|
|
return jsonify([
|
|
|
|
{'username': str(user.username), 'email': str(user.email)}
|
2022-06-18 17:35:05 +00:00
|
|
|
for user in User.query.all()])
|
2022-04-08 19:29:23 +00:00
|
|
|
|
|
|
|
@api_views.route('/introspect', methods=['POST'])
|
|
|
|
def introspect() -> ResponseReturnValue:
|
2022-07-15 08:53:06 +00:00
|
|
|
token = request.form['token'] # type: Optional[str]
|
2022-04-08 19:29:23 +00:00
|
|
|
resp = httpx.post("https://hydra.cloud.tux.ac/oauth2/introspect", data={'token':token})
|
|
|
|
if resp.status_code != 200:
|
|
|
|
return jsonify({}), 500
|
|
|
|
token_info = resp.json()
|
|
|
|
|
|
|
|
if not token_info['active']:
|
|
|
|
return jsonify({'active': False})
|
|
|
|
token_info['email'] = token_info['ext']['email']
|
|
|
|
|
|
|
|
|
|
|
|
return jsonify(token_info)
|
|
|
|
|
2022-05-27 10:35:28 +00:00
|
|
|
|
2022-07-15 08:53:06 +00:00
|
|
|
@api_views.route('/login/<service_name>', methods=['POST'])
|
|
|
|
def email_login(service_name: str) -> ResponseReturnValue:
|
|
|
|
if service_name not in lenticular_services:
|
|
|
|
return '', 404
|
|
|
|
service = lenticular_services[service_name]
|
|
|
|
|
2022-05-27 10:35:28 +00:00
|
|
|
if not request.is_json:
|
2022-06-17 11:38:49 +00:00
|
|
|
return jsonify({}), 400
|
2022-07-15 08:53:06 +00:00
|
|
|
req_payload = request.get_json() # type: Any
|
|
|
|
|
2022-06-18 11:05:18 +00:00
|
|
|
if not isinstance(req_payload, dict):
|
|
|
|
return 'bad request', 400
|
2022-07-15 08:53:06 +00:00
|
|
|
|
2022-05-27 10:35:28 +00:00
|
|
|
password = req_payload["password"]
|
|
|
|
username = req_payload["username"]
|
|
|
|
|
2022-07-15 08:53:06 +00:00
|
|
|
if '@' in username:
|
|
|
|
username = username.split('@')[0]
|
|
|
|
|
|
|
|
user = User.query.filter_by(username=username.lower()).first() # type: Optional[User]
|
|
|
|
if user is None:
|
|
|
|
logger.warning(f'login with invalid username')
|
|
|
|
return jsonify({}), 403
|
|
|
|
|
|
|
|
for app_token in user.get_tokens_by_service(service):
|
|
|
|
if secrets.compare_digest(password, app_token.token):
|
|
|
|
app_token.last_used = datetime.now()
|
|
|
|
db.session.commit()
|
|
|
|
return jsonify({'username': user.username}), 200
|
2022-05-27 10:35:28 +00:00
|
|
|
|
2022-07-15 08:53:06 +00:00
|
|
|
logger.warning(f'login with invalid password for {username}')
|
2022-05-27 10:35:28 +00:00
|
|
|
return jsonify({}), 403
|
|
|
|
|