"""
Defines the flask app which will run our HTTP application. This also creates
a flask-restful API object, which will serve as the router to the objects in
:mod:`api_views`.
"""
import logging
from flask import Flask, g, jsonify, request, abort
from flask_restful import Api
from auth import auth
from config import default_config as conf
from database import Administrator, User, ContextManagedSession
from views import UserContainer, UserView, ProjectContainer, Projects
from flask.ext.cors import CORS
log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)
__author__ = 'Michal Kononenko'
app = Flask(__name__)
api = Api(app, prefix='/api/v1')
api.add_resource(UserContainer, '/users')
api.add_resource(UserView, '/users/<username_or_id>')
api.add_resource(ProjectContainer, '/projects')
api.add_resource(Projects, 'projects/<project_name_or_id>')
database_session = ContextManagedSession(bind=conf.DATABASE_ENGINE)
CORS(app)
@app.route('/', methods=["GET", "OPTIONS"])
@app.route('/index', methods=["GET", "OPTIONS"])
[docs]def hello_world():
"""
Base URL to confirm that the API actually works. Eventually, this endpoint
will serve the OmicronClient_. JavaScript UI to users.
**Example Response**
.. sourcecode:: http
GET / HTTP/1.1
Content-Type: application/json
Hello World!
.. _OmicronClient: https://github.com/MichalKononenko/OmicronClient
:return: Hello, world!
:rtype: str
"""
return jsonify({'message': 'hello_world'})
@app.route('/api/v1/token', methods=['POST'])
@auth.login_required
[docs]def create_token():
"""
Generate a user's auth token from the user in Flask's :attr:`Flask.g`
object, which acts as an object repository unique to each request. Expects
an Authorization header with Basic Auth.
**Example Request**
.. sourcecode:: http
POST /api/v1/token HTTP/1.1
Host: example.com
Content-Type: application/json
Authorization: B12kS1l2jS1=
**Example Response**
.. sourcecode:: http
Content-Type: application/json
{
"token": "a409a362-d733-11e5-b625-7e14f79230d0",
"expiration_date": "2015-01-01T12:00:00"
}
:return: A Flask response object with the token jsonified into ASCII
"""
try:
token, expiration_date = g.user.generate_auth_token(
expiration=int(request.args.get('expiration'))
)
except TypeError:
log.debug('No expiration supplied, using default expiration time')
token, expiration_date = g.user.generate_auth_token()
response = jsonify(
{'token': token,
'expiration_date': expiration_date.isoformat()
}
)
response.status_code = 201
return response
@app.route('/api/v1/token', methods=['DELETE'])
@auth.login_required
[docs]def revoke_token():
"""
Revoke the current token for the user that has just authenticated,
or the user with username given by a query parameter, allowed only if the
user is an Administrator
"""
username_to_delete = request.args.get('username')
if username_to_delete is None:
username_to_delete = g.user.username
else:
username_to_delete = str(username_to_delete)
if isinstance(g.user, Administrator):
with database_session() as session:
user = session.query(
User
).filter_by(
username=username_to_delete
).first()
if user is None:
abort(404)
user.current_token.first().revoke()
else:
with database_session() as session:
session.query(g.user.__class__).filter_by(
id=g.user.id
).first().current_token.first().revoke()
response = jsonify({'token_status': 'deleted'})
return response