diff --git a/build.sh b/build.sh index ce9bc57df..1095d6b4c 100644 --- a/build.sh +++ b/build.sh @@ -28,7 +28,7 @@ echo # Add js libs. See: https://github.com/rockstor/rockstor-jslibs # Set jslibs_version of GitHub release: -jslibs_version=5.0.3 +jslibs_version=5.0.4 jslibs_url=https://github.com/rockstor/rockstor-jslibs/archive/refs/tags/"${jslibs_version}".tar.gz # Check for rpm embedded, or previously downloaded jslibs. diff --git a/pyproject.toml b/pyproject.toml index de0a1e786..0e882c646 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "rockstor" -version = "5.0.3" +version = "5.0.4" description = "Btrfs Network Attached Storage (NAS) Appliance." homepage = "https://rockstor.com/" repository = "https://github.com/rockstor/rockstor-core" diff --git a/src/rockstor/settings.py b/src/rockstor/settings.py index 6d24a5c83..5bb0b414c 100644 --- a/src/rockstor/settings.py +++ b/src/rockstor/settings.py @@ -1,5 +1,5 @@ """ -Copyright (c) 2012 RockStor, Inc. +Copyright (c) 2023 RockStor, Inc. This file is part of RockStor. RockStor is free software; you can redistribute it and/or modify @@ -145,7 +145,7 @@ }, ] -MIDDLEWARE_CLASSES = ( +MIDDLEWARE = ( # New in 1.8, 1.11 newly sets Content-Length header. # 'django.middleware.common.CommonMiddleware', "django.contrib.sessions.middleware.SessionMiddleware", diff --git a/src/rockstor/storageadmin/middleware.py b/src/rockstor/storageadmin/middleware.py index 96e92ffdf..2a397662e 100644 --- a/src/rockstor/storageadmin/middleware.py +++ b/src/rockstor/storageadmin/middleware.py @@ -1,5 +1,5 @@ """ -Copyright (c) 2012-2020 RockStor, Inc. +Copyright (c) 2012-2023 RockStor, Inc. This file is part of RockStor. RockStor is free software; you can redistribute it and/or modify @@ -13,18 +13,19 @@ General Public License for more details. You should have received a copy of the GNU General Public License -along with this program. If not, see . +along with this program. If not, see . """ from system.osi import run_command from django.conf import settings +from django.utils.deprecation import MiddlewareMixin import logging logger = logging.getLogger(__name__) -class ProdExceptionMiddleware(object): +class ProdExceptionMiddleware(MiddlewareMixin): def process_exception(self, request, exception): """just log the exception""" e_msg = ( diff --git a/src/rockstor/storageadmin/models/disk.py b/src/rockstor/storageadmin/models/disk.py index a699bc798..f6164b344 100644 --- a/src/rockstor/storageadmin/models/disk.py +++ b/src/rockstor/storageadmin/models/disk.py @@ -31,8 +31,6 @@ class AttachedManager(models.Manager): """Manager subclass to return only attached disks""" - use_for_related_fields = True - def attached(self): # Return default queryset after excluding name="detached-*" items. # Alternative lookup type __regex=r'^detached-' @@ -151,3 +149,4 @@ def target_name(self, *args, **kwargs): class Meta: app_label = "storageadmin" + base_manager_name = "attached" diff --git a/src/rockstor/storageadmin/static/storageadmin/js/router.js b/src/rockstor/storageadmin/static/storageadmin/js/router.js index 8486b9412..efd011a55 100644 --- a/src/rockstor/storageadmin/static/storageadmin/js/router.js +++ b/src/rockstor/storageadmin/static/storageadmin/js/router.js @@ -979,8 +979,7 @@ $(document).ready(function() { }; var distroInfo = function(data) { - $('#distro-info').text("Uses " + data.distro); - $('#distro-info').attr('title', data.version); + $('#distro-info').text("Uses " + data.distro + ": " + data.version); }; var displayLocaleTime = function(data) { diff --git a/src/rockstor/storageadmin/views/home.py b/src/rockstor/storageadmin/views/home.py index db932a516..3a9fe77ca 100644 --- a/src/rockstor/storageadmin/views/home.py +++ b/src/rockstor/storageadmin/views/home.py @@ -1,5 +1,5 @@ """ -Copyright (c) 2012-2020 RockStor, Inc. +Copyright (c) 2012-2023 RockStor, Inc. This file is part of RockStor. RockStor is free software; you can redistribute it and/or modify @@ -13,7 +13,7 @@ General Public License for more details. You should have received a copy of the GNU General Public License -along with this program. If not, see . +along with this program. If not, see . """ from django.shortcuts import render @@ -28,6 +28,7 @@ logger = logging.getLogger(__name__) + def login_page(request): return render(request, "login.html") @@ -65,7 +66,7 @@ def home(request): "update_channel": update_channel, } logger.debug("context={}".format(context)) - if request.user.is_authenticated(): + if request.user.is_authenticated: logger.debug("ABOUT TO RENDER INDEX") return render(request, "index.html", context) else: diff --git a/src/rockstor/system/directory_services.py b/src/rockstor/system/directory_services.py index 1bca3cfab..9f6d17911 100644 --- a/src/rockstor/system/directory_services.py +++ b/src/rockstor/system/directory_services.py @@ -1,5 +1,5 @@ """ -Copyright (c) 2012-2021 RockStor, Inc. +Copyright (c) 2012-2023 RockStor, Inc. This file is part of RockStor. RockStor is free software; you can redistribute it and/or modify @@ -13,7 +13,7 @@ General Public License for more details. You should have received a copy of the GNU General Public License -along with this program. If not, see . +along with this program. If not, see . """ import os @@ -295,7 +295,7 @@ def leave_domain(config, method="sssd"): run_command(cmd, log=True) -def domain_workgroup(domain=None, method="sssd"): +def domain_workgroup(domain: str, method: str = "sssd") -> str: """ Fetches the Workgroup value from an Active Directory domain to be fed to Samba configuration. @@ -303,20 +303,17 @@ def domain_workgroup(domain=None, method="sssd"): :param method: String - SSSD or Winbind (default is sssd) :return: """ - cmd = [NET, "ads", "workgroup", "-S", domain] - if method == "winbind": - cmd = [ADCLI, "info", domain] - o, e, rc = run_command(cmd) + cmd = [NET, "ads", "workgroup", f"--realm={domain.upper()}"] match_str = "Workgroup:" if method == "winbind": + cmd = [ADCLI, "info", domain] match_str = "domain-short = " - for l in o: - l = l.strip() - if re.match(match_str, l) is not None: - return l.split(match_str)[1].strip() - raise Exception( - "Failed to retrieve Workgroup. out: {} err: {} rc: {}".format(o, e, rc) - ) + o, e, rc = run_command(cmd, log=True) + for line in o: + line = line.strip() + if re.match(match_str, line) is not None: + return line.split(match_str)[1].strip() + raise Exception(f"Failed to retrieve Workgroup. out: {o} err: {e} rc: {rc}") def validate_idmap_range(config): diff --git a/src/rockstor/system/tests/test_directory_services.py b/src/rockstor/system/tests/test_directory_services.py index 2111975ba..a65c6463a 100644 --- a/src/rockstor/system/tests/test_directory_services.py +++ b/src/rockstor/system/tests/test_directory_services.py @@ -22,8 +22,9 @@ class SystemDirectoryServicesTests(unittest.TestCase): """ The tests in this suite can be run via the following command: - cd - ./bin/test --settings=test-settings -v 3 -p test_directory_services* + cd /opt/rockstor/src/rockstor + export DJANGO_SETTINGS_MODULE=settings + poetry run django-admin test -p test_directory_services.py -v 2 """ def setUp(self): @@ -50,8 +51,8 @@ def test_domain_workgroup(self): returned, expected, msg="Un-expected domain_workgroup() result:\n " - "returned = ({}).\n " - "expected = ({}).".format(returned, expected), + f"returned = {returned}.\n " + f"expected = {expected}.", ) def test_domain_workgroup_invalid(self): @@ -62,7 +63,7 @@ def test_domain_workgroup_invalid(self): domain = "bogusad.bogusdomain.com" self.mock_run_command.side_effect = CommandException( err=["Didn't find the cldap server!", ""], - cmd=["/usr/bin/net", "ads", "workgroup", "-S", domain], + cmd=["/usr/bin/net", "ads", "workgroup", f"--realm={domain.upper()}"], out=[""], rc=255, ) diff --git a/src/rockstor/system/users.py b/src/rockstor/system/users.py index 1f44b83d0..b5f81dc89 100644 --- a/src/rockstor/system/users.py +++ b/src/rockstor/system/users.py @@ -1,5 +1,5 @@ """ -Copyright (c) 2012-2023 RockStor, Inc. +Copyright (c) 2012-2023 RockStor, Inc. This file is part of RockStor. RockStor is free software; you can redistribute it and/or modify @@ -13,21 +13,21 @@ General Public License for more details. You should have received a copy of the GNU General Public License -along with this program. If not, see . +along with this program. If not, see . """ import crypt -import grp import logging import os import pwd import re import stat -from subprocess import run, Popen, PIPE from shutil import move +from subprocess import run, Popen, PIPE from tempfile import mkstemp +from typing import Union, Optional, Dict, Any import dbus -from dbus import DBusException +import grp from system.exceptions import CommandException from system.osi import run_command @@ -126,7 +126,8 @@ def get_groups(*gids): for ifp_gp, ifp_gid in ifp_groups.items(): if ifp_gp not in groups: groups[ifp_gp] = ifp_gid - except DBusException: + except dbus.DBusException as e: + logger.debug(f"Exception while getting groups from InfoPipe: {e}") pass return groups @@ -284,7 +285,9 @@ def add_ssh_key(username, key, old_key=None): run_command([CHOWN, "%s:%s" % (username, groupname), AUTH_KEYS]) -def ifp_get_properties_from_name_or_id(iface_type, target, *obj_properties): +def ifp_get_properties_from_name_or_id( + iface_type: str, target: Union[str, int], *obj_properties: str +) -> Optional[Dict[str, Any]]: """Get user of group properties from InfoPipe Uses InfoPipe (SSSD D-Bus responder) to get desired properties @@ -299,29 +302,34 @@ def ifp_get_properties_from_name_or_id(iface_type, target, *obj_properties): # InfoPipe depends on the sssd service running: if not is_systemd_service_active("sssd"): return None - bus = dbus.SystemBus() - ifp_bus_name = "org.freedesktop.sssd.infopipe" - - ifp_obj = bus.get_object(ifp_bus_name, IFP_CONSTANTS[iface_type]["obj_path"]) - ifp_iface = dbus.Interface(ifp_obj, IFP_CONSTANTS[iface_type]["main_iface"]) - - if isinstance(target, str): - my_obj = bus.get_object(ifp_bus_name, ifp_iface.FindByName(target)) - elif isinstance(target, int): - my_obj = bus.get_object(ifp_bus_name, ifp_iface.FindByID(target)) - else: - raise Exception( - "Incompatible type for target {}: {}.".format(target, type(target)) - ) + try: + bus = dbus.SystemBus() + ifp_bus_name = "org.freedesktop.sssd.infopipe" + ifp_obj = bus.get_object(ifp_bus_name, IFP_CONSTANTS[iface_type]["obj_path"]) + ifp_iface = dbus.Interface(ifp_obj, IFP_CONSTANTS[iface_type]["main_iface"]) + + if isinstance(target, str): + my_obj = bus.get_object(ifp_bus_name, ifp_iface.FindByName(target)) + elif isinstance(target, int): + my_obj = bus.get_object(ifp_bus_name, ifp_iface.FindByID(target)) + else: + raise Exception( + "Incompatible type for target {}: {}.".format(target, type(target)) + ) - my_iface_properties = dbus.Interface(my_obj, "org.freedesktop.DBus.Properties") + my_iface_properties = dbus.Interface(my_obj, "org.freedesktop.DBus.Properties") - ifp_res = {} - for obj_property in obj_properties: - ifp_res[obj_property] = my_iface_properties.Get( - IFP_CONSTANTS[iface_type]["sub_iface"], obj_property + ifp_res = {} + for obj_property in obj_properties: + ifp_res[obj_property] = my_iface_properties.Get( + IFP_CONSTANTS[iface_type]["sub_iface"], obj_property + ) + return ifp_res + except dbus.DBusException as e: + logger.debug( + f"Exception while getting {obj_properties} for {target} on {iface_type}: {e}" ) - return ifp_res + return None def ifp_get_groups():