#! /usr/bin/env python

from __future__ import print_function

"""
Reset LDAP association and force (optional) accounts and groups updates

The script resets first the LDAP association for the accounts and for the groups.
Secondly LDAP synchronization (from Axigen to LDAP) is triggered by:
- modifying and restoring back the 'aolScreenName' attribute (for accounts)
- adding and removing (or vice-versa) the postmaster account (for groups)
"""
#
# ver 1 - Jul 2016: II - initial release
# ver 2 - Dec 2016: PB - fix logmsg (AXIGEN#2016112999000069)
# ver 3 - Jun 2020: II - add support for Python 3
#

import os,datetime

### Configuration parameters block
AXIGEN_PYLIB_DIR="/opt/axigen/scripts/lib"
CLI_HOST=os.getenv("CLI_HOST","127.0.0.1")
CLI_PORT=7000
CLI_ADMIN_USER="admin"
CLI_ADMIN_PASS="mypass"
### End of configuration parameters block

import sys
import syslog
sys.path.insert(0, AXIGEN_PYLIB_DIR)
import cli2

def logmsg(msg):
    if os.isatty(1):
        print('{0:%Y-%m-%d %H:%M:%S }'.format(datetime.datetime.now()) + msg)
    syslog.syslog(msg);

def show_help():
    print("""
Basic usage:
  %(s)s [domain]
  Where, each parameter is:
  domain - if set, the operations will be limited only to the specified domain
  
To only reset the LDAP association, without forcing the synchronization to LDAP,
the NO_UPDATE environment parameter should be set to the 'true' value, like below:
  NO_UPDATE=true %(s)s [domain]

Running without any changes is possible by setting the DRY_RUN environment parameter
to the 'true' value, like below:
  DRY_RUN=true %(s)s [domain]
""" % {'s' : sys.argv[0]}, file=sys.stderr)


domains = []
no_update = os.getenv("NO_UPDATE","false")
dry_run = os.getenv("DRY_RUN","false")

if len(sys.argv) == 2:
    param = sys.argv[1]
    if param == 'help' or param == '--help' or param == '-h':
        show_help()
        sys.exit()
    else:
        domains = [param]

try:
    cli = cli2.CLI(CLI_HOST, CLI_PORT)
    cli.auth(CLI_ADMIN_PASS, CLI_ADMIN_USER)

    if len(domains) == 0:
        domains = cli.get_domains()

    for d in domains:
        cli.goto_root_context()
        cli.update_domain(d)
        for a in cli.get_accounts():
            cli.update_account(a)
            ari = cli.get_show_registry()
            if dry_run == 'false':
                (code, text, resp) = cli.parse_resp(cli.cmdr('RESET ldapAssociation'))
            cli.back()
            logmsg('userReset[' + str(ari['Associated LDAP ID']) + '] ' + a + '@' + d)

        cli.goto_root_context()
        cli.update_domain(d)
        for g in cli.get_groups():
            cli.update_forwarder(g)
            gri = cli.get_show_registry()
            if dry_run == 'false':
                (code, text, resp) = cli.parse_resp(cli.cmdr('RESET ldapAssociation'))
            cli.back()
            logmsg('groupReset[' + str(gri['Associated LDAP ID']) + '] ' + g + '@' + d)

    if dry_run == 'true':
        logmsg('jobFinished DRY_RUN=true')
        sys.exit(0)

    if no_update == 'true':
        logmsg('jobFinished NO_UPDATE=true')
        sys.exit(0)

    for d in domains:
        cli.goto_root_context()
        cli.update_domain(d)
        for a in cli.get_accounts():
            cli.update_account(a)
            cli.config_contactinfo()
            bck = cli.get_show(param='aolScreenName')
            cli.set('aolScreenName "' + bck.replace('"','') + '."')
            cli.done()
            cli.commit()
            cli.update_account(a)
            cli.config_contactinfo()
            cli.set('aolScreenName ' + bck)
            cli.done()
            cli.commit()
            logmsg('userUpdate ' + a + '@' + d)

        cli.goto_root_context()
        cli.update_domain(d)
        for g in cli.get_groups():
            cli.update_forwarder(g)
            p = 'postmaster@'+ d
            if p in cli.list_addresses():
                revert_logic = True
            else:
                revert_logic = False
            (code, text, resp) = cli.parse_resp(cli.cmdr('RESET ldapAssociation'))
            if not revert_logic:
                cli.add_forwarder_address('postmaster')
            else:
                (code, text, resp) = cli.parse_resp(cli.cmdr('REMOVE Address postmaster'))
            cli.commit()
            cli.update_forwarder(g)
            if not revert_logic:
                (code, text, resp) = cli.parse_resp(cli.cmdr('REMOVE Address postmaster'))
            else:
                cli.add_forwarder_address('postmaster')
            cli.commit()
            logmsg('groupUpdate ' + g + '@' + d)

    logmsg('jobFinished normal')

except SystemExit as e:
    sys.exit(e)

except:
    import traceback
    for line in traceback.format_exc().split(os.linesep):
        logmsg('ERR>>> %s' % line)
    logmsg('jobFinished with-errors')
    sys.exit(1)
