Hello community, here is the log from the commit of package yast2-gpmc for openSUSE:Factory checked in at 2019-04-28 20:01:16 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/yast2-gpmc (Old) and /work/SRC/openSUSE:Factory/.yast2-gpmc.new.5536 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "yast2-gpmc" Sun Apr 28 20:01:16 2019 rev:2 rq:694808 version:1.4.2 Changes: -------- --- /work/SRC/openSUSE:Factory/yast2-gpmc/yast2-gpmc.changes 2018-11-13 18:30:16.812925169 +0100 +++ /work/SRC/openSUSE:Factory/.yast2-gpmc.new.5536/yast2-gpmc.changes 2019-04-28 20:01:19.570867155 +0200 @@ -1,0 +2,16 @@ +Fri Mar 15 16:18:08 UTC 2019 - [email protected] + +- Use libsmb instead of the deprecated smb library + +------------------------------------------------------------------- +Thu Mar 14 15:30:58 UTC 2019 - [email protected] + +- Update to 1.4.2: + + Move module to Network Services + + Use samba preg file pack/unpack (Requires samba 4.10) + + Unconfigured/Enable/Disable policy states + + Use common adcommon password prompt (Requires yast2-adcommon-python) + + Add a unified file/actions menu, instead of various buttons + + Allow switching domains + +------------------------------------------------------------------- Old: ---- _service yast2-gpmc-v1.4.1+git.11.e264ccc.tar.bz2 New: ---- yast2-gpmc-1.4.2.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ yast2-gpmc.spec ++++++ --- /var/tmp/diff_new_pack.f4qwdg/_old 2019-04-28 20:01:21.190866178 +0200 +++ /var/tmp/diff_new_pack.f4qwdg/_new 2019-04-28 20:01:21.194866175 +0200 @@ -1,7 +1,7 @@ # # spec file for package yast2-gpmc # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,19 +17,20 @@ Name: yast2-gpmc -Version: 1.4.1+git.11.e264ccc +Version: 1.4.2 Release: 0 Summary: Group Policy Management Console for YaST License: GPL-3.0-only Group: Productivity/Networking/Samba -Url: http://www.github.com/dmulder/yast2-gpmc -Source: %{name}-v%{version}.tar.bz2 +Url: http://www.github.com/yast-samba/yast2-gpmc +Source: %{name}-%{version}.tar.bz2 BuildArch: noarch Requires: krb5-client Requires: python3-ldap Requires: samba-client -Requires: samba-python3 +Requires: samba-python3 >= 4.10.0 Requires: yast2 +Requires: yast2-adcommon-python Requires: yast2-python3-bindings >= 4.0.0 BuildRequires: autoconf BuildRequires: automake @@ -47,10 +48,10 @@ modifying Group Policy Objects in Active Directory. %prep -%setup -q -n %{name}-v%{version} +%setup -q %build -autoreconf -if +make -f Makefile.cvs all CONFIGURE_OPTIONS="\ %if 0%{?is_opensuse} @@ -59,23 +60,19 @@ --disable-experimental \ %endif " - %configure ${CONFIGURE_OPTIONS} -make %{?_smp_mflags} +make %install -%make_install +%yast_install %files %defattr(-,root,root) -%dir %{_datadir}/YaST2/include/gpmc -%{_datadir}/YaST2/clients/gpmc.py -%{_datadir}/YaST2/include/gpmc/complex.py -%{_datadir}/YaST2/include/gpmc/dialogs.py -%{_datadir}/YaST2/include/gpmc/wizards.py -%{_datadir}/YaST2/include/gpmc/defaults.py -%{_datadir}/applications/YaST2/gpmc.desktop -%dir %{_datadir}/doc/yast2-gpmc -%{_datadir}/doc/yast2-gpmc/COPYING +%dir %{yast_yncludedir}/gpmc +%{yast_yncludedir}/gpmc/* +%{yast_clientdir}/*.py +%{yast_desktopdir}/gpmc.desktop +%doc %{yast_docdir} +%license COPYING %changelog ++++++ yast2-gpmc-v1.4.1+git.11.e264ccc.tar.bz2 -> yast2-gpmc-1.4.2.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-gpmc-v1.4.1+git.11.e264ccc/.travis.yml new/yast2-gpmc-1.4.2/.travis.yml --- old/yast2-gpmc-v1.4.1+git.11.e264ccc/.travis.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-gpmc-1.4.2/.travis.yml 2019-03-15 17:19:21.000000000 +0100 @@ -0,0 +1,11 @@ +sudo: required +language: bash +services: + - docker + +before_install: + - docker build -t yast2-gpmc-image . +script: + # the "yast-travis-cpp" script is included in the base yastdevel/cpp image + # see https://github.com/yast/docker-yast-cpp/blob/master/yast-travis-cpp + - docker run -it -e TRAVIS=1 -e TRAVIS_JOB_ID="$TRAVIS_JOB_ID" yast2-gpmc-image yast-travis-cpp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-gpmc-v1.4.1+git.11.e264ccc/Dockerfile new/yast2-gpmc-1.4.2/Dockerfile --- old/yast2-gpmc-v1.4.1+git.11.e264ccc/Dockerfile 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-gpmc-1.4.2/Dockerfile 2019-03-15 17:19:21.000000000 +0100 @@ -0,0 +1,2 @@ +FROM yastdevel/cpp +COPY . /usr/src/app diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-gpmc-v1.4.1+git.11.e264ccc/Makefile.am new/yast2-gpmc-1.4.2/Makefile.am --- old/yast2-gpmc-v1.4.1+git.11.e264ccc/Makefile.am 2018-11-12 08:54:41.000000000 +0100 +++ new/yast2-gpmc-1.4.2/Makefile.am 1970-01-01 01:00:00.000000000 +0100 @@ -1,163 +0,0 @@ -# Emacs: -*- makefile -*- -# -# Toplevel Makefile.am for a YaST2 subproject -# -# -- This file is generated by y2automake - DO NOT EDIT! -- -# (Edit ./SUBDIRS instead) -# - -#where devtools are -Y2TOOL = $(Y2DEVTOOLS_PREFIX)/bin/y2tool - -RPMNAME = $(shell cat $(srcdir)/RPMNAME) -VERSION = $(shell grep -m 1 '^[[:space:]]*Version:' $(srcdir)/package/$(RPMNAME).spec | sed -e 's/Version:[[:space:]]*\([[:print:]]\+\)/\1/') -SUBDIRS_FILE = $(shell test -e $(srcdir)/SUBDIRS && echo SUBDIRS) -ACINCLUDE_FILE = $(shell test -e $(srcdir)/acinclude.m4 && echo acinclude.m4) - -COPYRIGHT_files = COPYING -doc_DATA = $(COPYRIGHT_files) - -# do we do Makefile.am for devtools? It is a little special... -IS_DEVTOOLS = $(findstring yast2-devtools,$(RPMNAME)) - -DEVTOOLS_DIR = $(if $(IS_DEVTOOLS),$(srcdir),$(Y2DEVTOOLS_PREFIX)/share/YaST2/data/devtools) - -# less strict; prefer bzip2 -AUTOMAKE_OPTIONS = foreign dist-bzip2 no-dist-gzip -# where devtools install m4 snippets -# argh, executed literally -#ACLOCAL_AMFLAGS = -I $(Y2DEVTOOLS_PREFIX)/share/aclocal -ACLOCAL_AMFLAGS = -I . -I $(if test -d ./build-tools; then echo ./build-tools; else pkg-config --print-errors --variable=datadir yast2-devtools; fi)/aclocal - -# create bzip2ed tar and make some sanity checks -$(RPMNAME)-$(VERSION).tar.bz2: checkpo dist-bzip2 - @if [ $(bunzip2 -c $(RPMNAME)-$(VERSION).tar.bz2 | wc --bytes) = 0 ] ; then \ - echo "Error: created tar is empty" ; \ - exit 1 ; \ - fi - -CLEANFILES = -MAINTAINERCLEANFILES = package/$(RPMNAME)-$(VERSION).tar.bz2 package/$(RPMNAME).spec - -POT_DST = $(shell find -type d -name testsuite -prune , \ - -type f -name "*.pot") - -EXTRA_DIST = \ - RPMNAME MAINTAINER configure.in.in \ - $(COPYRIGHT_files) \ - $(SUBDIRS_FILE) $(ACINCLUDE_FILE) \ - $(if $(IS_DEVTOOLS),$(POT_DST)) - -show-extra-dist: - @echo $(EXTRA_DIST) - -# info '(automake)Conditionals' -if CREATE_PKGCONFIG -# create the file here instead of by configure -# because the prerequisite is made here (not anymore!) -# and we don't want any paths in y2autoconf -# info '(autoconf)config.status Invocation' -$(RPMNAME).pc: $(RPMNAME).pc.in config.status - ./config.status --file=$@:$< - -if CREATE_PKGCONFIG_NOARCH -pkgconfigdatadir = . -pkgconfigdata_DATA = $(RPMNAME).pc -else -pkgconfigdir = . -pkgconfig_DATA = $(RPMNAME).pc -endif - -EXTRA_DIST += $(RPMNAME).pc.in -endif - -LIBTOOL_DEPS = @LIBTOOL_DEPS@ - -libtool: $(LIBTOOL_DEPS) - $(SHELL) ./config.status libtool - -pot: - $(Y2TOOL) y2makepot -s $(srcdir) - -install-pot: pot - @POT_DST=$(find -type d -name testsuite -prune , \ - -type f -name "*.pot") ; \ - if [ -n "$$POT_DST" ] ; then \ - echo "mkdir -p $(DESTDIR)$(potdir)" ; \ - mkdir -p $(DESTDIR)$(potdir) ; \ - list="$$POT_DST"; \ - for I in $$list ; \ - do \ - echo $$I ; \ - if [ "$$I" == "pot" ] ; then \ - continue ; \ - fi ; \ - echo "$(INSTALL_DATA) $$I $(DESTDIR)$(potdir)" ; \ - $(INSTALL_DATA) $$I $(DESTDIR)$(potdir) ; \ - done ; \ - fi - -spellcheck: pot - $(Y2TOOL) pot-spellcheck - -# all-local: $(if $(IS_DEVTOOLS),,$(POT_DST)) - -package-local: check-parse $(if $(IS_DEVTOOLS),,$(POT_DST)) $(RPMNAME)-$(VERSION).tar.bz2 - rm -f package/$(RPMNAME)-*.tar.bz2 - rm -f package/*~ - rm -f package/*.bak - rm -f package/*.auto - mv $(RPMNAME)-$(VERSION).tar.bz2 package/ - if ! test -x $(Y2TOOL); then \ - echo "$(Y2TOOL): not found."; \ - echo "You have to install yast2-devtools to making a package"; \ - false; \ - fi - here=$(pwd); \ - cd $(srcdir) && for i in $(RPMNAME)*.spec.in; do \ - if [ -f "$$i" ]; then \ - newname="$(echo "$$i" | sed "s/\.in$$//g")"; \ - $(Y2TOOL) create-spec < $$i > $$here/package/$${newname} ; \ - fi \ - done - -package: check-up-to-date check-tagversion check-textdomain package-local - -TAGVERSION = $(Y2TOOL) tagversion - -# check if there is no modified files and all commits were pushed -check-up-to-date: - if [ $(git status --short --branch | sed '/##[^[]*$/d;/^??/d' | wc -l) -gt 0 ]; then \ - (echo "ERROR: Source is not commited and pushed. See `git status`"; false) \ - fi - -check-tagversion: - cd $(srcdir) && $(TAGVERSION) --check >/dev/null; \ - [ $$? = 0 ] || ( echo "ERROR: Please run 'tagversion' first"; false ) - -check-parse-old: - @if [ $(find -type f -name "*.ycp" | wc -l) -gt 0 -a "$(RPMNAME)" != "yast2-core" ] ; then \ - echo "Running parseycp..." ; \ - parseycp -q -R ; \ - else \ - echo "Not running parseycp." ; \ - fi - -check-parse: - @echo "Not running parseycp." - -check-textdomain: - $(Y2TOOL) check-textdomain $(srcdir) - -stable: checkin-stable - -checkin-stable: package - $(Y2TOOL) checkin-stable - - -# For po/ modules -checkpo: - test ! -f $(srcdir)/po/Makefile || $(MAKE) -C po checkpo -# test ! -f $(srcdir)/po/Makefile || $(MAKE) -C po checkpo make-pox -# No ./SUBDIRS file found - assuming default: All direct subdirs with Makefile.am -SUBDIRS = agents doc src diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-gpmc-v1.4.1+git.11.e264ccc/Makefile.cvs new/yast2-gpmc-1.4.2/Makefile.cvs --- old/yast2-gpmc-v1.4.1+git.11.e264ccc/Makefile.cvs 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-gpmc-1.4.2/Makefile.cvs 2019-03-15 17:19:21.000000000 +0100 @@ -0,0 +1,23 @@ +# +# Makefile.cvs +# + +LIB = $(shell y2tool get-lib) + +PREFIX = /usr + +configure: all + ./configure --prefix=$(PREFIX) --libdir=$(PREFIX)/$(LIB) + +all: + y2tool y2autoconf + y2tool y2automake + autoreconf --force --install + +install: configure + make + make install + +reconf: all + ./config.status --recheck + ./config.status diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-gpmc-v1.4.1+git.11.e264ccc/Rakefile new/yast2-gpmc-1.4.2/Rakefile --- old/yast2-gpmc-v1.4.1+git.11.e264ccc/Rakefile 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-gpmc-1.4.2/Rakefile 2019-03-15 17:19:21.000000000 +0100 @@ -0,0 +1,6 @@ +require "yast/rake" + +Yast::Tasks.configuration do |conf| + #lets ignore license check for now + conf.skip_license_check << /.*/ +end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-gpmc-v1.4.1+git.11.e264ccc/SUBDIRS new/yast2-gpmc-1.4.2/SUBDIRS --- old/yast2-gpmc-v1.4.1+git.11.e264ccc/SUBDIRS 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-gpmc-1.4.2/SUBDIRS 2019-03-15 17:19:21.000000000 +0100 @@ -0,0 +1,2 @@ +doc src + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-gpmc-v1.4.1+git.11.e264ccc/configure.ac new/yast2-gpmc-1.4.2/configure.ac --- old/yast2-gpmc-v1.4.1+git.11.e264ccc/configure.ac 2018-11-12 08:54:41.000000000 +0100 +++ new/yast2-gpmc-1.4.2/configure.ac 1970-01-01 01:00:00.000000000 +0100 @@ -1,77 +0,0 @@ -dnl configure.ac for yast2-gpmc -dnl -dnl -- This file is generated by y2autoconf - DO NOT EDIT! -- -dnl (edit configure.ac.in or configure.in.in instead) - -AC_INIT([yast2-gpmc],[1.0],[http://bugs.opensuse.org/],[yast2-gpmc]) -AM_INIT_AUTOMAKE -AM_PATH_PYTHON([2.7]) - -dnl Checks for programs. -AC_PROG_INSTALL -dnl The YCP interpreter checks whether dependent ybc files are older -dnl so we must preserve their timestamps -INSTALL="${INSTALL} -p" -AC_PROG_LN_S -AC_PROG_MAKE_SET - -dnl pkgconfig -AC_ARG_VAR([PKG_CONFIG_PATH], [where to search for pkg-config files]) -dnl devtools -dnl ... - -AC_ARG_ENABLE([experimental], AS_HELP_STRING([--enable-experimental], [Enable experimental features])) - -if test "x$enable_experimental" = "xyes"; then -AC_SUBST([experimental], ['True']) -else -AC_SUBST([experimental], ['False']) -fi - -dnl no need for AC_ARG_VAR -AC_PATH_PROG(XGETTEXT, xgettext) -if test -z "$XGETTEXT" ; then - AC_MSG_ERROR(xgettext is missing; please install gettext-tools.) -fi - -Y2DEVTOOLS_PREFIX=`pkg-config --print-errors --variable=prefix yast2-devtools` -AC_SUBST(Y2DEVTOOLS_PREFIX) -devtools_ybindir=`pkg-config --print-errors --variable=ybindir yast2-devtools` -devtools_yast2dir=`pkg-config --print-errors --variable=yast2dir yast2-devtools` - -dnl producing pkg-config for others? -AM_CONDITIONAL(CREATE_PKGCONFIG, test "x${CREATE_PKGCONFIG}" != x) -AM_CONDITIONAL(CREATE_PKGCONFIG_NOARCH, test "x${CREATE_PKGCONFIG}" = xnoarch) - -dbdir=${devtools_yast2dir}/data/docbook -STYLESHEET_HTML=${dbdir}/stylesheets/customize-html.xsl -STYLESHEET_PDF=${dbdir}/stylesheets/customize-fo.xsl -STYLESHEET_CSS=${dbdir}/css/yast2docs.css -AC_SUBST(STYLESHEET_HTML) -AC_SUBST(STYLESHEET_PDF) -AC_SUBST(STYLESHEET_CSS) - - -AC_CHECK_FILE($devtools_yast2dir/data/testsuite/Makefile.testsuite, [], [ - AC_MSG_WARN([yast2-testsuite.rpm is not installed]) -]) - -# handle .dep files in Makefile.am.common if any YCP module is present -AC_MSG_CHECKING([for YCP modules]) - -# YCP module file name starts with an upper case letter -[find . -type f | grep -q "[[:upper:]][^/]*\.ycp$" && has_ycp_modules=1] -AM_CONDITIONAL([HAS_YCP_MODULES], [test -n "$has_ycp_modules"]) - -if test -n "$has_ycp_modules"; then - AC_MSG_RESULT([found]) -else - AC_MSG_RESULT([not found]) -fi - - -AC_CONFIG_FILES(Makefile agents/Makefile -doc/Makefile -src/Makefile) -AC_OUTPUT - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-gpmc-v1.4.1+git.11.e264ccc/configure.in.in new/yast2-gpmc-1.4.2/configure.in.in --- old/yast2-gpmc-v1.4.1+git.11.e264ccc/configure.in.in 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-gpmc-1.4.2/configure.in.in 2019-03-15 17:19:21.000000000 +0100 @@ -0,0 +1,20 @@ +## YCP module configure.in.in + +## Initialize +@YAST2-INIT-COMMON@ +@YAST2-INIT-YCP@ + +## some common checks +@YAST2-CHECKS-COMMON@ +@YAST2-CHECKS-YCP@ + +AC_ARG_ENABLE([experimental], AS_HELP_STRING([--enable-experimental], [Enable experimental features])) + +if test "x$enable_experimental" = "xyes"; then +AC_SUBST([experimental], ['True']) +else +AC_SUBST([experimental], ['False']) +fi + +## and generate the output... +@YAST2-OUTPUT@ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-gpmc-v1.4.1+git.11.e264ccc/package/yast2-gpmc.changes new/yast2-gpmc-1.4.2/package/yast2-gpmc.changes --- old/yast2-gpmc-v1.4.1+git.11.e264ccc/package/yast2-gpmc.changes 2018-11-12 08:54:41.000000000 +0100 +++ new/yast2-gpmc-1.4.2/package/yast2-gpmc.changes 2019-03-15 17:19:21.000000000 +0100 @@ -1,4 +1,20 @@ ------------------------------------------------------------------- +Fri Mar 15 16:18:08 UTC 2019 - [email protected] + +- Use libsmb instead of the deprecated smb library + +------------------------------------------------------------------- +Thu Mar 14 15:30:58 UTC 2019 - [email protected] + +- Update to 1.4.2: + + Move module to Network Services + + Use samba preg file pack/unpack (Requires samba 4.10) + + Unconfigured/Enable/Disable policy states + + Use common adcommon password prompt (Requires yast2-adcommon-python) + + Add a unified file/actions menu, instead of various buttons + + Allow switching domains + +------------------------------------------------------------------- Thu Nov 1 21:50:27 UTC 2018 - [email protected] - Disable experimental features in sle diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-gpmc-v1.4.1+git.11.e264ccc/package/yast2-gpmc.spec new/yast2-gpmc-1.4.2/package/yast2-gpmc.spec --- old/yast2-gpmc-v1.4.1+git.11.e264ccc/package/yast2-gpmc.spec 2018-11-12 08:54:41.000000000 +0100 +++ new/yast2-gpmc-1.4.2/package/yast2-gpmc.spec 2019-03-15 17:19:21.000000000 +0100 @@ -1,7 +1,7 @@ # # spec file for package yast2-gpmc # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -12,25 +12,26 @@ # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. -# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# Please submit bugfixes or comments via https://bugs.opensuse.org/ # Name: yast2-gpmc -Version: 1.4.1 +Version: 1.4.2 Release: 0 Summary: Group Policy Management Console for YaST -License: GPL-3.0 +License: GPL-3.0-only Group: Productivity/Networking/Samba -Url: http://www.github.com/dmulder/yast2-gpmc -Source: %{name}-v%{version}.tar.bz2 +Url: http://www.github.com/yast-samba/yast2-gpmc +Source: %{name}-%{version}.tar.bz2 BuildArch: noarch Requires: krb5-client Requires: python3-ldap Requires: samba-client -Requires: samba-python3 +Requires: samba-python3 >= 4.10.0 Requires: yast2 Requires: yast2-python3-bindings >= 4.0.0 +Requires: yast2-adcommon-python BuildRequires: autoconf BuildRequires: automake BuildRequires: perl-XML-Writer @@ -47,10 +48,10 @@ modifying Group Policy Objects in Active Directory. %prep -%setup -q -n %{name}-v%{version} +%setup -q %build -autoreconf -if +make -f Makefile.cvs all CONFIGURE_OPTIONS="\ %if 0%{?is_opensuse} @@ -59,23 +60,19 @@ --disable-experimental \ %endif " - %configure ${CONFIGURE_OPTIONS} -make %{?_smp_mflags} +make %install -%make_install +%yast_install %files %defattr(-,root,root) -%dir %{_datadir}/YaST2/include/gpmc -%{_datadir}/YaST2/clients/gpmc.py -%{_datadir}/YaST2/include/gpmc/complex.py -%{_datadir}/YaST2/include/gpmc/dialogs.py -%{_datadir}/YaST2/include/gpmc/wizards.py -%{_datadir}/YaST2/include/gpmc/defaults.py -%{_datadir}/applications/YaST2/gpmc.desktop -%dir %{_datadir}/doc/yast2-gpmc -%{_datadir}/doc/yast2-gpmc/COPYING +%dir %{yast_yncludedir}/gpmc +%{yast_yncludedir}/gpmc/* +%{yast_clientdir}/*.py +%{yast_desktopdir}/gpmc.desktop +%doc %{yast_docdir} +%license COPYING %changelog diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-gpmc-v1.4.1+git.11.e264ccc/src/complex.py new/yast2-gpmc-1.4.2/src/complex.py --- old/yast2-gpmc-v1.4.1+git.11.e264ccc/src/complex.py 2018-11-12 08:54:41.000000000 +0100 +++ new/yast2-gpmc-1.4.2/src/complex.py 2019-03-15 17:19:21.000000000 +0100 @@ -1,6 +1,5 @@ from __future__ import absolute_import, division, print_function, unicode_literals -import ldap, ldap.modlist, ldap.sasl -from samba import smb +from samba.samba3 import libsmb_samba_internal as smb, param as s3param import six if six.PY3: def ConfigParser(**kwargs): @@ -15,47 +14,21 @@ from samba.dcerpc import nbt from subprocess import Popen, PIPE import uuid -from ldap.modlist import addModlist as addlist -from ldap.modlist import modifyModlist as modlist import re import traceback import ldb from samba.dcerpc import security -from samba.ndr import ndr_unpack import samba.security from samba.ntacls import dsacl2fsacl from yast import ycpbuiltins import struct from samba import registry from collections import OrderedDict - -def strcmp(first, second): - if six.PY3: - if isinstance(first, six.string_types): - first = six.binary_type(first, 'utf8') - if isinstance(second, six.string_types): - second = six.binary_type(second, 'utf8') - return first == second - -def strcasecmp(first, second): - if six.PY3: - if isinstance(first, six.string_types): - first = six.binary_type(first, 'utf8') - if isinstance(second, six.string_types): - second = six.binary_type(second, 'utf8') - return first.lower() == second.lower() - -class LdapException(Exception): - def __init__(self, *args, **kwargs): - Exception.__init__(self, *args, **kwargs) - if len(self.args) > 0: - self.msg = self.args[0] - else: - self.msg = None - if len(self.args) > 1: - self.info = self.args[1] - else: - self.info = None +from samba.ndr import ndr_unpack, ndr_pack +from samba.dcerpc import preg +from adcommon.creds import kinit_for_gssapi +from adcommon.yldap import Ldap, LdapException, SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, addlist, modlist +from adcommon.strings import strcmp, strcasecmp def open_bytes(filename): if six.PY3: @@ -144,132 +117,10 @@ ret += "[LDAP://%s;%d]" % (g['dn'], g['options']) return ret -REGFILE_SIGNATURE = 0x67655250 -REGISTRY_FILE_VERSION = 1 -def unpack_registry_pol(data): - pol_conf = OrderedDict() - sig = struct.unpack('<L', data[:4])[0] - if sig != REGFILE_SIGNATURE: - raise IOError('Registry file signature did not match') - vers = struct.unpack('<L', data[4:8])[0] - if vers != REGISTRY_FILE_VERSION: - raise IOError('Registry file version did not match') - o = 7 - while o < len(data)-1: - obrack = data[o:o+2].decode('utf-16-be') - if obrack != '[': - raise IOError('Failed unpacking data from registry pol') - o += 2 - rk_epos = data[o:].find(b';')-1 - if rk_epos < 0: - raise IOError('Failed unpacking data from registry pol') - try: - reg_key = data[o:o+rk_epos-2].decode('utf-16-be') - except UnicodeDecodeError: - raise IOError('Failed unpacking data from registry pol') - if not reg_key in pol_conf.keys(): - pol_conf[reg_key] = {} - o += rk_epos - osep = data[o:o+2].decode('utf-16-be') - if osep != ';': - raise IOError('Failed unpacking data from registry pol') - o += 2 - rk_epos = data[o:].find(b';')-1 - if rk_epos < 0: - raise IOError('Failed unpacking data from registry pol') - key = data[o:o+rk_epos-2].decode('utf-16-be') - o += rk_epos - osep = data[o:o+2].decode('utf-16-be') - if osep != ';': - raise IOError('Failed unpacking data from registry pol') - o += 2 - rk_epos = data[o:].find(b';')-1 - if rk_epos < 0: - raise IOError('Failed unpacking data from registry pol') - ntype = struct.unpack(">Hxx", data[o:o+rk_epos])[0] - rtype = registry.str_regtype(ntype) - o += rk_epos - osep = data[o:o+2].decode('utf-16-be') - if osep != ';': - raise IOError('Failed unpacking data from registry pol') - o += 2 - rsize = struct.unpack("<xHx", data[o:o+4])[0] - o += 4 - osep = data[o:o+2].decode('utf-16-be') - if osep != ';': - raise IOError('Failed unpacking data from registry pol') - o += 2 - if rtype == 'REG_SZ': - val = data[o:o+rsize][:-2].decode('utf-16-be') - elif rtype == 'REG_DWORD': - val = struct.unpack("<xHx", data[o:o+rsize])[0] - elif rtype == 'REG_BINARY': - val = data[o:o+rsize] - elif rtype == 'REG_NONE': - val = None - else: - ycpbuiltins.y2warning('%s Not Implemented' % rtype) - raise IOError('Failed unpacking value from registry pol') - o += rsize - cbrack = data[o:o+2] - if cbrack != b'\x00]' and cbrack != b'<]': - raise IOError('Failed unpacking data from registry pol') - o += 2 - - pol_conf[reg_key][key] = {} - pol_conf[reg_key][key]['value'] = val - pol_conf[reg_key][key]['type'] = ntype - pol_conf[reg_key][key]['size'] = rsize - return pol_conf - -def pack_registry_pol(pol_conf): - ret = struct.pack('<L', REGFILE_SIGNATURE) - ret += struct.pack('<Hx', REGISTRY_FILE_VERSION) - for reg_key in pol_conf.keys(): - for key in pol_conf[reg_key].keys(): - ret += b'\x00[' - ret += reg_key.encode('utf-16-be') - ret += b'\x00\x00' - ret += b'\x00;' - ret += key.encode('utf-16-be') - ret += b'\x00\x00' - ret += b'\x00;' - ret += struct.pack(">Hxx", pol_conf[reg_key][key]['type']) - ret += b'\x00;' - ret += struct.pack("<xHx", pol_conf[reg_key][key]['size']) - ret += b'\x00;' - rtype = registry.str_regtype(pol_conf[reg_key][key]['type']) - if rtype == 'REG_SZ': - ret += pol_conf[reg_key][key]['value'].encode('utf-16-be') + b'\x00\x00' - elif rtype == 'REG_DWORD': - ret += struct.pack("<xHx", pol_conf[reg_key][key]['value']) - elif rtype == 'REG_BINARY': - ret += pol_conf[reg_key][key]['value'] - elif rtype == 'REG_NONE': - pass - else: - raise IOError('Failed packing value for registry pol') - if rtype == 'REG_BINARY': - ret += b'<]' - else: - ret += b'\x00]' - ret += b'\x00' - return ret - -class GPConnection: +class GPConnection(Ldap): def __init__(self, lp, creds): - self.lp = lp - self.creds = creds - self.realm = lp.get('realm') + super().__init__(lp, creds) self.kinit = False - self.__ldap_connect() - - def __kinit_for_gssapi(self): - p = Popen(['kinit', '%s@%s' % (self.creds.get_username(), self.realm) if not self.realm in self.creds.get_username() else self.creds.get_username()], stdin=PIPE, stdout=PIPE, stderr=PIPE) - p.stdin.write(('%s\n' % self.creds.get_password()).encode()) - p.stdin.flush() - self.kinit = p.wait() == 0 - return self.kinit def realm_to_dn(self, realm): return ','.join(['DC=%s' % part for part in realm.lower().split('.')]) @@ -284,7 +135,7 @@ wkguiduc = 'A361B2FFFFD211D1AA4B00C04FD7D83A' elif strcmp(container, 'users'): wkguiduc = 'A9D1CA15768811D1ADED00C04FD8D5CD' - result = self.ldap_search_s('<WKGUID=%s,%s>' % (wkguiduc, self.realm_to_dn(self.realm)), ldap.SCOPE_SUBTREE, '(objectClass=container)', stringify_ldap(['distinguishedName'])) + result = self.ldap_search_s('<WKGUID=%s,%s>' % (wkguiduc, self.realm_to_dn(self.realm)), SCOPE_SUBTREE, '(objectClass=container)', stringify_ldap(['distinguishedName'])) result = stringify_ldap(result) if result and len(result) > 0 and len(result[0]) > 1 and 'distinguishedName' in result[0][1] and len(result[0][1]['distinguishedName']) > 0: res = result[0][1]['distinguishedName'][-1] @@ -292,11 +143,11 @@ return stringify_ldap(res) def user_from_sid(self, sid, attrs=[]): - res = self.ldap_search(self.__well_known_container('users'), ldap.SCOPE_SUBTREE, '(objectSID=%s)' % sid, stringify_ldap(attrs)) + res = self.ldap_search(self.__well_known_container('users'), SCOPE_SUBTREE, '(objectSID=%s)' % sid, stringify_ldap(attrs)) return res[0][1] def get_domain_sid(self): - res = self.ldap_search(self.realm_to_dn(self.realm), ldap.SCOPE_BASE, "(objectClass=*)", []) + res = self.ldap_search(self.realm_to_dn(self.realm), SCOPE_BASE, "(objectClass=*)", []) return ndr_unpack(security.dom_sid, res[0][1]["objectSid"][0]) def gpo_list(self, displayName=None, attrs=[]): @@ -305,7 +156,7 @@ search_expr = '(objectClass=groupPolicyContainer)' if displayName is not None: search_expr = '(&(objectClass=groupPolicyContainer)(displayname=%s))' % ldb.binary_encode(displayName) - result = self.ldap_search(res, ldap.SCOPE_SUBTREE, search_expr, stringify_ldap(attrs)) + result = self.ldap_search(res, SCOPE_SUBTREE, search_expr, stringify_ldap(attrs)) result = stringify_ldap(result) return result @@ -332,7 +183,7 @@ gpo = GPOConnection(self.lp, self.creds, unc_path) try: - self.ldap_add(dn, addlist(stringify_ldap(ldap_mod))) + self.ldap_add(dn, addlist(ldap_mod)) self.ldap_add(machine_dn, addlist(stringify_ldap(sub_ldap_mod))) self.ldap_add(user_dn, addlist(stringify_ldap(sub_ldap_mod))) except LdapException as e: @@ -350,7 +201,7 @@ gplink_options |= (1 << 1) # Check if valid Container DN - msg = self.ldap_search(container_dn, ldap.SCOPE_BASE, + msg = self.ldap_search(container_dn, SCOPE_BASE, "(objectClass=*)", stringify_ldap(['gPLink']))[0][1] @@ -383,7 +234,7 @@ def delete_link(self, gpo_dn, container_dn): # Check if valid Container DN - msg = self.ldap_search(container_dn, ldap.SCOPE_BASE, + msg = self.ldap_search(container_dn, SCOPE_BASE, "(objectClass=*)", stringify_ldap(['gPLink']))[0][1] @@ -437,7 +288,7 @@ '''lists dn of containers for a GPO''' search_expr = "(&(objectClass=*)(gPLink=*%s*))" % gpo - msg = self.ldap_search(self.realm_to_dn(self.realm), ldap.SCOPE_SUBTREE, search_expr, []) + msg = self.ldap_search(self.realm_to_dn(self.realm), SCOPE_SUBTREE, search_expr, []) if not msg: return [] @@ -445,7 +296,7 @@ def get_gpos_for_container(self, container_dn): search_expr = '(distinguishedName=%s)' % container_dn - msg = self.ldap_search(self.realm_to_dn(self.realm), ldap.SCOPE_SUBTREE, search_expr, []) + msg = self.ldap_search(self.realm_to_dn(self.realm), SCOPE_SUBTREE, search_expr, []) if not msg: return None @@ -456,112 +307,19 @@ gpos = [] for gpo in gpos: search_expr = '(distinguishedName=%s)' % gpos[gpo]['dn'] - msg = self.ldap_search(self.realm_to_dn(self.realm), ldap.SCOPE_SUBTREE, search_expr, []) + msg = self.ldap_search(self.realm_to_dn(self.realm), SCOPE_SUBTREE, search_expr, []) results.append(msg[0]) return results def get_containers_with_gpos(self): search_expr = "(|(objectClass=organizationalUnit)(objectClass=domain))" - msg = self.ldap_search(self.realm_to_dn(self.realm), ldap.SCOPE_SUBTREE, search_expr, []) + msg = self.ldap_search(self.realm_to_dn(self.realm), SCOPE_SUBTREE, search_expr, []) if not msg: return [] return [res[1] for res in msg if type(res[1]) is dict] - def __ldap_exc_msg(self, e): - if len(e.args) > 0 and \ - type(e.args[-1]) is dict and \ - 'desc' in e.args[-1]: - return e.args[-1]['desc'] - else: - return str(e) - - def __ldap_exc_info(self, e): - if len(e.args) > 0 and \ - type(e.args[-1]) is dict and \ - 'info' in e.args[-1]: - return e.args[-1]['info'] - else: - return '' - - def __ldap_connect(self): - self.net = Net(creds=self.creds, lp=self.lp) - cldap_ret = self.net.finddc(domain=self.realm, flags=(nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE)) - self.dc_hostname = cldap_ret.pdc_dns_name - self.l = ldap.initialize('ldap://%s' % cldap_ret.pdc_dns_name) - if self.kinit or self.__kinit_for_gssapi(): - auth_tokens = ldap.sasl.gssapi('') - self.l.sasl_interactive_bind_s('', auth_tokens) - else: - ycpbuiltins.y2error('Failed to initialize ldap connection') - raise Exception('Failed to initialize ldap connection') - - def ldap_search_s(self, *args): - try: - try: - return self.l.search_s(*args) - except ldap.SERVER_DOWN: - self.__ldap_connect() - return self.l.search_s(*args) - except Exception as e: - ycpbuiltins.y2error(traceback.format_exc()) - ycpbuiltins.y2error('ldap.search_s: %s\n' % self.__ldap_exc_msg(e)) - - def ldap_search(self, *args): - result = [] - try: - try: - res_id = self.l.search(*args) - except ldap.SERVER_DOWN: - self.__ldap_connect() - res_id = self.l.search(*args) - while 1: - t, d = self.l.result(res_id, 0) - if d == []: - break - else: - if t == ldap.RES_SEARCH_ENTRY: - result.append(d[0]) - except ldap.LDAPError: - pass - except Exception as e: - ycpbuiltins.y2error(traceback.format_exc()) - ycpbuiltins.y2error('ldap.search: %s\n' % self.__ldap_exc_msg(e)) - return result - - def ldap_add(self, *args): - try: - try: - return self.l.add_s(*args) - except ldap.SERVER_DOWN: - self.__ldap_connect() - return self.l.add_s(*args) - except Exception as e: - raise LdapException(self.__ldap_exc_msg(e), self.__ldap_exc_info(e)) - - def ldap_modify(self, *args): - try: - try: - return self.l.modify(*args) - except ldap.SERVER_DOWN: - self.__ldap_connect() - return self.l.modify(*args) - except Exception as e: - ycpbuiltins.y2error(traceback.format_exc()) - ycpbuiltins.y2error('ldap.modify: %s\n' % self.__ldap_exc_msg(e)) - - def ldap_delete(self, *args): - try: - try: - return self.l.delete_s(*args) - except ldap.SERVER_DOWN: - self.__ldap_connect() - return self.l.delete_s(*args) - except Exception as e: - ycpbuiltins.y2error(traceback.format_exc()) - ycpbuiltins.y2error('ldap.delete_s: %s\n' % self.__ldap_exc_msg(e)) - class GPOConnection(GPConnection): def __init__(self, lp, creds, gpo_path): GPConnection.__init__(self, lp, creds) @@ -573,8 +331,12 @@ self.name = gpo_path.split('\\')[-1] self.realm_dn = self.realm_to_dn(self.realm) self.gpo_dn = 'CN=%s,CN=Policies,CN=System,%s' % (self.name, self.realm_dn) + # the SMB bindings rely on having a s3 loadparm + s3_lp = s3param.get_context() + s3_lp.load(self.lp.configfile) + s3_lp.set('realm', self.lp.get('realm')) try: - self.conn = smb.SMB(self.dc_hostname, service, lp=self.lp, creds=self.creds) + self.conn = smb.Conn(self.dc_hostname, service, lp=s3_lp, creds=self.creds, sign=True) except Exception as e: ycpbuiltins.y2error(traceback.format_exc()) ycpbuiltins.y2error("Exception %s"%str(e)) @@ -694,7 +456,7 @@ def __parse_dn(self, dn): dn = dn % self.gpo_dn - resp = self.ldap_search(dn, ldap.SCOPE_SUBTREE, '(objectCategory=packageRegistration)', []) + resp = self.ldap_search(dn, SCOPE_SUBTREE, '(objectCategory=packageRegistration)', []) resp = stringify_ldap(resp) if resp: keys = ['objectClass', 'msiFileList', 'msiScriptPath', 'displayName', 'versionNumberHi', 'versionNumberLo'] @@ -784,9 +546,9 @@ try: path = os.path.relpath(os.path.join(self.path, filename).replace('\\', '/')).replace('/', '\\') raw = self.conn.loadfile(path) - pol_conf = unpack_registry_pol(raw) + pol_conf = ndr_unpack(preg.file, raw) except: - pol_conf = None + pol_conf = preg.file() return pol_conf def __smb_mkdir_p(self, path): @@ -817,6 +579,7 @@ if six.PY3 and type(text) is str: text = text.encode('utf-8') try: + self.conn.unlink(path) self.conn.savefile(path, text) except Exception as e: if e.args[0] == 0xC000003A: # STATUS_OBJECT_PATH_NOT_FOUND @@ -835,7 +598,7 @@ self.__write(filename, value) def __write_reg(self, filename, pol_conf): - buf = pack_registry_pol(pol_conf) + buf = ndr_pack(pol_conf) self.__write(filename, buf) def upload_file(self, local, remote_dir): @@ -847,6 +610,7 @@ if six.PY3 and type(value) is str: value = value.encode('utf-8') try: + self.conn.unlink(filename) self.conn.savefile(filename, value) except Exception as e: if e.args[0] == 0xC0000035: # STATUS_OBJECT_NAME_COLLISION diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-gpmc-v1.4.1+git.11.e264ccc/src/defaults.py new/yast2-gpmc-1.4.2/src/defaults.py --- old/yast2-gpmc-v1.4.1+git.11.e264ccc/src/defaults.py 2018-11-12 08:54:41.000000000 +0100 +++ new/yast2-gpmc-1.4.2/src/defaults.py 2019-03-15 17:19:21.000000000 +0100 @@ -3,10 +3,57 @@ import uuid import os.path from subprocess import Popen, PIPE +from complex import strcmp +from samba.dcerpc import preg +import six from yast import import_module import_module('UI') from yast import UI + +def delete_admx_value(conf, reg_key, key): + entries = [] + for x in conf.entries: + if not (strcmp(x.keyname, reg_key) and strcmp(x.valuename, key)): + entries.append(x) + conf.num_entries = len(entries) + conf.entries = entries + +def set_admx_value(conf, reg_key, key, val, val_type): + if val == None: + return delete_admx_value(conf, reg_key, key) + e = preg.entry() + e.keyname = six.b(reg_key) + e.valuename = six.b(key) + if val_type == 'TextEntry': + e.type = 1 + e.data = six.b(val) + elif val_type == 'IntField': + e.type = 4 + e.data = int(val) + elif val_type == 'CheckBox': + e.type = 4 + e.data = 1 if val else 0 + entries = [] + for x in conf.entries: + if not (strcmp(x.keyname, reg_key) and strcmp(x.valuename, key)): + entries.append(x) + entries.append(e) + conf.num_entries = len(entries) + conf.entries = entries + +def get_admx_value(conf, reg_key, key): + for e in conf.entries: + if strcmp(e.keyname, reg_key) and strcmp(e.valuename, key): + return e.data + return None + +def get_admx_configured(conf, reg_key, key): + for e in conf.entries: + if strcmp(e.keyname, reg_key) and strcmp(e.valuename, key): + return True + return False + def select_script(title, policy, conn): full_path = UI.AskForExistingFile('/', '*.sh *.py *.pl', title) if policy == 'comp_scripts_shutdown': diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-gpmc-v1.4.1+git.11.e264ccc/src/dialogs.py.in new/yast2-gpmc-1.4.2/src/dialogs.py.in --- old/yast2-gpmc-v1.4.1+git.11.e264ccc/src/dialogs.py.in 2018-11-12 08:54:41.000000000 +0100 +++ new/yast2-gpmc-1.4.2/src/dialogs.py.in 2019-03-15 17:19:21.000000000 +0100 @@ -1,6 +1,7 @@ from __future__ import absolute_import, division, print_function, unicode_literals -from defaults import Policies, fetch_inf_value -from complex import GPConnection, GPOConnection, dn_to_path, parse_gplink, strcmp, strcasecmp +from defaults import Policies, fetch_inf_value, set_admx_value, get_admx_value, get_admx_configured +from complex import GPConnection, GPOConnection, dn_to_path, parse_gplink +from adcommon.strings import strcmp, strcasecmp from yast import import_module import_module('Wizard') import_module('UI') @@ -13,36 +14,30 @@ from samba.ntacls import dsacl2fsacl import os.path from itertools import chain +from samba.dcerpc import preg +import six +from adcommon.creds import YCreds, switch_domains +from adcommon.ui import CreateMenu, DeleteButtonBox ENABLE_EXPERIMENTAL = @ENABLE_EXPERIMENTAL@ -def have_x(): - from subprocess import Popen, PIPE - p = Popen(['xset', '-q'], stdout=PIPE, stderr=PIPE) - return p.wait() == 0 -have_advanced_gui = have_x() - selected_gpo = None -def set_admx_value(conf, reg_key, key, val): - conf[reg_key][key]['value'] = val - class GPME: def __init__(self, lp, creds): global selected_gpo self.conn = GPOConnection(lp, creds, selected_gpo[1]['gPCFileSysPath'][-1]) def __reset(self): - global have_advanced_gui - if not have_advanced_gui: - Wizard.RestoreNextButton() UI.SetApplicationTitle('Group Policy Management Editor') Wizard.SetContentsButtons('Group Policy Management Editor', self.__gpme_page(), 'Group Policy Management Editor', '', 'Close') - if have_advanced_gui: - Wizard.HideNextButton() - else: - Wizard.HideAbortButton() - Wizard.HideBackButton() + self.__setup_menus() + DeleteButtonBox() + + def __setup_menus(self): + menus = [{'title': '&File', 'id': 'file', 'type': 'Menu'}, + {'title': 'Exit', 'id': 'abort', 'type': 'MenuEntry', 'parent': 'file'}] + CreateMenu(menus) def Show(self): if not self.conn: @@ -75,10 +70,17 @@ subret = UI.UserInput() if str(subret) == 'ok_change_setting' or str(subret) == 'apply_change_setting': for k in values.keys(): - if values[k]['set'] or values[k]['input']['options']: - value = UI.QueryWidget('entry_%s' % k, 'Value') - if values[k]['input']['options']: - value = values[k]['input']['options'][value.strip()] + if 'configurable' in values[k]['input'] and values[k]['input']['configurable']: + configured = UI.QueryWidget('configured_%s' % k, 'Value') + if configured or configured == None: + value = UI.QueryWidget('entry_%s' % k, 'Value') + else: + value = None + else: + if values[k]['set'] or values[k]['input']['options']: + value = UI.QueryWidget('entry_%s' % k, 'Value') + if values[k]['input']['options']: + value = values[k]['input']['options'][value.strip()] if values[k]['set']: if type(value) is str: value = value.strip() @@ -99,6 +101,9 @@ break UI.ReplaceWidget('rightPane', self.__display_policy(policy)) UI.SetFocus(str(ret)) + elif str(ret) == 'delete_policy': + selection = UI.QueryWidget(str(ret), 'CurrentItem') + Policies[policy]['delete'](conf, selection) return Symbol(ret) @@ -122,8 +127,15 @@ if not value[-1]['input']: continue if strcmp(value[-1]['input']['type'], 'TextEntry'): + configurable = Empty() + configured = value[-1]['get'] != None + if 'configurable' in value[-1]['input'] and value[-1]['input']['configurable']: + configurable = CheckBox(Id('configured_%s' % k), Opt('hstretch'), 'Configured', configured) items.append(Top(MinWidth(30, Left( - ReplacePoint(Id('text_entry_%s' % k), TextEntry(Id('entry_%s' % k), Opt('hstretch'), value[-1]['title'], value[-1]['get'] if value[-1]['get'] else '')), + ReplacePoint(Id('text_entry_%s' % k), VBox( + configurable, + TextEntry(Id('entry_%s' % k), Opt('hstretch'), value[-1]['title'], value[-1]['get'] if value[-1]['get'] else '') + )), )))) elif strcmp(value[-1]['input']['type'], 'ComboBox'): combo_options = [] @@ -147,13 +159,30 @@ ) )))) elif strcmp(value[-1]['input']['type'], 'IntField'): + configurable = Empty() + configured = value[-1]['get'] != None + if 'configurable' in value[-1]['input'] and value[-1]['input']['configurable']: + configurable = CheckBox(Id('configured_%s' % k), Opt('hstretch'), 'Configured', configured) items.append(Top(MinWidth(30, Left( - ReplacePoint(Id('int_field_%s' % k), IntField(Id('entry_%s' % k), Opt('hstretch'), value[-1]['title'], 0, 999999999, value[-1]['get'] if value[-1]['get'] else 0)) + ReplacePoint(Id('int_field_%s' % k), VBox( + configurable, + IntField(Id('entry_%s' % k), Opt('hstretch'), value[-1]['title'], 0, 999999999, value[-1]['get'] if value[-1]['get'] else 0) + )) )))) elif strcmp(value[-1]['input']['type'], 'CheckBox'): - items.append(Top(Left( - ReplacePoint(Id('check_box_%s' % k), CheckBox(Id('entry_%s' % k), Opt('hstretch'), value[-1]['title'], bool(value[-1]['get']) if value[-1]['get'] else False)) - ))) + if 'configurable' in value[-1]['input'] and value[-1]['input']['configurable']: + disp = value[-1]['valstr'](value[-1]['get']) + items.append(Top(Left( + ReplacePoint(Id('check_box_%s' % k), RadioButtonGroup(Id('entry_%s' % k), VBox( + Left(RadioButton(Id(None), 'Not Configured', strcmp(disp, 'Not configured'))), + Left(RadioButton(Id(True), 'Enabled', strcmp(disp, 'Enabled'))), + Left(RadioButton(Id(False), 'Disabled', strcmp(disp, 'Disabled'))) + ))) + ))) + else: + items.append(Top(Left( + ReplacePoint(Id('check_box_%s' % k), CheckBox(Id('entry_%s' % k), Opt('hstretch'), value[-1]['title'], bool(value[-1]['get']) if value[-1]['get'] else False)) + ))) if reverse: items.reverse() items = tuple(items) @@ -197,7 +226,8 @@ buttons = [] if terms['add']: buttons.append(PushButton(Id('add_policy'), 'Add')) - buttons.append(PushButton(Id('delete_policy'), 'Delete')) + if 'delete' in terms.keys(): + buttons.append(PushButton(Id('delete_policy'), 'Delete')) buttons = tuple(buttons) return VBox( @@ -277,7 +307,7 @@ Policies[parent]['add'] = None Policies[parent]['header'] = (lambda : ['Setting', 'Value']) Policies[parent]['values'] = \ - (lambda conf, reg_key, key, desc, valstr, _input : { + (lambda conf, reg_key, key, desc, valstr, val_type, _input : { 'setting' : { 'order' : 0, 'title' : 'Setting', @@ -293,9 +323,9 @@ 'value' : { 'order' : 1, 'title' : key, - 'get' : conf[reg_key][key]['value'] if reg_key in conf and key in conf[reg_key] else '', - 'set' : (lambda v : set_admx_value(conf, reg_key, key, v)), - 'valstr' : valstr, + 'get' : get_admx_value(conf, reg_key, key), + 'set' : (lambda v : set_admx_value(conf, reg_key, key, v, val_type)), + 'valstr' : (lambda v : valstr(v) if get_admx_configured(conf, reg_key, key) else 'Not configured'), 'input' : _input, }, } ) @@ -310,19 +340,21 @@ values[disp] = {} val_type = None elements = policy.find('elements') + defined = get_admx_configured(conf, policy.attrib['key'], disp) if elements.find('text') is not None: val_type = 'TextEntry' - val_str = (lambda v : v if v else 'Not Defined') + val_str = (lambda v : v if v else '') elif elements.find('decimal') is not None: val_type = 'IntField' - val_str = (lambda v : v if v else 'Not Defined') + val_str = (lambda v : v) elif elements.find('boolean') is not None: val_type = 'CheckBox' - val_str = (lambda v : 'Not Defined' if not v else 'Disabled' if int(v) == 0 else 'Enabled') + val_str = (lambda v : 'Disabled' if int(v) == 0 else 'Enabled') values[disp]['values'] = Policies[parent]['values']( - conf, policy.attrib['key'], disp, desc, val_str, + conf, policy.attrib['key'], disp, desc, val_str, val_type, { 'type' : val_type, + 'configurable' : True, 'options' : None, }, ) @@ -374,12 +406,12 @@ os_settings_items ) ) - if ENABLE_EXPERIMENTAL: - policy_items.append( - Item('Administrative Templates', False, - admin_templates - ) + + policy_items.append( + Item('Administrative Templates', False, + admin_templates ) + ) computer_config = [ Item('Policies', False, @@ -442,66 +474,52 @@ class GPMC: def __init__(self, lp, creds): - global selected_gpo, have_advanced_gui + global selected_gpo self.realm = lp.get('realm') self.lp = lp self.creds = creds self.gpos = [] selected_gpo = None self.__setup_menus() - if have_advanced_gui: - Wizard.HideAbortButton() - Wizard.HideBackButton() - Wizard.HideNextButton() - self.got_creds = self.__get_creds(creds) - while self.got_creds: + DeleteButtonBox() + ycred = YCreds(creds, auto_krb5_creds=False) + def cred_valid(): try: self.q = GPConnection(lp, creds) self.gpos = self.q.gpo_list() self.realm_dn = self.q.realm_to_dn(self.realm) - break + return True except Exception as e: ycpbuiltins.y2error(str(e)) - creds.set_password('') - self.got_creds = self.__get_creds(creds) + return False + self.cred_valid = cred_valid + self.got_creds = ycred.Show(self.cred_valid) + + def __setup_menus(self, actions=None): + 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'}] + if actions: + menus.extend(actions) + CreateMenu(menus) + + def __gpo_menus(self, parent=None): + menus = [{'title': 'Action', 'id': 'action', 'type': 'Menu'}, + {'title': 'Edit...', 'id': 'edit_gpo', 'type': 'MenuEntry', 'parent': 'action'}] + if parent: + delete_id = 'context_del_link' + else: + delete_id = 'context_del_gpo' + menus.append({'title': 'Delete', 'id': delete_id, 'type': 'MenuEntry', 'parent': 'action'}) + self.__setup_menus(actions=menus) - def __setup_menus(self): - UI.WizardCommand(Term('DeleteMenus')) - UI.WizardCommand(Term('AddMenu', '&File', 'file-menu')) - UI.WizardCommand(Term('AddMenuEntry', 'file-menu', 'Close', 'abort')) - - def __get_creds(self, creds): - if not creds.get_password(): - UI.SetApplicationTitle('Authenticate') - UI.OpenDialog(self.__password_prompt(creds.get_username())) - while True: - subret = UI.UserInput() - if str(subret) == 'creds_ok': - user = UI.QueryWidget('username_prompt', 'Value') - password = UI.QueryWidget('password_prompt', 'Value') - UI.CloseDialog() - if not password: - return False - creds.set_username(user) - creds.set_password(password) - return True - if str(subret) == 'creds_cancel': - UI.CloseDialog() - return False - return True - - def __password_prompt(self, user): - return MinWidth(30, HBox(HSpacing(1), VBox( - VSpacing(.5), - Left(Label('To continue, type an administrator password')), - Left(TextEntry(Id('username_prompt'), Opt('hstretch'), 'Username', user)), - Left(Password(Id('password_prompt'), Opt('hstretch'), 'Password')), - Right(HBox( - PushButton(Id('creds_ok'), 'OK'), - PushButton(Id('creds_cancel'), 'Cancel'), - )), - VSpacing(.5) - ), HSpacing(1))) + def __objs_menus(self, container=None): + menus = [{'title': 'Action', 'id': 'action', 'type': 'Menu'}] + if container: + menus.append({'title': 'Create a GPO in this domain, and Link it here...', 'id': 'context_add_gpo_and_link', 'type': 'MenuEntry', 'parent': 'action'}) + else: + menus.append({'title': 'New', 'id': 'context_add_gpo', 'type': 'MenuEntry', 'parent': 'action'}) + self.__setup_menus(actions=menus) def __find_gpo(self, gpo_guid): fgpo = None @@ -549,20 +567,10 @@ self.gpos = [] def __reset(self): - global have_advanced_gui - if not have_advanced_gui: - Wizard.RestoreBackButton() - Wizard.RestoreNextButton() - Wizard.RestoreAbortButton() UI.SetApplicationTitle('Group Policy Management Console') Wizard.SetContentsButtons('Group Policy Management Console', self.__gpmc_page(), self.__help(), 'Back', 'Edit GPO') - if have_advanced_gui: - Wizard.HideAbortButton() - Wizard.HideBackButton() - Wizard.HideNextButton() - else: - Wizard.DisableBackButton() - Wizard.DisableNextButton() + self.__setup_menus() + DeleteButtonBox() def Show(self): global selected_gpo @@ -599,16 +607,16 @@ UI.ReplaceWidget('rightPane', self.__container(gpo_guid)) current_page = 'Realm' elif ret == 'gpmc_tree' and event['EventReason'] == 'ContextMenuActivated': - parent = UI.QueryWidget('gpmc_tree', 'CurrentBranch')[-2] if gpo_guid == 'Group Policy Objects': UI.OpenContextMenu(self.__objs_context_menu()) elif gpo_guid != 'Domains' and self.__find_gpo(gpo_guid): + parent = UI.QueryWidget('gpmc_tree', 'CurrentBranch')[-2] if parent != 'Group Policy Objects' and parent != self.realm_dn: UI.OpenContextMenu(self.__gpo_context_menu(parent)) else: UI.OpenContextMenu(self.__gpo_context_menu()) elif gpo_guid != 'Domains': - UI.OpenContextMenu(self.__objs_context_menu(gpo_guid)) + UI.OpenContextMenu(self.__objs_context_menu(gpo_guid, realm=(gpo_guid == self.realm_dn))) elif ret == 'edit_gpo': selected_gpo = self.__find_gpo(gpo_guid) ret = 'next' @@ -636,6 +644,10 @@ self.__reset() UI.ReplaceWidget('rightPane', Empty()) current_page = None + elif ret == 'change_domain': + if switch_domains(self.lp, self.creds, self.cred_valid): + self.realm = self.lp.get('realm') + self.__reset() elif UI.HasSpecialWidget('DumbTab'): if gpo_guid == 'Domains': if current_page != None: @@ -653,15 +665,27 @@ UI.ReplaceWidget(Id('realm_tabContainer'), self.__realm_delegation()) elif ret == 'Group Policy Inheritance': UI.ReplaceWidget(Id('realm_tabContainer'), self.__realm_inheritance()) + if event['EventReason'] == 'SelectionChanged': + self.__objs_menus(gpo_guid) elif gpo_guid == 'Group Policy Objects': if current_page != 'Group Policy Objects': Wizard.DisableNextButton() UI.ReplaceWidget('rightPane', Empty()) current_page = 'Group Policy Objects' + if event['EventReason'] == 'SelectionChanged': + self.__objs_menus() elif gpo_guid.lower().startswith('ou='): UI.ReplaceWidget('rightPane', self.__container(gpo_guid)) current_page = None + if event['EventReason'] == 'SelectionChanged': + self.__objs_menus(gpo_guid) else: + parent = UI.QueryWidget('gpmc_tree', 'CurrentBranch')[-2] + if event['EventReason'] == 'SelectionChanged': + if parent != 'Group Policy Objects' and parent != self.realm_dn: + self.__gpo_menus(parent) + else: + self.__gpo_menus() if current_page != 'Dumbtab' or old_gpo_guid != gpo_guid: Wizard.EnableNextButton() selected_gpo = self.__find_gpo(gpo_guid) @@ -698,15 +722,15 @@ Item(Id(delete_id), 'Delete') ]) - def __objs_context_menu(self, container=None): + def __objs_context_menu(self, container=None, realm=False): + items = [] + if realm: + items.append(Item(Id('change_domain'), 'Change Domain...')) if container: - return Term('menu', [ - Item(Id('context_add_gpo_and_link'), 'Create a GPO in this domain, and Link it here...') - ]) + items.append(Item(Id('context_add_gpo_and_link'), 'Create a GPO in this domain, and Link it here...')) else: - return Term('menu', [ - Item(Id('context_add_gpo'), 'New') - ]) + items.append(Item(Id('context_add_gpo'), 'New')) + return Term('menu', items) def __name_gpo(self): return MinWidth(30, VBox( @@ -852,21 +876,12 @@ return contents def __container(self, dn): - global have_advanced_gui - if have_advanced_gui: - buttons = Empty() - else: - buttons = Right(HBox( - PushButton(Id('del_gpo'), 'Delete GPO'), - PushButton(Id('add_gpo'), 'Create a GPO') - )) return VBox( Frame(self.realm, DumbTab([ 'Linked Group Policy Objects', #'Group Policy Inheritance', #'Delegation' ], ReplacePoint(Id('realm_tabContainer'), self.__container_links(dn)))), - buttons, ) def __realm_delegation(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-gpmc-v1.4.1+git.11.e264ccc/src/gpmc.desktop.in new/yast2-gpmc-1.4.2/src/gpmc.desktop.in --- old/yast2-gpmc-v1.4.1+git.11.e264ccc/src/gpmc.desktop.in 2018-11-12 08:54:41.000000000 +0100 +++ new/yast2-gpmc-1.4.2/src/gpmc.desktop.in 2019-03-15 17:19:21.000000000 +0100 @@ -7,7 +7,7 @@ X-KDE-Library=yast2 X-SuSE-YaST-Call=gpmc -X-SuSE-YaST-Group=Misc +X-SuSE-YaST-Group=Net_advanced X-SuSE-YaST-Argument= X-SuSE-YaST-RootOnly=true X-SuSE-YaST-AutoInst=
