@app.route('/login', methods=["POST"])
-@app.route('/login/<uid>')
-def login(uid=None):
+@app.route('/login/<iid>')
+def login(iid=None):
if request.method == "POST":
- uid = request.data.decode("utf-8")
- if uid is not None:
- db.add_user(uid)
- session["uid"] = uid
+ iid = request.data.decode("utf-8")
+ if iid is not None:
+ uid = db.get_uid(iid)
+
+ session["iid"] = iid
+
+ if uid is None:
+ db.add_user_identifier(iid, iid, "Default")
+ session["uid"] = iid
+ db.add_user(iid)
+ else:
+ session["uid"] = uid
return redirect(url_for('user'))
@app.route('/logout')
def logout():
session.pop('uid', None)
+ session.pop('iid', None)
return redirect(url_for('user'))
flavors=[_name for (_name, _ord) in db.flavors()],
count=counts.get("Coffee", 0),
count_mate=counts.get("Club-Mate", 0),
+ identifiers=db.list_user_identifiers(uid),
+ iid=session["iid"],
stamp=time.time()
)
# TODO: Replace stamp parameter with proper cache control HTTP
return redirect(url_for('user'))
+@app.route('/user/identifier/add', methods=["POST"])
+def user_add_identifier():
+ if request.method == "POST":
+ json = request.json
+ if "uid" in session and "id" in json:
+ db.add_user_identifier(session["uid"], json["id"], 'None')
+ return redirect(url_for('user'))
+
+
+@app.route('/user/identifier/rename', methods=["POST"])
+def user_rename_identifier():
+ if request.method == "POST":
+ json = request.json
+ if "uid" in session and all(key in json for key in ["id", "name"]):
+ db.rename_user_identifier(session["uid"], json["id"], json["name"])
+ return redirect(url_for('user'))
+
+
+@app.route('/user/identifier/disable', methods=["POST"])
+def user_disable_identifier():
+ if request.method == "POST":
+ json = request.json
+ if "uid" in session and "id" in json:
+ db.disable_user_identifier(session["uid"], json["id"])
+ return logout() # force logout
+
+
@app.route("/coffee/graph_flavors")
def coffee_graph_flavors():
days = request.args.get('days', default = 0, type = int)
def coffee_add():
if request.method == "POST":
json = request.json
- print("User '%(uid)s' had '%(flavor)s' at %(time)s" % json)
- db.add_coffee(json["uid"], json["flavor"], json["time"])
+
+ if "iid" in session and all(key in json for key in ["flavor", "time"]):
+ print("User '%s' had '%s' at %s" % (session["iid"], json["flavor"], json["time"]))
+ db.add_coffee(session["iid"], json["flavor"], json["time"])
return redirect(url_for('user'))
c.execute("insert or ignore into users (id) values (?)", (uid,))
close_db(conn)
+def add_user_identifier(uid, iid, name):
+ # Check if this identifier is not currently associated with different account
+ if not get_uid(iid):
+ conn, c = open_db()
+
+ # Try to remove old relation of identifier
+ # As 'delete or ignore' does not exist, workaround is used
+ res = c.execute("select * from identifiers where id = ? and status = ?", (iid, 0, ))
+
+ # This is True when some rows were found before; delete old relation
+ if res.fetchone():
+ res = c.execute("delete from identifiers where id = ? and status = ?", (iid, 0, ))
+
+ # Add new relation
+ res = c.execute("insert into identifiers (userid, id, name) values (?, ?, ?)", (uid, iid, name, ))
+
+ close_db(conn)
+
+def disable_user_identifier(uid, iid):
+ conn, c = open_db()
+ c.execute("update identifiers set status = ? where userid = ? and id = ?", (0, uid, iid, ))
+ close_db(conn)
+
def get_name(uid):
conn, c = open_db()
for name, in c.execute("select name from users where id = ?",(uid,)):
close_db(conn)
return None
+def get_uid(iid):
+ conn, c = open_db()
+ res = list(c.execute("""
+ select userid from identifiers where id = ? and status
+ """, (iid,)))
+ close_db(conn)
+
+ return res[0][0] if len(res) > 0 else None
def name_user(uid, name):
conn, c = open_db()
c.execute("update users set name = ? where id = ?", (name, uid))
close_db(conn)
+def rename_user_identifier(uid, iid, name):
+ conn, c = open_db()
+ c.execute("update identifiers set name = ? where userid = ? and id = ?", (name, uid, iid, ))
+ close_db(conn)
+
def list_users():
conn, c = open_db()
for row in c.execute("select * from users"):
print(row)
close_db(conn)
+def list_user_identifiers(uid):
+ conn, c = open_db()
+ res = list(c.execute("""
+ select * from identifiers where userid = ? and status
+ """, (uid,)))
+ close_db(conn)
+ return res
+
def add_coffee(uid, flavor, time=None):
conn, c = open_db()
query += " where date(time) between date('now', 'localtime', '-"+ str(days+start-1) +" days') and date('now', 'localtime', '-"+ str(start) +" days')"
if uid is not None:
- query += " and id = ?"
+ query += " and ids.userid = ? and ids.status"
variables.append(uid)
elif uid is not None:
- query += " where id = ?"
+ query += " where ids.userid = ? and ids.status"
variables.append(uid)
res = list(c.execute("""
select f.name, count(c.flavor) from flavors f
- left join (select * from coffees
+ left join (select * from coffees co left join identifiers ids on co.id=ids.id
"""+query+""") c
on f.name=c.flavor group by f.name
order by f.ord asc
select strftime('%s', ds.d),count(c.flavor),c.flavor from
(select num,date('now', 'localtime', -num || ' days') as d from days) ds
left join
- (select date(time, 'localtime') as time,flavor from coffees where id = ?) c
+ (select date(time, 'localtime') as time,flavor from coffees co left join identifiers ids on co.id = ids.id where ids.userid = ? and ids.status) c
on d = date(c.time) group by d, c.flavor
"""
, (uid,)))
clauses = []
if uid is not None:
- clauses.append("id = ?")
+ clauses.append("ids.userid = ? and ids.status")
args.append(uid)
if start is not None:
if stop is not None:
clauses.append("date(time, 'localtime') <= date('now', 'localtime', '-%d days')" % int(stop))
- return dict(c.execute("SELECT CASE WHEN flavor LIKE 'Club%' THEN 'Club-Mate' ELSE 'Coffee' END AS drink, COUNT() "
- "FROM coffees WHERE " + " AND ".join(clauses) + " GROUP BY drink", args))
+ return dict(c.execute("select case when flavor like 'Club%' then 'Club-Mate' else 'Coffee' end as drink, count(*) "
+ "from coffees co left join identifiers ids on co.id = ids.id where "
+ + " and ".join(clauses) + " group by drink", args))
insert or ignore into days values
(0),(1),(2),(3),(4),(5),(6)
;
+
+CREATE TABLE if not exists identifiers (
+ `userid` varchar ( 24 ) NOT NULL,
+ `id` varchar ( 24 ) PRIMARY KEY NOT NULL,
+ `name` varchar ( 24 ),
+ `status` INTEGER NOT NULL DEFAULT 1,
+ FOREIGN KEY(`userid`) REFERENCES `users`(`id`)
+);
// State variables
-var updateRemote = undefined; // defined iff remote server accessible
-var timeToLogout = undefined; // defined during logout countdown
+var updateRemote = undefined; // defined iff remote server accessible
+var timeToLogout = undefined; // defined during logout countdown
var logoutTimer;
var reloadTimer = undefined;
-var id_user; // ID of the user who is to be accounted for the next coffee
+var id_user; // ID of the user who is to be accounted for the next coffee
+var identifier_registration = false; // true if identifier is supposed to be registered for user
console.log("hello from flask");
//sendJSON("{\"type\":\"empty\"}");
case "empty":
break;
case "rfid":
- login(msg.uid);
+ if (identifier_registration) {
+ ajax("POST", "user/identifier/add", JSON.stringify({ id: msg.uid }), "user");
+
+ addIdentifier_finish();
+ } else {
+ login(msg.uid);
+ }
break;
case "keys":
- var flavor = getFlavor(msg.key);
- if (flavor !== "") {
- addCoffee(flavor, time);
+ if (!identifier_registration) {
+ var flavor = getFlavor(msg.key);
+ if (flavor !== "") {
+ addCoffee(flavor, time);
+ }
}
break;
case "ajax_failure":
ajax(msg.method, msg.route, msg.data, msg.id);
break;
}
+
sendLog(json);
}
ajax("GET", "logout", "", "user");
id_user = undefined;
timeToLogout = undefined;
+ identifier_registration = false;
}
function countingTimeLogout(count_time)
function addCoffee(flavor, time = new Date()) {
var data = JSON.stringify({
time: time.toISOString(),
- flavor: flavor,
- uid: id_user
+ flavor: flavor
});
if (id_user) {
ajax("POST", "coffee/add", data, "user");
}
}
+function addIdentifier_start() {
+ identifier_registration = true;
+ document.getElementById("addIdentifier").disabled = true;
+ document.getElementById("labelIdentifier").style.visibility = "visible";
+ document.getElementById("abortIdentifier").disabled = false;
+}
+
+function addIdentifier_finish() {
+ identifier_registration = false;
+ document.getElementById("addIdentifier").disabled = false;
+ document.getElementById("labelIdentifier").style.visibility = "hidden";
+ document.getElementById("abortIdentifier").disabled = true;
+}
+
+function disableIdentifier(id) {
+ ajax("POST", "user/identifier/disable", JSON.stringify({ id: id }), "user");
+}
+
+function renameIdentifier(i) {
+ var data = JSON.stringify({
+ id: document.getElementById("identifier_" + i).innerText,
+ name: document.getElementById("identifier_name_" + i).value
+ });
+
+ ajax("POST", "user/identifier/rename", data, "user");
+}
+
function sendLog(json) {
ajax("POST", "log", json, "log");
}
</p>
<p>
<form>
+ <label for="username">Username:</label>
<input id="username" type="text" name="name">
<input type="button" value="rename" onclick="renameUser()">
</form>
</p>
+ <form>
+ <table style="padding: 2px">
+ <tr>
+ <td colspan="4" align="center"><b>Identifiers:</b></td>
+ </tr>
+ {% for id in identifiers %}
+ <tr>
+ <td><input type="text" id="identifier_name_{{ loop.index }}" value="{{ id[2] }}" /></td>
+ <td {% if iid == id[1] %} style="font-weight: bold" {% endif %}>#<span id="identifier_{{ loop.index }}">{{ id[1] }}</span></td>
+ <td><input type="button" value="rename" onclick="renameIdentifier({{ loop.index }})" /></td>
+ <td><input type="button" value="remove" onclick="disableIdentifier({{ id[1] }})" /></td>
+ </tr>
+ {% endfor %}
+ <tr>
+ <td><input type="button" id="addIdentifier" value="add identifier" onclick="addIdentifier_start()" /></td>
+ <td colspan="2" style="visibility: hidden" id="labelIdentifier"><b>Use your identifier.</b></td>
+ <td><input type="button" id="abortIdentifier" value="abort" disabled onclick="addIdentifier_finish()" /></td>
+ </tr>
+ </table>
+ </form>
{% else %}
<p>Use your card/token to log in...</p>