diff --git a/app/db/__init__.py b/app/db/__init__.py deleted file mode 100644 index f999b01..0000000 --- a/app/db/__init__.py +++ /dev/null @@ -1,76 +0,0 @@ -""" - - -@author: jlusiardi -""" - -from datetime import datetime -import sqlite3 - - -class Db(object): - """ - classdocs - """ - - def __init__(self, db_file): - """ - Constructor - """ - self.db = sqlite3.connect(db_file) - - def __del__(self): - self.db.close() - - def get_all_pit_stops(self): - return self._perform_query('select * from pitstops order by id asc') - - def get_last_pit_stop(self): - pitstops = self._perform_query('select * from pitstops order by id desc limit 1') - if len(pitstops) == 0: - return {'date': datetime.strftime(datetime.now(), '%Y-%m-%d'), 'odometer': 0, 'litres': 0} - return pitstops[0] - - def add_pit_stop(self, date, odometer, litres): - self.db.execute('insert into pitstops (date, odometer, litres) values (?, ?, ?)', [date, odometer, litres]) - self.db.commit() - - def get_salt_for_user(self, user): - salt = self._perform_query_param('select salt from users where name = ?', [user]) - if len(salt) == 0: - return None - return salt[0]['salt'] - - def check_password_for_user(self, user, password): - user = self._perform_query_param('select * from users where name = ? and password = ?', [user, password]) - if len(user) == 0: - return False - return True - - def _perform_query_param(self, query, data): - cursor = self.db.execute(query, data) - names = list(map(lambda x: x[0], cursor.description)) - result = [] - for row in cursor.fetchall(): - row_result = {} - for index in range(0, len(names)): - row_result[names[index]] = row[index] - result.append(row_result) - return result - - def _perform_query(self, query): - cursor = self.db.execute(query) - names = list(map(lambda x: x[0], cursor.description)) - result = [] - for row in cursor.fetchall(): - row_result = {} - for index in range(0, len(names)): - row_result[names[index]] = row[index] - result.append(row_result) - return result - - def init_db(self, resource): - with resource as f: - sql_commands = f.read() - self.db.cursor().executescript(sql_commands) - self.db.commit() diff --git a/app/db/__pycache__/__init__.cpython-34.pyc b/app/db/__pycache__/__init__.cpython-34.pyc index 12fb500..fcd275f 100644 Binary files a/app/db/__pycache__/__init__.cpython-34.pyc and b/app/db/__pycache__/__init__.cpython-34.pyc differ diff --git a/app/main.py b/app/main.py index 16a8fdb..de85eb0 100644 --- a/app/main.py +++ b/app/main.py @@ -1,32 +1,75 @@ +from datetime import date from datetime import datetime from flask import Flask from flask import render_template, make_response from flask import request, redirect, g from flask import url_for -from flask import Response +from flask_sqlalchemy import SQLAlchemy +import uuid import hashlib -import os.path import time - from functools import wraps -import db - app = Flask(__name__) DATABASE = '/data/rollerverbrauch.db' +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'+DATABASE +sqldb = SQLAlchemy(app) + DEBUG = True SECRET_KEY = 'development key' app.config.from_object(__name__) +class User(sqldb.Model): + id = sqldb.Column(sqldb.Integer, primary_key=True) + username = sqldb.Column(sqldb.String(80), unique=True) + email = sqldb.Column(sqldb.String(120), unique=True) + salt = sqldb.Column(sqldb.String(8)) + password_hash = sqldb.Column(sqldb.String(64)) + + def __init__(self, username, email, password): + self.username = username + self.email = email + self.salt = uuid.uuid4().hex + m = hashlib.sha256(password.encode('utf-8')) + m = hashlib.sha256((m.hexdigest() + self.salt).encode('utf-8')).hexdigest() + self.password_hash = m + pass + + def __repr__(self): + return '' % self.username + + +class Pitstop(sqldb.Model): + id = sqldb.Column(sqldb.Integer, primary_key=True) + date = sqldb.Column(sqldb.Date) + odometer = sqldb.Column(sqldb.Integer) + litres = sqldb.Column(sqldb.Numeric(5,2)) + + def __init__(self, odometer, litres, date): + self.odometer = odometer + self.litres = litres + self.date = date + + def __repr__(self): + return '' % (self.odometer, self.litres) + +sqldb.create_all() +if User.query.filter_by(username='jlusiardi').first() is None: + user1 = User('jlusiardi', 'joachim@lusiardi.de', 'pitstops') + sqldb.session.add(user1) + sqldb.session.commit() + + def check_auth(username, password): - salt = g.db2.get_salt_for_user(username) - if salt is None: + user = User.query.filter_by(username=username).first() + if user is None: return False + salt = user.salt m = hashlib.sha256(password.encode('utf-8')) m = hashlib.sha256((m.hexdigest()+salt).encode('utf-8')) digest = m.hexdigest() - ok = g.db2.check_password_for_user(username, digest) + ok = (User.query.filter_by(username=username, password_hash=digest).first() is not None) if not ok: app.logger.error("digest: " + digest) return ok @@ -50,7 +93,6 @@ def requires_auth(f): @app.before_request def before_request(): - g.db2 = db.Db(app.config['DATABASE']) g.data = {} @@ -68,15 +110,17 @@ def index(): @app.route('/pitstops', methods=['POST']) @requires_auth def create_pit_stop(): - last_pitstop = g.db2.get_last_pit_stop() + last_pitstop = Pitstop.query.order_by(Pitstop.date.desc()).first() + if last_pitstop is None: + last_pitstop = Pitstop(0, 0, None) error_msg = {} - date = request.form['date'] + date_of_pitstop = request.form['date'] try: - date = datetime.strptime(date, '%Y-%m-%d').strftime('%Y-%m-%d') + date_of_pitstop = datetime.strptime(date_of_pitstop, '%Y-%m-%d').strftime('%Y-%m-%d') except ValueError: error_msg['date'] = 'invalid date, only YYYY-MM-DD is allowed' - date = request.form['date'] + date_of_pitstop = request.form['date'] odometer = request.form['odometer'] try: @@ -84,7 +128,7 @@ def create_pit_stop(): except ValueError: error_msg['odometer'] = 'Illegal Value, only Integers allowed' odometer = None - if odometer is not None and odometer <= last_pitstop['odometer']: + if odometer is not None and odometer <= last_pitstop.odometer: error_msg['odometer'] = 'Illegal Value, new Value must be bigger as given value' odometer = request.form['odometer'] if odometer is None: @@ -104,18 +148,25 @@ def create_pit_stop(): # error checking here if len(error_msg) > 0: - data = {'last': {'date': date, 'odometer': odometer, 'litres': litres}, 'error': error_msg} + data = {'last': {'date': date_of_pitstop, 'odometer': odometer, 'litres': litres}, 'error': error_msg} return render_template('newPitStopForm.html', data=data) - g.db2.add_pit_stop(date, odometer, litres) - + new_stop = Pitstop(odometer, litres, datetime.strptime(date_of_pitstop, '%Y-%m-%d')) + sqldb.session.add(new_stop) + sqldb.session.commit() + return redirect(url_for('get_pit_stops')) @app.route('/pitstops/createForm', methods=['GET']) @requires_auth def create_pit_stop_form(): - values = g.db2.get_last_pit_stop() + last_stop = Pitstop.query.order_by(Pitstop.date.desc()).first() + if last_stop is None: + last_stop = Pitstop(0, 0, date(1970, 1, 1)) + values = dict() + values['odometer'] = last_stop.odometer + values['litres'] = last_stop.litres values['date'] = time.strftime("%Y-%m-%d") g.data['last'] = values g.data['error'] = None @@ -125,7 +176,7 @@ def create_pit_stop_form(): @app.route('/pitstops', methods=['GET']) @requires_auth def get_pit_stops(): - data = prepare_pit_stops(g.db2.get_all_pit_stops()) + data = prepare_pit_stops(Pitstop.query.all()) g.data['pitstops'] = data return render_template('pitstops.html', data=g.data) @@ -139,7 +190,7 @@ def get_manual(): @app.route('/statistics', methods=['GET']) @requires_auth def get_statistics(): - pitstops = g.db2.get_all_pit_stops() + pitstops = Pitstop.query.all() count = len(pitstops) distance = 0 sum_litres = 0 @@ -150,12 +201,12 @@ def get_statistics(): if count > 0: sum_litres = 0 for pitstop in pitstops: - sum_litres += pitstop['litres'] + sum_litres += pitstop.litres average_litres_fuelled = sum_litres/count if count > 1: - distance = pitstops[-1]['odometer'] - pitstops[0]['odometer'] + distance = pitstops[-1].odometer - pitstops[0].odometer average_distance = distance/(count - 1) - average_litres_used = 100 * (sum_litres-pitstops[0]['litres'])/distance + average_litres_used = 100 * (sum_litres-pitstops[0].litres)/distance g.data['distance'] = distance g.data['count'] = count g.data['litres'] = sum_litres @@ -165,20 +216,24 @@ def get_statistics(): return render_template('statistics.html', data=g.data) -def prepare_pit_stops(pitstops): - for index in range(1, len(pitstops)): - last = pitstops[index - 1] - curr = pitstops[index] +def prepare_pit_stops(pss): + pitstops = [] + for pitstop_index in range(0, len(pss)): + p = dict() + p['odometer'] = pss[pitstop_index].odometer + p['litres'] = pss[pitstop_index].litres + p['date'] = pss[pitstop_index].date + pitstops.append(p) + for pitstop_index in range(1, len(pitstops)): + last = pitstops[pitstop_index - 1] + curr = pitstops[pitstop_index] curr['distance'] = curr['odometer'] - last['odometer'] curr['average'] = 100 * curr['litres']/curr['distance'] - last_date = datetime.strptime(last['date'], '%Y-%m-%d') - curr_date = datetime.strptime(curr['date'], '%Y-%m-%d') + last_date = last['date'] + curr_date = curr['date'] curr['days'] = (curr_date - last_date).days pitstops.reverse() return pitstops if __name__ == '__main__': - if not os.path.isfile(DATABASE) or os.stat(DATABASE).st_size == 0: - db = db.Db(app.config['DATABASE']) - db.init_db(app.open_resource('schema.sql', mode='r')) app.run(debug=True, host='0.0.0.0') diff --git a/app/requirements.txt b/app/requirements.txt index 0f0841d..fb675a9 100644 --- a/app/requirements.txt +++ b/app/requirements.txt @@ -1,2 +1,2 @@ -#db-sqlite3 -Flask \ No newline at end of file +Flask +Flask-SQLAlchemy