Hello community,

here is the log from the commit of package yast2-aduc for openSUSE:Factory 
checked in at 2019-09-26 20:41:24
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/yast2-aduc (Old)
 and      /work/SRC/openSUSE:Factory/.yast2-aduc.new.2352 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "yast2-aduc"

Thu Sep 26 20:41:24 2019 rev:7 rq:733244 version:1.8

Changes:
--------
--- /work/SRC/openSUSE:Factory/yast2-aduc/yast2-aduc.changes    2019-09-25 
08:27:17.158393649 +0200
+++ /work/SRC/openSUSE:Factory/.yast2-aduc.new.2352/yast2-aduc.changes  
2019-09-26 20:41:27.562506366 +0200
@@ -1,0 +2,6 @@
+Wed Sep 25 20:29:49 UTC 2019 - dmul...@suse.com
+
+- Update to 1.8:
+  + Add ability to change/enable/unlock user's passwords; (bsc#1152052);
+
+-------------------------------------------------------------------

Old:
----
  yast2-aduc-1.7.tar.bz2

New:
----
  yast2-aduc-1.8.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ yast2-aduc.spec ++++++
--- /var/tmp/diff_new_pack.dh13J9/_old  2019-09-26 20:41:28.246504539 +0200
+++ /var/tmp/diff_new_pack.dh13J9/_new  2019-09-26 20:41:28.250504528 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           yast2-aduc
-Version:        1.7
+Version:        1.8
 Release:        0
 Summary:        Active Directory Users and Computers for YaST
 License:        GPL-3.0-only

++++++ yast2-aduc-1.7.tar.bz2 -> yast2-aduc-1.8.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-aduc-1.7/package/yast2-aduc.changes 
new/yast2-aduc-1.8/package/yast2-aduc.changes
--- old/yast2-aduc-1.7/package/yast2-aduc.changes       2019-09-23 
20:03:30.000000000 +0200
+++ new/yast2-aduc-1.8/package/yast2-aduc.changes       2019-09-25 
22:31:56.000000000 +0200
@@ -1,4 +1,10 @@
 -------------------------------------------------------------------
+Wed Sep 25 20:29:49 UTC 2019 - dmul...@suse.com
+
+- Update to 1.8:
+  + Add ability to change/enable/unlock user's passwords; (bsc#1152052);
+
+-------------------------------------------------------------------
 Mon Sep 23 17:10:07 UTC 2019 - dmul...@suse.com
 
 - Update to 1.7:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-aduc-1.7/package/yast2-aduc.spec 
new/yast2-aduc-1.8/package/yast2-aduc.spec
--- old/yast2-aduc-1.7/package/yast2-aduc.spec  2019-09-23 20:03:30.000000000 
+0200
+++ new/yast2-aduc-1.8/package/yast2-aduc.spec  2019-09-25 22:31:56.000000000 
+0200
@@ -17,7 +17,7 @@
 
 
 Name:           yast2-aduc
-Version:        1.7
+Version:        1.8
 Release:        0
 Summary:        Active Directory Users and Computers for YaST
 License:        GPL-3.0-only
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-aduc-1.7/src/include/aduc/complex.py 
new/yast2-aduc-1.8/src/include/aduc/complex.py
--- old/yast2-aduc-1.7/src/include/aduc/complex.py      2019-09-23 
20:03:30.000000000 +0200
+++ new/yast2-aduc-1.8/src/include/aduc/complex.py      2019-09-25 
22:31:56.000000000 +0200
@@ -7,7 +7,8 @@
 import traceback
 from yast import ycpbuiltins
 from adcommon.strings import strcmp, strcasecmp
-from adcommon.yldap import Ldap, LdapException, stringify_ldap, SCOPE_SUBTREE, 
SCOPE_ONELEVEL, SCOPE_BASE, addlist, modlist, y2error_dialog
+from adcommon.yldap import Ldap, LdapException, stringify_ldap, SCOPE_SUBTREE, 
SCOPE_ONELEVEL, SCOPE_BASE, addlist, modlist, y2error_dialog, ldb
+from samba import NTSTATUSError
 
 import six
 
@@ -253,3 +254,38 @@
             ycpbuiltins.y2error(traceback.format_exc())
             ycpbuiltins.y2error('ldap.rename_s: %s\n' % str(e))
             y2error_dialog(str(e))
