From 14a7c9ff8a785608c54cd38f50dc14686907889e Mon Sep 17 00:00:00 2001 From: Holger Cremer Date: Sun, 16 Apr 2017 01:32:07 +0200 Subject: adds some bootsrap documentation --- README | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README b/README index ef9c84d..6d8a54d 100644 --- a/README +++ b/README @@ -67,4 +67,6 @@ Usage: * setup ktt-shopsystem.cfg * start the curses UI in /etc/inittab * start the web UI via /etc/init.d/ + * create new user `TODO` + * Sets a user's password with `mdbus2 io.mainframe.shopsystem.Database /io/mainframe/shopsystem/database io.mainframe.shopsystem.Database.SetUserPassword 1 test` * call the invoice tool via cron -- cgit v1.2.3 From f891ecc9fbe159ec8a6cf321c43217d59f8cdf02 Mon Sep 17 00:00:00 2001 From: Holger Cremer Date: Sun, 16 Apr 2017 01:34:22 +0200 Subject: adds a new feature: a user can select it's sond theme in the web interface. If not selected, a random theme is used. --- sql/tables.sql | 2 +- src/audio/audio-interface.vala | 1 + src/audio/audio.vala | 4 +++ src/database/database.vala | 51 ++++++++++++++++++++++++++------- src/database/db-interface.vala | 3 ++ src/scanner-session/scannersession.vala | 5 +++- src/web/Makefile | 2 +- src/web/main.vala | 8 ++++-- src/web/web.vala | 27 +++++++++++++---- templates/css/base.css | 8 ++++++ templates/users/entry.html | 21 +++++++++++++- 11 files changed, 109 insertions(+), 23 deletions(-) diff --git a/sql/tables.sql b/sql/tables.sql index 0a6100f..a912740 100644 --- a/sql/tables.sql +++ b/sql/tables.sql @@ -3,7 +3,7 @@ CREATE TABLE IF NOT EXISTS products (id INTEGER PRIMARY KEY NOT NULL CHECK (id < CREATE TABLE IF NOT EXISTS sales (user INTEGER NOT NULL REFERENCES users, product INTEGER NOT NULL REFERENCES products, timestamp INTEGER NOT NULL DEFAULT 0); CREATE TABLE IF NOT EXISTS restock (user INTEGER NOT NULL REFERENCES users, product INTEGER NOT NULL REFERENCES products, amount INTEGER NOT NULL DEFAULT 0, timestamp INTEGER NOT NULL DEFAULT 0, price INTEGER NOT NULL DEFAULT 0, supplier INTEGER, best_before_date INTEGER); CREATE TABLE IF NOT EXISTS prices (product INTEGER NOT NULL REFERENCES products, valid_from INTEGER NOT NULL DEFAULT 0, memberprice INTEGER NOT NULL DEFAULT 0, guestprice INTEGER NOT NULL DEFAULT 0); -CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY NOT NULL, email TEXT, firstname TEXT NOT NULL, lastname TEXT NOT NULL, gender TEXT, street TEXT, plz INTEGER, city TEXT, pgp TEXT, disabled BOOLEAN NOT NULL DEFAULT 0, hidden BOOLEAN NOT NULL DEFAULT 0); +CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY NOT NULL, email TEXT, firstname TEXT NOT NULL, lastname TEXT NOT NULL, gender TEXT, street TEXT, plz INTEGER, city TEXT, pgp TEXT, disabled BOOLEAN NOT NULL DEFAULT 0, hidden BOOLEAN NOT NULL DEFAULT 0, sound_theme TEXT); CREATE TABLE IF NOT EXISTS authentication(user INTEGER PRIMARY KEY NOT NULL REFERENCES users, password TEXT, session CHARACTER(20), superuser BOOLEAN NOT NULL DEFAULT 0, auth_users BOOLEAN NOT NULL DEFAULT 0, auth_products BOOLEAN NOT NULL DEFAULT 0, auth_cashbox BOOLEAN NOT NULL DEFAULT 0, disabled BOOLEAN NOT NULL DEFAULT 0); CREATE TABLE IF NOT EXISTS supplier(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, city TEXT, postal_code TEXT, street TEXT, phone TEXT, website TEXT); CREATE TABLE IF NOT EXISTS cashbox_diff(id INTEGER PRIMARY KEY AUTOINCREMENT, user INTEGER NOT NULL REFERENCES users, amount INTEGER NOT NULL, timestamp INTEGER NOT NULL DEFAULT 0); diff --git a/src/audio/audio-interface.vala b/src/audio/audio-interface.vala index 89d4a6f..fe13af5 100644 --- a/src/audio/audio-interface.vala +++ b/src/audio/audio-interface.vala @@ -19,5 +19,6 @@ public interface AudioPlayer : Object { public abstract void play_system(string file) throws IOError; public abstract string get_random_user_theme() throws IOError; + public abstract string[] get_user_themes() throws IOError; public abstract void play_user(string theme, string type) throws IOError; } diff --git a/src/audio/audio.vala b/src/audio/audio.vala index a6e5007..1404969 100644 --- a/src/audio/audio.vala +++ b/src/audio/audio.vala @@ -74,6 +74,10 @@ public class AudioPlayerImplementation { return get_random_file(path + "user/"); } + public string[] get_user_themes() { + return get_files(path + "user/"); + } + public void play_user(string theme, string type) { p.set_state(Gst.State.NULL); var file = get_random_file(path + "user/" + theme+ "/" + type); diff --git a/src/database/database.vala b/src/database/database.vala index 74a554d..9596954 100644 --- a/src/database/database.vala +++ b/src/database/database.vala @@ -104,9 +104,11 @@ public class DataBase : Object { queries["session_set"] = "UPDATE authentication SET session=? WHERE user = ?"; queries["session_get"] = "SELECT user FROM authentication WHERE session = ?"; queries["username"] = "SELECT firstname, lastname FROM users WHERE id = ?"; + queries["user_theme_get"] = "SELECT CASE WHEN sound_theme IS NULL THEN ? ELSE sound_theme END FROM users WHERE id = ?"; + queries["user_theme_set"] = "UPDATE users SET sound_theme=? WHERE id = ?"; queries["password_get"] = "SELECT password FROM authentication WHERE user = ?"; queries["password_set"] = "UPDATE authentication SET password=? WHERE user = ?"; - queries["userinfo"] = "SELECT firstname, lastname, email, gender, street, plz, city, pgp, hidden, disabled FROM users WHERE id = ?"; + queries["userinfo"] = "SELECT firstname, lastname, email, gender, street, plz, city, pgp, hidden, disabled, sound_theme FROM users WHERE id = ?"; queries["userauth"] = "SELECT superuser, auth_users, auth_products, auth_cashbox FROM authentication WHERE user = ?"; queries["userauth_set"] = "UPDATE authentication SET auth_users = ?, auth_products = ?, auth_cashbox = ? WHERE user = ?"; queries["profit_by_product"] = "SELECT name, SUM(memberprice - (SELECT price FROM purchaseprices WHERE product = purch.product)) AS price FROM sales purch, prices, products WHERE purch.product = products.id AND purch.product = prices.product AND purch.user > 0 AND purch.timestamp > ? AND purch.timestamp < ? AND prices.valid_from = (SELECT valid_from FROM prices WHERE product = purch.product AND valid_from < purch.timestamp ORDER BY valid_from DESC LIMIT 1) GROUP BY name ORDER BY price;"; @@ -597,16 +599,17 @@ public class DataBase : Object { if(rc == Sqlite.ROW) { result.id = user; - result.firstname = statements["userinfo"].column_text(0); - result.lastname = statements["userinfo"].column_text(1); - result.email = statements["userinfo"].column_text(2); - result.gender = statements["userinfo"].column_text(3); - result.street = statements["userinfo"].column_text(4); - result.postcode = statements["userinfo"].column_text(5); - result.city = statements["userinfo"].column_text(6); - result.pgp = statements["userinfo"].column_text(7); - result.hidden = statements["userinfo"].column_int(8) == 1; - result.disabled = statements["userinfo"].column_int(9) == 1; + result.firstname = statements["userinfo"].column_text(0); + result.lastname = statements["userinfo"].column_text(1); + result.email = statements["userinfo"].column_text(2); + result.gender = statements["userinfo"].column_text(3); + result.street = statements["userinfo"].column_text(4); + result.postcode = statements["userinfo"].column_text(5); + result.city = statements["userinfo"].column_text(6); + result.pgp = statements["userinfo"].column_text(7); + result.hidden = statements["userinfo"].column_int(8) == 1; + result.disabled = statements["userinfo"].column_int(9) == 1; + result.soundTheme = statements["userinfo"].column_text(10); } else if(rc == Sqlite.DONE) { throw new DatabaseError.USER_NOT_FOUND("user not found"); } else { @@ -675,6 +678,32 @@ public class DataBase : Object { } } + public string get_user_theme(int user, string fallback) throws DatabaseError { + statements["user_theme_get"].reset(); + statements["user_theme_get"].bind_text(1, fallback); + statements["user_theme_get"].bind_int(2, user); + + if(statements["user_theme_get"].step() == Sqlite.ROW) { + return statements["user_theme_get"].column_text(0); + } else { + throw new DatabaseError.USER_NOT_FOUND("No such user available in database!"); + } + } + + public void set_userTheme(int user, string userTheme) throws DatabaseError { + statements["user_theme_set"].reset(); + if (userTheme == "") { + statements["user_theme_set"].bind_null(1); + } else { + statements["user_theme_set"].bind_text(1, userTheme); + } + statements["user_theme_set"].bind_int(2, user); + + int rc = statements["user_theme_set"].step(); + if(rc != Sqlite.DONE) + throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc); + } + public InvoiceEntry[] get_invoice(int user, int64 from=0, int64 to=-1) throws DatabaseError { InvoiceEntry[] result = {}; diff --git a/src/database/db-interface.vala b/src/database/db-interface.vala index f5bfada..6142fcf 100644 --- a/src/database/db-interface.vala +++ b/src/database/db-interface.vala @@ -32,11 +32,13 @@ public interface Database : Object { public abstract bool check_user_password(int32 user, string password) throws IOError; public abstract void set_user_password(int32 user, string password) throws IOError, DatabaseError; public abstract void set_sessionid(int user, string sessionid) throws IOError, DatabaseError; + public abstract void set_userTheme(int user, string userTheme) throws IOError, DatabaseError; public abstract int get_user_by_sessionid(string sessionid) throws IOError, DatabaseError; public abstract UserInfo get_user_info(int user) throws IOError, DatabaseError; public abstract UserAuth get_user_auth(int user) throws IOError, DatabaseError; public abstract void set_user_auth(UserAuth auth) throws IOError, DatabaseError; public abstract string get_username(int user) throws IOError, DatabaseError; + public abstract string get_user_theme(int user, string fallback) throws IOError, DatabaseError; public abstract InvoiceEntry[] get_invoice(int user, int64 from=0, int64 to=-1) throws IOError, DatabaseError; public abstract int64 get_first_purchase(int user) throws IOError; public abstract int64 get_last_purchase(int user) throws IOError; @@ -121,6 +123,7 @@ public struct UserInfo { public string pgp; public bool disabled; public bool hidden; + public string soundTheme; public bool equals(UserInfo x) { if(id != x.id) return false; diff --git a/src/scanner-session/scannersession.vala b/src/scanner-session/scannersession.vala index 666f2ac..37b4ad4 100644 --- a/src/scanner-session/scannersession.vala +++ b/src/scanner-session/scannersession.vala @@ -67,7 +67,10 @@ public class ScannerSessionImplementation { this.logged_in = true; try { - this.theme = audio.get_random_user_theme(); + this.theme = db.get_user_theme(user, ""); + if (this.theme == "") { + this.theme = audio.get_random_user_theme(); + } } catch(IOError e) { this.theme = "beep"; } diff --git a/src/web/Makefile b/src/web/Makefile index 17140c3..e6094f6 100644 --- a/src/web/Makefile +++ b/src/web/Makefile @@ -1,7 +1,7 @@ all: web @echo > /dev/null -web: main.vala web.vala websession.vala csv.vala template.vala ../database/db-interface.vala ../pgp/pgp-interface.vala ../price.vapi ../config/config-interface.vala +web: main.vala web.vala websession.vala csv.vala template.vala ../database/db-interface.vala ../pgp/pgp-interface.vala ../price.vapi ../config/config-interface.vala ../audio/audio-interface.vala valac -X -w -o $@ --vapidir=../../vapi --enable-experimental --pkg gee-0.8 --pkg gio-2.0 --pkg libsoup-2.4 --pkg posix $^ clean: diff --git a/src/web/main.vala b/src/web/main.vala index 86caea5..22c586b 100644 --- a/src/web/main.vala +++ b/src/web/main.vala @@ -17,6 +17,7 @@ Database db; public CSVMemberFile csvimport; public PGP pgp; public Config cfg; +public AudioPlayer audio; string templatedir; public static int main(string[] args) { @@ -26,9 +27,10 @@ public static int main(string[] args) { uint port = 8080; try { - db = Bus.get_proxy_sync(BusType.SESSION, "io.mainframe.shopsystem.Database", "/io/mainframe/shopsystem/database"); - pgp = Bus.get_proxy_sync(BusType.SESSION, "io.mainframe.shopsystem.PGP", "/io/mainframe/shopsystem/pgp"); - cfg = Bus.get_proxy_sync(BusType.SESSION, "io.mainframe.shopsystem.Config", "/io/mainframe/shopsystem/config"); + db = Bus.get_proxy_sync(BusType.SESSION, "io.mainframe.shopsystem.Database", "/io/mainframe/shopsystem/database"); + pgp = Bus.get_proxy_sync(BusType.SESSION, "io.mainframe.shopsystem.PGP", "/io/mainframe/shopsystem/pgp"); + cfg = Bus.get_proxy_sync(BusType.SESSION, "io.mainframe.shopsystem.Config", "/io/mainframe/shopsystem/config"); + audio = Bus.get_proxy_sync(BusType.SESSION, "io.mainframe.shopsystem.AudioPlayer", "/io/mainframe/shopsystem/audio"); templatedir = cfg.get_string("WEB", "filepath"); port = cfg.get_integer("WEB", "port"); diff --git a/src/web/web.vala b/src/web/web.vala index fb03e4b..c63db73 100644 --- a/src/web/web.vala +++ b/src/web/web.vala @@ -359,19 +359,36 @@ public class WebServer { t.replace("ISADMIN2", "disabled=\"disabled\""); } + var userThemeList = audio.get_user_themes(); + var message = ""; var postdata = Soup.Form.decode_multipart(msg, null, null, null, null); if(postdata != null && postdata.contains("password1") && postdata.contains("password2")) { if(postdata["password1"] != postdata["password2"]) { - t.replace("MESSAGE", "
Error! Passwords do not match!
"); + message = "
Error! Passwords do not match!
"; } else if(postdata["password1"] == "") { - t.replace("MESSAGE", "
Error! Empty Password not allowed!
"); + message = "
Error! Empty Password not allowed!
"; } else { db.set_user_password(id, postdata["password1"]); - t.replace("MESSAGE", "
Password Changed!
"); + message = "
Password Changed!
"; } - } else { - t.replace("MESSAGE", ""); + } else if(postdata != null && postdata.contains("soundTheme")) { + if (postdata["soundTheme"] in userThemeList) { + userinfo.soundTheme = postdata["soundTheme"]; + db.set_userTheme(id, postdata["soundTheme"]); + } else { + userinfo.soundTheme = null; + db.set_userTheme(id, ""); + } + message = "
Sound theme changed.
"; + } + t.replace("MESSAGE", message); + + var soundThemes = ""; + foreach(var theme in userThemeList) { + var selected = userinfo.soundTheme == theme ? "selected" : ""; + soundThemes += @""; } + t.replace("SOUND_THEMES", soundThemes); msg.set_response("text/html", Soup.MemoryUse.COPY, t.data); msg.set_status(200); diff --git a/templates/css/base.css b/templates/css/base.css index 6192406..e273808 100644 --- a/templates/css/base.css +++ b/templates/css/base.css @@ -76,6 +76,14 @@ text-align: right !important; } +table.user-entry th { + min-width: 150px; +} + +table.user-entry td { + min-width: 350px; +} + @media print { .navbar-fixed-top { display: none !important; diff --git a/templates/users/entry.html b/templates/users/entry.html index d72b304..60d2dd3 100644 --- a/templates/users/entry.html +++ b/templates/users/entry.html @@ -3,7 +3,7 @@ {{{MESSAGE}}}
- +
@@ -22,6 +22,24 @@ + + + + +
ID{{{UID}}}
Barcode
Street{{{STREET}}}
PLZ{{{POSTALCODE}}}
City{{{CITY}}}
Settings
Sound theme + + + + +
+ See Preview +
+ +
+ @@ -41,6 +59,7 @@ code39_init(); code39_draw("USER {{{UID}}}", true); + $('#authproductsbutton').on('click', function (e) { var req = $.getJSON( "/users/{{{UID}}}/toggle_auth_products", -- cgit v1.2.3
Status Information
Disabled{{{DISABLED}}}
Hidden{{{HIDDEN}}}