the application was rewritten a bit to be more testable

This commit is contained in:
Martin
2016-06-28 18:59:20 +02:00
parent 27542b9ebb
commit 2edf0ba8b0
14 changed files with 122 additions and 54 deletions
+1 -48
View File
@@ -1,48 +1 @@
from flask import Flask, jsonify, Response, request from .core import *
from flask_sqlalchemy import SQLAlchemy
from esales.cluster import Cluster
app = Flask(__name__)
app.config.from_object('config')
def on_404(e):
return jsonify(dict(error='Not found')), 404
app.errorhandler(404)(on_404)
# SQLAlchemy
db = SQLAlchemy(app)
# eSales
esales = Cluster(app.config.get("ESALES_URL"))
from api.views import designers, categories
app.register_blueprint(designers.mod)
app.register_blueprint(categories.mod)
def check_authentication():
auth = request.authorization
if not auth:
return False
return auth.username in app.config.get("API_KEYS")
@app.before_request
def authenticate():
if not check_authentication():
return Response(
'No valid API key provided', 401,
{'WWW-Authenticate': 'Basic realm="Login Required"'}
)
@app.route("/")
def index():
data = {
"info": {
"api_version": "0.0.1"
}
}
return jsonify(data)
+30
View File
@@ -0,0 +1,30 @@
from flask import Flask, jsonify, Response, request
from flask_sqlalchemy import SQLAlchemy
from api.extensions.esales import Esales
from api.helpers import check_api_key
db = SQLAlchemy()
esales = Esales()
def create_app(config_name='config'):
app = Flask(__name__)
app.config.from_object(config_name)
db.init_app(app)
esales.init_app(app)
# register errors handlers
@app.errorhandler(404)
def on_404(e):
return jsonify(dict(error='Not found')), 404
# register blueprints
from api.views import server, designers, categories
app.register_blueprint(server.mod)
app.register_blueprint(designers.mod)
app.register_blueprint(categories.mod)
# authentication
app.before_request(check_api_key)
return app
View File
+12
View File
@@ -0,0 +1,12 @@
from esales.cluster import Cluster
class Esales(object):
def __init__(self, app=None):
self.cluster = Cluster()
if app:
self.init_app(app)
def init_app(self, app):
self.cluster.url = app.config.get('ESALES_URL')
+12
View File
@@ -1,7 +1,19 @@
# coding=UTF-8 # coding=UTF-8
from flask import request, current_app, Response
import unidecode import unidecode
import re import re
def check_api_key():
api_keys = current_app.config.get("API_KEYS")
if not api_keys:
return
auth = request.authorization
if not auth or not auth.username in api_keys:
return Response(
'No valid API key provided', 401,
{'WWW-Authenticate': 'Basic realm="Login Required"'}
)
def slugify(text): def slugify(text):
"""Converts a string to a human-readable url""" """Converts a string to a human-readable url"""
+3 -3
View File
@@ -1,5 +1,5 @@
# coding=utf-8 # coding=utf-8
from api import app from flask import current_app
from api.models.locale import Locale from api.models.locale import Locale
from esales.models import Category, CategoryTree from esales.models import Category, CategoryTree
from esales.utils import ImportFile from esales.utils import ImportFile
@@ -25,7 +25,7 @@ def update_designer(designer):
tree.add_category(category) tree.add_category(category)
importfile.add_operation("update", tree) importfile.add_operation("update", tree)
directory = app.config.get("ESALES_IMPORT_DIR") directory = current_app.config.get("ESALES_IMPORT_DIR")
importfile.write(directory) importfile.write(directory)
@@ -46,5 +46,5 @@ def update_category(category):
)) ))
importfile.add_operation("update", tree) importfile.add_operation("update", tree)
directory = app.config.get("ESALES_IMPORT_DIR") directory = current_app.config.get("ESALES_IMPORT_DIR")
importfile.write(directory) importfile.write(directory)
+11
View File
@@ -0,0 +1,11 @@
from flask import Blueprint, jsonify
mod = Blueprint('server', __name__, url_prefix='/')
@mod.route("/", methods=["GET"])
def status():
data = {
'version': '0.0.1',
'status': 'ok'
}
return jsonify(data)
+1
View File
@@ -0,0 +1 @@
from .cluster import Cluster
+1 -1
View File
@@ -14,7 +14,7 @@ class CommandException(Exception):
class Cluster(object): class Cluster(object):
def __init__(self, url): def __init__(self, url=None):
self.url = url self.url = url
def run_command(self, command): def run_command(self, command):
+3 -2
View File
@@ -1,7 +1,8 @@
from flask.ext.script import Manager, prompt_bool from flask.ext.script import Manager, prompt_bool
from api import app, db, esales from api import create_app, db, esales
from api.models import Designer from api.models import Designer
app = create_app()
manager = Manager(app) manager = Manager(app)
@@ -30,7 +31,7 @@ def seed_db():
def run_esales_import(): def run_esales_import():
print("Importing products and categories into eSales") print("Importing products and categories into eSales")
pattern = "{}/*.xml".format(app.config.get("ESALES_IMPORT_DIR")) pattern = "{}/*.xml".format(app.config.get("ESALES_IMPORT_DIR"))
esales.import_products_and_categories(pattern) esales.cluster.import_products_and_categories(pattern)
if __name__ == '__main__': if __name__ == '__main__':
manager.run() manager.run()
View File
+46
View File
@@ -0,0 +1,46 @@
# coding=UTF-8
import unittest2
import base64
from api import create_app
try:
import httplib
except ImportError:
# support for python 3
import http.client as httplib
class ApiTest(unittest2.TestCase):
def setUp(self):
self.app = create_app('tests.config')
self.client = self.app.test_client()
class TestHttpBasicAuth(ApiTest):
api_key = 'secret'
def _enable_basic_auth(self):
self.app.config['API_KEYS'] = [self.api_key]
def _create_auth_headers(self, username, password=''):
data = base64.b64encode(bytes(':'.join([username, password]), 'ascii')).decode('ascii')
headers = [('Authorization', 'Basic %s' % data)]
return headers
def test_missing_credentials(self):
self._enable_basic_auth()
resp = self.client.get('/')
self.assertEqual(resp.status_code, httplib.UNAUTHORIZED)
def test_correct_credentials(self):
self._enable_basic_auth()
headers = self._create_auth_headers(self.api_key)
resp = self.client.get('/', headers=headers)
self.assertEqual(resp.status_code, httplib.OK)
def test_basic_auth_disabled(self):
resp = self.client.get('/')
self.assertEqual(resp.status_code, httplib.OK)
+2
View File
@@ -0,0 +1,2 @@
from api import create_app
app = create_app()