11 Commits

Author SHA1 Message Date
0bb8913794 Add check for settings key 2019-12-09 17:10:38 +01:00
d515051244 Merge pull request #21 in KSC/webapp-tools from ~MALBERTS/webapp-tools-martijn:add_calendar_resolution to master
* commit 'a708768c7a1c248bbfd5fb8c7ee793ad113257f2':
  Add calendar resolution setting
2019-09-12 12:39:39 +02:00
a708768c7a Add calendar resolution setting 2019-09-12 12:00:34 +02:00
5048d33cf1 add hint that python3-pkg-resources is required for debian 10 2019-08-13 16:38:14 +02:00
87a5ab0b07 create empty prop if not exist 2019-07-22 16:00:07 +02:00
7a75569e5d Merge pull request #20 in KSC/webapp-tools from ~MALBERTS/webapp-tools-martijn:norecipient to master
* commit '7477f89a54af5b5fb10d1c46a9f81e88eb4d77df':
  Manage recipient: Display error when PR_EC_RECIPIENT_HISTORY_JSON_W does not exist
2019-07-18 13:56:21 +02:00
7477f89a54 Manage recipient: Display error when PR_EC_RECIPIENT_HISTORY_JSON_W does not exist 2019-07-18 13:08:13 +02:00
7b4845a877 Merge pull request #19 in KSC/webapp-tools from ~MALBERTS/webapp-tools-martijn:python3 to master
* commit '35b4bbeec1bde647cbf0da316ef0984f5a23bf00':
  Add brackets around prints
2019-07-18 12:40:29 +02:00
35b4bbeec1 Add brackets around prints 2019-07-18 12:36:41 +02:00
8d8e3f3e50 Merge pull request #17 in KSC/webapp-tools from ~MALBERTS/webapp-tools-martijn:addInterval to master
* commit 'e976f230da31301ab16531caf9997fa6216f7ff3':
  WebApp Admin: Add polling interval injection
2019-07-12 09:32:20 +02:00
e976f230da WebApp Admin: Add polling interval injection 2019-07-11 16:02:30 +02:00
4 changed files with 80 additions and 28 deletions

View File

@ -54,6 +54,14 @@ def files(options):
files = options.file.split(',')
for file in files:
configfile = ConfigObj(file)
# Check if the settings section key is present in the file
try:
value = configfile['setting']
except KeyError:
print('Setting does not exist in', file)
continue
if configfile['setting'].as_bool('use_zarafa_credentials'):
username = options.user
else:

View File

@ -2,8 +2,10 @@
#encoding: utf-8
import kopano
from kopano.errors import NotFoundError
from MAPI.Util import *
import json
import sys
def opt_args():
@ -24,14 +26,22 @@ def main():
options, args = opt_args()
if not options.user:
print 'Please use:\n %s --user <username>' % (sys.argv[0])
print('Please use:\n %s --user <username>' % (sys.argv[0]))
sys.exit(0)
user = kopano.Server(options).user(options.user)
webapp = user.store.prop(0X6773001F).value
try:
webapp = user.store.prop(0X6773001F).value
except NotFoundError:
webapp = dict(recipients=[])
webapp = json.loads(webapp)
if options.backup:
if len(webapp['recipients']) == 0:
print('Property PR_EC_RECIPIENT_HISTORY_JSON_W not found . User might have never used recipient history before.', file=sys.stderr)
sys.exit(1)
f = open('%s.json' % user.name, 'w')
f.write(json.dumps(webapp, sort_keys=True,
indent=4, separators=(',', ': ')))
@ -50,8 +60,8 @@ def main():
sys.exit(0)
if options.list:
print json.dumps(webapp, sort_keys=True,
indent=4, separators=(',', ': '))
print(json.dumps(webapp, sort_keys=True,
indent=4, separators=(',', ': ')))
sys.exit(0)
if options.remove:
@ -59,7 +69,7 @@ def main():
for rec in webapp['recipients']:
if options.remove in rec['display_name'] or options.remove in rec['smtp_address'] \
or options.remove in rec['email_address']:
print 'removing contact %s [%s]' % (rec['display_name'], rec['smtp_address'])
print('removing contact %s [%s]' % (rec['display_name'], rec['smtp_address']))
else:
newlist['recipients'].append(rec)

View File

@ -1,11 +1,14 @@
# WebApp Admin
>**This tool is under contruction. Use caution on a live server. Always make a backup of the user settings and test first before modifing**
>**Always make a backup of the user settings and test the new settings afterwards**
WebApp admin is a command-line interface to modify, inject and export WebApp settings.
# Example Usage
Overview of all options:
> python3 webapp_admin -h
Reset WebApp settings
> python3 webapp_admin -u john --reset
@ -23,6 +26,8 @@ If you want to make a change for all users pass the --all-users parameter. Examp
- OpenSSL
- dotty_dict
For debian 10 python3-pkg-resources is required
# License
licensed under GNU Affero General Public License v3.
licensed under GNU Affero General Public License v3.

View File

