From b81188cb0d6aca81457418c153385abe364a5be6 Mon Sep 17 00:00:00 2001 From: Alexis Lahouze Date: Fri, 5 Jun 2015 18:15:50 +0200 Subject: [PATCH] Base of authentication. --- __init__.py | 0 api/controller/__init__.py | 3 +++ api/controller/accounts.py | 25 +++++++++++++++++++------ api/controller/users.py | 29 +++++++++++++++++++++++++++++ app.py | 4 ++++ forms/__init__.py | 0 forms/accounts.py | 9 +++++++++ 7 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 __init__.py create mode 100644 api/controller/users.py create mode 100644 forms/__init__.py create mode 100644 forms/accounts.py diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/api/controller/__init__.py b/api/controller/__init__.py index 252bd63..a27d8eb 100644 --- a/api/controller/__init__.py +++ b/api/controller/__init__.py @@ -1,4 +1,7 @@ import pkgutil +from flask.ext.httpauth import HTTPBasicAuth + +auth = HTTPBasicAuth() __all__ = [] diff --git a/api/controller/accounts.py b/api/controller/accounts.py index be78c76..c7ce08c 100644 --- a/api/controller/accounts.py +++ b/api/controller/accounts.py @@ -14,6 +14,7 @@ You should have received a copy of the GNU Affero General Public License along with Accountant. If not, see . """ +from . import auth from .. import api from ..model import db, session_scope from ..model.accounts import Account @@ -21,8 +22,10 @@ from ..model.entries import Entry from ..model.operations import Operation from flask import json, request from sqlalchemy import func, case, cast, extract, distinct +from forms.accounts import AccountIdForm, AccountForm @api.route("/accounts", methods=["GET"]) +@auth.login_required def get_accounts(): """ Returns accounts with their solds. @@ -47,6 +50,7 @@ def get_accounts(): } for i in query.all()]) @api.route("/accounts////") +@auth.login_required def get_account_status(account_id, year, month): with session_scope() as session: query = session.query( @@ -76,6 +80,7 @@ def get_account_status(account_id, year, month): }) @api.route("/accounts//months") +@auth.login_required def get_months(account_id): with session_scope() as session: query = session.query( @@ -89,6 +94,7 @@ def get_months(account_id): } for i in query.all()]) @api.route("/accounts", methods=["PUT"]) +@auth.login_required def add_account(): with session_scope() as session: account = Account(request.json['name'], request.json['authorized_overdraft']) @@ -99,18 +105,25 @@ def add_account(): @api.route("/accounts/", methods=["PUT"]) +@auth.login_required def update_account(account_id): - with session_scope() as session: - account = session.query(Account).filter(Account.id == account_id).first() + account_form = AccountForm() - account.name = request.json['name'] - account.authorized_overdraft = request.json['authorized_overdraft'] + if account_form.validate(): + with session_scope() as session: + account = session.query(Account).filter(Account.id == account_id).first() - session.merge(account) + account.name = request.json['name'] + account.authorized_overdraft = request.json['authorized_overdraft'] - return json.dumps("Account #%s updated." % account_id) + session.merge(account) + + return json.dumps("Account #%s updated." % account_id) + else: + return json.dumps({'ok': False, 'error_type': 'validation', 'errors': account_form.errors}) @api.route("/accounts/", methods=["DELETE"]) +@auth.login_required def delete_account(account_id): with session_scope() as session: account = session.query(Account).filter(Account.id == account_id).first() diff --git a/api/controller/users.py b/api/controller/users.py new file mode 100644 index 0000000..2abf1c5 --- /dev/null +++ b/api/controller/users.py @@ -0,0 +1,29 @@ +""" + This file is part of Accountant. + + Accountant is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Accountant is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with Accountant. If not, see . +""" + +from . import auth +from .. import api +from ..model import db, session_scope + +@auth.verify_password +def verify_password(username, password): + + if username == 'titi' and password == 'toto': + return True + # Update principal identity + + return False diff --git a/app.py b/app.py index 8a9716f..3c8d227 100644 --- a/app.py +++ b/app.py @@ -16,6 +16,7 @@ """ from api import api +#from api.controller import login_manager from api.model import db from flask import Flask from flask.ext.sqlalchemy import SQLAlchemy @@ -28,8 +29,11 @@ app = Flask(__name__, static_folder = None) app.config['SQLALCHEMY_DATABASE_URI'] = config.db_uri app.config['SQLALCHEMY_RECORD_QUERIES'] = config.debug +app.config['WTF_CSRF_ENABLED'] = False +app.config['SECRET_KEY'] = 'my_secret_key' db.init_app(app) +#login_manager.init_app(app) app.register_blueprint(frontend, url_prefix='') app.register_blueprint(api, url_prefix='/api') diff --git a/forms/__init__.py b/forms/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/forms/accounts.py b/forms/accounts.py new file mode 100644 index 0000000..3bb40da --- /dev/null +++ b/forms/accounts.py @@ -0,0 +1,9 @@ +from flask_wtf import Form +from wtforms import DecimalField, IntegerField, StringField + +class AccountIdForm(Form): + id = IntegerField() + +class AccountForm(AccountIdForm): + name = StringField() + authorized_overdraft = DecimalField()