#!/usr/bin/python2
# coding=utf-8

import ldb
from samba.samdb import SamDB
from samba.auth import system_session
# from samba.ndr import ndr_pack, ndr_unpack
# from samba.dcerpc import security
import samba.param
# import base64
# import binascii
import time

base = "CN=Users,DC=techgrow,DC=local"  # можно не заморачиваться с ОУ и тогда base = "CN=Users,DC=myDom,DC=lan"
domainName = 'techgrow.local'

class UserAd:
    def __init__(self, sam, base, domainName, usrName, usrPass=''):
        self.sam = sam
        self.base = base
        self.domainName = domainName
        self.usrName = usrName
        self.usrPass = usrPass
        self.exists = self.chek_if_exists()
        self.memberOf = self.check_memberof()

    def chek_if_exists(self):
        expression = "(&(objectCategory=person)(objectClass=user)(sAMAccountName=%s))" % self.usrName
        if len(self.sam.search(base=base, expression=expression, attrs=['sAMAccountName'])) > 0:
            return True
        else:
            return False

    def check_memberof(self):
        expression = "(&(objectCategory=person)(objectClass=user)(sAMAccountName=%s))" % self.usrName
        res = self.sam.search(base=base, expression=expression, attrs=['memberOf'])
        groups = []
        if len(res) == 0 or len(res[0]) == 0:
            return groups
        for k in res[0]['memberOf']:
            groups.append(str(k).split(',')[0].split('=')[1])
        return groups

    def add(self):
        ld = {'dn': 'CN=%s,%s' % (self.usrName, base),
              "sAMAccountName": self.usrName,
              "userPrincipalName": "%s@%s" % (self.usrName, self.domainName),
              "objectClass": "user",
              "displayName": self.usrName,
              "description": self.usrName,
              "homeDirectory": r"\\%s\users\%s" % ("dc01", self.usrName),
              'scriptPath': "loginScr.cmd",
              }
        self.sam.transaction_start()
        try:
            self.sam.add(ld)
            self.sam.setpassword("(samAccountName=%s)" % ldb.binary_encode(self.usrName), self.usrPass, False)
        except Exception as exc:
            self.sam.transaction_cancel()
            return exc
        else:
            self.sam.transaction_commit()
            self.exists = self.chek_if_exists()
            return False

    def set_passwd(self):
        self.sam.transaction_start()
        try:
            self.sam.setpassword("(&(objectClass=user)(samAccountName=%s))" % ldb.binary_encode(self.usrName),
                                 self.usrPass, False)
        except Exception as exc:
            self.sam.transaction_cancel()
            return exc
        else:
            self.sam.transaction_commit()
            return False

    def add_in_group(self, grpName):
        self.sam.transaction_start()
        try:
            self.sam.add_remove_group_members(grpName, [self.usrName], add_members_operation=True)
        except Exception as exc:
            self.sam.transaction_cancel()
            return exc
        else:
            self.sam.transaction_commit()
            self.memberOf = self.check_memberof()
            return False

    def remove_from_group(self, grpName):
        self.sam.transaction_start()
        try:
            self.sam.add_remove_group_members(grpName, [self.usrName], add_members_operation=True)
        except Exception as exc:
            self.sam.transaction_cancel()
            return exc
        else:
            self.sam.transaction_commit()
            return False

    def remove(self):
        smb_filter = ("(&(sAMAccountName=%s)(sAMAccountType=805306368))" %
                      ldb.binary_encode(self.usrName))

        try:
            res = self.sam.search(base=self.sam.domain_dn(),
                                  scope=ldb.SCOPE_SUBTREE,
                                  expression=smb_filter,
                                  attrs=["dn"])
            user_dn = res[0].dn
        except IndexError:
            return 'Unable to find user "%s"' % self.usrName

        try:
            self.sam.delete(user_dn)
        except Exception as e:
            return 'Failed to remove user "%s", %s' % (self.usrName, e)
        return False

    def disable(self):
        self.sam.transaction_start()
        try:
            self.sam.disable_account("(&(objectClass=user)(samAccountName=%s))" % ldb.binary_encode(self.usrName))
        except Exception as exc:
            self.sam.transaction_cancel()
            return exc
        else:
            self.sam.transaction_commit()
            return False

    def enable(self):
        self.sam.transaction_start()
        try:
            self.sam.enable_account("(&(objectClass=user)(samAccountName=%s))" % ldb.binary_encode(self.usrName))
        except Exception as exc:
            self.sam.transaction_cancel()
            return exc
        else:
            self.sam.transaction_commit()
            return False


def main():
    lp = samba.param.LoadParm()
    lp.load(samba.param.default_path())  # или lp.load("/etc/samba/smb.conf")
    sam = SamDB(lp=lp, session_info=system_session())
    test_usr = UserAd(sam, base, domainName, 'tst', "secret34daD")
    print test_usr.memberOf
    print "Set disable error: ", test_usr.disable()
    time.sleep(1)
    print "Set enable error: ", test_usr.enable()
    time.sleep(1)
    print "Set remove error: ", test_usr.remove()


if __name__ == '__main__':
    main()