the application was rewritten a bit to be more testable
This commit is contained in:
+1
-48
@@ -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
@@ -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
|
||||||
@@ -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')
|
||||||
@@ -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
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
from .cluster import Cluster
|
||||||
+1
-1
@@ -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):
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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)
|
||||||
Reference in New Issue
Block a user