profile and other stuff

This commit is contained in:
2019-08-14 16:38:03 +02:00
parent 859a5d880a
commit 9ab0d43f43
16 changed files with 297 additions and 624 deletions

View File

@@ -45,6 +45,13 @@ api_v1.add_namespace(api_cron_job)
api_v1.add_namespace(api_control)
auth_api_bp = Blueprint('auth_api', __name__, url_prefix='/api/auth')
auth_api_v1 = Api(auth_api_bp, prefix="/v1", version='0.1', title='Auth API',
description='Auth API', doc='/v1/doc/', authorizations=api_authorizations, security='bearerAuth')
auth_api_providers_ns = Namespace('providers')
auth_api_register_ns = Namespace('register')
auth_api_v1.add_namespace(auth_api_providers_ns)
auth_api_v1.add_namespace(auth_api_register_ns)
# user_api_bp = Blueprint('user_api', __name__, url_prefix='/api/user')
# group_api_bp = Blueprint('group_api', __name__, url_prefix='/api/group')

View File

@@ -7,23 +7,27 @@ Login through API does not start a new session, but instead returns JWT.
"""
import base64
import json
from pprint import pprint
import flask
from datetime import datetime, timedelta
import jwt
from flask import request, jsonify, current_app, url_for, Response, session, redirect, make_response
from flask_jwt_extended import create_access_token, create_refresh_token, jwt_refresh_token_required, get_jwt_identity
from flask_jwt_extended import create_access_token, create_refresh_token, jwt_refresh_token_required, get_jwt_identity, \
get_raw_jwt, jwt_required
from functools import wraps
from random import randint
from flask_login import logout_user, login_user
from typing import Iterable
from flask_restplus import Resource, fields
from werkzeug.routing import BuildError
from backend import db, app
from backend.api import auth_api_bp
from backend import db, app, jwt_extended
from backend.api import auth_api_bp, auth_api_providers_ns, auth_api_register_ns
from backend.auth import AUTH_PROVIDERS, oidc_auth
from backend.models.user_model import User, Group
from backend.models.user_model import User, Group, BlacklistToken
@auth_api_bp.route('/providers', methods=('GET',))
@@ -39,6 +43,12 @@ def get_auth_providers():
return jsonify(providers)
@auth_api_providers_ns.route('/')
class AuthProviders(Resource):
def get(self):
return get_auth_providers()
@auth_api_bp.route('/register', methods=('POST',))
def register():
data = request.get_json()
@@ -48,6 +58,21 @@ def register():
return jsonify(user.to_dict()), 201
@auth_api_register_ns.route('/')
@auth_api_register_ns.expect(auth_api_register_ns.model('RegisterModel', {
'nickname': fields.String(required=False, description='The user\'s nickname'),
'first_name': fields.String(required=False, description='The user\'s first name'),
'last_name': fields.String(required=False, description='The user\'s last name'),
'lang': fields.String(required=False, description='The user\'s preferred language'),
'timezone': fields.String(required=False, description='The user\'s preferred timezone'),
'email': fields.String(required=True, description='The user\'s e-mail address'),
'password': fields.String(required=False, description='The group\'s name')
}))
class AuthProviders(Resource):
def get(self):
return register()
@auth_api_bp.route('/login', methods=('GET', 'POST',))
def login():
print("login")
@@ -62,11 +87,30 @@ def login():
return jsonify({'message': 'Invalid credentials', 'authenticated': False}), 401
token = {
'access_token': create_access_token(identity=user.email, fresh=True),
'refresh_token': create_refresh_token(identity=user.email)
'access_token': create_access_token(identity=user, fresh=True),
'refresh_token': create_refresh_token(identity=user)
}
return jsonify(token), 200
# Endpoint for revoking the current users access token
@auth_api_bp.route('/logout', methods=['GET', 'DELETE'])
@jwt_required
def logout():
jti = get_raw_jwt()['jti']
db.session.add(BlacklistToken(token=jti))
db.session.commit()
return jsonify({"msg": "Successfully logged out"}), 200
# Endpoint for revoking the current users refresh token
@auth_api_bp.route('/logout2', methods=['GET', 'DELETE'])
@jwt_refresh_token_required
def logout2():
jti = get_raw_jwt()['jti']
db.session.add(BlacklistToken(token=jti))
db.session.commit()
return jsonify({"msg": "Successfully logged out"}), 200
def check_and_create_groups(groups: Iterable[str]):
user_groups = []
@@ -92,6 +136,7 @@ def create_or_retrieve_user_from_userinfo(userinfo):
if user is not None:
app.logger.info("user found -> update user")
pprint(user.to_dict())
user.first_name = userinfo.get("given_name", "")
user.last_name = userinfo.get("family_name", "")
for g in user_groups:
@@ -121,8 +166,8 @@ def oidc(redirect_url=None):
token = jwt.encode(flask.session['id_token'], current_app.config['SECRET_KEY'])
else:
token = json.dumps({
'access_token': create_access_token(identity=user.email, fresh=True),
'refresh_token': create_refresh_token(identity=user.email)
'access_token': create_access_token(identity=user, fresh=True),
'refresh_token': create_refresh_token(identity=user)
})
if redirect_url is None:
redirect_url = request.headers.get("Referer")
@@ -142,8 +187,10 @@ def refresh():
"""Refresh token endpoint. This will generate a new access token from
the refresh token, but will mark that access token as non-fresh,
as we do not actually verify a password in this endpoint."""
current_user = get_jwt_identity()
app.logger.info("Refreshing token for " + current_user)
new_token = create_access_token(identity=current_user, fresh=False)
jwt_identity = get_jwt_identity()
user = User.get_by_identifier(jwt_identity)
app.logger.info("Refreshing token for " + str(user))
new_token = create_access_token(identity=user, fresh=False)
ret = {'access_token': new_token}
return jsonify(ret), 200

View File

@@ -8,7 +8,7 @@ Login through API does not start a new session, but instead returns JWT.
import json
from datetime import datetime
from flask_jwt_extended import jwt_required
from flask_jwt_extended import jwt_required, get_current_user, get_jwt_claims
from flask_restplus import fields, Resource
from backend import db
@@ -35,6 +35,8 @@ class ControlCommand(Resource):
@api_control.expect(control_command_parser)
@api_control.marshal_with(control_command_response_model, skip_none=False, code=201)
def post(self):
current_user = {'identity': get_jwt_identity(), 'type': type(get_jwt_identity())}
print(get_current_user())
print(get_jwt_identity())
current_user = {'user': get_current_user(), 'claims': get_jwt_claims()}
args = self.control_command_parser.parse_args()
return {'time': datetime.utcnow(), 'output': args, 'state': current_user}

View File

@@ -5,46 +5,72 @@ For example: listing of available auth providers or registration of users.
Login through API does not start a new session, but instead returns JWT.
"""
from datetime import datetime
from pprint import pprint
import flask
import jwt
from flask import request, jsonify, current_app, url_for
from flask_jwt_extended import get_jwt_identity, jwt_optional, jwt_required
from flask_restplus import Resource, fields
from flask_restplus import Resource, fields, inputs
from backend import db, app, jwt_auth
from backend.api import api_bp, api_user
from backend.auth import oidc_auth
from backend.models.user_model import User, Group
user_model = api_user.model('User', {
'id': fields.String(required=True, description='The user\'s identifier'),
'first_name': fields.String(required=True, description='The user\'s first name'),
'last_name': fields.String(required=True, description='The user\'s last name'),
'email': fields.String(required=True, description='The user\'s email address'),
'nickname': fields.String(required=False, description='The user\'s nick name'),
'groups': fields.List(fields.Nested(api_user.model('user_group', {'id':fields.Integer(), 'name': fields.String()})),
required=False, description='Group memberships.'),
'groups': fields.List(
fields.Nested(api_user.model('user_group', {'id': fields.Integer(), 'name': fields.String()})),
required=False, description='Group memberships.'),
})
user_update_parser = api_user.parser()
user_update_parser.add_argument('email', type=inputs.email, required=False, nullable=False, store_missing=False)
user_update_parser.add_argument('nickname', type=str, required=False, store_missing=False)
user_update_parser.add_argument('first_name', type=str, required=False, store_missing=False)
user_update_parser.add_argument('last_name', type=str, required=False, store_missing=False)
@api_user.route('/profile', methods=['GET'])
@api_user.route('/profile')
class Profile(Resource):
@jwt_auth.login_required
@api_user.marshal_list_with(user_model)
@jwt_required
@api_user.marshal_with(user_model)
def get(self):
"""Get infos about logged in user."""
current_user_id = get_jwt_identity()
app.logger.info(current_user_id)
return User.get_by_identifier(current_user_id)
@jwt_required
def put(self):
current_user_id = get_jwt_identity()
print(api_user.payload)
app.logger.info(current_user_id)
args = user_update_parser.parse_args()
args['last_time_modified'] = datetime.utcnow()
pprint(args)
num_rows_matched = User.query.filter_by(id=current_user_id).update(args)
print(num_rows_matched)
if num_rows_matched < 1:
api_user.abort(404)
db.session.commit()
return "ok"
@api_user.route('')
class UserList(Resource):
"""
This is a test class.
"""
#@jwt_auth.login_required
# @jwt_auth.login_required
@jwt_required
@api_user.doc('users')
@api_user.marshal_list_with(user_model)