Skip to content

Commit

Permalink
Changing where auth functions are, and creating another namespace for it
Browse files Browse the repository at this point in the history
-Changing where auth functions are, and creating another namespace for it

-Creating a standard dto model for responses (status and message) and pagination
  • Loading branch information
CleitonAlmeida committed Dec 20, 2018
1 parent c9ec10e commit d19875a
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 169 deletions.
5 changes: 4 additions & 1 deletion call_records/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
from flask.logging import default_handler
from flask_jwt_extended import JWTManager

from call_records.controller.user import User as UserController
from call_records.controller import user, auth
from call_records.dto.user import UserDto
from call_records.dto.auth import AuthDto

db = SQLAlchemy()

Expand Down Expand Up @@ -52,7 +53,9 @@ def configure_namespace(app):
doc='/api',
authorizations=authorizations,
security='Bearer Auth')

api.add_namespace(UserDto.ns, path='/api/user')
api.add_namespace(AuthDto.ns, path='/api')

def configure_jwt(app):
app.config['JWT_SECRET_KEY'] = 'AUIRgoasdgfuyAUYFaisuebf' # Change this!
Expand Down
56 changes: 56 additions & 0 deletions call_records/controller/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from flask import current_app
from flask_restplus import Resource
from flask_restplus import reqparse
from flask_jwt_extended import jwt_refresh_token_required, get_raw_jwt

from call_records.controller import user_required
from call_records.dto.auth import AuthDto
from call_records.service.auth import login_user, get_refresh_token, logout_user

ns = AuthDto.ns
authLogInDtoModel = AuthDto.authLogIn
authRefreshDtoModel = AuthDto.authRefresh
authResponsesDtoModel = AuthDto.authResponses


def get_login_parser():
parser = reqparse.RequestParser()
parser.add_argument('username', type=str, required=True)
parser.add_argument('password', type=str, required=True)
return parser

@ns.route('/login')
class UserLogin(Resource):
@ns.expect(get_login_parser(), validate=True)
@ns.marshal_with(authLogInDtoModel, skip_none=True)
@ns.doc(responses={
200: 'Success',
401: 'Username or password does not match'
})
@ns.doc(security=[])
def post(self):
"""To Login in"""
parser = get_login_parser()
data = parser.parse_args()

return login_user(data=data)

@ns.route('/refresh')
class UserLoginRefresh(Resource):
@user_required
@ns.marshal_with(authRefreshDtoModel, skip_none=True)
#@jwt_refresh_token_required
def post(self):
"""To get a refresh token"""
return get_refresh_token()

@ns.route('/logout')
class UserLogout(Resource):
@user_required
@ns.marshal_with(authResponsesDtoModel, skip_none=True)
@ns.doc(responses={
200: 'Logout Successfully'
})
def post(self):
"""To logout an user"""
return logout_user()
45 changes: 3 additions & 42 deletions call_records/controller/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,14 @@

from call_records.dto.user import UserDto
from call_records.service.user import (save_user, get_a_user, get_all_users,
login_user, get_refresh_token, logout_user, update_user)
update_user)
from call_records.controller import user_required, admin_required
from flask_restplus import reqparse, inputs
from flask_jwt_extended import jwt_refresh_token_required, get_raw_jwt

ns = UserDto.ns
userDtoModel = UserDto.user
userListDtoModel = UserDto.userList
userLogInDtoModel = UserDto.userLogIn
userRefreshDtoModel = UserDto.userRefresh
userResponsesDtoModel = UserDto.userResponses
userResponseDtoModel = UserDto.userResponses

def get_parser_user():
parser = reqparse.RequestParser()
Expand Down Expand Up @@ -77,7 +74,7 @@ def get(self, username):

