1
0
mirror of https://github.com/dkmstr/openuds.git synced 2025-10-12 07:33:39 +03:00

13 Commits

Author SHA1 Message Date
Adolfo Gómez García
844060addb Added info on modurls fail loading 2025-10-09 17:27:02 +02:00
Adolfo Gómez García
cd60b398a9 Fixed sample settings and added more info to log on case of SAML failure 2025-10-03 18:03:50 +02:00
Adolfo Gómez García
979f992b6d Update RDP and X2GO tunnel scripts and signatures with new configurations 2025-10-01 18:47:43 +02:00
Adolfo Gómez García
83689dddaa Merge remote-tracking branch 'origin/dev/andres/v4.0' into v4.0 2025-09-25 19:19:19 +02:00
Adolfo Gómez García
037b4abad1 Add enumerate_servers method to filter out servers in maintenance mode 2025-09-23 19:26:52 +02:00
Adolfo Gómez García
839e4c6b1d Fix access check in ServersServers class to use parent object instead of item 2025-09-23 19:10:49 +02:00
aschumann-virtualcable
2fd157e463 Merge remote-tracking branch 'origin/v4.0' into dev/andres/v4.0 2025-09-22 17:36:09 +02:00
Adolfo Gómez García
7e51c1fd93 Handle InvalidServiceException in enable_service function and log a warning 2025-09-22 16:53:45 +02:00
Adolfo Gómez García
b6af59cc44 Refactor MAC address handling in IPMachinesUserService to use constant for unknown MACs 2025-09-22 16:27:57 +02:00
Adolfo Gómez García
50072e948e Fix token assignment in IPMachinesService to use the correct attribute 2025-09-22 16:22:25 +02:00
Adolfo Gómez García
c5e0d0721f Add max_users attribute to ServerStatsWeights for load calculation 2025-09-19 16:03:16 +02:00
aschumann-virtualcable
afbd4c5355 Fixes incorrect parameter usage for macOS RDP connections
Updates logic to use the correct macOS-specific custom parameters
instead of Linux parameters when generating RDP connection settings.
Adds type ignore comments to improve compatibility with type checkers
and prevent related runtime issues.
2025-09-19 13:54:36 +02:00
Adolfo Gómez García
bf97c6f2dc Reduce default max items to 200 and enhance service pool export logic to include additional user services, while adding server group serialization to the tree command output. 2025-09-17 17:57:41 +02:00
19 changed files with 77 additions and 40 deletions

View File

