Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kj #8

Closed
wants to merge 15 commits into from
Closed

kj #8

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## stackS-api

[![Build Status](https://travis-ci.org/hogum/stackS-api.svg?branch=develop)](https://travis-ci.org/hogum/stackS-api)
[![Coverage Status](https://coveralls.io/repos/github/hogum/stackS-api/badge.svg?branch=develop)](https://coveralls.io/github/hogum/stackS-api?branch=develop) [![Maintainability](https://api.codeclimate.com/v1/badges/026466004435ebedbdf8/maintainability)](https://codeclimate.com/github/hogum/stackS-api/maintainability)
[![Coverage Status](https://coveralls.io/repos/github/hogum/stackS-api/badge.svg)](https://coveralls.io/github/hogum/stackS-api) [![Maintainability](https://api.codeclimate.com/v1/badges/026466004435ebedbdf8/maintainability)](https://codeclimate.com/github/hogum/stackS-api/maintainability)

[![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/faa1bb2518cd81a3e91d)

Expand Down Expand Up @@ -53,9 +53,10 @@ $ flask run

##### Authorization Endpoints

Method | Enpoint | Functionality
Method | Endpoint | Functionality
--- | --- |---
POST | `api/v1/auth/users` | Re gister new User
POST | `api/v1/auth/register` | Register new User
POST | `api/v1/auth/login` | Login registered User
PUT | `api/v1/auth/users/user_id` | Update user details
DELETE | `api/v1/auth/users/user_id` | Delete a user account
GET | `api/v1/auth/users` | Get all registered users
Expand Down
10 changes: 9 additions & 1 deletion app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
from flask import Flask
from app.v1.views.users import auth
from app.v1.views.users import auth, blacklisted_tokens
from instance.config import APP_CONFIG
from flask_jwt_extended import JWTManager


def create_app(config_setting):
app = Flask(__name__)
app.register_blueprint(auth)
app.config['JWT_BLACKLIST_ENABLED'] = True
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = ['access']

jwt = JWTManager(app)
app.config.from_object(APP_CONFIG[
config_setting.strip().lower()])

@jwt.token_in_blacklist_loader
def check_blacklisted_token(token):
jti = token['jti']
return jti in blacklisted_tokens

return app
20 changes: 18 additions & 2 deletions app/v1/utils/helper.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import re
from functools import wraps
from functools import wraps, partial
from flask import request, make_response, jsonify
from werkzeug.exceptions import BadRequest


def verify_email(email):
Expand All @@ -23,3 +22,20 @@ def wrapper(*args, **kwargs):
Please provide a valid json header\t")), 400
return f(*args, **kwargs)
return wrapper


"""
def verify_email(f, email):
@wraps(f)
def wrapper(*args, **kwargs):
email_regex = re.compile(r"[^@\\s]+@[^@\\s]+\\.[a-zA-Z0-9]+$")

if email_regex.match(email):
return f(*args, **kwargs)
else:
return make_response(jsonify("Email format unkown")), 400
return wrapper


real_email = partial(verify_email)
"""
22 changes: 19 additions & 3 deletions app/v1/views/users.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
from flask import Blueprint, request, make_response, jsonify, session
import random
from flask_jwt_extended import jwt_required, create_access_token
from flask_jwt_extended import (
jwt_required, create_access_token, get_jwt_identity, get_raw_jwt)

from app.v1.utils.helper import verify_email, validate_json_header
from app.v1.models.users import UserModel

auth = Blueprint('auth', __name__, url_prefix='/api/v1/auth/')

blacklisted_tokens = set()


@auth.route('register', methods=['POST', 'GET'])
@validate_json_header
Expand All @@ -18,8 +21,8 @@ def register_user():
"""
if request.method == 'POST':
data = request.get_json()
email = data['email']
password = data['password']
email = data.get('email')
password = data.get('password')
username = data.get('username')

if verify_email(email) and len(password) > 6:
Expand Down Expand Up @@ -77,3 +80,16 @@ def login_user():
"Logged in as": repr(user),
"Token": user_token
})), 201


@auth.route('logout', methods=['DELETE'])
@validate_json_header
@jwt_required
def logout_user():
data = request.get_json()

jti = get_raw_jwt()['jti']

blacklisted_tokens.add(jti)
return make_response(jsonify(
"Logout successful")), 201
6 changes: 4 additions & 2 deletions instance/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ class BaseConfig:
DEBUG = False
TESTING = False
SECRET_KEY = os.environ.get('SECRET_KEY',
os.urandom(16))
b'\xc2;F]l\x046t\xfe\x08'
)
CSRF_ENABLED = True
JWT_SECRET_KET = os.environ.get('JWT_SECRET_KEY',
os.urandom(25))
b'\xa3$\x0bm\xae\xbbmd\x12\x8f'
)


class DevelopmentConfig(BaseConfig):
Expand Down
8 changes: 8 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
atomicwrites==1.2.1
attrs==18.2.0
certifi==2018.11.29
chardet==3.0.4
Click==7.0
coverage==4.5.2
coverage-badge==0.2.0
coveralls==1.5.1
docopt==0.6.2
Flask==1.0.2
Flask-JWT-Extended==3.14.0
idna==2.8
itsdangerous==1.1.0
Jinja2==2.10
MarkupSafe==1.1.0
Expand All @@ -13,5 +19,7 @@ py==1.7.0
PyJWT==1.7.1
pytest==4.0.2
pytest-cov==2.6.0
requests==2.21.0
six==1.12.0
urllib3==1.24.1
Werkzeug==0.14.1
13 changes: 13 additions & 0 deletions tests/auth_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,16 @@ def test_login_with_unregistered_email(self):
content_type='application/json')
self.assertEqual(response.status_code, 400,
msg="Fails. Logs in user with unknown email")

def test_logged_in_user_can_log_out(self):

self.client.post('/api/v1/auth/login',
data=self.user_data,
content_type='application/json')

response = self.client.delete('/api/v1/auth/logout',
headers=self.auth_header,
data=self.user_data,
content_type='application/json')
self.assertEqual(response.status_code, 201,
msg="Fails to logout user")
6 changes: 6 additions & 0 deletions tests/base_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,9 @@ def setUp(self):
data=self.user_data,
content_type='application/json')
self.new_user = json.loads(response.data.decode())

login_response = self.client.post('/api/v1/auth/login',
data=self.user_data,
content_type='application/json')
user = json.loads(login_response.data.decode()).get("Token")
self.auth_header = {"Authorization": "Bearer " + user}