diff --git a/server/src/uds/REST/methods/tickets.py b/server/src/uds/REST/methods/tickets.py index 1f1c862a8..5b6ddfab0 100644 --- a/server/src/uds/REST/methods/tickets.py +++ b/server/src/uds/REST/methods/tickets.py @@ -129,6 +129,9 @@ class Tickets(Handler): userIp: typing.Optional[str] = self._params.get('userIp', None) try: + servicePoolId = None + transportId = None + authId = self._params.get('authId', None) authName = self._params.get('auth', None) authTag = self._params.get('authTag', self._params.get('authSmallName', None)) @@ -161,39 +164,61 @@ class Tickets(Handler): realname: str = self._params.get('realname', self._params['username']) if 'servicePool' in self._params: - servicePool: models.ServicePool = models.ServicePool.objects.get(uuid=processUuid(self._params['servicePool'])) + # Check if is pool or metapool + poolUuid = processUuid(self._params['servicePool']) + pool : typing.Union[models.ServicePool, models.MetaPool] - # If forced that servicePool must honor groups - if force: - for addGrp in set(groupIds) - set(servicePool.assignedGroups.values_list('uuid', flat=True)): - servicePool.assignedGroups.add(auth.groups.get(uuid=addGrp)) + try: + pool = typing.cast(models.MetaPool, models.MetaPool.objects.get(uuid=poolUuid)) # If not an metapool uuid, will process it as a servicePool + if force: + # First, add groups to metapool + for addGrp in set(groupIds) - set(pool.assignedGroups.values_list('uuid', flat=True)): + pool.assignedGroups.add(auth.groups.get(uuid=addGrp)) + # And now, to ALL metapool members + for memberPool in pool.members.all(): + # First, add groups to metapool + for addGrp in set(groupIds) - set(memberPool.assignedGroups.values_list('uuid', flat=True)): + memberPool.assignedGroups.add(auth.groups.get(uuid=addGrp)) + + # For metapool, transport is ignored.. - if 'transport' in self._params: - transport: models.Transport = models.Transport.objects.get(uuid=processUuid(self._params['transport'])) - try: - servicePool.validateTransport(transport) - except Exception: - logger.error('Transport %s is not valid for Service Pool %s', transport.name, servicePool.name) - raise Exception('Invalid transport for Service Pool') - else: - transport = models.Transport(uuid=None) - if userIp: - for v in servicePool.transports.order_by('priority'): - if v.validForIp(userIp): - transport = v - break + servicePoolId = 'M' + pool.uuid + transportId = 'meta' + + except models.MetaPool.DoesNotExist: + pool = typing.cast(models.ServicePool, models.ServicePool.objects.get(uuid=poolUuid)) - if transport.uuid is None: - logger.error('Service pool %s does not has valid transports for ip %s', servicePool.name, userIp) - raise Exception('Service pool does not has any valid transports for ip {}'.format(userIp)) + # If forced that servicePool must honor groups + if force: + for addGrp in set(groupIds) - set(pool.assignedGroups.values_list('uuid', flat=True)): + pool.assignedGroups.add(auth.groups.get(uuid=addGrp)) - servicePool = servicePool.uuid - transport = transport.uuid + if 'transport' in self._params: + transport: models.Transport = models.Transport.objects.get(uuid=processUuid(self._params['transport'])) + try: + pool.validateTransport(transport) + except Exception: + logger.error('Transport %s is not valid for Service Pool %s', transport.name, pool.name) + raise Exception('Invalid transport for Service Pool') + else: + transport = models.Transport(uuid=None) + if userIp: + for v in pool.transports.order_by('priority'): + if v.validForIp(userIp): + transport = v + break + if transport.uuid is None: + logger.error('Service pool %s does not has valid transports for ip %s', pool.name, userIp) + raise Exception('Service pool does not has any valid transports for ip {}'.format(userIp)) + + servicePoolId = 'F' + pool.uuid + transportId = transport.uuid + except models.Authenticator.DoesNotExist: return Tickets.result(error='Authenticator does not exists') except models.ServicePool.DoesNotExist: - return Tickets.result(error='Service pool does not exists') + return Tickets.result(error='Service pool (or metapool) does not exists') except models.Transport.DoesNotExist: return Tickets.result(error='Transport does not exists') except Exception as e: @@ -205,8 +230,8 @@ class Tickets(Handler): 'realname': realname, 'groups': groupIds, 'auth': auth.uuid, - 'servicePool': servicePool, - 'transport': transport, + 'servicePool': servicePoolId, + 'transport': transportId, } ticket = models.TicketStore.create(data) diff --git a/server/src/uds/core/managers/user_service.py b/server/src/uds/core/managers/user_service.py index 62a0083b9..732d7f211 100644 --- a/server/src/uds/core/managers/user_service.py +++ b/server/src/uds/core/managers/user_service.py @@ -656,13 +656,14 @@ class UserServiceManager: if meta.isAccessAllowed() is False: raise ServiceAccessDeniedByCalendar() + poolMembers = [p for p in meta.members.all() if p.pool.isVisible() and p.pool.isUsable()] # Sort pools based on meta selection if meta.policy == MetaPool.PRIORITY_POOL: - sortPools = [(p.priority, p.pool) for p in meta.members.all()] + sortPools = [(p.priority, p.pool) for p in poolMembers] elif meta.policy == MetaPool.MOST_AVAILABLE_BY_NUMBER: - sortPools = [(p.usage(), p) for p in meta.pools.all()] + sortPools = [(p.usage(), p) for p in poolMembers] else: - sortPools = [(random.randint(0, 10000), p) for p in meta.pools.all()] # Just shuffle them + sortPools = [(random.randint(0, 10000), p) for p in poolMembers] # Just shuffle them # Sort pools related to policy now, and xtract only pools, not sort keys # Remove "full" pools (100%) from result and pools in maintenance mode, not ready pools, etc... diff --git a/server/src/uds/web/views/auth.py b/server/src/uds/web/views/auth.py index f30245fcd..509ade045 100644 --- a/server/src/uds/web/views/auth.py +++ b/server/src/uds/web/views/auth.py @@ -183,7 +183,7 @@ def ticketAuth(request: 'HttpRequest', ticketId: str) -> HttpResponse: # pylint groups = data['groups'] auth = data['auth'] realname = data['realname'] - servicePool = data['servicePool'] + poolUuid = data['servicePool'] password = cryptoManager().decrypt(data['password']) transport = data['transport'] except Exception: @@ -220,12 +220,12 @@ def ticketAuth(request: 'HttpRequest', ticketId: str) -> HttpResponse: # pylint # Override and recalc transport based on current os transport = None - logger.debug("Service & transport: %s, %s", servicePool, transport) + logger.debug("Service & transport: %s, %s", poolUuid, transport) # Check if servicePool is part of the ticket - if servicePool: + if poolUuid: # If service pool is in there, also is transport - res = userServiceManager().getService(request.user, request.os, request.ip, 'F' + servicePool, transport, False) + res = userServiceManager().getService(request.user, request.os, request.ip, poolUuid, transport, False) _, userService, _, transport, _ = res transportInstance = transport.getInstance()