diff --git a/app/__init__.py b/app/__init__.py index 40fc33f..0dc6025 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -2,12 +2,14 @@ from flask_api import FlaskAPI from flask_sqlalchemy import SQLAlchemy from flask_bcrypt import Bcrypt +from flasgger import Swagger app = FlaskAPI(__name__, instance_relative_config=True) app.config.from_object('config') app.config.from_pyfile('config.py', silent=True) db = SQLAlchemy(app) bcrypt = Bcrypt(app) +swagger = Swagger(app, template_file='swagger/template.yaml') def setup_blueprints(app): @@ -34,5 +36,5 @@ setup_blueprints(app) @app.route("/") -def hello(): +def root(): return "Hello World!" diff --git a/app/api/__init__.py b/app/api/__init__.py index 0bbb6ed..6a74a8b 100644 --- a/app/api/__init__.py +++ b/app/api/__init__.py @@ -4,6 +4,7 @@ from .resources.account import AccountResource from .resources.token import TokenResource from marshmallow import ValidationError + api_bp = Blueprint('api', __name__) api = Api(api_bp) diff --git a/app/api/resources/account.py b/app/api/resources/account.py index c8a1b3d..3b7ae7a 100644 --- a/app/api/resources/account.py +++ b/app/api/resources/account.py @@ -1,6 +1,7 @@ from flask_restful import Resource, abort from webargs import fields from webargs.flaskparser import use_args +from flasgger import swag_from import app.accounts as accounts @@ -14,6 +15,7 @@ class AccountResource(Resource): } @use_args(user_args) + @swag_from('swagger/create_account_spec.yaml') def post(self, args): try: args = args['user'] @@ -25,3 +27,7 @@ class AccountResource(Resource): return '', 201 except ValueError: abort(422, message='Account already exists', status='error') + + @swag_from('swagger/get_account_spec.yaml') + def get(self): + return '', 200 diff --git a/app/api/resources/swagger/create_account_spec.yaml b/app/api/resources/swagger/create_account_spec.yaml new file mode 100644 index 0000000..8ef8f8f --- /dev/null +++ b/app/api/resources/swagger/create_account_spec.yaml @@ -0,0 +1,28 @@ +Creates new user account +Requires User object and creates account +or returns an error if account already exists +--- +tags: + - Account +parameters: + - in: body + name: body + required: true + schema: + type: object + required: + - user + properties: + user: + required: + - username + - password + - email + $ref: '#/definitions/User' +responses: + 201: + description: Successful creation + 422: + description: Account already exists + schema: + $ref: '#/definitions/Error' diff --git a/app/api/resources/swagger/create_token_spec.yaml b/app/api/resources/swagger/create_token_spec.yaml new file mode 100644 index 0000000..6ef7c70 --- /dev/null +++ b/app/api/resources/swagger/create_token_spec.yaml @@ -0,0 +1,36 @@ +Creates new token for given account +Requires a registered User with a valid username and password +Creates a JWT token and returns it or returns an error if credentials are wrong +--- +tags: + - Token + - Account +parameters: + - in: body + name: body + required: true + schema: + type: object + required: + - user + properties: + user: + $ref: '#/definitions/Credentials' +responses: + 200: + description: Successful creation + schema: + required: + - status + - token + properties: + status: + type: string + default: success + token: + type: string + description: JWT token + 401: + description: Bad credentials + schema: + $ref: '#/definitions/Error' diff --git a/app/api/resources/swagger/get_account_spec.yaml b/app/api/resources/swagger/get_account_spec.yaml new file mode 100644 index 0000000..1150dc3 --- /dev/null +++ b/app/api/resources/swagger/get_account_spec.yaml @@ -0,0 +1,22 @@ +Gets a user account +--- +tags: + - Account +parameters: + - in: body + name: body + required: true + schema: + type: object + required: + - user + properties: + user: + $ref: '#/definitions/User' +responses: + 201: + description: Successful creation + 422: + description: Account already exists + schema: + $ref: '#/definitions/Error' diff --git a/app/api/resources/token.py b/app/api/resources/token.py index 2c0cc8f..345127f 100644 --- a/app/api/resources/token.py +++ b/app/api/resources/token.py @@ -1,6 +1,7 @@ from flask_restful import Resource, abort from webargs import fields from webargs.flaskparser import use_args +from flasgger import swag_from import app.accounts as accounts @@ -13,6 +14,7 @@ class TokenResource(Resource): } @use_args(user_args) + @swag_from('swagger/create_token_spec.yaml') def post(self, args): try: args = args['user'] diff --git a/app/swagger/template.yaml b/app/swagger/template.yaml new file mode 100644 index 0000000..339d8b6 --- /dev/null +++ b/app/swagger/template.yaml @@ -0,0 +1,77 @@ +--- +servers: + - url: https://final-iot-backend.herokuapp.com/ + description: Heroku deployed app for testing + +basePath: "" + +definitions: + + username: + type: string + description: User's name in the system + default: testusername + + email: + type: string + format: email + description: User's registered email + default: user@test.com + + password: + type: string + format: password + description: User's password + default: TestPassword1234 + + status: + type: string + description: Status of request + + message: + type: string + description: Descriptive message + + Credentials: + type: object + required: + - username + - password + properties: + username: + $ref: '#/definitions/username' + password: + $ref: '#/definitions/password' + + User: + type: object + required: + - username + - password + - email + properties: + username: + $ref: '#/definitions/username' + password: + $ref: '#/definitions/password' + email: + $ref: '#/definitions/email' + + Error: + type: object + required: + - status + - message + properties: + status: + $ref: '#/definitions/status' + default: error + message: + $ref: '#/definitions/message' + default: Error message + +info: + description: Python (Flask) backend for IoT sysyem made for master's degree final project + title: IoT Backend + version: 0.0.1 +swagger: '2.0' diff --git a/requirements.txt b/requirements.txt index 1e38e1c..93056ac 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,7 @@ aniso8601==3.0.0 bcrypt==3.1.4 cffi==1.11.5 click==6.7 +flasgger==0.8.3 Flask==1.0.2 Flask-API==1.0 Flask-Bcrypt==0.7.1 @@ -14,9 +15,11 @@ Flask-SQLAlchemy==2.3.2 gunicorn==19.8.1 itsdangerous==0.24 Jinja2==2.10 +jsonschema==2.6.0 Mako==1.0.7 MarkupSafe==1.0 marshmallow==3.0.0b9 +mistune==0.8.3 paho-mqtt==1.3.1 psycopg2==2.7.4 psycopg2-binary==2.7.4 @@ -25,6 +28,7 @@ PyJWT==1.6.1 python-dateutil==2.7.2 python-editor==1.0.3 pytz==2018.4 +PyYAML==3.12 six==1.11.0 SQLAlchemy==1.2.7 typing==3.6.4