1
0
mirror of https://github.com/dkmstr/openuds.git synced 2025-03-08 16:58:31 +03:00

advancing on refactoring

This commit is contained in:
Adolfo Gómez García 2024-01-09 02:45:44 +01:00
parent 5c6ed274c8
commit 6ae18f4a58
No known key found for this signature in database
GPG Key ID: DD1ABF20724CDA23
45 changed files with 500 additions and 508 deletions

View File

@ -168,7 +168,7 @@ class Dispatcher(View):
logger.debug('Path: %s', full_path)
logger.debug('Error: %s', e)
log.logOperation(handler, 400, log.LogLevel.ERROR)
log.log_operation(handler, 400, log.LogLevel.ERROR)
return http.HttpResponseBadRequest(
f'Invalid parameters invoking {full_path}: {e}',
content_type="text/plain",
@ -178,13 +178,13 @@ class Dispatcher(View):
for n in ['get', 'post', 'put', 'delete']:
if hasattr(handler, n):
allowedMethods.append(n)
log.logOperation(handler, 405, log.LogLevel.ERROR)
log.log_operation(handler, 405, log.LogLevel.ERROR)
return http.HttpResponseNotAllowed(allowedMethods, content_type="text/plain")
except AccessDenied:
log.logOperation(handler, 403, log.LogLevel.ERROR)
log.log_operation(handler, 403, log.LogLevel.ERROR)
return http.HttpResponseForbidden('access denied', content_type="text/plain")
except Exception:
log.logOperation(handler, 500, log.LogLevel.ERROR)
log.log_operation(handler, 500, log.LogLevel.ERROR)
logger.exception('error accessing attribute')
logger.debug('Getting attribute %s for %s', http_method, full_path)
return http.HttpResponseServerError('Unexcepected error', content_type="text/plain")
@ -202,28 +202,28 @@ class Dispatcher(View):
# Log de operation on the audit log for admin
# Exceptiol will also be logged, but with ERROR level
log.logOperation(handler, response.status_code, log.LogLevel.INFO)
log.log_operation(handler, response.status_code, log.LogLevel.INFO)
return response
except RequestError as e:
log.logOperation(handler, 400, log.LogLevel.ERROR)
log.log_operation(handler, 400, log.LogLevel.ERROR)
return http.HttpResponseBadRequest(str(e), content_type="text/plain")
except ResponseError as e:
log.logOperation(handler, 500, log.LogLevel.ERROR)
log.log_operation(handler, 500, log.LogLevel.ERROR)
return http.HttpResponseServerError(str(e), content_type="text/plain")
except NotSupportedError as e:
log.logOperation(handler, 501, log.LogLevel.ERROR)
log.log_operation(handler, 501, log.LogLevel.ERROR)
return http.HttpResponseBadRequest(str(e), content_type="text/plain")
except AccessDenied as e:
log.logOperation(handler, 403, log.LogLevel.ERROR)
log.log_operation(handler, 403, log.LogLevel.ERROR)
return http.HttpResponseForbidden(str(e), content_type="text/plain")
except NotFound as e:
log.logOperation(handler, 404, log.LogLevel.ERROR)
log.log_operation(handler, 404, log.LogLevel.ERROR)
return http.HttpResponseNotFound(str(e), content_type="text/plain")
except HandlerError as e:
log.logOperation(handler, 500, log.LogLevel.ERROR)
log.log_operation(handler, 500, log.LogLevel.ERROR)
return http.HttpResponseBadRequest(str(e), content_type="text/plain")
except Exception as e:
log.logOperation(handler, 500, log.LogLevel.ERROR)
log.log_operation(handler, 500, log.LogLevel.ERROR)
# Get ecxeption backtrace
trace_back = traceback.format_exc()
logger.error('Exception processing request: %s', full_path)

View File

@ -146,7 +146,7 @@ class Handler:
if self.needs_staff and not self.is_staff_member():
raise AccessDenied()
try:
self._user = self.getUser()
self._user = self.get_user()
except Exception as e:
# Maybe the user was deleted, so access is denied
raise AccessDenied() from e
@ -166,7 +166,7 @@ class Handler:
"""
return self._headers.get(headerName)
def addHeader(self, header: str, value: str) -> None:
def add_header(self, header: str, value: str) -> None:
"""
Inserts a new header inside the headers list
:param header: name of header to insert
@ -174,7 +174,7 @@ class Handler:
"""
self._headers[header] = value
def removeHeader(self, header: str) -> None:
def delete_header(self, header: str) -> None:
"""
Removes an specific header from the headers list
:param header: Name of header to remove
@ -206,14 +206,14 @@ class Handler:
return self._args
# Auth related
def getAuthToken(self) -> typing.Optional[str]:
def get_auth_token(self) -> typing.Optional[str]:
"""
Returns the authentication token for this REST request
"""
return self._authToken
@staticmethod
def storeSessionAuthdata(
def set_rest_auth(
session: SessionBase,
id_auth: int,
username: str,
@ -251,7 +251,7 @@ class Handler:
'staff_member': staff_member,
}
def genAuthToken(
def gen_auth_token(
self,
id_auth: int,
username: str,
@ -272,7 +272,7 @@ class Handler:
:param staf_member: If user is considered staff member or not
"""
session = SessionStore()
Handler.storeSessionAuthdata(
Handler.set_rest_auth(
session,
id_auth,
username,
@ -289,7 +289,7 @@ class Handler:
return self._authToken
def cleanAuthToken(self) -> None:
def clear_auth_token(self) -> None:
"""
Cleans up the authentication token
"""
@ -299,7 +299,7 @@ class Handler:
self._session = None
# Session related (from auth token)
def getValue(self, key: str) -> typing.Any:
def recover_value(self, key: str) -> typing.Any:
"""
Get REST session related value for a key
"""
@ -313,7 +313,7 @@ class Handler:
except Exception:
return None
def setValue(self, key: str, value: typing.Any) -> None:
def store_value(self, key: str, value: typing.Any) -> None:
"""
Set a session key value
"""
@ -331,7 +331,7 @@ class Handler:
'Got an exception setting session value %s to %s', key, value
)
def validSource(self) -> bool:
def valid_source(self) -> bool:
try:
return net.contains(
GlobalConfig.ADMIN_TRUSTED_SOURCES.get(True), self._request.ip
@ -348,21 +348,21 @@ class Handler:
"""
True if user of this REST request is administrator and SOURCE is valid admint trusted sources
"""
return bool(self.getValue('is_admin')) and self.validSource()
return bool(self.recover_value('is_admin')) and self.valid_source()
def is_staff_member(self) -> bool:
"""
True if user of this REST request is member of staff
"""
return bool(self.getValue('staff_member')) and self.validSource()
return bool(self.recover_value('staff_member')) and self.valid_source()
def getUser(self) -> 'User':
def get_user(self) -> 'User':
"""
If user is staff member, returns his Associated user on auth
"""
logger.debug('REST : %s', self._session)
authId = self.getValue('auth')
username = self.getValue('username')
authId = self.recover_value('auth')
username = self.recover_value('username')
# Maybe it's root user??
if (
GlobalConfig.SUPER_USER_ALLOW_WEBACCESS.getBool(True)
@ -373,7 +373,7 @@ class Handler:
return Authenticator.objects.get(pk=authId).users.get(name=username)
def getParam(self, *names: str) -> str:
def get_param(self, *names: str) -> str:
"""
Returns the first parameter found in the parameters (_params) list

View File

@ -55,7 +55,7 @@ UUID_REPLACER = (
)
def replacePath(path: str) -> str:
def replace_path(path: str) -> str:
"""Replaces uuids in path with names
All paths are in the form .../type/uuid/...
"""
@ -71,7 +71,7 @@ def replacePath(path: str) -> str:
return path
def logOperation(
def log_operation(
handler: typing.Optional['Handler'], response_code: int, level: LogLevel = LogLevel.INFO
):
"""
@ -88,7 +88,7 @@ def logOperation(
):
return
path = replacePath(path)
path = replace_path(path)
username = handler.request.user.pretty_name if handler.request.user else 'Unknown'
log(

View File

@ -82,8 +82,8 @@ class Accounts(ModelHandler):
'permission': permissions.effective_permissions(self._user, item),
}
def getGui(self, type_: str) -> list[typing.Any]:
return self.addDefaultFields([], ['name', 'comments', 'tags'])
def get_gui(self, type_: str) -> list[typing.Any]:
return self.add_default_fields([], ['name', 'comments', 'tags'])
def timemark(self, item: 'Model') -> typing.Any:
item = ensure.is_instance(item, Account)
@ -93,5 +93,5 @@ class Accounts(ModelHandler):
def clear(self, item: 'Model') -> typing.Any:
item = ensure.is_instance(item, Account)
self.ensureAccess(item, uds.core.types.permissions.PermissionType.MANAGEMENT)
self.ensure_has_access(item, uds.core.types.permissions.PermissionType.MANAGEMENT)
return item.usages.filter(user_service=None).delete()

View File

@ -77,7 +77,7 @@ class AccountsUsage(DetailHandler): # pylint: disable=too-many-public-methods
return retVal
def getItems(self, parent: 'Model', item: typing.Optional[str]):
def get_items(self, parent: 'Model', item: typing.Optional[str]):
parent = ensure.is_instance(parent, Account)
# Check what kind of access do we have to parent provider
perm = permissions.effective_permissions(self._user, parent)
@ -88,9 +88,9 @@ class AccountsUsage(DetailHandler): # pylint: disable=too-many-public-methods
return AccountsUsage.usageToDict(k, perm)
except Exception:
logger.exception('itemId %s', item)
raise self.invalidItemException()
raise self.invalid_item_response()
def getFields(self, parent: 'Model') -> list[typing.Any]:
def get_fields(self, parent: 'Model') -> list[typing.Any]:
return [
{'pool_name': {'title': _('Pool name')}},
{'user_name': {'title': _('User name')}},
@ -101,13 +101,13 @@ class AccountsUsage(DetailHandler): # pylint: disable=too-many-public-methods
{'elapsed_timemark': {'title': _('Elapsed timemark')}},
]
def getRowStyle(self, parent: 'Model') -> dict[str, typing.Any]:
def get_row_style(self, parent: 'Model') -> dict[str, typing.Any]:
return {'field': 'running', 'prefix': 'row-running-'}
def saveItem(self, parent: 'Model', item: typing.Optional[str]) -> None:
def save_item(self, parent: 'Model', item: typing.Optional[str]) -> None:
raise RequestError('Accounts usage cannot be edited')
def deleteItem(self, parent: 'Model', item: str) -> None:
def delete_item(self, parent: 'Model', item: str) -> None:
parent = ensure.is_instance(parent, Account)
logger.debug('Deleting account usage %s from %s', item, parent)
try:
@ -115,9 +115,9 @@ class AccountsUsage(DetailHandler): # pylint: disable=too-many-public-methods
usage.delete()
except Exception:
logger.exception('Exception')
raise self.invalidItemException()
raise self.invalid_item_response()
def getTitle(self, parent: 'Model') -> str:
def get_title(self, parent: 'Model') -> str:
parent = ensure.is_instance(parent, Account)
try:
return _('Usages of {0}').format(parent.name)

View File

@ -97,7 +97,7 @@ class ActorTokens(ModelHandler):
if len(self._args) != 1:
raise RequestError('Delete need one and only one argument')
self.ensureAccess(
self.ensure_has_access(
self.model(), permissions.PermissionType.ALL, root=True
) # Must have write permissions to delete

View File

@ -84,33 +84,33 @@ class Authenticators(ModelHandler):
def enum_types(self) -> collections.abc.Iterable[type[auths.Authenticator]]:
return auths.factory().providers().values()
def typeInfo(self, type_: type['Module']) -> dict[str, typing.Any]:
def type_info(self, type_: type['Module']) -> dict[str, typing.Any]:
if issubclass(type_, auths.Authenticator):
return {
'canSearchUsers': type_.search_users != auths.Authenticator.search_users, # type: ignore
'canSearchGroups': type_.search_groups != auths.Authenticator.search_groups, # type: ignore
'needsPassword': type_.needsPassword,
'userNameLabel': _(type_.userNameLabel),
'groupNameLabel': _(type_.groupNameLabel),
'passwordLabel': _(type_.passwordLabel),
'canCreateUsers': type_.create_user != auths.Authenticator.create_user, # type: ignore
'isExternal': type_.isExternalSource,
'supportsMFA': type_.provides_mfa(),
'search_users_supported': type_.search_users != auths.Authenticator.search_users, # type: ignore
'search_groups_supported': type_.search_groups != auths.Authenticator.search_groups, # type: ignore
'needs_password': type_.needs_password,
'label_username': _(type_.label_username),
'label_groupname': _(type_.label_groupname),
'label_password': _(type_.label_password),
'create_users_supported': type_.create_user != auths.Authenticator.create_user, # type: ignore
'is_external': type_.isExternalSource,
'mfa_supported': type_.provides_mfa(),
}
# Not of my type
return {}
def getGui(self, type_: str) -> list[typing.Any]:
def get_gui(self, type_: str) -> list[typing.Any]:
try:
authType = auths.factory().lookup(type_)
if authType:
# Create a new instance of the authenticator to access to its GUI
authInstance = authType(Environment.getTempEnv(), None)
field = self.addDefaultFields(
field = self.add_default_fields(
authInstance.guiDescription(),
['name', 'comments', 'tags', 'priority', 'small_name', 'networks'],
)
self.addField(
self.add_field(
field,
{
'name': 'state',
@ -131,7 +131,7 @@ class Authenticators(ModelHandler):
)
# If supports mfa, add MFA provider selector field
if authType.provides_mfa():
self.addField(
self.add_field(
field,
{
'name': 'mfa_id',
@ -170,11 +170,11 @@ class Authenticators(ModelHandler):
'users_count': item.users.count(),
'type': type_.get_type(),
'type_name': type_.name(),
'type_info': self.typeInfo(type_),
'type_info': self.type_info(type_),
'permission': permissions.effective_permissions(self._user, item),
}
def afterSave(self, item: 'Model') -> None:
def post_save(self, item: 'Model') -> None:
item = ensure.is_instance(item, Authenticator)
try:
networks = self._params['networks']
@ -189,11 +189,11 @@ class Authenticators(ModelHandler):
# Custom "search" method
def search(self, item: 'Model') -> list[dict]:
item = ensure.is_instance(item, Authenticator)
self.ensureAccess(item, types.permissions.PermissionType.READ)
self.ensure_has_access(item, types.permissions.PermissionType.READ)
try:
type_ = self._params['type']
if type_ not in ('user', 'group'):
raise self.invalidRequestException()
raise self.invalid_request_response()
term = self._params['term']
@ -207,7 +207,7 @@ class Authenticators(ModelHandler):
or (auth.search_groups != auths.Authenticator.search_groups) # type: ignore
)
if canDoSearch is False:
raise self.notSupported()
raise self.not_supported_response()
if type_ == 'user':
return list(auth.search_users(term))[:limit]
@ -220,7 +220,7 @@ class Authenticators(ModelHandler):
def test(self, type_: str):
authType = auths.factory().lookup(type_)
if not authType:
raise self.invalidRequestException(f'Invalid type: {type_}')
raise self.invalid_request_response(f'Invalid type: {type_}')
dct = self._params.copy()
dct['_request'] = self._request
@ -229,7 +229,7 @@ class Authenticators(ModelHandler):
return self.success()
return res[1]
def beforeSave(
def pre_save(
self, fields: dict[str, typing.Any]
) -> None: # pylint: disable=too-many-branches,too-many-statements
logger.debug(self._params)
@ -246,11 +246,11 @@ class Authenticators(ModelHandler):
fields['small_name'] = fields['small_name'].strip().replace(' ', '_')
# And ensure small_name chars are valid [a-zA-Z0-9:-]+
if fields['small_name'] and not re.match(r'^[a-zA-Z0-9:.-]+$', fields['small_name']):
raise self.invalidRequestException(
raise self.invalid_request_response(
typing.cast(str, _('Label must contain only letters, numbers, or symbols: - : .'))
)
def deleteItem(self, item: 'Model'):
def delete_item(self, item: 'Model'):
# For every user, remove assigned services (mark them for removal)
item = ensure.is_instance(item, Authenticator)

View File

@ -79,7 +79,7 @@ class CalendarRules(DetailHandler): # pylint: disable=too-many-public-methods
return retVal
def getItems(self, parent: 'Model', item: typing.Optional[str]) -> typing.Any:
def get_items(self, parent: 'Model', item: typing.Optional[str]) -> typing.Any:
parent = ensure.is_instance(parent, Calendar)
# Check what kind of access do we have to parent provider
perm = permissions.effective_permissions(self._user, parent)
@ -90,9 +90,9 @@ class CalendarRules(DetailHandler): # pylint: disable=too-many-public-methods
return CalendarRules.ruleToDict(k, perm)
except Exception as e:
logger.exception('itemId %s', item)
raise self.invalidItemException() from e
raise self.invalid_item_response() from e
def getFields(self, parent: 'Model') -> list[typing.Any]:
def get_fields(self, parent: 'Model') -> list[typing.Any]:
parent = ensure.is_instance(parent, Calendar)
return [
@ -111,7 +111,7 @@ class CalendarRules(DetailHandler): # pylint: disable=too-many-public-methods
{'comments': {'title': _('Comments')}},
]
def saveItem(self, parent: 'Model', item: typing.Optional[str]) -> None:
def save_item(self, parent: 'Model', item: typing.Optional[str]) -> None:
parent = ensure.is_instance(parent, Calendar)
# Extract item db fields
@ -131,7 +131,7 @@ class CalendarRules(DetailHandler): # pylint: disable=too-many-public-methods
)
if int(fields['interval']) < 1:
raise self.invalidItemException('Repeat must be greater than zero')
raise self.invalid_item_response('Repeat must be greater than zero')
# Convert timestamps to datetimes
fields['start'] = datetime.datetime.fromtimestamp(fields['start'])
@ -147,14 +147,14 @@ class CalendarRules(DetailHandler): # pylint: disable=too-many-public-methods
calRule.__dict__.update(fields)
calRule.save()
except CalendarRule.DoesNotExist:
raise self.invalidItemException() from None
raise self.invalid_item_response() from None
except IntegrityError as e: # Duplicate key probably
raise RequestError(_('Element already exists (duplicate key error)')) from e
except Exception as e:
logger.exception('Saving calendar')
raise RequestError(f'incorrect invocation to PUT: {e}') from e
def deleteItem(self, parent: 'Model', item: str) -> None:
def delete_item(self, parent: 'Model', item: str) -> None:
parent = ensure.is_instance(parent, Calendar)
logger.debug('Deleting rule %s from %s', item, parent)
try:
@ -164,9 +164,9 @@ class CalendarRules(DetailHandler): # pylint: disable=too-many-public-methods
calRule.delete()
except Exception as e:
logger.exception('Exception')
raise self.invalidItemException() from e
raise self.invalid_item_response() from e
def getTitle(self, parent: 'Model') -> str:
def get_title(self, parent: 'Model') -> str:
parent = ensure.is_instance(parent, Calendar)
try:
return _('Rules of {0}').format(parent.name)

View File

@ -92,5 +92,5 @@ class Calendars(ModelHandler):
'permission': permissions.effective_permissions(self._user, item),
}
def getGui(self, type_: str) -> list[typing.Any]:
return self.addDefaultFields([], ['name', 'comments', 'tags'])
def get_gui(self, type_: str) -> list[typing.Any]:
return self.add_default_fields([], ['name', 'comments', 'tags'])

View File

@ -151,7 +151,7 @@ class Connection(Handler):
transport,
transportInstance,
) = res # pylint: disable=unused-variable
password = CryptoManager().symmetric_decrypt(self.getValue('password'), scrambler)
password = CryptoManager().symmetric_decrypt(self.recover_value('password'), scrambler)
userService.setConnectionSource(
types.connections.ConnectionSource(self._request.ip, hostname)

View File

@ -73,21 +73,21 @@ class Images(ModelHandler):
{'size': {'title': _('Size')}},
]
def beforeSave(self, fields: dict[str, typing.Any]) -> None:
def pre_save(self, fields: dict[str, typing.Any]) -> None:
fields['image'] = fields['data']
del fields['data']
#fields['data'] = Image.prepareForDb(Image.decode64(fields['data']))[2]
def afterSave(self, item: 'Model') -> None:
def post_save(self, item: 'Model') -> None:
item = ensure.is_instance(item, Image)
# Updates the thumbnail and re-saves it
logger.debug('After save: item = %s', item)
#item.updateThumbnail()
#item.save()
def getGui(self, type_: str) -> list[typing.Any]:
return self.addField(
self.addDefaultFields([], ['name']),
def get_gui(self, type_: str) -> list[typing.Any]:
return self.add_field(
self.add_default_fields([], ['name']),
{
'name': 'data',
'value': '',

View File

@ -160,8 +160,8 @@ class Login(Handler):
if GlobalConfig.SUPER_USER_LOGIN.get(True) == username and CryptoManager().check_hash(
password, GlobalConfig.SUPER_USER_PASS.get(True)
):
self.genAuthToken(-1, username, password, locale, platform, True, True, scrambler)
return Login.result(result='ok', token=self.getAuthToken())
self.gen_auth_token(-1, username, password, locale, platform, True, True, scrambler)
return Login.result(result='ok', token=self.get_auth_token())
return Login.result(error='Invalid credentials')
# Will raise an exception if no auth found
@ -186,7 +186,7 @@ class Login(Handler):
return Login.result(error='Invalid credentials')
return Login.result(
result='ok',
token=self.genAuthToken(
token=self.gen_auth_token(
auth.id,
authResult.user.name,
password,
@ -216,7 +216,7 @@ class Logout(Handler):
def get(self):
# Remove auth token
self.cleanAuthToken()
self.clear_auth_token()
return {'result': 'ok'}
def post(self):

View File

@ -158,8 +158,8 @@ class MetaPools(ModelHandler):
return val
# Gui related
def getGui(self, type_: str) -> list[typing.Any]:
localGUI = self.addDefaultFields([], ['name', 'comments', 'tags'])
def get_gui(self, type_: str) -> list[typing.Any]:
localGUI = self.add_default_fields([], ['name', 'comments', 'tags'])
for field in [
{
@ -250,11 +250,11 @@ class MetaPools(ModelHandler):
'tab': types.ui.Tab.DISPLAY,
},
]:
self.addField(localGUI, field)
self.add_field(localGUI, field)
return localGUI
def beforeSave(self, fields: dict[str, typing.Any]) -> None:
def pre_save(self, fields: dict[str, typing.Any]) -> None:
# logger.debug(self._params)
try:
# **** IMAGE ***
@ -286,13 +286,13 @@ class MetaPools(ModelHandler):
logger.debug('Fields: %s', fields)
def deleteItem(self, item: 'Model') -> None:
def delete_item(self, item: 'Model') -> None:
item = ensure.is_instance(item, MetaPool)
item.delete()
# Set fallback status
def setFallbackAccess(self, item: MetaPool):
self.ensureAccess(item, types.permissions.PermissionType.MANAGEMENT)
self.ensure_has_access(item, types.permissions.PermissionType.MANAGEMENT)
fallback = self._params.get('fallbackAccess', 'ALLOW')
logger.debug('Setting fallback of %s to %s', item.name, fallback)

View File

@ -72,7 +72,7 @@ class MetaServicesPool(DetailHandler):
'user_services_in_preparation': item.pool.userServices.filter(state=State.PREPARING).count(),
}
def getItems(self, parent: 'Model', item: typing.Optional[str]):
def get_items(self, parent: 'Model', item: typing.Optional[str]):
parent = ensure.is_instance(parent, models.MetaPool)
try:
if not item:
@ -81,19 +81,19 @@ class MetaServicesPool(DetailHandler):
return MetaServicesPool.as_dict(i)
except Exception:
logger.exception('err: %s', item)
raise self.invalidItemException()
raise self.invalid_item_response()
def getTitle(self, parent: 'Model') -> str:
def get_title(self, parent: 'Model') -> str:
return _('Service pools')
def getFields(self, parent: 'Model') -> list[typing.Any]:
def get_fields(self, parent: 'Model') -> list[typing.Any]:
return [
{'priority': {'title': _('Priority'), 'type': 'numeric', 'width': '6em'}},
{'name': {'title': _('Service Pool name')}},
{'enabled': {'title': _('Enabled')}},
]
def saveItem(self, parent: 'Model', item: typing.Optional[str]):
def save_item(self, parent: 'Model', item: typing.Optional[str]):
parent = ensure.is_instance(parent, models.MetaPool)
# If already exists
uuid = process_uuid(item) if item else None
@ -122,7 +122,7 @@ class MetaServicesPool(DetailHandler):
return self.success()
def deleteItem(self, parent: 'Model', item: str):
def delete_item(self, parent: 'Model', item: str):
parent = ensure.is_instance(parent, models.MetaPool)
member = parent.members.get(uuid=process_uuid(self._args[0]))
logStr = "Removed meta pool member {} by {}".format(member.pool.name, self._user.pretty_name)
@ -138,12 +138,12 @@ class MetaAssignedService(DetailHandler):
"""
@staticmethod
def itemToDict(
def item_as_dict(
metaPool: 'models.MetaPool',
item: 'models.UserService',
props: typing.Optional[dict[str, typing.Any]],
) -> dict[str, typing.Any]:
element = AssignedService.itemToDict(item, props, False)
element = AssignedService.item_as_dict(item, props, False)
element['pool_id'] = item.deployed_service.uuid
element['pool_name'] = item.deployed_service.name
return element
@ -160,9 +160,9 @@ class MetaAssignedService(DetailHandler):
deployed_service__in=[i.pool for i in metaPool.members.all()],
)[0]
except Exception:
raise self.invalidItemException()
raise self.invalid_item_response()
def getItems(self, parent: 'Model', item: typing.Optional[str]):
def get_items(self, parent: 'Model', item: typing.Optional[str]):
parent = ensure.is_instance(parent, models.MetaPool)
def assignedUserServicesForPools() -> (
typing.Generator[
@ -189,10 +189,10 @@ class MetaAssignedService(DetailHandler):
result = {}
for k, props in assignedUserServicesForPools():
result[k.uuid] = MetaAssignedService.itemToDict(parent, k, props)
result[k.uuid] = MetaAssignedService.item_as_dict(parent, k, props)
return list(result.values())
return MetaAssignedService.itemToDict(
return MetaAssignedService.item_as_dict(
parent,
self._getAssignedService(parent, item),
props={
@ -203,14 +203,14 @@ class MetaAssignedService(DetailHandler):
},
)
except Exception:
logger.exception('getItems')
raise self.invalidItemException()
logger.exception('get_items')
raise self.invalid_item_response()
def getTitle(self, parent: 'Model') -> str:
def get_title(self, parent: 'Model') -> str:
parent = ensure.is_instance(parent, models.MetaPool)
return _('Assigned services')
def getFields(self, parent: 'Model') -> list[typing.Any]:
def get_fields(self, parent: 'Model') -> list[typing.Any]:
parent = ensure.is_instance(parent, models.MetaPool)
return [
{'creation_date': {'title': _('Creation date'), 'type': 'datetime'}},
@ -232,20 +232,20 @@ class MetaAssignedService(DetailHandler):
{'actor_version': {'title': _('Actor version')}},
]
def getRowStyle(self, parent: 'Model') -> dict[str, typing.Any]:
def get_row_style(self, parent: 'Model') -> dict[str, typing.Any]:
parent = ensure.is_instance(parent, models.MetaPool)
return {'field': 'state', 'prefix': 'row-state-'}
def getLogs(self, parent: 'Model', item: str) -> list[typing.Any]:
def get_logs(self, parent: 'Model', item: str) -> list[typing.Any]:
parent = ensure.is_instance(parent, models.MetaPool)
try:
asignedService = self._getAssignedService(parent, item)
logger.debug('Getting logs for %s', asignedService)
return log.get_logs(asignedService)
except Exception:
raise self.invalidItemException()
raise self.invalid_item_response()
def deleteItem(self, parent: 'Model', item: str) -> None:
def delete_item(self, parent: 'Model', item: str) -> None:
parent = ensure.is_instance(parent, models.MetaPool)
userService = self._getAssignedService(parent, item)
@ -263,17 +263,17 @@ class MetaAssignedService(DetailHandler):
elif userService.state == State.PREPARING:
userService.cancel()
elif userService.state == State.REMOVABLE:
raise self.invalidItemException(_('Item already being removed'))
raise self.invalid_item_response(_('Item already being removed'))
else:
raise self.invalidItemException(_('Item is not removable'))
raise self.invalid_item_response(_('Item is not removable'))
log.log(parent, log.LogLevel.INFO, logStr, log.LogSource.ADMIN)
# Only owner is allowed to change right now
def saveItem(self, parent: 'Model', item: typing.Optional[str]):
def save_item(self, parent: 'Model', item: typing.Optional[str]):
parent = ensure.is_instance(parent, models.MetaPool)
if item is None:
raise self.invalidItemException()
raise self.invalid_item_response()
fields = self.fields_from_params(['auth_id', 'user_id'])
service = self._getAssignedService(parent, item)
@ -291,7 +291,7 @@ class MetaAssignedService(DetailHandler):
.count()
> 0
):
raise self.invalidResponseException(
raise self.invalid_response_response(
'There is already another user service assigned to {}'.format(user.pretty_name)
)

View File

@ -66,17 +66,17 @@ class MFA(ModelHandler):
def enum_types(self) -> collections.abc.Iterable[type[mfas.MFA]]:
return mfas.factory().providers().values()
def getGui(self, type_: str) -> list[typing.Any]:
def get_gui(self, type_: str) -> list[typing.Any]:
mfaType = mfas.factory().lookup(type_)
if not mfaType:
raise self.invalidItemException()
raise self.invalid_item_response()
# Create a temporal instance to get the gui
mfa = mfaType(Environment.getTempEnv(), None)
localGui = self.addDefaultFields(mfa.guiDescription(), ['name', 'comments', 'tags'])
self.addField(
localGui = self.add_default_fields(mfa.guiDescription(), ['name', 'comments', 'tags'])
self.add_field(
localGui,
{
'name': 'remember_device',
@ -88,7 +88,7 @@ class MFA(ModelHandler):
'order': 111,
},
)
self.addField(
self.add_field(
localGui,
{
'name': 'validity',

View File

@ -87,9 +87,9 @@ class Networks(ModelHandler):
{'tags': {'title': _('tags'), 'visible': False}},
]
def getGui(self, type_: str) -> list[typing.Any]:
return self.addField(
self.addDefaultFields([], ['name', 'tags']),
def get_gui(self, type_: str) -> list[typing.Any]:
return self.add_field(
self.add_default_fields([], ['name', 'tags']),
{
'name': 'net_string',
'value': '',

View File

@ -78,15 +78,15 @@ class Notifiers(ModelHandler):
def enum_types(self) -> collections.abc.Iterable[type[messaging.Notifier]]:
return messaging.factory().providers().values()
def getGui(self, type_: str) -> list[typing.Any]:
def get_gui(self, type_: str) -> list[typing.Any]:
notifierType = messaging.factory().lookup(type_)
if not notifierType:
raise self.invalidItemException()
raise self.invalid_item_response()
notifier = notifierType(Environment.getTempEnv(), None)
localGui = self.addDefaultFields(
localGui = self.add_default_fields(
notifier.guiDescription(), ['name', 'comments', 'tags']
)
@ -108,7 +108,7 @@ class Notifiers(ModelHandler):
'default': True,
}
]:
self.addField(localGui, field)
self.add_field(localGui, field)
return localGui

View File

@ -65,7 +65,7 @@ class AccessCalendars(DetailHandler):
'priority': item.priority,
}
def getItems(self, parent: 'Model', item: typing.Optional[str]):
def get_items(self, parent: 'Model', item: typing.Optional[str]):
parent = ensure.is_instance(parent, ServicePool)
try:
if not item:
@ -75,19 +75,19 @@ class AccessCalendars(DetailHandler):
)
except Exception as e:
logger.exception('err: %s', item)
raise self.invalidItemException() from e
raise self.invalid_item_response() from e
def getTitle(self, parent: 'Model'):
def get_title(self, parent: 'Model'):
return _('Access restrictions by calendar')
def getFields(self, parent: 'Model') -> list[typing.Any]:
def get_fields(self, parent: 'Model') -> list[typing.Any]:
return [
{'priority': {'title': _('Priority'), 'type': 'numeric', 'width': '6em'}},
{'calendar': {'title': _('Calendar')}},
{'access': {'title': _('Access')}},
]
def saveItem(self, parent: 'Model', item: typing.Optional[str]) -> None:
def save_item(self, parent: 'Model', item: typing.Optional[str]) -> None:
parent = ensure.is_instance(parent, ServicePool)
# If already exists
uuid = process_uuid(item) if item is not None else None
@ -100,7 +100,7 @@ class AccessCalendars(DetailHandler):
if access not in (ALLOW, DENY):
raise Exception()
except Exception as e:
raise self.invalidRequestException(
raise self.invalid_request_response(
_('Invalid parameters on request')
) from e
priority = int(self._params['priority'])
@ -124,7 +124,7 @@ class AccessCalendars(DetailHandler):
log.LogSource.ADMIN,
)
def deleteItem(self, parent: 'Model', item: str) -> None:
def delete_item(self, parent: 'Model', item: str) -> None:
parent = ensure.is_instance(parent, ServicePool)
calendarAccess = parent.calendarAccess.get(uuid=process_uuid(self._args[0]))
logStr = f'Removed access calendar {calendarAccess.calendar.name} by {self._user.pretty_name}'
@ -160,7 +160,7 @@ class ActionsCalendars(DetailHandler):
'lastExecution': item.last_execution,
}
def getItems(self, parent: 'Model', item: typing.Optional[str]):
def get_items(self, parent: 'Model', item: typing.Optional[str]):
parent = ensure.is_instance(parent, ServicePool)
try:
if item is None:
@ -170,12 +170,12 @@ class ActionsCalendars(DetailHandler):
i = parent.calendaraction_set.get(uuid=process_uuid(item))
return ActionsCalendars.as_dict(i)
except Exception as e:
raise self.invalidItemException() from e
raise self.invalid_item_response() from e
def getTitle(self, parent: 'Model'):
def get_title(self, parent: 'Model'):
return _('Scheduled actions')
def getFields(self, parent: 'Model') -> list[typing.Any]:
def get_fields(self, parent: 'Model') -> list[typing.Any]:
return [
{'calendar': {'title': _('Calendar')}},
{'actionDescription': {'title': _('Action')}},
@ -186,7 +186,7 @@ class ActionsCalendars(DetailHandler):
{'lastExecution': {'title': _('Last execution'), 'type': 'datetime'}},
]
def saveItem(self, parent: 'Model', item: typing.Optional[str]) -> None:
def save_item(self, parent: 'Model', item: typing.Optional[str]) -> None:
parent = ensure.is_instance(parent, ServicePool)
# If already exists
uuid = process_uuid(item) if item is not None else None
@ -194,7 +194,7 @@ class ActionsCalendars(DetailHandler):
calendar = Calendar.objects.get(uuid=process_uuid(self._params['calendarId']))
action = self._params['action'].upper()
if action not in CALENDAR_ACTION_DICT:
raise self.invalidRequestException()
raise self.invalid_request_response()
eventsOffset = int(self._params['eventsOffset'])
atStart = self._params['atStart'] not in ('false', False, '0', 0)
params = json.dumps(self._params['params'])
@ -227,7 +227,7 @@ class ActionsCalendars(DetailHandler):
log.log(parent, log.LogLevel.INFO, logStr, log.LogSource.ADMIN)
def deleteItem(self, parent: 'Model', item: str) -> None:
def delete_item(self, parent: 'Model', item: str) -> None:
parent = ensure.is_instance(parent, ServicePool)
calendarAction = CalendarAction.objects.get(uuid=process_uuid(self._args[0]))
logStr = (
@ -246,7 +246,7 @@ class ActionsCalendars(DetailHandler):
logger.debug('Launching action')
uuid = process_uuid(item)
calendarAction: CalendarAction = CalendarAction.objects.get(uuid=uuid)
self.ensureAccess(calendarAction, types.permissions.PermissionType.MANAGEMENT)
self.ensure_has_access(calendarAction, types.permissions.PermissionType.MANAGEMENT)
logStr = (
f'Launched scheduled action "{calendarAction.calendar.name},'

View File

@ -82,7 +82,7 @@ class OsManagers(ModelHandler):
item = ensure.is_instance(item, OSManager)
return self.osmToDict(item)
def checkDelete(self, item: 'Model') -> None:
def validate_delete(self, item: 'Model') -> None:
item = ensure.is_instance(item, OSManager)
# Only can delete if no ServicePools attached
if item.deployedServices.count() > 0:
@ -95,7 +95,7 @@ class OsManagers(ModelHandler):
return osmanagers.factory().providers().values()
# Gui related
def getGui(self, type_: str) -> list[typing.Any]:
def get_gui(self, type_: str) -> list[typing.Any]:
try:
osmanagerType = osmanagers.factory().lookup(type_)
@ -104,7 +104,7 @@ class OsManagers(ModelHandler):
osmanager = osmanagerType(Environment.getTempEnv(), None)
return self.addDefaultFields(
return self.add_default_fields(
osmanager.guiDescription(), # type: ignore # may raise an exception if lookup fails
['name', 'comments', 'tags'],
)

View File

@ -112,7 +112,7 @@ class Providers(ModelHandler):
'permission': permissions.effective_permissions(self._user, item),
}
def checkDelete(self, item: 'Model') -> None:
def validate_delete(self, item: 'Model') -> None:
item = ensure.is_instance(item, Provider)
if item.services.count() > 0:
raise RequestError(gettext('Can\'t delete providers with services'))
@ -122,11 +122,11 @@ class Providers(ModelHandler):
return services.factory().providers().values()
# Gui related
def getGui(self, type_: str) -> list[typing.Any]:
def get_gui(self, type_: str) -> list[typing.Any]:
providerType = services.factory().lookup(type_)
if providerType:
provider = providerType(Environment.getTempEnv(), None)
return self.addDefaultFields(provider.guiDescription(), ['name', 'comments', 'tags'])
return self.add_default_fields(provider.guiDescription(), ['name', 'comments', 'tags'])
raise NotFound('Type not found!')
def allservices(self) -> typing.Generator[dict, None, None]:
@ -147,8 +147,8 @@ class Providers(ModelHandler):
"""
try:
service = Service.objects.get(uuid=self._args[1])
self.ensureAccess(service.provider, uds.core.types.permissions.PermissionType.READ)
perm = self.getPermissions(service.provider)
self.ensure_has_access(service.provider, uds.core.types.permissions.PermissionType.READ)
perm = self.get_permissions(service.provider)
return DetailServices.serviceToDict(service, perm, True)
except Exception:
# logger.exception('Exception')
@ -160,7 +160,7 @@ class Providers(ModelHandler):
:param item:
"""
item = ensure.is_instance(item, Provider)
self.ensureAccess(item, uds.core.types.permissions.PermissionType.MANAGEMENT)
self.ensure_has_access(item, uds.core.types.permissions.PermissionType.MANAGEMENT)
item.maintenance_mode = not item.maintenance_mode
item.save()
return self.item_as_dict(item)

View File

@ -85,7 +85,7 @@ class Reports(model.BaseModelHandler):
break
if not found:
raise self.invalidRequestException('Invalid report uuid!')
raise self.invalid_request_response('Invalid report uuid!')
return found
@ -93,20 +93,20 @@ class Reports(model.BaseModelHandler):
logger.debug('method GET for %s, %s', self.__class__.__name__, self._args)
def error() -> typing.NoReturn:
raise self.invalidRequestException()
raise self.invalid_request_response()
return match(
self._args,
error,
((), lambda: list(self.getItems())),
((model.OVERVIEW,), lambda: list(self.getItems())),
((), lambda: list(self.get_items())),
((model.OVERVIEW,), lambda: list(self.get_items())),
(
(model.TABLEINFO,),
lambda: self.processTableFields(
lambda: self.process_table_fields(
str(self.table_title), self.table_fields, self.table_row_style
),
),
((model.GUI, '<report>'), lambda report: self.getGui(report)),
((model.GUI, '<report>'), lambda report: self.get_gui(report)),
)
def put(self):
@ -121,7 +121,7 @@ class Reports(model.BaseModelHandler):
)
if len(self._args) != 1:
raise self.invalidRequestException()
raise self.invalid_request_response()
report = self._findReport(self._args[0], self._params)
@ -139,15 +139,15 @@ class Reports(model.BaseModelHandler):
return data
except Exception as e:
logger.exception('Generating report')
raise self.invalidRequestException(str(e))
raise self.invalid_request_response(str(e))
# Gui related
def getGui(self, type_: str) -> list[typing.Any]:
def get_gui(self, type_: str) -> list[typing.Any]:
report = self._findReport(type_)
return sorted(report.guiDescription(), key=lambda f: f['gui']['order'])
# Returns the list of
def getItems(
def get_items(
self, *args, **kwargs
) -> typing.Generator[dict[str, typing.Any], None, None]:
for i in reports.availableReports:

View File

@ -95,7 +95,7 @@ class ServersTokens(ModelHandler):
if len(self._args) != 1:
raise RequestError('Delete need one and only one argument')
self.ensureAccess(
self.ensure_has_access(
self.model(), types.permissions.PermissionType.ALL, root=True
) # Must have write permissions to delete
@ -111,7 +111,7 @@ class ServersTokens(ModelHandler):
class ServersServers(DetailHandler):
custom_methods = ['maintenance']
def getItems(self, parent_: 'Model', item: typing.Optional[str]):
def get_items(self, parent_: 'Model', item: typing.Optional[str]):
parent = typing.cast('models.ServerGroup', parent_) # We will receive for sure
try:
multi = False
@ -139,16 +139,16 @@ class ServersServers(DetailHandler):
return res[0]
except Exception as e:
logger.exception('REST servers')
raise self.invalidItemException() from e
raise self.invalid_item_response() from e
def getTitle(self, parent: 'Model') -> str:
def get_title(self, parent: 'Model') -> str:
parent = ensure.is_instance(parent, models.ServerGroup)
try:
return _('Servers of {0}').format(parent.name)
except Exception:
return str(_('Servers'))
def getFields(self, parent: 'Model') -> list[typing.Any]:
def get_fields(self, parent: 'Model') -> list[typing.Any]:
parent = ensure.is_instance(parent, models.ServerGroup)
return [
{
@ -167,16 +167,16 @@ class ServersServers(DetailHandler):
},
]
def getRowStyle(self, parent: 'Model') -> dict[str, typing.Any]:
def get_row_style(self, parent: 'Model') -> dict[str, typing.Any]:
parent = ensure.is_instance(parent, models.ServerGroup)
return {'field': 'maintenance_mode', 'prefix': 'row-maintenance-'}
def getGui(self, parent: 'Model', forType: str = '') -> list[typing.Any]:
def get_gui(self, parent: 'Model', forType: str = '') -> list[typing.Any]:
parent = ensure.is_instance(parent, models.ServerGroup)
kind, subkind = parent.server_type, parent.subtype
title = _('of type') + f' {subkind.upper()} {kind.name.capitalize()}'
if kind == types.servers.ServerType.UNMANAGED:
return self.addField(
return self.add_field(
[],
[
{
@ -211,7 +211,7 @@ class ServersServers(DetailHandler):
],
)
else:
return self.addField(
return self.add_field(
[],
[
{
@ -235,7 +235,7 @@ class ServersServers(DetailHandler):
],
)
def saveItem(self, parent: 'Model', item: typing.Optional[str]) -> None:
def save_item(self, parent: 'Model', item: typing.Optional[str]) -> None:
parent = ensure.is_instance(parent, models.ServerGroup)
# Item is the uuid of the server to add
server: typing.Optional['models.Server'] = None # Avoid warning on reference before assignment
@ -263,21 +263,21 @@ class ServersServers(DetailHandler):
# Check server type is also SERVER
if server and server.type != types.servers.ServerType.SERVER:
logger.error('Server type for %s is not SERVER', server.host)
raise self.invalidRequestException() from None
raise self.invalid_request_response() from None
parent.servers.add(server)
except Exception:
raise self.invalidItemException() from None
raise self.invalid_item_response() from None
pass
else:
try:
server = models.Server.objects.get(uuid=process_uuid(item))
parent.servers.add(server)
except Exception:
raise self.invalidItemException() from None
raise self.invalid_item_response() from None
raise self.invalidRequestException() from None
raise self.invalid_request_response() from None
def deleteItem(self, parent: 'Model', item: str) -> None:
def delete_item(self, parent: 'Model', item: str) -> None:
parent = ensure.is_instance(parent, models.ServerGroup)
try:
server = models.Server.objects.get(uuid=process_uuid(item))
@ -287,7 +287,7 @@ class ServersServers(DetailHandler):
else:
parent.servers.remove(server) # Just remove reference
except Exception:
raise self.invalidItemException() from None
raise self.invalid_item_response() from None
# Custom methods
def maintenance(self, parent: 'Model', id: str) -> typing.Any:
@ -297,7 +297,7 @@ class ServersServers(DetailHandler):
:param item:
"""
item = models.Server.objects.get(uuid=process_uuid(id))
self.ensureAccess(item, types.permissions.PermissionType.MANAGEMENT)
self.ensure_has_access(item, types.permissions.PermissionType.MANAGEMENT)
item.maintenance_mode = not item.maintenance_mode
item.save()
return 'ok'
@ -316,7 +316,7 @@ class ServersGroups(ModelHandler):
path = 'servers'
name = 'groups'
save_fields = ['name', 'comments', 'type', 'tags'] # Subtype is appended on beforeSave
save_fields = ['name', 'comments', 'type', 'tags'] # Subtype is appended on pre_save
table_title = typing.cast(str, _('Servers Groups'))
table_fields = [
{'name': {'title': _('Name')}},
@ -334,7 +334,7 @@ class ServersGroups(ModelHandler):
).as_dict(group=gettext('Managed') if i.managed else gettext('Unmanaged'))
yield v
def getGui(self, type_: str) -> list[typing.Any]:
def get_gui(self, type_: str) -> list[typing.Any]:
if '@' not in type_: # If no subtype, use default
type_ += '@default'
kind, subkind = type_.split('@')[:2]
@ -343,8 +343,8 @@ class ServersGroups(ModelHandler):
elif kind == types.servers.ServerType.UNMANAGED.name:
kind = typing.cast(str, _('Unmanaged'))
title = _('of type') + f' {subkind.upper()} {kind}'
return self.addField(
self.addDefaultFields(
return self.add_field(
self.add_default_fields(
[],
['name', 'comments', 'tags'],
),
@ -362,12 +362,12 @@ class ServersGroups(ModelHandler):
],
)
def beforeSave(self, fields: dict[str, typing.Any]) -> None:
def pre_save(self, fields: dict[str, typing.Any]) -> None:
# Update type and subtype to correct values
type, subtype = fields['type'].split('@')
fields['type'] = types.servers.ServerType[type.upper()].value
fields['subtype'] = subtype
return super().beforeSave(fields)
return super().pre_save(fields)
def item_as_dict(self, item: 'Model') -> dict[str, typing.Any]:
item = ensure.is_instance(item, models.ServerGroup)
@ -383,12 +383,12 @@ class ServersGroups(ModelHandler):
'permission': permissions.effective_permissions(self._user, item),
}
def deleteItem(self, item: 'Model') -> None:
def delete_item(self, item: 'Model') -> None:
item = ensure.is_instance(item, models.ServerGroup)
"""
Processes a DELETE request
"""
self.ensureAccess(
self.ensure_has_access(
self.model(), permissions.PermissionType.ALL, root=True
) # Must have write permissions to delete

View File

@ -118,7 +118,7 @@ class Services(DetailHandler): # pylint: disable=too-many-public-methods
return retVal
def getItems(self, parent: 'Model', item: typing.Optional[str]):
def get_items(self, parent: 'Model', item: typing.Optional[str]):
parent = ensure.is_instance(parent, models.Provider)
# Check what kind of access do we have to parent provider
perm = permissions.effective_permissions(self._user, parent)
@ -127,12 +127,12 @@ class Services(DetailHandler): # pylint: disable=too-many-public-methods
return [Services.serviceToDict(k, perm) for k in parent.services.all()]
k = parent.services.get(uuid=process_uuid(item))
val = Services.serviceToDict(k, perm, full=True)
return self.fillIntanceFields(k, val)
return self.fill_instance_fields(k, val)
except Exception as e:
logger.error('Error getting services for %s: %s', parent, e)
raise self.invalidItemException() from e
raise self.invalid_item_response() from e
def getRowStyle(self, parent: 'Model') -> dict[str, typing.Any]:
def get_row_style(self, parent: 'Model') -> dict[str, typing.Any]:
parent = ensure.is_instance(parent, models.Provider)
return {'field': 'maintenance_mode', 'prefix': 'row-maintenance-'}
@ -149,7 +149,7 @@ class Services(DetailHandler): # pylint: disable=too-many-public-methods
except Exception: # nosec: This is a delete, we don't care about exceptions
pass
def saveItem(self, parent: 'Model', item: typing.Optional[str]) -> None:
def save_item(self, parent: 'Model', item: typing.Optional[str]) -> None:
parent = ensure.is_instance(parent, models.Provider)
# Extract item db fields
# We need this fields for all
@ -191,7 +191,7 @@ class Services(DetailHandler): # pylint: disable=too-many-public-methods
service.save()
except models.Service.DoesNotExist:
raise self.invalidItemException() from None
raise self.invalid_item_response() from None
except IntegrityError as e: # Duplicate key probably
if service and service.token and not item:
service.delete()
@ -213,7 +213,7 @@ class Services(DetailHandler): # pylint: disable=too-many-public-methods
logger.exception('Saving Service')
raise RequestError('incorrect invocation to PUT: {0}'.format(e)) from e
def deleteItem(self, parent: 'Model', item: str) -> None:
def delete_item(self, parent: 'Model', item: str) -> None:
parent = ensure.is_instance(parent, models.Provider)
try:
service = parent.services.get(uuid=process_uuid(item))
@ -222,18 +222,18 @@ class Services(DetailHandler): # pylint: disable=too-many-public-methods
return
except Exception:
logger.exception('Deleting service')
raise self.invalidItemException() from None
raise self.invalid_item_response() from None
raise RequestError('Item has associated deployed services')
def getTitle(self, parent: 'Model') -> str:
def get_title(self, parent: 'Model') -> str:
parent = ensure.is_instance(parent, models.Provider)
try:
return _('Services of {}').format(parent.name)
except Exception:
return _('Current services')
def getFields(self, parent: 'Model') -> list[typing.Any]:
def get_fields(self, parent: 'Model') -> list[typing.Any]:
return [
{'name': {'title': _('Service name'), 'visible': True, 'type': 'iconType'}},
{'comments': {'title': _('Comments')}},
@ -288,22 +288,22 @@ class Services(DetailHandler): # pylint: disable=too-many-public-methods
return offers # Default is that details do not have types
def getGui(self, parent: 'Model', forType: str) -> collections.abc.Iterable[typing.Any]:
def get_gui(self, parent: 'Model', forType: str) -> collections.abc.Iterable[typing.Any]:
parent = ensure.is_instance(parent, models.Provider)
try:
logger.debug('getGui parameters: %s, %s', parent, forType)
parentInstance = parent.get_instance()
serviceType = parentInstance.get_service_by_type(forType)
if not serviceType:
raise self.invalidItemException(f'Gui for {forType} not found')
raise self.invalid_item_response(f'Gui for {forType} not found')
service = serviceType(
Environment.getTempEnv(), parentInstance
) # Instantiate it so it has the opportunity to alter gui description based on parent
localGui = self.addDefaultFields(
localGui = self.add_default_fields(
service.guiDescription(), ['name', 'comments', 'tags']
)
self.addField(
self.add_field(
localGui,
{
'name': 'max_services_count_type',
@ -327,14 +327,14 @@ class Services(DetailHandler): # pylint: disable=too-many-public-methods
logger.exception('getGui')
raise ResponseError(str(e)) from e
def getLogs(self, parent: 'Model', item: str) -> list[typing.Any]:
def get_logs(self, parent: 'Model', item: str) -> list[typing.Any]:
parent = ensure.is_instance(parent, models.Provider)
try:
service = parent.services.get(uuid=process_uuid(item))
logger.debug('Getting logs for %s', item)
return log.get_logs(service)
except Exception:
raise self.invalidItemException() from None
raise self.invalid_item_response() from None
def servicesPools(self, parent: 'Model', item: str) -> typing.Any:
parent = ensure.is_instance(parent, models.Provider)
@ -343,7 +343,7 @@ class Services(DetailHandler): # pylint: disable=too-many-public-methods
res = []
for i in service.deployedServices.all():
try:
self.ensureAccess(
self.ensure_has_access(
i, uds.core.types.permissions.PermissionType.READ
) # Ensures access before listing...
res.append(

View File

@ -79,7 +79,7 @@ class ServicesPoolGroups(ModelHandler):
{'comments': {'title': _('Comments')}},
]
def beforeSave(self, fields: dict[str, typing.Any]) -> None:
def pre_save(self, fields: dict[str, typing.Any]) -> None:
imgId = fields['image_id']
fields['image_id'] = None
logger.debug('Image id: %s', imgId)
@ -91,8 +91,8 @@ class ServicesPoolGroups(ModelHandler):
logger.exception('At image recovering')
# Gui related
def getGui(self, type_: str) -> list[typing.Any]:
localGui = self.addDefaultFields([], ['name', 'comments', 'priority'])
def get_gui(self, type_: str) -> list[typing.Any]:
localGui = self.add_default_fields([], ['name', 'comments', 'priority'])
for field in [
{
@ -110,7 +110,7 @@ class ServicesPoolGroups(ModelHandler):
'order': 102,
}
]:
self.addField(localGui, field)
self.add_field(localGui, field)
return localGui

View File

@ -137,10 +137,10 @@ class ServicesPools(ModelHandler):
('createFromAssignable', True),
]
def getItems(self, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
def get_items(self, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
# Optimized query, due that there is a lot of info needed for theee
d = sql_datetime() - datetime.timedelta(seconds=GlobalConfig.RESTRAINT_TIME.getInt())
return super().getItems(
return super().get_items(
overview=kwargs.get('overview', True),
query=(
ServicePool.objects.prefetch_related(
@ -181,8 +181,8 @@ class ServicesPools(ModelHandler):
)
),
)
# return super().getItems(overview=kwargs.get('overview', True), prefetch=['service', 'service__provider', 'servicesPoolGroup', 'image', 'tags'])
# return super(ServicesPools, self).getItems(*args, **kwargs)
# return super().get_items(overview=kwargs.get('overview', True), prefetch=['service', 'service__provider', 'servicesPoolGroup', 'image', 'tags'])
# return super(ServicesPools, self).get_items(*args, **kwargs)
def item_as_dict(self, item: 'Model') -> dict[str, typing.Any]:
item = ensure.is_instance(item, ServicePool)
@ -277,13 +277,13 @@ class ServicesPools(ModelHandler):
return val
# Gui related
def getGui(self, type_: str) -> list[typing.Any]:
def get_gui(self, type_: str) -> list[typing.Any]:
# if OSManager.objects.count() < 1: # No os managers, can't create db
# raise ResponseError(gettext('Create at least one OS Manager before creating a new service pool'))
if Service.objects.count() < 1:
raise ResponseError(gettext('Create at least a service before creating a new service pool'))
g = self.addDefaultFields([], ['name', 'comments', 'tags'])
g = self.add_default_fields([], ['name', 'comments', 'tags'])
for f in [
{
@ -464,12 +464,12 @@ class ServicesPools(ModelHandler):
'order': 131,
},
]:
self.addField(g, f)
self.add_field(g, f)
return g
# pylint: disable=too-many-statements
def beforeSave(self, fields: dict[str, typing.Any]) -> None:
def pre_save(self, fields: dict[str, typing.Any]) -> None:
# logger.debug(self._params)
def macro_fld_len(x) -> int:
w = x
@ -581,7 +581,7 @@ class ServicesPools(ModelHandler):
except Exception as e:
raise RequestError(str(e)) from e
def afterSave(self, item: 'Model') -> None:
def post_save(self, item: 'Model') -> None:
item = ensure.is_instance(item, ServicePool)
if self._params.get('publish_on_save', False) is True:
try:
@ -589,7 +589,7 @@ class ServicesPools(ModelHandler):
except Exception as e:
logger.error('Could not publish service pool %s: %s', item.name, e)
def deleteItem(self, item: 'Model') -> None:
def delete_item(self, item: 'Model') -> None:
item = ensure.is_instance(item, ServicePool)
try:
logger.debug('Deleting %s', item)
@ -599,7 +599,7 @@ class ServicesPools(ModelHandler):
logger.exception('deleting service pool')
# Logs
def getLogs(self, item: 'Model') -> list[dict]:
def get_logs(self, item: 'Model') -> list[dict]:
item = ensure.is_instance(item, ServicePool)
try:
return log.get_logs(item)
@ -609,7 +609,7 @@ class ServicesPools(ModelHandler):
# Set fallback status
def setFallbackAccess(self, item: 'Model'):
item = ensure.is_instance(item, ServicePool)
self.ensureAccess(item, types.permissions.PermissionType.MANAGEMENT)
self.ensure_has_access(item, types.permissions.PermissionType.MANAGEMENT)
fallback = self._params.get('fallbackAccess')
if fallback:
@ -665,7 +665,7 @@ class ServicesPools(ModelHandler):
def createFromAssignable(self, item: 'Model') -> typing.Any:
item = ensure.is_instance(item, ServicePool)
if 'user_id' not in self._params or 'assignable_id' not in self._params:
return self.invalidRequestException('Invalid parameters')
return self.invalid_request_response('Invalid parameters')
logger.debug('Creating from assignable: %s', self._params)
UserServiceManager().create_from_assignable(

View File

@ -56,7 +56,7 @@ class ServicesUsage(DetailHandler):
"""
@staticmethod
def itemToDict(item: UserService) -> dict[str, typing.Any]:
def item_as_dict(item: UserService) -> dict[str, typing.Any]:
"""
Converts an assigned/cached service db item to a dictionary for REST response
:param item: item to convert
@ -90,7 +90,7 @@ class ServicesUsage(DetailHandler):
'in_use': item.in_use,
}
def getItems(self, parent: 'Model', item: typing.Optional[str]):
def get_items(self, parent: 'Model', item: typing.Optional[str]):
parent = ensure.is_instance(parent, Provider)
try:
if item is None:
@ -103,20 +103,20 @@ class ServicesUsage(DetailHandler):
)
return [
ServicesUsage.itemToDict(k)
ServicesUsage.item_as_dict(k)
for k in userServicesQuery.filter(state=State.USABLE)
.order_by('creation_date')
.prefetch_related('deployed_service', 'deployed_service__service', 'user', 'user__manager')
]
except Exception:
logger.exception('getItems')
raise self.invalidItemException()
logger.exception('get_items')
raise self.invalid_item_response()
def getTitle(self, parent: 'Model') -> str:
def get_title(self, parent: 'Model') -> str:
return _('Services Usage')
def getFields(self, parent: 'Model') -> list[typing.Any]:
def get_fields(self, parent: 'Model') -> list[typing.Any]:
return [
# {'creation_date': {'title': _('Creation date'), 'type': 'datetime'}},
{'state_date': {'title': _('Access'), 'type': 'datetime'}},
@ -130,10 +130,10 @@ class ServicesUsage(DetailHandler):
{'source_host': {'title': _('Src Host')}},
]
def getRowStyle(self, parent: 'Model') -> dict[str, typing.Any]:
def get_row_style(self, parent: 'Model') -> dict[str, typing.Any]:
return {'field': 'state', 'prefix': 'row-state-'}
def deleteItem(self, parent: 'Model', item: str) -> None:
def delete_item(self, parent: 'Model', item: str) -> None:
parent = ensure.is_instance(parent, Provider)
userService: UserService
try:
@ -141,7 +141,7 @@ class ServicesUsage(DetailHandler):
uuid=process_uuid(item), deployed_service__service__provider=parent
)
except Exception:
raise self.invalidItemException()
raise self.invalid_item_response()
logger.debug('Deleting user service')
if userService.state in (State.USABLE, State.REMOVING):
@ -149,6 +149,6 @@ class ServicesUsage(DetailHandler):
elif userService.state == State.PREPARING:
userService.cancel()
elif userService.state == State.REMOVABLE:
raise self.invalidItemException(_('Item already being removed'))
raise self.invalid_item_response(_('Item already being removed'))
else:
raise self.invalidItemException(_('Item is not removable'))
raise self.invalid_item_response(_('Item is not removable'))

View File

@ -154,15 +154,15 @@ class Tickets(Handler):
# Check that call is correct (pamateters, args, ...)
self._checkInput()
force: bool = self.getParam('force') in ('1', 'true', 'True', True)
force: bool = self.get_param('force') in ('1', 'true', 'True', True)
try:
servicePoolId: typing.Optional[str] = None
# First param is recommended, last ones are compatible with old versions
authId = self.getParam('auth_id', 'authId')
authName = self.getParam('auth_name', 'auth')
authTag = self.getParam('auth_tag', 'authTag', 'authSmallName')
authId = self.get_param('auth_id', 'authId')
authName = self.get_param('auth_name', 'auth')
authTag = self.get_param('auth_tag', 'authTag', 'authSmallName')
# Will raise an exception if no auth found
if authId:
@ -174,12 +174,12 @@ class Tickets(Handler):
else:
auth = models.Authenticator.objects.get(small_name=authTag)
username: str = self.getParam('username')
password: str = self.getParam('password')
username: str = self.get_param('username')
password: str = self.get_param('password')
# Some machines needs password, depending on configuration
groupIds: list[str] = []
for groupName in ensure.is_list(self.getParam('groups')):
for groupName in ensure.is_list(self.get_param('groups')):
try:
groupIds.append(auth.groups.get(name=groupName).uuid or '')
except Exception:
@ -204,13 +204,13 @@ class Tickets(Handler):
)
try:
time = int(self.getParam('time') or 60)
time = int(self.get_param('time') or 60)
time = 60 if time < 1 else time
except Exception:
time = 60
realname: str = self.getParam('realname', 'username') or ''
realname: str = self.get_param('realname', 'username') or ''
poolUuid = self.getParam('servicePool')
poolUuid = self.get_param('servicePool')
if poolUuid:
# Check if is pool or metapool
poolUuid = process_uuid(poolUuid)

View File

@ -84,18 +84,18 @@ class Transports(ModelHandler):
def enum_types(self) -> collections.abc.Iterable[type[transports.Transport]]:
return transports.factory().providers().values()
def getGui(self, type_: str) -> list[typing.Any]:
def get_gui(self, type_: str) -> list[typing.Any]:
transportType = transports.factory().lookup(type_)
if not transportType:
raise self.invalidItemException()
raise self.invalid_item_response()
transport = transportType(Environment.getTempEnv(), None)
field = self.addDefaultFields(
field = self.add_default_fields(
transport.guiDescription(), ['name', 'comments', 'tags', 'priority', 'networks']
)
field = self.addField(
field = self.add_field(
field,
{
'name': 'allowed_oss',
@ -113,7 +113,7 @@ class Transports(ModelHandler):
'order': 102,
},
)
field = self.addField(
field = self.add_field(
field,
{
'name': 'pools',
@ -131,7 +131,7 @@ class Transports(ModelHandler):
'order': 103,
},
)
field = self.addField(
field = self.add_field(
field,
{
'name': 'label',
@ -170,15 +170,15 @@ class Transports(ModelHandler):
'permission': permissions.effective_permissions(self._user, item),
}
def beforeSave(self, fields: dict[str, typing.Any]) -> None:
def pre_save(self, fields: dict[str, typing.Any]) -> None:
fields['allowed_oss'] = ','.join(fields['allowed_oss'])
# If label has spaces, replace them with underscores
fields['label'] = fields['label'].strip().replace(' ', '-')
# And ensure small_name chars are valid [ a-zA-Z0-9:-]+
if fields['label'] and not re.match(r'^[a-zA-Z0-9:-]+$', fields['label']):
raise self.invalidRequestException(gettext('Label must contain only letters, numbers, ":" and "-"'))
raise self.invalid_request_response(gettext('Label must contain only letters, numbers, ":" and "-"'))
def afterSave(self, item: 'Model') -> None:
def post_save(self, item: 'Model') -> None:
item = ensure.is_instance(item, Transport)
try:
networks = self._params['networks']

View File

@ -55,7 +55,7 @@ class TunnelServers(DetailHandler):
# tunnels/[id]/servers
custom_methods = ['maintenance']
def getItems(self, parent: 'Model', item: typing.Optional[str]):
def get_items(self, parent: 'Model', item: typing.Optional[str]):
parent = ensure.is_instance(parent, models.ServerGroup)
try:
multi = False
@ -82,16 +82,16 @@ class TunnelServers(DetailHandler):
return res[0]
except Exception as e:
logger.exception('REST groups')
raise self.invalidItemException() from e
raise self.invalid_item_response() from e
def getTitle(self, parent: 'Model') -> str:
def get_title(self, parent: 'Model') -> str:
parent = ensure.is_instance(parent, models.ServerGroup)
try:
return _('Servers of {0}').format(parent.name)
except Exception:
return gettext('Servers')
def getFields(self, parent: 'Model') -> list[typing.Any]:
def get_fields(self, parent: 'Model') -> list[typing.Any]:
parent = ensure.is_instance(parent, models.ServerGroup)
return [
{
@ -110,18 +110,18 @@ class TunnelServers(DetailHandler):
},
]
def getRowStyle(self, parent: 'Model') -> dict[str, typing.Any]:
def get_row_style(self, parent: 'Model') -> dict[str, typing.Any]:
parent = ensure.is_instance(parent, models.ServerGroup)
return {'field': 'maintenance_mode', 'prefix': 'row-maintenance-'}
# Cannot save a tunnel server, it's not editable...
def deleteItem(self, parent: 'Model', item: str) -> None:
def delete_item(self, parent: 'Model', item: str) -> None:
parent = ensure.is_instance(parent, models.ServerGroup)
try:
parent.servers.remove(models.Server.objects.get(uuid=process_uuid(item)))
except Exception:
raise self.invalidItemException() from None
raise self.invalid_item_response() from None
# Custom methods
def maintenance(self, parent: 'Model', id: str) -> typing.Any:
@ -131,7 +131,7 @@ class TunnelServers(DetailHandler):
:param item:
"""
item = models.Server.objects.get(uuid=process_uuid(id))
self.ensureAccess(item, uds.core.types.permissions.PermissionType.MANAGEMENT)
self.ensure_has_access(item, uds.core.types.permissions.PermissionType.MANAGEMENT)
item.maintenance_mode = not item.maintenance_mode
item.save()
return 'ok'
@ -161,9 +161,9 @@ class Tunnels(ModelHandler):
{'tags': {'title': _('tags'), 'visible': False}},
]
def getGui(self, type_: str) -> list[typing.Any]:
return self.addField(
self.addDefaultFields(
def get_gui(self, type_: str) -> list[typing.Any]:
return self.add_field(
self.add_default_fields(
[],
['name', 'comments', 'tags'],
),
@ -203,7 +203,7 @@ class Tunnels(ModelHandler):
'permission': permissions.effective_permissions(self._user, item),
}
def beforeSave(self, fields: dict[str, typing.Any]) -> None:
def pre_save(self, fields: dict[str, typing.Any]) -> None:
fields['type'] = types.servers.ServerType.TUNNEL.value
fields['port'] = int(fields['port'])
# Ensure host is a valid IP(4 or 6) or hostname
@ -211,21 +211,21 @@ class Tunnels(ModelHandler):
def assign(self, parent: 'Model') -> typing.Any:
parent = ensure.is_instance(parent, models.ServerGroup)
self.ensureAccess(parent, uds.core.types.permissions.PermissionType.MANAGEMENT)
self.ensure_has_access(parent, uds.core.types.permissions.PermissionType.MANAGEMENT)
server: typing.Optional['models.Server'] = None # Avoid warning on reference before assignment
item = self._args[-1]
if item is None:
raise self.invalidItemException('No server specified')
raise self.invalid_item_response('No server specified')
try:
server = models.Server.objects.get(uuid=process_uuid(item))
self.ensureAccess(server, uds.core.types.permissions.PermissionType.READ)
self.ensure_has_access(server, uds.core.types.permissions.PermissionType.READ)
parent.servers.add(server)
except Exception:
raise self.invalidItemException() from None
raise self.invalid_item_response() from None
# TODO: implement this
return 'ok'

View File

@ -63,7 +63,7 @@ class AssignedService(DetailHandler):
custom_methods = ['reset']
@staticmethod
def itemToDict(
def item_as_dict(
item: models.UserService,
props: typing.Optional[dict[str, typing.Any]] = None,
is_cache: bool = False,
@ -117,7 +117,7 @@ class AssignedService(DetailHandler):
)
return val
def getItems(self, parent: 'Model', item: typing.Optional[str]):
def get_items(self, parent: 'Model', item: typing.Optional[str]):
parent = ensure.is_instance(parent, models.ServicePool)
# Extract provider
try:
@ -132,12 +132,12 @@ class AssignedService(DetailHandler):
).values_list('key', 'value')
}
return [
AssignedService.itemToDict(k, properties.get(k.uuid, {}))
AssignedService.item_as_dict(k, properties.get(k.uuid, {}))
for k in parent.assigned_user_services()
.all()
.prefetch_related('deployed_service', 'publication', 'user')
]
return AssignedService.itemToDict(
return AssignedService.item_as_dict(
parent.assigned_user_services().get(process_uuid(uuid=process_uuid(item))),
props={
k: v
@ -147,13 +147,13 @@ class AssignedService(DetailHandler):
},
)
except Exception as e:
logger.exception('getItems')
raise self.invalidItemException() from e
logger.exception('get_items')
raise self.invalid_item_response() from e
def getTitle(self, parent: 'Model') -> str:
def get_title(self, parent: 'Model') -> str:
return _('Assigned services')
def getFields(self, parent: 'Model') -> list[typing.Any]:
def get_fields(self, parent: 'Model') -> list[typing.Any]:
return [
{'creation_date': {'title': _('Creation date'), 'type': 'datetime'}},
{'revision': {'title': _('Revision')}},
@ -175,26 +175,26 @@ class AssignedService(DetailHandler):
{'actor_version': {'title': _('Actor version')}},
]
def getRowStyle(self, parent: 'Model') -> dict[str, typing.Any]:
def get_row_style(self, parent: 'Model') -> dict[str, typing.Any]:
return {'field': 'state', 'prefix': 'row-state-'}
def getLogs(self, parent: 'Model', item: str) -> list[typing.Any]:
def get_logs(self, parent: 'Model', item: str) -> list[typing.Any]:
parent = ensure.is_instance(parent, models.ServicePool)
try:
userService: models.UserService = parent.assigned_user_services().get(uuid=process_uuid(item))
logger.debug('Getting logs for %s', userService)
return log.get_logs(userService)
except Exception as e:
raise self.invalidItemException() from e
raise self.invalid_item_response() from e
# This is also used by CachedService, so we use "userServices" directly and is valid for both
def deleteItem(self, parent: 'Model', item: str) -> None:
def delete_item(self, parent: 'Model', item: str) -> None:
parent = ensure.is_instance(parent, models.ServicePool)
try:
userService: models.UserService = parent.userServices.get(uuid=process_uuid(item))
except Exception as e:
logger.exception('deleteItem')
raise self.invalidItemException() from e
logger.exception('delete_item')
raise self.invalid_item_response() from e
if userService.user:
logStr = f'Deleted assigned service {userService.friendly_name} to user {userService.user.pretty_name} by {self._user.pretty_name}'
@ -206,17 +206,17 @@ class AssignedService(DetailHandler):
elif userService.state == State.PREPARING:
userService.cancel()
elif userService.state == State.REMOVABLE:
raise self.invalidItemException(_('Item already being removed'))
raise self.invalid_item_response(_('Item already being removed'))
else:
raise self.invalidItemException(_('Item is not removable'))
raise self.invalid_item_response(_('Item is not removable'))
log.log(parent, log.LogLevel.INFO, logStr, log.LogSource.ADMIN)
# Only owner is allowed to change right now
def saveItem(self, parent: 'Model', item: typing.Optional[str]) -> None:
def save_item(self, parent: 'Model', item: typing.Optional[str]) -> None:
parent = ensure.is_instance(parent, models.ServicePool)
if not item:
raise self.invalidItemException('Only modify is allowed')
raise self.invalid_item_response('Only modify is allowed')
fields = self.fields_from_params(['auth_id', 'user_id'])
userService = parent.userServices.get(uuid=process_uuid(item))
user = models.User.objects.get(uuid=process_uuid(fields['user_id']))
@ -231,7 +231,7 @@ class AssignedService(DetailHandler):
.count()
> 0
):
raise self.invalidResponseException(
raise self.invalid_response_response(
f'There is already another user service assigned to {user.pretty_name}'
)
@ -253,27 +253,27 @@ class CachedService(AssignedService):
custom_methods: typing.ClassVar[list[str]] = [] # Remove custom methods from assigned services
def getItems(self, parent: 'Model', item: typing.Optional[str]):
def get_items(self, parent: 'Model', item: typing.Optional[str]):
parent = ensure.is_instance(parent, models.ServicePool)
# Extract provider
try:
if not item:
return [
AssignedService.itemToDict(k, is_cache=True)
AssignedService.item_as_dict(k, is_cache=True)
for k in parent.cached_users_services()
.all()
.prefetch_related('deployed_service', 'publication')
]
cachedService: models.UserService = parent.cached_users_services().get(uuid=process_uuid(item))
return AssignedService.itemToDict(cachedService, is_cache=True)
return AssignedService.item_as_dict(cachedService, is_cache=True)
except Exception as e:
logger.exception('getItems')
raise self.invalidItemException() from e
logger.exception('get_items')
raise self.invalid_item_response() from e
def getTitle(self, parent: 'Model') -> str:
def get_title(self, parent: 'Model') -> str:
return _('Cached services')
def getFields(self, parent: 'Model') -> list[typing.Any]:
def get_fields(self, parent: 'Model') -> list[typing.Any]:
return [
{'creation_date': {'title': _('Creation date'), 'type': 'datetime'}},
{'revision': {'title': _('Revision')}},
@ -291,14 +291,14 @@ class CachedService(AssignedService):
{'actor_version': {'title': _('Actor version')}},
]
def getLogs(self, parent: 'Model', item: str) -> list[typing.Any]:
def get_logs(self, parent: 'Model', item: str) -> list[typing.Any]:
parent = ensure.is_instance(parent, models.ServicePool)
try:
userService = parent.cached_users_services().get(uuid=process_uuid(item))
logger.debug('Getting logs for %s', item)
return log.get_logs(userService)
except Exception:
raise self.invalidItemException() from None
raise self.invalid_item_response() from None
class Groups(DetailHandler):
@ -306,7 +306,7 @@ class Groups(DetailHandler):
Processes the groups detail requests of a Service Pool
"""
def getItems(self, parent: 'Model', item: typing.Optional[str]):
def get_items(self, parent: 'Model', item: typing.Optional[str]):
parent = ensure.is_instance(parent, models.ServicePool)
group: models.Group
return [
@ -323,11 +323,11 @@ class Groups(DetailHandler):
for group in parent.assignedGroups.all()
]
def getTitle(self, parent: 'Model') -> str:
def get_title(self, parent: 'Model') -> str:
parent = ensure.is_instance(parent, models.ServicePool)
return _('Assigned groups')
def getFields(self, parent: 'Model') -> list[typing.Any]:
def get_fields(self, parent: 'Model') -> list[typing.Any]:
return [
# Note that this field is "self generated" on client table
{
@ -352,10 +352,10 @@ class Groups(DetailHandler):
},
]
def getRowStyle(self, parent: 'Model') -> dict[str, typing.Any]:
def get_row_style(self, parent: 'Model') -> dict[str, typing.Any]:
return {'field': 'state', 'prefix': 'row-state-'}
def saveItem(self, parent: 'Model', item: typing.Optional[str]) -> None:
def save_item(self, parent: 'Model', item: typing.Optional[str]) -> None:
parent = ensure.is_instance(parent, models.ServicePool)
group: models.Group = models.Group.objects.get(uuid=process_uuid(self._params['id']))
parent.assignedGroups.add(group)
@ -366,7 +366,7 @@ class Groups(DetailHandler):
log.LogSource.ADMIN,
)
def deleteItem(self, parent: 'Model', item: str) -> None:
def delete_item(self, parent: 'Model', item: str) -> None:
parent = ensure.is_instance(parent, models.ServicePool)
group: models.Group = models.Group.objects.get(uuid=process_uuid(self._args[0]))
parent.assignedGroups.remove(group)
@ -383,11 +383,11 @@ class Transports(DetailHandler):
Processes the transports detail requests of a Service Pool
"""
def getItems(self, parent: 'Model', item: typing.Optional[str]):
def get_items(self, parent: 'Model', item: typing.Optional[str]):
parent = ensure.is_instance(parent, models.ServicePool)
def get_type(trans: 'models.Transport'):
try:
return self.typeAsDict(trans.get_type())
return self.type_as_dict(trans.get_type())
except Exception: # No type found
return None
@ -404,11 +404,11 @@ class Transports(DetailHandler):
if get_type(i)
]
def getTitle(self, parent: 'Model') -> str:
def get_title(self, parent: 'Model') -> str:
parent = ensure.is_instance(parent, models.ServicePool)
return _('Assigned transports')
def getFields(self, parent: 'Model') -> list[typing.Any]:
def get_fields(self, parent: 'Model') -> list[typing.Any]:
return [
{'priority': {'title': _('Priority'), 'type': 'numeric', 'width': '6em'}},
{'name': {'title': _('Name')}},
@ -416,7 +416,7 @@ class Transports(DetailHandler):
{'comments': {'title': _('Comments')}},
]
def saveItem(self, parent: 'Model', item: typing.Optional[str]) -> None:
def save_item(self, parent: 'Model', item: typing.Optional[str]) -> None:
parent = ensure.is_instance(parent, models.ServicePool)
transport: models.Transport = models.Transport.objects.get(uuid=process_uuid(self._params['id']))
parent.transports.add(transport)
@ -427,7 +427,7 @@ class Transports(DetailHandler):
log.LogSource.ADMIN,
)
def deleteItem(self, parent: 'Model', item: str) -> None:
def delete_item(self, parent: 'Model', item: str) -> None:
parent = ensure.is_instance(parent, models.ServicePool)
transport: models.Transport = models.Transport.objects.get(uuid=process_uuid(self._args[0]))
parent.transports.remove(transport)
@ -459,7 +459,7 @@ class Publications(DetailHandler):
is False
):
logger.debug('Management Permission failed for user %s', self._user)
raise self.accessDenied()
raise self.access_denied_response()
logger.debug('Custom "publish" invoked for %s', parent)
parent.publish(changeLog) # Can raise exceptions that will be processed on response
@ -486,7 +486,7 @@ class Publications(DetailHandler):
is False
):
logger.debug('Management Permission failed for user %s', self._user)
raise self.accessDenied()
raise self.access_denied_response()
try:
ds = models.ServicePoolPublication.objects.get(uuid=process_uuid(uuid))
@ -503,7 +503,7 @@ class Publications(DetailHandler):
return self.success()
def getItems(self, parent: 'Model', item: typing.Optional[str]):
def get_items(self, parent: 'Model', item: typing.Optional[str]):
parent = ensure.is_instance(parent, models.ServicePool)
return [
{
@ -517,11 +517,11 @@ class Publications(DetailHandler):
for i in parent.publications.all()
]
def getTitle(self, parent: 'Model') -> str:
def get_title(self, parent: 'Model') -> str:
parent = ensure.is_instance(parent, models.ServicePool)
return _('Publications')
def getFields(self, parent: 'Model') -> list[typing.Any]:
def get_fields(self, parent: 'Model') -> list[typing.Any]:
return [
{'revision': {'title': _('Revision'), 'type': 'numeric', 'width': '6em'}},
{'publish_date': {'title': _('Publish date'), 'type': 'datetime'}},
@ -535,7 +535,7 @@ class Publications(DetailHandler):
{'reason': {'title': _('Reason')}},
]
def getRowStyle(self, parent: 'Model') -> dict[str, typing.Any]:
def get_row_style(self, parent: 'Model') -> dict[str, typing.Any]:
return {'field': 'state', 'prefix': 'row-state-'}
@ -544,7 +544,7 @@ class Changelog(DetailHandler):
Processes the transports detail requests of a Service Pool
"""
def getItems(self, parent: 'Model', item: typing.Optional[str]):
def get_items(self, parent: 'Model', item: typing.Optional[str]):
parent = ensure.is_instance(parent, models.ServicePool)
return [
{
@ -555,11 +555,11 @@ class Changelog(DetailHandler):
for i in parent.changelog.all()
]
def getTitle(self, parent: 'Model') -> str:
def get_title(self, parent: 'Model') -> str:
parent = ensure.is_instance(parent, models.ServicePool)
return _(f'Changelog')
def getFields(self, parent: 'Model') -> list[typing.Any]:
def get_fields(self, parent: 'Model') -> list[typing.Any]:
return [
{'revision': {'title': _('Revision'), 'type': 'numeric', 'width': '6em'}},
{'stamp': {'title': _('Publish date'), 'type': 'datetime'}},

View File

@ -82,7 +82,7 @@ def get_service_pools_for_groups(groups):
class Users(DetailHandler):
custom_methods = ['servicesPools', 'userServices', 'cleanRelated']
def getItems(self, parent: 'Model', item: typing.Optional[str]) -> typing.Any:
def get_items(self, parent: 'Model', item: typing.Optional[str]) -> typing.Any:
parent = ensure.is_instance(parent, Authenticator)
# processes item to change uuid key for id
@ -147,9 +147,9 @@ class Users(DetailHandler):
return res
except Exception as e:
# User not found
raise self.invalidItemException() from e
raise self.invalid_item_response() from e
def getTitle(self, parent: 'Model') -> str:
def get_title(self, parent: 'Model') -> str:
try:
return _('Users of {0}').format(
Authenticator.objects.get(uuid=process_uuid(self._kwargs['parent_id'])).name
@ -157,7 +157,7 @@ class Users(DetailHandler):
except Exception:
return _('Current users')
def getFields(self, parent: 'Model') -> list[typing.Any]:
def get_fields(self, parent: 'Model') -> list[typing.Any]:
return [
{
'name': {
@ -180,20 +180,20 @@ class Users(DetailHandler):
{'last_access': {'title': _('Last access'), 'type': 'datetime'}},
]
def getRowStyle(self, parent: 'Model') -> dict[str, typing.Any]:
def get_row_style(self, parent: 'Model') -> dict[str, typing.Any]:
return {'field': 'state', 'prefix': 'row-state-'}
def getLogs(self, parent: 'Model', item: str) -> list[typing.Any]:
def get_logs(self, parent: 'Model', item: str) -> list[typing.Any]:
parent = ensure.is_instance(parent, Authenticator)
user = None
try:
user = parent.users.get(uuid=process_uuid(item))
except Exception:
raise self.invalidItemException() from None
raise self.invalid_item_response() from None
return log.get_logs(user)
def saveItem(self, parent: 'Model', item):
def save_item(self, parent: 'Model', item):
parent = ensure.is_instance(parent, Authenticator)
logger.debug('Saving user %s / %s', parent, item)
valid_fields = [
@ -242,7 +242,7 @@ class Users(DetailHandler):
# Save but skip meta groups, they are not real groups, but just a way to group users based on rules
user.groups.set(g for g in parent.groups.filter(uuid__in=groups) if g.is_meta is False)
except User.DoesNotExist:
raise self.invalidItemException() from None
raise self.invalid_item_response() from None
except IntegrityError: # Duplicate key probably
raise RequestError(_('User already exists (duplicate key error)')) from None
except exceptions.auth.AuthenticatorException as e:
@ -253,11 +253,11 @@ class Users(DetailHandler):
raise # Re-raise
except Exception as e:
logger.exception('Saving user')
raise self.invalidRequestException() from e
raise self.invalid_request_response() from e
return self.getItems(parent, user.uuid)
return self.get_items(parent, user.uuid)
def deleteItem(self, parent: 'Model', item: str):
def delete_item(self, parent: 'Model', item: str):
parent = ensure.is_instance(parent, Authenticator)
try:
user = parent.users.get(uuid=process_uuid(item))
@ -266,7 +266,7 @@ class Users(DetailHandler):
'Removal of user %s denied due to insufficients rights',
user.pretty_name,
)
raise self.invalidItemException(
raise self.invalid_item_response(
f'Removal of user {user.pretty_name} denied due to insufficients rights'
)
@ -286,7 +286,7 @@ class Users(DetailHandler):
user.delete()
except Exception as e:
logger.exception('Removing user')
raise self.invalidItemException() from e
raise self.invalid_item_response() from e
return 'deleted'
@ -318,7 +318,7 @@ class Users(DetailHandler):
res = []
for i in user.userServices.all():
if i.state == State.USABLE:
v = AssignedService.itemToDict(i)
v = AssignedService.item_as_dict(i)
v['pool'] = i.deployed_service.name
v['pool_id'] = i.deployed_service.uuid
res.append(v)
@ -335,7 +335,7 @@ class Users(DetailHandler):
class Groups(DetailHandler):
custom_methods = ['servicesPools', 'users']
def getItems(self, parent: 'Model', item: typing.Optional[str]):
def get_items(self, parent: 'Model', item: typing.Optional[str]):
parent = ensure.is_instance(parent, Authenticator)
try:
multi = False
@ -369,16 +369,16 @@ class Groups(DetailHandler):
return result
except Exception as e:
logger.exception('REST groups')
raise self.invalidItemException() from e
raise self.invalid_item_response() from e
def getTitle(self, parent: 'Model') -> str:
def get_title(self, parent: 'Model') -> str:
parent = ensure.is_instance(parent, Authenticator)
try:
return _('Groups of {0}').format(parent.name)
except Exception:
return _('Current groups')
def getFields(self, parent: 'Model') -> list[typing.Any]:
def get_fields(self, parent: 'Model') -> list[typing.Any]:
return [
{
'name': {
@ -424,9 +424,9 @@ class Groups(DetailHandler):
try:
return next(filter(lambda x: x['type'] == forType, types))
except Exception:
raise self.invalidRequestException() from None
raise self.invalid_request_response() from None
def saveItem(self, parent: 'Model', item: typing.Optional[str]) -> None:
def save_item(self, parent: 'Model', item: typing.Optional[str]) -> None:
parent = ensure.is_instance(parent, Authenticator)
group = None # Avoid warning on reference before assignment
try:
@ -480,7 +480,7 @@ class Groups(DetailHandler):
group.save()
except Group.DoesNotExist:
raise self.invalidItemException() from None
raise self.invalid_item_response() from None
except IntegrityError: # Duplicate key probably
raise RequestError(_('User already exists (duplicate key error)')) from None
except exceptions.auth.AuthenticatorException as e:
@ -489,16 +489,16 @@ class Groups(DetailHandler):
raise # Re-raise
except Exception as e:
logger.exception('Saving group')
raise self.invalidRequestException() from e
raise self.invalid_request_response() from e
def deleteItem(self, parent: 'Model', item: str) -> None:
def delete_item(self, parent: 'Model', item: str) -> None:
parent = ensure.is_instance(parent, Authenticator)
try:
group = parent.groups.get(uuid=item)
group.delete()
except Exception:
raise self.invalidItemException() from None
raise self.invalid_item_response() from None
def servicesPools(self, parent: 'Model', item: str) -> list[collections.abc.Mapping[str, typing.Any]]:
parent = ensure.is_instance(parent, Authenticator)

View File

@ -31,6 +31,7 @@
"""
# pylint: disable=too-many-public-methods
import abc
import fnmatch
import inspect
import logging
@ -76,7 +77,7 @@ class BaseModelHandler(Handler):
Base Handler for Master & Detail Handlers
"""
def addField(
def add_field(
self, gui: list[typing.Any], field: typing.Union[FieldType, list[FieldType]]
) -> list[typing.Any]:
"""
@ -88,7 +89,7 @@ class BaseModelHandler(Handler):
"""
if isinstance(field, list):
for i in field:
gui = self.addField(gui, i)
gui = self.add_field(gui, i)
else:
if 'values' in field:
caller = inspect.stack()[1]
@ -147,7 +148,7 @@ class BaseModelHandler(Handler):
gui.append(v)
return gui
def addDefaultFields(self, gui: list[typing.Any], flds: list[str]) -> list[typing.Any]:
def add_default_fields(self, gui: list[typing.Any], flds: list[str]) -> list[typing.Any]:
"""
Adds default fields (based in a list) to a "gui" description
:param gui: Gui list where the "default" fielsds will be added
@ -155,7 +156,7 @@ class BaseModelHandler(Handler):
'priority' and 'small_name', 'short_name', 'tags'
"""
if 'tags' in flds:
self.addField(
self.add_field(
gui,
{
'name': 'tags',
@ -166,7 +167,7 @@ class BaseModelHandler(Handler):
},
)
if 'name' in flds:
self.addField(
self.add_field(
gui,
{
'name': 'name',
@ -179,7 +180,7 @@ class BaseModelHandler(Handler):
},
)
if 'comments' in flds:
self.addField(
self.add_field(
gui,
{
'name': 'comments',
@ -192,7 +193,7 @@ class BaseModelHandler(Handler):
},
)
if 'priority' in flds:
self.addField(
self.add_field(
gui,
{
'name': 'priority',
@ -206,7 +207,7 @@ class BaseModelHandler(Handler):
},
)
if 'small_name' in flds:
self.addField(
self.add_field(
gui,
{
'name': 'small_name',
@ -219,7 +220,7 @@ class BaseModelHandler(Handler):
},
)
if 'networks' in flds:
self.addField(
self.add_field(
gui,
{
'name': 'net_filtering',
@ -238,7 +239,7 @@ class BaseModelHandler(Handler):
'tab': types.ui.Tab.ADVANCED,
},
)
self.addField(
self.add_field(
gui,
{
'name': 'networks',
@ -257,19 +258,19 @@ class BaseModelHandler(Handler):
return gui
def ensureAccess(
def ensure_has_access(
self,
obj: models.Model,
permission: 'types.permissions.PermissionType',
root: bool = False,
) -> None:
if not permissions.has_access(self._user, obj, permission, root):
raise self.accessDenied()
raise self.access_denied_response()
def getPermissions(self, obj: models.Model, root: bool = False) -> int:
def get_permissions(self, obj: models.Model, root: bool = False) -> int:
return permissions.effective_permissions(self._user, obj, root)
def typeInfo(
def type_info(
self, type_: type['Module'] # pylint: disable=unused-argument
) -> dict[str, typing.Any]:
"""
@ -278,7 +279,7 @@ class BaseModelHandler(Handler):
"""
return {}
def typeAsDict(self, type_: type['Module']) -> dict[str, typing.Any]:
def type_as_dict(self, type_: type['Module']) -> dict[str, typing.Any]:
"""
Returns a dictionary describing the type (the name, the icon, description, etc...)
"""
@ -287,12 +288,12 @@ class BaseModelHandler(Handler):
type=type_.get_type(),
description=_(type_.description()),
icon=type_.icon64().replace('\n', ''),
).as_dict(**self.typeInfo(type_))
).as_dict(**self.type_info(type_))
if hasattr(type_, 'group'):
res['group'] = _(type_.group) # Add group info is it is contained
return res
def processTableFields(
def process_table_fields(
self,
title: str,
fields: list[typing.Any],
@ -335,7 +336,7 @@ class BaseModelHandler(Handler):
return args
def fillIntanceFields(
def fill_instance_fields(
self, item: 'models.Model', res: dict[str, typing.Any]
) -> dict[str, typing.Any]:
"""
@ -351,7 +352,7 @@ class BaseModelHandler(Handler):
return res
# Exceptions
def invalidRequestException(self, message: typing.Optional[str] = None) -> exceptions.HandlerError:
def invalid_request_response(self, message: typing.Optional[str] = None) -> exceptions.HandlerError:
"""
Raises an invalid request error with a default translated string
:param message: Custom message to add to exception. If it is None, "Invalid Request" is used
@ -359,17 +360,17 @@ class BaseModelHandler(Handler):
message = message or _('Invalid Request')
return exceptions.RequestError(f'{message} {self.__class__}: {self._args}')
def invalidResponseException(self, message: typing.Optional[str] = None) -> exceptions.HandlerError:
def invalid_response_response(self, message: typing.Optional[str] = None) -> exceptions.HandlerError:
message = 'Invalid response' if message is None else message
return exceptions.ResponseError(message)
def invalidMethodException(self) -> exceptions.HandlerError:
def invalid_method_response(self) -> exceptions.HandlerError:
"""
Raises a NotFound exception with translated "Method not found" string to current locale
"""
return exceptions.RequestError(_('Method not found in {}: {}').format(self.__class__, self._args))
def invalidItemException(self, message: typing.Optional[str] = None) -> exceptions.HandlerError:
def invalid_item_response(self, message: typing.Optional[str] = None) -> exceptions.HandlerError:
"""
Raises a NotFound exception, with location info
"""
@ -377,10 +378,10 @@ class BaseModelHandler(Handler):
return exceptions.NotFound(message)
# raise NotFound('{} {}: {}'.format(message, self.__class__, self._args))
def accessDenied(self, message: typing.Optional[str] = None) -> exceptions.HandlerError:
def access_denied_response(self, message: typing.Optional[str] = None) -> exceptions.HandlerError:
return exceptions.AccessDenied(message or _('Access denied'))
def notSupported(self, message: typing.Optional[str] = None) -> exceptions.HandlerError:
def not_supported_response(self, message: typing.Optional[str] = None) -> exceptions.HandlerError:
return exceptions.NotSupportedError(message or _('Operation not supported'))
# Success methods
@ -396,7 +397,7 @@ class BaseModelHandler(Handler):
Invokes a test for an item
"""
logger.debug('Called base test for %s --> %s', self.__class__.__name__, self._params)
raise self.invalidMethodException()
raise self.invalid_method_response()
# Details do not have types at all
@ -406,7 +407,7 @@ class DetailHandler(BaseModelHandler):
"""
Detail handler (for relations such as provider-->services, authenticators-->users,groups, deployed services-->cache,assigned, groups, transports
Urls recognized for GET are:
[path] --> get Items (all items, this call is delegated to getItems)
[path] --> get Items (all items, this call is delegated to get_items)
[path]/overview
[path]/ID
[path]/gui
@ -452,7 +453,7 @@ class DetailHandler(BaseModelHandler):
self._kwargs = kwargs
self._user = kwargs.get('user', None)
def __checkCustom(self, check: str, parent: models.Model, arg: typing.Any = None) -> typing.Any:
def _check_is_custom_method(self, check: str, parent: models.Model, arg: typing.Any = None) -> typing.Any:
"""
checks curron methods
:param check: Method to check
@ -481,18 +482,18 @@ class DetailHandler(BaseModelHandler):
parent: models.Model = self._kwargs['parent']
if nArgs == 0:
return self.getItems(parent, None)
return self.get_items(parent, None)
# if has custom methods, look for if this request matches any of them
r = self.__checkCustom(self._args[0], parent)
r = self._check_is_custom_method(self._args[0], parent)
if r is not None:
return r
if nArgs == 1:
if self._args[0] == OVERVIEW:
return self.getItems(parent, None)
return self.get_items(parent, None)
# if self._args[0] == GUI:
# gui = self.getGui(parent, None)
# gui = self.get_gui(parent, None)
# return sorted(gui, key=lambda f: f['gui']['order'])
if self._args[0] == TYPES:
types_ = self.get_types(parent, None)
@ -500,40 +501,40 @@ class DetailHandler(BaseModelHandler):
return types_
if self._args[0] == GUI:
# Gui without type, valid
gui = self.getGui(parent, '') # No type
gui = self.get_gui(parent, '') # No type
return sorted(gui, key=lambda f: f['gui']['order'])
if self._args[0] == TABLEINFO:
return self.processTableFields(
self.getTitle(parent),
self.getFields(parent),
self.getRowStyle(parent),
return self.process_table_fields(
self.get_title(parent),
self.get_fields(parent),
self.get_row_style(parent),
)
# try to get id
return self.getItems(parent, process_uuid(self._args[0]))
return self.get_items(parent, process_uuid(self._args[0]))
if nArgs == 2:
if self._args[0] == GUI:
gui = self.getGui(parent, self._args[1])
gui = self.get_gui(parent, self._args[1])
return sorted(gui, key=lambda f: f['gui']['order'])
if self._args[0] == TYPES:
types_ = self.get_types(parent, self._args[1])
logger.debug('Types: %s', types_)
return types_
if self._args[1] == LOG:
return self.getLogs(parent, self._args[0])
return self.get_logs(parent, self._args[0])
r = self.__checkCustom(self._args[1], parent, self._args[0])
r = self._check_is_custom_method(self._args[1], parent, self._args[0])
if r is not None:
return r
return self.fallbackGet()
return self.fallback_get()
def put(self) -> typing.Any:
"""
Process the "PUT" operation, making the correspondent checks.
Evaluates if it is a new element or a "modify" operation (based on if it has parameter),
and invokes "saveItem" with parent & item (that can be None for a new Item)
and invokes "save_item" with parent & item (that can be None for a new Item)
"""
logger.debug('Detail args for PUT: %s, %s', self._args, self._params)
@ -544,10 +545,10 @@ class DetailHandler(BaseModelHandler):
if len(self._args) == 1:
item = self._args[0]
elif len(self._args) > 1: # PUT expects 0 or 1 parameters. 0 == NEW, 1 = EDIT
raise self.invalidRequestException()
raise self.invalid_request_response()
logger.debug('Invoking proper saving detail item %s', item)
self.saveItem(parent, item)
self.save_item(parent, item)
# Empty response
return rest_result(consts.OK)
@ -557,34 +558,34 @@ class DetailHandler(BaseModelHandler):
Post can be used for, for example, testing.
Right now is an invalid method for Detail elements
"""
raise self.invalidRequestException('This method does not accepts POST')
raise self.invalid_request_response('This method does not accepts POST')
def delete(self) -> typing.Any:
"""
Process the "DELETE" operation, making the correspondent checks.
Extracts the item id and invokes deleteItem with parent item and item id (uuid)
Extracts the item id and invokes delete_item with parent item and item id (uuid)
"""
logger.debug('Detail args for DELETE: %s', self._args)
parent = self._kwargs['parent']
if len(self._args) != 1:
raise self.invalidRequestException()
raise self.invalid_request_response()
self.deleteItem(parent, self._args[0])
self.delete_item(parent, self._args[0])
return consts.OK
def fallbackGet(self) -> typing.Any:
def fallback_get(self) -> typing.Any:
"""
Invoked if default get can't process request.
Here derived classes can process "non default" (and so, not understood) GET constructions
"""
raise self.invalidRequestException('Fallback invoked')
raise self.invalid_request_response('Fallback invoked')
# Override this to provide functionality
# Default (as sample) getItems
def getItems(
# Default (as sample) get_items
def get_items(
self, parent: models.Model, item: typing.Optional[str]
) -> typing.Union[list[dict], dict]:
"""
@ -596,10 +597,10 @@ class DetailHandler(BaseModelHandler):
# if item is None: # Returns ALL detail items
# return []
# return {} # Returns one item
raise NotImplementedError(f'Must provide an getItems method for {self.__class__} class')
raise NotImplementedError(f'Must provide an get_items method for {self.__class__} class')
# Default save
def saveItem(self, parent: models.Model, item: typing.Optional[str]) -> None:
def save_item(self, parent: models.Model, item: typing.Optional[str]) -> None:
"""
Invoked for a valid "put" operation
If this method is not overridden, the detail class will not have "Save/modify" operations.
@ -608,11 +609,11 @@ class DetailHandler(BaseModelHandler):
:param item: Item id (uuid)
:return: Normally "success" is expected, but can throw any "exception"
"""
logger.debug('Default saveItem handler caller for %s', self._path)
raise self.invalidRequestException()
logger.debug('Default save_item handler caller for %s', self._path)
raise self.invalid_request_response()
# Default delete
def deleteItem(self, parent: models.Model, item: str) -> None:
def delete_item(self, parent: models.Model, item: str) -> None:
"""
Invoked for a valid "delete" operation.
If this method is not overriden, the detail class will not have "delete" operation.
@ -620,10 +621,10 @@ class DetailHandler(BaseModelHandler):
:param item: Item id (uuid)
:return: Normally "success" is expected, but can throw any "exception"
"""
raise self.invalidRequestException()
raise self.invalid_request_response()
# A detail handler must also return title & fields for tables
def getTitle(self, parent: models.Model) -> str: # pylint: disable=no-self-use
def get_title(self, parent: models.Model) -> str: # pylint: disable=no-self-use
"""
A "generic" title for a view based on this detail.
If not overridden, defaults to ''
@ -632,7 +633,7 @@ class DetailHandler(BaseModelHandler):
"""
return ''
def getFields(self, parent: models.Model) -> list[typing.Any]:
def get_fields(self, parent: models.Model) -> list[typing.Any]:
"""
A "generic" list of fields for a view based on this detail.
If not overridden, defaults to emty list
@ -641,7 +642,7 @@ class DetailHandler(BaseModelHandler):
"""
return []
def getRowStyle(self, parent: models.Model) -> dict[str, typing.Any]:
def get_row_style(self, parent: models.Model) -> dict[str, typing.Any]:
"""
A "generic" row style based on row field content.
If not overridden, defaults to {}
@ -654,7 +655,7 @@ class DetailHandler(BaseModelHandler):
"""
return {}
def getGui(self, parent: models.Model, forType: str) -> collections.abc.Iterable[typing.Any]:
def get_gui(self, parent: models.Model, forType: str) -> collections.abc.Iterable[typing.Any]:
"""
Gets the gui that is needed in order to "edit/add" new items on this detail
If not overriden, means that the detail has no edit/new Gui
@ -677,14 +678,14 @@ class DetailHandler(BaseModelHandler):
"""
return [] # Default is that details do not have types
def getLogs(self, parent: models.Model, item: str) -> list[typing.Any]:
def get_logs(self, parent: models.Model, item: str) -> list[typing.Any]:
"""
If the detail has any log associated with it items, provide it overriding this method
:param parent:
:param item:
:return: a list of log elements (normally got using "uds.core.util.log.getLogs" method)
:return: a list of log elements (normally got using "uds.core.util.log.get_logs" method)
"""
raise self.invalidMethodException()
raise self.invalid_method_response()
class ModelHandler(BaseModelHandler):
@ -731,7 +732,7 @@ class ModelHandler(BaseModelHandler):
# * If a field is in the form "field:default" and field is not present in the request, default will be used
# * If the "default" is the string "None", then the default will be None
# * If the "default" is _ (underscore), then the field will be ignored (not saved) if not present in the request
# Note that these fields has to be present in the model, and they can be "edited" in the beforeSave method
# Note that these fields has to be present in the model, and they can be "edited" in the pre_save method
save_fields: typing.ClassVar[list[str]] = []
# Put removable fields before updating
remove_fields: typing.ClassVar[list[str]] = []
@ -768,7 +769,7 @@ class ModelHandler(BaseModelHandler):
def get_types(self, *args, **kwargs) -> typing.Generator[dict[str, typing.Any], None, None]:
for type_ in self.enum_types():
yield self.typeAsDict(type_)
yield self.type_as_dict(type_)
def get_type(self, type_: str) -> dict[str, typing.Any]:
found = None
@ -784,8 +785,8 @@ class ModelHandler(BaseModelHandler):
return found
# log related
def getLogs(self, item: models.Model) -> list[dict]:
self.ensureAccess(item, types.permissions.PermissionType.READ)
def get_logs(self, item: models.Model) -> list[dict]:
self.ensure_has_access(item, types.permissions.PermissionType.READ)
try:
return log.get_logs(item)
except Exception as e:
@ -793,31 +794,31 @@ class ModelHandler(BaseModelHandler):
return []
# gui related
def getGui(self, type_: str) -> list[typing.Any]:
def get_gui(self, type_: str) -> list[typing.Any]:
return []
# raise self.invalidRequestException()
# Delete related, checks if the item can be deleted
# If it can't be so, raises an exception
def checkDelete(self, item: models.Model) -> None:
def validate_delete(self, item: models.Model) -> None:
pass
# Save related, checks if the item can be saved
# If it can't be saved, raises an exception
def checkSave(self, item: models.Model) -> None:
def validate_save(self, item: models.Model) -> None:
pass
# Invoked to possibily fix fields (or add new one, or check
def beforeSave(self, fields: dict[str, typing.Any]) -> None:
def pre_save(self, fields: dict[str, typing.Any]) -> None:
pass
# Invoked right after saved an item (no matter if new or edition)
def afterSave(self, item: models.Model) -> None:
def post_save(self, item: models.Model) -> None:
pass
# End overridable
def extractFilter(self) -> None:
def extract_filter(self) -> None:
# Extract filter from params if present
self.fltr = None
if 'filter' in self._params:
@ -825,7 +826,7 @@ class ModelHandler(BaseModelHandler):
del self._params['filter'] # Remove parameter
logger.debug('Found a filter expression (%s)', self.fltr)
def doFilter(self, data: typing.Any) -> typing.Any:
def filter(self, data: typing.Any) -> typing.Any:
# Right now, filtering only supports a single filter, in a future
# we may improve it
if self.fltr is None:
@ -867,7 +868,7 @@ class ModelHandler(BaseModelHandler):
# Helper to process detail
# Details can be managed (writen) by any user that has MANAGEMENT permission over parent
def processDetail(self) -> typing.Any:
def process_detail(self) -> typing.Any:
logger.debug('Processing detail %s for with params %s', self._path, self._params)
try:
item: models.Model = self.model.objects.filter(uuid=self._args[0])[0] # type: ignore # Slicing is not supported by pylance right now
@ -884,10 +885,10 @@ class ModelHandler(BaseModelHandler):
self._user,
requiredPermission,
)
raise self.accessDenied()
raise self.access_denied_response()
if not self.detail:
raise self.invalidRequestException()
raise self.invalid_request_response()
# pylint: disable=unsubscriptable-object
detailCls = self.detail[self._args[1]]
@ -898,16 +899,16 @@ class ModelHandler(BaseModelHandler):
return method()
except IndexError as e:
raise self.invalidItemException() from e
raise self.invalid_item_response() from e
except (KeyError, AttributeError) as e:
raise self.invalidMethodException() from e
raise self.invalid_method_response() from e
except exceptions.HandlerError:
raise
except Exception as e:
logger.error('Exception processing detail: %s', e)
raise self.invalidRequestException() from e
raise self.invalid_request_response() from e
def getItems(self, *args, **kwargs) -> typing.Generator[collections.abc.MutableMapping[str, typing.Any], None, None]:
def get_items(self, *args, **kwargs) -> typing.Generator[collections.abc.MutableMapping[str, typing.Any], None, None]:
if 'overview' in kwargs:
overview = kwargs['overview']
del kwargs['overview']
@ -950,7 +951,7 @@ class ModelHandler(BaseModelHandler):
yield self.item_as_dict_overview(item)
else:
res = self.item_as_dict(item)
self.fillIntanceFields(item, res)
self.fill_instance_fields(item, res)
yield res
except Exception as e: # maybe an exception is thrown to skip an item
logger.debug('Got exception processing item from model: %s', e)
@ -961,16 +962,16 @@ class ModelHandler(BaseModelHandler):
Wraps real get method so we can process filters if they exists
"""
# Extract filter from params if present
self.extractFilter()
return self.doFilter(self.doGet())
self.extract_filter()
return self.filter(self.process_get())
# pylint: disable=too-many-return-statements
def doGet(self) -> typing.Any:
def process_get(self) -> typing.Any:
logger.debug('method GET for %s, %s', self.__class__.__name__, self._args)
nArgs = len(self._args)
if nArgs == 0:
return list(self.getItems(overview=False))
return list(self.get_items(overview=False))
# if has custom methods, look for if this request matches any of them
for cm in self.custom_methods:
@ -988,7 +989,7 @@ class ModelHandler(BaseModelHandler):
self._params,
e,
)
raise self.invalidMethodException()
raise self.invalid_method_response()
return operation(item)
@ -997,69 +998,69 @@ class ModelHandler(BaseModelHandler):
try:
operation = getattr(self, self._args[0])
except Exception as e:
raise self.invalidMethodException() from e
raise self.invalid_method_response() from e
return operation()
if nArgs == 1:
if self._args[0] == OVERVIEW:
return list(self.getItems())
return list(self.get_items())
if self._args[0] == TYPES:
return list(self.get_types())
if self._args[0] == TABLEINFO:
return self.processTableFields(
return self.process_table_fields(
self.table_title,
self.table_fields,
self.table_row_style,
self.table_subtitle,
)
if self._args[0] == GUI:
return self.getGui('')
return self.get_gui('')
# get item ID
try:
item = self.model.objects.get(uuid=self._args[0].lower()) # type: ignore # mypy complains about type of model
self.ensureAccess(item, types.permissions.PermissionType.READ)
self.ensure_has_access(item, types.permissions.PermissionType.READ)
res = self.item_as_dict(item)
self.fillIntanceFields(item, res)
self.fill_instance_fields(item, res)
return res
except Exception as e:
logger.exception('Got Exception looking for item')
raise self.invalidItemException() from e
raise self.invalid_item_response() from e
# nArgs > 1
# Request type info or gui, or detail
if self._args[0] == OVERVIEW:
if nArgs != 2:
raise self.invalidRequestException()
raise self.invalid_request_response()
elif self._args[0] == TYPES:
if nArgs != 2:
raise self.invalidRequestException()
raise self.invalid_request_response()
return self.get_type(self._args[1])
elif self._args[0] == GUI:
if nArgs != 2:
raise self.invalidRequestException()
gui = self.getGui(self._args[1])
raise self.invalid_request_response()
gui = self.get_gui(self._args[1])
return sorted(gui, key=lambda f: f['gui']['order'])
elif self._args[1] == LOG:
if nArgs != 2:
raise self.invalidRequestException()
raise self.invalid_request_response()
try:
# DB maybe case sensitive??, anyway, uuids are stored in lowercase
item = self.model.objects.get( # type: ignore # mypy complains about type of model
uuid=self._args[0].lower()
)
return self.getLogs(item)
return self.get_logs(item)
except Exception as e:
raise self.invalidItemException() from e
raise self.invalid_item_response() from e
# If has detail and is requesting detail
if self.detail is not None:
return self.processDetail()
return self.process_detail()
raise self.invalidRequestException() # Will not return
raise self.invalid_request_response() # Will not return
def post(self) -> typing.Any:
"""
@ -1071,7 +1072,7 @@ class ModelHandler(BaseModelHandler):
if self._args[0] == 'test':
return self.test(self._args[1])
raise self.invalidMethodException() # Will not return
raise self.invalid_method_response() # Will not return
def put(self) -> typing.Any:
"""
@ -1086,10 +1087,10 @@ class ModelHandler(BaseModelHandler):
deleteOnError = False
if len(self._args) > 1: # Detail?
return self.processDetail()
return self.process_detail()
# Here, self.model() indicates an "django model object with default params"
self.ensureAccess(
self.ensure_has_access(
self.model(), types.permissions.PermissionType.ALL, root=True
) # Must have write permissions to create, modify, etc..
@ -1097,7 +1098,7 @@ class ModelHandler(BaseModelHandler):
# Extract fields
args = self.fields_from_params(self.save_fields)
logger.debug('Args: %s', args)
self.beforeSave(args)
self.pre_save(args)
# If tags is in save fields, treat it "specially"
if 'tags' in self.save_fields:
tags = args['tags']
@ -1129,7 +1130,7 @@ class ModelHandler(BaseModelHandler):
item.tags.clear()
if not deleteOnError:
self.checkSave(
self.validate_save(
item
) # Will raise an exception if item can't be saved (only for modify operations..)
@ -1144,14 +1145,14 @@ class ModelHandler(BaseModelHandler):
item.save()
res = self.item_as_dict(item)
self.fillIntanceFields(item, res)
self.fill_instance_fields(item, res)
except Exception:
logger.exception('Exception on put')
if deleteOnError:
item.delete()
raise
self.afterSave(item)
self.post_save(item)
return res
@ -1173,25 +1174,25 @@ class ModelHandler(BaseModelHandler):
"""
logger.debug('method DELETE for %s, %s', self.__class__.__name__, self._args)
if len(self._args) > 1:
return self.processDetail()
return self.process_detail()
if len(self._args) != 1:
raise exceptions.RequestError('Delete need one and only one argument')
self.ensureAccess(
self.ensure_has_access(
self.model(), types.permissions.PermissionType.ALL, root=True
) # Must have write permissions to delete
try:
item = self.model.objects.get(uuid=self._args[0].lower()) # type: ignore # mypy complains about type of model
self.checkDelete(item)
self.deleteItem(item)
self.validate_delete(item)
self.delete_item(item)
except self.model.DoesNotExist: # type: ignore # mypy complains about type of model
raise exceptions.NotFound('Element do not exists') from None
return consts.OK
def deleteItem(self, item: models.Model) -> None:
def delete_item(self, item: models.Model) -> None:
"""
Basic, overridable method for deleting an item
"""

View File

@ -74,9 +74,9 @@ class IPAuth(auths.Authenticator):
type_description = _('IP Authenticator')
icon_file = 'auth.png'
needsPassword = False
userNameLabel = _('IP')
groupNameLabel = _('IP Range')
needs_password = False
label_username = _('IP')
label_groupname = _('IP Range')
isExternalSource = True
blockUserOnLoginFailures = False

View File

@ -63,7 +63,7 @@ class InternalDBAuth(auths.Authenticator):
icon_file = 'auth.png'
# If we need to enter the password for this user
needsPassword = True
needs_password = True
# This is the only internal source
isExternalSource = False

View File

@ -59,8 +59,8 @@ class RadiusAuth(auths.Authenticator):
type_description = _('Radius Authenticator')
icon_file = 'radius.png'
userNameLabel = _('User')
groupNameLabel = _('Group')
label_username = _('User')
label_groupname = _('Group')
server = gui.TextField(
length=64,

View File

@ -203,13 +203,13 @@ class RegexLdap(auths.Authenticator):
# If it has and external source where to get "new" users (groups must be declared inside UDS)
isExternalSource = True
# If we need to enter the password for this user
needsPassword = False
needs_password = False
# Label for username field
userNameLabel = _('Username')
label_username = _('Username')
# Label for group field
groupNameLabel = _("Group")
label_groupname = _("Group")
# Label for password field
passwordLabel = _("Password")
label_password = _("Password")
_connection: typing.Any = None
_host: str = ''

View File

@ -105,13 +105,13 @@ class SAMLAuthenticator(auths.Authenticator):
# : If we need to enter the password for this user when creating a new
# : user at administration interface. Used basically by internal authenticator.
# : False is the default value, so this is not needed in fact
# : needsPassword = False
# : needs_password = False
# : Label for username field, shown at administration interface user form.
userNameLabel = _('User')
label_username = _('User')
# Label for group field, shown at administration interface user form.
groupNameLabel = _('Group')
label_groupname = _('Group')
# : Definition of this type of authenticator form
# : We will define a simple form where we will use a simple

View File

@ -107,13 +107,13 @@ class SampleAuth(auths.Authenticator):
# : If we need to enter the password for this user when creating a new
# : user at administration interface. Used basically by internal authenticator.
# : False is the default value, so this is not needed in fact
# : needsPassword = False
# : needs_password = False
# : Label for username field, shown at administration interface user form.
userNameLabel = _('Fake User')
label_username = _('Fake User')
# Label for group field, shown at administration interface user form.
groupNameLabel = _('Fake Group')
label_groupname = _('Fake Group')
# : Definition of this type of authenticator form
# : We will define a simple form where we will use a simple

View File

@ -196,13 +196,13 @@ class SimpleLDAPAuthenticator(auths.Authenticator):
# If it has and external source where to get "new" users (groups must be declared inside UDS)
isExternalSource = True
# If we need to enter the password for this user
needsPassword = False
needs_password = False
# Label for username field
userNameLabel = _('Username')
label_username = _('Username')
# Label for group field
groupNameLabel = _("Group")
label_groupname = _("Group")
# Label for password field
passwordLabel = _("Password")
label_password = _("Password")
_connection: typing.Any = None
_host: str = ''

View File

@ -441,7 +441,7 @@ def web_login(
# Ensures that this user will have access through REST api if logged in through web interface
# Note that REST api will set the session expiry to selected value if user is an administrator
REST.Handler.storeSessionAuthdata(
REST.Handler.set_rest_auth(
request.session,
manager_id,
user.name,

View File

@ -138,18 +138,18 @@ class Authenticator(Module):
# : If we need to enter the password for this user when creating a new
# : user at administration interface. Used basically by internal authenticator.
needsPassword: typing.ClassVar[bool] = False
needs_password: typing.ClassVar[bool] = False
# : Label for username field, shown at administration interface user form.
userNameLabel: typing.ClassVar[str] = _('User name')
label_username: typing.ClassVar[str] = _('User name')
# : Label for group field, shown at administration interface user form.
groupNameLabel: typing.ClassVar[str] = _('Group name')
label_groupname: typing.ClassVar[str] = _('Group name')
# : Label for password field, , shown at administration interface user form.
# : Not needed for external authenticators (where credentials are stored with
# : an already existing user.
passwordLabel: typing.ClassVar[str] = _('Password')
label_password: typing.ClassVar[str] = _('Password')
# : If this authenticators casues a temporal block of an user on repeated login failures
blockUserOnLoginFailures: typing.ClassVar[bool] = True

File diff suppressed because one or more lines are too long

View File

@ -102,6 +102,6 @@
</svg>
</div>
</uds-root>
<script src="/uds/res/admin/runtime.js?stamp=1704725462" type="module"></script><script src="/uds/res/admin/polyfills.js?stamp=1704725462" type="module"></script><script src="/uds/res/admin/main.js?stamp=1704725462" type="module"></script></body>
<script src="/uds/res/admin/runtime.js?stamp=1704764627" type="module"></script><script src="/uds/res/admin/polyfills.js?stamp=1704764627" type="module"></script><script src="/uds/res/admin/main.js?stamp=1704764627" type="module"></script></body>
</html>

View File

@ -83,22 +83,11 @@ class GroupsTest(rest.test.RESTActorTestCase):
self.assertIn('fields', tableinfo)
self.assertIn('row-style', tableinfo)
# Ensure at least name, comments ans state are present on tableinfo['fields']
fields: list[collections.abc.Mapping[str, typing.Any]] = tableinfo['fields']
self.assertTrue(
functools.reduce(
lambda x, y: x and y,
map(
lambda f: next(iter(f.keys()))
in (
'name',
'comments',
'state',
),
fields,
),
)
)
# Ensure at least name, comments, state and skip_mfa are present on tableinfo['fields']
# fields: list[collections.abc.Mapping[str, typing.Any]] = tableinfo['fields']
fields: list[str] = [list(k.keys())[0] for k in tableinfo['fields']]
for i in ('name', 'comments', 'state', 'skip_mfa'):
self.assertIn(i, fields)
def test_group(self) -> None:
url = f'authenticators/{self.auth.uuid}/groups'
@ -116,7 +105,7 @@ class GroupsTest(rest.test.RESTActorTestCase):
def test_group_create_edit(self) -> None:
url = f'authenticators/{self.auth.uuid}/groups'
# Normal group
group_dct = rest_fixtures.createGroup()
group_dct = rest_fixtures.create_group()
response = self.client.rest_put(
url,
group_dct,
@ -136,7 +125,7 @@ class GroupsTest(rest.test.RESTActorTestCase):
# Now a meta group, with some groups inside
# groups = [self.simple_groups[0].uuid]
group_dct = rest_fixtures.createGroup(
group_dct = rest_fixtures.create_group(
meta=True, groups=[self.simple_groups[0].uuid, self.simple_groups[1].uuid]
)

View File

@ -57,6 +57,7 @@ class GroupRestStruct(rest.RestStruct):
type: str
is_meta: bool
meta_if_any: bool
skip_mfa: str # 'A' or 'I' (State.ACTIVE or State.INACTIVE)
# ServicePool REST structure
@ -96,9 +97,10 @@ def createUser(**kwargs) -> dict[str, typing.Any]:
return data
def createGroup(**kwargs) -> dict[str, typing.Any]:
def create_group(**kwargs) -> dict[str, typing.Any]:
data = GroupRestStruct.random_create(**kwargs).as_dict()
data['state'] = 'A' # Fix state to 1 char
data['skip_mfa'] = 'A' # Fix state to 1 char
return data