From afe0975e49cc795e36c98e62f0b662ad1759134e Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Fri, 5 Oct 2012 23:05:51 +0200 Subject: refactor scanner session code --- src/db.vala | 97 ++++++++++++------------------- src/main.vala | 64 +-------------------- src/scannersession.vala | 148 ++++++++++++++++++++++++++++++++++++++++++++++++ src/session.vala | 142 ---------------------------------------------- src/websession.vala | 142 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 327 insertions(+), 266 deletions(-) create mode 100644 src/scannersession.vala delete mode 100644 src/session.vala create mode 100644 src/websession.vala (limited to 'src') diff --git a/src/db.vala b/src/db.vala index 2ab5f7c..838b977 100644 --- a/src/db.vala +++ b/src/db.vala @@ -152,9 +152,6 @@ public class Database { private static Gee.HashMap queries = new Gee.HashMap(); private static Gee.HashMap statements = new Gee.HashMap(); - int32 user = 0; - bool logged_in = false; - public Database(string file) { int rc; @@ -207,18 +204,6 @@ public class Database { } } - public bool login(int32 id) { - this.user = id; - this.logged_in = true; - return true; - } - - public bool logout() { - this.user = 0; - this.logged_in = false; - return true; - } - public Gee.HashMap get_products() { var result = new Gee.HashMap(null, null); statements["products"].reset(); @@ -397,24 +382,20 @@ public class Database { return result; } - public bool buy(uint64 article) { - if(is_logged_in()) { - int rc = 0; - int64 timestamp = (new DateTime.now_utc()).to_unix(); + public bool buy(int32 user, uint64 article) { + int rc = 0; + int64 timestamp = (new DateTime.now_utc()).to_unix(); - statements["purchase"].reset(); - statements["purchase"].bind_text(1, "%d".printf(user)); - statements["purchase"].bind_text(2, "%llu".printf(article)); - statements["purchase"].bind_text(3, "%llu".printf(timestamp)); + statements["purchase"].reset(); + statements["purchase"].bind_int(1, user); + statements["purchase"].bind_text(2, "%llu".printf(article)); + statements["purchase"].bind_text(3, "%llu".printf(timestamp)); - rc = statements["purchase"].step(); - if(rc != Sqlite.DONE) - error("[internal error: %d]".printf(rc)); + rc = statements["purchase"].step(); + if(rc != Sqlite.DONE) + error("[internal error: %d]".printf(rc)); - return true; - } else { - return false; - } + return true; } public string get_product_name(uint64 article) { @@ -451,7 +432,7 @@ public class Database { } } - public int get_product_price(uint64 article) { + public Price get_product_price(int user, uint64 article) { int64 timestamp = (new DateTime.now_utc()).to_unix(); bool member = user != 0; @@ -476,38 +457,34 @@ public class Database { } } - public bool undo() { - if(is_logged_in()) { - uint64 pid = 0; - int rc = 0; - - statements["last_purchase"].reset(); - statements["last_purchase"].bind_text(1, "%d".printf(user)); - - rc = statements["last_purchase"].step(); - switch(rc) { - case Sqlite.ROW: - pid = uint64.parse(statements["last_purchase"].column_text(0)); - write_to_log("remove purchase of %llu", pid); - break; - case Sqlite.DONE: - write_to_log("undo not possible without purchases"); - return false; - default: - error("[internal error: %d]".printf(rc)); - } + public bool undo(int32 user) { + uint64 pid = 0; + int rc = 0; - statements["undo"].reset(); - statements["undo"].bind_text(1, "%d".printf(user)); + statements["last_purchase"].reset(); + statements["last_purchase"].bind_int(1, user); - rc = statements["undo"].step(); - if(rc != Sqlite.DONE) + rc = statements["last_purchase"].step(); + switch(rc) { + case Sqlite.ROW: + pid = uint64.parse(statements["last_purchase"].column_text(0)); + write_to_log("Remove purchase of %llu", pid); + break; + case Sqlite.DONE: + write_to_log("Error: undo not possible without purchases"); + return false; + default: error("[internal error: %d]".printf(rc)); - - return true; } - return false; + statements["undo"].reset(); + statements["undo"].bind_int(1, user); + + rc = statements["undo"].step(); + if(rc != Sqlite.DONE) + error("[internal error: %d]".printf(rc)); + + return true; } public bool restock(int user, uint64 product, uint amount, uint price) { @@ -563,10 +540,6 @@ public class Database { return true; } - public bool is_logged_in() { - return this.logged_in; - } - public bool check_user_password(int32 user, string password) { statements["password_get"].reset(); statements["password_get"].bind_int(1, user); diff --git a/src/main.vala b/src/main.vala index eff3a9d..b1c91d8 100644 --- a/src/main.vala +++ b/src/main.vala @@ -17,6 +17,7 @@ public Device dev; public Database db; public AudioPlayer audio; public CSVMemberFile csvimport; +public ScannerSession localsession; public MainLoop loop; public static int main(string[] args) { @@ -31,14 +32,13 @@ public static int main(string[] args) { Unix.signal_add(Posix.SIGTERM, handle_signals); Unix.signal_add(Posix.SIGINT, handle_signals); - dev = new Device(args[1], 9600, 8, 1); db = new Database("shop.db"); audio = new AudioPlayer(); loop = new MainLoop(); dev.received_barcode.connect((data) => { - if(interpret(data)) + if(localsession.interpret(data)) dev.blink(10); }); @@ -73,66 +73,6 @@ public void write_to_log(string format, ...) { stdout.printf(message + "\n"); } -public static bool interpret(string data) { - if(data.has_prefix("USER ")) { - string str_id = data.substring(5); - int32 id = int.parse(str_id); - - /* check if data has valid format */ - if(data != "USER %d".printf(id)) { - write_to_log("ungültige Benutzernummer: %s", data); - return false; - } - - if(db.is_logged_in()) { - write_to_log("Last User forgot to logout!"); - db.logout(); - } - - write_to_log("Login: %d", id); - return db.login(id); - } else if(data == "GUEST") { - if(db.is_logged_in()) { - write_to_log("Last User forgot to logout!"); - db.logout(); - } - - write_to_log("Login: Guest"); - return db.login(0); - } else if(data == "UNDO") { - if(!db.is_logged_in()) { - write_to_log("Can't undo if not logged in!"); - return false; - } else { - write_to_log("Undo last purchase!"); - return db.undo(); - } - } else if(data == "LOGOUT") { - if(db.is_logged_in()) { - write_to_log("Logout!"); - return db.logout(); - } - - return false; - } else { - uint64 id = uint64.parse(data); - - /* check if data has valid format */ - if(data != "%llu".printf(id)) { - write_to_log("ungültiges Produkt: %s", data); - return false; - } - - if(db.buy(id)) { - write_to_log("gekaufter Artikel: %s (%d,%02d €)", db.get_product_name(id), db.get_product_price(id)/100, db.get_product_price(id) % 100); - return true; - } else { - write_to_log("Kauf fehlgeschlagen!"); - return false; - } - } -} - bool handle_signals() { loop.quit(); return false; diff --git a/src/scannersession.vala b/src/scannersession.vala new file mode 100644 index 0000000..e286387 --- /dev/null +++ b/src/scannersession.vala @@ -0,0 +1,148 @@ +/* Copyright 2012, Sebastian Reichel + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +public class ScannerSession { + public int user { + get; + private set; + default = 0; + } + public string name { + get; + private set; + default = "Guest"; + } + public bool logged_in { + get; + private set; + default = false; + } + public bool disabled { + get; + private set; + default = false; + } + + public void logout() { + logged_in = false; + } + + public bool login(int user) { + this.user = user; + try { + this.name = db.get_username(user); + this.disabled = db.get_user_auth(user).disabled; + } catch(WebSessionError e) { + return false; + } + this.logged_in = true; + + return true; + } + + public ScannerSession() { + } + + public bool interpret(string scannerdata) { + if(scannerdata.has_prefix("USER ")) { + string str_id = scannerdata.substring(5); + int32 id = int.parse(str_id); + + /* check if scannerdata has valid format */ + if(scannerdata != "USER %d".printf(id)) { + audio.play("system/error.ogg"); + write_to_log("Error: Invalid User ID: %s", scannerdata); + return false; + } + + if(logged_in) { + write_to_log("Warning: Last user forgot to logout"); + logout(); + } + + if(login(id)) { + /* TODO: play audio */ + write_to_log("Login: %s (%d)", name, user); + return true; + } else { + audio.play("system/error.ogg"); + write_to_log("Error: Login failed (User ID = %d)", id); + return false; + } + } else if(scannerdata == "GUEST") { + if(logged_in) { + write_to_log("Warning: Last user forgot to logout"); + logout(); + } + + if(login(0)) { + /* TODO: play audio */ + write_to_log("Login: %s (%d)", name, user); + return true; + } else { + audio.play("system/error.ogg"); + write_to_log("Error: Login failed (User ID = 0)"); + return false; + } + } else if(scannerdata == "UNDO") { + if(!logged_in) { + audio.play("system/error.ogg"); + write_to_log("Error: Can't undo if not logged in!"); + return false; + } else { + if(db.undo(user)) { + /* TODO: play audio */ + write_to_log("Undo last purchase!"); + return true; + } else { + /* TODO: play audio */ + write_to_log("Error: Couldn't undo last purchase!"); + return false; + } + } + } else if(scannerdata == "LOGOUT") { + if(logged_in) { + /* TODO: play audio */ + write_to_log("Logout!"); + logout(); + return true; + } + + return false; + } else { + uint64 id = uint64.parse(scannerdata); + + /* check if scannerdata has valid format */ + if(scannerdata != "%llu".printf(id)) { + /* TODO: play audio */ + write_to_log("Error: invalid product: %s", scannerdata); + return false; + } + + if(db.buy(user, id)) { + /* TODO: play audio */ + var name = db.get_product_name(id); + var price = db.get_product_price(user, id); + write_to_log(@"article bought: $name ($price €)"); + return true; + } else { + /* TODO: play audio */ + write_to_log("Error: purchase failed!"); + return false; + } + } + } +} + diff --git a/src/session.vala b/src/session.vala deleted file mode 100644 index 5c562c6..0000000 --- a/src/session.vala +++ /dev/null @@ -1,142 +0,0 @@ -/* Copyright 2012, Sebastian Reichel - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -public errordomain WebSessionError { - SESSION_NOT_FOUND, - USER_NOT_FOUND -} - -public class WebSession { - public int user { - get; - private set; - default = 0; - } - public string name { - get; - private set; - default = "Guest"; - } - public bool failed { - get; - private set; - default = false; - } - public bool logged_in { - get; - private set; - default = false; - } - public bool superuser { - get; - private set; - default = false; - } - public bool disabled { - get; - private set; - default = false; - } - - private string generate_session_id(int user) { - const string charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; - string result = ""; - - Random.set_seed((uint32) time_t() + (uint32) Posix.getpid() + (uint32) user); - - for(int i=0; i<19; i++) { - int character_position = Random.int_range(0,charset.length); - string character = charset[character_position].to_string(); - result += character; - } - - /* TODO: make sure, that session id is unique */ - - return result; - } - - private void setup_auth(int user) { - var auth = db.get_user_auth(user); - this.disabled = auth.disabled; - this.superuser = auth.superuser; - this.logged_in = true; - } - - public void logout() { - if(logged_in) { - db.set_sessionid(user, ""); - superuser = false; - logged_in = false; - } - } - - public WebSession(Soup.Server server, Soup.Message msg, string path, GLib.HashTable? query, Soup.ClientContext client) { - var cookies = Soup.cookies_from_request(msg); - - /* Check for existing session */ - foreach(var cookie in cookies) { - if(cookie.name == "session") { - var sessionid = cookie.value; - - try { - user = db.get_user_by_sessionid(sessionid); - name = db.get_username(user); - setup_auth(user); - return; - } catch(WebSessionError e) { - /* invalid session, ignore */ - } - } - } - - /* check for login query */ - if(query == null || !query.contains("user") || !query.contains("password")) - return; - - /* get credentials */ - var userid = int.parse(query["user"]); - var password = query["password"]; - - /* check credentials */ - if(db.check_user_password(userid, password)) { - /* generate session */ - var sessionid = generate_session_id(userid); - - /* set session in database */ - db.set_sessionid(userid, sessionid); - - /* set session in reply cookie */ - cookies = new SList(); - var sessioncookie = new Soup.Cookie("session", sessionid, "", "/", -1); - sessioncookie.domain = null; - cookies.append(sessioncookie); - Soup.cookies_to_response(cookies, msg); - - /* login successful */ - user = userid; - try { - name = db.get_username(user); - } catch(WebSessionError e) { - name = "Unknown User"; - } - - setup_auth(user); - } else { - /* login failed */ - failed=true; - } - } -} - diff --git a/src/websession.vala b/src/websession.vala new file mode 100644 index 0000000..5c562c6 --- /dev/null +++ b/src/websession.vala @@ -0,0 +1,142 @@ +/* Copyright 2012, Sebastian Reichel + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +public errordomain WebSessionError { + SESSION_NOT_FOUND, + USER_NOT_FOUND +} + +public class WebSession { + public int user { + get; + private set; + default = 0; + } + public string name { + get; + private set; + default = "Guest"; + } + public bool failed { + get; + private set; + default = false; + } + public bool logged_in { + get; + private set; + default = false; + } + public bool superuser { + get; + private set; + default = false; + } + public bool disabled { + get; + private set; + default = false; + } + + private string generate_session_id(int user) { + const string charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; + string result = ""; + + Random.set_seed((uint32) time_t() + (uint32) Posix.getpid() + (uint32) user); + + for(int i=0; i<19; i++) { + int character_position = Random.int_range(0,charset.length); + string character = charset[character_position].to_string(); + result += character; + } + + /* TODO: make sure, that session id is unique */ + + return result; + } + + private void setup_auth(int user) { + var auth = db.get_user_auth(user); + this.disabled = auth.disabled; + this.superuser = auth.superuser; + this.logged_in = true; + } + + public void logout() { + if(logged_in) { + db.set_sessionid(user, ""); + superuser = false; + logged_in = false; + } + } + + public WebSession(Soup.Server server, Soup.Message msg, string path, GLib.HashTable? query, Soup.ClientContext client) { + var cookies = Soup.cookies_from_request(msg); + + /* Check for existing session */ + foreach(var cookie in cookies) { + if(cookie.name == "session") { + var sessionid = cookie.value; + + try { + user = db.get_user_by_sessionid(sessionid); + name = db.get_username(user); + setup_auth(user); + return; + } catch(WebSessionError e) { + /* invalid session, ignore */ + } + } + } + + /* check for login query */ + if(query == null || !query.contains("user") || !query.contains("password")) + return; + + /* get credentials */ + var userid = int.parse(query["user"]); + var password = query["password"]; + + /* check credentials */ + if(db.check_user_password(userid, password)) { + /* generate session */ + var sessionid = generate_session_id(userid); + + /* set session in database */ + db.set_sessionid(userid, sessionid); + + /* set session in reply cookie */ + cookies = new SList(); + var sessioncookie = new Soup.Cookie("session", sessionid, "", "/", -1); + sessioncookie.domain = null; + cookies.append(sessioncookie); + Soup.cookies_to_response(cookies, msg); + + /* login successful */ + user = userid; + try { + name = db.get_username(user); + } catch(WebSessionError e) { + name = "Unknown User"; + } + + setup_auth(user); + } else { + /* login failed */ + failed=true; + } + } +} + -- cgit v1.2.3