From c89a4bc537ecf3acc87ff1dbdcb605b80f407465 Mon Sep 17 00:00:00 2001 From: subnixr Date: Sat, 30 Sep 2017 02:45:43 +0200 Subject: [PATCH] Agigunte definizioni tabelle --- .gitignore | 6 +- autogestionale/config.py | 4 +- autogestionale/database.py | 30 ++++++-- autogestionale/logging.py | 2 +- autogestionale/rest.py | 139 ++++++++++++++++++++++++++++++++++--- autogestionale/routes.py | 7 +- cli.py | 6 +- web.py | 9 ++- 8 files changed, 173 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index 3a2363b..320b8f5 100644 --- a/.gitignore +++ b/.gitignore @@ -93,10 +93,10 @@ ENV/ # Rope project settings .ropeproject -# macao-pos files +# macao-autogestionale files conf/ -pos.db -pos.log* +autogestionale.db +autogestionale.log* *.swp .idea diff --git a/autogestionale/config.py b/autogestionale/config.py index 896d1c0..a055862 100644 --- a/autogestionale/config.py +++ b/autogestionale/config.py @@ -3,9 +3,9 @@ from configparser import ConfigParser import yaml -APP_NAME = 'pos' +APP_NAME = 'autogestionale' -CONFIG_PATHS = ['conf/', '~/.config/pos', '/usr/local/etc/pos', '/etc/pos'] +CONFIG_PATHS = ['conf/', '~/.config/autogestionale', '/usr/local/etc/autogestionale', '/etc/autogestionale'] CONFIG_FILES = { 'core': 'core.ini', 'logging': 'logging.yaml' diff --git a/autogestionale/database.py b/autogestionale/database.py index 4e3c9b7..6942b9c 100644 --- a/autogestionale/database.py +++ b/autogestionale/database.py @@ -5,7 +5,7 @@ import sqlalchemy as sa import sqlalchemy.ext.declarative from sqlalchemy.exc import SQLAlchemyError from sqlalchemy import Table, Column, ForeignKey -from sqlalchemy import Integer, String, Boolean, DateTime +from sqlalchemy import Integer, String, Boolean, DateTime, Numeric from sqlalchemy.orm import relationship from sqlalchemy_utils import force_auto_coercion @@ -101,15 +101,35 @@ class User(Base): return u'{}'.format(self.uid) -class Event(Base): +class Entry(Base): __tablename__ = 'events' uid = Column(Integer, primary_key=True) + amount = Column(Numeric(precision=3)) + description = Column(String, nullable=False) + starts_at = Column(DateTime, nullable=False, default=datetime.now) + ends_at = Column(DateTime) + created_at = Column(DateTime, nullable=False, default=datetime.now) + + +class Event(Base): + __tablename__ = 'event' + uid = Column(Integer, primary_key=True) name = Column(String, nullable=False) starts_at = Column(DateTime, nullable=False, default=datetime.now) ends_at = Column(DateTime) created_at = Column(DateTime, nullable=False, default=datetime.now) - transactions = relationship('Transaction', lazy='joined') + entries = relationship('Entry', lazy='joined') + + +class Group(Base): + __tablename__ = 'group' + uid = Column(Integer, primary_key=True) + name = Column(String, nullable=False) + description = Column(String, nullable=False) + created_at = Column(DateTime, nullable=False, default=datetime.now) + + products = relationship('Event', lazy='joined') class ProductCategory(Base): @@ -145,12 +165,14 @@ class Transaction(Base): event = relationship('Event', lazy='joined') orders = relationship('Order', lazy='joined') + class Order(Base): __tablename__ = 'orders' uid = Column(Integer, primary_key=True) product_uid = Column(Integer, ForeignKey('products.uid'), nullable=False) quantity = Column(Integer, nullable=False) - transaction_uid = Column(Integer, ForeignKey('transactions.uid'), nullable=False) + transaction_uid = Column(Integer, ForeignKey( + 'transactions.uid'), nullable=False) product = relationship('Product', lazy='joined') transaction = relationship('Transaction', lazy='joined') diff --git a/autogestionale/logging.py b/autogestionale/logging.py index ed6eb6c..ccce1e3 100644 --- a/autogestionale/logging.py +++ b/autogestionale/logging.py @@ -1,7 +1,7 @@ import logging import logging.config -from pos.config import APP_NAME +from autogestionale.config import APP_NAME root = logging.getLogger(APP_NAME) diff --git a/autogestionale/rest.py b/autogestionale/rest.py index ac96a74..b4b2267 100644 --- a/autogestionale/rest.py +++ b/autogestionale/rest.py @@ -1,17 +1,134 @@ +from functools import wraps from aiohttp.web import json_response +from autogestionale.database import User, ProductCategory, Event -async def playlist_add(request): - uuid = request.match_info['uuid'] - try: - request.app['playlist'].put(uuid) +def needs(*needed): + def decorator(func): + @wraps(func) + async def wrapper(request): + request_json = await request.json() + if not all(k in request_json.keys() for k in needed): + return json_response({ + 'err': 'malformed_request', + 'msg': 'Missing one or more keys: {}.'.format( + ", ".join(needed)) + }, status=400) + else: + return func(request) - except DuplicateTrackError: - return json_response({ - 'err': 'duplicate', - 'msg': 'The track is already present in the playlist.' - }, status=400) + return wrapper + return decorator - else: - return json_response({}, status=200) +def auth_required(func): + @wraps(func) + async def wrapper(request): + db = request.app['db'] + headers = request.headers + + if 'Authorization' not in headers.keys(): + return json_response({'err': 'malformed_request', + 'msg': 'Missing Authorization header.'}, + status=400) + else: + remote_token = headers['Authorization'] + + with db.get_session() as session: + token = session.query(AccessToken) \ + .filter_by(token=remote_token) \ + .one_or_none() + + if not token: + return json_response({'err': 'unauthorized', + 'msg': 'The token is not valid.'}, + status=401) + elif not token.is_valid(): + return json_response({'err': 'forbidden', + 'msg': 'The token has expired.'}, + status=403) + else: + return await func(request) + + return wrapper + + +@needs('username', 'password') +async def token_create(request): + db = request.app['db'] + request_json = await request.json() + + username = request_json['username'] + password = request_json['password'] + + with db.get_session() as session: + user = session.query(User) \ + .filter_by(username=username) \ + .one_or_none() + + if not user or user.password != password: + return json_response({'err': 'invalid_credentials'}, + status=400) + + with db.get_session() as session: + token = AccessToken(user=user) + session.add(token) + + return json_response({ + 'token': token.token, + 'created_at': token.created_at.isoformat(), + 'expires_at': token.created_at.isoformat() + }) + + +@auth_required +async def token_destroy(request): + db = request.app['db'] + remote_token = request.headers['Authorization'] + + with db.get_session() as session: + token = session.query(AccessToken) \ + .filter_by(token=remote_token) \ + .one_or_none() + token.is_active = False + session.add(token) + + return json_response({}, status=200) + + +@auth_required +async def product_list(request): + db = request.app['db'] + + with db.get_session() as session: + categories = session.query(ProductCategory).all() + + return json_response({ + 'categories': [{ + 'uid': c.uid, + 'name': c.name, + 'products': [{ + 'uid': p.uid, + 'name': p.name, + 'price': p.price + } for p in c.products] + } for c in categories] + }) + + +async def event_list(request): + db = request.app['db'] + + with db.get_session() as session: + events = session.query(Event).all() + + return json_response({ + 'events': [{ + 'uid': evt.uid, + 'name': evt.name, + 'entries': [{ + 'uid': entr.uid, + 'amount': entr.amount + } for entr in evt.entries] + } for evt in events] + }) diff --git a/autogestionale/routes.py b/autogestionale/routes.py index 1d660c7..94c76c0 100644 --- a/autogestionale/routes.py +++ b/autogestionale/routes.py @@ -1,7 +1,12 @@ +from autogestionale.rest import event_list + + def setup_routes(app): - app.router.add_route('GET','/', info) + app.router.add_route('GET', '/', info) app.router.add_route('GET', '/login', info) app.router.add_route('POST', '/login', info) + app.router.add_route('GET', '/events', event_list) + async def info(request): return json_response({ diff --git a/cli.py b/cli.py index f7d9fb6..8060c53 100755 --- a/cli.py +++ b/cli.py @@ -3,9 +3,9 @@ import click from tabulate import tabulate from datetime import datetime -from pos.config import Config -from pos.logging import init_logging, get_logger -from pos.database import Database, User, Event, ProductCategory, Product,\ +from autogestionale.config import Config +from autogestionale.logging import init_logging, get_logger +from autogestionale.database import Database, User, Event, ProductCategory, Product,\ Transaction config = Config() diff --git a/web.py b/web.py index d404038..236616f 100755 --- a/web.py +++ b/web.py @@ -1,9 +1,9 @@ #! /usr/bin/env python3 -from pos.config import Config -from pos.logging import init_logging, get_logger -from pos.database import Database -from pos.routes import setup_routes +from autogestionale.config import Config +from autogestionale.logging import init_logging, get_logger +from autogestionale.database import Database +from autogestionale.routes import setup_routes import asyncio from aiohttp import web @@ -30,4 +30,3 @@ if __name__ == '__main__': web.run_app(app, host=config.core.get('GENERAL', 'Address'), port=config.core.getint('GENERAL', 'Port')) -