From 238dd20d207c9d98b9167bf202e6d9aa9cc34772 Mon Sep 17 00:00:00 2001 From: b3yond Date: Tue, 6 Nov 2018 16:17:47 +0100 Subject: [PATCH 01/15] if no config.toml, set config through environment #64 --- config.py | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/config.py b/config.py index fa01302..abbae62 100755 --- a/config.py +++ b/config.py @@ -1,5 +1,57 @@ import pytoml as toml +import os + +def load_env(): + """ + load environment variables from the environment. If empty, use default + values from config.toml.example. + + :return: config dictionary of dictionaries. + """ + with open('config.toml.example') as defaultconf: + config = toml.load(configfile) + + try: + config['twitter']['consumer_key'] = os.environ['CONSUMER_KEY'] + except KeyError: + pass + + try: + config['twitter']['consumer_secret'] = os.environ['CONSUMER_SECRET'] + except KeyError: + pass + + try: + config['web']['host'] = os.environ['HOST'] + except KeyError: + pass + + try: + config['web']['port'] = os.environ['PORT'] + except KeyError: + pass + + try: + config['web']['contact'] = os.environ['CONTACT'] + except KeyError: + pass + + try: + config['mail']['mbox_user'] = os.environ['MBOX_USER'] + except KeyError: + pass + + try: + config['database']['db_path'] = os.environ['DB_PATH'] + except KeyError: + pass + + return config + # read config in TOML format (https://github.com/toml-lang/toml#toml) -with open('config.toml') as configfile: - config = toml.load(configfile) +try: + with open('config.toml') as configfile: + config = toml.load(configfile) +except FileNotFoundError: + config = load_env() From d964927a3f00ee392d8a29eeff85532faef7a32f Mon Sep 17 00:00:00 2001 From: b3yond Date: Tue, 6 Nov 2018 16:22:11 +0100 Subject: [PATCH 02/15] fix small bug, print current config if directly called #64 --- config.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/config.py b/config.py index abbae62..4550b14 100755 --- a/config.py +++ b/config.py @@ -9,7 +9,7 @@ def load_env(): :return: config dictionary of dictionaries. """ with open('config.toml.example') as defaultconf: - config = toml.load(configfile) + config = toml.load(defaultconf) try: config['twitter']['consumer_key'] = os.environ['CONSUMER_KEY'] @@ -55,3 +55,8 @@ try: config = toml.load(configfile) except FileNotFoundError: config = load_env() + +if __name__ == "__main__": + for category in config: + for key in config[category]: + print(key + " = " + str(config[category][key])) From bc7a4a72f80c1c7a4822531579cc3e200cd306b6 Mon Sep 17 00:00:00 2001 From: b3yond Date: Tue, 6 Nov 2018 16:23:47 +0100 Subject: [PATCH 03/15] beauty overhaul of config.py --- config.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/config.py b/config.py index 4550b14..2b8a6cb 100755 --- a/config.py +++ b/config.py @@ -1,6 +1,7 @@ import pytoml as toml import os + def load_env(): """ load environment variables from the environment. If empty, use default @@ -9,44 +10,44 @@ def load_env(): :return: config dictionary of dictionaries. """ with open('config.toml.example') as defaultconf: - config = toml.load(defaultconf) + configdict = toml.load(defaultconf) try: - config['twitter']['consumer_key'] = os.environ['CONSUMER_KEY'] + configdict['twitter']['consumer_key'] = os.environ['CONSUMER_KEY'] except KeyError: pass try: - config['twitter']['consumer_secret'] = os.environ['CONSUMER_SECRET'] + configdict['twitter']['consumer_secret'] = os.environ['CONSUMER_SECRET'] except KeyError: pass try: - config['web']['host'] = os.environ['HOST'] + configdict['web']['host'] = os.environ['HOST'] except KeyError: pass try: - config['web']['port'] = os.environ['PORT'] + configdict['web']['port'] = os.environ['PORT'] except KeyError: pass try: - config['web']['contact'] = os.environ['CONTACT'] + configdict['web']['contact'] = os.environ['CONTACT'] except KeyError: pass try: - config['mail']['mbox_user'] = os.environ['MBOX_USER'] + configdict['mail']['mbox_user'] = os.environ['MBOX_USER'] except KeyError: pass try: - config['database']['db_path'] = os.environ['DB_PATH'] + configdict['database']['db_path'] = os.environ['DB_PATH'] except KeyError: pass - return config + return configdict # read config in TOML format (https://github.com/toml-lang/toml#toml) From 945a90c7e1ad379b8310382ce7ceb61cf79f1e1d Mon Sep 17 00:00:00 2001 From: b3yond Date: Tue, 6 Nov 2018 17:50:57 +0100 Subject: [PATCH 04/15] make config.py output directly applicable --- config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.py b/config.py index 2b8a6cb..d47bb8e 100755 --- a/config.py +++ b/config.py @@ -60,4 +60,4 @@ except FileNotFoundError: if __name__ == "__main__": for category in config: for key in config[category]: - print(key + " = " + str(config[category][key])) + print(key + "=" + str(config[category][key])) From 5a4763366be2d33ae465c9b3d96ea8877c99e64d Mon Sep 17 00:00:00 2001 From: b3yond Date: Tue, 6 Nov 2018 18:08:51 +0100 Subject: [PATCH 05/15] if an env var is an empty string, use values from example config --- config.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/config.py b/config.py index d47bb8e..bc7baaf 100755 --- a/config.py +++ b/config.py @@ -13,37 +13,44 @@ def load_env(): configdict = toml.load(defaultconf) try: - configdict['twitter']['consumer_key'] = os.environ['CONSUMER_KEY'] + if os.environ['CONSUMER_KEY'] != "": + configdict['twitter']['consumer_key'] = os.environ['CONSUMER_KEY'] except KeyError: pass try: - configdict['twitter']['consumer_secret'] = os.environ['CONSUMER_SECRET'] + if os.environ['CONSUMER_SECRET'] != "": + configdict['twitter']['consumer_secret'] = os.environ['CONSUMER_SECRET'] except KeyError: pass try: - configdict['web']['host'] = os.environ['HOST'] + if os.environ['HOST'] != "": + configdict['web']['host'] = os.environ['HOST'] except KeyError: pass try: - configdict['web']['port'] = os.environ['PORT'] + if os.environ['PORT'] != "": + configdict['web']['port'] = os.environ['PORT'] except KeyError: pass try: - configdict['web']['contact'] = os.environ['CONTACT'] + if os.environ['CONTACT'] != "": + configdict['web']['contact'] = os.environ['CONTACT'] except KeyError: pass try: - configdict['mail']['mbox_user'] = os.environ['MBOX_USER'] + if os.environ['MBOX_USER'] != "": + configdict['mail']['mbox_user'] = os.environ['MBOX_USER'] except KeyError: pass try: - configdict['database']['db_path'] = os.environ['DB_PATH'] + if os.environ['DB_PATH'] != "": + configdict['database']['db_path'] = os.environ['DB_PATH'] except KeyError: pass From 4c61b1ba9909a76d4dfcb3aa36186e6f7e7e8fca Mon Sep 17 00:00:00 2001 From: b3yond Date: Wed, 7 Nov 2018 01:57:47 +0100 Subject: [PATCH 06/15] setting host to 0.0.0.0 - it never worked with smth else anyway --- frontend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend.py b/frontend.py index 37144d3..894f6c5 100755 --- a/frontend.py +++ b/frontend.py @@ -260,6 +260,6 @@ bottle.install(SessionPlugin('/')) if __name__ == '__main__': # testing only - bottle.run(host=config["web"]["host"], port=config["web"]["port"]) + bottle.run(host="0.0.0.0", port=config["web"]["port"]) else: application.catchall = False From 8e1234d9b57c9280189edb0355478edc47f379f4 Mon Sep 17 00:00:00 2001 From: b3yond Date: Wed, 7 Nov 2018 09:22:02 +0100 Subject: [PATCH 07/15] removed wrong comment - not only testing, also docker containers use this --- frontend.py | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend.py b/frontend.py index 894f6c5..6b4fe15 100755 --- a/frontend.py +++ b/frontend.py @@ -259,7 +259,6 @@ application = bottle.default_app() bottle.install(SessionPlugin('/')) if __name__ == '__main__': - # testing only bottle.run(host="0.0.0.0", port=config["web"]["port"]) else: application.catchall = False From 1c8853341a26dea16dc42d8e087390d91cd63f3d Mon Sep 17 00:00:00 2001 From: b3yond Date: Fri, 11 Jan 2019 12:15:28 +0100 Subject: [PATCH 08/15] check if account already exists #37 --- frontend.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frontend.py b/frontend.py index 37144d3..0ea9d1f 100755 --- a/frontend.py +++ b/frontend.py @@ -56,6 +56,9 @@ def register_post(): @get('/confirm//') @view('template/propaganda.tpl') def confirm(city, token): + # check whether city already exists + if db.by_city(city): + return dict(error='Account already exists.') # create db-entry if db.confirm(token, city): # :todo show info "Account creation successful." From 2ce27fc52f845b1c238bb6d6a7724a33059cc4f4 Mon Sep 17 00:00:00 2001 From: b3yond Date: Fri, 11 Jan 2019 13:21:47 +0100 Subject: [PATCH 09/15] nicer error messages --- frontend.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend.py b/frontend.py index 0ea9d1f..63143d5 100755 --- a/frontend.py +++ b/frontend.py @@ -58,12 +58,13 @@ def register_post(): def confirm(city, token): # check whether city already exists if db.by_city(city): - return dict(error='Account already exists.') + return dict(error='This Account was already confirmed, please try ' + 'signing in.') # create db-entry if db.confirm(token, city): # :todo show info "Account creation successful." redirect('/settings') - return dict(error='Email confirmation failed.') + return dict(error='Account creation failed. Please try to register again.') @post('/login') From 76b3b574f00bff4b386e97447c7a2e95e5bbaebe Mon Sep 17 00:00:00 2001 From: b3yond Date: Fri, 11 Jan 2019 13:23:37 +0100 Subject: [PATCH 10/15] replaced attribute with get call --- db.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/db.py b/db.py index 811d197..61100ae 100644 --- a/db.py +++ b/db.py @@ -14,7 +14,6 @@ class DB(object): self.conn = sqlite3.connect(dbfile) self.cur = self.conn.cursor() self.create() - self.secret = self.get_secret() def execute(self, *args, **kwargs): return self.cur.execute(*args, **kwargs) @@ -189,7 +188,7 @@ class DB(object): 'passhash': scrypt_mcf( password.encode('utf-8') ).decode('ascii') - }, self.secret).decode('ascii') + }, self.get_secret()).decode('ascii') def mail_subscription_token(self, email, city): """ @@ -203,17 +202,17 @@ class DB(object): token = jwt.encode({ 'email': email, 'city': city - }, self.secret).decode('ascii') + }, self.get_secret()).decode('ascii') return token def confirm_subscription(self, token): - json = jwt.decode(token, self.secret) + json = jwt.decode(token, self.get_secret()) return json['email'], json['city'] def confirm(self, token, city): from user import User try: - json = jwt.decode(token, self.secret) + json = jwt.decode(token, self.get_secret()) except jwt.DecodeError: return None # invalid token if 'passhash' in json.keys(): From 12a0b1efe5475d2b7140343d05bbb87f9c1c9cdf Mon Sep 17 00:00:00 2001 From: b3yond Date: Fri, 11 Jan 2019 13:38:47 +0100 Subject: [PATCH 11/15] added call to GET version (commit hash) --- README.md | 2 +- frontend.py | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 680285d..0a68e78 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ virtualenv -p python3 . Install the dependencies: ```shell -pip install tweepy pytoml Mastodon.py bottle pyjwt pylibscrypt Markdown twx +pip install tweepy pytoml Mastodon.py bottle pyjwt pylibscrypt Markdown twx gitpython ``` Configure the bot: diff --git a/frontend.py b/frontend.py index 37144d3..8f86d1e 100755 --- a/frontend.py +++ b/frontend.py @@ -63,6 +63,13 @@ def confirm(city, token): return dict(error='Email confirmation failed.') +@get('/version') +def version(): + import git + repo = git.Repo(search_parent_directories=True) + return repo.head.object.hexsha + + @post('/login') @view('template/login.tpl') def login_post(): From 4bd99ebb90c1157cce91fdda2f833c2f6d47b276 Mon Sep 17 00:00:00 2001 From: b3yond Date: Fri, 11 Jan 2019 13:44:27 +0100 Subject: [PATCH 12/15] updated the issue template --- .github/ISSUE_TEMPLATE/bug_report.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 7c1e5b0..045eb1c 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -17,6 +17,9 @@ Steps to reproduce the behavior: 3. Scroll down to '....' 4. See error +**Ticketfrei Version** +See the commit on which Ticketfrei is running at example.org/version. + **Screenshots** If applicable, add screenshots to help explain your problem. From 7507d0392d74fc3c71fb7876dc04f141b36b1013 Mon Sep 17 00:00:00 2001 From: sid <25916907+git-sid@users.noreply.github.com> Date: Fri, 11 Jan 2019 13:48:29 +0100 Subject: [PATCH 13/15] Update LICENSE --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 6b24afd..2249ac4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ Copyright (c) 2017 Thomas L Copyright (c) 2017 b3yond -Copyright (c) 2018 sid +Copyright (c) 2018 sid Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above From 4b8798ddea9ae453ed8f8c4ffa5f024f1380a9a1 Mon Sep 17 00:00:00 2001 From: b3yond Date: Fri, 11 Jan 2019 14:52:58 +0100 Subject: [PATCH 14/15] fixing shutdown when exim4 is not set up --- active_bots/mailbot.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/active_bots/mailbot.py b/active_bots/mailbot.py index 7c8fcb5..984d09f 100644 --- a/active_bots/mailbot.py +++ b/active_bots/mailbot.py @@ -19,7 +19,11 @@ class Mailbot(Bot): def crawl(self, user): reports = [] # todo: adjust to actual mailbox - mails = mailbox.mbox("/var/mail/" + config['mail']['mbox_user']) + try: + mails = mailbox.mbox("/var/mail/" + config['mail']['mbox_user']) + except FileNotFoundError: + logger.error("No mbox file found.", exc_info=True) + return reports for msg in mails: if get_date_from_header(msg['Date']) > user.get_seen_mail(): if user.get_city().lower() in msg['To'].lower(): From 54489807daed432d90fd06cfa2cf58db44e2e059 Mon Sep 17 00:00:00 2001 From: b3yond Date: Fri, 11 Jan 2019 15:16:37 +0100 Subject: [PATCH 15/15] no need for such a verbose error message. --- active_bots/mailbot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/active_bots/mailbot.py b/active_bots/mailbot.py index 984d09f..fbcd02b 100644 --- a/active_bots/mailbot.py +++ b/active_bots/mailbot.py @@ -22,7 +22,7 @@ class Mailbot(Bot): try: mails = mailbox.mbox("/var/mail/" + config['mail']['mbox_user']) except FileNotFoundError: - logger.error("No mbox file found.", exc_info=True) + logger.error("No mbox file found.") return reports for msg in mails: if get_date_from_header(msg['Date']) > user.get_seen_mail():