Compare commits
No commits in common. "master" and "use-python-fire" have entirely different histories.
master
...
use-python
12
LICENSE.txt
12
LICENSE.txt
@ -1,12 +0,0 @@
|
||||
Copyright (C) 2019 Kopano and its licensors
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under the terms of the
|
||||
GNU Affero General Public License as published by the Free Software Foundation, either version
|
||||
3 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License along with this program.
|
||||
If not, see http://www.gnu.org/licenses/.
|
27
README.md
27
README.md
@ -1,27 +0,0 @@
|
||||
# WebApp tools
|
||||
|
||||
WebApp tools repository can be found [here](https://stash.kopano.io/projects/KSC/repos/webapp-tools/) and consist of various sub-projects:
|
||||
|
||||
## WebApp_Admin
|
||||
|
||||
A CLI tool that can be used to manage WebApp user settings, signatures, S/MIME certificates and more.
|
||||
More info [here](https://stash.kopano.io/projects/KSC/repos/webapp-tools/browse/webapp_admin/README.md).
|
||||
|
||||
## Files_Admin
|
||||
|
||||
A CLI tool to inject files accounts into a user settings. More info [here](https://stash.kopano.io/projects/KSC/repos/webapp-tools/browse/files_admin/README.md).
|
||||
|
||||
## Manage_recipients
|
||||
|
||||
A simple script to manage the recipient history list for a user. More info [here](https://stash.kopano.io/projects/KSC/repos/webapp-tools/browse/manage_recipients/readme.md).
|
||||
|
||||
# How to contribute
|
||||
|
||||
1) Clone the repository from `https://stash.kopano.io/` or `https://github.com/Kopano-mirror/webapp_tools`.
|
||||
2) Commit and sign your work (git commit -s).
|
||||
3) Upload commits to a git store of your choosing, or export the series as a patchset using git format-patch.
|
||||
4) Send the patch(es) or git link to `contributing @ kopano .io` and we will consider the submission.
|
||||
|
||||
# License
|
||||
|
||||
All software found in this repostory and sub-projects are licensed under GNU Affero General Public License v3 unless stated otherwise. A copy of this license can be found in the main directory of this project and in every sub-project.
|
@ -1,12 +0,0 @@
|
||||
Copyright (C) 2019 Kopano and its licensors
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under the terms of the
|
||||
GNU Affero General Public License as published by the Free Software Foundation, either version
|
||||
3 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License along with this program.
|
||||
If not, see http://www.gnu.org/licenses/.
|
@ -20,7 +20,3 @@ Use the username and password provided in the config file
|
||||
|
||||
- python-kopano
|
||||
- python-mapi
|
||||
|
||||
# License
|
||||
|
||||
licensed under GNU Affero General Public License v3.
|
@ -54,19 +54,11 @@ 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
|
||||
if configfile['setting']['use_zarafa_credentials']:
|
||||
username = configfile['setting']['default_user']
|
||||
else:
|
||||
username = configfile['setting'].get('default_user', 'does not matter')
|
||||
password = encode(configfile['setting'].get('default_password', 'does not matter'))
|
||||
username = options.user
|
||||
password = encode(configfile['setting']['default_password'])
|
||||
backendoptions = {
|
||||
'ftp': {"backend_features": {
|
||||
"Streaming": "true", }},
|
||||
@ -101,7 +93,6 @@ def files(options):
|
||||
address = configfile['setting']['server_address']
|
||||
ssl = configfile['setting']['server_ssl']
|
||||
id = str(uuid.uuid4())
|
||||
|
||||
filesjson['accounts'][id] = {
|
||||
"status": "ok",
|
||||
"backend_config": {
|
||||
@ -110,7 +101,7 @@ def files(options):
|
||||
"server_address": encode(address).decode('utf-8'),
|
||||
"server_ssl": ssl,
|
||||
"current_account_id": encode('d4cacda458a2a26c301f2b7d75ada530').decode('utf-8'),
|
||||
"use_zarafa_credentials": configfile['setting'].as_bool('use_zarafa_credentials'),
|
||||
"use_zarafa_credentials": configfile['setting']['use_zarafa_credentials'],
|
||||
"user": encode(username).decode('utf-8'),
|
||||
"password": password.decode('utf-8'),
|
||||
"server_port": encode(port).decode('utf-8')
|
||||
|
@ -1,13 +0,0 @@
|
||||
[setting]
|
||||
|
||||
name = FTP server
|
||||
type = FTP
|
||||
workgroup =
|
||||
server_path = /srv/ftp
|
||||
server_address = 10.10.11.9
|
||||
server_ssl = false
|
||||
use_zarafa_credentials = false
|
||||
server_port = 21
|
||||
default_user = ftpuser
|
||||
default_password = ftpuser
|
||||
server_pasv = false
|
@ -4,7 +4,7 @@ name = Samba share
|
||||
type = SMB
|
||||
workgroup = zarafa
|
||||
server_path = files
|
||||
server_address = 10.10.11.9
|
||||
server_address = 192.168.1.230
|
||||
server_ssl = false
|
||||
use_zarafa_credentials = true
|
||||
server_port = 80
|
||||
|
@ -1,12 +0,0 @@
|
||||
Copyright (C) 2019 Kopano and its licensors
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under the terms of the
|
||||
GNU Affero General Public License as published by the Free Software Foundation, either version
|
||||
3 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License along with this program.
|
||||
If not, see http://www.gnu.org/licenses/.
|
@ -2,10 +2,8 @@
|
||||
#encoding: utf-8
|
||||
|
||||
import kopano
|
||||
from kopano.errors import NotFoundError
|
||||
from MAPI.Util import *
|
||||
import json
|
||||
import sys
|
||||
|
||||
|
||||
def opt_args():
|
||||
@ -26,22 +24,14 @@ 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)
|
||||
try:
|
||||
webapp = user.store.prop(0X6773001F).value
|
||||
except NotFoundError:
|
||||
webapp = dict(recipients=[])
|
||||
|
||||
webapp = user.store.prop(0X6773001F).value
|
||||
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=(',', ': ')))
|
||||
@ -60,8 +50,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:
|
||||
@ -69,7 +59,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)
|
||||
|
||||
|
@ -31,8 +31,4 @@ Remove all recipients that have example.com in there display_name, smtp_address
|
||||
python remove_recipients.py --user user --remove example.com
|
||||
```
|
||||
|
||||
# License
|
||||
|
||||
licensed under GNU Affero General Public License v3.
|
||||
|
||||
|
@ -1,12 +0,0 @@
|
||||
Copyright (C) 2019 Kopano and its licensors
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under the terms of the
|
||||
GNU Affero General Public License as published by the Free Software Foundation, either version
|
||||
3 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License along with this program.
|
||||
If not, see http://www.gnu.org/licenses/.
|
@ -1,14 +1,11 @@
|
||||
# WebApp Admin
|
||||
|
||||
>**Always make a backup of the user settings and test the new settings afterwards**
|
||||
>**This tool is under contruction. Use caution on a live server. Always make a backup of the user settings and test first before modifing**
|
||||
|
||||
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
|
||||
|
||||
@ -18,35 +15,6 @@ Change free/busy to 36 months
|
||||
If you want to make a change for all users pass the --all-users parameter. Example:
|
||||
> python3 webapp_admin --all-users --icons Breeze
|
||||
|
||||
## Signatures
|
||||
|
||||
To restore, replace and backup signatures we need a two part, underscore separated filename consisting of a `name` and `id`.\
|
||||
|
||||
Example single user: `this-is-my-signature_1234.html`\
|
||||
|
||||
---
|
||||
**Note**\
|
||||
The hypens in the filename will be displayed as spaces in WebApp\
|
||||
The username can also be part of the .html file, but is then ignored by the script.
|
||||
In WebApp the ID is created based on the unix time, so the ID can be anything
|
||||
|
||||
---
|
||||
|
||||
Examples
|
||||
|
||||
Backup signature for user `henk`
|
||||
> python3 webapp_admin -u henk --backup-signature
|
||||
|
||||
Restore signature for user `henk`
|
||||
> python3 webapp_admin -u henk --restore-signature my-cool-signature_1615141312112.html
|
||||
|
||||
Replace signature for user `henk`
|
||||
> python3 webapp_admin -u henk --replace-signature my-cool-signature_1615141312112.html
|
||||
|
||||
Restore signatures for all users
|
||||
> python3 webapp_admin --all-users --restore-signature mycompany-signature_1412130992124.html
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
- python3
|
||||
@ -54,9 +22,3 @@ Restore signatures for all users
|
||||
- python-mapi
|
||||
- OpenSSL
|
||||
- dotty_dict
|
||||
|
||||
For debian 10 python3-pkg-resources is required
|
||||
|
||||
# License
|
||||
|
||||
licensed under GNU Affero General Public License v3.
|
||||
|
@ -1,6 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# encoding: utf-8
|
||||
from pkg_resources import parse_version
|
||||
import sys
|
||||
try:
|
||||
import kopano
|
||||
@ -17,17 +16,17 @@ import base64
|
||||
try:
|
||||
import OpenSSL.crypto
|
||||
except ImportError:
|
||||
pass
|
||||
from datetime import datetime, timedelta
|
||||
print('pip3 install pyOpenSSL')
|
||||
sys.exit(1)
|
||||
from datetime import datetime
|
||||
from time import mktime
|
||||
import getpass
|
||||
import time
|
||||
from optparse import OptionGroup
|
||||
from tabulate import tabulate
|
||||
try:
|
||||
from dotty_dict import dotty
|
||||
except ImportError:
|
||||
pass
|
||||
print('dotty_dict not found on your system. Run pip3 install dotty_dict')
|
||||
|
||||
|
||||
"""
|
||||
@ -51,20 +50,11 @@ def opt_args(print_help=None):
|
||||
group.add_option("--reset", dest="reset", action="store_true", help="Reset WebApp settings")
|
||||
parser.add_option_group(group)
|
||||
|
||||
# Addionals stores group
|
||||
group = OptionGroup(parser, "Store", "")
|
||||
group.add_option("--add-store", dest="add_store", action="store", help="Add shared store")
|
||||
group.add_option("--del-store", dest="del_store", action="store", help="Delete shared store")
|
||||
group.add_option("--folder-type", dest="folder_type", action="store", help="Folder to add")
|
||||
group.add_option("--subfolder", dest="sub_folder", action="store_true", help="Add subfolders")
|
||||
group.add_option("--list-stores", dest="list_stores", action="store_true", help="List shared stores")
|
||||
parser.add_option_group(group)
|
||||
|
||||
# Signature option group
|
||||
group = OptionGroup(parser, "Signature", "")
|
||||
group.add_option("--backup-signature", dest="backup_signature", action="store_true", help="Backup signature")
|
||||
group.add_option("--restore-signature", dest="restore_signature", action="store", help="Restore signature (need file name)")
|
||||
group.add_option("--replace-signature", dest="replace_signature", action="store", help="Replace existing signature, file layout must be: username_signature-name_signatureid.html or signature-name_signatureid.html ")
|
||||
group.add_option("--replace", dest="replace", action="store_true", help="Replace existing signature, file layout must be: username_signature-name_signatureid.html")
|
||||
group.add_option("--default-signature", dest="default_signature", action="store_true", help="Set signature as default one")
|
||||
parser.add_option_group(group)
|
||||
|
||||
@ -72,13 +62,12 @@ 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)
|
||||
|
||||
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")
|
||||
group.add_option("--import-smime", dest="import_smime", action="store", help="Import private S/MIME certificate")
|
||||
group.add_option("--remove-expired", dest="remove_expired", action="store_true", help="Remove expired public S/MIME certificates")
|
||||
group.add_option("--public", dest="public_smime", action="store_true", help="Export/Import public S/MIME certificate")
|
||||
group.add_option("--password", dest="password", action="store", help="set password")
|
||||
group.add_option("--ask-password", dest="ask_password", action="store_true", help="ask for password if needed")
|
||||
@ -86,15 +75,11 @@ def opt_args(print_help=None):
|
||||
|
||||
# WebApp setting option group
|
||||
group = OptionGroup(parser, "webapp-settings", "")
|
||||
group.add_option("--language", dest="language", action="store", type="string", help="Set new language (e.g. en_GB or nl_NL)")
|
||||
group.add_option("--language", dest="language", action="store", help="Set new language (e.g. en_GB or nl_NL)")
|
||||
group.add_option("--theme", dest="theme", action="store", help="Change theme (e.g. dark)")
|
||||
group.add_option("--free-busy", dest="freebusy", action="store", help="Change free/busy time span in months")
|
||||
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="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
|
||||
@ -209,73 +194,6 @@ def language(user, language):
|
||||
write_settings(user, json.dumps(settings))
|
||||
|
||||
|
||||
"""
|
||||
Add shared store
|
||||
"""
|
||||
def add_store(user, user_to_add, folder_type, subfolder=False):
|
||||
allowed_folder_types = ["all", "inbox", "calendar", "contact", "note", "task"]
|
||||
if folder_type not in allowed_folder_types:
|
||||
print("Unknown folder type allowed: {}".format(','.join(allowed_folder_types)))
|
||||
sys.exit(1)
|
||||
|
||||
settings = read_settings(user)
|
||||
if not settings['settings']['zarafa']['v1']['contexts'].get('hierarchy') or not settings['settings']['zarafa']['v1']['contexts']['hierarchy'].get('shared_stores'):
|
||||
settings['settings']['zarafa']['v1']['contexts']['hierarchy']['shared_stores'] = {}
|
||||
|
||||
settings['settings']['zarafa']['v1']['contexts']['hierarchy']['shared_stores'][user_to_add]= {folder_type : {'folder_type': folder_type, 'show_subfolders': subfolder}}
|
||||
print("Saving settings")
|
||||
write_settings(user, json.dumps(settings))
|
||||
|
||||
|
||||
"""
|
||||
Delete shared store
|
||||
"""
|
||||
def del_store(user, user_to_del, folder_type=None):
|
||||
if folder_type:
|
||||
allowed_folder_types = ["all", "inbox", "calendar", "contact", "note", "task"]
|
||||
if folder_type not in allowed_folder_types:
|
||||
print("Unknown folder type allowed: {}".format(','.join(allowed_folder_types)))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
settings = read_settings(user)
|
||||
if not settings['settings']['zarafa']['v1']['contexts'].get('hierarchy') or not settings['settings']['zarafa']['v1']['contexts']['hierarchy'].get('shared_stores'):
|
||||
print("No additional stores found")
|
||||
return
|
||||
|
||||
shared_store = settings['settings']['zarafa']['v1']['contexts']['hierarchy']['shared_stores'].get(user_to_del)
|
||||
if not shared_store:
|
||||
print("No additional stores found")
|
||||
return
|
||||
try:
|
||||
if not folder_type:
|
||||
settings['settings']['zarafa']['v1']['contexts']['hierarchy']['shared_stores'].pop(user_to_del)
|
||||
else:
|
||||
settings['settings']['zarafa']['v1']['contexts']['hierarchy']['shared_stores'][user_to_del].pop(folder_type)
|
||||
except KeyError:
|
||||
pass
|
||||
print("Saving settings")
|
||||
write_settings(user, json.dumps(settings))
|
||||
|
||||
"""
|
||||
List all added stores
|
||||
"""
|
||||
def list_stores(user):
|
||||
settings = read_settings(user)
|
||||
|
||||
try:
|
||||
stores = settings['settings']['zarafa']['v1']['contexts']['hierarchy']['shared_stores']
|
||||
except KeyError:
|
||||
print("No additional stores found")
|
||||
return
|
||||
table_header = ["User", 'Folder type', 'Show subfolders']
|
||||
table_data =[]
|
||||
for user in stores:
|
||||
for folder in stores[user]:
|
||||
table_data.append([user, folder, stores[user][folder]['show_subfolders']])
|
||||
|
||||
print(tabulate(table_data, headers=table_header,tablefmt="grid"))
|
||||
|
||||
"""
|
||||
Backup signature from the users store
|
||||
|
||||
@ -292,8 +210,6 @@ def backup_signature(user, location=None):
|
||||
except Exception as e:
|
||||
print('Could not load WebApp settings for user {} (Error: {})'.format(user.name, repr(e)))
|
||||
sys.exit(1)
|
||||
if not settings['settings']['zarafa']['v1']['contexts'].get("mail"):
|
||||
settings['settings']['zarafa']['v1']['contexts']['mail'] = {}
|
||||
if settings['settings']['zarafa']['v1']['contexts']['mail'].get('signatures'):
|
||||
for item in settings['settings']['zarafa']['v1']['contexts']['mail']['signatures']['all']:
|
||||
name = settings['settings']['zarafa']['v1']['contexts']['mail']['signatures']['all'][item]['name']
|
||||
@ -317,31 +233,16 @@ Restore signature into the users store
|
||||
def restore_signature(user, filename, replace=None, default=None):
|
||||
|
||||
restorefile = filename
|
||||
filename_split = filename.split('_')
|
||||
|
||||
if len(filename_split) == 2:
|
||||
signaturename = filename_split[0].replace('-',' ')
|
||||
if replace:
|
||||
signatureid = filename_split[1].split('.')[0]
|
||||
elif len(filename_split) == 3:
|
||||
signaturename = filename_split[1].replace('-',' ')
|
||||
if replace:
|
||||
signatureid = filename_split[2].split('.')[0]
|
||||
else:
|
||||
if replace:
|
||||
print('File format is not supported')
|
||||
sys.exit(1)
|
||||
|
||||
with open(restorefile, 'r') as sigfile:
|
||||
signaturehtml = sigfile.read()
|
||||
|
||||
if replace:
|
||||
signatureid = filename.split('_')[2].split('.')[0]
|
||||
action = 'Replacing'
|
||||
else:
|
||||
signaturename = filename.split('.')[0]
|
||||
signatureid = int(time.time())
|
||||
action = 'Adding'
|
||||
|
||||
signaturename = filename.split('_')[1].replace('-',' ')
|
||||
signaturecontent = dict(
|
||||
{u'name': signaturename, u'content': signaturehtml, u'isHTML': True})
|
||||
settings = read_settings(user)
|
||||
@ -368,7 +269,6 @@ def restore_signature(user, filename, replace=None, default=None):
|
||||
|
||||
write_settings(user, json.dumps(settings))
|
||||
|
||||
|
||||
"""
|
||||
Export categories from users store
|
||||
|
||||
@ -415,11 +315,11 @@ def import_categories(user, filename=None):
|
||||
if not user.store.get_prop(PR_EC_WEBAPP_PERSISTENT_SETTINGS_JSON_W):
|
||||
persistent_settings ={'settings': {'kopano': {'main': {'categories':data}}}}
|
||||
else:
|
||||
persistent_settings = json.loads(user.store.get_prop(PR_EC_WEBAPP_PERSISTENT_SETTINGS_JSON_W).value)
|
||||
persistent_settings = user.store.get_prop(PR_EC_WEBAPP_PERSISTENT_SETTINGS_JSON_W)
|
||||
persistent_settings['settings']['kopano']['main']['categories'] = data
|
||||
|
||||
print('Restoring categories for user {}'.format(user.name))
|
||||
user.store.create_prop(PR_EC_WEBAPP_PERSISTENT_SETTINGS_JSON_W, json.dumps(persistent_settings))
|
||||
user.store.create_prop(PR_EC_WEBAPP_PERSISTENT_SETTINGS_JSON_W, json.dumps(persistent_settings).decode('utf-8'))
|
||||
|
||||
|
||||
"""
|
||||
@ -430,7 +330,6 @@ Export S/MIME certificate from users store
|
||||
:param public: Export public certificate part
|
||||
"""
|
||||
def export_smime(user, location=None, public=None):
|
||||
|
||||
if location:
|
||||
backup_location = location
|
||||
else:
|
||||
@ -443,7 +342,7 @@ def export_smime(user, location=None, public=None):
|
||||
return
|
||||
|
||||
for cert in certificates:
|
||||
if public and cert.prop(PR_MESSAGE_CLASS_W).value == 'WebApp.Security.Public':
|
||||
if public and cert.prop(PR_MESSAGE_CLASS_w).value == 'WebApp.Security.Public':
|
||||
extension = 'pub'
|
||||
body = cert.text
|
||||
else:
|
||||
@ -465,9 +364,6 @@ Import S/MIME certificate into users store
|
||||
:param public: Import public certificate part
|
||||
"""
|
||||
def import_smime(user, cert_file, passwd, ask_password=None, public=None):
|
||||
if not sys.modules.get('OpenSSL'):
|
||||
print('PyOpenSSl not installed \npip3 install pyOpenSSL')
|
||||
sys.exit(1)
|
||||
if ask_password:
|
||||
passwd = getpass.getpass()
|
||||
elif not passwd:
|
||||
@ -523,27 +419,6 @@ def import_smime(user, cert_file, passwd, ask_password=None, public=None):
|
||||
else:
|
||||
print('Email address doesn\'t match')
|
||||
|
||||
"""
|
||||
Remove expired S/MIME Public certificates
|
||||
|
||||
:param user: The user
|
||||
"""
|
||||
def remove_expired_smime(user):
|
||||
# unable to loop over the associated items so getting the items in a list instead
|
||||
certificates =list(user.store.root.associated.items())
|
||||
|
||||
if len(certificates) == 0:
|
||||
print('No certificates found')
|
||||
return
|
||||
|
||||
now = datetime.now()
|
||||
for cert in certificates:
|
||||
# We only want to remove the public certificate
|
||||
if cert.prop(PR_MESSAGE_CLASS_W).value == 'WebApp.Security.Public':
|
||||
if cert.prop(PR_MESSAGE_DELIVERY_TIME).value < now:
|
||||
print('deleting public certificate {} ({})'.format(cert.subject, cert.prop(PR_MESSAGE_DELIVERY_TIME).value))
|
||||
user.store.root.associated.delete(cert)
|
||||
|
||||
|
||||
"""
|
||||
Custom function to merge two dictionaries.
|
||||
@ -553,7 +428,6 @@ but this function caused undesired behavior
|
||||
:param dict1: The first dictionary
|
||||
:param dict2: The second dictionary
|
||||
"""
|
||||
|
||||
def mergedicts(dict1, dict2):
|
||||
for k in set(dict1.keys()).union(dict2.keys()):
|
||||
if k in dict1 and k in dict2:
|
||||
@ -573,21 +447,11 @@ Inject webapp settings into the users store
|
||||
:param user: The user
|
||||
:param data: The webapp setting
|
||||
"""
|
||||
def advanced_inject(user, data, value_type='string'):
|
||||
if not sys.modules.get('dotty_dict'):
|
||||
print('dotty_dict not found on your system. \nRun pip3 install dotty_dict')
|
||||
sys.exit(1)
|
||||
def advanced_inject(user, data):
|
||||
settings = read_settings(user)
|
||||
split_data = data.split('=')
|
||||
|
||||
value = split_data[1].lstrip().rstrip()
|
||||
if value.lower() == 'true':
|
||||
value = True
|
||||
elif value.lower() == 'false':
|
||||
value = False
|
||||
if value_type == 'list':
|
||||
value = value.split(',')
|
||||
|
||||
dot = dotty()
|
||||
dot[split_data[0].rstrip()] = value
|
||||
|
||||
@ -605,15 +469,14 @@ def main():
|
||||
opt_args(True)
|
||||
options, args = opt_args()
|
||||
|
||||
# Always first!
|
||||
# If the script should execute for all users
|
||||
# The admin should pass the '--all-users' parameter
|
||||
if not options.users and not options.all_users:
|
||||
print('There are no users specified. Use "--all-users" to run for all users')
|
||||
sys.exit(1)
|
||||
|
||||
server = kopano.Server(options)
|
||||
|
||||
for user in server.users(options.users):
|
||||
for user in kopano.Server(options).users(options.users):
|
||||
# Backup and restore
|
||||
if options.backup:
|
||||
backup(user, options.location)
|
||||
@ -624,36 +487,22 @@ def main():
|
||||
if options.language:
|
||||
language(user, options.language)
|
||||
|
||||
if options.add_store:
|
||||
add_store(user, options.add_store, options.folder_type, options.sub_folder)
|
||||
|
||||
if options.del_store:
|
||||
del_store(user, options.del_store, options.folder_type)
|
||||
|
||||
if options.list_stores:
|
||||
list_stores(user)
|
||||
|
||||
#Categories
|
||||
if options.export_categories:
|
||||
export_categories(user, options.file)
|
||||
export_categories(user, options.change_locale)
|
||||
if options.import_categories:
|
||||
import_categories(user, options.file)
|
||||
|
||||
# S/MIME import/export
|
||||
if options.export_smime:
|
||||
export_smime(user, options.location, options.public_smime)
|
||||
if options.import_smime:
|
||||
import_smime(user, options.import_smime, options.password, options.ask_password, options.public_smime)
|
||||
if options.remove_expired:
|
||||
remove_expired_smime(user)
|
||||
|
||||
# Signature
|
||||
if options.backup_signature:
|
||||
backup_signature(user, options.location)
|
||||
if options.restore_signature:
|
||||
restore_signature(user, options.restore_signature, False, options.default_signature)
|
||||
if options.replace_signature:
|
||||
restore_signature(user, options.replace_signature, True, options.default_signature)
|
||||
restore_signature(user, options.restore_signature, options.replace, options.default_signature)
|
||||
|
||||
# Advanced injection option
|
||||
if options.add_option:
|
||||
@ -685,7 +534,7 @@ def main():
|
||||
sys.exit(1)
|
||||
setting = 'settings.zarafa.v1.main.active_iconset = {}'.format(options.icons)
|
||||
advanced_inject(user, setting)
|
||||
print('Icon set changed to {}'.format(options.icons))
|
||||
print('icon set changed to {}'.format(options.icons))
|
||||
|
||||
# Editor
|
||||
if options.htmleditor:
|
||||
@ -697,47 +546,6 @@ def main():
|
||||
advanced_inject(user, setting)
|
||||
print('Editor changed to {}'.format(options.htmleditor))
|
||||
|
||||
# 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))
|
||||
|
||||
# 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:
|
||||
reset_settings(user)
|
||||
|
Loading…
x
Reference in New Issue
Block a user