+
+    def is_user(self, cn, container):
+        SAM_USER_OBJECT = 0x30000000
+        res = self.search(container, SCOPE_ONELEVEL, '(cn=%s)' % cn, 
['sAMAccountType'])
+        if len(res) == 1 and 'sAMAccountType' in res[0].keys():
+            sAMAccountType = int(str(res[0]['sAMAccountType']))
+            if sAMAccountType == SAM_USER_OBJECT:
+                return True
+        return False
+
+    def is_user_enabled(self, cn, container):
+        DISABLED = 0x0002
+        res = self.search(container, SCOPE_ONELEVEL, '(cn=%s)' % cn, 
['userAccountControl'])
+        if len(res) == 1 and 'userAccountControl' in res[0].keys():
+            userAccountControl = int(str(res[0]['userAccountControl']))
+            if not bool(userAccountControl & DISABLED):
+                return True
+        return False
+
+    def reset_password(self, dn, sAMAccountName, password, pwdLastSet, unlock):
+        try:
+            self.net.set_password(sAMAccountName, self.realm, password)
+        except NTSTATUSError as e:
+            y2error_dialog(e.args[-1])
+            return False
+        ldif = 'dn: %s\nchangetype: modify\n' % dn
+        if unlock:
+            ldif += 'replace: lockoutTime\nlockoutTime: 0\n'
+        ldif += 'replace: pwdLastSet\npwdLastSet: %d\n' % pwdLastSet
+        try:
+            self.modify_ldif(ldif)
+        except ldb.LdbError as e:
+            y2error_dialog(e.args[-1])
+            return False
+        return True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-aduc-1.7/src/include/aduc/dialogs.py 
new/yast2-aduc-1.8/src/include/aduc/dialogs.py
--- old/yast2-aduc-1.7/src/include/aduc/dialogs.py      2019-09-23 
20:03:30.000000000 +0200
+++ new/yast2-aduc-1.8/src/include/aduc/dialogs.py      2019-09-25 
22:31:56.000000000 +0200
@@ -12,6 +12,7 @@
 from adcommon.creds import YCreds, switch_domains
 from adcommon.ui import CreateMenu, DeleteButtonBox
 import traceback