@user_required
@ns.expect(get_parser_update_user(), validate=True)
@ns.marshal_with(userResponsesDtoModel, skip_none=True)
@ns.marshal_with(userResponseDtoModel, skip_none=True)
@ns.doc(responses={
200: 'Successfully updated',
404: 'User not found'
Expand All @@ -96,39 +93,3 @@ def put(self, username):
'message': 'Try again'
}
return response_object, 500

@ns.route('/login')
class UserLogin(Resource):
@ns.expect(get_parser_user(), validate=True)
@ns.marshal_with(userLogInDtoModel, skip_none=True)
@ns.doc(responses={
200: 'Success',
401: 'Username or password does not match'
})
@ns.doc(security=[])
def post(self):
"""To Login in"""
parser = get_parser_user()
data = parser.parse_args()

return login_user(data=data)

@ns.route('/refresh')
class UserLoginRefresh(Resource):
@user_required
@ns.marshal_with(userRefreshDtoModel, skip_none=True)
#@jwt_refresh_token_required
def post(self):
"""To get a refresh token"""
return get_refresh_token()

@ns.route('/logout')
class UserLogout(Resource):
@user_required
@ns.marshal_with(userResponsesDtoModel, skip_none=True)
@ns.doc(responses={
200: 'Logout Successfully'
})
def post(self):
"""To logout an user"""
return logout_user()
15 changes: 15 additions & 0 deletions call_records/dto/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from flask_restplus import fields
from flask_restplus import Model
from flask import current_app

standardResponseDtoModel = Model('standardResponse', {
'status': fields.String(required=True, enum=('success', 'fail'), description='Status of operation'),
'message': fields.String(required=True, description='Message describing the success of the operation or the reason for an error')
})

standardPaginationDtoModel = Model('standardPagination', {
'start': fields.Integer(required=True, description='It is the position from which we want the data to be returned'),
'limit': fields.Integer(required=True, description='It is the max number of items to return from that position'),
'next': fields.String(required=False, description='It is the url for the next page of the query assuming current value of limit'),
'previous': fields.String(required=False, description='It is the url for the previous page of the query assuming current value of limit')
})
14 changes: 14 additions & 0 deletions call_records/dto/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from flask_restplus import Namespace, fields
from call_records.dto import standardResponseDtoModel


class AuthDto:
ns = Namespace('auth', description='Auth')
authLogIn = ns.clone('authLogIn', standardResponseDtoModel, {
'access_token': fields.String(required=False, description='Token used to access protected resources', example='eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NDQ3MjE2MDAsIm5iZiI6MTU0NDcyMTYwMCwianRpIjoiZjQ3NTBmMjEtMWExMS00YWExLWI2YTYtMz.argP9jSHhZ7xWSzFAf1hWHIq6MjpoZb_hTDzUl5uGUc')
})
authRefresh = ns.model('authRefresh', {
'status': fields.String(required=True, enum=('success', 'fail'), description='Status of refresh token operation'),
'access_token': fields.String(required=False, description='Token used to access protected resources', example='eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NDQ3MjE2MDAsIm5iZiI6MTU0NDcyMTYwMCwianRpIjoiZjQ3NTBmMjEtMWExMS00YWExLWI2YTYtMz.argP9jSHhZ7xWSzFAf1hWHIq6MjpoZb_hTDzUl5uGUc')
})
authResponses = ns.clone('authResponses', standardResponseDtoModel, {})
22 changes: 3 additions & 19 deletions call_records/dto/user.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from flask_restplus import Namespace, fields

from call_records.dto import standardPaginationDtoModel, standardResponseDtoModel

class UserDto:
ns = Namespace('user', description='User')
Expand All @@ -9,23 +9,7 @@ class UserDto:
'date_modified': fields.DateTime(description='Datetime of user modification'),
'is_admin': fields.Boolean(description='Role of user (if is admin or not admin)')
})
userList = ns.model('userList', {
'start': fields.Integer(required=True, description='It is the position from which we want the data to be returned'),
'limit': fields.Integer(required=True, description='It is the max number of items to return from that position'),
'next': fields.String(required=False, description='It is the url for the next page of the query assuming current value of limit'),
'previous': fields.String(required=False, description='It is the url for the previous page of the query assuming current value of limit'),
userList = ns.clone('userList', standardPaginationDtoModel, {
'results': fields.List(fields.Nested(user, skip_none=True))
})
userLogIn = ns.model('userLogIn', {
'status': fields.String(required=True, enum=('success', 'fail'), description='Status of login operation'),
'message': fields.String(required=True, description='An message description', example='Successfully logged in'),
'access_token': fields.String(required=False, description='Token used to access protected resources', example='eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NDQ3MjE2MDAsIm5iZiI6MTU0NDcyMTYwMCwianRpIjoiZjQ3NTBmMjEtMWExMS00YWExLWI2YTYtMz.argP9jSHhZ7xWSzFAf1hWHIq6MjpoZb_hTDzUl5uGUc')
})
userRefresh = ns.model('userRefresh', {
'status': fields.String(required=True, enum=('success', 'fail'), description='Status of refresh token operation'),
'access_token': fields.String(required=False, description='Token used to access protected resources', example='eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NDQ3MjE2MDAsIm5iZiI6MTU0NDcyMTYwMCwianRpIjoiZjQ3NTBmMjEtMWExMS00YWExLWI2YTYtMz.argP9jSHhZ7xWSzFAf1hWHIq6MjpoZb_hTDzUl5uGUc')
})
userResponses = ns.model('userResponses', {
'status': fields.String(required=True, enum=('success', 'fail'), description='Status of operation'),
'message': fields.String(required=True, description='Message describing the success of the operation or the reason for an error')
})
userResponses = ns.clone('userResponses', standardResponseDtoModel, {})
88 changes: 88 additions & 0 deletions call_records/service/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
def login_user(data):
from call_records.model.user import User
from call_records.service.tokenblacklist import add_token_to_database
from flask import current_app
from flask_jwt_extended import (
JWTManager, jwt_required, create_access_token,
get_jwt_identity
)

try:
user = User.query.filter_by(username=data.get('username')).first()
if user and user.verify_password(password=data.get('password')):
access_token = create_access_token(identity=user)
add_token_to_database(access_token, current_app.config['JWT_IDENTITY_CLAIM'])
response_object = {
'status': 'success',
'message': 'Successfully logged in',
'access_token': access_token
}
return response_object, 200
else:
response_object = {
'status': 'fail',
'message': 'Username or password does not match.'
}
return response_object, 401
except Exception as e:
current_app.logger.error('login_user %s', e)
response_object = {
'status': 'fail',
'message': 'Try again'
}
return response_object, 500

def get_refresh_token():
from flask_jwt_extended import create_access_token, get_raw_jwt
from flask import current_app
from call_records.model.user import User
from call_records.service.tokenblacklist import add_token_to_database, revoke_token

try:
#Revoke Current Token
current_claims = get_raw_jwt()
revoke_token(current_claims.get('jti'), current_claims.get('identity'))
current_user = current_claims.get('identity')
user = User.query.filter_by(username=current_user).first()
if user:
new_access_token = create_access_token(identity=user)
add_token_to_database(new_access_token, current_app.config['JWT_IDENTITY_CLAIM'])
response_object = {
'status': 'success',
'access_token': new_access_token
}
return response_object, 200
else:
response_object = {
'status': 'fail',
'message': 'User does not match.'
}
return response_object, 401
except Exception as e:
current_app.logger.error('get_refresh_token %s', e)
response_object = {
'status': 'fail',
'message': 'Try again'
}
return response_object, 500

def logout_user():
from call_records.service.tokenblacklist import revoke_token_user
from flask import current_app
from flask_jwt_extended import get_raw_jwt
try:
#Revoke Current Token
current_claims = get_raw_jwt()
revoke_token_user(current_claims.get('identity'))
response_object = {
'status': 'success',
'message': 'Logout Successfully'
}
return response_object, 200
except Exception as e:
current_app.logger.error('logout_user %s', e)
response_object = {
'status': 'fail',
'message': 'Try again'
}
return response_object, 500
89 changes: 0 additions & 89 deletions call_records/service/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,92 +110,3 @@ def get_all_users(paginated=False, start=None, limit=None):
return paginated_list(User, request.base_url, start=start, limit=limit)
else:
return User.query.all()

def login_user(data):
from call_records.model.user import User
from call_records.service.tokenblacklist import add_token_to_database
from flask import current_app
from flask_jwt_extended import (
JWTManager, jwt_required, create_access_token,
get_jwt_identity
)

try:
user = User.query.filter_by(username=data.get('username')).first()
if user and user.verify_password(password=data.get('password')):
access_token = create_access_token(identity=user)
add_token_to_database(access_token, current_app.config['JWT_IDENTITY_CLAIM'])
response_object = {
'status': 'success',
'message': 'Successfully logged in',
'access_token': access_token
}
return response_object, 200
else:
response_object = {
'status': 'fail',
'message': 'Username or password does not match.'
}
return response_object, 401
except Exception as e:
current_app.logger.error('login_user %s', e)
response_object = {
'status': 'fail',
'message': 'Try again'
}
return response_object, 500

def get_refresh_token():
from flask_jwt_extended import create_access_token, get_raw_jwt
from flask import current_app
from call_records.model.user import User
from call_records.service.tokenblacklist import add_token_to_database, revoke_token

try:
#Revoke Current Token
current_claims = get_raw_jwt()
revoke_token(current_claims.get('jti'), current_claims.get('identity'))
current_user = current_claims.get('identity')
user = User.query.filter_by(username=current_user).first()
if user:
new_access_token = create_access_token(identity=user)
add_token_to_database(new_access_token, current_app.config['JWT_IDENTITY_CLAIM'])
response_object = {
'status': 'success',
'access_token': new_access_token
}
return response_object, 200
else:
response_object = {
'status': 'fail',
'message': 'User does not match.'
}
return response_object, 401
except Exception as e:
current_app.logger.error('get_refresh_token %s', e)
response_object = {
'status': 'fail',
'message': 'Try again'
}
return response_object, 500

def logout_user():
from call_records.service.tokenblacklist import revoke_token_user
from flask import current_app
from flask_jwt_extended import get_raw_jwt
try:
#Revoke Current Token
current_claims = get_raw_jwt()
revoke_token_user(current_claims.get('identity'))
response_object = {
'status': 'success',
'message': 'Logout Successfully'
}
return response_object, 200
except Exception as e:
current_app.logger.error('logout_user %s', e)
response_object = {
'status': 'fail',
'message': 'Try again'
}
return response_object, 500
Loading

0 comments on commit d19875a

Please sign in to comment.