add a basic api based on flask-restless

not really a final solution, but it can probably get pretty far
This commit is contained in:
termie 2013-11-26 16:54:44 -08:00
parent 822272be09
commit c8284b2bdc
7 changed files with 97 additions and 4 deletions

View File

@ -21,7 +21,7 @@ def init_app(app):
admin.init_app(app) admin.init_app(app)
def configure_admin(): def configure_admin(app):
admin.add_view(SecureView(models.Cloud, db.session)) admin.add_view(SecureView(models.Cloud, db.session))
admin.add_view(SecureView(models.User, db.session)) admin.add_view(SecureView(models.User, db.session))
admin.add_view(SecureView(models.Vendor, db.session)) admin.add_view(SecureView(models.Vendor, db.session))

68
refstack/api.py Normal file
View File

@ -0,0 +1,68 @@
"""Basic API code.
This is using Flask-Restless at the moment because it is super simple,
but probably should be moved to a more versatile framework like
Flask-Restful later on.
"""
import flask
from flask.ext import restless
from refstack import models
from refstack.extensions import api
def init_app(app, *args, **kw):
api.init_app(app, *args, **kw)
def access_control(**kw):
if not flask.g.user:
raise _not_authorized()
if not flask.g.user.su:
return _not_authorized()
# That's it, we're defaulting to superuser only access
# until we flesh this out further
ALL_METHODS = {'GET_SINGLE': [access_control],
'GET_MANY': [access_control],
'PUT_SINGLE': [access_control],
'PUT_MANY': [access_control],
'POST': [access_control],
'DELETE': [access_control]}
def configure_api(app):
cloud_api = api.create_api_blueprint(models.Cloud,
preprocessors=ALL_METHODS)
cloud_api.before_request(authenticate)
app.register_blueprint(cloud_api)
def _not_authorized():
return restless.ProcessingException(message='Not Authorized',
status_code=401)
def authenticate():
# If we're already authenticated, we can ignore this
if flask.g.user:
return
# Otherwise check headers
openid = flask.request.headers.get('X-AUTH-OPENID')
if openid:
# In debug mode accept anything
if flask.current_app.debug and False:
flask.g.user = models.User.query.filter_by(openid=openid).first()
return
apikey = flask.request.headers.get('X-AUTH-APIKEY')
apikey_ref = models.ApiKey.query.filter_by(key=apikey)
if apikey_ref['openid'] == openid:
flask.g.user = apikey_ref.user

View File

@ -15,6 +15,7 @@ from .config import DefaultConfig
#from .admin import admin #from .admin import admin
#from .extensions import db, mail, cache, login_manager, oid #from .extensions import db, mail, cache, login_manager, oid
from refstack import admin from refstack import admin
from refstack import api
from .extensions import db from .extensions import db
from .extensions import oid from .extensions import oid
@ -94,7 +95,11 @@ def configure_extensions(app):
# flask-admin # flask-admin
admin.init_app(app) admin.init_app(app)
admin.configure_admin() admin.configure_admin(app)
# flask-restless
api.init_app(app, flask_sqlalchemy_db=db)
api.configure_api(app)
## flask-mail ## flask-mail
#mail.init_app(app) #mail.init_app(app)

View File

@ -5,6 +5,9 @@
from flask.ext.admin import Admin from flask.ext.admin import Admin
admin = Admin() admin = Admin()
from flask.ext.restless import APIManager
api = APIManager()
from flask.ext.sqlalchemy import SQLAlchemy from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy() db = SQLAlchemy()

View File

@ -41,6 +41,20 @@ class User(db.Model):
def __str__(self): def __str__(self):
return self.name return self.name
class ApiKey(db.Model):
__tablename__ = 'apikey'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(60))
key = db.Column(db.String(200))
openid = db.Column(db.String(200))
timestamp = db.Column(db.DateTime, default=datetime.now)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
user = db.relationship('User',
backref=db.backref('apikeys', lazy='dynamic'))
""" """
Note: The vendor list will be pre-populated from the sponsoring company database. Note: The vendor list will be pre-populated from the sponsoring company database.
TODO: better define the vendor object and its relationship with user TODO: better define the vendor object and its relationship with user

View File

@ -31,6 +31,8 @@ from flask_mail import Mail
from refstack import app as base_app from refstack import app as base_app
from refstack.extensions import db from refstack.extensions import db
from refstack.extensions import oid from refstack.extensions import oid
from refstack import api
from refstack.models import ApiKey
from refstack.models import Cloud from refstack.models import Cloud
from refstack.models import Test from refstack.models import Test
from refstack.models import TestResults from refstack.models import TestResults
@ -50,9 +52,9 @@ mail = Mail(app)
@app.before_request @app.before_request
def before_request(): def before_request():
"""Runs before the request itself.""" """Runs before the request itself."""
g.user = None flask.g.user = None
if 'openid' in session: if 'openid' in session:
g.user = User.query.filter_by(openid=session['openid']).first() flask.g.user = User.query.filter_by(openid=session['openid']).first()
@app.route('/', methods=['POST', 'GET']) @app.route('/', methods=['POST', 'GET'])

View File

@ -7,6 +7,7 @@ Flask-Principal==0.3.5
Flask-SQLAlchemy==1.0 Flask-SQLAlchemy==1.0
Flask-Security==1.6.3 Flask-Security==1.6.3
Flask-WTF==0.8.3 Flask-WTF==0.8.3
Flask-Restless=0.12.0
SQLAlchemy==0.8.3 SQLAlchemy==0.8.3
WTForms==1.0.4 WTForms==1.0.4
Werkzeug==0.8.3 Werkzeug==0.8.3