@@ -14,6 +14,7 @@ BASE_DIR = '/'.join(
) # If used 'relpath' instead of abspath, returns path of "enterprise" instead of "openuds"
DEBUG = True
PROFILING = False
# USE_X_FORWARDED_HOST = True
SECURE_PROXY_SSL_HEADER = (

View File

@@ -338,7 +338,7 @@ class ServersServers(DetailHandler):
:param item:
"""
item = models.Server.objects.get(uuid=process_uuid(id))
self.ensure_has_access(item, types.permissions.PermissionType.MANAGEMENT)
self.ensure_has_access(parent, types.permissions.PermissionType.MANAGEMENT)
item.maintenance_mode = not item.maintenance_mode
item.save()
return 'ok'

View File

@@ -657,7 +657,10 @@ class SAMLAuthenticator(auths.Authenticator):
raise exceptions.auth.AuthenticatorException(gettext('Error processing SAML response: ') + str(e))
errors = typing.cast(list[str], auth.get_errors())
if errors:
raise exceptions.auth.AuthenticatorException('SAML response error: ' + str(errors))
logger.debug('Errors processing SAML response: %s (%s)', errors, auth.get_last_error_reason()) # pyright: ignore reportUnknownVariableType
logger.debug('post_data: %s', req['post_data'])
logger.info('Response XML: %s', auth.get_last_response_xml()) # pyright: ignore reportUnknownVariableType
raise exceptions.auth.AuthenticatorException(f'SAML response error: {errors} ({auth.get_last_error_reason()})')
if not auth.is_authenticated():
raise exceptions.auth.AuthenticatorException(gettext('SAML response not authenticated'))

View File

@@ -75,4 +75,4 @@ UNLIMITED: typing.Final[int] = -1
# Constant marking no more names available
NO_MORE_NAMES: typing.Final[str] = 'NO-NAME-ERROR'
# For convenience, same as MAC_UNKNOWN, but different meaning
NO_MORE_MACS: typing.Final[str] = '00:00:00:00:00:00'
NO_MORE_MACS: typing.Final[str] = MAC_UNKNOWN

View File

@@ -142,6 +142,7 @@ class ServerStatsWeights:
cpu: float = 0.3
memory: float = 0.6
users: float = 0.1
max_users: int = 100 # Max users to consider in load calculation
def normalize(self) -> 'ServerStatsWeights':
total = self.cpu + self.memory + self.users
@@ -155,6 +156,7 @@ class ServerStatsWeights:
'cpu': self.cpu,
'memory': self.memory,
'users': self.users,
'max_users': self.max_users,
}
@staticmethod
@@ -163,6 +165,7 @@ class ServerStatsWeights:
data.get('cpu', 0.3),
data.get('memory', 0.6),
data.get('users', 0.1),
int(data.get('max_users', 100)),
).normalize()
@@ -210,7 +213,7 @@ class ServerStats:
w = (
weights.cpu * self.cpuused
+ weights.memory * (self.memused / (self.memtotal or 1))
+ weights.users * (min(1.0, self.current_users / 100.0))
+ weights.users * (min(1.0, self.current_users / weights.max_users))
)
return min(max(0.0, w), 1.0)

View File

@@ -76,8 +76,8 @@ def get_urlpatterns_from_modules() -> list[typing.Any]:
# Append patters from mod
for up in urlpatterns:
patterns.append(up)
except Exception:
logger.error('No patterns found in %s', module_fullname)
except Exception as e:
logger.error('No patterns found in %s (%s)', module_fullname, e)
except Exception:
logger.exception('Processing dispatchers loading')

View File

@@ -130,7 +130,7 @@ class Command(BaseCommand):
'--max-items',
action='store',
dest='maxitems',
default=400,
default=200,
help='Maximum elements exported for groups and user services',
)
@@ -166,7 +166,15 @@ class Command(BaseCommand):
fltr = servicepool.userServices.all()
if not options['alluserservices']:
fltr = fltr.filter(state=types.states.State.ERROR)
for item in fltr[:max_items]: # at most max_items items
fltr_list = list(fltr)[:max_items]
if len(fltr_list) < max_items:
# Append rest of userservices, if there is space
fltr_list += list(
servicepool.userServices.exclude(
pk__in=[u.pk for u in fltr_list]
)[: max_items - len(fltr_list)]
)
for item in fltr_list[:max_items]: # at most max_items items
logs = [
f'{l["date"]}: {types.log.LogLevel.from_int(l["level"])} [{l["source"]}] - {l["message"]}'
for l in log.get_logs(item)
@@ -241,8 +249,22 @@ class Command(BaseCommand):
'_': get_serialized_from_managed_object(provider),
'services': services,
}
tree[counter('PROVIDERS')] = providers
# Get server groups
server_groups: dict[str, typing.Any] = {}
for server_group in models.ServerGroup.objects.all():
servers: dict[str, typing.Any] = {}
for server in server_group.servers.all()[:max_items]: # at most max_items items
servers[server.hostname] = get_serialized_from_model(server, exclude_uuid=False)
server_groups[server_group.name] = {
'_': get_serialized_from_model(server_group, exclude_uuid=False),
'servers': servers,
}
tree[counter('SERVICES')] = {
'providers': providers,
'server_groups': server_groups
}
# authenticators
authenticators: dict[str, typing.Any] = {}
@@ -380,12 +402,12 @@ class Command(BaseCommand):
tree[counter('CONFIG')] = cfg
# Last 7 days of logs
# Last 7 days of logs or 500 entries, whichever is less
logs = [
get_serialized_from_model(log_entry)
for log_entry in models.Log.objects.filter(
created__gt=now - datetime.timedelta(days=7)
).order_by('-created')
).order_by('-created')[:500]
]
# Cluster nodes
cluster_nodes: list[dict[str, str]] = [node.as_dict() for node in cluster.enumerate_cluster_nodes()]

View File

@@ -109,7 +109,7 @@ class IPMachinesService(services.Service):
self.ipList.value = [_as_identifier(i) for i in _ips]
if values[0] != b'v1':
self._token = values[1].decode()
self.token.value = values[1].decode()
if values[0] in (b'v3', b'v4', b'v5', b'v6', b'v7'):
self.port.value = int(values[2].decode())
if values[0] in (b'v4', b'v5', b'v6', b'v7'):

View File

@@ -33,7 +33,7 @@ Author: Adolfo Gómez, dkmaster at dkmon dot com
import logging
import typing
from uds.core import services, types
from uds.core import consts, services, types
from uds.core.util import autoserializable
# Not imported at runtime, just for type checking
@@ -73,7 +73,7 @@ class IPMachinesUserService(services.UserService, autoserializable.AutoSerializa
def get_unique_id(self) -> str:
# Generate a 16 chars string mixing up all _vmid chars
return self._mac or self._ip
return self._mac if self._mac and self._mac != consts.MAC_UNKNOWN else self._ip
def set_ready(self) -> types.states.TaskState:
self.service().wakeup(self._ip, self._mac)

View File

@@ -141,6 +141,9 @@ class IPMachinesService(services.Service):
services_type_provided = types.services.ServiceType.VDI
def enumerate_servers(self) -> typing.Iterable['models.Server']:
return fields.get_server_group_from_field(self.server_group).servers.filter(maintenance_mode=False)
def get_token(self) -> typing.Optional[str]:
return self.token.as_str() or None
@@ -153,7 +156,7 @@ class IPMachinesService(services.Service):
now = sql_now()
return [
gui.choice_item(server.uuid, f'{server.host}|{server.mac}')
for server in fields.get_server_group_from_field(self.server_group).servers.all()
for server in self.enumerate_servers()
if server.locked_until is None or server.locked_until < now
]
@@ -175,14 +178,15 @@ class IPMachinesService(services.Service):
'''
Returns an unassigned machine
'''
list_of_servers = list(fields.get_server_group_from_field(self.server_group).servers.all())
# Get all servers in the group, not in maintenance mode
list_of_servers = list(self.enumerate_servers())
if self.randomize_host.as_bool() is True:
random.shuffle(list_of_servers) # Reorder the list randomly if required
for server in list_of_servers:
# If not locked or lock expired
if server.locked_until is None or server.locked_until < sql_now():
# if port check enabled, check
# if port check enabled, check
if self.port.value != 0:
if not net.test_connectivity(server.host, self.port.value):
server.lock(datetime.timedelta(minutes=self.ignore_minutes_on_failure.value))

View File

@@ -183,7 +183,7 @@ class RDPTransport(BaseRDPTransport):
if self.mac_use_rdp_file.as_bool():
r.custom_parameters = self.wnd_custom_parameters.value
else:
r.custom_parameters = self.lnx_custom_parameters.value
r.custom_parameters = self.mac_custom_parameters.value
sp.update(
{
'as_new_xfreerdp_params': r.as_new_xfreerdp_params,

View File

@@ -218,7 +218,7 @@ class TRDPTransport(BaseRDPTransport):
if self.mac_use_rdp_file.as_bool():
r.custom_parameters = self.wnd_custom_parameters.value
else:
r.custom_parameters = self.lnx_custom_parameters.value
r.custom_parameters = self.mac_custom_parameters.value
sp.update(
{
'as_new_xfreerdp_params': r.as_new_xfreerdp_params,

View File

@@ -43,25 +43,25 @@ def _exec_client_with_params(executable: str, params: typing.List[str], unlink_f
tools.addFileToUnlink(unlink_file)
def exec_udsrdp(udsrdp: str) -> None:
params = [os.path.expandvars(i) for i in [udsrdp] + sp['as_new_xfreerdp_params'] + [f'/v:{sp["address"]}']]
params = [os.path.expandvars(i) for i in [udsrdp] + sp['as_new_xfreerdp_params'] + [f'/v:{sp["address"]}']] # type: ignore
_exec_client_with_params(udsrdp, params)
def exec_new_xfreerdp(xfreerdp: str) -> None:
if sp.get('as_file', ''):
dest_filename = _prepare_rdp_file(sp['as_file'], '.uds.rdp')
params = [xfreerdp, dest_filename, f'/p:{sp.get("password", "")}']
if sp.get('as_file', ''): # type: ignore
dest_filename = _prepare_rdp_file(sp['as_file'], '.uds.rdp') # type: ignore
params = [xfreerdp, dest_filename, f'/p:{sp.get("password", "")}'] # type: ignore
_exec_client_with_params(xfreerdp, params, unlink_file=dest_filename)
else:
params = [os.path.expandvars(i) for i in [xfreerdp] + sp['as_new_xfreerdp_params'] + [f'/v:{sp["address"]}']]
params = [os.path.expandvars(i) for i in [xfreerdp] + sp['as_new_xfreerdp_params'] + [f'/v:{sp["address"]}']] # type: ignore
_exec_client_with_params(xfreerdp, params)
def exec_thincast(thincast: str) -> None:
if sp.get('as_file', ''):
dest_filename = _prepare_rdp_file(sp['as_file'], '.rdp')
params = [thincast, dest_filename, f'/p:{sp.get("password", "")}']
if sp.get('as_file', ''): # type: ignore
dest_filename = _prepare_rdp_file(sp['as_file'], '.rdp') # type: ignore
params = [thincast, dest_filename, f'/p:{sp.get("password", "")}'] # type: ignore
_exec_client_with_params(thincast, params, unlink_file=dest_filename)
else:
params = [os.path.expandvars(i) for i in [thincast] + sp['as_new_xfreerdp_params'] + [f'/v:{sp["address"]}']]
params = [os.path.expandvars(i) for i in [thincast] + sp['as_new_xfreerdp_params'] + [f'/v:{sp["address"]}']] # type: ignore
_exec_client_with_params(thincast, params)
# Typical Thincast Routes on Linux

View File

@@ -1 +1 @@
Jk6itcePhQyNebx65AQanMLRapBn/cfN066shvowwMWN5dKn+YONY1ydxObj1p645AWXYVoVMJNwxWrlL4orqo6VkPOVBZjzT0pWKplRHcdxVuAnCvNyiprjiLGSgm401kp5F4jSIIm+nADb2a0gdlADBwVok2+Dqps19ebP1j3hvX7f4/sUEIPAl9xGAS4MCrOuEde8SnGvDnLJfTGzq5Kt4guSEhM81s037PK/RgkQQIxBIyeinTmaklFsMhmnKI9csQ5QW7Zkig5BSwARe/m2SWuf/WJfFE9L9l5ObroXjw4wV4MLp1EpWusVwjel+OEeNdU7lanKxxlqBXPwqeVRDyh1ag43O30TQHWkdAZOdFYGUxL7ft6AVuAewMwNp76px65M00dYL5QbQ2PXPmuAjGnZskTshCvyo82G5kYJgXireHieim8eW0fULA5P4PHv/dH1+RwhuO71An1tq34ngeOVFkskIWmvDQqlbkoHz6Bfk2JhkLDU88voa1toxeRXm1ZXdRPdUPrD91HRvEOUTlm4VJxiYiEWOH4jJGy/na6EKAFm4rM+xptAebp73y6KQbcwBZRocRKpMvnd3EG3qvV2l37HMTJyg8Rn7an9yad3j6iFq3tKBeTp8ExNo0bPUV4UV+ymDzA49f5DsizJxu6+qCT/Ee4O4sMotok=
Y7IpJNU/ne7JUqmOqNPu5gPlCWRDjK6nYKK69K6yxjEu7PT6g1ZkGlrNS2QeQY9bvOuxTlWF8nF+inbQTUQOte6rIX8kSZUJFcOKbxxcWDJiJvPArE5iKCJPpPPHFFH97MVVDYuYT4C5XvR7bDQNVlmxB6oUGvO/71mC4D3gxau1FA24fISRio3aCUVWFjEBlt55PyVhg9qn4r+jBP4bwBVW1NmmjONsIrf6+pvI3gIspYIwzBg9Nflv67aKY7tLdylkcQ7lHx2pY20onaDuT+WGRlQdqc4K0kAzZyTO9FEe/SGe0Nsi0BPMBK1LjFtNJ0KQABLWoTZWSXgloY/2JQvoOC1Z57K4g9R8Nq2BDNpCWADz2nP713zt30dK4Emg6Uh3lkew4zF98atY9Mb5bdNmzQp3dCv9xGAGPm66eIqQUEKDt7zone6j6r81c8jPbl7m/9f/iul8d3a4bPEv5DMHTL23YdFSc6AHDp32ngaB4qLxgtDCvQhnkrayqiYHOlYnS1A/TBS7c2K/Od0nZvuxZKUuDiC7RlSxEAo/EdmWSbeA01cYeh7v0lkdkQaOMGI45DPjLaCwuhgb85cbHcFEDo1CpZSYhyhqApx15/0Jt/CIuFM3FG0cf4B6/6T7Ll7IqGCeTl6nuF2N3ux1ND7UAMBpqjWAlg9/Y7T+aq4=

View File

@@ -60,10 +60,10 @@ def exec_udsrdp(udsrdp: str, port: int) -> None:
_exec_client_with_params(udsrdp, params)
def exec_new_xfreerdp(xfreerdp: str, port: int) -> None:
if sp.get('as_file', ''):
if sp.get('as_file', ''): # type: ignore
logger.debug('XFREERDP client will use RDP file')
dest_filename = _prepare_rdp_file(sp['as_file'], port, '.rdp')
params = [xfreerdp, dest_filename, f'/p:{sp.get("password", "")}']
dest_filename = _prepare_rdp_file(sp['as_file'], port, '.rdp') # type: ignore
params = [xfreerdp, dest_filename, f'/p:{sp.get("password", "")}'] # type: ignore
_exec_client_with_params(xfreerdp, params, unlink_file=dest_filename)
else:
logging.debug('XFREERDP client will use command line parameters')
@@ -71,11 +71,11 @@ def exec_new_xfreerdp(xfreerdp: str, port: int) -> None:
_exec_client_with_params(xfreerdp, params)
def exec_thincast(thincast: str, port: int) -> None:
if sp.get('as_file', ''):
if sp.get('as_file', ''): # type: ignore
logger.debug('Thincast client will use RDP file')
dest_filename = _prepare_rdp_file(sp['as_file'], port, '.rdp')
params = [thincast, dest_filename, f'/p:{sp.get("password", "")}']
_exec_client_with_params(thincast, params, unlink_file=dest_filename )
dest_filename = _prepare_rdp_file(sp['as_file'], port, '.rdp') # type: ignore
params = [thincast, dest_filename, f'/p:{sp.get("password", "")}'] # type: ignore
_exec_client_with_params(thincast, params, unlink_file=dest_filename)
else:
logging.debug('Thincast client will use command line parameters')
params: typing.List[str] = [os.path.expandvars(i) for i in [app] + sp['as_new_xfreerdp_params'] + [f'/v:127.0.0.1:{port}']] # type: ignore

View File

@@ -1 +1 @@
rHy0885L4XPOrWLCKgn/A+7LYfPpuymRo5Pq3zcDKpW9lUmBdBryTJAGYuaEDiJWq3+Lp0y3W5GIhE11xHtR/XpF70GW/GW7YGRgbDvYlvDz06jNoQWi6tzFnAsA+cvcVPd18PLaC6rDWJpx55PEa8Aq+kqZeGIjiLBRFeTMiv4BXGz60ba9vNNfn+dCHbqOXjXk+zOKHkaGE3hHz3CIrb3IkLYI0KfEODgySZs39yNqfcnRmFgdnH3sM+V09ZUm5hJNgP41Nc8UJgwidBwQXnZXMk0VQMv5BBX9NWdnwuO/nI0JKanpnWd0QLQ991i4TDjWDkchXVWAIwune7djgKy9b0yVkfWYxykJXT2EEzBtSGqm4NETj4q3BIzHJNSaL2HZkPSY9/5olTCaPZY5JfmUPVNJK8wSMzSTPeinn1NkGfSQDgcc28yu6M+/xSrQV6XB9kt9k5Q0TacXfONr5q5F4ReDqasD/EPLJdcVc0f5DI+t7+/no+xNk+f0NrfmjvTNKTqCmTBaJXC+gX72rzTQslxyFokIPJN+luLYasZureRFHCnXlrQn579B4eLQ1+QcPVFKU0SZChkbNbBgpTABkAI3j9Kg41NLp5f1/Sx28ACTW3cSRJbNQKe3s5XXCCn1Fg5XC49MinrSwNk34HfafgQ+X/G1HNqeydtHn1M=
n3a+b8OD5i8IAbP/fK2c72A1UzRScr7kH2BeY4zSaVJoJf+Xn4+F6Osm0emtS+1muStwHvIE9Hqnxdg8lbYHIrjRAGvFazs5xcExIvYU1rVA/gmBjaViqUl6SQc+3zWa7xXwOVrwQdoXF9WGYOAH8DAPT/aiKgeaCoKlCFNyrxlMImxWPlWRvCKrZQlWxvB6rKFC0apO+xxi4FU3xXIomWBufnLuDppYL+xwVzMj4YNWec3rdV6RT8cpBQzfkNec7rgHBOB+Py2BnY54TtMqlECpXZlEYy4NVORI0rwZ+aK8dvpGvRS4nWQnq3edRkWTzDZAo+Kkp17/fmCTEGucQ/TC4Y2qBoB35kxQmv1aWhWWyJ/BdpHI6lNJR884lK/yup3I+vQbf7ZJzu6wT98YHk0x+rsPt97FPxJsVdsxWG4IcaVgheuIjlYPNShMDoy/slOyEz/k0j7jWAhRu0WWMHjI/ozighX+jHmNeIG9EPim0sKZ/04okSXxhwwC1UzwcevUdrI2eUyaUEbq9Ua3SMCuQNmDVKFlJJ6PUucbWvgKsdsSMbW1L4syA41yTPk9dcYHlu32k8oaZ1o3QIDw7Do48pygwnWSJM9XlynFcRcYmOikRIrINJlJmKH6oY+ez9nva7cAV6rFel+jk7bgSZUrKMfdsnsLh1PSabnLJ/s=

View File

@@ -27,7 +27,7 @@ theFile = sp['xf'].format(export=home, keyFile=keyFile.replace('\\', '/'), ip='1
filename = tools.saveTempFile(theFile)
x2goPath = os.environ['PROGRAMFILES(X86)'] + '\\x2goclient'
executable = tools.findApp('x2goclient.exe', [x2goPath])
executable = tools.findApp('x2goclient.exe', x2goPath)
if executable is None:
raise Exception(
'''<p>You must have installed latest X2GO Client in default program file folder in order to connect to this UDS service.</p>

View File

@@ -1 +1 @@
NzheeXAbv2kVktgPeHMrFR+fkSjoz4NcPHrfrMXKP4BGS8oeBO8CBJw0OFYqXIRKCsBPi6yvd961Ofg2UFi6brr4dCut6PfXddKEJIEbanwTUr3yx6882TOw95h3ibLkIP9Fi/6VmId8X3QnPqdmN8XgU2eB7ONrvFzu9aCcMuKj2rKLXlesJ1t/ArxRn80xrCKp/27jDX1aitcTHzo9VsM9bjBNodHp6V+/hHiw+Ht7qI9MZ1a2jQxA63CR5uqsAJ5B4qcp/fn4TBXgPr2NxL1StT19v3e36YuCKhSUVS8b3ggDrGU982m5rfcbn9Gz3yaaYNcHmf2600AdMFGsjiBmiv65Tjc1utC81rsmbsomsSBj48IZ0ZoYXgZkSHDYzRU7xVA2QAYpLI1IM8tputACN1L5vcNQXl6SqrJc3+3PidOmUyxrQxjNDc6wlfsTOH0UhgT8FPxJu9NFPU/eYq3w3hPsvowg4MewjA4X8NBtqpus76Jyux2e8ym3WJHvlAff04VrwEeidaci591xbuu62ezTfACXtSOK5mOAgUWhCAHWE3/U32ibtsw5SER4u5ywk2nVGlvFY3+5x6RxoGN4FhsYwfumSHO54caonHyBVkkTK1FRbYJ6zNXMf37491YOrdqAFX7R205d4qcJkqLldo/DaYO10CSSiZ323x4=
TpOuQbtplQOuMXpTtxaAQJwZJtoVTMtWruV9d8+d6HJnSd7Y7iLMWkqerP3+rQBOqT67YAI8fq8ZZsYSDNKCoYQwJXqp8d2S8K2LyW7ClnYZXlFzVvjW0+wgTVV4E3f5Y7xT5TGlQ7/mO/KPgEloTxC8KD/DOTRc6MBusSgc/nd1ssE946qznCvihTsWuM4KGTfhQ4q9BVIVaxcFRszmhPqjVT0iY8sF3Aqghx4hvbgZKglqF9o/1JemzffLn/pxyclIePFJTPZlIzecfYcQ7Gsa+BpLbryRr6LUmuZLhBZYTnRP0dCrwMjfnitVSspwo0MJX4bDa1rQNPsQZLylrzNqbjA/aCf60qLit58KA2i7Vb/BfE3lPtoXKKILDEzOFqZObfRDDNQpiP8xCyJVXb5f3oVYYtRbuk/Ld1pNtsmTsEw69kQ30pW5Mqw+Qy5/6Nf75dAm1/9/FJga1uVBhlgPG0qgSf96M1s8FlSUrC5gn9neJB3ThOBpJkDRqvER192dwVlwcSbGLzgEGdZLFZq4cskfdsJHdWQ5aTcbnEBPrWRbvKbM1c2iuXXkLiKAAcY1rFmPWZscWbj8HqjFHwDd4bUjKzUA2GZt0LbhLG0ujQAK49Xdx7rHR15RL9hFFRwH4gUKQj/zuHCNkNXcW4bMmL1ZYWQXVW/X8Tv+LtQ=

View File

@@ -42,6 +42,7 @@ from uds.core.auths.auth import get_webpassword
from uds.core.managers.crypto import CryptoManager
from uds.core.managers.userservice import UserServiceManager
from uds.core.exceptions.services import (
InvalidServiceException,
MaxServicesReachedError,
ServiceAccessDeniedByCalendar,
ServiceNotReadyError,
@@ -466,6 +467,9 @@ def enable_service(
except ServiceAccessDeniedByCalendar:
logger.info('Access tried to a calendar limited access pool "%s"', service_id)
error = types.errors.Error.SERVICE_CALENDAR_DENIED.message
except InvalidServiceException as e:
logger.warning('Invalid service: %s', e)
error = types.errors.Error.INVALID_SERVICE.message
except Exception as e:
logger.exception('Error')
error = str(e)