mirror of
https://github.com/dkmstr/openuds.git
synced 2024-12-22 13:34:04 +03:00
more refactoring and fixes and tests...
This commit is contained in:
parent
d21f66408f
commit
9dbb47a4ad
2
actor
2
actor
@ -1 +1 @@
|
||||
Subproject commit 0489009e08acfd59ec9936ab33457cb32151e11f
|
||||
Subproject commit a7a2ff7cf60b5063a8b717a197ff25da2c130feb
|
@ -74,7 +74,7 @@ class NotifyActionType(enum.StrEnum):
|
||||
|
||||
|
||||
# Helpers
|
||||
def fixIdsList(idsList: list[str]) -> list[str]:
|
||||
def fix_list_of_ids(idsList: list[str]) -> list[str]:
|
||||
"""
|
||||
Params:
|
||||
idsList: List of ids to fix
|
||||
@ -151,7 +151,7 @@ class ActorV3Action(Handler):
|
||||
}
|
||||
)
|
||||
|
||||
def getUserService(self) -> UserService:
|
||||
def get_userservice(self) -> UserService:
|
||||
'''
|
||||
Looks for an userService and, if not found, raises a exceptions.rest.BlockAccess request
|
||||
'''
|
||||
@ -179,7 +179,7 @@ class ActorV3Action(Handler):
|
||||
raise exceptions.rest.AccessDenied('Access denied')
|
||||
|
||||
# Some helpers
|
||||
def notifyService(self, action: NotifyActionType) -> None:
|
||||
def notify_service(self, action: NotifyActionType) -> None:
|
||||
try:
|
||||
# If unmanaged, use Service locator
|
||||
service: 'services.Service' = Service.objects.get(token=self._params['token']).get_instance()
|
||||
@ -190,7 +190,7 @@ class ActorV3Action(Handler):
|
||||
idsList = [x['ip'] for x in self._params['id']] + [x['mac'] for x in self._params['id']][:10]
|
||||
|
||||
# ensure idsLists has upper and lower versions for case sensitive databases
|
||||
idsList = fixIdsList(idsList)
|
||||
idsList = fix_list_of_ids(idsList)
|
||||
|
||||
validId: typing.Optional[str] = service.get_valid_id(idsList)
|
||||
|
||||
@ -430,7 +430,7 @@ class Initialize(ActorV3Action):
|
||||
# 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
|
||||
idsList = fixIdsList(idsList)
|
||||
idsList = fix_list_of_ids(idsList)
|
||||
# Set full filter
|
||||
dbFilter = dbFilter.filter(
|
||||
unique_id__in=idsList,
|
||||
@ -446,7 +446,7 @@ class Initialize(ActorV3Action):
|
||||
# Set last seen actor version
|
||||
userService.actor_version = self._params['version']
|
||||
osData: collections.abc.MutableMapping[str, typing.Any] = {}
|
||||
osManager = userService.getOsManagerInstance()
|
||||
osManager = userService.get_osmanager_instance()
|
||||
if osManager:
|
||||
osData = osManager.actor_data(userService)
|
||||
|
||||
@ -484,7 +484,7 @@ class BaseReadyChange(ActorV3Action):
|
||||
}
|
||||
"""
|
||||
logger.debug('Args: %s, Params: %s', self._args, self._params)
|
||||
userService = self.getUserService()
|
||||
userService = self.get_userservice()
|
||||
# Stores known IP and notifies it to deployment
|
||||
userService.log_ip(self._params['ip'])
|
||||
userServiceInstance = userService.get_instance()
|
||||
@ -502,7 +502,7 @@ class BaseReadyChange(ActorV3Action):
|
||||
if userService.os_state != State.USABLE:
|
||||
userService.setOsState(State.USABLE)
|
||||
# Notify osManager or readyness if has os manager
|
||||
osManager = userService.getOsManagerInstance()
|
||||
osManager = userService.get_osmanager_instance()
|
||||
|
||||
if osManager:
|
||||
osManager.to_ready(userService)
|
||||
@ -550,7 +550,7 @@ class Ready(BaseReadyChange):
|
||||
result = super().action()
|
||||
|
||||
# Maybe we could also set as "inUse" to false because a ready can only ocurr if an user is not logged in
|
||||
userService = self.getUserService()
|
||||
userService = self.get_userservice()
|
||||
userService.setInUse(False)
|
||||
|
||||
return result
|
||||
@ -566,7 +566,7 @@ class Version(ActorV3Action):
|
||||
|
||||
def action(self) -> dict[str, typing.Any]:
|
||||
logger.debug('Version Args: %s, Params: %s', self._args, self._params)
|
||||
userService = self.getUserService()
|
||||
userService = self.get_userservice()
|
||||
userService.actor_version = self._params['version']
|
||||
userService.log_ip(self._params['ip'])
|
||||
|
||||
@ -589,52 +589,53 @@ class Login(ActorV3Action):
|
||||
# }
|
||||
|
||||
@staticmethod
|
||||
def process_login(userService: UserService, username: str) -> typing.Optional[osmanagers.OSManager]:
|
||||
osManager: typing.Optional[osmanagers.OSManager] = userService.getOsManagerInstance()
|
||||
if not userService.in_use: # If already logged in, do not add a second login (windows does this i.e.)
|
||||
osmanagers.OSManager.logged_in(userService, username)
|
||||
def process_login(userservice: UserService, username: str) -> typing.Optional[osmanagers.OSManager]:
|
||||
osManager: typing.Optional[osmanagers.OSManager] = userservice.get_osmanager_instance()
|
||||
if not userservice.in_use: # If already logged in, do not add a second login (windows does this i.e.)
|
||||
osmanagers.OSManager.logged_in(userservice, username)
|
||||
return osManager
|
||||
|
||||
def action(self) -> dict[str, typing.Any]:
|
||||
isManaged = self._params.get('type') != consts.actor.UNMANAGED
|
||||
src = types.connections.ConnectionSource('', '')
|
||||
deadLine = maxIdle = None
|
||||
deadline = max_idle = None
|
||||
session_id = ''
|
||||
|
||||
logger.debug('Login Args: %s, Params: %s', self._args, self._params)
|
||||
|
||||
try:
|
||||
userService: UserService = self.getUserService()
|
||||
osManager = Login.process_login(userService, self._params.get('username') or '')
|
||||
userservice: UserService = self.get_userservice()
|
||||
os_manager = Login.process_login(userservice, self._params.get('username') or '')
|
||||
|
||||
maxIdle = osManager.max_idle() if osManager else None
|
||||
max_idle = os_manager.max_idle() if os_manager else None
|
||||
|
||||
logger.debug('Max idle: %s', maxIdle)
|
||||
logger.debug('Max idle: %s', max_idle)
|
||||
|
||||
src = userService.getConnectionSource()
|
||||
session_id = userService.start_session() # creates a session for every login requested
|
||||
src = userservice.getConnectionSource()
|
||||
session_id = userservice.start_session() # creates a session for every login requested
|
||||
|
||||
if osManager: # For os managed services, let's check if we honor deadline
|
||||
if osManager.ignore_deadline():
|
||||
deadLine = userService.deployed_service.get_deadline()
|
||||
if os_manager: # For os managed services, let's check if we honor deadline
|
||||
if os_manager.ignore_deadline():
|
||||
deadline = userservice.deployed_service.get_deadline()
|
||||
else:
|
||||
deadLine = None
|
||||
deadline = None
|
||||
else: # For non os manager machines, process deadline as always
|
||||
deadLine = userService.deployed_service.get_deadline()
|
||||
deadline = userservice.deployed_service.get_deadline()
|
||||
|
||||
except (
|
||||
Exception
|
||||
): # If unamanaged host, lest do a bit more work looking for a service with the provided parameters...
|
||||
if isManaged:
|
||||
raise
|
||||
self.notifyService(action=NotifyActionType.LOGIN)
|
||||
self.notify_service(action=NotifyActionType.LOGIN)
|
||||
|
||||
return ActorV3Action.actor_result(
|
||||
{
|
||||
'ip': src.ip,
|
||||
'hostname': src.hostname,
|
||||
'dead_line': deadLine,
|
||||
'max_idle': maxIdle,
|
||||
'dead_line': deadline, # Kept for compat, will be removed on 5.x
|
||||
'deadline': deadline,
|
||||
'max_idle': max_idle,
|
||||
'session_id': session_id,
|
||||
}
|
||||
)
|
||||
@ -648,41 +649,41 @@ class Logout(ActorV3Action):
|
||||
name = 'logout'
|
||||
|
||||
@staticmethod
|
||||
def process_logout(userService: UserService, username: str, session_id: str) -> None:
|
||||
def process_logout(userservice: UserService, username: str, session_id: str) -> None:
|
||||
"""
|
||||
This method is static so can be invoked from elsewhere
|
||||
"""
|
||||
osManager: typing.Optional[osmanagers.OSManager] = userService.getOsManagerInstance()
|
||||
osManager: typing.Optional[osmanagers.OSManager] = userservice.get_osmanager_instance()
|
||||
|
||||
# Close session
|
||||
# For compat, we have taken '' as "all sessions"
|
||||
userService.end_session(session_id)
|
||||
userservice.end_session(session_id)
|
||||
|
||||
if userService.in_use: # If already logged out, do not add a second logout (windows does this i.e.)
|
||||
osmanagers.OSManager.logged_out(userService, username)
|
||||
if userservice.in_use: # If already logged out, do not add a second logout (windows does this i.e.)
|
||||
osmanagers.OSManager.logged_out(userservice, username)
|
||||
if osManager:
|
||||
if osManager.is_removable_on_logout(userService):
|
||||
if osManager.is_removable_on_logout(userservice):
|
||||
logger.debug('Removable on logout: %s', osManager)
|
||||
userService.remove()
|
||||
userservice.remove()
|
||||
else:
|
||||
userService.remove()
|
||||
userservice.remove()
|
||||
|
||||
def action(self) -> dict[str, typing.Any]:
|
||||
isManaged = self._params.get('type') != consts.actor.UNMANAGED
|
||||
is_managed = self._params.get('type') != consts.actor.UNMANAGED
|
||||
|
||||
logger.debug('Args: %s, Params: %s', self._args, self._params)
|
||||
try:
|
||||
userService: UserService = self.getUserService() # if not exists, will raise an error
|
||||
userservice: UserService = self.get_userservice() # if not exists, will raise an error
|
||||
Logout.process_logout(
|
||||
userService,
|
||||
userservice,
|
||||
self._params.get('username') or '',
|
||||
self._params.get('session_id') or '',
|
||||
)
|
||||
# If unamanaged host, lets do a bit more work looking for a service with the provided parameters...
|
||||
except Exception:
|
||||
if isManaged:
|
||||
if is_managed:
|
||||
raise
|
||||
self.notifyService(NotifyActionType.LOGOUT) # Logout notification
|
||||
self.notify_service(NotifyActionType.LOGOUT) # Logout notification
|
||||
# Result is that we have not processed the logout in fact, but notified the service
|
||||
return ActorV3Action.actor_result('notified')
|
||||
|
||||
@ -698,14 +699,14 @@ class Log(ActorV3Action):
|
||||
|
||||
def action(self) -> dict[str, typing.Any]:
|
||||
logger.debug('Args: %s, Params: %s', self._args, self._params)
|
||||
userService = self.getUserService()
|
||||
if userService.actor_version < '4.0.0':
|
||||
userservice = self.get_userservice()
|
||||
if userservice.actor_version < '4.0.0':
|
||||
# Adjust loglevel to own, we start on 10000 for OTHER, and received is 0 for OTHER
|
||||
level = log.LogLevel.from_int(int(self._params['level']) + 10000)
|
||||
else:
|
||||
level = log.LogLevel.from_int(int(self._params['level']))
|
||||
log.log(
|
||||
userService,
|
||||
userservice,
|
||||
level,
|
||||
self._params['message'],
|
||||
log.LogSource.ACTOR,
|
||||
@ -766,53 +767,53 @@ class Unmanaged(ActorV3Action):
|
||||
|
||||
# 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
|
||||
idsList = [x['ip'] for x in self._params['id']] + [x['mac'] for x in self._params['id']][:10]
|
||||
validId: typing.Optional[str] = service.get_valid_id(idsList)
|
||||
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
|
||||
idsList = fixIdsList(idsList)
|
||||
list_of_ids = fix_list_of_ids(list_of_ids)
|
||||
|
||||
# Check if there is already an assigned user service
|
||||
# To notify it logout
|
||||
userService: typing.Optional[UserService]
|
||||
userservice: typing.Optional[UserService]
|
||||
try:
|
||||
dbFilter = UserService.objects.filter(
|
||||
unique_id__in=idsList,
|
||||
db_filter = UserService.objects.filter(
|
||||
unique_id__in=list_of_ids,
|
||||
state__in=[State.USABLE, State.PREPARING],
|
||||
)
|
||||
|
||||
userService = next(
|
||||
userservice = next(
|
||||
iter(
|
||||
dbFilter.filter(
|
||||
unique_id__in=idsList,
|
||||
db_filter.filter(
|
||||
unique_id__in=list_of_ids,
|
||||
state__in=[State.USABLE, State.PREPARING],
|
||||
)
|
||||
)
|
||||
)
|
||||
except StopIteration:
|
||||
userService = None
|
||||
userservice = None
|
||||
|
||||
# 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 validId in (x['ip'], x['mac']))
|
||||
ip = next(x['ip'] for x in self._params['id'] if valid_id in (x['ip'], x['mac']))
|
||||
except StopIteration:
|
||||
ip = self._params['id'][0]['ip'] # Get first IP if no valid ip found
|
||||
|
||||
# Generates a certificate and send it to client (actor).
|
||||
privateKey, certificate, password = security.create_self_signed_cert(ip)
|
||||
private_key, certificate, password = security.create_self_signed_cert(ip)
|
||||
|
||||
if validId:
|
||||
if valid_id:
|
||||
# If id is assigned to an user service, notify "logout" to it
|
||||
if userService:
|
||||
Logout.process_logout(userService, 'init', '')
|
||||
if userservice:
|
||||
Logout.process_logout(userservice, 'init', '')
|
||||
else:
|
||||
# If it is not assgined to an user service, notify service
|
||||
service.notify_initialization(validId)
|
||||
service.notify_initialization(valid_id)
|
||||
|
||||
# Store certificate, secret & port with service if validId
|
||||
service.store_id_info(
|
||||
validId,
|
||||
valid_id,
|
||||
{
|
||||
'cert': certificate,
|
||||
'secret': self._params['secret'],
|
||||
@ -820,7 +821,7 @@ class Unmanaged(ActorV3Action):
|
||||
},
|
||||
)
|
||||
|
||||
return ActorV3Action.actorCertResult(privateKey, certificate, password)
|
||||
return ActorV3Action.actorCertResult(private_key, certificate, password)
|
||||
|
||||
|
||||
class Notify(ActorV3Action):
|
||||
@ -847,7 +848,7 @@ class Notify(ActorV3Action):
|
||||
elif action == NotifyActionType.LOGOUT:
|
||||
Logout.action(typing.cast(Logout, self))
|
||||
elif action == NotifyActionType.DATA:
|
||||
self.notifyService(action)
|
||||
self.notify_service(action)
|
||||
|
||||
return ActorV3Action.actor_result('ok')
|
||||
except UserService.DoesNotExist:
|
||||
|
@ -347,7 +347,7 @@ class BaseModelHandler(Handler):
|
||||
if isinstance(item, ManagedObjectModel):
|
||||
i = item.get_instance()
|
||||
i.init_gui() # Defaults & stuff
|
||||
res.update(i.get_dict_of_values())
|
||||
res.update(i.get_dict_of_fields_values())
|
||||
return res
|
||||
|
||||
# Exceptions
|
||||
|
@ -276,7 +276,7 @@ class RegexLdap(auths.Authenticator):
|
||||
def mfa_identifier(self, username: str) -> str:
|
||||
return self.storage.get_unpickle(self.mfaStorageKey(username)) or ''
|
||||
|
||||
def get_dict_of_values(self) -> gui.ValuesDictType:
|
||||
def get_dict_of_fields_values(self) -> gui.ValuesDictType:
|
||||
return {
|
||||
'host': self._host,
|
||||
'port': self._port,
|
||||
|
@ -241,7 +241,7 @@ class SimpleLDAPAuthenticator(auths.Authenticator):
|
||||
self._verifySsl = gui.as_bool(values['verifySsl'])
|
||||
self._certificate = values['certificate']
|
||||
|
||||
def get_dict_of_values(self) -> gui.ValuesDictType:
|
||||
def get_dict_of_fields_values(self) -> gui.ValuesDictType:
|
||||
return {
|
||||
'host': self._host,
|
||||
'port': self._port,
|
||||
|
@ -75,7 +75,7 @@ def process_login(server: 'models.Server', data: dict[str, typing.Any]) -> typin
|
||||
{
|
||||
'ip': 'ip of connection origin',
|
||||
'hostname': 'hostname of connection origin',
|
||||
'dead_line': 'dead line of service', # The point in time when the service will be automatically removed, optional (None if not set)
|
||||
'deadline': 'dead line of service', # The point in time when the service will be automatically removed, optional (None if not set)
|
||||
'max_idle': 'max idle time of service', # The max time the service can be idle before being removed, optional (None if not set)
|
||||
'session_id': 'session id', # The session id assigned to this login
|
||||
'ticket': 'ticket if any' # optional
|
||||
@ -99,7 +99,7 @@ def process_login(server: 'models.Server', data: dict[str, typing.Any]) -> typin
|
||||
src = userService.getConnectionSource()
|
||||
session_id = userService.start_session() # creates a session for every login requested
|
||||
|
||||
osManager: typing.Optional[osmanagers.OSManager] = userService.getOsManagerInstance()
|
||||
osManager: typing.Optional[osmanagers.OSManager] = userService.get_osmanager_instance()
|
||||
maxIdle = osManager.max_idle() if osManager else None
|
||||
|
||||
logger.debug('Max idle: %s', maxIdle)
|
||||
@ -111,7 +111,7 @@ def process_login(server: 'models.Server', data: dict[str, typing.Any]) -> typin
|
||||
'ip': src.ip,
|
||||
'hostname': src.hostname,
|
||||
'session_id': session_id,
|
||||
'dead_line': deadLine, # Can be None
|
||||
'deadline': deadLine, # For compatibility with old clients
|
||||
'max_idle': maxIdle, # Can be None
|
||||
}
|
||||
# If ticket is included, add it to result (the content of the ticket, not the ticket id itself)
|
||||
@ -138,7 +138,7 @@ def process_logout(server: 'models.Server', data: dict[str, typing.Any]) -> typi
|
||||
|
||||
if userService.in_use: # If already logged out, do not add a second logout (windows does this i.e.)
|
||||
osmanagers.OSManager.logged_out(userService, data['username'])
|
||||
osManager: typing.Optional[osmanagers.OSManager] = userService.getOsManagerInstance()
|
||||
osManager: typing.Optional[osmanagers.OSManager] = userService.get_osmanager_instance()
|
||||
if not osManager or osManager.is_removable_on_logout(userService):
|
||||
logger.debug('Removable on logout: %s', osManager)
|
||||
userService.remove()
|
||||
|
@ -66,8 +66,8 @@ class OSManager(Module):
|
||||
icon_file = 'osmanager.png'
|
||||
|
||||
# If true, this os manager will be invoked with every user service assigned, but not used
|
||||
# The interval is defined as a global config
|
||||
processUnusedMachines: bool = False
|
||||
# This is an object variable, so it can be overriden on derived classes on runtime
|
||||
handles_unused_userservices: bool = False
|
||||
|
||||
# : Type of services for which this OS Manager is designed
|
||||
# : Defaults to all. (list or tuple)
|
||||
@ -93,7 +93,7 @@ class OSManager(Module):
|
||||
Default implementation does nothing
|
||||
"""
|
||||
|
||||
def release(self, userService: 'UserService') -> None:
|
||||
def release(self, userservice: 'UserService') -> None:
|
||||
"""
|
||||
Called by a service that is in Usable state before destroying it so osmanager can release data associated with it
|
||||
Only invoked for services that reach the state "removed"
|
||||
@ -102,7 +102,7 @@ class OSManager(Module):
|
||||
|
||||
# These methods must be overriden
|
||||
def actor_data(
|
||||
self, userService: 'UserService' # pylint: disable=unused-argument
|
||||
self, userservice: 'UserService' # pylint: disable=unused-argument
|
||||
) -> collections.abc.MutableMapping[str, typing.Any]:
|
||||
"""
|
||||
This method provides information to actor, so actor can complete os configuration.
|
||||
@ -144,7 +144,7 @@ class OSManager(Module):
|
||||
"""
|
||||
return {}
|
||||
|
||||
def check_state(self, userService: 'UserService') -> str: # pylint: disable=unused-argument
|
||||
def check_state(self, userservice: 'UserService') -> str: # pylint: disable=unused-argument
|
||||
"""
|
||||
This method must be overriden so your os manager can respond to requests from system to the current state of the service
|
||||
This method will be invoked when:
|
||||
@ -157,13 +157,14 @@ class OSManager(Module):
|
||||
"""
|
||||
return State.FINISHED
|
||||
|
||||
def process_unused(self, userService: 'UserService') -> None:
|
||||
def handle_unused(self, userservice: 'UserService') -> None:
|
||||
"""
|
||||
This will be invoked for every assigned and unused user service that has been in this state at least 1/2 of Globalconfig.CHECK_UNUSED_TIME
|
||||
This function can update userService values. Normal operation will be remove machines if this state is not valid
|
||||
"""
|
||||
|
||||
def is_removable_on_logout(self, userService: 'UserService') -> bool: # pylint: disable=unused-argument
|
||||
pass
|
||||
|
||||
def is_removable_on_logout(self, userservice: 'UserService') -> bool: # pylint: disable=unused-argument
|
||||
"""
|
||||
If returns true, when actor notifies "logout", UDS will mark service for removal
|
||||
can be overriden
|
||||
@ -190,7 +191,7 @@ class OSManager(Module):
|
||||
|
||||
def process_user_password(
|
||||
self,
|
||||
userService: 'UserService', # pylint: disable=unused-argument
|
||||
userservice: 'UserService', # pylint: disable=unused-argument
|
||||
username: str,
|
||||
password: str,
|
||||
) -> tuple[str, str]:
|
||||
@ -227,42 +228,42 @@ class OSManager(Module):
|
||||
self.ready_notified(userService)
|
||||
|
||||
@staticmethod
|
||||
def logged_in(userService: 'UserService', userName: typing.Optional[str] = None) -> None:
|
||||
def logged_in(userservice: 'UserService', username: typing.Optional[str] = None) -> None:
|
||||
"""
|
||||
This method:
|
||||
- Add log in event to stats
|
||||
- Sets service in use
|
||||
- Invokes userLoggedIn for user service instance
|
||||
"""
|
||||
uniqueId = userService.unique_id
|
||||
userService.setInUse(True)
|
||||
userService.properties['last_username'] = userName or 'unknown' # Store it for convenience
|
||||
userServiceInstance = userService.get_instance()
|
||||
userServiceInstance.user_logged_in(userName or 'unknown')
|
||||
userService.update_data(userServiceInstance)
|
||||
uniqueId = userservice.unique_id
|
||||
userservice.setInUse(True)
|
||||
userservice.properties['last_username'] = username or 'unknown' # Store it for convenience
|
||||
userServiceInstance = userservice.get_instance()
|
||||
userServiceInstance.user_logged_in(username or 'unknown')
|
||||
userservice.update_data(userServiceInstance)
|
||||
|
||||
serviceIp = userServiceInstance.get_ip()
|
||||
|
||||
fullUserName = userService.user.pretty_name if userService.user else 'unknown'
|
||||
fullUserName = userservice.user.pretty_name if userservice.user else 'unknown'
|
||||
|
||||
knownUserIP = userService.src_ip + ':' + userService.src_hostname
|
||||
knownUserIP = userservice.src_ip + ':' + userservice.src_hostname
|
||||
knownUserIP = knownUserIP if knownUserIP != ':' else 'unknown'
|
||||
|
||||
userName = userName or 'unknown'
|
||||
username = username or 'unknown'
|
||||
|
||||
add_event(
|
||||
userService.deployed_service,
|
||||
userservice.deployed_service,
|
||||
types.stats.EventType.LOGIN,
|
||||
fld1=userName,
|
||||
fld1=username,
|
||||
fld2=knownUserIP,
|
||||
fld3=serviceIp,
|
||||
fld4=fullUserName,
|
||||
)
|
||||
|
||||
log.log(
|
||||
userService,
|
||||
userservice,
|
||||
log.LogLevel.INFO,
|
||||
f'User {userName} has logged in',
|
||||
f'User {username} has logged in',
|
||||
log.LogSource.OSMANAGER,
|
||||
)
|
||||
|
||||
@ -270,27 +271,27 @@ class OSManager(Module):
|
||||
'login',
|
||||
uniqueId,
|
||||
serviceIp,
|
||||
userName,
|
||||
username,
|
||||
knownUserIP,
|
||||
fullUserName,
|
||||
userService.friendly_name,
|
||||
userService.deployed_service.name,
|
||||
userservice.friendly_name,
|
||||
userservice.deployed_service.name,
|
||||
)
|
||||
|
||||
# Context makes a transaction, so we can use it to update the counter
|
||||
with userService.properties as p:
|
||||
with userservice.properties as p:
|
||||
counter = int(typing.cast(str, p.get('logins_counter', 0))) + 1
|
||||
p['logins_counter'] = counter
|
||||
|
||||
@staticmethod
|
||||
def logged_out(userService: 'UserService', userName: typing.Optional[str] = None) -> None:
|
||||
def logged_out(userservice: 'UserService', username: typing.Optional[str] = None) -> None:
|
||||
"""
|
||||
This method:
|
||||
- Add log in event to stats
|
||||
- Sets service in use
|
||||
- Invokes userLoggedIn for user service instance
|
||||
"""
|
||||
with userService.properties as p:
|
||||
with userservice.properties as p:
|
||||
counter = int(typing.cast(str, p.get('logins_counter', 0))) - 1
|
||||
if counter > 0:
|
||||
counter -= 1
|
||||
@ -299,49 +300,49 @@ class OSManager(Module):
|
||||
if GlobalConfig.EXCLUSIVE_LOGOUT.as_bool(True) and counter > 0:
|
||||
return
|
||||
|
||||
uniqueId = userService.unique_id
|
||||
userService.setInUse(False)
|
||||
userServiceInstance = userService.get_instance()
|
||||
userServiceInstance.user_logged_out(userName or 'unknown')
|
||||
userService.update_data(userServiceInstance)
|
||||
unique_id = userservice.unique_id
|
||||
userservice.setInUse(False)
|
||||
user_service_instance = userservice.get_instance()
|
||||
user_service_instance.user_logged_out(username or 'unknown')
|
||||
userservice.update_data(user_service_instance)
|
||||
|
||||
serviceIp = userServiceInstance.get_ip()
|
||||
service_ip = user_service_instance.get_ip()
|
||||
|
||||
fullUserName = userService.user.pretty_name if userService.user else 'unknown'
|
||||
full_username = userservice.user.pretty_name if userservice.user else 'unknown'
|
||||
|
||||
knownUserIP = userService.src_ip + ':' + userService.src_hostname
|
||||
knownUserIP = knownUserIP if knownUserIP != ':' else 'unknown'
|
||||
known_user_ip = userservice.src_ip + ':' + userservice.src_hostname
|
||||
known_user_ip = known_user_ip if known_user_ip != ':' else 'unknown'
|
||||
|
||||
userName = userName or 'unknown'
|
||||
username = username or 'unknown'
|
||||
|
||||
add_event(
|
||||
userService.deployed_service,
|
||||
userservice.deployed_service,
|
||||
types.stats.EventType.LOGOUT,
|
||||
fld1=userName,
|
||||
fld2=knownUserIP,
|
||||
fld3=serviceIp,
|
||||
fld4=fullUserName,
|
||||
fld1=username,
|
||||
fld2=known_user_ip,
|
||||
fld3=service_ip,
|
||||
fld4=full_username,
|
||||
)
|
||||
|
||||
log.log(
|
||||
userService,
|
||||
userservice,
|
||||
log.LogLevel.INFO,
|
||||
f'User {userName} has logged out',
|
||||
f'User {username} has logged out',
|
||||
log.LogSource.OSMANAGER,
|
||||
)
|
||||
|
||||
log.log_use(
|
||||
'logout',
|
||||
uniqueId,
|
||||
serviceIp,
|
||||
userName,
|
||||
knownUserIP,
|
||||
fullUserName,
|
||||
userService.friendly_name,
|
||||
userService.deployed_service.name,
|
||||
unique_id,
|
||||
service_ip,
|
||||
username,
|
||||
known_user_ip,
|
||||
full_username,
|
||||
userservice.friendly_name,
|
||||
userservice.deployed_service.name,
|
||||
)
|
||||
|
||||
def ready_notified(self, userService: 'UserService') -> None:
|
||||
def ready_notified(self, userservice: 'UserService') -> None:
|
||||
"""
|
||||
Invoked by actor when userService is ready
|
||||
"""
|
||||
|
@ -1387,7 +1387,7 @@ class UserInterface(metaclass=UserInterfaceAbstract):
|
||||
of this posibility in a near version...
|
||||
"""
|
||||
|
||||
def get_dict_of_values(self) -> gui.ValuesDictType:
|
||||
def get_dict_of_fields_values(self) -> gui.ValuesDictType:
|
||||
"""
|
||||
Returns own data needed for user interaction as a dict of key-names ->
|
||||
values. The values returned must be strings.
|
||||
|
@ -47,10 +47,12 @@ from ldap import (
|
||||
from django.utils.translation import gettext as _
|
||||
from django.conf import settings
|
||||
|
||||
# So it is avaliable for importers
|
||||
from ldap.ldapobject import LDAPObject
|
||||
|
||||
from uds.core.util import utils
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
LDAPResultType = collections.abc.MutableMapping[str, typing.Any]
|
||||
|
@ -78,13 +78,13 @@ class AssignedAndUnused(Job):
|
||||
# If do not needs os manager, this is
|
||||
if ds.osmanager:
|
||||
osm = ds.osmanager.get_instance()
|
||||
if osm.processUnusedMachines:
|
||||
if osm.handles_unused_userservices:
|
||||
logger.debug(
|
||||
'Processing unused services for %s, %s', ds, ds.osmanager
|
||||
)
|
||||
for us in unusedMachines:
|
||||
logger.debug('Found unused assigned service %s', us)
|
||||
osm.process_unused(us)
|
||||
osm.handle_unused(us)
|
||||
else: # No os manager, simply remove unused services in specified time
|
||||
for us in unusedMachines:
|
||||
logger.debug(
|
||||
|
@ -57,7 +57,7 @@ def getSerializedFromManagedObject(
|
||||
try:
|
||||
obj = mod.get_instance()
|
||||
gui = {i['name']: i['gui']['type'] for i in obj.gui_description()}
|
||||
values = obj.get_dict_of_values()
|
||||
values = obj.get_dict_of_fields_values()
|
||||
# Remove password fields
|
||||
for k, v in gui.items():
|
||||
if v == 'password':
|
||||
|
@ -277,7 +277,7 @@ class UserService(UUIDModel, properties.PropertiesMixin):
|
||||
self.update_data(si)
|
||||
return self.unique_id
|
||||
|
||||
def storeValue(self, name: str, value: str) -> None:
|
||||
def store_value(self, name: str, value: str) -> None:
|
||||
"""
|
||||
Stores a value inside custom storage
|
||||
|
||||
@ -288,7 +288,7 @@ class UserService(UUIDModel, properties.PropertiesMixin):
|
||||
# Store value as a property
|
||||
self.properties[name] = value
|
||||
|
||||
def recoverValue(self, name: str) -> str:
|
||||
def recover_value(self, name: str) -> str:
|
||||
"""
|
||||
Recovers a value from custom storage
|
||||
|
||||
@ -346,7 +346,7 @@ class UserService(UUIDModel, properties.PropertiesMixin):
|
||||
def getOsManager(self) -> typing.Optional['OSManager']:
|
||||
return self.deployed_service.osmanager
|
||||
|
||||
def getOsManagerInstance(self) -> typing.Optional['osmanagers.OSManager']:
|
||||
def get_osmanager_instance(self) -> typing.Optional['osmanagers.OSManager']:
|
||||
osManager = self.getOsManager()
|
||||
if osManager:
|
||||
return osManager.get_instance()
|
||||
|
@ -111,30 +111,33 @@ class EmailNotifier(messaging.Notifier):
|
||||
tab=_('SMTP Server'),
|
||||
)
|
||||
|
||||
fromEmail = gui.TextField(
|
||||
from_email = gui.TextField(
|
||||
length=128,
|
||||
label=_('From Email'),
|
||||
order=11,
|
||||
tooltip=_('Email address that will be used as sender'),
|
||||
required=True,
|
||||
tab=_('Config'),
|
||||
stored_field_name='fromEmail'
|
||||
)
|
||||
|
||||
toEmail = gui.TextField(
|
||||
to_email = gui.TextField(
|
||||
length=128,
|
||||
label=_('To Email'),
|
||||
order=12,
|
||||
tooltip=_('Email address that will be used as recipient'),
|
||||
required=True,
|
||||
tab=_('Config'),
|
||||
stored_field_name='toEmail'
|
||||
)
|
||||
|
||||
enableHTML = gui.CheckBoxField(
|
||||
enable_html = gui.CheckBoxField(
|
||||
label=_('Enable HTML'),
|
||||
order=13,
|
||||
tooltip=_('Enable HTML in emails'),
|
||||
default=True,
|
||||
tab=_('Config'),
|
||||
stored_field_name='enableHTML'
|
||||
)
|
||||
|
||||
def initialize(self, values: 'Module.ValuesType' = None):
|
||||
@ -160,8 +163,8 @@ class EmailNotifier(messaging.Notifier):
|
||||
self.hostname.value = validators.validate_fqdn(host)
|
||||
|
||||
# now check from email and to email
|
||||
self.fromEmail.value = validators.validate_email(self.fromEmail.value)
|
||||
self.toEmail.value = validators.validate_email(self.toEmail.value)
|
||||
self.from_email.value = validators.validate_email(self.from_email.value)
|
||||
self.to_email.value = validators.validate_email(self.to_email.value)
|
||||
|
||||
# Done
|
||||
|
||||
@ -172,18 +175,18 @@ class EmailNotifier(messaging.Notifier):
|
||||
# Create message container
|
||||
msg = MIMEMultipart('alternative')
|
||||
msg['Subject'] = f'{group} - {identificator}'
|
||||
msg['From'] = self.fromEmail.value
|
||||
msg['To'] = self.toEmail.value
|
||||
msg['From'] = self.from_email.value
|
||||
msg['To'] = self.to_email.value
|
||||
|
||||
part1 = MIMEText(message, 'plain')
|
||||
part2 = MIMEText(message, 'html')
|
||||
|
||||
msg.attach(part1)
|
||||
|
||||
if self.enableHTML.value:
|
||||
if self.enable_html.value:
|
||||
msg.attach(part2)
|
||||
|
||||
smtp.sendmail(self.fromEmail.value, self.toEmail.value, msg.as_string())
|
||||
smtp.sendmail(self.from_email.value, self.to_email.value, msg.as_string())
|
||||
except smtplib.SMTPException as e:
|
||||
logger.error('Error sending email: %s', e)
|
||||
|
||||
|
@ -36,4 +36,4 @@ class TelegramReceiver(jobs.Job):
|
||||
logger.error('Notifier %s is not a Telegram notifier', telegramDbNotifier.name)
|
||||
continue
|
||||
|
||||
n.retrieveMessages()
|
||||
n.retrieve_messages()
|
||||
|
@ -80,7 +80,7 @@ class TelegramNotifier(messaging.Notifier):
|
||||
tab=_('Telegram'),
|
||||
)
|
||||
|
||||
accessToken = gui.TextField(
|
||||
access_token = gui.TextField(
|
||||
length=64,
|
||||
label=_('Access Token'),
|
||||
order=2,
|
||||
@ -88,6 +88,7 @@ class TelegramNotifier(messaging.Notifier):
|
||||
required=True,
|
||||
default='',
|
||||
tab=_('Telegram'),
|
||||
stored_field_name='accessToken',
|
||||
)
|
||||
|
||||
# Secret key used to validate join and subscribe requests
|
||||
@ -104,7 +105,7 @@ class TelegramNotifier(messaging.Notifier):
|
||||
# The bot will allow commmand (/join {secret} or /subscribe {secret} and /leave or /unsubscribe) to subscribe and unsubscribe
|
||||
# For this to work, we will process the message and check if it is a command from time to time
|
||||
# This var defines the delay in secods between checks (1 hour by default, we do not need to check this every second)
|
||||
checkDelay = gui.NumericField(
|
||||
check_delay = gui.NumericField(
|
||||
length=3,
|
||||
label=_('Check delay'),
|
||||
order=3,
|
||||
@ -114,6 +115,7 @@ class TelegramNotifier(messaging.Notifier):
|
||||
min_value=60,
|
||||
max_value=86400,
|
||||
tab=_('Telegram'),
|
||||
stored_field_name='checkDelay',
|
||||
)
|
||||
|
||||
def initialize(self, values: 'Module.ValuesType' = None):
|
||||
@ -126,7 +128,7 @@ class TelegramNotifier(messaging.Notifier):
|
||||
# check hostname for stmp server si valid and is in the right format
|
||||
# that is a hostname or ip address with optional port
|
||||
# if hostname is not valid, we will raise an exception
|
||||
for i in (self.botname, self.accessToken, self.secret):
|
||||
for i in (self.botname, self.access_token, self.secret):
|
||||
s = i.as_clean_str()
|
||||
if not s:
|
||||
raise exceptions.validation.ValidationError(_('Invalid value for {}').format(i.label))
|
||||
@ -139,54 +141,54 @@ class TelegramNotifier(messaging.Notifier):
|
||||
def notify(self, group: str, identificator: str, level: messaging.LogLevel, message: str) -> None:
|
||||
telegramMsg = f'{group} - {identificator} - {str(level)}: {message}'
|
||||
logger.debug('Sending telegram message: %s', telegramMsg)
|
||||
# load chatIds
|
||||
chatIds = self.storage.get_unpickle('chatIds') or []
|
||||
t = telegram.Telegram(self.accessToken.value, self.botname.value)
|
||||
for chatId in chatIds:
|
||||
# load chat_ids
|
||||
chat_ids = self.storage.get_unpickle('chat_ids') or []
|
||||
t = telegram.Telegram(self.access_token.value, self.botname.value)
|
||||
for chatId in chat_ids:
|
||||
with ignore_exceptions():
|
||||
t.send_message(chatId, telegramMsg)
|
||||
# Wait a bit, so we don't send more than 10 messages per second
|
||||
time.sleep(0.1)
|
||||
|
||||
def subscribeUser(self, chatId: int) -> None:
|
||||
def subscribe_user(self, chat_id: int) -> None:
|
||||
# we do not expect to have a lot of users, so we will use a simple storage
|
||||
# that holds a list of chatIds
|
||||
chatIds = self.storage.get_unpickle('chatIds') or []
|
||||
if chatId not in chatIds:
|
||||
chatIds.append(chatId)
|
||||
self.storage.put_pickle('chatIds', chatIds)
|
||||
logger.info('User %s subscribed to notifications', chatId)
|
||||
# that holds a list of chat_ids
|
||||
chat_ids = self.storage.get_unpickle('chat_ids') or []
|
||||
if chat_id not in chat_ids:
|
||||
chat_ids.append(chat_id)
|
||||
self.storage.put_pickle('chat_ids', chat_ids)
|
||||
logger.info('User %s subscribed to notifications', chat_id)
|
||||
|
||||
def unsubscriteUser(self, chatId: int) -> None:
|
||||
def unsubscrite_user(self, chatId: int) -> None:
|
||||
# we do not expect to have a lot of users, so we will use a simple storage
|
||||
# that holds a list of chatIds
|
||||
chatIds = self.storage.get_unpickle('chatIds') or []
|
||||
if chatId in chatIds:
|
||||
chatIds.remove(chatId)
|
||||
self.storage.put_pickle('chatIds', chatIds)
|
||||
# that holds a list of chat_ids
|
||||
chat_ids = self.storage.get_unpickle('chat_ids') or []
|
||||
if chatId in chat_ids:
|
||||
chat_ids.remove(chatId)
|
||||
self.storage.put_pickle('chat_ids', chat_ids)
|
||||
logger.info('User %s unsubscribed from notifications', chatId)
|
||||
|
||||
def retrieveMessages(self) -> None:
|
||||
if not self.accessToken.value.strip():
|
||||
def retrieve_messages(self) -> None:
|
||||
if not self.access_token.value.strip():
|
||||
return # no access token, no messages
|
||||
# Time of last retrieve
|
||||
lastCheck: typing.Optional[datetime.datetime] = self.storage.get_unpickle('lastCheck')
|
||||
last_check: typing.Optional[datetime.datetime] = self.storage.get_unpickle('last_check')
|
||||
now = sql_datetime()
|
||||
|
||||
# If last check is not set, we will set it to now
|
||||
if lastCheck is None:
|
||||
lastCheck = now - datetime.timedelta(seconds=self.checkDelay.as_int() + 1)
|
||||
self.storage.put_pickle('lastCheck', lastCheck)
|
||||
if last_check is None:
|
||||
last_check = now - datetime.timedelta(seconds=self.check_delay.as_int() + 1)
|
||||
self.storage.put_pickle('last_check', last_check)
|
||||
|
||||
# If not enough time has passed, we will not check
|
||||
if lastCheck + datetime.timedelta(seconds=self.checkDelay.as_int()) > now:
|
||||
if last_check + datetime.timedelta(seconds=self.check_delay.as_int()) > now:
|
||||
return
|
||||
|
||||
# Update last check
|
||||
self.storage.put_pickle('lastCheck', now)
|
||||
self.storage.put_pickle('last_check', now)
|
||||
|
||||
lastOffset = self.storage.get_unpickle('lastOffset') or 0
|
||||
t = telegram.Telegram(self.accessToken.value, last_offset=lastOffset)
|
||||
last_offset = self.storage.get_unpickle('last_offset') or 0
|
||||
t = telegram.Telegram(self.access_token.value, last_offset=last_offset)
|
||||
with ignore_exceptions(): # In case getUpdates fails, ignore it
|
||||
for update in t.get_updates():
|
||||
# Process update
|
||||
@ -202,9 +204,9 @@ class TelegramNotifier(messaging.Notifier):
|
||||
'Invalid subscribe command received from telegram bot (invalid secret: %s)',
|
||||
message,
|
||||
)
|
||||
self.subscribeUser(update.chat.id)
|
||||
self.subscribe_user(update.chat.id)
|
||||
t.send_message(update.chat.id, _('You have been subscribed to notifications'))
|
||||
elif message in ('/leave', '/unsubscribe'):
|
||||
self.unsubscriteUser(update.chat.id)
|
||||
self.unsubscrite_user(update.chat.id)
|
||||
t.send_message(update.chat.id, _('You have been unsubscribed from notifications'))
|
||||
self.storage.put_pickle('lastOffset', t.lastOffset)
|
||||
self.storage.put_pickle('last_offset', t.last_offset)
|
||||
|
@ -24,19 +24,19 @@ class From:
|
||||
@dataclasses.dataclass
|
||||
class Message:
|
||||
chat: Chat
|
||||
from_: From
|
||||
src: From
|
||||
date: int
|
||||
text: str
|
||||
|
||||
@staticmethod
|
||||
def from_dict(data: collections.abc.Mapping[str, typing.Any]) -> 'Message':
|
||||
return Message(
|
||||
Chat(
|
||||
chat=Chat(
|
||||
id=data['chat']['id'],
|
||||
type=data['chat']['type'],
|
||||
first_name=data['chat']['first_name'],
|
||||
),
|
||||
From(
|
||||
src=From(
|
||||
id=data['from']['id'],
|
||||
is_bot=data['from']['is_bot'],
|
||||
first_name=data['from']['first_name'],
|
||||
@ -50,13 +50,13 @@ class Message:
|
||||
|
||||
class Telegram:
|
||||
token: str
|
||||
reqTimeout: int
|
||||
lastOffset: int
|
||||
req_timeout: int
|
||||
last_offset: int
|
||||
|
||||
def __init__(self, token: str, last_offset: int = 0) -> None:
|
||||
self.token = token
|
||||
self.reqTimeout = 3 * 2 + 1
|
||||
self.lastOffset = last_offset
|
||||
self.req_timeout = 3 * 2 + 1
|
||||
self.last_offset = last_offset
|
||||
|
||||
def request(
|
||||
self,
|
||||
@ -71,7 +71,7 @@ class Telegram:
|
||||
if stream:
|
||||
kwargs['stream'] = True
|
||||
# If params has a timeout, use the max of that and our own timeout
|
||||
timeout = max(params.get('timeout', 0), self.reqTimeout)
|
||||
timeout = max(params.get('timeout', 0), self.req_timeout)
|
||||
response = requests.get(
|
||||
f'https://api.telegram.org/bot{self.token}/{method}',
|
||||
timeout=timeout,
|
||||
@ -83,10 +83,10 @@ class Telegram:
|
||||
return self.request('send_message', {'chat_id': chat_id, 'text': text})
|
||||
|
||||
def get_updates(self, offset: int = 0, timeout: int = 0) -> collections.abc.Iterable[Message]:
|
||||
self.lastOffset = offset or self.lastOffset
|
||||
res = self.request('get_updates', {'offset': self.lastOffset, 'timeout': timeout}, stream=True)
|
||||
self.last_offset = offset or self.last_offset
|
||||
res = self.request('get_updates', {'offset': self.last_offset, 'timeout': timeout}, stream=True)
|
||||
if res['ok'] and res['result']: # if ok and there are results
|
||||
# Update the offset
|
||||
self.lastOffset = res['result'][-1]['update_id'] + 1
|
||||
self.last_offset = res['result'][-1]['update_id'] + 1
|
||||
for update in res['result']:
|
||||
yield Message.from_dict(update['message'])
|
||||
|
@ -88,7 +88,7 @@ class LinuxOsADManager(LinuxOsManager):
|
||||
'Organizational unit where to add machines in domain (check it before using it). i.e.: ou=My Machines,dc=mydomain,dc=local'
|
||||
),
|
||||
)
|
||||
clientSoftware = gui.ChoiceField(
|
||||
client_software = gui.ChoiceField(
|
||||
label=_('Client software'),
|
||||
order=5,
|
||||
tooltip=_('Use specific client software'),
|
||||
@ -100,7 +100,7 @@ class LinuxOsADManager(LinuxOsManager):
|
||||
tab=types.ui.Tab.ADVANCED,
|
||||
default='automatically',
|
||||
)
|
||||
membershipSoftware = gui.ChoiceField(
|
||||
membership_software = gui.ChoiceField(
|
||||
label=_('Membership software'),
|
||||
order=6,
|
||||
tooltip=_('Use specific membership software'),
|
||||
@ -112,7 +112,7 @@ class LinuxOsADManager(LinuxOsManager):
|
||||
tab=types.ui.Tab.ADVANCED,
|
||||
default='automatically',
|
||||
)
|
||||
removeOnExit = gui.CheckBoxField(
|
||||
remove_on_exit = gui.CheckBoxField(
|
||||
label=_('Machine clean'),
|
||||
order=7,
|
||||
tooltip=_(
|
||||
@ -128,7 +128,7 @@ class LinuxOsADManager(LinuxOsManager):
|
||||
tab=types.ui.Tab.ADVANCED,
|
||||
default=True,
|
||||
)
|
||||
automaticIdMapping = gui.CheckBoxField(
|
||||
automatic_id_mapping = gui.CheckBoxField(
|
||||
label=_('Automatic ID mapping'),
|
||||
order=9,
|
||||
tooltip=_('If checked, automatic ID mapping'),
|
||||
@ -136,10 +136,10 @@ class LinuxOsADManager(LinuxOsManager):
|
||||
default=True,
|
||||
)
|
||||
|
||||
# Inherits base "onLogout"
|
||||
onLogout = LinuxOsManager.onLogout
|
||||
# Inherits base "on_logout"
|
||||
on_logout = LinuxOsManager.on_logout
|
||||
idle = LinuxOsManager.idle
|
||||
deadLine = LinuxOsManager.deadLine
|
||||
deadline = LinuxOsManager.deadline
|
||||
|
||||
_domain: str
|
||||
_ou: str
|
||||
@ -154,6 +154,7 @@ class LinuxOsADManager(LinuxOsManager):
|
||||
|
||||
def __init__(self, environment: 'Environment', values: 'Module.ValuesType') -> None:
|
||||
super().__init__(environment, values)
|
||||
self._server_software = 'active-directory' # Currently, fixed value
|
||||
if values:
|
||||
if values['domain'] == '':
|
||||
raise exceptions.validation.ValidationError(_('Must provide a domain!'))
|
||||
@ -165,19 +166,17 @@ class LinuxOsADManager(LinuxOsManager):
|
||||
self._account = values['account']
|
||||
self._password = values['password']
|
||||
self._ou = values['ou'].strip()
|
||||
self._client_software = values['clientSoftware']
|
||||
self._server_software = 'active-directory'
|
||||
self._membership_software = values['membershipSoftware']
|
||||
self._remove_on_exit = 'y' if values['removeOnExit'] else 'n'
|
||||
self._client_software = values['client_software']
|
||||
self._membership_software = values['membership_software']
|
||||
self._remove_on_exit = 'y' if values['remove_on_exit'] else 'n'
|
||||
self._ssl = 'y' if values['ssl'] else 'n'
|
||||
self._automatic_id_mapping = 'y' if values['automaticIdMapping'] else 'n'
|
||||
self._automatic_id_mapping = 'y' if values['automatic_id_mapping'] else 'n'
|
||||
else:
|
||||
self._domain = ''
|
||||
self._account = ''
|
||||
self._password = '' # nosec: no encoded password
|
||||
self._ou = ''
|
||||
self._client_software = ''
|
||||
self._server_software = 'active-directory'
|
||||
self._membership_software = ''
|
||||
self._remove_on_exit = 'n'
|
||||
self._ssl = 'n'
|
||||
@ -238,16 +237,15 @@ class LinuxOsADManager(LinuxOsManager):
|
||||
self._automatic_id_mapping = values[10]
|
||||
super().unmarshal(codecs.decode(values[11].encode(), 'hex'))
|
||||
|
||||
def get_dict_of_values(self) -> gui.ValuesDictType:
|
||||
dct = super().get_dict_of_values()
|
||||
def get_dict_of_fields_values(self) -> gui.ValuesDictType:
|
||||
dct = super().get_dict_of_fields_values()
|
||||
dct['domain'] = self._domain
|
||||
dct['account'] = self._account
|
||||
dct['password'] = self._password
|
||||
dct['ou'] = self._ou
|
||||
dct['clientSoftware'] = self._client_software
|
||||
dct['serverSoftware'] = self._server_software
|
||||
dct['membershipSoftware'] = self._membership_software
|
||||
dct['removeOnExit'] = self._remove_on_exit == 'y'
|
||||
dct['client_software'] = self._client_software
|
||||
dct['membership_software'] = self._membership_software
|
||||
dct['remove_on_exit'] = self._remove_on_exit == 'y'
|
||||
dct['ssl'] = self._ssl == 'y'
|
||||
dct['automaticIdMapping'] = self._automatic_id_mapping == 'y'
|
||||
dct['automatic_id_mapping'] = self._automatic_id_mapping == 'y'
|
||||
return dct
|
||||
|
@ -80,7 +80,7 @@ class LinuxOsFreeIPAManager(LinuxOsManager):
|
||||
tooltip=_('Password of the account'),
|
||||
required=True,
|
||||
)
|
||||
clientSoftware = gui.ChoiceField(
|
||||
client_software = gui.ChoiceField(
|
||||
label=_('Client software'),
|
||||
order=4,
|
||||
tooltip=_('Use specific client software'),
|
||||
@ -92,7 +92,7 @@ class LinuxOsFreeIPAManager(LinuxOsManager):
|
||||
tab=types.ui.Tab.ADVANCED,
|
||||
default='automatically',
|
||||
)
|
||||
membershipSoftware = gui.ChoiceField(
|
||||
membership_software = gui.ChoiceField(
|
||||
label=_('Membership software'),
|
||||
order=5,
|
||||
tooltip=_('Use specific membership software'),
|
||||
@ -104,7 +104,7 @@ class LinuxOsFreeIPAManager(LinuxOsManager):
|
||||
tab=types.ui.Tab.ADVANCED,
|
||||
default='automatically',
|
||||
)
|
||||
removeOnExit = gui.CheckBoxField(
|
||||
remove_on_exit = gui.CheckBoxField(
|
||||
label=_('Machine clean'),
|
||||
order=6,
|
||||
tooltip=_(
|
||||
@ -120,7 +120,7 @@ class LinuxOsFreeIPAManager(LinuxOsManager):
|
||||
tab=types.ui.Tab.ADVANCED,
|
||||
default=True,
|
||||
)
|
||||
automaticIdMapping = gui.CheckBoxField(
|
||||
automatic_id_mapping = gui.CheckBoxField(
|
||||
label=_('Automatic ID mapping'),
|
||||
order=8,
|
||||
tooltip=_('If checked, automatic ID mapping'),
|
||||
@ -129,9 +129,9 @@ class LinuxOsFreeIPAManager(LinuxOsManager):
|
||||
)
|
||||
|
||||
# Inherits base "fields"
|
||||
onLogout = LinuxOsManager.onLogout
|
||||
on_logout = LinuxOsManager.on_logout
|
||||
idle = LinuxOsManager.idle
|
||||
deadLine = LinuxOsManager.deadLine
|
||||
deadline = LinuxOsManager.deadline
|
||||
|
||||
_domain: str
|
||||
_account: str
|
||||
@ -145,6 +145,7 @@ class LinuxOsFreeIPAManager(LinuxOsManager):
|
||||
|
||||
def __init__(self, environment: 'Environment', values: 'Module.ValuesType') -> None:
|
||||
super().__init__(environment, values)
|
||||
self._server_software = 'ipa' # Currently fixed to IPA
|
||||
if values:
|
||||
if values['domain'] == '':
|
||||
raise exceptions.validation.ValidationError(_('Must provide a domain!'))
|
||||
@ -155,18 +156,16 @@ class LinuxOsFreeIPAManager(LinuxOsManager):
|
||||
self._domain = values['domain']
|
||||
self._account = values['account']
|
||||
self._password = values['password']
|
||||
self._client_software = values['clientSoftware']
|
||||
self._server_software = 'ipa'
|
||||
self._membership_software = values['membershipSoftware']
|
||||
self._remove_on_exit = 'y' if values['removeOnExit'] else 'n'
|
||||
self._client_software = values['client_software']
|
||||
self._membership_software = values['membership_software']
|
||||
self._remove_on_exit = 'y' if values['remove_on_exit'] else 'n'
|
||||
self._ssl = 'y' if values['ssl'] else 'n'
|
||||
self._automatic_id_mapping = 'y' if values['automaticIdMapping'] else 'n'
|
||||
self._automatic_id_mapping = 'y' if values['automatic_id_mapping'] else 'n'
|
||||
else:
|
||||
self._domain = ''
|
||||
self._account = ''
|
||||
self._password = '' # nosec: no encoded password
|
||||
self._client_software = ''
|
||||
self._server_software = 'ipa'
|
||||
self._membership_software = ''
|
||||
self._remove_on_exit = 'n'
|
||||
self._ssl = 'n'
|
||||
@ -224,15 +223,14 @@ class LinuxOsFreeIPAManager(LinuxOsManager):
|
||||
self._automatic_id_mapping = values[9]
|
||||
super().unmarshal(codecs.decode(values[10].encode(), 'hex'))
|
||||
|
||||
def get_dict_of_values(self) -> gui.ValuesDictType:
|
||||
dct = super().get_dict_of_values()
|
||||
def get_dict_of_fields_values(self) -> gui.ValuesDictType:
|
||||
dct = super().get_dict_of_fields_values()
|
||||
dct['domain'] = self._domain
|
||||
dct['account'] = self._account
|
||||
dct['password'] = self._password
|
||||
dct['clientSoftware'] = self._client_software
|
||||
dct['serverSoftware'] = self._server_software
|
||||
dct['membershipSoftware'] = self._membership_software
|
||||
dct['removeOnExit'] = self._remove_on_exit == 'y'
|
||||
dct['client_software'] = self._client_software
|
||||
dct['membership_software'] = self._membership_software
|
||||
dct['remove_on_exit'] = self._remove_on_exit == 'y'
|
||||
dct['ssl'] = self._ssl == 'y'
|
||||
dct['automaticIdMapping'] = self._automatic_id_mapping == 'y'
|
||||
dct['automatic_id_mapping'] = self._automatic_id_mapping == 'y'
|
||||
return dct
|
||||
|
@ -59,7 +59,7 @@ class LinuxOsManager(osmanagers.OSManager):
|
||||
|
||||
servicesType = serviceTypes.VDI
|
||||
|
||||
onLogout = gui.ChoiceField(
|
||||
on_logout = gui.ChoiceField(
|
||||
label=_('Logout Action'),
|
||||
order=10,
|
||||
readonly=True,
|
||||
@ -87,7 +87,7 @@ class LinuxOsManager(osmanagers.OSManager):
|
||||
required=True,
|
||||
)
|
||||
|
||||
deadLine = gui.CheckBoxField(
|
||||
deadline = gui.CheckBoxField(
|
||||
label=_('Calendar logout'),
|
||||
order=90,
|
||||
tooltip=_(
|
||||
@ -99,29 +99,29 @@ class LinuxOsManager(osmanagers.OSManager):
|
||||
|
||||
_on_logout: str
|
||||
_idle: int
|
||||
_deadLine: bool
|
||||
_deadline: bool
|
||||
|
||||
def _set_process_unused_machines(self) -> None:
|
||||
self.processUnusedMachines = self._on_logout == 'remove'
|
||||
def _flag_processes_unused_machines(self) -> None:
|
||||
self.handles_unused_userservices = self._on_logout == 'remove'
|
||||
|
||||
def __init__(self, environment: 'Environment', values: 'Module.ValuesType') -> None:
|
||||
super().__init__(environment, values)
|
||||
if values is not None:
|
||||
self._on_logout = values['onLogout']
|
||||
self._on_logout = values['on_logout']
|
||||
self._idle = int(values['idle'])
|
||||
self._deadLine = gui.as_bool(values['deadLine'])
|
||||
self._deadline = gui.as_bool(values['deadline'])
|
||||
else:
|
||||
self._on_logout = ''
|
||||
self._idle = -1
|
||||
self._deadLine = True
|
||||
self._deadline = True
|
||||
|
||||
self._set_process_unused_machines()
|
||||
self._flag_processes_unused_machines()
|
||||
|
||||
def release(self, userService: 'UserService') -> None:
|
||||
pass
|
||||
|
||||
def ignore_deadline(self) -> bool:
|
||||
return not self._deadLine
|
||||
return not self._deadline
|
||||
|
||||
def is_removable_on_logout(self, userService: 'UserService') -> bool:
|
||||
'''
|
||||
@ -159,19 +159,19 @@ class LinuxOsManager(osmanagers.OSManager):
|
||||
) -> collections.abc.MutableMapping[str, typing.Any]:
|
||||
return {'action': 'rename', 'name': userService.get_name()} # No custom data
|
||||
|
||||
def process_unused(self, userService: 'UserService') -> None:
|
||||
def handle_unused(self, userservice: 'UserService') -> None:
|
||||
"""
|
||||
This will be invoked for every assigned and unused user service that has been in this state at least 1/2 of Globalconfig.CHECK_UNUSED_TIME
|
||||
This function can update userService values. Normal operation will be remove machines if this state is not valid
|
||||
"""
|
||||
if self.is_removable_on_logout(userService):
|
||||
if self.is_removable_on_logout(userservice):
|
||||
log.log(
|
||||
userService,
|
||||
userservice,
|
||||
log.LogLevel.INFO,
|
||||
'Unused user service for too long. Removing due to OS Manager parameters.',
|
||||
log.LogSource.OSMANAGER,
|
||||
)
|
||||
userService.remove()
|
||||
userservice.remove()
|
||||
|
||||
def is_persistent(self) -> bool:
|
||||
return self._on_logout == 'keep-always'
|
||||
@ -186,7 +186,7 @@ class LinuxOsManager(osmanagers.OSManager):
|
||||
"""
|
||||
if (
|
||||
self._idle <= 0
|
||||
): # or (settings.DEBUG is False and self._onLogout != 'remove'):
|
||||
): # or (settings.DEBUG is False and self._on_logout != 'remove'):
|
||||
return None
|
||||
|
||||
return self._idle
|
||||
@ -196,29 +196,29 @@ class LinuxOsManager(osmanagers.OSManager):
|
||||
Serializes the os manager data so we can store it in database
|
||||
"""
|
||||
return '\t'.join(
|
||||
['v3', self._on_logout, str(self._idle), gui.from_bool(self._deadLine)]
|
||||
['v3', self._on_logout, str(self._idle), gui.from_bool(self._deadline)]
|
||||
).encode('utf8')
|
||||
|
||||
def unmarshal(self, data: bytes) -> None:
|
||||
values = data.decode('utf8').split('\t')
|
||||
self._idle = -1
|
||||
self._deadLine = True
|
||||
self._deadline = True
|
||||
if values[0] == 'v1':
|
||||
self._on_logout = values[1]
|
||||
elif values[0] == 'v2':
|
||||
self._on_logout, self._idle = values[1], int(values[2])
|
||||
elif values[0] == 'v3':
|
||||
self._on_logout, self._idle, self._deadLine = (
|
||||
self._on_logout, self._idle, self._deadline = (
|
||||
values[1],
|
||||
int(values[2]),
|
||||
gui.as_bool(values[3]),
|
||||
)
|
||||
|
||||
self._set_process_unused_machines()
|
||||
self._flag_processes_unused_machines()
|
||||
|
||||
def get_dict_of_values(self) -> gui.ValuesDictType:
|
||||
def get_dict_of_fields_values(self) -> gui.ValuesDictType:
|
||||
return {
|
||||
'onLogout': self._on_logout,
|
||||
'on_logout': self._on_logout,
|
||||
'idle': str(self._idle),
|
||||
'deadLine': gui.from_bool(self._deadLine),
|
||||
'deadline': gui.from_bool(self._deadline),
|
||||
}
|
||||
|
@ -48,6 +48,8 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from uds.models.user_service import UserService
|
||||
from uds.core.environment import Environment
|
||||
from uds.core.module import Module
|
||||
|
||||
|
||||
class LinuxRandomPassManager(LinuxOsManager):
|
||||
@ -59,7 +61,7 @@ class LinuxRandomPassManager(LinuxOsManager):
|
||||
icon_file = 'losmanager.png'
|
||||
|
||||
# Apart form data from linux os manager, we need also domain and credentials
|
||||
userAccount = gui.TextField(
|
||||
user_account = gui.TextField(
|
||||
length=64,
|
||||
label=_('Account'),
|
||||
order=2,
|
||||
@ -67,21 +69,21 @@ class LinuxRandomPassManager(LinuxOsManager):
|
||||
required=True,
|
||||
)
|
||||
|
||||
# Inherits base "onLogout"
|
||||
onLogout = LinuxOsManager.onLogout
|
||||
# Inherits base "on_logout"
|
||||
on_logout = LinuxOsManager.on_logout
|
||||
idle = LinuxOsManager.idle
|
||||
deadLine = LinuxOsManager.deadLine
|
||||
deadline = LinuxOsManager.deadline
|
||||
|
||||
_user_account: str
|
||||
|
||||
def __init__(self, environment, values):
|
||||
def __init__(self, environment: 'Environment', values: 'Module.ValuesType') -> None:
|
||||
super().__init__(environment, values)
|
||||
if values is not None:
|
||||
if values['userAccount'] == '':
|
||||
if values['user_account'] == '':
|
||||
raise exceptions.validation.ValidationError(
|
||||
_('Must provide an user account!!!')
|
||||
)
|
||||
self._user_account = values['userAccount']
|
||||
self._user_account = values['user_account']
|
||||
else:
|
||||
self._user_account = ''
|
||||
|
||||
@ -89,17 +91,17 @@ class LinuxRandomPassManager(LinuxOsManager):
|
||||
self, userService: 'UserService', username: str, password: str
|
||||
) -> tuple[str, str]:
|
||||
if username == self._user_account:
|
||||
return (username, userService.recoverValue('linOsRandomPass'))
|
||||
return (username, userService.recover_value('linOsRandomPass'))
|
||||
return username, password
|
||||
|
||||
def gen_random_password(self, service: 'UserService') -> str:
|
||||
randomPass = service.recoverValue('linOsRandomPass')
|
||||
randomPass = service.recover_value('linOsRandomPass')
|
||||
if randomPass is None:
|
||||
randomPass = ''.join(
|
||||
random.SystemRandom().choice(string.ascii_letters + string.digits)
|
||||
for _ in range(16)
|
||||
)
|
||||
service.storeValue('linOsRandomPass', randomPass)
|
||||
service.store_value('linOsRandomPass', randomPass)
|
||||
log.log(
|
||||
service,
|
||||
log.LogLevel.INFO,
|
||||
@ -144,7 +146,7 @@ class LinuxRandomPassManager(LinuxOsManager):
|
||||
self._user_account = values[1].decode()
|
||||
LinuxOsManager.unmarshal(self, codecs.decode(values[2], 'hex'))
|
||||
|
||||
def get_dict_of_values(self) -> gui.ValuesDictType:
|
||||
dic = LinuxOsManager.get_dict_of_values(self)
|
||||
dic['userAccount'] = self._user_account
|
||||
def get_dict_of_fields_values(self) -> gui.ValuesDictType:
|
||||
dic = LinuxOsManager.get_dict_of_fields_values(self)
|
||||
dic['user_account'] = self._user_account
|
||||
return dic
|
||||
|
@ -57,7 +57,7 @@ class TestOSManager(osmanagers.OSManager):
|
||||
|
||||
servicesType = types.services.ServiceType.VDI
|
||||
|
||||
onLogout = gui.ChoiceField(
|
||||
on_logout = gui.ChoiceField(
|
||||
label=_('Logout Action'),
|
||||
order=10,
|
||||
readonly=True,
|
||||
@ -86,7 +86,7 @@ class TestOSManager(osmanagers.OSManager):
|
||||
)
|
||||
|
||||
def initialize(self, values: 'Module.ValuesType'):
|
||||
self.processUnusedMachines = True
|
||||
self.handles_unused_userservices = True
|
||||
|
||||
def release(self, userService: 'UserService') -> None:
|
||||
logger.debug('User service %s released', userService)
|
||||
@ -96,8 +96,8 @@ class TestOSManager(osmanagers.OSManager):
|
||||
Says if a machine is removable on logout
|
||||
'''
|
||||
if not userService.in_use:
|
||||
if (self.onLogout.value == 'remove') or (
|
||||
not userService.check_publication_validity() and self.onLogout.value == 'keep'
|
||||
if (self.on_logout.value == 'remove') or (
|
||||
not userService.check_publication_validity() and self.on_logout.value == 'keep'
|
||||
):
|
||||
return True
|
||||
|
||||
@ -127,22 +127,22 @@ class TestOSManager(osmanagers.OSManager):
|
||||
) -> collections.abc.MutableMapping[str, typing.Any]:
|
||||
return {'action': 'rename', 'name': userService.get_name()}
|
||||
|
||||
def process_unused(self, userService: 'UserService') -> None:
|
||||
def handle_unused(self, userservice: 'UserService') -> None:
|
||||
"""
|
||||
This will be invoked for every assigned and unused user service that has been in this state at least 1/2 of Globalconfig.CHECK_UNUSED_TIME
|
||||
This function can update userService values. Normal operation will be remove machines if this state is not valid
|
||||
"""
|
||||
if self.is_removable_on_logout(userService):
|
||||
if self.is_removable_on_logout(userservice):
|
||||
log.log(
|
||||
userService,
|
||||
userservice,
|
||||
log.LogLevel.INFO,
|
||||
'Unused user service for too long. Removing due to OS Manager parameters.',
|
||||
log.LogSource.OSMANAGER,
|
||||
)
|
||||
userService.remove()
|
||||
userservice.remove()
|
||||
|
||||
def is_persistent(self):
|
||||
return self.onLogout.value == 'keep-always'
|
||||
return self.on_logout.value == 'keep-always'
|
||||
|
||||
def check_state(self, userService: 'UserService') -> str:
|
||||
logger.debug('Checking state for service %s', userService)
|
||||
@ -154,7 +154,7 @@ class TestOSManager(osmanagers.OSManager):
|
||||
"""
|
||||
if (
|
||||
self.idle.value <= 0
|
||||
): # or (settings.DEBUG is False and self._onLogout != 'remove'):
|
||||
): # or (settings.DEBUG is False and self.on_logout != 'remove'):
|
||||
return None
|
||||
|
||||
return self.idle.value
|
||||
|
@ -50,7 +50,7 @@ class WindowsOsManager(osmanagers.OSManager):
|
||||
icon_file = 'wosmanager.png'
|
||||
servicesType = serviceTypes.VDI
|
||||
|
||||
onLogout = gui.ChoiceField(
|
||||
on_logout = gui.ChoiceField(
|
||||
label=_('Logout Action'),
|
||||
order=10,
|
||||
readonly=True,
|
||||
@ -78,7 +78,7 @@ class WindowsOsManager(osmanagers.OSManager):
|
||||
required=True,
|
||||
)
|
||||
|
||||
deadLine = gui.CheckBoxField(
|
||||
deadline = gui.CheckBoxField(
|
||||
label=_('Calendar logout'),
|
||||
order=90,
|
||||
tooltip=_(
|
||||
@ -106,21 +106,21 @@ class WindowsOsManager(osmanagers.OSManager):
|
||||
)
|
||||
return length
|
||||
|
||||
def __setProcessUnusedMachines(self):
|
||||
self.processUnusedMachines = self._on_logout == 'remove'
|
||||
def _set_handles_unused(self):
|
||||
self.handles_unused_userservices = self._on_logout == 'remove'
|
||||
|
||||
def __init__(self, environment, values):
|
||||
super().__init__(environment, values)
|
||||
if values is not None:
|
||||
self._on_logout = values['onLogout']
|
||||
self._on_logout = values['on_logout']
|
||||
self._idle = int(values['idle'])
|
||||
self._deadline = gui.as_bool(values['deadLine'])
|
||||
self._deadline = gui.as_bool(values['deadline'])
|
||||
else:
|
||||
self._on_logout = ''
|
||||
self._idle = -1
|
||||
self._deadline = True
|
||||
|
||||
self.__setProcessUnusedMachines()
|
||||
self._set_handles_unused()
|
||||
|
||||
def is_removable_on_logout(self, userService: 'UserService') -> bool:
|
||||
"""
|
||||
@ -186,26 +186,26 @@ class WindowsOsManager(osmanagers.OSManager):
|
||||
self, userService, username, password
|
||||
)
|
||||
|
||||
def process_unused(self, userService: 'UserService') -> None:
|
||||
def handle_unused(self, userservice: 'UserService') -> None:
|
||||
"""
|
||||
This will be invoked for every assigned and unused user service that has been in this state at least 1/2 of Globalconfig.CHECK_UNUSED_TIME
|
||||
This function can update userService values. Normal operation will be remove machines if this state is not valid
|
||||
"""
|
||||
if self.is_removable_on_logout(userService):
|
||||
if self.is_removable_on_logout(userservice):
|
||||
log.log(
|
||||
userService,
|
||||
userservice,
|
||||
log.LogLevel.INFO,
|
||||
'Unused user service for too long. Removing due to OS Manager parameters.',
|
||||
log.LogSource.OSMANAGER,
|
||||
)
|
||||
userService.remove()
|
||||
userservice.remove()
|
||||
|
||||
def is_persistent(self):
|
||||
return self._on_logout == 'keep-always'
|
||||
|
||||
def check_state(self, userService: 'UserService') -> str:
|
||||
def check_state(self, userservice: 'UserService') -> str:
|
||||
# will alway return true, because the check is done by an actor callback
|
||||
logger.debug('Checking state for service %s', userService)
|
||||
logger.debug('Checking state for service %s', userservice)
|
||||
return State.RUNNING
|
||||
|
||||
def max_idle(self):
|
||||
@ -214,7 +214,7 @@ class WindowsOsManager(osmanagers.OSManager):
|
||||
"""
|
||||
if (
|
||||
self._idle <= 0
|
||||
): # or (settings.DEBUG is False and self._onLogout != 'remove'):
|
||||
): # or (settings.DEBUG is False and self._on_logout != 'remove'):
|
||||
return None
|
||||
|
||||
return self._idle
|
||||
@ -247,11 +247,11 @@ class WindowsOsManager(osmanagers.OSManager):
|
||||
'Exception unmarshalling. Some values left as default ones'
|
||||
)
|
||||
|
||||
self.__setProcessUnusedMachines()
|
||||
self._set_handles_unused()
|
||||
|
||||
def get_dict_of_values(self) -> gui.ValuesDictType:
|
||||
def get_dict_of_fields_values(self) -> 'gui.ValuesDictType':
|
||||
return {
|
||||
'onLogout': self._on_logout,
|
||||
'on_logout': self._on_logout,
|
||||
'idle': str(self._idle),
|
||||
'deadLine': gui.from_bool(self._deadline),
|
||||
'deadline': gui.from_bool(self._deadline),
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
tooltip=_('Group to which add machines on creation. If empty, no group will be used.'),
|
||||
tab=_('Advanced'),
|
||||
)
|
||||
removeOnExit = gui.CheckBoxField(
|
||||
remove_on_exit = gui.CheckBoxField(
|
||||
label=_('Machine clean'),
|
||||
order=8,
|
||||
tooltip=_(
|
||||
@ -110,7 +110,7 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
tab=_('Advanced'),
|
||||
default=True,
|
||||
)
|
||||
serverHint = gui.TextField(
|
||||
server_hint = gui.TextField(
|
||||
length=64,
|
||||
label=_('Server Hint'),
|
||||
order=9,
|
||||
@ -125,10 +125,10 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
default=True,
|
||||
)
|
||||
|
||||
# Inherits base "onLogout"
|
||||
onLogout = WindowsOsManager.onLogout
|
||||
# Inherits base "on_logout"
|
||||
on_logout = WindowsOsManager.on_logout
|
||||
idle = WindowsOsManager.idle
|
||||
deadLine = WindowsOsManager.deadLine
|
||||
deadline = WindowsOsManager.deadline
|
||||
|
||||
_domain: str
|
||||
_ou: str
|
||||
@ -157,9 +157,9 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
self._account = values['account']
|
||||
self._password = values['password']
|
||||
self._group = values['grp'].strip()
|
||||
self._server_hint = values['serverHint'].strip()
|
||||
self._server_hint = values['server_hint'].strip()
|
||||
self._ssl = 'y' if values['ssl'] else 'n'
|
||||
self._remove_on_exit = 'y' if values['removeOnExit'] else 'n'
|
||||
self._remove_on_exit = 'y' if values['remove_on_exit'] else 'n'
|
||||
else:
|
||||
self._domain = ''
|
||||
self._ou = ''
|
||||
@ -176,7 +176,7 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
if self._ou.lower().find(lpath) == -1:
|
||||
self._ou += ',' + lpath
|
||||
|
||||
def __getServerList(self) -> collections.abc.Iterable[tuple[str, int]]:
|
||||
def _get_server_list(self) -> collections.abc.Iterable[tuple[str, int]]:
|
||||
if self._server_hint != '':
|
||||
yield (self._server_hint, 389)
|
||||
|
||||
@ -193,7 +193,7 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
):
|
||||
yield (str(server.target)[:-1], server.port)
|
||||
|
||||
def __connectLdap(
|
||||
def _connect_ldap(
|
||||
self, servers: typing.Optional[collections.abc.Iterable[tuple[str, int]]] = None
|
||||
) -> typing.Any:
|
||||
"""
|
||||
@ -203,7 +203,7 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
ldaputil.LDAPError
|
||||
"""
|
||||
if servers is None:
|
||||
servers = self.__getServerList()
|
||||
servers = self._get_server_list()
|
||||
|
||||
account = self._account
|
||||
if account.find('@') == -1:
|
||||
@ -229,7 +229,7 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
|
||||
raise ldaputil.LDAPError(_str)
|
||||
|
||||
def __getGroup(self, ldapConnection: typing.Any) -> typing.Optional[str]:
|
||||
def _get_group(self, ldapConnection: 'ldaputil.LDAPObject') -> typing.Optional[str]:
|
||||
base = ','.join(['DC=' + i for i in self._domain.split('.')])
|
||||
group = ldaputil.escape(self._group)
|
||||
obj: typing.Optional[collections.abc.MutableMapping[str, typing.Any]]
|
||||
@ -251,16 +251,16 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
|
||||
return obj['dn'] # Returns the DN
|
||||
|
||||
def __getMachine(self, ldapConnection, machineName: str) -> typing.Optional[str]:
|
||||
def _get_machine(self, ldap_connection: 'ldaputil.LDAPObject', machine_name: str) -> typing.Optional[str]:
|
||||
# if self._ou:
|
||||
# base = self._ou
|
||||
# else:
|
||||
base = ','.join(['DC=' + i for i in self._domain.split('.')])
|
||||
|
||||
fltr = f'(&(objectClass=computer)(sAMAccountName={ldaputil.escape(machineName)}$))'
|
||||
fltr = f'(&(objectClass=computer)(sAMAccountName={ldaputil.escape(machine_name)}$))'
|
||||
obj: typing.Optional[collections.abc.MutableMapping[str, typing.Any]]
|
||||
try:
|
||||
obj = next(ldaputil.as_dict(ldapConnection, base, fltr, ['dn'], sizeLimit=50))
|
||||
obj = next(ldaputil.as_dict(ldap_connection, base, fltr, ['dn'], sizeLimit=50))
|
||||
except StopIteration:
|
||||
obj = None
|
||||
|
||||
@ -269,7 +269,7 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
|
||||
return obj['dn'] # Returns the DN
|
||||
|
||||
def ready_notified(self, userService: 'UserService') -> None:
|
||||
def ready_notified(self, userservice: 'UserService') -> None:
|
||||
# No group to add
|
||||
if self._group == '':
|
||||
return
|
||||
@ -280,16 +280,16 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
|
||||
# The machine is on a AD for sure, and maybe they are not already sync
|
||||
error: typing.Optional[str] = None
|
||||
for s in self.__getServerList():
|
||||
for s in self._get_server_list():
|
||||
try:
|
||||
ldapConnection = self.__connectLdap(servers=(s,))
|
||||
ldap_connection = self._connect_ldap(servers=(s,))
|
||||
|
||||
machine = self.__getMachine(ldapConnection, userService.friendly_name)
|
||||
group = self.__getGroup(ldapConnection)
|
||||
machine = self._get_machine(ldap_connection, userservice.friendly_name)
|
||||
group = self._get_group(ldap_connection)
|
||||
# #
|
||||
# Direct LDAP operation "modify", maybe this need to be added to ldaputil? :)
|
||||
# #
|
||||
ldapConnection.modify_s(
|
||||
ldap_connection.modify_s(
|
||||
group, ((ldap.MOD_ADD, 'member', [machine.encode()]),) # type: ignore # (valid)
|
||||
) # @UndefinedVariable
|
||||
error = None
|
||||
@ -297,7 +297,7 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
except dns.resolver.NXDOMAIN: # No domain found, log it and pass
|
||||
logger.warning('Could not find _ldap._tcp.%s', self._domain)
|
||||
log.log(
|
||||
userService,
|
||||
userservice,
|
||||
log.LogLevel.WARNING,
|
||||
f'Could not remove machine from domain (_ldap._tcp.{self._domain} not found)',
|
||||
log.LogSource.OSMANAGER,
|
||||
@ -310,15 +310,15 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
logger.exception('Ldap Exception caught')
|
||||
error = f'Could not add machine (invalid credentials? for {self._account})'
|
||||
except Exception as e:
|
||||
error = f'Could not add machine {userService.friendly_name} to group {self._group}: {e}'
|
||||
error = f'Could not add machine {userservice.friendly_name} to group {self._group}: {e}'
|
||||
# logger.exception('Ldap Exception caught')
|
||||
|
||||
if error:
|
||||
log.log(userService, log.LogLevel.WARNING, error, log.LogSource.OSMANAGER)
|
||||
log.log(userservice, log.LogLevel.WARNING, error, log.LogSource.OSMANAGER)
|
||||
logger.error(error)
|
||||
|
||||
def release(self, userService: 'UserService') -> None:
|
||||
super().release(userService)
|
||||
def release(self, userservice: 'UserService') -> None:
|
||||
super().release(userservice)
|
||||
|
||||
# If no removal requested, just return
|
||||
if self._remove_on_exit != 'y':
|
||||
@ -327,7 +327,7 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
if '.' not in self._domain:
|
||||
# logger.info('Releasing from a not FQDN domain is not supported')
|
||||
log.log(
|
||||
userService,
|
||||
userservice,
|
||||
log.LogLevel.INFO,
|
||||
"Removing a domain machine form a non FQDN domain is not supported.",
|
||||
log.LogSource.OSMANAGER,
|
||||
@ -335,11 +335,11 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
return
|
||||
|
||||
try:
|
||||
ldapConnection = self.__connectLdap()
|
||||
ldap_connection = self._connect_ldap()
|
||||
except dns.resolver.NXDOMAIN: # No domain found, log it and pass
|
||||
logger.warning('Could not find _ldap._tcp.%s', self._domain)
|
||||
log.log(
|
||||
userService,
|
||||
userservice,
|
||||
log.LogLevel.WARNING,
|
||||
f'Could not remove machine from domain (_ldap._tcp.{self._domain} not found)',
|
||||
log.LogSource.OSMANAGER,
|
||||
@ -348,7 +348,7 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
except ldaputil.LDAPError as e:
|
||||
# logger.exception('Ldap Exception caught')
|
||||
log.log(
|
||||
userService,
|
||||
userservice,
|
||||
log.LogLevel.WARNING,
|
||||
f'Could not remove machine from domain ({e})',
|
||||
log.LogSource.OSMANAGER,
|
||||
@ -357,7 +357,7 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
except Exception as e:
|
||||
# logger.exception('Exception caught')
|
||||
log.log(
|
||||
userService,
|
||||
userservice,
|
||||
log.LogLevel.WARNING,
|
||||
f'Could not remove machine from domain ({e})',
|
||||
log.LogSource.OSMANAGER,
|
||||
@ -365,18 +365,18 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
return
|
||||
|
||||
try:
|
||||
res = self.__getMachine(ldapConnection, userService.friendly_name)
|
||||
res = self._get_machine(ldap_connection, userservice.friendly_name)
|
||||
if res is None:
|
||||
raise Exception(f'Machine {userService.friendly_name} not found on AD (permissions?)')
|
||||
ldaputil.recursive_delete(ldapConnection, res)
|
||||
raise Exception(f'Machine {userservice.friendly_name} not found on AD (permissions?)')
|
||||
ldaputil.recursive_delete(ldap_connection, res)
|
||||
except IndexError:
|
||||
logger.error('Error deleting %s from BASE %s', userService.friendly_name, self._ou)
|
||||
logger.error('Error deleting %s from BASE %s', userservice.friendly_name, self._ou)
|
||||
except Exception:
|
||||
logger.exception('Deleting from AD: ')
|
||||
|
||||
def check(self) -> str:
|
||||
try:
|
||||
ldapConnection = self.__connectLdap()
|
||||
ldap_connection = self._connect_ldap()
|
||||
except ldaputil.LDAPError as e:
|
||||
return _('Check error: {}').format(e)
|
||||
except dns.resolver.NXDOMAIN:
|
||||
@ -388,13 +388,13 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
return str(e)
|
||||
|
||||
try:
|
||||
ldapConnection.search_st(self._ou, ldap.SCOPE_BASE) # type: ignore # (valid)
|
||||
ldap_connection.search_st(self._ou, ldap.SCOPE_BASE) # type: ignore # (valid)
|
||||
except ldaputil.LDAPError as e:
|
||||
return _('Check error: {}').format(e)
|
||||
|
||||
# Group
|
||||
if self._group != '':
|
||||
if self.__getGroup(ldapConnection) is None:
|
||||
if self._get_group(ldap_connection) is None:
|
||||
return _('Check Error: group "{}" not found (using "cn" to locate it)').format(self._group)
|
||||
|
||||
return _('Server check was successful')
|
||||
@ -407,7 +407,7 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
logger.debug(wd)
|
||||
try:
|
||||
try:
|
||||
ldapConnection = wd.__connectLdap()
|
||||
ldap_connection = wd._connect_ldap()
|
||||
except ldaputil.LDAPError as e:
|
||||
return [False, _('Could not access AD using LDAP ({0})').format(e)]
|
||||
|
||||
@ -416,7 +416,7 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
ou = 'cn=Computers,dc=' + ',dc='.join(wd._domain.split('.'))
|
||||
|
||||
logger.info('Checking %s with ou %s', wd._domain, ou)
|
||||
r = ldapConnection.search_st(ou, ldap.SCOPE_BASE) # type: ignore # (valid)
|
||||
r = ldap_connection.search_st(ou, ldap.SCOPE_BASE) # type: ignore # (valid)
|
||||
logger.info('Result of search: %s', r)
|
||||
|
||||
except ldaputil.LDAPError:
|
||||
@ -437,10 +437,10 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
|
||||
return [True, _("All parameters seem to work fine.")]
|
||||
|
||||
def actor_data(self, userService: 'UserService') -> collections.abc.MutableMapping[str, typing.Any]:
|
||||
def actor_data(self, userservice: 'UserService') -> collections.abc.MutableMapping[str, typing.Any]:
|
||||
return {
|
||||
'action': 'rename_ad',
|
||||
'name': userService.get_name(),
|
||||
'name': userservice.get_name(),
|
||||
|
||||
# Repeat data, to keep compat with old versions of Actor
|
||||
# Will be removed in a couple of versions
|
||||
@ -503,14 +503,14 @@ class WinDomainOsManager(WindowsOsManager):
|
||||
self._remove_on_exit = 'y'
|
||||
super().unmarshal(codecs.decode(values[5].encode(), 'hex'))
|
||||
|
||||
def get_dict_of_values(self) -> gui.ValuesDictType:
|
||||
dct = super().get_dict_of_values()
|
||||
def get_dict_of_fields_values(self) -> gui.ValuesDictType:
|
||||
dct = super().get_dict_of_fields_values()
|
||||
dct['domain'] = self._domain
|
||||
dct['ou'] = self._ou
|
||||
dct['account'] = self._account
|
||||
dct['password'] = self._password
|
||||
dct['grp'] = self._group
|
||||
dct['serverHint'] = self._server_hint
|
||||
dct['server_hint'] = self._server_hint
|
||||
dct['ssl'] = self._ssl == 'y'
|
||||
dct['removeOnExit'] = self._remove_on_exit == 'y'
|
||||
dct['remove_on_exit'] = self._remove_on_exit == 'y'
|
||||
return dct
|
||||
|
@ -63,7 +63,7 @@ class WinRandomPassManager(WindowsOsManager):
|
||||
icon_file = 'wosmanager.png'
|
||||
|
||||
# Apart form data from windows os manager, we need also domain and credentials
|
||||
userAccount = gui.TextField(
|
||||
user_account = gui.TextField(
|
||||
length=64,
|
||||
label=_('Account'),
|
||||
order=2,
|
||||
@ -78,10 +78,10 @@ class WinRandomPassManager(WindowsOsManager):
|
||||
required=True,
|
||||
)
|
||||
|
||||
# Inherits base "onLogout"
|
||||
onLogout = WindowsOsManager.onLogout
|
||||
# Inherits base "on_logout"
|
||||
on_logout = WindowsOsManager.on_logout
|
||||
idle = WindowsOsManager.idle
|
||||
deadLine = WindowsOsManager.deadLine
|
||||
dead_line = WindowsOsManager.deadline
|
||||
|
||||
_user_account: str
|
||||
_password: str
|
||||
@ -103,12 +103,12 @@ class WinRandomPassManager(WindowsOsManager):
|
||||
self, userService: 'UserService', username: str, password: str
|
||||
) -> tuple[str, str]:
|
||||
if username == self._user_account:
|
||||
password = userService.recoverValue('winOsRandomPass')
|
||||
password = userService.recover_value('winOsRandomPass')
|
||||
|
||||
return WindowsOsManager.process_user_password(self, userService, username, password)
|
||||
|
||||
def gen_random_password(self, userService: 'UserService'):
|
||||
randomPass = userService.recoverValue('winOsRandomPass')
|
||||
randomPass = userService.recover_value('winOsRandomPass')
|
||||
if not randomPass:
|
||||
# Generates a password that conforms to complexity
|
||||
rnd = random.SystemRandom()
|
||||
@ -118,7 +118,7 @@ class WinRandomPassManager(WindowsOsManager):
|
||||
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)
|
||||
userService.store_value('winOsRandomPass', randomPass)
|
||||
log.log(
|
||||
userService,
|
||||
log.LogLevel.INFO,
|
||||
@ -159,8 +159,8 @@ class WinRandomPassManager(WindowsOsManager):
|
||||
self._password = CryptoManager().decrypt(values[2])
|
||||
super().unmarshal(codecs.decode(values[3].encode(), 'hex'))
|
||||
|
||||
def get_dict_of_values(self) -> gui.ValuesDictType:
|
||||
dic = super().get_dict_of_values()
|
||||
dic['userAccount'] = self._user_account
|
||||
def get_dict_of_fields_values(self) -> gui.ValuesDictType:
|
||||
dic = super().get_dict_of_fields_values()
|
||||
dic['user_account'] = self._user_account
|
||||
dic['password'] = self._password
|
||||
return dic
|
||||
|
@ -189,7 +189,7 @@ class IPMachinesService(IPServiceBase):
|
||||
def get_token(self):
|
||||
return self._token or None
|
||||
|
||||
def get_dict_of_values(self) -> gui.ValuesDictType:
|
||||
def get_dict_of_fields_values(self) -> gui.ValuesDictType:
|
||||
ips = (i.split('~')[0] for i in self._ips)
|
||||
return {
|
||||
'ipList': ensure.is_list(ips),
|
||||
|
@ -70,7 +70,7 @@ class ServerEventsLoginLogoutTest(rest.test.RESTTestCase):
|
||||
# {
|
||||
# 'ip': src.ip,
|
||||
# 'hostname': src.hostname,
|
||||
# 'dead_line': deadLine,
|
||||
# 'deadline': deadLine,
|
||||
# 'max_idle': maxIdle,
|
||||
# 'session_id': session_id,
|
||||
# }
|
||||
|
@ -151,7 +151,7 @@ class UserinterfaceInternalTest(UDSTestCase):
|
||||
def test_valuesDict(self):
|
||||
ui = TestingUserInterface()
|
||||
self.assertEqual(
|
||||
ui.get_dict_of_values(),
|
||||
ui.get_dict_of_fields_values(),
|
||||
{
|
||||
'str_field': DEFAULTS['str_field'],
|
||||
'str_auto_field': DEFAULTS['str_auto_field'],
|
||||
|
6
server/tests/fixtures/notifiers.py
vendored
6
server/tests/fixtures/notifiers.py
vendored
@ -60,9 +60,9 @@ def createEmailNotifier(
|
||||
)
|
||||
instance.username.value = username or ''
|
||||
instance.password.value = password or ''
|
||||
instance.fromEmail.value = fromEmail or 'from@email.com'
|
||||
instance.toEmail.value = toEmail or 'to@email.com'
|
||||
instance.enableHTML.value = enableHtml
|
||||
instance.from_email.value = fromEmail or 'from@email.com'
|
||||
instance.to_email.value = toEmail or 'to@email.com'
|
||||
instance.enable_html.value = enableHtml
|
||||
instance.security.value = security or 'none'
|
||||
# Save
|
||||
notifier.data = instance.serialize()
|
||||
|
2
server/tests/fixtures/services.py
vendored
2
server/tests/fixtures/services.py
vendored
@ -90,7 +90,7 @@ def createOsManager() -> models.OSManager:
|
||||
from uds.osmanagers.Test import TestOSManager
|
||||
|
||||
values: dict[str, typing.Any] = {
|
||||
'onLogout': 'remove',
|
||||
'on_logout': 'remove',
|
||||
'idle': 300,
|
||||
}
|
||||
osmanager = models.OSManager.objects.create(
|
||||
|
Loading…
Reference in New Issue
Block a user