+from adcommon.yldap import ldb
 
 def escape_filter_chars(val):
     """ Escape special chars from RFC 4515
@@ -1156,7 +1157,7 @@
         self.got_creds = ycred.Show(self.cred_valid)
         self.realm = self.lp.get('realm')
 
-    def __setup_menus(self, container=None, obj=False):
+    def __setup_menus(self, container=None, obj=None, user=False, 
enabled=True):
         menus = [{'title': '&File', 'id': 'file', 'type': 'Menu'},
                  {'title': 'Change domain...', 'id': 'change_domain', 'type': 
'MenuEntry', 'parent': 'file'},
                  {'title': 'Exit', 'id': 'abort', 'type': 'MenuEntry', 
'parent': 'file'},
@@ -1176,7 +1177,13 @@
             menus.append({'title': 'User', 'id': 'context_add_user', 'type': 
'MenuEntry', 'parent': 'new_but'})
             menus.append({'title': 'Shared Folder', 'id': 
'context_add_shared_folder', 'type': 'MenuEntry', 'parent': 'new_but'})
             menus.append({'title': 'Refresh', 'id': 'refresh', 'type': 
'MenuEntry', 'parent': 'action'})
-        elif obj:
+        if user and enabled:
+            menus.append({'title': 'Disable Account', 'id': 'disable', 'type': 
'MenuEntry', 'parent': 'action'})
+        elif user and not enabled:
+            menus.append({'title': 'Enable Account', 'id': 'enable', 'type': 
'MenuEntry', 'parent': 'action'})
+        if user:
+            menus.append({'title': 'Reset Password...', 'id': 'reset', 'type': 
'MenuEntry', 'parent': 'action'})
+        if obj:
             menus.append({'title': 'Move...', 'id': 'context_move', 'type': 
'MenuEntry', 'parent': 'action'})
             menus.append({'title': 'Delete', 'id': 'delete', 'type': 
'MenuEntry', 'parent': 'action'})
             menus.append({'title': 'Properties', 'id': 'properties', 'type': 
'MenuEntry', 'parent': 'action'})
@@ -1240,12 +1247,21 @@
             #Item(Id('context_help'), 'Help'),
             ])
 
-    def __obj_context_menu(self):
-        return Term('menu', [
-            Item(Id('context_move'), 'Move...'),
+    def __obj_context_menu(self, user=False, enabled=True):
+        items = [
+            Item(Id('context_move'), 'Move...')
+        ]
+        if user and not enabled:
+            items.append(Item(Id('enable'), 'Enable Account'))
+        if user and enabled:
+            items.append(Item(Id('disable'), 'Disable Account'))
+        if user:
+            items.append(Item(Id('reset'), 'Reset Password...'))
+        items.extend([
             Item(Id('properties'), 'Properties'),
             Item(Id('delete'), 'Delete')
         ])
+        return Term('menu', items)
 
     def __dom_context_menu(self):
         return Term('menu', [
@@ -1292,13 +1308,18 @@
             elif str(ret) == 'next':
                 return Symbol('abort')
             elif str(ret) == 'items':
-                self.__setup_menus(obj=True)
+                user = False
+                enabled = True
+                obj = UI.QueryWidget('items', 'CurrentItem')
+                if obj:
+                    user = self.conn.is_user(obj, current_container)
+                    enabled = self.conn.is_user_enabled(obj, current_container)
+                self.__setup_menus(obj=True, user=user, enabled=enabled)
                 if event['EventReason'] == 'ContextMenuActivated':
-                    check = UI.QueryWidget('items', 'CurrentItem')
-                    if check is None:
+                    if obj is None:
                         
UI.OpenContextMenu(self.__objs_context_menu(current_container))
                     else:
-                        UI.OpenContextMenu(self.__obj_context_menu())
+                        UI.OpenContextMenu(self.__obj_context_menu(user=user, 
enabled=enabled))
                 elif event['EventReason'] == 'Activated':
                     self.__show_properties(current_container)
             elif str(ret) == 'properties':
@@ -1389,9 +1410,72 @@
                 if switch_domains(self.lp, self.creds, self.cred_valid):
                     self.realm = self.lp.get('realm')
                     Wizard.SetContents('Active Directory Users and Computers', 
self.__aduc_page(), '', False, False)
+            elif str(ret) == 'enable':
+                obj = UI.QueryWidget('items', 'CurrentItem')
+                searchList = self.conn.objects_list(current_container)
+                currentItem = self.__find_by_name(searchList, obj)
+                if currentItem:
+                    try:
+                        self.conn.enable_account('(sAMAccountName=%s)' % 
currentItem[-1]['sAMAccountName'][-1].decode())
+                    except ldb.LdbError as e:
+                        MessageBox(e.args[-1]).Show()
+                    else:
+                        MessageBox('Object %s has been enabled.' % obj).Show()
+            elif str(ret) == 'disable':
+                obj = UI.QueryWidget('items', 'CurrentItem')
+                searchList = self.conn.objects_list(current_container)
+                currentItem = self.__find_by_name(searchList, obj)
+                if currentItem:
+                    try:
+                        self.conn.disable_account('(sAMAccountName=%s)' % 
currentItem[-1]['sAMAccountName'][-1].decode())
+                    except ldb.LdbError as e:
+                        MessageBox(e.args[-1]).Show()
+                    else:
+                        MessageBox('Object %s has been disabled.' % obj).Show()
+            elif str(ret) == 'reset':
+                obj = UI.QueryWidget('items', 'CurrentItem')
+                searchList = self.conn.objects_list(current_container)
+                currentItem = self.__find_by_name(searchList, obj)
+                if currentItem:
+                    password, pwdLastSet, unlock = self.__reset_password()
+                    if password:
+                        sam = currentItem[-1]['sAMAccountName'][-1].decode()
+                        if self.conn.reset_password(currentItem[0], sam, 
password, pwdLastSet, unlock):
+                            MessageBox('The password for %s has been changed.' 
% obj).Show()
             UI.SetApplicationTitle('Active Directory Users and Computers')
         return Symbol(ret)
 
+    def __reset_password(self):
+        UI.SetApplicationTitle('Reset Password')
+        UI.OpenDialog(HBox(HSpacing(1), VBox(
+            VSpacing(.3),
+            Left(Password(Id('userPassword'), Opt('hstretch'), 'New 
password:')),
+            Left(Password(Id('confirm_passwd'), Opt('hstretch'), 'Confirm 
password:')),
+            Left(CheckBox(Id('pwdLastSet'), Opt('hstretch'), 
UserDataModel['account']['pwdLastSet'], True)),
+            Left(CheckBox(Id('unlock'), Opt('hstretch'), 'Unlock the user\'s 
account', False)),
+            Right(HBox(
+                PushButton(Id('ok'), 'OK'),
+                PushButton(Id('cancel'), 'Cancel')
+            )),
+            VSpacing(.3),
+        ), HSpacing(1)))
+        while True:
+            ret = UI.UserInput()
+            if str(ret) == 'ok':
+                userPassword = UI.QueryWidget('userPassword', 'Value')
+                confirm_passwd = UI.QueryWidget('confirm_passwd', 'Value')
+                if userPassword != confirm_passwd:
+                    self.__warn_message('Active Directory Domain Services', 
'The New and Confirm passwords must match. Please re-type them.')
+                    continue
+                pwdLastSet = 0 if UI.QueryWidget('pwdLastSet', 'Value') else -1
+                unlock = UI.QueryWidget('unlock', 'Value')
+                UI.CloseDialog()
+                return (userPassword, pwdLastSet, unlock)
+            elif str(ret) == 'abort' or str(ret) == 'cancel':
+                break
+        UI.CloseDialog()
+        return (None, None, None)
+
     def __warn_message(self, title, msg):
         if six.PY3 and type(msg) is bytes:
             msg = msg.decode('utf-8')


Reply via email to