From a59f02e21b55eccdcf21e48545fa5dfa6a9a67d0 Mon Sep 17 00:00:00 2001 From: Thomas Hooge Date: Sat, 8 Nov 2025 09:04:59 +0100 Subject: [PATCH] Install and database setup improvements --- INSTALL | 30 ++++++++------ db/mariadb_sample.sql | 78 ++++++++++++++++++++++++++++++++++++ db/minimal.sql | 26 ++++++++++++ db/minimal_en.sql | 26 ++++++++++++ yms/vessel.py | 89 ++++++++++++++++++++++++++++++++++++++++++ yms48.png | Bin 0 -> 2837 bytes 6 files changed, 236 insertions(+), 13 deletions(-) create mode 100644 db/mariadb_sample.sql create mode 100644 yms/vessel.py create mode 100644 yms48.png diff --git a/INSTALL b/INSTALL index b2eff33..896b72a 100644 --- a/INSTALL +++ b/INSTALL @@ -31,12 +31,12 @@ the privileges for accessing and modifying it. Create database-user for application with minimum necessary rights. - CREATE USER 'ymsgui'@'localhost' IDENTIFIED BY '********'; - GRANT SELECT, INSERT, UPDATE, DELETE ON yms.* TO 'ymsgui'@'localhost'; + CREATE USER 'ymsweb'@'localhost' IDENTIFIED BY '********'; + GRANT SELECT, INSERT, UPDATE, DELETE ON yms.* TO 'ymsweb'@'localhost'; 3. Run database import -Import the mariadb.sql file into your database, which will create the tables +Import the mariadb.sql file into your database, which will create the tables. mariadb yms < mariadb.sql @@ -54,21 +54,23 @@ Optional import some sample data mariadb yms < mariadb_sample.sql 4. Initialize document storage -Customize path and accessrights to your needs - +Customize path and access rights to your needs + mkdir /var/local/yms mkdir /var/local/yms/thumb chown -R www-data /var/local/yms chmod -R 750 /var/local/yms -5. Upload webgui files +5. Install webgui + +5.1 Upload webgui files Upload all files and directories (except the install directory) to your webserver. Disallow access to include files (.inc). There is an example _htaccess file. -6. Create and edit webgui config file +5.2. Create and edit webgui config file Rename sample configfile config.php-sample: @@ -76,24 +78,26 @@ Rename sample configfile config.php-sample: Open config.inc in a text editor and fill in your database details. -7. Check file access rights for security +5.3. Check file access rights for security Configfile should be readable by webserver but not writeable. chmod 640 config.inc chgrp www-data config.inc -8. Setup local GUI +6. Setup local GUI Create a local database user with same name as your computer user and allow database acces with current unix credentials: - mysql> CREATE USER 'ymsgui'@'localhost' IDENTIFIED BY 'geheim'; - mysql> ALTER USER ymsgui@localhost IDENTIFIED VIA unix_socket; + mysql> CREATE USER 'ymsgui'@'localhost' IDENTIFIED VIA unix_socket; -Start ymdgui.py, default configuration file is automatically created +Start ymsgui.py, default configuration file is automatically created -9. Start using YMS +7. Start using YMS +Use webgui: Start your browser and login to YMS with the default username/password: captain/captain +Use local client: +Start ymsgui.py diff --git a/db/mariadb_sample.sql b/db/mariadb_sample.sql new file mode 100644 index 0000000..b571033 --- /dev/null +++ b/db/mariadb_sample.sql @@ -0,0 +1,78 @@ +/* Generic data suitable for all kind of boats + * SPDX-License-Identifier: WTFPL + */ + +INSERT INTO user (userid, login, pass, displayname, role) VALUES +(2, 'helmsman', '$2y$10$4keuVm.WD/JeRmAqp2h4MeSxxKITsKv2q07XZrxPUuT/V80CTPbje', 'Helmsman', 'helmsman'), +(3, 'sailor', '$2y$10$4keuVm.WD/JeRmAqp2h4MeSxxKITsKv2q07XZrxPUuT/V80CTPbje', 'Sailor', 'sailor'); + +INSERT INTO settings (userid, sno, valint) VALUES +(2, 1, 1), -- Vessel 1 for helmsman +(3, 1, 1); -- Vessel 1 for sailor + +INSERT INTO dropdown (ddid, ddval, ddtext) VALUES +(1, 1, 'Einrumpf'), -- Mono +(1, 2, 'Katamaran'), +(1, 3, 'Trimaran'); + +INSERT INTO dropdown (ddid, ddval, ddtext) VALUES +(2, 3, 'Dienstleister'), -- Service +(2, 4, 'Werft'), -- Shipyard +(2, 5, 'Segelmacher'), -- Sailmaker +(2, 6, 'Yachthafen'), -- Marina + +INSERT INTO dropdown (ddid, ddval, ddtext) VALUES +(3, 2, 'Bilge'), +(3, 3, 'Schwalbennest'); + +INSERT INTO dropdown (ddid, ddval, ddtext) VALUES +(4, 1, 'Rumpf'), +(4, 2, 'Decks'), +(4, 3, 'Rigg'), +(4, 4, 'Segel'), +(4, 5, 'Motor'), +(4, 6, 'Elektrik'), +(4, 7, 'Elektronik'), +(4, 8, 'Navigation'), +(4, 9, 'Pantry'); + +INSERT INTO dropdown (ddid, ddval, ddtext) VALUES +(5, 1, 'Allgemein'), +(5, 2, 'Getränke'); + +INSERT INTO dropdown (ddid, ddval, ddtext) VALUES +(6, 1, 'kg'), +(6, 2, 'Liter'), +(6, 3, 'Stück'), +(6, 4, 'Packung'), +(6, 5, 'Dose'), +(6, 6, 'Flasche'); + +INSERT INTO dropdown (ddid, ddval, ddtext) VALUES +(7, 1, 'ATO'), +(7, 2, 'Streifensicherung'), +(7, 3, 'Feinsicherung (GS)'), +(7, 4, 'Torpedosicherung'), +(7, 5, 'T-Sicherung'); + +INSERT INTO dropdown (ddid, ddval, ddtext) VALUES +(8, 1, 'mm'), +(8, 2, 'cm'), +(8, 3, 'g'), +(8, 4, 'kg'); + +INSERT INTO storage (sid, vid, sname, stype, x, y, z, remarks) VALUES +(0, 1, 'An Bord', 0, 0, 0, 0, 'Alles wo der Ort nicht spezifiziert werden kann'); + +/* Eine Liste mit häufig verwendeten Herstellern + comptype=2 +*/ + +INSERT INTO company (comptype, compname) VALUES +(2, 'Garmin'), +(2, 'Watcheye'), +(2, 'Digital Yacht'), +(2, 'B&G'), +(2, 'Raymarine'), +(2, 'Harken'), +(2, 'Selden'); diff --git a/db/minimal.sql b/db/minimal.sql index 922fa14..9d29b7f 100644 --- a/db/minimal.sql +++ b/db/minimal.sql @@ -16,6 +16,32 @@ INSERT INTO settings (userid, sno, valint) VALUES (0, 1, 0), -- Keine Bootszuordnung für SYSTEM (1, 1, 0); -- Keine Bootszuordnung für Benutzer "captain" +/* setting descriptions */ +INSERT INTO settings (userid, sno, valstr) VALUES +(-1, 1, 'vessel id'), +(-1, 100, 'equipment sorting order'), +(-1, 101, 'inventory sorting order'), +(-1, 102, 'provision sorting order'), +(-1, 103, 'storage sorting order'), +(-1, 104, 'maintenance sorting order'), +(-1, 105, 'project sorting order'), +(-1, 106, 'task sorting order'), +(-1, 107, 'measurement sorting order'), +(-1, 108, 'company sorting order'), +(-1, 109, 'document sorting order'), +(-1, 110, 'tag sorting order'), +(-1, 200, 'equipment filter json'), +(-1, 201, 'inventory filter json'), +(-1, 202, 'provision filter json'), +(-1, 203, 'storage filter json'), +(-1, 204, 'maintenance filter json'), +(-1, 205, 'project filter json'), +(-1, 206, 'task filter json'), +(-1, 207, 'measurement filter json'), +(-1, 208, 'company filter json'), +(-1, 209, 'document filter json'), +(-1, 210, 'tag filter json'); + /* Liste der Listen wird immer benötigt */ INSERT INTO dropdown (ddid, ddval, ddtext) VALUES (0, 0, 'Liste der Listen'), diff --git a/db/minimal_en.sql b/db/minimal_en.sql index 6fa427f..cb81fc4 100644 --- a/db/minimal_en.sql +++ b/db/minimal_en.sql @@ -16,6 +16,32 @@ INSERT INTO settings (userid, sno, valint) VALUES (0, 1, 0), -- No vessel for SYSTEM (1, 1, 0); -- No vessel for captain +/* setting descriptions */ +INSERT INTO settings (userid, sno, valstr) VALUES +(-1, 1, 'vessel id'), +(-1, 100, 'equipment sorting order'), +(-1, 101, 'inventory sorting order'), +(-1, 102, 'provision sorting order'), +(-1, 103, 'storage sorting order'), +(-1, 104, 'maintenance sorting order'), +(-1, 105, 'project sorting order'), +(-1, 106, 'task sorting order'), +(-1, 107, 'measurement sorting order'), +(-1, 108, 'company sorting order'), +(-1, 109, 'document sorting order'), +(-1, 110, 'tag sorting order'), +(-1, 200, 'equipment filter json'), +(-1, 201, 'inventory filter json'), +(-1, 202, 'provision filter json'), +(-1, 203, 'storage filter json'), +(-1, 204, 'maintenance filter json'), +(-1, 205, 'project filter json'), +(-1, 206, 'task filter json'), +(-1, 207, 'measurement filter json'), +(-1, 208, 'company filter json'), +(-1, 209, 'document filter json'), +(-1, 210, 'tag filter json'); + /* list of lists needed */ INSERT INTO dropdown (ddid, ddval, ddtext) VALUES (0, 0, 'list of lists'), diff --git a/yms/vessel.py b/yms/vessel.py new file mode 100644 index 0000000..e58c441 --- /dev/null +++ b/yms/vessel.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- + +from datetime import datetime +import MySQLdb.cursors + +class Vessel(): + + def __init__(self, dbconn, vessel_id=None): + self.conn = dbconn + self.dcur = dbconn.cursor(MySQLdb.cursors.DictCursor) + self.fields = ('vid', 'vtype', 'vesselname', 'model', 'loa', 'lwl', + 'beam', 'draught', 'draught_min', 'displacement', 'ballast', + 'beltpos_aft', 'beltpos_bow', 'shapefile', 'remarks') + if vessel_id: + self.vid = long(vessel_id) + self.load() + else: + self.vid = None + self.vtype = None + self.model = None + self.loa = None + self.lwl = None + self.beam = None + self.draught = None + self.draught_min = None + self.displacement = None + self.ballast = None + self.beltpos_aft = None + self.beltpos_bow = None + self.shapefile = None + self.remarks = None + self.data = {} # for old/new checks + + def load(self): + sql = ( + "SELECT {}".format(', '.join(self.fields)) + "FROM vessel " + "WHERE vessel_id=%s" + ) + self.dcur.execute(sql, (self.vid,)) + self.data = self.dcur.fetchone() + # TODO + self.parent_id = self.data['parent_id'] + + def save(self): + last_row_id = None + self.last_update = datetime.now() + if self.vid: + # record already available + sqlfield = [] + values = [] + for field in self.fields: + newdata = getattr(self, field) + if self.data[field] != newdata: + sqlfield.append("{}=%s".format(field)) + values.append(newdata) + self.data[field] = newdata + if values: + # only save ich there are changes + sql = ( + "UPDATE vessel SET " + ",".join(sqlfield) + + " WHERE vidid=%s" + ) + values.append(self.vid) + self.dcur.execute(sql, values) + # TODO check sql result + last_row_id = self.vid + else: + # new record + sql = ( + "INSERT INTO risk (" + ",".join(self.fields) + + ") VALUES (" + ",".join(["%s"] * len(self.fields)) + ")" + ) + values = [] + for field in self.fields: + newdata = getattr(self, field) + values.append(newdata) + self.data[field] = newdata + self.dcur.execute(sql, values) + last_row_id = self.dcur.lastrowid + self.vid = last_row_id + + def delete(self, vessel_id): + sql = "DELETE FROM vessel WHERE vid=%s" + self.cur.execute(sql, (self.vid,)) + + def __str__(self): + out = "Vessel({})".format(self.vid) + return out diff --git a/yms48.png b/yms48.png new file mode 100644 index 0000000000000000000000000000000000000000..7a7f805d2523a52c07153c4c92513403448383de GIT binary patch literal 2837 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 literal 0 HcmV?d00001