#!/usr/bin/python3
#
# Univention Samba4 Password sync
#  sync the password from UCS to Samba4
#
# SPDX-FileCopyrightText: 2010-2025 Univention GmbH
# SPDX-License-Identifier: AGPL-3.0-only


import sys
from argparse import ArgumentParser
from logging import getLogger

import ldap

import univention.admin.uldap
import univention.s4connector.s4.password
import univention.uldap
from univention.config_registry import ConfigRegistry
from univention.logging import Structured


log = Structured(getLogger("LDAP").getChild(__name__))


class S4:

    def __init__(self, ucrbase, binddn, bindpwdfile):
        self.ucrbase = ucrbase
        self.ucr = ConfigRegistry()
        self.ucr.load()

        if binddn:
            self.ucr['%s/ldap/binddn' % (ucrbase,)] = binddn
        if bindpwdfile:
            self.ucr['%s/ldap/bindpw' % (ucrbase,)] = bindpwdfile

        self.s4 = univention.s4connector.s4.s4.main(self.ucr, ucrbase)
        self.s4.init_ldap_connections()
        self.s4._object_mapping = self._object_mapping
        self.s4.modules = {
            "user": univention.admin.modules.get("users/user"),
        }

    def _object_mapping(self, key, object, connection):
        return key

    def sync_password(self, username):
        try:
            ucs_dn = self.s4.lo.lo.search(base=self.s4.lo.base, scope='sub', filter=ldap.filter.filter_format('(&(objectClass=sambaSamAccount)(uid=%s))', [username]), attr=['dn'])[0][0]
        except (ldap.NO_SUCH_OBJECT, IndexError):
            log.process("password_ucs_to_s4: The UCS user (%s) was not found.", username)
            print("password_ucs_to_s4: The UCS user (%s) was not found." % username)
            return
        ucs_object = {}
        ucs_object['dn'] = ucs_dn

        try:
            s4_dn = self.s4.lo_s4.lo.search_s(self.s4.lo_s4.base, ldap.SCOPE_SUBTREE, '(&(objectClass=user)(!(objectClass=computer))(cn=%s))' % username, ['dn'])[0][0]
        except (ldap.NO_SUCH_OBJECT, IndexError):
            log.process("password_ucs_to_s4: The Samba4 user (%s) was not found.", username)
            print("password_ucs_to_s4: The Samba4 user (%s) was not found." % username)
            return
        except ldap.SERVER_DOWN:
            print("Can't initialize Samba4 LDAP connection")
            raise

        s4_object = {}
        s4_object['dn'] = s4_dn
        univention.s4connector.s4.password.password_sync_ucs_to_s4(self.s4, ucs_object, s4_object)


def main():
    parser = ArgumentParser()
    parser.add_argument("--ucrbase", help="", metavar="ucrbase", default="connector")
    parser.add_argument("--binddn", help="Binddn for UCS LDAP connection", default=None)
    parser.add_argument("--bindpwd", help="Not supported anymore.", default=None)
    parser.add_argument("--bindpwdfile", help="Bindpwdfile for UCS LDAP connection", default=None)
    parser.add_argument('username')
    options = parser.parse_args()
    if options.bindpwd:
        parser.error('--bindpwd is not supported anymore!')  # joinscript api: bindpwdfile

    try:
        s4 = S4(options.ucrbase, options.binddn, options.bindpwdfile)
        s4.sync_password(options.username)
    except ldap.SERVER_DOWN:
        sys.exit(1)


if __name__ == '__main__':
    main()
