mirror of
https://github.com/dkmstr/openuds.git
synced 2025-01-21 18:03:54 +03:00
Fixing up unmanaged hosts mesh
This commit is contained in:
parent
9e0266d26b
commit
c21652fe83
2
actor
2
actor
@ -1 +1 @@
|
||||
Subproject commit 18a1e4722dda938c545b2c67eddc87279627cacc
|
||||
Subproject commit 6b2f9df247fc24e57c5c6652c1616aca71b67a07
|
@ -194,138 +194,140 @@ class ActorInitializeTest(rest.test.RESTActorTestCase):
|
||||
"""
|
||||
Test actor initialize v3 for unmanaged actor
|
||||
"""
|
||||
user_service = self.user_service_unmanaged
|
||||
userservice = self.userservice_unmanaged
|
||||
actor_token: str = (
|
||||
user_service.deployed_service.service.token if user_service.deployed_service.service else None
|
||||
userservice.deployed_service.service.token if userservice.deployed_service.service else None
|
||||
) or ''
|
||||
|
||||
unique_id = user_service.get_unique_id()
|
||||
|
||||
if actor_token == '':
|
||||
self.fail('Service token not found')
|
||||
|
||||
success = functools.partial(self.invoke_success, 'unmanaged')
|
||||
failure = functools.partial(self.invoke_failure, 'unmanaged')
|
||||
|
||||
TEST_MAC: typing.Final[str] = '00:00:00:00:00:00'
|
||||
NONEXISTING_MAC: typing.Final[str] = '00:00:00:00:00:00'
|
||||
USERSERVICE_MAC: typing.Final[str] = userservice.get_unique_id()
|
||||
|
||||
# This will succeed, but only alias token is returned because MAC is not registered by UDS
|
||||
result = success(
|
||||
actor_token,
|
||||
mac=TEST_MAC,
|
||||
mac=NONEXISTING_MAC,
|
||||
)
|
||||
|
||||
# Unmanaged host is the response for initialization of unmanaged actor ALWAYS
|
||||
self.assertIsInstance(result['token'], str)
|
||||
self.assertEqual(result['token'], result['own_token'])
|
||||
self.assertIsInstance(result['master_token'], str)
|
||||
self.assertIsNone(result['unique_id'])
|
||||
self.assertIsNone(result['os'])
|
||||
self.assertIsNone(result['own_token'])
|
||||
self.assertIsNone(result['token'])
|
||||
|
||||
# Store alias token for later tests
|
||||
alias_token = result['token']
|
||||
alias_token = result['master_token']
|
||||
# Ensure that the alias returned is on alias db, and it points to the same service as the one we belong to
|
||||
alias = models.ServiceTokenAlias.objects.get(alias=alias_token)
|
||||
self.assertEqual(alias.service, userservice.deployed_service.service)
|
||||
self.assertEqual(alias.unique_id, NONEXISTING_MAC.lower())
|
||||
|
||||
# If repeated, same token is returned
|
||||
result = success(
|
||||
actor_token,
|
||||
mac=TEST_MAC,
|
||||
mac=NONEXISTING_MAC,
|
||||
)
|
||||
self.assertEqual(result['token'], alias_token)
|
||||
|
||||
# Now, invoke a "nice" initialize
|
||||
self.assertEqual(result['master_token'], alias_token)
|
||||
|
||||
# Now, invoke with a correct mac (Exists os user services)
|
||||
result = success(
|
||||
actor_token,
|
||||
mac=unique_id,
|
||||
mac=USERSERVICE_MAC,
|
||||
)
|
||||
|
||||
# Note that due the change of mac, a new alias is created
|
||||
alias_token = result['master_token']
|
||||
alias = models.ServiceTokenAlias.objects.get(alias=alias_token)
|
||||
self.assertEqual(alias.service, userservice.deployed_service.service)
|
||||
self.assertEqual(alias.unique_id, USERSERVICE_MAC.lower())
|
||||
|
||||
self.assertEqual(USERSERVICE_MAC, result['unique_id'])
|
||||
self.assertEqual(result['own_token'], result['token'])
|
||||
self.assertEqual(result['token'], userservice.uuid)
|
||||
|
||||
# Now, invoke with alias, result shouls be the same
|
||||
result2 = success(
|
||||
alias_token,
|
||||
mac=USERSERVICE_MAC,
|
||||
)
|
||||
|
||||
token = result['token']
|
||||
|
||||
self.assertIsInstance(token, str)
|
||||
self.assertEqual(token, user_service.uuid)
|
||||
self.assertEqual(token, result['own_token'])
|
||||
self.assertEqual(result['unique_id'], unique_id)
|
||||
|
||||
# Ensure that the alias returned is on alias db, and it points to the same service as the one we belong to
|
||||
alias = models.ServiceTokenAlias.objects.get(alias=alias_token)
|
||||
self.assertEqual(alias.service, user_service.deployed_service.service)
|
||||
|
||||
# Now, we should be able to "initialize" with valid mac and with original and alias tokens
|
||||
# If we call initialize and we get "own-token" means that we have already logged in with this data
|
||||
result = success(alias_token, mac=unique_id)
|
||||
|
||||
self.assertEqual(result['token'], user_service.uuid)
|
||||
self.assertEqual(result['token'], result['own_token'])
|
||||
self.assertEqual(result['unique_id'], unique_id)
|
||||
|
||||
# master_token should be the same as the alias token
|
||||
self.assertEqual(result, result2)
|
||||
#
|
||||
failure('invalid token', mac=unique_id, expect_forbidden=True)
|
||||
failure('invalid token', mac=USERSERVICE_MAC, expect_forbidden=True)
|
||||
|
||||
def test_initialize_unmanaged_by_ip(self) -> None:
|
||||
"""
|
||||
Test actor initialize v3 for unmanaged actor
|
||||
"""
|
||||
user_service = services_fixtures.create_db_one_assigned_userservice(
|
||||
userservice = services_fixtures.create_db_one_assigned_userservice(
|
||||
self.provider,
|
||||
self.admins[0],
|
||||
self.groups,
|
||||
'unmanaged',
|
||||
)
|
||||
# Set an IP as unique_id
|
||||
unique_id = '1.2.3.4'
|
||||
user_service.unique_id = unique_id
|
||||
user_service.save()
|
||||
USERSERVICE_IP: typing.Final[str] = '1.2.3.4'
|
||||
userservice.unique_id = USERSERVICE_IP
|
||||
userservice.save()
|
||||
|
||||
actor_token: str = (
|
||||
user_service.deployed_service.service.token if user_service.deployed_service.service else None
|
||||
userservice.deployed_service.service.token if userservice.deployed_service.service else None
|
||||
) or ''
|
||||
|
||||
success = functools.partial(self.invoke_success, 'unmanaged', mac='00:00:00:00:00:00')
|
||||
failure = functools.partial(self.invoke_failure, 'unmanaged', mac='00:00:00:00:00:00')
|
||||
|
||||
TEST_IP: typing.Final[str] = '00:00:00:00:00:00'
|
||||
NONEXISTING_IP: typing.Final[str] = '00:00:00:00:00:00'
|
||||
|
||||
# This will succeed, but only alias token is returned because MAC is not registered by UDS
|
||||
result = success(
|
||||
actor_token,
|
||||
ip=TEST_IP,
|
||||
ip=NONEXISTING_IP,
|
||||
)
|
||||
|
||||
# Unmanaged host is the response for initialization of unmanaged actor ALWAYS
|
||||
self.assertIsInstance(result['token'], str)
|
||||
self.assertEqual(result['token'], result['own_token'])
|
||||
self.assertIsInstance(result['master_token'], str)
|
||||
self.assertIsNone(result['unique_id'])
|
||||
self.assertIsNone(result['os'])
|
||||
self.assertIsNone(result['own_token'])
|
||||
self.assertIsNone(result['token'])
|
||||
|
||||
# Store alias token for later tests
|
||||
alias_token = result['token']
|
||||
|
||||
# If repeated, same token is returned
|
||||
result = success(
|
||||
actor_token,
|
||||
ip=TEST_IP,
|
||||
)
|
||||
self.assertEqual(result['token'], alias_token)
|
||||
|
||||
# Now, invoke a "nice" initialize
|
||||
result = success(
|
||||
actor_token,
|
||||
ip=unique_id,
|
||||
)
|
||||
|
||||
token = result['token']
|
||||
|
||||
self.assertIsInstance(token, str)
|
||||
self.assertEqual(token, user_service.uuid)
|
||||
self.assertEqual(token, result['own_token'])
|
||||
self.assertEqual(result['unique_id'], unique_id)
|
||||
|
||||
alias_token = result['master_token']
|
||||
# Ensure that the alias returned is on alias db, and it points to the same service as the one we belong to
|
||||
alias = models.ServiceTokenAlias.objects.get(alias=alias_token)
|
||||
self.assertEqual(alias.service, user_service.deployed_service.service)
|
||||
self.assertEqual(alias.service, userservice.deployed_service.service)
|
||||
self.assertEqual(alias.unique_id, NONEXISTING_IP.lower())
|
||||
|
||||
# Now, we should be able to "initialize" with valid mac and with original and alias tokens
|
||||
# If we call initialize and we get "own-token" means that we have already logged in with this data
|
||||
result = success(alias_token, ip=unique_id)
|
||||
# Now, invoke with a correct mac (Exists os user services)
|
||||
result = success(
|
||||
actor_token,
|
||||
mac=USERSERVICE_IP,
|
||||
)
|
||||
|
||||
# Note that due the change of mac, a new alias is created
|
||||
alias_token = result['master_token']
|
||||
alias = models.ServiceTokenAlias.objects.get(alias=alias_token)
|
||||
self.assertEqual(alias.service, userservice.deployed_service.service)
|
||||
self.assertEqual(alias.unique_id, USERSERVICE_IP.lower())
|
||||
|
||||
self.assertEqual(USERSERVICE_IP, result['unique_id'])
|
||||
self.assertEqual(result['own_token'], result['token'])
|
||||
self.assertEqual(result['token'], userservice.uuid)
|
||||
|
||||
self.assertEqual(result['token'], user_service.uuid)
|
||||
self.assertEqual(result['token'], result['own_token'])
|
||||
self.assertEqual(result['unique_id'], unique_id)
|
||||
# Now, invoke with alias, result shouls be the same
|
||||
result2 = success(
|
||||
alias_token,
|
||||
mac=USERSERVICE_IP,
|
||||
)
|
||||
|
||||
# master_token should be the same as the alias token
|
||||
self.assertEqual(result, result2)
|
||||
#
|
||||
failure('invalid token', ip=unique_id, expect_forbidden=True)
|
||||
failure('invalid token', mac=USERSERVICE_IP, expect_forbidden=True)
|
||||
|
149
server/src/tests/REST/actor/test_unmanaged.py
Normal file
149
server/src/tests/REST/actor/test_unmanaged.py
Normal file
@ -0,0 +1,149 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2022 Virtual Cable S.L.U.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * 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.U. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
Author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
import typing
|
||||
import logging
|
||||
|
||||
|
||||
from uds import models
|
||||
from uds.core.managers.crypto import CryptoManager
|
||||
from ...utils import rest
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ActorUnmanagedTest(rest.test.RESTActorTestCase):
|
||||
"""
|
||||
Test actor functionality
|
||||
"""
|
||||
|
||||
def invoke_success(
|
||||
self,
|
||||
token: str,
|
||||
*,
|
||||
mac: typing.Optional[str] = None,
|
||||
ip: typing.Optional[str] = None,
|
||||
) -> dict[str, typing.Any]:
|
||||
response = self.client.post(
|
||||
'/uds/rest/actor/v3/unmanaged',
|
||||
data={
|
||||
'id': [{'mac': mac or '42:AC:11:22:33', 'ip': ip or '1.2.3.4'}],
|
||||
'token': token,
|
||||
'seecret': 'test_secret',
|
||||
'port': 1234,
|
||||
},
|
||||
content_type='application/json',
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data = response.json()
|
||||
self.assertIsInstance(data['result'], dict)
|
||||
return data['result']
|
||||
|
||||
def invoke_failure(
|
||||
self,
|
||||
token: str,
|
||||
*,
|
||||
mac: typing.Optional[str] = None,
|
||||
ip: typing.Optional[str] = None,
|
||||
expect_forbidden: bool = False,
|
||||
) -> dict[str, typing.Any]:
|
||||
response = self.client.post(
|
||||
'/uds/rest/actor/v3/unmanaged',
|
||||
data={
|
||||
'id': [{'mac': mac or '42:AC:11:22:33', 'ip': ip or '1.2.3.4'}],
|
||||
'token': token,
|
||||
'seecret': 'test_secret',
|
||||
'port': 1234,
|
||||
},
|
||||
content_type='application/json',
|
||||
)
|
||||
self.assertEqual(response.status_code, 200 if not expect_forbidden else 403)
|
||||
if expect_forbidden:
|
||||
return {}
|
||||
|
||||
data = response.json()
|
||||
self.assertIsInstance(data['result'], dict)
|
||||
return data['result']
|
||||
|
||||
def test_unmanaged(self) -> None:
|
||||
"""
|
||||
Test actor initialize v3 for unmanaged actor
|
||||
"""
|
||||
userservice = self.userservice_unmanaged
|
||||
actor_token: str = (
|
||||
userservice.deployed_service.service.token if userservice.deployed_service.service else None
|
||||
) or ''
|
||||
|
||||
if actor_token == '':
|
||||
self.fail('Service token not found')
|
||||
|
||||
TEST_MAC: typing.Final[str] = '00:00:00:00:00:00'
|
||||
|
||||
# This will succeed, but only alias token is returned because MAC is not registered by UDS
|
||||
result = self.invoke_success(
|
||||
actor_token,
|
||||
mac=TEST_MAC,
|
||||
)
|
||||
|
||||
# 'private_key': key, # To be removed on 5.0
|
||||
# 'key': key,
|
||||
# 'server_certificate': certificate, # To be removed on 5.0
|
||||
# 'certificate': certificate,
|
||||
# 'password': password,
|
||||
# 'ciphers': getattr(settings, 'SECURE_CIPHERS', ''),
|
||||
|
||||
self.assertIn('private_key', result)
|
||||
self.assertIn('key', result)
|
||||
self.assertIn('server_certificate', result)
|
||||
self.assertIn('certificate', result)
|
||||
self.assertIn('password', result)
|
||||
self.assertIn('ciphers', result)
|
||||
|
||||
# Create a token_alias assiciated with the service
|
||||
token_alias = CryptoManager.manager().random_string(40)
|
||||
models.ServiceTokenAlias.objects.create(
|
||||
alias=token_alias,
|
||||
unique_id=TEST_MAC,
|
||||
service=userservice.service_pool.service,
|
||||
)
|
||||
|
||||
result2 = self.invoke_success(
|
||||
actor_token,
|
||||
mac=TEST_MAC,
|
||||
)
|
||||
|
||||
# Keys showld be different
|
||||
self.assertIn('private_key', result2)
|
||||
self.assertIn('key', result2)
|
||||
self.assertIn('server_certificate', result2)
|
||||
self.assertIn('certificate', result2)
|
||||
self.assertIn('password', result2)
|
||||
self.assertEqual(result['ciphers'], result2['ciphers'])
|
@ -69,7 +69,7 @@ class SystemTest(rest.test.RESTTestCase):
|
||||
def test_chart_pool(self) -> None:
|
||||
# First, create fixtures for the pool
|
||||
DAYS = 30
|
||||
for pool in [self.user_service_managed, self.user_service_unmanaged]:
|
||||
for pool in [self.user_service_managed, self.userservice_unmanaged]:
|
||||
stats_counters.create_stats_interval_total(
|
||||
id=pool.deployed_service.id,
|
||||
counter_type=[counters.types.stats.CounterType.ASSIGNED, counters.types.stats.CounterType.INUSE, counters.types.stats.CounterType.CACHED],
|
||||
|
@ -86,7 +86,7 @@ class TestProxmoxHelpers(UDSTransactionTestCase):
|
||||
self.assertGreaterEqual(len(choices), 1)
|
||||
for choice in choices:
|
||||
self.assertIsInstance(choice, dict)
|
||||
self.assertIsInstance(choice['id'], int)
|
||||
self.assertIsInstance(choice['id'], str)
|
||||
self.assertIsInstance(choice['text'], str)
|
||||
|
||||
api.get_pool_info.assert_called_once()
|
||||
|
@ -55,7 +55,7 @@ class RESTTestCase(test.UDSTransactionTestCase):
|
||||
|
||||
provider: models.Provider
|
||||
user_service_managed: models.UserService
|
||||
user_service_unmanaged: models.UserService
|
||||
userservice_unmanaged: models.UserService
|
||||
|
||||
user_services: list[models.UserService]
|
||||
|
||||
@ -98,7 +98,7 @@ class RESTTestCase(test.UDSTransactionTestCase):
|
||||
self.groups,
|
||||
'managed',
|
||||
)
|
||||
self.user_service_unmanaged = services_fixtures.create_db_one_assigned_userservice(
|
||||
self.userservice_unmanaged = services_fixtures.create_db_one_assigned_userservice(
|
||||
self.provider,
|
||||
self.admins[0],
|
||||
self.groups,
|
||||
|
@ -397,15 +397,16 @@ class Initialize(ActorV3Action):
|
||||
alias_token: typing.Optional[str] = None
|
||||
|
||||
def _initialization_result(
|
||||
own_token: typing.Optional[str],
|
||||
token: typing.Optional[str],
|
||||
unique_id: typing.Optional[str],
|
||||
os: typing.Any,
|
||||
alias_token: typing.Optional[str],
|
||||
master_token: typing.Optional[str],
|
||||
) -> dict[str, typing.Any]:
|
||||
return ActorV3Action.actor_result(
|
||||
{
|
||||
'own_token': own_token or alias_token, # Compat with old actor versions, TBR on 5.0
|
||||
'token': own_token or alias_token, # New token, will be used from now onwards
|
||||
'own_token': token, # Compat with old actor versions, TBR on 5.0
|
||||
'token': token, # New token, will be used from now onwards
|
||||
'master_token': master_token, # Master token, to replace on unmanaged machines
|
||||
'unique_id': unique_id,
|
||||
'os': os,
|
||||
}
|
||||
@ -413,6 +414,8 @@ class Initialize(ActorV3Action):
|
||||
|
||||
try:
|
||||
token = self._params['token']
|
||||
list_of_ids = get_list_of_ids(self)
|
||||
|
||||
# First, try to locate an user service providing this token.
|
||||
if self._params['type'] == consts.actor.UNMANAGED:
|
||||
# First, try to locate on alias table
|
||||
@ -427,7 +430,7 @@ class Initialize(ActorV3Action):
|
||||
service = Service.objects.get(token=token)
|
||||
# If exists, create and alias for it
|
||||
# Get first mac and, if not exists, get first ip
|
||||
unique_id = self._params['id'][0].get('mac', self._params['id'][0].get('ip', ''))
|
||||
unique_id = self._params['id'][0].get('mac', self._params['id'][0].get('ip', '')).lower()
|
||||
if unique_id is None:
|
||||
raise exceptions.rest.BlockAccess()
|
||||
# If exists, do not create a new one (avoid creating for old 3.x actors lots of aliases...)
|
||||
@ -440,20 +443,17 @@ class Initialize(ActorV3Action):
|
||||
|
||||
# Locate an userService that belongs to this service and which
|
||||
# Build the possible ids and make initial filter to match service
|
||||
list_of_ids = get_list_of_ids(self)
|
||||
dbfilter = UserService.objects.filter(deployed_service__service=service)
|
||||
else:
|
||||
# If not service provided token, use actor tokens
|
||||
if not Server.validate_token(token, server_type=types.servers.ServerType.ACTOR):
|
||||
raise exceptions.rest.BlockAccess()
|
||||
# Build the possible ids and make initial filter to match ANY userservice with provided MAC
|
||||
list_of_ids = [i['mac'] for i in self._params['id'][:5]]
|
||||
dbfilter = UserService.objects.all()
|
||||
|
||||
# Valid actor token, now validate access allowed. That is, look for a valid mac from the ones provided.
|
||||
try:
|
||||
# ensure idsLists has upper and lower versions for case sensitive databases
|
||||
list_of_ids = get_list_of_ids(self)
|
||||
# Set full filter
|
||||
dbfilter = dbfilter.filter(
|
||||
unique_id__in=list_of_ids,
|
||||
@ -462,7 +462,7 @@ class Initialize(ActorV3Action):
|
||||
|
||||
userservice: UserService = next(iter(dbfilter))
|
||||
except Exception as e:
|
||||
logger.info('Unmanaged host request: %s, %s', self._params, e)
|
||||
logger.info('Not managed host request: %s, %s', self._params, e)
|
||||
return _initialization_result(None, None, None, alias_token)
|
||||
|
||||
# Managed by UDS, get initialization data from osmanager and return it
|
||||
@ -479,11 +479,6 @@ class Initialize(ActorV3Action):
|
||||
if osmanager:
|
||||
os_data = osmanager.actor_data(userservice)
|
||||
|
||||
if service and not alias_token: # is an UNMANAGED without already an alias?
|
||||
# Create a new alias for it, and save
|
||||
alias_token = CryptoManager().random_string(40) # fix alias with new token
|
||||
service.aliases.create(alias=alias_token)
|
||||
|
||||
return _initialization_result(userservice.uuid, userservice.unique_id, os_data, alias_token)
|
||||
except Service.DoesNotExist:
|
||||
raise exceptions.rest.BlockAccess() from None
|
||||
@ -775,7 +770,7 @@ class Unmanaged(ActorV3Action):
|
||||
unmanaged method expect a json POST with this fields:
|
||||
* id: List[dict] -> List of dictionary containing ip and mac:
|
||||
* token: str -> Valid Actor "master_token" (if invalid, will return an error).
|
||||
* secret: Secret for commsUrl for actor (Cu
|
||||
* secret: Secret for commsUrl for actor
|
||||
* port: port of the listener (normally 43910)
|
||||
|
||||
This method will also regenerater the public-private key pair for client, that will be needed for the new ip
|
||||
@ -788,31 +783,28 @@ class Unmanaged(ActorV3Action):
|
||||
logger.debug('Args: %s, Params: %s', self._args, self._params)
|
||||
|
||||
try:
|
||||
dbService: Service = Service.objects.get(token=self._params['token'])
|
||||
service: 'services.Service' = dbService.get_instance()
|
||||
token = self._params['token']
|
||||
if ServiceTokenAlias.objects.filter(alias=token).exists():
|
||||
# Retrieve real service from token alias
|
||||
dbservice = ServiceTokenAlias.objects.get(alias=token).service
|
||||
else:
|
||||
dbservice: Service = Service.objects.get(token=token)
|
||||
service: 'services.Service' = dbservice.get_instance()
|
||||
except Exception:
|
||||
logger.exception('Unmanaged host request: %s', self._params)
|
||||
return ActorV3Action.actor_result(error='Invalid token')
|
||||
|
||||
# Build the possible ids and ask service if it recognizes any of it
|
||||
# If not recognized, will generate anyway the certificate, but will not be saved
|
||||
list_of_ids = [x['ip'] for x in self._params['id']] + [x['mac'] for x in self._params['id']][:10]
|
||||
valid_id: typing.Optional[str] = service.get_valid_id(list_of_ids)
|
||||
|
||||
# ensure idsLists has upper and lower versions for case sensitive databases
|
||||
list_of_ids = get_list_of_ids(self)
|
||||
valid_id: typing.Optional[str] = service.get_valid_id(list_of_ids)
|
||||
|
||||
# Check if there is already an assigned user service
|
||||
# To notify it logout
|
||||
userservice: typing.Optional[UserService]
|
||||
try:
|
||||
db_filter = UserService.objects.filter(
|
||||
unique_id__in=list_of_ids,
|
||||
state__in=[State.USABLE, State.PREPARING],
|
||||
)
|
||||
|
||||
userservice = next(
|
||||
iter(
|
||||
db_filter.filter(
|
||||
UserService.objects.filter(
|
||||
unique_id__in=list_of_ids,
|
||||
state__in=[State.USABLE, State.PREPARING],
|
||||
)
|
||||
@ -824,7 +816,7 @@ class Unmanaged(ActorV3Action):
|
||||
# Try to infer the ip from the valid id (that could be an IP or a MAC)
|
||||
ip: str
|
||||
try:
|
||||
ip = next(x['ip'] for x in self._params['id'] if valid_id in (x['ip'], x['mac']))
|
||||
ip = next(x['ip'] for x in self._params['id'] if valid_id and valid_id.lower() in (x['ip'].lower(), x['mac'].lower()))
|
||||
except StopIteration:
|
||||
ip = self._params['id'][0]['ip'] # Get first IP if no valid ip found
|
||||
|
||||
@ -839,7 +831,7 @@ class Unmanaged(ActorV3Action):
|
||||
# If it is not assgined to an user service, notify service
|
||||
service.notify_initialization(valid_id)
|
||||
|
||||
# Store certificate, secret & port with service if validId
|
||||
# Store certificate, secret & port with service if service recognized the id
|
||||
service.store_id_info(
|
||||
valid_id,
|
||||
{
|
||||
|
@ -121,7 +121,7 @@ CallbackResultType = list[CallbackResultItem]
|
||||
|
||||
|
||||
class Filler(typing.TypedDict):
|
||||
callback_name: str
|
||||
callback_name: typing.NotRequired[str]
|
||||
parameters: list[str]
|
||||
function: typing.NotRequired[collections.abc.Callable[..., CallbackResultType]]
|
||||
|
||||
|
@ -51,7 +51,7 @@ from django.utils.functional import Promise # To recognize lazy translations
|
||||
|
||||
from uds.core import consts, exceptions, types
|
||||
from uds.core.managers.crypto import UDSK, CryptoManager
|
||||
from uds.core.util import serializer, validators, ensure
|
||||
from uds.core.util import modfinder, serializer, validators, ensure
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -1121,8 +1121,9 @@ class gui:
|
||||
self._field_info.choices = gui.as_choices(choices)
|
||||
# if has fillers, set them
|
||||
if fills:
|
||||
if 'function' not in fills or 'callback_name' not in fills:
|
||||
if 'function' not in fills:
|
||||
raise ValueError('Invalid fills parameters')
|
||||
fills['callback_name'] = fills.get('callback_name', modfinder.callable_path(fills['function']))
|
||||
fnc = fills['function']
|
||||
fills.pop('function')
|
||||
self._field_info.fills = fills
|
||||
|
@ -199,3 +199,8 @@ def dynamically_load_and_register_modules(
|
||||
module_name,
|
||||
checker=_checker,
|
||||
)
|
||||
|
||||
|
||||
# Given a callable, return the full path to it as a string
|
||||
def callable_path(callable_: collections.abc.Callable[..., typing.Any]) -> str:
|
||||
return f'{callable_.__module__}.{callable_.__name__}'
|
||||
|
@ -51,7 +51,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UserServiceInfoItemsCleaner(Job):
|
||||
frecuency = 3600 # Constant time, every hour will check for old info items
|
||||
frecuency = 600 # Constant time, every hour will check for old info items
|
||||
# frecuency_cfg = (
|
||||
# GlobalConfig.KEEP_INFO_TIME
|
||||
# ) # Request run cache "info" cleaner every configured seconds. If config value is changed, it will be used at next reload
|
||||
|
Loading…
x
Reference in New Issue
Block a user