@ -26,8 +26,7 @@ from optparse import OptionGroup
try:
from dotty_dict import dotty
except ImportError:
pass
pass
"""
@ -63,8 +62,8 @@ def opt_args(print_help=None):
group = OptionGroup(parser, "Categories", "")
group.add_option("--export-categories", dest="export_categories", action="store_true", help="Export Categories (name and color)")
group.add_option("--import-categories", dest="import_categories", action="store_true", help="Import Categories (name and color)")
parser.add_option_group(group)
# S/MIME option group
group = OptionGroup(parser, "S/MIME", "")
group.add_option("--export-smime", dest="export_smime", action="store_true", help="Export private S/MIME certificate")
@ -82,7 +81,9 @@ def opt_args(print_help=None):
group.add_option("--icons", dest="icons", action="store", help="Change icons (e.g. breeze)")
group.add_option("--htmleditor", dest="htmleditor", action="store", help="Change the HTML editor (e.g. full_tinymce)")
group.add_option("--remove-state", dest="remove_state", action="store_true", help="Remove all the state settings")
group.add_option("--add-safesender", dest="addsender", action="store", help="Add domain to safe sender list")
group.add_option("--add-safesender", dest="add_sender", action="store", help="Add domain to safe sender list")
group.add_option("--polling-interval", dest="polling_interval", action="store", help="Change the polling interval (seconds)")
group.add_option("--calendar-resolution", dest="calendar_resolution", action="store", help="Change the calendar resolution (minutes)")
parser.add_option_group(group)
# Advanced option group
@ -189,7 +190,7 @@ def language(user, language):
except:
print('User language is not defined using en_GB as fallback')
language = 'en_GB'
if not settings['settings']['zarafa']['v1'].get('main'):
settings['settings']['zarafa']['v1']['main'] = {}
settings['settings']['zarafa']['v1']['main']['language'] = language
@ -229,7 +230,7 @@ def backup_signature(user, location=None):
Restore signature into the users store
:param user: The user
:param filename: The filename of the signature
:param filename: The filename of the signature
:param replace: Remove all existing signatures for the restore signature
:param default: Set the signature as default for new mail and replies
"""
@ -272,6 +273,7 @@ def restore_signature(user, filename, replace=None, default=None):
write_settings(user, json.dumps(settings))
"""
Export categories from users store
@ -305,7 +307,7 @@ def export_categories(user, location=None):
Import categories from users store
:param user: The user
:param filename: The filename of the signature
:param filename: The filename of the signature
"""
def import_categories(user, filename=None):
if filename:
@ -389,7 +391,7 @@ def import_smime(user, cert_file, passwd, ask_password=None, public=None):
except Exception as e:
print(e)
sys.exit(1)
certificate = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, p12.get_certificate())
cert_data = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, certificate)
date_before = MAPI.Time.unixtime(mktime(datetime.strptime(cert_data.get_notBefore().decode('utf-8'), "%Y%m%d%H%M%SZ" ).timetuple()))
@ -407,7 +409,7 @@ def import_smime(user, cert_file, passwd, ask_password=None, public=None):
email = dict_issued_to[key].decode('utf-8')
else:
issued_to += "%s=%s\n" % (key, dict_issued_to[key])
if user.email == email:
item = assoc.mapiobj.CreateMessage(None, MAPI_ASSOCIATED)
@ -462,7 +464,7 @@ def advanced_inject(user, data, value_type='string'):
split_data = data.split('=')
value = split_data[1].lstrip().rstrip()
if value.lower() == 'true':
if value.lower() == 'true':
value = True
elif value.lower() == 'false':
value = False
@ -477,7 +479,7 @@ def advanced_inject(user, data, value_type='string'):
write_settings(user, json.dumps(new_settings))
"""
Main function run with arguments
"""
@ -566,17 +568,44 @@ def main():
# State settings
if options.remove_state:
settings = read_settings(user)
settings['settings']['zarafa']['v1']['state'] = {}
write_settings(user, json.dumps(settings))
print('Removed state settings for {}'.format(user.name))
settings = read_settings(user)
settings['settings']['zarafa']['v1']['state'] = {}
write_settings(user, json.dumps(settings))
print('Removed state settings for {}'.format(user.name))
# Add sender to safe sender list
if options.addsender:
settings = read_settings(user)
setting = 'settings.zarafa.v1.contexts.mail.safe_senders_list = {}'.format(options.addsender)
advanced_inject(user, setting, 'list')
print('{}'.format(options.addsender), 'Added to safe sender list')
# Add sender to safe sender list
if options.add_sender:
settings = read_settings(user)
setting = 'settings.zarafa.v1.contexts.mail.safe_senders_list = {}'.format(options.add_sender)
advanced_inject(user, setting, 'list')
print('{}'.format(options.add_sender), 'Added to safe sender list for {}'.format(user.name))
# Polling interval
if options.polling_interval:
try:
value = int(options.polling_interval)
except ValueError:
print('Invalid number used. Please specify the value in seconds')
sys.exit(1)
settings = read_settings(user)
setting = 'settings.zarafa.v1.main.reminder.polling_interval = {}'.format(options.polling_interval)
advanced_inject(user, setting)
print('Polling interval changed to', '{}'.format(options.polling_interval), 'for {}'.format(user.name))
# Calendar resolution (zoom level)
if options.calendar_resolution:
try:
value = int(options.calendar_resolution)
except ValueError:
print('Invalid number used. Please specify the value in minutes')
sys.exit(1)
if value < 5 or value > 60:
print('Unsupported value used. Use a number between 5 and 60')
sys.exit(1)
settings = read_settings(user)
setting = 'settings.zarafa.v1.contexts.calendar.default_zoom_level = {}'.format(options.calendar_resolution)
advanced_inject(user, setting)
print('Calendar resolution changed to', '{}'.format(options.calendar_resolution), 'for {}'.format(user.name))
# Always at last!!!
if options.reset: