diff --git a/server/src/uds/core/environment.py b/server/src/uds/core/environment.py index 41b7af456..21fd46ced 100644 --- a/server/src/uds/core/environment.py +++ b/server/src/uds/core/environment.py @@ -47,12 +47,17 @@ class Environment: not stored with main module data. The environment is composed of a "cache" and a "storage". First are volatile data, while second are persistent data. """ + _key: str _cache: Cache _storage: Storage _idGenerators: typing.Dict[str, UniqueIDGenerator] - def __init__(self, uniqueKey: str, idGenerators: typing.Optional[typing.Dict[str, UniqueIDGenerator]] = None): + def __init__( + self, + uniqueKey: str, + idGenerators: typing.Optional[typing.Dict[str, UniqueIDGenerator]] = None, + ): """ Initialized the Environment for the specified id @param uniqueKey: Key for this environment @@ -112,7 +117,11 @@ class Environment: v.release() @staticmethod - def getEnvForTableElement(tblName, id_, idGeneratorsTypes: typing.Optional[typing.Dict[str, typing.Any]] = None) -> 'Environment': + def getEnvForTableElement( + tblName, + id_, + idGeneratorsTypes: typing.Optional[typing.Dict[str, typing.Any]] = None, + ) -> 'Environment': """ From a table name, and a id, tries to load the associated environment or creates a new one if no environment exists at database. The table name and the id are used to obtain the key @@ -155,7 +164,9 @@ class Environment: """ Provides global environment """ - return Environment(GLOBAL_ENV) # This environment is a global environment for general utility. + return Environment( + GLOBAL_ENV + ) # This environment is a global environment for general utility. class Environmentable: diff --git a/server/src/uds/core/module.py b/server/src/uds/core/module.py index b093755a8..688ecbdb4 100644 --- a/server/src/uds/core/module.py +++ b/server/src/uds/core/module.py @@ -97,8 +97,11 @@ class Module(UserInterface, Environmentable, Serializable): Environmentable is a base class that provides utility method to access a separate Environment for every single module. """ + # Types - ValuesType = typing.Optional[typing.Dict[str, typing.Any]] # values type value will be str or list[str] int most cases + ValuesType = typing.Optional[ + typing.Dict[str, typing.Any] + ] # values type value will be str or list[str] int most cases # : Which coded to use to encode module by default. # : Basic name used to provide the administrator an "huma readable" form for the module @@ -108,7 +111,9 @@ class Module(UserInterface, Environmentable, Serializable): # : Description of this module, used at admin level typeDescription: typing.ClassVar[str] = 'Base Module' # : Icon file, relative to module folders - iconFile: typing.ClassVar[str] = 'base.png' # This is expected to be png, use this format always + iconFile: typing.ClassVar[ + str + ] = 'base.png' # This is expected to be png, use this format always # Not defined, but declared. If module is groupable, this value will contain to which group belongs group: typing.ClassVar[str] @@ -175,7 +180,10 @@ class Module(UserInterface, Environmentable, Serializable): Base 64 encoded or raw image, obtained from the specified file at 'iconFile' class attribute """ - file_ = open(os.path.dirname(sys.modules[cls.__module__].__file__) + '/' + cls.iconFile, 'rb') + file_ = open( + os.path.dirname(sys.modules[cls.__module__].__file__) + '/' + cls.iconFile, + 'rb', + ) data = file_.read() file_.close() @@ -206,7 +214,12 @@ class Module(UserInterface, Environmentable, Serializable): """ return [True, _("No connection checking method is implemented.")] - def __init__(self, environment: Environment, values: ValuesType = None, uuid: typing.Optional[str] = None): + def __init__( + self, + environment: Environment, + values: ValuesType = None, + uuid: typing.Optional[str] = None, + ): """ Do not forget to invoke this in your derived class using "super(self.__class__, self).__init__(environment, values)". @@ -273,7 +286,7 @@ class Module(UserInterface, Environmentable, Serializable): Returns: Internacionalized (using ugettext) string of result of the check. """ - return _("No check method provided.") + return _("No check method provided.") def getUuid(self) -> str: return self._uuid diff --git a/server/src/uds/core/serializable.py b/server/src/uds/core/serializable.py index 30c2ed11f..e1bdcfc7b 100644 --- a/server/src/uds/core/serializable.py +++ b/server/src/uds/core/serializable.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # -# Copyright (c) 2012-2019 Virtual Cable S.L. +# Copyright (c) 2012-2021 Virtual Cable S.L.U. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, @@ -12,7 +12,7 @@ # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. -# * Neither the name of Virtual Cable S.L. nor the names of its contributors +# * Neither the name of Virtual Cable S.L.U. nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # @@ -33,6 +33,7 @@ import base64 import typing + class Serializable: """ This class represents the interface that all serializable objects must provide. diff --git a/server/src/uds/core/util/storage.py b/server/src/uds/core/util/storage.py index 944406591..63b54f4e7 100644 --- a/server/src/uds/core/util/storage.py +++ b/server/src/uds/core/util/storage.py @@ -108,9 +108,9 @@ class StorageAsDict(MutableMapping): @property def _db(self) -> typing.Union[models.QuerySet, models.Manager]: if self._atomic: - return DBStorage.objects.select_for_update() + return DBStorage.objects.select_for_update() # type: ignore else: - return DBStorage.objects + return DBStorage.objects # type: ignore @property def _filtered(self) -> 'models.QuerySet[DBStorage]': diff --git a/server/src/uds/core/util/unique_id_generator.py b/server/src/uds/core/util/unique_id_generator.py index f4e0ee82a..d37cfeecc 100644 --- a/server/src/uds/core/util/unique_id_generator.py +++ b/server/src/uds/core/util/unique_id_generator.py @@ -36,11 +36,13 @@ import typing from django.db import transaction, OperationalError, connection from django.db.utils import IntegrityError -from django.db.models.query import QuerySet from uds.models.unique_id import UniqueId from uds.models.util import getSqlDatetimeAsUnix +if typing.TYPE_CHECKING: + from django.db import models + logger = logging.getLogger(__name__) MAX_SEQ = 1000000000000000 @@ -65,13 +67,13 @@ class UniqueIDGenerator: def __filter( self, rangeStart: int, rangeEnd: int = MAX_SEQ, forUpdate: bool = False - ) -> QuerySet: + ) -> 'models.QuerySet[UniqueId]': # Order is defined on UniqueId model, and is '-seq' by default (so this gets items in sequence order) # if not for update, do not use the clause :) obj = UniqueId.objects.select_for_update() if forUpdate else UniqueId.objects return obj.filter( basename=self._baseName, seq__gte=rangeStart, seq__lte=rangeEnd - ) # @UndefinedVariable + ) def get(self, rangeStart: int = 0, rangeEnd: int = MAX_SEQ) -> int: """ diff --git a/server/src/uds/core/workers/hanged_userservice_cleaner.py b/server/src/uds/core/workers/hanged_userservice_cleaner.py index 67822bf3d..f2c0b9895 100644 --- a/server/src/uds/core/workers/hanged_userservice_cleaner.py +++ b/server/src/uds/core/workers/hanged_userservice_cleaner.py @@ -41,6 +41,7 @@ from uds.core.util import log logger = logging.getLogger(__name__) + class HangedCleaner(Job): frecuency = 3601 frecuency_cfg = GlobalConfig.MAX_INITIALIZING_TIME @@ -51,9 +52,7 @@ class HangedCleaner(Job): since_state = now - timedelta( seconds=GlobalConfig.MAX_INITIALIZING_TIME.getInt() ) - since_removing = now -timedelta( - seconds=GlobalConfig.MAX_REMOVAL_TIME.getInt() - ) + since_removing = now - timedelta(seconds=GlobalConfig.MAX_REMOVAL_TIME.getInt()) # Filter for locating machine not ready flt = Q(state_date__lt=since_state, state=State.PREPARING) | Q( state_date__lt=since_state, state=State.USABLE, os_state=State.PREPARING @@ -72,7 +71,8 @@ class HangedCleaner(Job): userServices__state_date__lt=since_state, userServices__state=State.USABLE, userServices__os_state=State.PREPARING, - ) | Q( + ) + | Q( userServices__state_date__lt=since_removing, userServices__state=State.REMOVING, ), @@ -95,7 +95,9 @@ class HangedCleaner(Job): ): # It's waiting for removal, skip this very specific case continue logger.debug('Found hanged service %s', us) - if us.state == State.REMOVING: # Removing too long, remark it as removable + if ( + us.state == State.REMOVING + ): # Removing too long, remark it as removable log.doLog( us, log.ERROR, diff --git a/server/src/uds/development/middleware/__init__.py b/server/src/uds/development/middleware/__init__.py index 4791409dc..d0cee4dc7 100644 --- a/server/src/uds/development/middleware/__init__.py +++ b/server/src/uds/development/middleware/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (c) 2013-2019 Virtual Cable S.L. +# Copyright (c) 2013-2019 Virtual Cable S.L.U. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, @@ -11,7 +11,7 @@ # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. -# * Neither the name of Virtual Cable S.L. nor the names of its contributors +# * Neither the name of Virtual Cable S.L.U. nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # @@ -35,6 +35,7 @@ class RequestDebug: """ Used for logging some request data on develeopment """ + def __init__(self, get_response): self.get_response = get_response diff --git a/server/src/uds/dispatchers/guacamole/urls.py b/server/src/uds/dispatchers/guacamole/urls.py index e79bf22be..a8988eeb1 100644 --- a/server/src/uds/dispatchers/guacamole/urls.py +++ b/server/src/uds/dispatchers/guacamole/urls.py @@ -35,7 +35,11 @@ from .views import guacamole urlpatterns = [ # Authenticated path - url(r'^uds/guacamole/auth/(?P[^/]+)/(?P.+)$', guacamole, name='dispatcher.guacamole'), + url( + r'^uds/guacamole/auth/(?P[^/]+)/(?P.+)$', + guacamole, + name='dispatcher.guacamole', + ), # Non authenticated path. Disabled # url(r'^uds/guacamole/(?P.+)$', guacamole, name='dispatcher.guacamole.noauth'), ] diff --git a/server/src/uds/dispatchers/guacamole/views.py b/server/src/uds/dispatchers/guacamole/views.py index 8d91ca664..b61858c0f 100644 --- a/server/src/uds/dispatchers/guacamole/views.py +++ b/server/src/uds/dispatchers/guacamole/views.py @@ -54,7 +54,9 @@ def dict2resp(dct: typing.Mapping[typing.Any, typing.Any]) -> str: return '\r'.join((str(k) + '\t' + str(v) for k, v in dct.items())) -def guacamole(request: ExtendedHttpRequestWithUser, token: str, tunnelId: str) -> HttpResponse: +def guacamole( + request: ExtendedHttpRequestWithUser, token: str, tunnelId: str +) -> HttpResponse: if not TunnelToken.validateToken(token): logger.error('Invalid token %s from %s', token, request.ip) return HttpResponse(ERROR, content_type=CONTENT_TYPE) @@ -65,12 +67,14 @@ def guacamole(request: ExtendedHttpRequestWithUser, token: str, tunnelId: str) - tunnelId, scrambler = tunnelId.split('.') # All strings excetp "ticket-info", that is fixed if it exists later - val = typing.cast(typing.MutableMapping[str, str], TicketStore.get(tunnelId, invalidate=False)) + val = typing.cast( + typing.MutableMapping[str, str], TicketStore.get(tunnelId, invalidate=False) + ) # Extra check that the ticket data belongs to original requested user service/user if 'ticket-info' in val: ti = typing.cast(typing.Mapping[str, str], val['ticket-info']) - del val['ticket-info'] # Do not send this data to guacamole!! :) + del val['ticket-info'] # Do not send this data to guacamole!! :) try: userService = UserService.objects.get(uuid=ti['userService']) @@ -85,16 +89,21 @@ def guacamole(request: ExtendedHttpRequestWithUser, token: str, tunnelId: str) - userService.deployed_service, events.ET_TUNNEL_OPEN, username=userService.user.pretty_name, - source='HTML5-' + protocol, # On HTML5, currently src is not provided by Guacamole + source='HTML5-' + + protocol, # On HTML5, currently src is not provided by Guacamole dstip=host, uniqueid=userService.unique_id, ) except Exception: - logger.error('The requested guacamole userservice does not exists anymore') + logger.error( + 'The requested guacamole userservice does not exists anymore' + ) raise if userService.user.uuid != ti['user']: - logger.error('The requested userservice has changed owner and is not accesible') + logger.error( + 'The requested userservice has changed owner and is not accesible' + ) raise Exception() if 'password' in val: diff --git a/server/src/uds/dispatchers/opengnsys/urls.py b/server/src/uds/dispatchers/opengnsys/urls.py index dc140239d..5077bf0ee 100644 --- a/server/src/uds/dispatchers/opengnsys/urls.py +++ b/server/src/uds/dispatchers/opengnsys/urls.py @@ -34,5 +34,9 @@ from django.conf.urls import url from . import views urlpatterns = [ - url(r'^uds/ognotify/(?P[a-z]+)/(?P[a-zA-Z0-9-_]+)/(?P[a-zA-Z0-9-_]+)$', views.opengnsys, name='dispatcher.opengnsys'), + url( + r'^uds/ognotify/(?P[a-z]+)/(?P[a-zA-Z0-9-_]+)/(?P[a-zA-Z0-9-_]+)$', + views.opengnsys, + name='dispatcher.opengnsys', + ), ] diff --git a/server/src/uds/dispatchers/opengnsys/views.py b/server/src/uds/dispatchers/opengnsys/views.py index 7087d26fb..d1017b72a 100644 --- a/server/src/uds/dispatchers/opengnsys/views.py +++ b/server/src/uds/dispatchers/opengnsys/views.py @@ -52,7 +52,9 @@ def opengnsys(request: HttpRequest, msg: str, token: str, uuid: str) -> HttpResp def getUserService() -> typing.Optional[UserService]: try: - userService = UserService.objects.get(uuid=processUuid(uuid), state=states.userService.USABLE) + userService = UserService.objects.get( + uuid=processUuid(uuid), state=states.userService.USABLE + ) if userService.getProperty('token') == token: return userService logger.warning( @@ -63,7 +65,9 @@ def opengnsys(request: HttpRequest, msg: str, token: str, uuid: str) -> HttpResp # Sleep a while in case of error? except Exception as e: # Any exception will stop process - logger.warning('OpenGnsys: invalid userService %s:%s. (Ignored)', token, uuid) + logger.warning( + 'OpenGnsys: invalid userService %s:%s. (Ignored)', token, uuid + ) return None @@ -79,9 +83,14 @@ def opengnsys(request: HttpRequest, msg: str, token: str, uuid: str) -> HttpResp if userService: # Ignore login to cached machines... if userService.cache_level != 0: - logger.info('Ignored OpenGnsys login to %s to cached machine', userService.friendly_name) + logger.info( + 'Ignored OpenGnsys login to %s to cached machine', + userService.friendly_name, + ) return - logger.debug('Processing login from OpenGnsys %s', userService.friendly_name) + logger.debug( + 'Processing login from OpenGnsys %s', userService.friendly_name + ) actor_v3.Login.process_login(userService, 'OpenGnsys') def logout() -> None: @@ -89,9 +98,14 @@ def opengnsys(request: HttpRequest, msg: str, token: str, uuid: str) -> HttpResp if userService: # Ignore logout to cached machines... if userService.cache_level != 0: - logger.info('Ignored OpenGnsys logout to %s to cached machine', userService.friendly_name) + logger.info( + 'Ignored OpenGnsys logout to %s to cached machine', + userService.friendly_name, + ) return - logger.debug('Processing logout from OpenGnsys %s', userService.friendly_name) + logger.debug( + 'Processing logout from OpenGnsys %s', userService.friendly_name + ) actor_v3.Logout.process_logout(userService, 'OpenGnsys') fnc: typing.Optional[typing.Callable[[], None]] = { diff --git a/server/src/uds/dispatchers/pam/views.py b/server/src/uds/dispatchers/pam/views.py index 653ad6b16..34381040d 100644 --- a/server/src/uds/dispatchers/pam/views.py +++ b/server/src/uds/dispatchers/pam/views.py @@ -54,7 +54,11 @@ def pam(request: ExtendedHttpRequestWithUser) -> HttpResponse: # If request is not forged... if len(ids) == 1: userId = ids[0] - logger.debug("Auth request for user [%s] and pass [%s]", request.GET['id'], request.GET['pass']) + logger.debug( + "Auth request for user [%s] and pass [%s]", + request.GET['id'], + request.GET['pass'], + ) try: password = TicketStore.get(userId) if password == request.GET['pass']: @@ -63,7 +67,11 @@ def pam(request: ExtendedHttpRequestWithUser) -> HttpResponse: # Non existing ticket, log it and stop logger.info('Invalid access from %s using user %s', request.ip, userId) else: - logger.warning('Invalid request from %s: %s', request.ip, [v for v in request.GET.lists()]) + logger.warning( + 'Invalid request from %s: %s', + request.ip, + [v for v in request.GET.lists()], + ) elif 'uid' in request.GET: # This is an "get name for id" call logger.debug("NSS Request for id [%s]", request.GET['uid']) diff --git a/server/src/uds/management/commands/config.py b/server/src/uds/management/commands/config.py index 09df55f6c..8f0920778 100644 --- a/server/src/uds/management/commands/config.py +++ b/server/src/uds/management/commands/config.py @@ -57,7 +57,9 @@ class Command(BaseCommand): mod, name = first else: mod, name = GLOBAL_SECTION, first[0] - if Config.update(mod, name, value) is False: # If not exists, try to store value without any special parameters + if ( + Config.update(mod, name, value) is False + ): # If not exists, try to store value without any special parameters Config.section(mod).value(name, value).get() except Exception as e: print('The command could not be processed: {}'.format(e)) diff --git a/server/src/uds/management/commands/taskManager.py b/server/src/uds/management/commands/taskManager.py index 6ede3c037..316a85276 100644 --- a/server/src/uds/management/commands/taskManager.py +++ b/server/src/uds/management/commands/taskManager.py @@ -50,9 +50,15 @@ PID_FILE = 'taskmanager.pid' def getPidFile(): return settings.BASE_DIR + '/' + PID_FILE + # become_daemon seems te be removed on django 1.9 # This is a copy of posix version from django 1.8 -def become_daemon(our_home_dir: str = '.', out_log: str = '/dev/null', err_log: str = '/dev/null', umask: int = 0o022): +def become_daemon( + our_home_dir: str = '.', + out_log: str = '/dev/null', + err_log: str = '/dev/null', + umask: int = 0o022, +): """Robustly turn into a UNIX daemon, running in our_home_dir.""" # First fork try: @@ -93,21 +99,21 @@ class Command(BaseCommand): action='store_true', dest='start', default=False, - help='Starts a new daemon' + help='Starts a new daemon', ) parser.add_argument( '--stop', action='store_true', dest='stop', default=False, - help='Stop any running daemon' + help='Stop any running daemon', ) parser.add_argument( '--foreground', action='store_true', dest='foreground', default=False, - help='Stop any running daemon' + help='Stop any running daemon', ) def handle(self, *args, **options) -> None: @@ -141,7 +147,11 @@ class Command(BaseCommand): logger.info('Starting task manager.') if not foreground: - become_daemon(settings.BASE_DIR, settings.LOGDIR + '/taskManagerStdout.log', settings.LOGDIR + '/taskManagerStderr.log') + become_daemon( + settings.BASE_DIR, + settings.LOGDIR + '/taskManagerStdout.log', + settings.LOGDIR + '/taskManagerStderr.log', + ) pid = os.getpid() open(getPidFile(), 'w+').write('{}\n'.format(pid)) @@ -149,8 +159,10 @@ class Command(BaseCommand): manager = taskManager()() manager.run() - if not start and not stop: + if not start and not stop: if pid: - sys.stdout.write("Task manager found running (pid file exists: {0})\n".format(pid)) + sys.stdout.write( + "Task manager found running (pid file exists: {0})\n".format(pid) + ) else: sys.stdout.write("Task manager not foud (pid file do not exits)\n") diff --git a/server/src/uds/models/authenticator.py b/server/src/uds/models/authenticator.py index 0f1b4e8a3..e0e126fbc 100644 --- a/server/src/uds/models/authenticator.py +++ b/server/src/uds/models/authenticator.py @@ -105,7 +105,7 @@ class Authenticator(ManagedObjectModel, TaggingMixin): """ Get the type of the object this record represents. - The type is Python type, it obtains this type from ServiceProviderFactory and associated record field. + The type is Python type, it obtains this type from AuthsFactory and associated record field. Returns: The python type for this record object diff --git a/server/src/uds/models/config.py b/server/src/uds/models/config.py index 80310f7fb..404b2632f 100644 --- a/server/src/uds/models/config.py +++ b/server/src/uds/models/config.py @@ -64,7 +64,7 @@ class Config(models.Model): constraints = [ models.UniqueConstraint(fields=['section', 'key'], name='u_cfg_section_key') ] - + app_label = 'uds' def __str__(self) -> str: diff --git a/server/src/uds/models/delayed_task.py b/server/src/uds/models/delayed_task.py index aa6bf23c6..b3d452751 100644 --- a/server/src/uds/models/delayed_task.py +++ b/server/src/uds/models/delayed_task.py @@ -48,8 +48,11 @@ class DelayedTask(models.Model): This table contains uds.core.util.jobs.DelayedTask references """ + type = models.CharField(max_length=128) - tag = models.CharField(max_length=64, db_index=True) # A tag for letting us locate delayed publications... + tag = models.CharField( + max_length=64, db_index=True + ) # A tag for letting us locate delayed publications... instance = models.TextField() insert_date = models.DateTimeField() execution_delay = models.PositiveIntegerField() @@ -62,7 +65,10 @@ class DelayedTask(models.Model): """ Meta class to declare default order and unique multiple field index """ + app_label = 'uds' def __str__(self) -> str: - return "Run Queue task {0} owned by {3},inserted at {1} and with {2} seconds delay".format(self.type, self.insert_date, self.execution_delay, self.execution_time) + return "Run Queue task {0} owned by {3},inserted at {1} and with {2} seconds delay".format( + self.type, self.insert_date, self.execution_delay, self.execution_time + ) diff --git a/server/src/uds/models/group.py b/server/src/uds/models/group.py index 8c3305ebf..d540c4406 100644 --- a/server/src/uds/models/group.py +++ b/server/src/uds/models/group.py @@ -79,7 +79,9 @@ class Group(UUIDModel): app_label = 'uds' # unique_together = (("manager", "name"),) constraints = [ - models.UniqueConstraint(fields=['manager', 'name'], name='u_grp_manager_name') + models.UniqueConstraint( + fields=['manager', 'name'], name='u_grp_manager_name' + ) ] @property diff --git a/server/src/uds/models/meta_pool.py b/server/src/uds/models/meta_pool.py index 719f55a3d..607e396c3 100644 --- a/server/src/uds/models/meta_pool.py +++ b/server/src/uds/models/meta_pool.py @@ -81,7 +81,7 @@ class MetaPool(UUIDModel, TaggingMixin): # type: ignore TRANSPORT_SELECT: typing.Mapping[int, str] = { AUTO_TRANSPORT_SELECT: _('Automatic selection'), COMMON_TRANSPORT_SELECT: _('Use only common transports'), - LABEL_TRANSPORT_SELECT: _('Group Transports by label') + LABEL_TRANSPORT_SELECT: _('Group Transports by label'), } name = models.CharField(max_length=128, default='') diff --git a/server/src/uds/models/os_manager.py b/server/src/uds/models/os_manager.py index 43f615eb5..c5077753c 100644 --- a/server/src/uds/models/os_manager.py +++ b/server/src/uds/models/os_manager.py @@ -72,7 +72,7 @@ class OSManager(ManagedObjectModel, TaggingMixin): # type: ignore """ Get the type of the object this record represents. - The type is Python type, it obtains this type from ServiceProviderFactory and associated record field. + The type is Python type, it obtains this OsManagersFactory and associated record field. Returns: The python type for this record object diff --git a/server/src/uds/models/service.py b/server/src/uds/models/service.py index 768caf5b9..9fa16905e 100644 --- a/server/src/uds/models/service.py +++ b/server/src/uds/models/service.py @@ -88,7 +88,9 @@ class Service(ManagedObjectModel, TaggingMixin): # type: ignore ordering = ('name',) app_label = 'uds' constraints = [ - models.UniqueConstraint(fields=['provider', 'name'], name='u_srv_provider_name') + models.UniqueConstraint( + fields=['provider', 'name'], name='u_srv_provider_name' + ) ] def getEnvironment(self) -> Environment: @@ -105,7 +107,9 @@ class Service(ManagedObjectModel, TaggingMixin): # type: ignore }, ) - def getInstance(self, values: typing.Optional[typing.Dict[str, str]] = None) -> 'services.Service': + def getInstance( + self, values: typing.Optional[typing.Dict[str, str]] = None + ) -> 'services.Service': """ Instantiates the object this record contains. diff --git a/server/src/uds/models/service_pool.py b/server/src/uds/models/service_pool.py index 219c6dc0e..cea70e24a 100644 --- a/server/src/uds/models/service_pool.py +++ b/server/src/uds/models/service_pool.py @@ -159,7 +159,7 @@ class ServicePool(UUIDModel, TaggingMixin): # type: ignore userServices: 'models.QuerySet[UserService]' calendarAccess: 'models.QuerySet[CalendarAccess]' changelog: 'models.QuerySet[ServicePoolPublicationChangelog]' - + calendaraction_set: typing.Any class Meta(UUIDModel.Meta): diff --git a/server/src/uds/models/service_pool_group.py b/server/src/uds/models/service_pool_group.py index 86276e47e..b3aae2be2 100644 --- a/server/src/uds/models/service_pool_group.py +++ b/server/src/uds/models/service_pool_group.py @@ -49,11 +49,18 @@ class ServicePoolGroup(UUIDModel): """ A deployed service is the Service produced element that is assigned finally to an user (i.e. a Virtual Machine, etc..) """ + # pylint: disable=model-missing-unicode name = models.CharField(max_length=128, default='', db_index=True, unique=True) comments = models.CharField(max_length=256, default='') priority = models.IntegerField(default=0, db_index=True) - image: 'models.ForeignKey[ServicePoolGroup, Image]' = models.ForeignKey(Image, null=True, blank=True, related_name='servicesPoolsGroup', on_delete=models.SET_NULL) + image: 'models.ForeignKey[ServicePoolGroup, Image]' = models.ForeignKey( + Image, + null=True, + blank=True, + related_name='servicesPoolsGroup', + on_delete=models.SET_NULL, + ) # "fake" declarations for type checking objects: 'models.BaseManager[ServicePoolGroup]' @@ -62,11 +69,14 @@ class ServicePoolGroup(UUIDModel): """ Meta class to declare the name of the table at database """ + db_table = 'uds__pools_groups' app_label = 'uds' def __str__(self) -> str: - return 'Service Pool group {}({}): {}'.format(self.name, self.comments, self.image.name) + return 'Service Pool group {}({}): {}'.format( + self.name, self.comments, self.image.name + ) @property def as_dict(self) -> typing.MutableMapping[str, typing.Any]: @@ -75,12 +85,12 @@ class ServicePoolGroup(UUIDModel): 'name': self.name, 'comments': self.comments, 'priority': self.priority, - 'imageUuid': self.image.uuid if self.image is not None else 'x' + 'imageUuid': self.image.uuid if self.image is not None else 'x', } @property def thumb64(self) -> str: - return self.image.thumb64 if self.image else DEFAULT_THUMB_BASE64 + return self.image.thumb64 if self.image else DEFAULT_THUMB_BASE64 @staticmethod def default() -> 'ServicePoolGroup': diff --git a/server/src/uds/models/service_pool_publication.py b/server/src/uds/models/service_pool_publication.py index a4a5ac3c3..af749386e 100644 --- a/server/src/uds/models/service_pool_publication.py +++ b/server/src/uds/models/service_pool_publication.py @@ -109,7 +109,6 @@ class ServicePoolPublication(UUIDModel): objects: 'models.BaseManager[ServicePoolPublication]' userServices: 'models.QuerySet[UserService]' - class Meta(UUIDModel.Meta): """ Meta class to declare default order and unique multiple field index diff --git a/server/src/uds/models/stats_counters.py b/server/src/uds/models/stats_counters.py index f55c8dfc6..30c05e824 100644 --- a/server/src/uds/models/stats_counters.py +++ b/server/src/uds/models/stats_counters.py @@ -73,7 +73,7 @@ class StatsCounters(models.Model): @staticmethod def get_grouped( owner_type: typing.Union[int, typing.Iterable[int]], counter_type: int, **kwargs - ) -> 'models.QuerySet[StatsCounters]': # pylint: disable=too-many-locals + ) -> 'models.QuerySet[StatsCounters]': """ Returns the average stats grouped by interval for owner_type and owner_id (optional) diff --git a/server/src/uds/models/storage.py b/server/src/uds/models/storage.py index fb56ae3c9..9e6c47e3a 100644 --- a/server/src/uds/models/storage.py +++ b/server/src/uds/models/storage.py @@ -42,10 +42,13 @@ class Storage(models.Model): General storage model. Used to store specific instances (transport, service, servicemanager, ...) persistent information not intended to be serialized/deserialized everytime one object instance is loaded/saved. """ + owner = models.CharField(max_length=128, db_index=True) key = models.CharField(max_length=64, primary_key=True) data = models.TextField(default='') - attr1 = models.CharField(max_length=64, db_index=True, null=True, blank=True, default=None) + attr1 = models.CharField( + max_length=64, db_index=True, null=True, blank=True, default=None + ) # "fake" declarations for type checking objects: 'models.BaseManager[Storage]' @@ -54,7 +57,10 @@ class Storage(models.Model): """ Meta class to declare the name of the table at database """ + app_label = 'uds' def __str__(self) -> str: - return '{} {} > str= {}, {}'.format(self.owner, self.key, self.data, '/'.join([self.attr1])) + return '{} {} > str= {}, {}'.format( + self.owner, self.key, self.data, '/'.join([self.attr1]) + ) diff --git a/server/src/uds/models/ticket_store.py b/server/src/uds/models/ticket_store.py index 2f49adbfc..76d06224b 100644 --- a/server/src/uds/models/ticket_store.py +++ b/server/src/uds/models/ticket_store.py @@ -89,7 +89,9 @@ class TicketStore(UUIDModel): @staticmethod def generateUuid() -> str: - return cryptoManager().randomString(40).lower() # Temporary fix lower() for compat with 3.0 + return ( + cryptoManager().randomString(40).lower() + ) # Temporary fix lower() for compat with 3.0 @staticmethod def create( diff --git a/server/src/uds/models/transport.py b/server/src/uds/models/transport.py index f21053538..db5048997 100644 --- a/server/src/uds/models/transport.py +++ b/server/src/uds/models/transport.py @@ -88,7 +88,7 @@ class Transport(ManagedObjectModel, TaggingMixin): """ Get the type of the object this record represents. - The type is Python type, it obtains this type from ServiceProviderFactory and associated record field. + The type is Python type, it obtains this type from TransportsFactory and associated record field. Returns: The python type for this record object diff --git a/server/src/uds/models/tunnel_token.py b/server/src/uds/models/tunnel_token.py index 5cb53be51..429619d70 100644 --- a/server/src/uds/models/tunnel_token.py +++ b/server/src/uds/models/tunnel_token.py @@ -33,6 +33,7 @@ import typing from django.db import models from uds.core.util.request import ExtendedHttpRequest + class TunnelToken(models.Model): """ UDS Tunnel tokens on DB @@ -56,7 +57,9 @@ class TunnelToken(models.Model): ] @staticmethod - def validateToken(token: str, request: typing.Optional[ExtendedHttpRequest] = None) -> bool: + def validateToken( + token: str, request: typing.Optional[ExtendedHttpRequest] = None + ) -> bool: try: tt = TunnelToken.objects.get(token=token) # We could check the request ip here diff --git a/server/src/uds/models/user.py b/server/src/uds/models/user.py index 76fafcb14..e8f3de5b8 100644 --- a/server/src/uds/models/user.py +++ b/server/src/uds/models/user.py @@ -187,18 +187,18 @@ class User(UUIDModel): number_belongs_meta=Count('groups', filter=Q(groups__id__in=grps)) ) # g.groups.filter(id__in=grps).count() ): - numberGroupsBelongingInMeta: int = g.number_belongs_meta + numberGroupsBelongingInMeta: int = g.number_belongs_meta # type: ignore # anottation logger.debug('gn = %s', numberGroupsBelongingInMeta) - logger.debug('groups count: %s', g.number_groups) + logger.debug('groups count: %s', g.number_groups) # type: ignore # anottation if g.meta_if_any is True and numberGroupsBelongingInMeta > 0: - numberGroupsBelongingInMeta = g.number_groups + numberGroupsBelongingInMeta = g.number_groups # type: ignore # anottation logger.debug('gn after = %s', numberGroupsBelongingInMeta) # If a meta group is empty, all users belongs to it. we can use gn != 0 to check that if it is empty, is not valid - if numberGroupsBelongingInMeta == g.number_groups: + if numberGroupsBelongingInMeta == g.number_groups: # type: ignore # anottation # This group matches yield g diff --git a/server/src/uds/models/user_service_property.py b/server/src/uds/models/user_service_property.py index 7f5d72f78..88b5388ea 100644 --- a/server/src/uds/models/user_service_property.py +++ b/server/src/uds/models/user_service_property.py @@ -63,7 +63,9 @@ class UserServiceProperty(models.Model): # pylint: disable=too-many-public-meth db_table = 'uds__user_service_property' app_label = 'uds' constraints = [ - models.UniqueConstraint(fields=['name', 'user_service'], name='u_uprop_name_userservice') + models.UniqueConstraint( + fields=['name', 'user_service'], name='u_uprop_name_userservice' + ) ] def __str__(self) -> str: diff --git a/server/src/uds/models/util.py b/server/src/uds/models/util.py index 62fa5cf5a..1f760348d 100644 --- a/server/src/uds/models/util.py +++ b/server/src/uds/models/util.py @@ -42,6 +42,7 @@ logger = logging.getLogger(__name__) NEVER = datetime(1972, 7, 1) NEVER_UNIX = int(mktime(NEVER.timetuple())) + class UnsavedForeignKey(models.ForeignKey): """ From 1.8 of django, we need to point to "saved" objects. @@ -49,9 +50,11 @@ class UnsavedForeignKey(models.ForeignKey): We need to trick in some cases, because for example, root user is not in DB """ + # Allows pointing to an unsaved object allow_unsaved_instance_assignment = True + def getSqlDatetime() -> datetime: """ Returns the current date/time of the database server. @@ -64,17 +67,25 @@ def getSqlDatetime() -> datetime: """ if connection.vendor in ('mysql', 'microsoft'): cursor = connection.cursor() - sentence = 'SELECT NOW()' if connection.vendor == 'mysql' else 'SELECT CURRENT_TIMESTAMP' + sentence = ( + 'SELECT NOW()' + if connection.vendor == 'mysql' + else 'SELECT CURRENT_TIMESTAMP' + ) cursor.execute(sentence) date = cursor.fetchone()[0] else: - date = datetime.now() # If not know how to get database datetime, returns local datetime (this is fine for sqlite, which is local) + date = ( + datetime.now() + ) # If not know how to get database datetime, returns local datetime (this is fine for sqlite, which is local) return date + def getSqlDatetimeAsUnix() -> int: return int(mktime(getSqlDatetime().timetuple())) + def getSqlFnc(fncName: str) -> str: """ Convert different sql functions for different platforms diff --git a/server/src/uds/osmanagers/LinuxOsManager/__init__.py b/server/src/uds/osmanagers/LinuxOsManager/__init__.py index 1c8fdaf4e..1390d9be7 100644 --- a/server/src/uds/osmanagers/LinuxOsManager/__init__.py +++ b/server/src/uds/osmanagers/LinuxOsManager/__init__.py @@ -46,42 +46,60 @@ OSManagersFactory.factory().insert(LinuxRandomPassManager) downloadsManager().registerDownloadable( 'udsactor_{version}_all.deb'.format(version=VERSION), - _('UDS Actor for Debian, Ubuntu, ... Linux machines (Requires python >= 3.6)'), - os.path.dirname(sys.modules[__package__].__file__) + '/files/udsactor_{version}_all.deb'.format(version=VERSION), - 'application/x-debian-package' + _( + 'UDS Actor for Debian, Ubuntu, ... Linux machines (Requires python >= 3.6)' + ), + os.path.dirname(sys.modules[__package__].__file__) + + '/files/udsactor_{version}_all.deb'.format(version=VERSION), + 'application/x-debian-package', ) downloadsManager().registerDownloadable( 'udsactor-{version}-1.noarch.rpm'.format(version=VERSION), - _('UDS Actor for Centos, Fedora, RH, Suse, ... Linux machines (Requires python >= 3.6)'), - os.path.dirname(sys.modules[__package__].__file__) + '/files/udsactor-{version}-1.noarch.rpm'.format(version=VERSION), - 'application/x-redhat-package-manager' + _( + 'UDS Actor for Centos, Fedora, RH, Suse, ... Linux machines (Requires python >= 3.6)' + ), + os.path.dirname(sys.modules[__package__].__file__) + + '/files/udsactor-{version}-1.noarch.rpm'.format(version=VERSION), + 'application/x-redhat-package-manager', ) downloadsManager().registerDownloadable( 'udsactor-unmanaged_{version}_all.deb'.format(version=VERSION), - _('UDS Actor for Debian based Linux machines. Used ONLY for static machines. (Requires python >= 3.6)'), - os.path.dirname(sys.modules[__package__].__file__) + '/files/udsactor-unmanaged_{version}_all.deb'.format(version=VERSION), - 'application/x-debian-package' + _( + 'UDS Actor for Debian based Linux machines. Used ONLY for static machines. (Requires python >= 3.6)' + ), + os.path.dirname(sys.modules[__package__].__file__) + + '/files/udsactor-unmanaged_{version}_all.deb'.format(version=VERSION), + 'application/x-debian-package', ) downloadsManager().registerDownloadable( 'udsactor_2.2.0_legacy.deb', - _('Legacy UDS Actor for Debian, Ubuntu, ... Linux machines (Requires python 2.7)'), - os.path.dirname(sys.modules[__package__].__file__) + '/files/udsactor_2.2.0_legacy.deb', - 'application/x-debian-package' + _( + 'Legacy UDS Actor for Debian, Ubuntu, ... Linux machines (Requires python 2.7)' + ), + os.path.dirname(sys.modules[__package__].__file__) + + '/files/udsactor_2.2.0_legacy.deb', + 'application/x-debian-package', ) downloadsManager().registerDownloadable( 'udsactor-legacy-2.2.1-1.noarch.rpm', - _('Legacy UDS Actor for Centos, Fedora, RH, ... Linux machines (Requires python 2.7)'), - os.path.dirname(sys.modules[__package__].__file__) + '/files/udsactor-legacy-2.2.1-1.noarch.rpm', - 'application/x-redhat-package-manager' + _( + 'Legacy UDS Actor for Centos, Fedora, RH, ... Linux machines (Requires python 2.7)' + ), + os.path.dirname(sys.modules[__package__].__file__) + + '/files/udsactor-legacy-2.2.1-1.noarch.rpm', + 'application/x-redhat-package-manager', ) downloadsManager().registerDownloadable( 'udsactor-opensuse-legacy-2.2.1-1.noarch.rpm', - _('Legacy UDS Actor for OpenSUSE, ... Linux machines (Requires python 2.7)'), - os.path.dirname(sys.modules[__package__].__file__) + '/files/udsactor-opensuse-legacy-2.2.1-1.noarch.rpm', - 'application/x-redhat-package-manager' + _( + 'Legacy UDS Actor for OpenSUSE, ... Linux machines (Requires python 2.7)' + ), + os.path.dirname(sys.modules[__package__].__file__) + + '/files/udsactor-opensuse-legacy-2.2.1-1.noarch.rpm', + 'application/x-redhat-package-manager', ) diff --git a/server/src/uds/osmanagers/LinuxOsManager/linux_osmanager.py b/server/src/uds/osmanagers/LinuxOsManager/linux_osmanager.py index c93d3de27..9c0fbe556 100644 --- a/server/src/uds/osmanagers/LinuxOsManager/linux_osmanager.py +++ b/server/src/uds/osmanagers/LinuxOsManager/linux_osmanager.py @@ -65,17 +65,25 @@ class LinuxOsManager(osmanagers.OSManager): values=[ {'id': 'keep', 'text': ugettext_lazy('Keep service assigned')}, {'id': 'remove', 'text': ugettext_lazy('Remove service')}, - {'id': 'keep-always', 'text': ugettext_lazy('Keep service assigned even on new publication')}, + { + 'id': 'keep-always', + 'text': ugettext_lazy('Keep service assigned even on new publication'), + }, ], - defvalue='keep') + defvalue='keep', + ) idle = gui.NumericField( label=_("Max.Idle time"), length=4, defvalue=-1, - rdonly=False, order=11, - tooltip=_('Maximum idle time (in seconds) before session is automatically closed to the user (<= 0 means no max idle time).'), - required=True) + rdonly=False, + order=11, + tooltip=_( + 'Maximum idle time (in seconds) before session is automatically closed to the user (<= 0 means no max idle time).' + ), + required=True, + ) deadLine = gui.CheckBoxField( label=_('Calendar logout'), @@ -114,7 +122,9 @@ class LinuxOsManager(osmanagers.OSManager): Says if a machine is removable on logout ''' if not userService.in_use: - if (self._onLogout == 'remove') or (not userService.isValidPublication() and self._onLogout == 'keep'): + if (self._onLogout == 'remove') or ( + not userService.isValidPublication() and self._onLogout == 'keep' + ): return True return False @@ -174,13 +184,18 @@ class LinuxOsManager(osmanagers.OSManager): def readyNotified(self, userService): return - def actorData(self, userService: 'UserService') -> typing.MutableMapping[str, typing.Any]: - return { - 'action': 'rename', - 'name': userService.getName() - } + def actorData( + self, userService: 'UserService' + ) -> typing.MutableMapping[str, typing.Any]: + return {'action': 'rename', 'name': userService.getName()} - def process(self, userService: 'UserService', message: str, data: typing.Any, options: typing.Optional[typing.Dict[str, typing.Any]] = None) -> str: + def process( + self, + userService: 'UserService', + message: str, + data: typing.Any, + options: typing.Optional[typing.Dict[str, typing.Any]] = None, + ) -> str: """ We understand this messages: * msg = info, data = None. Get information about name of machine (or domain, in derived WinDomainOsManager class), old method @@ -189,17 +204,24 @@ class LinuxOsManager(osmanagers.OSManager): * msg = logoff, data = Username, Informs that the username has logged out of the machine * msg = ready, data = None, Informs machine ready to be used """ - logger.info("Invoked LinuxOsManager for %s with params: %s, %s", userService, message, data) + logger.info( + "Invoked LinuxOsManager for %s with params: %s, %s", + userService, + message, + data, + ) # We get from storage the name for this userService. If no name, we try to assign a new one ret = "ok" notifyReady = False doRemove = False state = userService.os_state if message in ('ready', 'ip'): - if not isinstance(data, dict): # Older actors?, previous to 2.5, convert it information.. + if not isinstance( + data, dict + ): # Older actors?, previous to 2.5, convert it information.. data = { 'ips': [v.split('=') for v in typing.cast(str, data).split(',')], - 'hostname': userService.friendly_name + 'hostname': userService.friendly_name, } # Old "info" state, will be removed in a near future @@ -246,7 +268,12 @@ class LinuxOsManager(osmanagers.OSManager): This function can update userService values. Normal operation will be remove machines if this state is not valid """ if self.isRemovableOnLogout(userService): - log.doLog(userService, log.INFO, 'Unused user service for too long. Removing due to OS Manager parameters.', log.OSMANAGER) + log.doLog( + userService, + log.INFO, + 'Unused user service for too long. Removing due to OS Manager parameters.', + log.OSMANAGER, + ) userService.remove() def isPersistent(self): @@ -260,7 +287,9 @@ class LinuxOsManager(osmanagers.OSManager): """ On production environments, will return no idle for non removable machines """ - if self._idle <= 0: # or (settings.DEBUG is False and self._onLogout != 'remove'): + if ( + self._idle <= 0 + ): # or (settings.DEBUG is False and self._onLogout != 'remove'): return None return self._idle @@ -269,7 +298,9 @@ class LinuxOsManager(osmanagers.OSManager): """ Serializes the os manager data so we can store it in database """ - return '\t'.join(['v3', self._onLogout, str(self._idle), gui.boolToStr(self._deadLine)]).encode('utf8') + return '\t'.join( + ['v3', self._onLogout, str(self._idle), gui.boolToStr(self._deadLine)] + ).encode('utf8') def unmarshal(self, data: bytes): values = data.decode('utf8').split('\t') @@ -280,9 +311,17 @@ class LinuxOsManager(osmanagers.OSManager): elif values[0] == 'v2': self._onLogout, self._idle = values[1], int(values[2]) elif values[0] == 'v3': - self._onLogout, self._idle, self._deadLine = values[1], int(values[2]), gui.strToBool(values[3]) + self._onLogout, self._idle, self._deadLine = ( + values[1], + int(values[2]), + gui.strToBool(values[3]), + ) self.__setProcessUnusedMachines() def valuesDict(self) -> gui.ValuesDictType: - return {'onLogout': self._onLogout, 'idle': str(self._idle), 'deadLine': gui.boolToStr(self._deadLine) } + return { + 'onLogout': self._onLogout, + 'idle': str(self._idle), + 'deadLine': gui.boolToStr(self._deadLine), + } diff --git a/server/src/uds/osmanagers/LinuxOsManager/linux_randompass_osmanager.py b/server/src/uds/osmanagers/LinuxOsManager/linux_randompass_osmanager.py index 95c83b54f..55de0f52d 100644 --- a/server/src/uds/osmanagers/LinuxOsManager/linux_randompass_osmanager.py +++ b/server/src/uds/osmanagers/LinuxOsManager/linux_randompass_osmanager.py @@ -48,14 +48,23 @@ logger = logging.getLogger(__name__) if typing.TYPE_CHECKING: from uds.models.user_service import UserService + class LinuxRandomPassManager(LinuxOsManager): typeName = _('Linux Random Password OS Manager') typeType = 'LinRandomPasswordManager' - typeDescription = _('Os Manager to control linux machines, with user password set randomly.') + typeDescription = _( + 'Os Manager to control linux machines, with user password set randomly.' + ) iconFile = 'losmanager.png' # Apart form data from linux os manager, we need also domain and credentials - userAccount = gui.TextField(length=64, label=_('Account'), order=2, tooltip=_('User account to change password'), required=True) + userAccount = gui.TextField( + length=64, + label=_('Account'), + order=2, + tooltip=_('User account to change password'), + required=True, + ) # Inherits base "onLogout" onLogout = LinuxOsManager.onLogout @@ -68,12 +77,16 @@ class LinuxRandomPassManager(LinuxOsManager): super(LinuxRandomPassManager, self).__init__(environment, values) if values is not None: if values['userAccount'] == '': - raise osmanagers.OSManager.ValidationException(_('Must provide an user account!!!')) + raise osmanagers.OSManager.ValidationException( + _('Must provide an user account!!!') + ) self._userAccount = values['userAccount'] else: self._userAccount = '' - def processUserPassword(self, userService: 'UserService', username: str, password: str) -> typing.Tuple[str, str]: + def processUserPassword( + self, userService: 'UserService', username: str, password: str + ) -> typing.Tuple[str, str]: if username == self._userAccount: return (username, userService.recoverValue('linOsRandomPass')) return username, password @@ -81,25 +94,39 @@ class LinuxRandomPassManager(LinuxOsManager): def genPassword(self, service): randomPass = service.recoverValue('linOsRandomPass') if randomPass is None: - randomPass = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(16)) + randomPass = ''.join( + random.SystemRandom().choice(string.ascii_letters + string.digits) + for _ in range(16) + ) service.storeValue('linOsRandomPass', randomPass) - log.doLog(service, log.INFO, "Password set to \"{}\"".format(randomPass), log.OSMANAGER) + log.doLog( + service, + log.INFO, + "Password set to \"{}\"".format(randomPass), + log.OSMANAGER, + ) return randomPass def infoVal(self, service): - return 'rename:{0}\t{1}\t\t{2}'.format(self.getName(service), self._userAccount, self.genPassword(service)) + return 'rename:{0}\t{1}\t\t{2}'.format( + self.getName(service), self._userAccount, self.genPassword(service) + ) def infoValue(self, service): - return 'rename\r{0}\t{1}\t\t{2}'.format(self.getName(service), self._userAccount, self.genPassword(service)) + return 'rename\r{0}\t{1}\t\t{2}'.format( + self.getName(service), self._userAccount, self.genPassword(service) + ) - def actorData(self, userService: 'UserService') -> typing.MutableMapping[str, typing.Any]: + def actorData( + self, userService: 'UserService' + ) -> typing.MutableMapping[str, typing.Any]: return { 'action': 'rename', 'name': userService.getName(), 'username': self._userAccount, 'password': '', # On linux, user password is not needed so we provide an empty one - 'new_password': self.genPassword(userService) + 'new_password': self.genPassword(userService), } def marshal(self) -> bytes: @@ -107,7 +134,9 @@ class LinuxRandomPassManager(LinuxOsManager): Serializes the os manager data so we can store it in database """ base = LinuxOsManager.marshal(self) - return '\t'.join(['v1', self._userAccount, codecs.encode(base, 'hex').decode()]).encode('utf8') + return '\t'.join( + ['v1', self._userAccount, codecs.encode(base, 'hex').decode()] + ).encode('utf8') def unmarshal(self, data: bytes) -> None: values = data.split(b'\t') diff --git a/server/src/uds/osmanagers/WindowsOsManager/__init__.py b/server/src/uds/osmanagers/WindowsOsManager/__init__.py index a5715abfb..efc7e8a08 100644 --- a/server/src/uds/osmanagers/WindowsOsManager/__init__.py +++ b/server/src/uds/osmanagers/WindowsOsManager/__init__.py @@ -50,11 +50,15 @@ osmanagers.factory().insert(WinRandomPassManager) managers.downloadsManager().registerDownloadable( 'UDSActorSetup-{version}.exe'.format(version=VERSION), _('UDS Actor for windows machines'), - os.path.dirname(sys.modules[__package__].__file__) + '/files/UDSActorSetup-{version}.exe'.format(version=VERSION), - 'application/x-msdos-program') + os.path.dirname(sys.modules[__package__].__file__) + + '/files/UDSActorSetup-{version}.exe'.format(version=VERSION), + 'application/x-msdos-program', +) managers.downloadsManager().registerDownloadable( 'UDSActorUnmanagedSetup-{version}.exe'.format(version=VERSION), _('UDS Actor for Unmanaged windows machines. Used ONLY for static machines.'), - os.path.dirname(sys.modules[__package__].__file__) + '/files/UDSActorUnmanagedSetup-{version}.exe'.format(version=VERSION), - 'application/x-msdos-program') + os.path.dirname(sys.modules[__package__].__file__) + + '/files/UDSActorUnmanagedSetup-{version}.exe'.format(version=VERSION), + 'application/x-msdos-program', +) diff --git a/server/src/uds/osmanagers/WindowsOsManager/windows.py b/server/src/uds/osmanagers/WindowsOsManager/windows.py index 4917e7b9e..2c3bf08e8 100644 --- a/server/src/uds/osmanagers/WindowsOsManager/windows.py +++ b/server/src/uds/osmanagers/WindowsOsManager/windows.py @@ -350,7 +350,9 @@ class WindowsOsManager(osmanagers.OSManager): """ Serializes the os manager data so we can store it in database """ - return '\t'.join(['v3', self._onLogout, str(self._idle), gui.boolToStr(self._deadLine)]).encode('utf8') + return '\t'.join( + ['v3', self._onLogout, str(self._idle), gui.boolToStr(self._deadLine)] + ).encode('utf8') def unmarshal(self, data: bytes) -> None: vals = data.decode('utf8').split('\t') @@ -362,7 +364,11 @@ class WindowsOsManager(osmanagers.OSManager): elif vals[0] == 'v2': self._onLogout, self._idle = vals[1], int(vals[2]) elif vals[0] == 'v3': - self._onLogout, self._idle, self._deadLine = vals[1], int(vals[2]), gui.strToBool(vals[3]) + self._onLogout, self._idle, self._deadLine = ( + vals[1], + int(vals[2]), + gui.strToBool(vals[3]), + ) except Exception: logger.exception( 'Exception unmarshalling. Some values left as default ones' @@ -371,4 +377,8 @@ class WindowsOsManager(osmanagers.OSManager): self.__setProcessUnusedMachines() def valuesDict(self) -> gui.ValuesDictType: - return {'onLogout': self._onLogout, 'idle': str(self._idle), 'deadLine': gui.boolToStr(self._deadLine) } + return { + 'onLogout': self._onLogout, + 'idle': str(self._idle), + 'deadLine': gui.boolToStr(self._deadLine), + } diff --git a/server/src/uds/osmanagers/WindowsOsManager/windows_random.py b/server/src/uds/osmanagers/WindowsOsManager/windows_random.py index b634bf99b..9f9799f41 100644 --- a/server/src/uds/osmanagers/WindowsOsManager/windows_random.py +++ b/server/src/uds/osmanagers/WindowsOsManager/windows_random.py @@ -58,12 +58,26 @@ logger = logging.getLogger(__name__) class WinRandomPassManager(WindowsOsManager): typeName = _('Windows Random Password OS Manager') typeType = 'WinRandomPasswordManager' - typeDescription = _('Os Manager to control windows machines, with user password set randomly.') + typeDescription = _( + 'Os Manager to control windows machines, with user password set randomly.' + ) iconFile = 'wosmanager.png' # Apart form data from windows os manager, we need also domain and credentials - userAccount = gui.TextField(length=64, label=_('Account'), order=2, tooltip=_('User account to change password'), required=True) - password = gui.PasswordField(length=64, label=_('Password'), order=3, tooltip=_('Current (template) password of the user account'), required=True) + userAccount = gui.TextField( + length=64, + label=_('Account'), + order=2, + tooltip=_('User account to change password'), + required=True, + ) + password = gui.PasswordField( + length=64, + label=_('Password'), + order=3, + tooltip=_('Current (template) password of the user account'), + required=True, + ) # Inherits base "onLogout" onLogout = WindowsOsManager.onLogout @@ -74,55 +88,87 @@ class WinRandomPassManager(WindowsOsManager): super().__init__(environment, values) if values: if values['userAccount'] == '': - raise osmanagers.OSManager.ValidationException(_('Must provide an user account!!!')) + raise osmanagers.OSManager.ValidationException( + _('Must provide an user account!!!') + ) if values['password'] == '': - raise osmanagers.OSManager.ValidationException(_('Must provide a password for the account!!!')) + raise osmanagers.OSManager.ValidationException( + _('Must provide a password for the account!!!') + ) self._userAccount = values['userAccount'] self._password = values['password'] else: self._userAccount = '' self._password = "" - def processUserPassword(self, userService: 'UserService', username: str, password: str) -> typing.Tuple[str, str]: + def processUserPassword( + self, userService: 'UserService', username: str, password: str + ) -> typing.Tuple[str, str]: if username == self._userAccount: password = userService.recoverValue('winOsRandomPass') - return WindowsOsManager.processUserPassword(self, userService, username, password) + return WindowsOsManager.processUserPassword( + self, userService, username, password + ) def genPassword(self, userService: 'UserService'): randomPass = userService.recoverValue('winOsRandomPass') if not randomPass: # Generates a password that conforms to complexity rnd = random.SystemRandom() - base = ''.join(rnd.choice(v) for v in (string.ascii_lowercase, string.ascii_uppercase, string.digits)) + rnd.choice('.+-') - randomPass = ''.join(rnd.choice(string.ascii_letters + string.digits) for _ in range(12)) + base = ''.join( + rnd.choice(v) + for v in (string.ascii_lowercase, string.ascii_uppercase, string.digits) + ) + rnd.choice('.+-') + randomPass = ''.join( + rnd.choice(string.ascii_letters + string.digits) for _ in range(12) + ) pos = rnd.randrange(0, len(randomPass)) randomPass = randomPass[:pos] + base + randomPass[pos:] userService.storeValue('winOsRandomPass', randomPass) - log.doLog(userService, log.INFO, "Password set to \"{}\"".format(randomPass), log.OSMANAGER) + log.doLog( + userService, + log.INFO, + "Password set to \"{}\"".format(randomPass), + log.OSMANAGER, + ) return randomPass - def actorData(self, userService: 'UserService') -> typing.MutableMapping[str, typing.Any]: + def actorData( + self, userService: 'UserService' + ) -> typing.MutableMapping[str, typing.Any]: return { 'action': 'rename', 'name': userService.getName(), 'username': self._userAccount, 'password': self._password, - 'new_password': self.genPassword(userService) + 'new_password': self.genPassword(userService), } def infoVal(self, userService: 'UserService') -> str: - return 'rename:{0}\t{1}\t{2}\t{3}'.format(self.getName(userService), self._userAccount, self._password, self.genPassword(userService)) + return 'rename:{0}\t{1}\t{2}\t{3}'.format( + self.getName(userService), + self._userAccount, + self._password, + self.genPassword(userService), + ) def infoValue(self, userService: 'UserService') -> str: - return 'rename\r{0}\t{1}\t{2}\t{3}'.format(self.getName(userService), self._userAccount, self._password, self.genPassword(userService)) + return 'rename\r{0}\t{1}\t{2}\t{3}'.format( + self.getName(userService), + self._userAccount, + self._password, + self.genPassword(userService), + ) def marshal(self) -> bytes: ''' Serializes the os manager data so we can store it in database ''' base = codecs.encode(super().marshal(), 'hex').decode() - return '\t'.join(['v1', self._userAccount, cryptoManager().encrypt(self._password), base]).encode('utf8') + return '\t'.join( + ['v1', self._userAccount, cryptoManager().encrypt(self._password), base] + ).encode('utf8') def unmarshal(self, data: bytes) -> None: values = data.decode('utf8').split('\t') diff --git a/server/src/uds/osmanagers/__init__.py b/server/src/uds/osmanagers/__init__.py index c4b3400e7..401c95e5b 100644 --- a/server/src/uds/osmanagers/__init__.py +++ b/server/src/uds/osmanagers/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # -# Copyright (c) 2012 Virtual Cable S.L. +# Copyright (c) 2012-2021 Virtual Cable S.L.U. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, @@ -12,7 +12,7 @@ # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. -# * Neither the name of Virtual Cable S.L. nor the names of its contributors +# * Neither the name of Virtual Cable S.L.U. nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # @@ -53,7 +53,7 @@ def __init__(): """ from uds.core import osmanagers - # Dinamycally import children of this package. The __init__.py files must register, if needed, inside ServiceProviderFactory + # Dinamycally import children of this package. pkgpath = os.path.dirname(sys.modules[__name__].__file__) for _, name, _ in pkgutil.iter_modules([pkgpath]): @@ -63,7 +63,7 @@ def __init__(): importlib.invalidate_caches() p = osmanagers.OSManager - # This is marked as error in IDE, but it's not (__subclasses__) + for cls in p.__subclasses__(): osmanagers.factory().insert(cls) diff --git a/server/src/uds/services/PhysicalMachines/__init__.py b/server/src/uds/services/PhysicalMachines/__init__.py index 876a63e55..bf78b80ea 100644 --- a/server/src/uds/services/PhysicalMachines/__init__.py +++ b/server/src/uds/services/PhysicalMachines/__init__.py @@ -32,7 +32,3 @@ """ from .provider import PhysicalMachinesProvider - -# Now we use __subclasses__ method to locate Service Providers -# and register them inside factory -# ServiceProviderFactory.factory().insert(PhysicalMachinesProvider) diff --git a/server/src/uds/services/__init__.py b/server/src/uds/services/__init__.py index b82d417b2..574786e27 100644 --- a/server/src/uds/services/__init__.py +++ b/server/src/uds/services/__init__.py @@ -58,7 +58,7 @@ def __init__(): """ from uds.core import services - # Dinamycally import children of this package. The __init__.py files must register, if needed, inside ServiceProviderFactory + # Dinamycally import children of this package. pkgpath = os.path.dirname(sys.modules[__name__].__file__) for _, name, _ in pkgutil.iter_modules([pkgpath]): # __import__('uds.services.' + name, globals(), locals(), [])