forked from shaba/openuds
fixes for python 3.x
This commit is contained in:
parent
0b97c15ca8
commit
6309047a34
@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -30,12 +30,9 @@
|
||||
"""
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
__updated__ = '2014-11-12'
|
||||
|
||||
|
||||
class AuthsFactory(object):
|
||||
class AuthsFactory:
|
||||
"""
|
||||
This class holds the register of all known authentication modules
|
||||
inside UDS.
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -31,20 +31,18 @@ Base module for all authenticators
|
||||
|
||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from uds.core import Module
|
||||
from django.utils.translation import ugettext_noop as _
|
||||
from uds.core.auths.GroupsManager import GroupsManager
|
||||
from uds.core.auths.Exceptions import InvalidUserException
|
||||
import logging
|
||||
|
||||
__updated__ = '2019-01-21'
|
||||
from django.utils.translation import ugettext_noop as _
|
||||
from uds.core import Module
|
||||
from uds.core.auths.GroupsManager import GroupsManager
|
||||
from uds.core.auths.Exceptions import InvalidUserException
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Authenticator(Module):
|
||||
class Authenticator(Module): # pylint: disable=too-many-public-methods
|
||||
"""
|
||||
This class represents the base interface to implement authenticators.
|
||||
|
||||
@ -181,7 +179,6 @@ class Authenticator(Module):
|
||||
|
||||
Default implementation does nothing
|
||||
"""
|
||||
pass
|
||||
|
||||
def dbAuthenticator(self):
|
||||
"""
|
||||
@ -430,7 +427,6 @@ class Authenticator(Module):
|
||||
calling its :py:meth:`uds.core.auths.GroupsManager.validate` method with groups names provided by the authenticator itself
|
||||
(for example, LDAP, AD, ...)
|
||||
"""
|
||||
pass
|
||||
|
||||
def getJavascript(self, request):
|
||||
"""
|
||||
@ -582,7 +578,6 @@ class Authenticator(Module):
|
||||
:note: By default, this will do nothing, as we can only modify "accesory" internal
|
||||
data of users.
|
||||
"""
|
||||
pass
|
||||
|
||||
def createGroup(self, groupData):
|
||||
"""
|
||||
@ -609,7 +604,6 @@ class Authenticator(Module):
|
||||
Take care with whatever you modify here, you can even modify provided
|
||||
name (group name) to a new one!
|
||||
"""
|
||||
pass
|
||||
|
||||
def modifyGroup(self, groupData):
|
||||
"""
|
||||
@ -635,7 +629,6 @@ class Authenticator(Module):
|
||||
|
||||
Note: 'name' output parameter will be ignored
|
||||
"""
|
||||
pass
|
||||
|
||||
def removeUser(self, username):
|
||||
"""
|
||||
@ -650,7 +643,6 @@ class Authenticator(Module):
|
||||
|
||||
If this method raises an exception, the user will not be removed from UDS
|
||||
"""
|
||||
pass
|
||||
|
||||
# We don't have a "modify" group option. Once u have created it, the only way of changing it if removing it an recreating it with another name
|
||||
|
||||
@ -667,4 +659,3 @@ class Authenticator(Module):
|
||||
|
||||
If this method raises an exception, the group will not be removed from UDS
|
||||
"""
|
||||
pass
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -30,30 +30,23 @@
|
||||
"""
|
||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
__updated__ = '2014-02-19'
|
||||
|
||||
|
||||
class AuthenticatorException(Exception):
|
||||
"""
|
||||
Generic authentication exception
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class InvalidUserException(AuthenticatorException):
|
||||
"""
|
||||
Invalid user specified. The user cant access the requested service
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class InvalidAuthenticatorException(AuthenticatorException):
|
||||
"""
|
||||
Invalida authenticator has been specified
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class Redirect(Exception):
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
@ -31,37 +31,40 @@
|
||||
"""
|
||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import six
|
||||
import logging
|
||||
import typing
|
||||
|
||||
from uds.models import Group as DBGroup
|
||||
|
||||
# Imports for type checking
|
||||
if typing.TYPE_CHECKING:
|
||||
from uds.core.auths.BaseAuthenticator import Authenticator as AuthenticatorInstance
|
||||
|
||||
__updated__ = '2018-01-05'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Group(object):
|
||||
class Group:
|
||||
"""
|
||||
A group is simply a database group associated with its authenticator instance
|
||||
|
||||
It's only constructor expect a database group as parameter.
|
||||
"""
|
||||
|
||||
def __init__(self, dbGroup):
|
||||
def __init__(self, dbGroup: DBGroup):
|
||||
"""
|
||||
Initializes internal data
|
||||
"""
|
||||
self._manager = dbGroup.getManager()
|
||||
self._dbGroup = dbGroup
|
||||
|
||||
def manager(self):
|
||||
def manager(self) -> 'AuthenticatorInstance':
|
||||
"""
|
||||
Returns the database authenticator associated with this group
|
||||
"""
|
||||
return self._manager
|
||||
|
||||
def dbGroup(self):
|
||||
def dbGroup(self) -> DBGroup:
|
||||
"""
|
||||
Returns the database group associated with this
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -30,23 +30,22 @@
|
||||
"""
|
||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
import re
|
||||
import logging
|
||||
import typing
|
||||
|
||||
from collections.abc import Iterable
|
||||
|
||||
from uds.core.util.State import State
|
||||
from uds.models import Group as dbGroup
|
||||
from uds.core.auths.Group import Group
|
||||
from uds.models import Group as DBGroup
|
||||
from uds.models import Authenticator as DBAuthenticator
|
||||
from .Group import Group
|
||||
|
||||
import six
|
||||
import re
|
||||
import inspect
|
||||
import logging
|
||||
|
||||
__updated__ = '2018-02-01'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GroupsManager(object):
|
||||
class GroupsManager:
|
||||
"""
|
||||
Manages registered groups for an specific authenticator.
|
||||
|
||||
@ -65,8 +64,9 @@ class GroupsManager(object):
|
||||
|
||||
Managed groups names are compared using case insensitive comparison.
|
||||
"""
|
||||
_groups: typing.Dict[str, dict]
|
||||
|
||||
def __init__(self, dbAuthenticator):
|
||||
def __init__(self, dbAuthenticator: DBAuthenticator):
|
||||
"""
|
||||
Initializes the groups manager.
|
||||
The dbAuthenticator is the database record of the authenticator
|
||||
@ -79,74 +79,73 @@ class GroupsManager(object):
|
||||
isPattern = name.find('pat:') == 0 # Is a pattern?
|
||||
self._groups[name] = {'name': g.name, 'group': Group(g), 'valid': False, 'pattern': isPattern}
|
||||
|
||||
def checkAllGroups(self, groupName):
|
||||
def checkAllGroups(self, groupName: str):
|
||||
"""
|
||||
Returns true if this groups manager contains the specified group name (string)
|
||||
"""
|
||||
name = groupName.lower()
|
||||
res = []
|
||||
for gName, grp in six.iteritems(self._groups):
|
||||
for gName, grp in self._groups.items():
|
||||
if grp['pattern'] is True:
|
||||
logger.debug('Group is a pattern: {}'.format(grp))
|
||||
logger.debug('Group is a pattern: %s', grp)
|
||||
try:
|
||||
logger.debug('Match: {}->{}'.format(grp['name'][4:], name))
|
||||
logger.debug('Match: %s->%s', grp['name'][4:], name)
|
||||
if re.search(grp['name'][4:], name, re.IGNORECASE) is not None:
|
||||
res.append(grp) # Stop searching, one group at least matches
|
||||
except Exception:
|
||||
logger.exception('Exception in RE')
|
||||
else:
|
||||
logger.debug('Group: {}=={}'.format(name, gName))
|
||||
logger.debug('Group: %s==%s', name, gName)
|
||||
if name == gName:
|
||||
res.append(grp)
|
||||
return res
|
||||
|
||||
def getGroupsNames(self):
|
||||
def getGroupsNames(self) -> typing.Iterable[str]:
|
||||
"""
|
||||
Return all groups names managed by this groups manager. The names are returned
|
||||
as where inserted inside Database (most probably using administration interface)
|
||||
"""
|
||||
for g in six.itervalues(self._groups):
|
||||
yield g['group'].dbGroup().name
|
||||
for g in self._groups.values():
|
||||
yield g['group'].DBGroup().name
|
||||
|
||||
def getValidGroups(self):
|
||||
def getValidGroups(self) -> typing.Iterable[Group]:
|
||||
"""
|
||||
returns the list of valid groups (:py:class:uds.core.auths.Group.Group)
|
||||
"""
|
||||
lst = ()
|
||||
for g in six.itervalues(self._groups):
|
||||
lst: typing.List[str] = []
|
||||
for g in self._groups.values():
|
||||
if g['valid'] is True:
|
||||
lst += (g['group'].dbGroup().id,)
|
||||
lst += (g['group'].DBGroup().id,)
|
||||
yield g['group']
|
||||
# Now, get metagroups and also return them
|
||||
for g in dbGroup.objects.filter(manager__id=self._dbAuthenticator.id, is_meta=True): # @UndefinedVariable
|
||||
gn = g.groups.filter(id__in=lst, state=State.ACTIVE).count()
|
||||
if g.meta_if_any is True and gn > 0:
|
||||
gn = g.groups.count()
|
||||
if gn == g.groups.count(): # If a meta group is empty, all users belongs to it. we can use gn != 0 to check that if it is empty, is not valid
|
||||
for g2 in DBGroup.objects.filter(manager__id=self._dbAuthenticator.id, is_meta=True): # @UndefinedVariable
|
||||
gn = g2.groups.filter(id__in=lst, state=State.ACTIVE).count()
|
||||
if g2.meta_if_any is True and gn > 0:
|
||||
gn = g2.groups.count()
|
||||
if gn == g2.groups.count(): # If a meta group is empty, all users belongs to it. we can use gn != 0 to check that if it is empty, is not valid
|
||||
# This group matches
|
||||
yield Group(g)
|
||||
yield Group(g2)
|
||||
|
||||
def hasValidGroups(self):
|
||||
"""
|
||||
Checks if this groups manager has at least one group that has been
|
||||
validated (using :py:meth:.validate)
|
||||
"""
|
||||
for g in six.itervalues(self._groups):
|
||||
for g in self._groups.values():
|
||||
if g['valid'] is True:
|
||||
return True
|
||||
return False
|
||||
|
||||
def getGroup(self, groupName):
|
||||
def getGroup(self, groupName: str) -> typing.Optional[Group]:
|
||||
"""
|
||||
If this groups manager contains that group manager, it returns the
|
||||
:py:class:uds.core.auths.Group.Group representing that group name.
|
||||
"""
|
||||
if groupName.lower() in self._groups:
|
||||
return self._groups[groupName.lower()]['group']
|
||||
else:
|
||||
return None
|
||||
return None
|
||||
|
||||
def validate(self, groupName):
|
||||
def validate(self, groupName: typing.Union[str, typing.Iterable]):
|
||||
"""
|
||||
Validates that the group groupName passed in is valid for this group manager.
|
||||
|
||||
@ -158,14 +157,14 @@ class GroupsManager(object):
|
||||
Returns nothing, it changes the groups this groups contains attributes,
|
||||
so they reflect the known groups that are considered valid.
|
||||
"""
|
||||
if type(groupName) is tuple or type(groupName) is list or inspect.isgenerator(groupName):
|
||||
if isinstance(groupName, Iterable):
|
||||
for n in groupName:
|
||||
self.validate(n)
|
||||
else:
|
||||
for grp in self.checkAllGroups(groupName):
|
||||
grp['valid'] = True
|
||||
|
||||
def isValid(self, groupName):
|
||||
def isValid(self, groupName: str) -> bool:
|
||||
"""
|
||||
Checks if this group name is marked as valid inside this groups manager.
|
||||
Returns True if group name is marked as valid, False if it isn't.
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -30,20 +30,30 @@
|
||||
"""
|
||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import logging
|
||||
import typing
|
||||
|
||||
from uds.models import Group as DBGroup, User as DBUser
|
||||
from .GroupsManager import GroupsManager
|
||||
from .Group import Group
|
||||
|
||||
# Imports for type checking
|
||||
if typing.TYPE_CHECKING:
|
||||
from uds.core.auths.BaseAuthenticator import Authenticator as AuthenticatorInstance
|
||||
|
||||
__updated__ = '2018-09-04'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class User(object):
|
||||
class User:
|
||||
"""
|
||||
An user represents a database user, associated with its authenticator (instance)
|
||||
and its groups.
|
||||
"""
|
||||
_manager: 'AuthenticatorInstance'
|
||||
_grpsManager: typing.Optional[GroupsManager]
|
||||
_dbUser: DBUser
|
||||
_groups: typing.Optional[typing.List[Group]]
|
||||
|
||||
def __init__(self, dbUser):
|
||||
self._manager = dbUser.getManager()
|
||||
@ -51,19 +61,17 @@ class User(object):
|
||||
self._dbUser = dbUser
|
||||
self._groups = None
|
||||
|
||||
def _groupsManager(self):
|
||||
def _groupsManager(self) -> GroupsManager:
|
||||
"""
|
||||
If the groups manager for this user already exists, it returns this.
|
||||
If it does not exists, it creates one default from authenticator and
|
||||
returns it.
|
||||
"""
|
||||
from .GroupsManager import GroupsManager
|
||||
|
||||
if self._grpsManager is None:
|
||||
self._grpsManager = GroupsManager(self._manager.dbAuthenticator())
|
||||
return self._grpsManager
|
||||
|
||||
def groups(self):
|
||||
def groups(self) -> typing.List[Group]:
|
||||
"""
|
||||
Returns the valid groups for this user.
|
||||
To do this, it will validate groups through authenticator instance using
|
||||
@ -71,34 +79,31 @@ class User(object):
|
||||
|
||||
:note: Once obtained valid groups, it caches them until object removal.
|
||||
"""
|
||||
from uds.models import User as DbUser
|
||||
from uds.core.auths.Group import Group
|
||||
|
||||
if self._groups is None:
|
||||
if self._manager.isExternalSource is True:
|
||||
self._manager.getGroups(self._dbUser.name, self._groupsManager())
|
||||
self._groups = list(self._groupsManager().getValidGroups())
|
||||
logger.debug(self._groups)
|
||||
# This is just for updating "cached" data of this user, we only get real groups at login and at modify user operation
|
||||
usr = DbUser.objects.get(pk=self._dbUser.id) # @UndefinedVariable
|
||||
lst = ()
|
||||
usr = DBUser.objects.get(pk=self._dbUser.id) # @UndefinedVariable
|
||||
lst: typing.List[DBGroup] = []
|
||||
for g in self._groups:
|
||||
if g.dbGroup().is_meta is False:
|
||||
lst += (g.dbGroup().id,)
|
||||
usr.groups.set(lst)
|
||||
else:
|
||||
# From db
|
||||
usr = DbUser.objects.get(pk=self._dbUser.id) # @UndefinedVariable
|
||||
usr = DBUser.objects.get(pk=self._dbUser.id) # @UndefinedVariable
|
||||
self._groups = [Group(g) for g in usr.getGroups()]
|
||||
return self._groups
|
||||
|
||||
def manager(self):
|
||||
def manager(self) -> 'AuthenticatorInstance':
|
||||
"""
|
||||
Returns the authenticator instance
|
||||
"""
|
||||
return self._manager
|
||||
|
||||
def dbUser(self):
|
||||
def dbUser(self) -> DBUser:
|
||||
"""
|
||||
Returns the database user
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -32,16 +32,12 @@ UDS authentication related interfaces and classes
|
||||
|
||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from uds.core.auths.BaseAuthenticator import Authenticator
|
||||
from uds.core.auths.User import User
|
||||
from uds.core.auths.Group import Group
|
||||
from uds.core.auths.GroupsManager import GroupsManager
|
||||
from uds.core.auths import Exceptions
|
||||
|
||||
__updated__ = '2014-11-11'
|
||||
|
||||
|
||||
def factory():
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -33,10 +33,11 @@ Provides useful functions for authenticating, used by web interface.
|
||||
|
||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
import logging
|
||||
import typing
|
||||
|
||||
from functools import wraps
|
||||
from django.http import HttpResponseRedirect, HttpResponseForbidden
|
||||
from django.http import HttpResponseRedirect, HttpResponseForbidden, HttpResponse, HttpRequest
|
||||
from django.utils.translation import get_language
|
||||
from django.utils.decorators import available_attrs
|
||||
from django.urls import reverse
|
||||
@ -49,12 +50,9 @@ from uds.core import auths
|
||||
from uds.core.util.stats import events
|
||||
from uds.core.managers import cryptoManager
|
||||
from uds.core.util.State import State
|
||||
from uds.models import User
|
||||
from uds.models import User, Authenticator
|
||||
from uds.core.auths.BaseAuthenticator import Authenticator as AuthenticatorInstance
|
||||
|
||||
import logging
|
||||
import six
|
||||
|
||||
__updated__ = '2019-01-21'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
authLogger = logging.getLogger('authLog')
|
||||
@ -64,7 +62,7 @@ PASS_KEY = 'pk'
|
||||
ROOT_ID = -20091204 # Any negative number will do the trick
|
||||
|
||||
|
||||
def getUDSCookie(request, response=None, force=False):
|
||||
def getUDSCookie(request: HttpRequest, response: typing.Optional[HttpResponse] = None, force: bool = False) -> str:
|
||||
'''
|
||||
Generates a random cookie for uds, used, for example, to encript things
|
||||
'''
|
||||
@ -84,9 +82,10 @@ def getUDSCookie(request, response=None, force=False):
|
||||
|
||||
def getRootUser():
|
||||
# pylint: disable=unexpected-keyword-arg, no-value-for-parameter
|
||||
from uds.models import Authenticator
|
||||
u = User(id=ROOT_ID, name=GlobalConfig.SUPER_USER_LOGIN.get(True), real_name=_('System Administrator'), state=State.ACTIVE, staff_member=True, is_admin=True)
|
||||
u = User(id=ROOT_ID, name=GlobalConfig.SUPER_USER_LOGIN.get(True), real_name=_(
|
||||
'System Administrator'), state=State.ACTIVE, staff_member=True, is_admin=True)
|
||||
u.manager = Authenticator()
|
||||
# Fake overwrite some methods, not too "legal" maybe? :)
|
||||
u.getGroups = lambda: []
|
||||
u.updateLastAccess = lambda: None
|
||||
u.logout = lambda: None
|
||||
@ -100,14 +99,13 @@ def getIp(request):
|
||||
|
||||
|
||||
# Decorator to make easier protect pages that needs to be logged in
|
||||
def webLoginRequired(admin=False):
|
||||
def webLoginRequired(admin: bool = False):
|
||||
"""
|
||||
Decorator to set protection to access page
|
||||
Look for samples at uds.core.web.views
|
||||
"""
|
||||
|
||||
def decorator(view_func):
|
||||
|
||||
@wraps(view_func, assigned=available_attrs(view_func))
|
||||
def _wrapped_view(request, *args, **kwargs):
|
||||
"""
|
||||
@ -117,7 +115,7 @@ def webLoginRequired(admin=False):
|
||||
url = request.build_absolute_uri(GlobalConfig.LOGIN_URL.get())
|
||||
if GlobalConfig.REDIRECT_TO_HTTPS.getBool() is True:
|
||||
url = url.replace('http://', 'https://')
|
||||
logger.debug('No user found, redirecting to {0}'.format(url))
|
||||
logger.debug('No user found, redirecting to %s', url)
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
if admin is True or admin == 'admin':
|
||||
@ -163,7 +161,7 @@ def denyNonAuthenticated(view_func):
|
||||
return _wrapped_view
|
||||
|
||||
|
||||
def __registerUser(authenticator, authInstance, username):
|
||||
def __registerUser(authenticator: Authenticator, authInstance: AuthenticatorInstance, username: str) -> typing.Optional[User]:
|
||||
"""
|
||||
Check if this user already exists on database with this authenticator, if don't, create it with defaults
|
||||
This will work correctly with both internal or externals cause we first authenticate the user, if internal and user do not exists in database
|
||||
@ -172,7 +170,7 @@ def __registerUser(authenticator, authInstance, username):
|
||||
from uds.core.util.request import getRequest
|
||||
|
||||
username = authInstance.transformUsername(username)
|
||||
logger.debug('Transformed username: {0}'.format(username))
|
||||
logger.debug('Transformed username: %s', username)
|
||||
|
||||
request = getRequest()
|
||||
|
||||
@ -184,13 +182,14 @@ def __registerUser(authenticator, authInstance, username):
|
||||
usr.getManager().recreateGroups(usr)
|
||||
# And add an login event
|
||||
events.addEvent(authenticator, events.ET_LOGIN, username=username, srcip=request.ip) # pylint: disable=maybe-no-member
|
||||
events.addEvent(authenticator, events.ET_PLATFORM, platform=request.os.OS, browser=request.os.Browser, version=request.os.Version) # pylint: disable=maybe-no-member
|
||||
events.addEvent(authenticator, events.ET_PLATFORM, platform=request.os.OS, browser=request.os.Browser,
|
||||
version=request.os.Version) # pylint: disable=maybe-no-member
|
||||
return usr
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def authenticate(username, password, authenticator, useInternalAuthenticate=False):
|
||||
def authenticate(username: str, password: str, authenticator: Authenticator, useInternalAuthenticate: bool = False) -> typing.Optional[User]:
|
||||
"""
|
||||
Given an username, password and authenticator, try to authenticate user
|
||||
@param username: username to authenticate
|
||||
@ -200,7 +199,7 @@ def authenticate(username, password, authenticator, useInternalAuthenticate=Fals
|
||||
This is so because in some situations we may want to use a "trusted" method (internalAuthenticate is never invoked directly from web)
|
||||
@return: None if authentication fails, User object (database object) if authentication is o.k.
|
||||
"""
|
||||
logger.debug('Authenticating user {0} with authenticator {1}'.format(username, authenticator))
|
||||
logger.debug('Authenticating user %s with authenticator %s', username, authenticator)
|
||||
|
||||
# If global root auth is enabled && user/password is correct,
|
||||
if GlobalConfig.SUPER_USER_ALLOW_WEBACCESS.getBool(True) and username == GlobalConfig.SUPER_USER_LOGIN.get(True) and password == GlobalConfig.SUPER_USER_PASS.get(True):
|
||||
@ -216,7 +215,7 @@ def authenticate(username, password, authenticator, useInternalAuthenticate=Fals
|
||||
if res is False:
|
||||
return None
|
||||
|
||||
logger.debug('Groups manager: {0}'.format(gm))
|
||||
logger.debug('Groups manager: %s', gm)
|
||||
|
||||
# If do not have any valid group
|
||||
if gm.hasValidGroups() is False:
|
||||
@ -226,7 +225,7 @@ def authenticate(username, password, authenticator, useInternalAuthenticate=Fals
|
||||
return __registerUser(authenticator, authInstance, username)
|
||||
|
||||
|
||||
def authenticateViaCallback(authenticator, params):
|
||||
def authenticateViaCallback(authenticator: Authenticator, params: typing.Any) -> typing.Optional[User]:
|
||||
"""
|
||||
Given an username, this method will get invoked whenever the url for a callback
|
||||
for an authenticator is requested.
|
||||
@ -260,26 +259,28 @@ def authenticateViaCallback(authenticator, params):
|
||||
return __registerUser(authenticator, authInstance, username)
|
||||
|
||||
|
||||
def authCallbackUrl(authenticator):
|
||||
def authCallbackUrl(authenticator) -> str:
|
||||
"""
|
||||
Helper method, so we can get the auth call back url for an authenticator
|
||||
"""
|
||||
return reverse('page.auth.callback', kwargs={'authName': authenticator.name})
|
||||
|
||||
|
||||
def authInfoUrl(authenticator):
|
||||
def authInfoUrl(authenticator: typing.Union[str, bytes, Authenticator]) -> str:
|
||||
"""
|
||||
Helper method, so we can get the info url for an authenticator
|
||||
"""
|
||||
if isinstance(authenticator, (six.text_type, six.binary_type)):
|
||||
if isinstance(authenticator, str):
|
||||
name = authenticator
|
||||
elif isinstance(authenticator, bytes):
|
||||
name = authenticator.decode('utf8')
|
||||
else:
|
||||
name = authenticator.name
|
||||
|
||||
return reverse('page.auth.info', kwargs={'authName': name})
|
||||
|
||||
|
||||
def webLogin(request, response, user, password):
|
||||
def webLogin(request: HttpRequest, response: HttpResponse, user: User, password: str) -> bool:
|
||||
"""
|
||||
Helper function to, once the user is authenticated, store the information at the user session.
|
||||
@return: Always returns True
|
||||
@ -303,7 +304,7 @@ def webLogin(request, response, user, password):
|
||||
return True
|
||||
|
||||
|
||||
def webPassword(request):
|
||||
def webPassword(request: HttpRequest) -> str:
|
||||
"""
|
||||
The password is stored at session using a simple scramble algorithm that keeps the password splited at
|
||||
session (db) and client browser cookies. This method uses this two values to recompose the user password
|
||||
@ -314,19 +315,21 @@ def webPassword(request):
|
||||
return cryptoManager().symDecrpyt(request.session.get(PASS_KEY, ''), getUDSCookie(request)) # recover as original unicode string
|
||||
|
||||
|
||||
def webLogout(request, exit_url=None):
|
||||
def webLogout(request: HttpRequest, exit_url: typing.Optional[str] = None) -> HttpResponse:
|
||||
"""
|
||||
Helper function to clear user related data from session. If this method is not used, the session we be cleaned anyway
|
||||
by django in regular basis.
|
||||
"""
|
||||
|
||||
authenticator = request.user and request.user.manager.getInstance() or None
|
||||
username = request.user and request.user.name or None
|
||||
exit_url = authenticator.logout(username) or exit_url
|
||||
|
||||
if request.user is not None and request.user.id != ROOT_ID:
|
||||
# Try yo invoke logout of auth
|
||||
events.addEvent(request.user.manager, events.ET_LOGOUT, username=request.user.name, srcip=request.ip)
|
||||
if request.user:
|
||||
authenticator = request.user.manager.getInstance()
|
||||
username = request.user.name
|
||||
exit_url = authenticator.logout(username) or exit_url
|
||||
if request.user.id != ROOT_ID:
|
||||
# Try yo invoke logout of auth
|
||||
events.addEvent(request.user.manager, events.ET_LOGOUT, username=request.user.name, srcip=request.ip)
|
||||
else: # No user, redirect to /
|
||||
return HttpResponseRedirect(reverse('page.login'))
|
||||
|
||||
request.session.clear()
|
||||
if exit_url is None:
|
||||
@ -341,7 +344,7 @@ def webLogout(request, exit_url=None):
|
||||
return response
|
||||
|
||||
|
||||
def authLogLogin(request, authenticator, userName, logStr=''):
|
||||
def authLogLogin(request: HttpRequest, authenticator: Authenticator, userName: str, logStr: str = '') -> None:
|
||||
"""
|
||||
Logs authentication
|
||||
"""
|
||||
@ -355,13 +358,11 @@ def authLogLogin(request, authenticator, userName, logStr=''):
|
||||
|
||||
try:
|
||||
user = authenticator.users.get(name=userName)
|
||||
log.doLog(user, level,
|
||||
'{} from {} where OS is {}'.format(logStr, request.ip, request.os['OS']), log.WEB
|
||||
)
|
||||
log.doLog(user, level, '{} from {} where OS is {}'.format(logStr, request.ip, request.os['OS']), log.WEB)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def authLogLogout(request):
|
||||
def authLogLogout(request: HttpRequest):
|
||||
log.doLog(request.user.manager, log.INFO, 'user {0} has logged out from {1}'.format(request.user.name, request.ip), log.WEB)
|
||||
log.doLog(request.user, log.INFO, 'has logged out from {0}'.format(request.ip), log.WEB)
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -30,12 +30,10 @@
|
||||
"""
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from uds.core.Environment import Environmentable
|
||||
import logging
|
||||
|
||||
__updated__ = '2018-09-17'
|
||||
from uds.core.Environment import Environmentable
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -64,7 +62,7 @@ class DelayedTask(Environmentable):
|
||||
"""
|
||||
logging.debug("Base run of job called for class")
|
||||
|
||||
def register(self, suggestedTime, tag='', check=True):
|
||||
def register(self, suggestedTime, tag: str = '', check: bool = True):
|
||||
"""
|
||||
Utility method that allows to register a Delayedtask
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -32,13 +32,9 @@ UDS jobs related modules
|
||||
|
||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from uds.core.jobs.Job import Job
|
||||
from uds.core.jobs.DelayedTask import DelayedTask
|
||||
|
||||
__updated__ = '2014-11-11'
|
||||
|
||||
|
||||
def factory():
|
||||
"""
|
||||
|
@ -30,25 +30,25 @@
|
||||
"""
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
from uds.core.util import encoders
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.Cipher import AES
|
||||
from uds.core.util import encoders
|
||||
from OpenSSL import crypto
|
||||
from Crypto.Random import atfork
|
||||
import typing
|
||||
import hashlib
|
||||
import array
|
||||
import uuid
|
||||
import struct
|
||||
import datetime
|
||||
import random
|
||||
import string
|
||||
|
||||
import logging
|
||||
import six
|
||||
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.Cipher import AES
|
||||
# from Crypto.Random import atfork
|
||||
|
||||
from OpenSSL import crypto
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from uds.core.util import encoders
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -59,7 +59,7 @@ logger = logging.getLogger(__name__)
|
||||
# RSA.generate(1024, os.urandom).exportKey()
|
||||
|
||||
|
||||
class CryptoManager(object):
|
||||
class CryptoManager:
|
||||
instance = None
|
||||
|
||||
def __init__(self):
|
||||
@ -68,60 +68,60 @@ class CryptoManager(object):
|
||||
self._counter = 0
|
||||
|
||||
@staticmethod
|
||||
def AESKey(key, length):
|
||||
if isinstance(key, six.text_type):
|
||||
def AESKey(key: typing.Union[str, bytes], length: int) -> bytes:
|
||||
if isinstance(key, str):
|
||||
key = key.encode('utf8')
|
||||
|
||||
while len(key) < length:
|
||||
key += key # Dup key
|
||||
|
||||
kl = [ord(v) for v in key]
|
||||
kl: typing.List[int] = [v for v in key]
|
||||
pos = 0
|
||||
while len(kl) > length:
|
||||
kl[pos] ^= kl[length]
|
||||
pos = (pos + 1) % length
|
||||
del kl[length]
|
||||
|
||||
return b''.join([chr(v) for v in kl])
|
||||
return bytes(kl)
|
||||
|
||||
@staticmethod
|
||||
def manager():
|
||||
def manager() -> 'CryptoManager':
|
||||
if CryptoManager.instance is None:
|
||||
CryptoManager.instance = CryptoManager()
|
||||
return CryptoManager.instance
|
||||
|
||||
def encrypt(self, value):
|
||||
if isinstance(value, six.text_type):
|
||||
def encrypt(self, value: typing.Union[str, bytes]) -> str:
|
||||
if isinstance(value, str):
|
||||
value = value.encode('utf-8')
|
||||
|
||||
atfork()
|
||||
return encoders.encode((self._rsa.encrypt(value, six.b(''))[0]), 'base64', asText=True)
|
||||
# atfork()
|
||||
return encoders.encode((self._rsa.encrypt(value, b'')[0]), 'base64', asText=True)
|
||||
|
||||
def decrypt(self, value):
|
||||
if isinstance(value, six.text_type):
|
||||
def decrypt(self, value: typing.Union[str, bytes]) -> str:
|
||||
if isinstance(value, str):
|
||||
value = value.encode('utf-8')
|
||||
# import inspect
|
||||
try:
|
||||
atfork()
|
||||
return six.text_type(self._rsa.decrypt(encoders.decode(value, 'base64')).decode('utf-8'))
|
||||
# atfork()
|
||||
return str(self._rsa.decrypt(encoders.decode(value, 'base64')).decode('utf-8'))
|
||||
except Exception:
|
||||
logger.exception('Decripting: {0}'.format(value))
|
||||
logger.exception('Decripting: %s', value)
|
||||
# logger.error(inspect.stack())
|
||||
return 'decript error'
|
||||
|
||||
def AESCrypt(self, text, key, base64=False):
|
||||
def AESCrypt(self, text: bytes, key: bytes, base64: bool = False) -> bytes:
|
||||
# First, match key to 16 bytes. If key is over 16, create a new one based on key of 16 bytes length
|
||||
cipher = AES.new(CryptoManager.AESKey(key, 16), AES.MODE_CBC, 'udsinitvectoruds')
|
||||
rndStr = self.randomString(cipher.block_size)
|
||||
paddedLength = ((len(text) + 4 + 15) // 16) * 16
|
||||
toEncode = struct.pack('>i', len(text)) + text + rndStr[:paddedLength - len(text) - 4]
|
||||
encoded = cipher.encrypt(toEncode)
|
||||
if hex:
|
||||
return encoders.encode(encoded, 'base64', True)
|
||||
if base64:
|
||||
return encoders.encode(encoded, 'base64', asText=False) # Return as binary
|
||||
|
||||
return encoded
|
||||
|
||||
def AESDecrypt(self, text, key, base64=False):
|
||||
def AESDecrypt(self, text: bytes, key: bytes, base64: bool = False) -> bytes:
|
||||
if base64:
|
||||
text = encoders.decode(text, 'base64')
|
||||
|
||||
@ -129,23 +129,21 @@ class CryptoManager(object):
|
||||
toDecode = cipher.decrypt(text)
|
||||
return toDecode[4:4 + struct.unpack('>i', toDecode[:4])[0]]
|
||||
|
||||
return
|
||||
|
||||
def xor(self, s1, s2):
|
||||
def xor(self, s1: typing.Union[str, bytes], s2: typing.Union[str, bytes]) -> bytes:
|
||||
if isinstance(s1, str):
|
||||
s1 = s1.encode('utf-8')
|
||||
if isinstance(s2, str):
|
||||
s2 = s2.encode('utf-8')
|
||||
mult = int(len(s1) / len(s2)) + 1
|
||||
s1 = array.array('B', s1)
|
||||
s2 = array.array('B', s2 * mult)
|
||||
s1a = array.array('B', s1)
|
||||
s2a = array.array('B', s2 * mult)
|
||||
# We must return bynary in xor, because result is in fact binary
|
||||
return array.array('B', (s1[i] ^ s2[i] for i in range(len(s1)))).tobytes()
|
||||
return array.array('B', (s1a[i] ^ s2a[i] for i in range(len(s1a)))).tobytes()
|
||||
|
||||
def symCrypt(self, text, key):
|
||||
def symCrypt(self, text: typing.Union[str, bytes], key: typing.Union[str, bytes]) -> bytes:
|
||||
return self.xor(text, key)
|
||||
|
||||
def symDecrpyt(self, cryptText, key):
|
||||
def symDecrpyt(self, cryptText: typing.Union[str, bytes], key: typing.Union[str, bytes]) -> str:
|
||||
return self.xor(cryptText, key).decode('utf-8')
|
||||
|
||||
def loadPrivateKey(self, rsaKey):
|
||||
@ -165,14 +163,14 @@ class CryptoManager(object):
|
||||
def certificateString(self, certificate):
|
||||
return certificate.replace('-----BEGIN CERTIFICATE-----', '').replace('-----END CERTIFICATE-----', '').replace('\n', '')
|
||||
|
||||
def hash(self, value):
|
||||
if isinstance(value, six.text_type):
|
||||
def hash(self, value: typing.Union[str, bytes]) -> str:
|
||||
if isinstance(value, str):
|
||||
value = value.encode('utf-8')
|
||||
|
||||
if value is '' or value is None:
|
||||
if not value:
|
||||
return ''
|
||||
|
||||
return six.text_type(hashlib.sha1(value).hexdigest())
|
||||
return str(hashlib.sha1(value).hexdigest())
|
||||
|
||||
def uuid(self, obj=None):
|
||||
"""
|
||||
|
@ -86,8 +86,9 @@ class TaskManager(object):
|
||||
def registerScheduledTasks():
|
||||
|
||||
logger.info("Registering sheduled tasks")
|
||||
# Simply import this to make workers "auto import"
|
||||
from uds.core import workers # @UnusedImport
|
||||
|
||||
# Simply import this to make workers "auto imported"
|
||||
from uds.core import workers # @UnusedImport pylint: disable=unused-import
|
||||
|
||||
@staticmethod
|
||||
def run():
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -32,40 +32,42 @@ UDS managers (downloads, users preferences, publications, ...)
|
||||
|
||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
import typing
|
||||
|
||||
__updated__ = '2019-02-05'
|
||||
|
||||
|
||||
def cryptoManager():
|
||||
':rtype uds.core.managers.CryptoManager.CryptoManager'
|
||||
# Imports for type checking
|
||||
if typing.TYPE_CHECKING:
|
||||
from .CryptoManager import CryptoManager
|
||||
from .TaskManager import TaskManager
|
||||
from .DownloadsManager import DownloadsManager
|
||||
from .LogManager import LogManager
|
||||
from .StatsManager import StatsManager
|
||||
from .UserServiceManager import UserServiceManager
|
||||
|
||||
def cryptoManager() -> 'CryptoManager':
|
||||
from .CryptoManager import CryptoManager # pylint: disable=redefined-outer-name
|
||||
return CryptoManager.manager()
|
||||
|
||||
|
||||
def taskManager():
|
||||
from .TaskManager import TaskManager
|
||||
from .TaskManager import TaskManager # pylint: disable=redefined-outer-name
|
||||
return TaskManager
|
||||
|
||||
|
||||
def downloadsManager():
|
||||
from .DownloadsManager import DownloadsManager
|
||||
from .DownloadsManager import DownloadsManager # pylint: disable=redefined-outer-name
|
||||
return DownloadsManager.manager()
|
||||
|
||||
|
||||
def logManager():
|
||||
':rtype uds.core.managers.LogManager.LogManager'
|
||||
from .LogManager import LogManager
|
||||
from .LogManager import LogManager # pylint: disable=redefined-outer-name
|
||||
return LogManager.manager()
|
||||
|
||||
|
||||
def statsManager():
|
||||
':rtype uds.core.managers.StatsManager.StatsManager'
|
||||
from .StatsManager import StatsManager
|
||||
from .StatsManager import StatsManager # pylint: disable=redefined-outer-name
|
||||
return StatsManager.manager()
|
||||
|
||||
|
||||
def userServiceManager():
|
||||
':rtype uds.core.managers.UserServiceManager.UserServiceManager'
|
||||
from .UserServiceManager import UserServiceManager
|
||||
from .UserServiceManager import UserServiceManager # pylint: disable=redefined-outer-name
|
||||
return UserServiceManager.manager()
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -30,18 +30,22 @@
|
||||
"""
|
||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
from django.utils.translation import get_language, ugettext as _, ugettext_noop
|
||||
from uds.core.util import encoders
|
||||
import datetime
|
||||
import typing
|
||||
import time
|
||||
import six
|
||||
import pickle
|
||||
import logging
|
||||
|
||||
# import six
|
||||
|
||||
from django.utils.translation import get_language, ugettext as _, ugettext_noop
|
||||
|
||||
from uds.core.util import encoders
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class gui(object):
|
||||
class gui:
|
||||
"""
|
||||
This class contains the representations of fields needed by UDS modules and
|
||||
administation interface.
|
||||
@ -89,7 +93,7 @@ class gui(object):
|
||||
DISPLAY_TAB = ugettext_noop('Display')
|
||||
|
||||
# : Static Callbacks simple registry
|
||||
callbacks = {}
|
||||
callbacks: typing.Dict[str, typing.Callable] = {}
|
||||
|
||||
# Helpers
|
||||
@staticmethod
|
||||
@ -107,7 +111,7 @@ class gui(object):
|
||||
@staticmethod
|
||||
def convertToList(vals):
|
||||
if vals is not None:
|
||||
return [six.text_type(v) for v in vals]
|
||||
return [str(v) for v in vals]
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
@ -127,11 +131,11 @@ class gui(object):
|
||||
:note: Text can be anything, the method converts it first to text before
|
||||
assigning to dictionary
|
||||
"""
|
||||
return {'id': str(id_), 'text': six.text_type(text)}
|
||||
return {'id': str(id_), 'text': str(text)}
|
||||
|
||||
@staticmethod
|
||||
def choiceImage(id_, text, img):
|
||||
return {'id': str(id_), 'text': six.text_type(text), 'img': img }
|
||||
return {'id': str(id_), 'text': str(text), 'img': img }
|
||||
|
||||
@staticmethod
|
||||
def sortedChoices(choices):
|
||||
@ -151,7 +155,7 @@ class gui(object):
|
||||
"""
|
||||
if isinstance(str_, bool):
|
||||
return str_
|
||||
if six.text_type(str_).lower() == gui.TRUE:
|
||||
if str(str_).lower() == gui.TRUE:
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -230,7 +234,7 @@ class gui(object):
|
||||
'length': options.get('length', gui.InputField.DEFAULT_LENTGH),
|
||||
'required': options.get('required', False),
|
||||
'label': options.get('label', ''),
|
||||
'defvalue': six.text_type(options.get('defvalue', '')),
|
||||
'defvalue': str(options.get('defvalue', '')),
|
||||
'rdonly': options.get('rdonly', False), # This property only affects in "modify" operations
|
||||
'order': options.get('order', 0),
|
||||
'tooltip': options.get('tooltip', ''),
|
||||
@ -349,7 +353,7 @@ class gui(object):
|
||||
"""
|
||||
|
||||
def __init__(self, **options):
|
||||
super(self.__class__, self).__init__(**options)
|
||||
super().__init__(**options)
|
||||
self._type(gui.InputField.TEXT_TYPE)
|
||||
multiline = int(options.get('multiline', 0))
|
||||
if multiline > 8:
|
||||
@ -378,7 +382,7 @@ class gui(object):
|
||||
"""
|
||||
|
||||
def __init__(self, **options):
|
||||
super(self.__class__, self).__init__(**options)
|
||||
super().__init__(**options)
|
||||
minValue = options.get('minValue', '987654321')
|
||||
maxValue = options.get('maxValue', '987654321')
|
||||
self._data['minValue'] = int(minValue)
|
||||
@ -432,7 +436,7 @@ class gui(object):
|
||||
for v in 'value', 'defvalue':
|
||||
self.processValue(v, options)
|
||||
|
||||
super(self.__class__, self).__init__(**options)
|
||||
super().__init__(**options)
|
||||
self._type(gui.InputField.DATE_TYPE)
|
||||
|
||||
def date(self):
|
||||
@ -467,7 +471,7 @@ class gui(object):
|
||||
"""
|
||||
|
||||
def __init__(self, **options):
|
||||
super(self.__class__, self).__init__(**options)
|
||||
super().__init__(**options)
|
||||
self._type(gui.InputField.PASSWORD_TYPE)
|
||||
|
||||
class HiddenField(InputField):
|
||||
@ -503,7 +507,7 @@ class gui(object):
|
||||
"""
|
||||
|
||||
def __init__(self, **options):
|
||||
super(self.__class__, self).__init__(**options)
|
||||
super().__init__(**options)
|
||||
self._isSerializable = options.get('serializable', '') != ''
|
||||
self._type(gui.InputField.HIDDEN_TYPE)
|
||||
|
||||
@ -531,7 +535,7 @@ class gui(object):
|
||||
"""
|
||||
|
||||
def __init__(self, **options):
|
||||
super(self.__class__, self).__init__(**options)
|
||||
super().__init__(**options)
|
||||
self._type(gui.InputField.CHECKBOX_TYPE)
|
||||
|
||||
@staticmethod
|
||||
@ -645,7 +649,7 @@ class gui(object):
|
||||
"""
|
||||
|
||||
def __init__(self, **options):
|
||||
super(self.__class__, self).__init__(**options)
|
||||
super().__init__(**options)
|
||||
self._data['values'] = options.get('values', [])
|
||||
if 'fills' in options:
|
||||
# Save fnc to register as callback
|
||||
@ -665,7 +669,7 @@ class gui(object):
|
||||
class ImageChoiceField(InputField):
|
||||
|
||||
def __init__(self, **options):
|
||||
super(self.__class__, self).__init__(**options)
|
||||
super().__init__(**options)
|
||||
self._data['values'] = options.get('values', [])
|
||||
|
||||
self._type(gui.InputField.IMAGECHOICE_TYPE)
|
||||
@ -711,7 +715,7 @@ class gui(object):
|
||||
"""
|
||||
|
||||
def __init__(self, **options):
|
||||
super(self.__class__, self).__init__(**options)
|
||||
super().__init__(**options)
|
||||
self._data['values'] = options.get('values', [])
|
||||
self._data['rows'] = options.get('rows', -1)
|
||||
self._type(gui.InputField.MULTI_CHOICE_TYPE)
|
||||
@ -753,16 +757,16 @@ class gui(object):
|
||||
SEPARATOR = '\001'
|
||||
|
||||
def __init__(self, **options):
|
||||
super(self.__class__, self).__init__(**options)
|
||||
super().__init__(**options)
|
||||
self._data['values'] = gui.convertToList(options.get('values', []))
|
||||
self._type(gui.InputField.EDITABLE_LIST)
|
||||
|
||||
def _setValue(self, values):
|
||||
def _setValue(self, value):
|
||||
"""
|
||||
So we can override value setting at descendants
|
||||
"""
|
||||
super(self.__class__, self)._setValue(values)
|
||||
self._data['values'] = gui.convertToList(values)
|
||||
super()._setValue(value)
|
||||
self._data['values'] = gui.convertToList(value)
|
||||
|
||||
class ImageField(InputField):
|
||||
"""
|
||||
@ -770,7 +774,7 @@ class gui(object):
|
||||
"""
|
||||
|
||||
def __init__(self, **options):
|
||||
super(self.__class__, self).__init__(**options)
|
||||
super().__init__(**options)
|
||||
self._type(gui.InputField.TEXT_TYPE)
|
||||
|
||||
class InfoField(InputField):
|
||||
@ -779,7 +783,7 @@ class gui(object):
|
||||
"""
|
||||
|
||||
def __init__(self, **options):
|
||||
super(self.__class__, self).__init__(**options)
|
||||
super().__init__(**options)
|
||||
self._type(gui.InputField.INFO_TYPE)
|
||||
|
||||
|
||||
@ -789,7 +793,7 @@ class UserInterfaceType(type):
|
||||
better place
|
||||
"""
|
||||
|
||||
def __new__(cls, classname, bases, classDict):
|
||||
def __new__(cls, classname, bases, classDict): # pylint: disable=bad-mcs-classmethod-argument
|
||||
newClassDict = {}
|
||||
_gui = {}
|
||||
# We will keep a reference to gui elements also at _gui so we can access them easily
|
||||
@ -801,8 +805,7 @@ class UserInterfaceType(type):
|
||||
return type.__new__(cls, classname, bases, newClassDict)
|
||||
|
||||
|
||||
# @six.add_metaclass(UserInterfaceType)
|
||||
class UserInterface(object, metaclass=UserInterfaceType):
|
||||
class UserInterface(metaclass=UserInterfaceType):
|
||||
"""
|
||||
This class provides the management for gui descriptions (user forms)
|
||||
|
||||
@ -813,7 +816,6 @@ class UserInterface(object, metaclass=UserInterfaceType):
|
||||
By default, the values passed to this class constructor are used to fill
|
||||
the gui form fields values.
|
||||
"""
|
||||
# __metaclass__ = UserInterfaceType
|
||||
|
||||
def __init__(self, values=None):
|
||||
import copy
|
||||
@ -821,15 +823,15 @@ class UserInterface(object, metaclass=UserInterfaceType):
|
||||
# Generate a deep copy of inherited Gui, so each User Interface instance has its own "field" set, and do not share the "fielset" with others, what can be really dangerous
|
||||
# Till now, nothing bad happened cause there where being used "serialized", but this do not have to be this way
|
||||
self._gui = copy.deepcopy(self._gui) # Ensure "gui" is our own instance, deep copied from base
|
||||
for key, val in six.iteritems(self._gui): # And refresh references to them
|
||||
for key, val in self._gui.items(): # And refresh references to them
|
||||
setattr(self, key, val)
|
||||
|
||||
if values is not None:
|
||||
for k, v in six.iteritems(self._gui):
|
||||
for k, v in self._gui.items():
|
||||
if k in values:
|
||||
v.value = values[k]
|
||||
else:
|
||||
logger.warning('Field {} not found'.format(k))
|
||||
logger.warning('Field %s not found', k)
|
||||
|
||||
def initGui(self):
|
||||
"""
|
||||
@ -850,7 +852,6 @@ class UserInterface(object, metaclass=UserInterfaceType):
|
||||
time, and returned data will be probable a nonsense. We will take care
|
||||
of this posibility in a near version...
|
||||
"""
|
||||
pass
|
||||
|
||||
def valuesDict(self):
|
||||
"""
|
||||
@ -880,7 +881,7 @@ class UserInterface(object, metaclass=UserInterfaceType):
|
||||
|
||||
"""
|
||||
dic = {}
|
||||
for k, v in six.iteritems(self._gui):
|
||||
for k, v in self._gui.items():
|
||||
if v.isType(gui.InputField.EDITABLE_LIST):
|
||||
dic[k] = gui.convertToList(v.value)
|
||||
elif v.isType(gui.InputField.MULTI_CHOICE_TYPE):
|
||||
@ -891,7 +892,7 @@ class UserInterface(object, metaclass=UserInterfaceType):
|
||||
# dic[k] = v.defValue
|
||||
else:
|
||||
dic[k] = v.value
|
||||
logger.debug('Values Dict: {0}'.format(dic))
|
||||
logger.debug('Values Dict: %s', dic)
|
||||
return dic
|
||||
|
||||
def serializeForm(self):
|
||||
@ -911,7 +912,7 @@ class UserInterface(object, metaclass=UserInterfaceType):
|
||||
|
||||
arr = []
|
||||
for k, v in self._gui.items():
|
||||
logger.debug('serializing Key: {0}/{1}'.format(k, v.value))
|
||||
logger.debug('serializing Key: %s/%s', k, v.value)
|
||||
if v.isType(gui.InputField.HIDDEN_TYPE) and v.isSerializable() is False:
|
||||
# logger.debug('Field {0} is not serializable'.format(k))
|
||||
continue
|
||||
@ -947,7 +948,7 @@ class UserInterface(object, metaclass=UserInterfaceType):
|
||||
|
||||
try:
|
||||
# Set all values to defaults ones
|
||||
for k in six.iterkeys(self._gui):
|
||||
for k in self._gui:
|
||||
if self._gui[k].isType(gui.InputField.HIDDEN_TYPE) and self._gui[k].isSerializable() is False:
|
||||
# logger.debug('Field {0} is not unserializable'.format(k))
|
||||
continue
|
||||
@ -975,7 +976,7 @@ class UserInterface(object, metaclass=UserInterfaceType):
|
||||
self._gui[k].value = val
|
||||
# logger.debug('Value for {0}:{1}'.format(k, val))
|
||||
except Exception:
|
||||
logger.exception('Exception on unserialization on {}'.format(self.__class__))
|
||||
logger.exception('Exception on unserialization on %s', self.__class__)
|
||||
# Values can contain invalid characters, so we log every single char
|
||||
# logger.info('Invalid serialization data on {0} {1}'.format(self, values.encode('hex')))
|
||||
|
||||
@ -990,7 +991,7 @@ class UserInterface(object, metaclass=UserInterfaceType):
|
||||
object: If not none, object that will get its "initGui" invoked
|
||||
This will only happen (not to be None) in Services.
|
||||
"""
|
||||
logger.debug('Active language for theGui translation: {0}'.format(get_language()))
|
||||
logger.debug('Active language for theGui translation: %s', get_language())
|
||||
theGui = cls
|
||||
if obj is not None:
|
||||
obj.initGui() # We give the "oportunity" to fill necesary theGui data before providing it to client
|
||||
@ -998,9 +999,9 @@ class UserInterface(object, metaclass=UserInterfaceType):
|
||||
|
||||
res = []
|
||||
# pylint: disable=protected-access,maybe-no-member
|
||||
for key, val in six.iteritems(theGui._gui):
|
||||
logger.debug('{0} ### {1}'.format(key, val))
|
||||
for key, val in theGui._gui.items():
|
||||
logger.debug('%s ### %s', key, val)
|
||||
res.append({'name': key, 'gui': val.guiDescription(), 'value': ''})
|
||||
|
||||
logger.debug('>>>>>>>>>>>> Gui Description: {0} -- {1}'.format(obj, res))
|
||||
logger.debug('>>>>>>>>>>>> Gui Description: %s -- %s', obj, res)
|
||||
return res
|
||||
|
@ -5,4 +5,4 @@ This module contains the definition of UserInterface, needed to describe the int
|
||||
between an UDS module and the administration interface
|
||||
"""
|
||||
|
||||
from uds.core.ui.UserInterface import gui
|
||||
from .UserInterface import gui
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# Copyright (c) 2014-2019 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
|
@ -30,13 +30,10 @@
|
||||
"""
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
import six
|
||||
import codecs
|
||||
|
||||
|
||||
def __toBinary(data):
|
||||
if isinstance(data, six.text_type):
|
||||
if isinstance(data, str):
|
||||
return data.encode('utf8')
|
||||
return data
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2012-2016 Virtual Cable S.L.
|
||||
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -29,24 +29,22 @@
|
||||
"""
|
||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
import threading
|
||||
import logging
|
||||
import typing
|
||||
|
||||
from uds.core.util import OsDetector
|
||||
from uds.core.util.Config import GlobalConfig
|
||||
from uds.core.auths.auth import ROOT_ID, USER_KEY, getRootUser
|
||||
from uds.models import User
|
||||
|
||||
import threading
|
||||
import logging
|
||||
|
||||
__updated__ = '2017-01-11'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_requests = {}
|
||||
_requests : typing.Dict[int, typing.Any] = {}
|
||||
|
||||
|
||||
def getIdent():
|
||||
def getIdent() -> typing.Optional[int]:
|
||||
return threading.current_thread().ident
|
||||
|
||||
|
||||
@ -57,8 +55,7 @@ def getRequest():
|
||||
return {}
|
||||
|
||||
|
||||
class GlobalRequestMiddleware(object):
|
||||
|
||||
class GlobalRequestMiddleware:
|
||||
def __init__(self, get_response):
|
||||
self.get_response = get_response
|
||||
|
||||
@ -70,20 +67,20 @@ class GlobalRequestMiddleware(object):
|
||||
# Ensures that requests contains the valid user
|
||||
GlobalRequestMiddleware.getUser(request)
|
||||
|
||||
# Add a counter var, reseted on every request
|
||||
# Store request on cache
|
||||
_requests[getIdent()] = request
|
||||
return None
|
||||
|
||||
|
||||
def _process_response(self, request, response):
|
||||
# Remove IP from global cache (processing responses after this will make global request unavailable,
|
||||
# but can be got from request again)
|
||||
ident = getIdent()
|
||||
logger.debug('Deleting {}'.format(ident))
|
||||
logger.debug('Deleting %s', ident)
|
||||
try:
|
||||
if ident in _requests:
|
||||
del _requests[ident]
|
||||
del _requests[ident] # Remove stored request
|
||||
else:
|
||||
logger.info('Request id {} not stored'.format(ident))
|
||||
logger.info('Request id %s not stored in cache', ident)
|
||||
except Exception:
|
||||
logger.exception('Deleting stored request')
|
||||
return response
|
||||
@ -105,7 +102,7 @@ class GlobalRequestMiddleware(object):
|
||||
behind_proxy = GlobalConfig.BEHIND_PROXY.getBool(False)
|
||||
try:
|
||||
request.ip = request.META['REMOTE_ADDR']
|
||||
except:
|
||||
except Exception:
|
||||
logger.exception('Request ip not found!!')
|
||||
request.ip = '0.0.0.0' # No remote addr?? set this IP to a "basic" one, anyway, this should never ocur
|
||||
|
||||
@ -117,7 +114,7 @@ class GlobalRequestMiddleware(object):
|
||||
request.ip = request.ip_proxy # Stores the ip
|
||||
# will raise "list out of range", leaving ip_proxy = proxy in case of no other proxy apart of nginx
|
||||
request.ip_proxy = proxies[1]
|
||||
except:
|
||||
except Exception:
|
||||
request.ip_proxy = request.ip
|
||||
|
||||
@staticmethod
|
||||
@ -127,7 +124,7 @@ class GlobalRequestMiddleware(object):
|
||||
"""
|
||||
logger.debug('Getting User on Middleware')
|
||||
user = request.session.get(USER_KEY)
|
||||
if user is not None:
|
||||
if user:
|
||||
try:
|
||||
if user == ROOT_ID:
|
||||
user = getRootUser()
|
||||
@ -136,7 +133,4 @@ class GlobalRequestMiddleware(object):
|
||||
except User.DoesNotExist:
|
||||
user = None
|
||||
|
||||
if user is not None:
|
||||
request.user = user
|
||||
else:
|
||||
request.user = None
|
||||
request.user = user
|
||||
|
@ -38,6 +38,7 @@ from django.db.models import signals
|
||||
|
||||
from uds.core.util.State import State
|
||||
from uds.core.util import log
|
||||
from uds.core.auths.BaseAuthenticator import Authenticator as AuthenticatorInstance
|
||||
from .UUIDModel import UUIDModel
|
||||
|
||||
from .Authenticator import Authenticator
|
||||
@ -62,7 +63,7 @@ class Group(UUIDModel):
|
||||
groups = models.ManyToManyField('self', symmetrical=False)
|
||||
created = models.DateTimeField(default=getSqlDatetime, blank=True)
|
||||
|
||||
class Meta(UUIDModel.Meta):
|
||||
class Meta:
|
||||
"""
|
||||
Meta class to declare default order and unique multiple field index
|
||||
"""
|
||||
@ -71,10 +72,10 @@ class Group(UUIDModel):
|
||||
app_label = 'uds'
|
||||
|
||||
@property
|
||||
def pretty_name(self):
|
||||
def pretty_name(self) -> str:
|
||||
return self.name + '@' + self.manager.name
|
||||
|
||||
def getManager(self):
|
||||
def getManager(self) -> AuthenticatorInstance:
|
||||
"""
|
||||
Returns the authenticator object that owns this user.
|
||||
|
||||
@ -107,7 +108,7 @@ class Group(UUIDModel):
|
||||
# Clears related logs
|
||||
log.clearLogs(toDelete)
|
||||
|
||||
logger.debug('Deleted group {0}'.format(toDelete))
|
||||
logger.debug('Deleted group %s', toDelete)
|
||||
|
||||
|
||||
signals.pre_delete.connect(Group.beforeDelete, sender=Group)
|
||||
|
Loading…
Reference in New Issue
Block a user