From 45094006051ac7883344ba5e9d755378e5714fb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20G=C3=B3mez=20Garc=C3=ADa?= Date: Tue, 5 Feb 2019 13:52:51 +0100 Subject: [PATCH] * Advancing on metapools * Removed non used old code --- server/src/server/settings.py.sample | 21 ---- server/src/uds/REST/methods/connection.py | 41 +----- server/src/uds/REST/methods/meta_pools.py | 1 + server/src/uds/REST/methods/services_pools.py | 2 + .../uds/core/managers/UserServiceManager.py | 71 ++++++++++- server/src/uds/core/managers/__init__.py | 3 +- server/src/uds/core/util/html.py | 6 +- server/src/uds/models/MetaPool.py | 58 ++++++++- server/src/uds/models/ServicesPool.py | 14 ++- server/src/uds/templatetags/html5.py | 119 ------------------ server/src/uds/urls.py | 2 +- server/src/uds/web/util/configjs.py | 5 + server/src/uds/web/util/services.py | 61 ++++++++- server/src/uds/web/views/__init__.py | 2 +- server/src/uds/web/views/login.py | 103 --------------- server/src/uds/web/views/service.py | 13 +- 16 files changed, 221 insertions(+), 301 deletions(-) delete mode 100644 server/src/uds/web/views/login.py diff --git a/server/src/server/settings.py.sample b/server/src/server/settings.py.sample index cd562184f..11d80c0d4 100644 --- a/server/src/server/settings.py.sample +++ b/server/src/server/settings.py.sample @@ -199,30 +199,9 @@ INSTALLED_APPS = ( 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', - 'compressor', 'uds', ) -# Compressor settings (for css/js) -COMPRESS_ENABLED = not DEBUG -COMPRESS_OUTPUT_DIR = 'cache' -COMPRESS_PRECOMPILERS = ( - ('text/coffeescript', 'coffee --compile --stdio'), - ('text/less', 'lessc {infile} {outfile}'), - ('text/x-sass', 'sass {infile} {outfile}'), - ('text/x-scss', 'sass --scss {infile} {outfile}'), - # ('text/stylus', 'stylus < {infile} > {outfile}'), - # ('text/foobar', 'path.to.MyPrecompilerFilter'), -) -if DEBUG: - COMPRESS_DEBUG_TOGGLE = 'debug' -# -# Enable this if you need to allow round robin load balancing of web server -# This is so because we need to share the files between servers -# Another options is put /var/server/static on a shared nfs forder for all servers -# -# COMPRESS_STORAGE = 'uds.core.util.FileStorage.CompressorFileStorage' - # See http://docs.djangoproject.com/en/dev/topics/logging for # more details on how to customize your logging configuration. LOGDIR = BASE_DIR + '/' + 'log' diff --git a/server/src/uds/REST/methods/connection.py b/server/src/uds/REST/methods/connection.py index 2fcd4f2fb..366e51501 100644 --- a/server/src/uds/REST/methods/connection.py +++ b/server/src/uds/REST/methods/connection.py @@ -36,7 +36,7 @@ from django.utils.translation import ugettext as _ from uds.REST import Handler from uds.REST import RequestError -from uds.models import UserService, DeployedService, ServicesPoolGroup +from uds.models import MetaPool, ServicePool, ServicesPoolGroup from uds.core.managers import userServiceManager from uds.core.managers import cryptoManager from uds.core.ui.images import DEFAULT_THUMB_BASE64 @@ -84,44 +84,11 @@ class Connection(Handler): def serviceList(self): # We look for services for this authenticator groups. User is logged in in just 1 authenticator, so his groups must coincide with those assigned to ds - groups = list(self._user.getGroups()) - availServices = DeployedService.getDeployedServicesForGroups(groups) + from uds.web.util.services import getServicesData - # Extract required data to show to user - services = [] - # User services - for servicePool in availServices: - trans = [] - for t in servicePool.transports.all().order_by('priority'): - if t.validForIp(self._request.ip) and t.getType().providesConnetionInfo(): - trans.append({'id': t.uuid, 'name': t.name}) + self._request.user = self._user - # Locate if user service has any already assigned user service for this - ads = userServiceManager().getExistingAssignationForUser(servicePool, self._user) - if ads is None: - in_use = False - else: - in_use = ads.in_use - - services.append({'id': 'F' + servicePool.uuid, - 'name': servicePool.name, - 'description': servicePool.comments, - 'visual_name': servicePool.visual_name, - 'group': servicePool.servicesPoolGroup if servicePool.servicesPoolGroup is not None else ServicesPoolGroup.default().as_dict, - 'thumb': servicePool.image.thumb64 if servicePool.image is not None else DEFAULT_THUMB_BASE64, - 'show_transports': servicePool.show_transports, - 'allow_users_remove': servicePool.allow_users_remove, - 'not_accesible': not servicePool.isAccessAllowed(), - 'to_be_replaced': servicePool.toBeReplaced(), - 'transports': trans, - 'maintenance': servicePool.isInMaintenance(), - 'in_use': in_use}) - - logger.debug('Services: {0}'.format(services)) - - services = sorted(services, key=lambda s: s['name'].upper()) - - return Connection.result(result=services) + return Connection.result(result=getServicesData(self._request)) def connection(self, doNotCheck=False): idService = self._args[0] diff --git a/server/src/uds/REST/methods/meta_pools.py b/server/src/uds/REST/methods/meta_pools.py index 43e0fba10..08309f174 100644 --- a/server/src/uds/REST/methods/meta_pools.py +++ b/server/src/uds/REST/methods/meta_pools.py @@ -68,6 +68,7 @@ class MetaPools(ModelHandler): table_title = _('Meta Pools') table_fields = [ {'name': {'title': _('Name')}}, + {'comments': {'title': _('Comments')}}, {'user_services_count': {'title': _('User services'), 'type': 'number'}}, {'user_services_in_preparation': {'title': _('In Preparation')}}, {'visible': {'title': _('Visible'), 'type': 'callback'}}, diff --git a/server/src/uds/REST/methods/services_pools.py b/server/src/uds/REST/methods/services_pools.py index 39a4c40e4..ce360b9e3 100644 --- a/server/src/uds/REST/methods/services_pools.py +++ b/server/src/uds/REST/methods/services_pools.py @@ -94,6 +94,7 @@ class ServicesPools(ModelHandler): {'visible': {'title': _('Visible'), 'type': 'callback'}}, {'show_transports': {'title': _('Shows transports'), 'type': 'callback'}}, {'pool_group_name': {'title': _('Pool group')}}, + {'usage': {'title': _('Usage')}}, {'parent': {'title': _('Parent service')}}, {'tags': {'title': _('tags'), 'visible': False}}, ] @@ -176,6 +177,7 @@ class ServicesPools(ModelHandler): val['pool_group_id'] = poolGroupId val['pool_group_name'] = poolGroupName val['pool_group_thumb'] = poolGroupThumb + val['usage'] = item.usage() if item.osmanager is not None: val['osmanager_id'] = item.osmanager.uuid diff --git a/server/src/uds/core/managers/UserServiceManager.py b/server/src/uds/core/managers/UserServiceManager.py index 04b3e10a9..ab3863383 100644 --- a/server/src/uds/core/managers/UserServiceManager.py +++ b/server/src/uds/core/managers/UserServiceManager.py @@ -39,8 +39,14 @@ from uds.core.services.Exceptions import OperationException from uds.core.util.State import State from uds.core.util import log from uds.core.util.Config import GlobalConfig -from uds.core.services.Exceptions import MaxServicesReachedError, ServiceInMaintenanceMode, InvalidServiceException, ServiceNotReadyError, ServiceAccessDeniedByCalendar -from uds.models import ServicePool, UserService, getSqlDatetime, Transport +from uds.core.services.Exceptions import ( + MaxServicesReachedError, + ServiceInMaintenanceMode, + InvalidServiceException, + ServiceNotReadyError, + ServiceAccessDeniedByCalendar +) +from uds.models import MetaPool, ServicePool, UserService, getSqlDatetime, Transport from uds.core import services from uds.core.services import Service from uds.core.util.stats import events @@ -50,8 +56,9 @@ from .userservice.opchecker import UserServiceOpChecker import requests import json import logging +import random -__updated__ = '2018-09-24' +__updated__ = '2019-02-05' logger = logging.getLogger(__name__) traceLogger = logging.getLogger('traceLog') @@ -551,8 +558,6 @@ class UserServiceManager(object): logger.debug('Getting A service {}'.format(idService)) userService = UserService.objects.get(uuid=idService) userService.deployed_service.validateUser(user) - elif kind == 'M': # This is a meta service.. - pass else: ds = ServicePool.objects.get(uuid=idService) # We first do a sanity check for this, if the user has access to this service @@ -600,7 +605,7 @@ class UserServiceManager(object): # If transport is not available for the request IP... if trans.validForIp(srcIp) is False: - msg = 'The requested transport {} is not valid for {}'.format(trans.name, srcIp) + msg = _('The requested transport {} is not valid for {}').format(trans.name, srcIp) logger.error(msg) raise InvalidServiceException(msg) @@ -650,3 +655,57 @@ class UserServiceManager(object): traceLogger.error('ERROR {} on service "{}" for user "{}" with transport "{}" (ip:{})'.format(serviceNotReadyCode, userService.name, userName, trans.name, ip)) raise ServiceNotReadyError(code=serviceNotReadyCode, service=userService, transport=trans) + + def getMeta(self, user, srcIp, os, idMetaPool): + logger.debug('This is meta') + # We need to locate the service pool related to this meta, and also the transport + # First, locate if there is a service in any pool associated with this metapool + meta = MetaPool.objects.get(uuid=idMetaPool) + + # Sort pools based on meta selection + if meta.policy == MetaPool.PRIORITY_POOL: + pools = [(p.priority, p.pool) for p in meta.members.all()] + elif meta.policy == MetaPool.MOST_AVAILABLE_BY_NUMBER: + pools = [(p.usage(), p) for p in meta.pools.all()] + else: + pools = [(random.randint(0, 10000), p) for p in meta.pools.all()] + + # Sort pools related to policy now, and xtract only pools, not sort keys + # Remove "full" pools (100%) from result + pools = [p[1] for p in sorted(pools, key=lambda x: x[0]) if p[1].usage() < 100] + + logger.debug('Pools: %s', pools) + + usable = None + # Now, Lets find first if there is one assigned in ANY pool + try: + alreadyAssigned = UserService.objects.filter(deployed_service__in=pools, user=user, cache_level=0).order_by('deployed_service__name')[0] + logger.debug('Already assigned %s', alreadyAssigned) + + # Ensure transport is available for the OS + for t in alreadyAssigned.deployed_service.transports.all().order_by('priority'): + typeTrans = t.getType() + if t.getType() and t.validForIp(srcIp) and typeTrans.supportsOs(os['OS']) and t.validForOs(os['OS']): + usable = (alreadyAssigned, t) + break + + except Exception: # No service already assigned, lets find a suitable one + for pool in pools: # Pools are already sorted, and "full" pools are filtered out + # Ensure transport is available for the OS + for t in pool.transports.all().order_by('priority'): + typeTrans = t.getType() + if t.getType() and t.validForIp(srcIp) and typeTrans.supportsOs(os['OS']) and t.validForOs(os['OS']): + usable = (pool, t) + break + + # Stop if a pool-transport is found + if usable: + break + + if not usable: + log.doLog(meta, log.WARN, "No user service accessible from device (ip {}, os: {})".format(srcIp, os['OS']), log.SERVICE) + raise InvalidServiceException(_('The service is not accessible from this device')) + + logger.debug('Found usable pair: %s', usable) + # We have found an usable user service already assigned & can be accessed from this, so return it + return None, usable[0], None, usable[1], None diff --git a/server/src/uds/core/managers/__init__.py b/server/src/uds/core/managers/__init__.py index 54f82cbc9..359a7ae00 100644 --- a/server/src/uds/core/managers/__init__.py +++ b/server/src/uds/core/managers/__init__.py @@ -34,7 +34,7 @@ UDS managers (downloads, users preferences, publications, ...) """ from __future__ import unicode_literals -__updated__ = '2018-08-30' +__updated__ = '2019-02-05' def cryptoManager(): @@ -66,5 +66,6 @@ def statsManager(): def userServiceManager(): + ':rtype uds.core.managers.UserServiceManager.UserServiceManager' from .UserServiceManager import UserServiceManager return UserServiceManager.manager() diff --git a/server/src/uds/core/util/html.py b/server/src/uds/core/util/html.py index f4ce77116..b22690544 100644 --- a/server/src/uds/core/util/html.py +++ b/server/src/uds/core/util/html.py @@ -39,7 +39,7 @@ from django.utils import formats import six import logging -__updated__ = '2015-05-03' +__updated__ = '2019-02-05' logger = logging.getLogger(__name__) @@ -58,6 +58,10 @@ def udsAccessLink(request, serviceId, transportId): return 'udsa://{}/{}'.format(serviceId, transportId) +def udsMetaLink(request, serviceId): + return 'udsa://{}/meta'.format(serviceId) + + def parseDate(dateToParse): import datetime diff --git a/server/src/uds/models/MetaPool.py b/server/src/uds/models/MetaPool.py index 9059076fd..69f1ba2e4 100644 --- a/server/src/uds/models/MetaPool.py +++ b/server/src/uds/models/MetaPool.py @@ -31,13 +31,15 @@ .. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com """ from django.db import models -from django.db.models import signals +from django.db.models import signals, QuerySet from django.utils.translation import ugettext_noop as _ from uds.core.util import log from uds.core.util import states from uds.models.UUIDModel import UUIDModel from uds.models.Tag import TaggingMixin +from uds.models.Util import getSqlDatetime +from uds.core.util.calendar import CalendarChecker from uds.models.Image import Image from uds.models.ServicesPoolGroup import ServicesPoolGroup @@ -47,7 +49,7 @@ from uds.models.Calendar import Calendar import logging -__updated__ = '2018-10-03' +__updated__ = '2019-02-05' logger = logging.getLogger(__name__) @@ -62,7 +64,7 @@ class MetaPool(UUIDModel, TaggingMixin): MOST_AVAILABLE_BY_NUMBER = 2 TYPES = { - ROUND_ROBIN_POOL: _('Round Robin (distribute among all services)'), + ROUND_ROBIN_POOL: _('Evenly distributed (distribute among all services equally)'), PRIORITY_POOL: _('Priority (lowest priority is first consumed)'), MOST_AVAILABLE_BY_NUMBER: _('Most available (based on max services value and current used value)'), } @@ -91,6 +93,56 @@ class MetaPool(UUIDModel, TaggingMixin): db_table = 'uds__pool_meta' app_label = 'uds' + def isInMaintenance(self) -> bool: + total, maintenance = 0, 0 + for p in self.pools.all(): + total += 1 + if p.isInMaintenance(): + maintenance += 1 + return total == maintenance + + def isAccessAllowed(self, chkDateTime=None) -> bool: + """ + Checks if the access for a service pool is allowed or not (based esclusively on associated calendars) + """ + if chkDateTime is None: + chkDateTime = getSqlDatetime() + + access = self.fallbackAccess + # Let's see if we can access by current datetime + for ac in self.calendarAccess.order_by('priority'): + if CalendarChecker(ac.calendar).check(chkDateTime) is True: + access = ac.access + break # Stops on first rule match found + + return access == states.action.ALLOW + + @property + def visual_name(self): + logger.debug("SHORT: {} {} {}".format(self.short_name, self.short_name is not None, self.name)) + if self.short_name and self.short_name.strip() != '': + return self.short_name + return self.name + + @staticmethod + def getForGroups(groups) -> QuerySet: + """ + Return deployed services with publications for the groups requested. + + Args: + groups: List of groups to check + + Returns: + List of accesible deployed services + """ + from uds.core import services + # Get services that HAS publications + meta = MetaPool.objects.filter(assignedGroups__in=groups, assignedGroups__state=states.group.ACTIVE, + visible=True) + # TODO: Maybe we can exclude non "usable" metapools (all his pools are in maintenance mode?) + + return meta + @staticmethod def beforeDelete(sender, **kwargs): """ diff --git a/server/src/uds/models/ServicesPool.py b/server/src/uds/models/ServicesPool.py index 41e6892ef..9285ab339 100644 --- a/server/src/uds/models/ServicesPool.py +++ b/server/src/uds/models/ServicesPool.py @@ -63,7 +63,7 @@ import logging import pickle import six -__updated__ = '2018-10-01' +__updated__ = '2019-02-05' logger = logging.getLogger(__name__) @@ -172,7 +172,7 @@ class DeployedService(UUIDModel, TaggingMixin): @property def is_meta(self): - return self.meta_pools.count() == 0 + return self.memberOfMeta.count() > 0 @property def visual_name(self): @@ -478,6 +478,16 @@ class DeployedService(UUIDModel, TaggingMixin): """ return self.userServices.filter(cache_level=0, user=None) + def usage(self): + """ + Returns the % used services, related to "maximum" user services + If no "maximum" number of services, will return 0% ofc + """ + if self.max_srvs == 0: + return 0 + + return 100 * self.assignedUserServices().count() // self.max_srvs + def testServer(self, host, port, timeout=4): return self.service.testServer(host, port, timeout) diff --git a/server/src/uds/templatetags/html5.py b/server/src/uds/templatetags/html5.py index ca7388bb4..2fc5c7a82 100644 --- a/server/src/uds/templatetags/html5.py +++ b/server/src/uds/templatetags/html5.py @@ -51,125 +51,6 @@ logger = logging.getLogger(__name__) register = template.Library() -# locale related -@register.filter(name='country') -def country(lang): - if lang == 'en': - return 'US' - if lang == 'ja': - return 'JP' - - return lang.upper() - - -# Config related -@register.simple_tag -def get_theme(): - return GlobalConfig.UDS_THEME.get() - - -class EnhacedVisual(template.Node): - - def __init__(self, nodelistTrue, nodelistFalse): - self._nodelistTrue = nodelistTrue - self._nodelistFalse = nodelistFalse - - def render(self, context): - if GlobalConfig.UDS_THEME_VISUAL.getBool(True) is True: - return self._nodelistTrue.render(context) - if self._nodelistFalse is None: - return '' - - return self._nodelistFalse.render(context) - - -@register.tag(name='enhaced_visual') -def enhaced_visual(parser, token): - states = {} - - default_states = ['enhaced_visual', 'else'] - end_tag = 'endenhaced_visual' - - while token.contents != end_tag: - current = token.contents - states[current.split()[0]] = parser.parse(default_states + [end_tag]) - token = parser.next_token() - - return EnhacedVisual(states['enhaced_visual'], states.get('else', None)) - - -class TabIndex(template.Node): - - def __init__(self, tabIndexName): - self.tabIndexIname = tabIndexName - - def render(self, context): - counter = context.get(self.tabIndexIname, 0) + 1 - context[self.tabIndexIname] = counter - return "{}".format(counter) - - -@register.tag(name='tabindex') -def tabindex(parser, token): - try: - # split_contents() knows not to split quoted strings. - tag_name, tabIndexName = token.split_contents() - except ValueError: - raise template.TemplateSyntaxError( - "%r tag requires a single argument" % token.contents.split()[0] - ) - - return TabIndex(tabIndexName) - - -class Preference(template.Node): - - def __init__(self, modName, prefName): - self.modName = modName - self.prefName = prefName - - def render(self, context): - if context.get('user') is None: - return '' - - prefs = context['user'].prefs(self.modName) - return prefs.get(self.prefName) - - -@register.tag(name='preference') -def preference(parser, token): - try: - # split_contents() knows not to split quoted strings. - tag_name, rest = token.split_contents() - modName, prefName = rest.split('.') - except ValueError: - raise template.TemplateSyntaxError( - "%r tag requires a single argument" % token.contents.split()[0] - ) - - return Preference(modName, prefName) - - -@register.simple_tag -def preferences_allowed(): - return GlobalConfig.PREFERENCES_ALLOWED.getBool(True) - - -@register.simple_tag -def pageReloadTime(): - return GlobalConfig.RELOAD_TIME.getInt(True) - - -@register.simple_tag -def root_id(): - return ROOT_ID - - -@register.simple_tag -def image_size(): - return Image.MAX_IMAGE_SIZE - - @register.simple_tag def calendar_denied_msg(): text = GlobalConfig.LIMITED_BY_CALENDAR_TEXT.get().strip() diff --git a/server/src/uds/urls.py b/server/src/uds/urls.py index 86566d8a3..a72cb691e 100644 --- a/server/src/uds/urls.py +++ b/server/src/uds/urls.py @@ -107,7 +107,7 @@ urlpatterns = [ re_path(r'^uds/webapi/img/transport/(?P[a-zA-Z0-9-]+)$', uds.web.views.transportIcon, name='webapi.transportIcon'), re_path(r'^uds/webapi/img/gallery/(?P[a-zA-Z0-9-]+)$', uds.web.views.image, name='webapi.galleryImage'), - re_path(r'^uds/webapi/action/(?P.+)/enable/(?P[a-zA-Z0-9-]+)$', uds.web.views.clientEnabler, name='webapi.enabler'), + re_path(r'^uds/webapi/action/(?P.+)/enable/(?P[a-zA-Z0-9-]+)$', uds.web.views.userServiceEnabler, name='webapi.enabler'), re_path(r'^uds/webapi/action/(?P.+)/(?P[a-zA-Z0-9-]+)$', uds.web.views.action, name='webapi.action'), diff --git a/server/src/uds/web/util/configjs.py b/server/src/uds/web/util/configjs.py index 7606c2e34..c0955b5eb 100644 --- a/server/src/uds/web/util/configjs.py +++ b/server/src/uds/web/util/configjs.py @@ -105,6 +105,11 @@ def udsJs(request): 'csrf_field': CSRF_FIELD, 'csrf': csrf_token, 'image_size': Image.MAX_IMAGE_SIZE, + 'reload_time': GlobalConfig.RELOAD_TIME.getInt(True), + 'messages': { + # Calendar denied message + 'calendarDenied': GlobalConfig.LIMITED_BY_CALENDAR_TEXT.get().strip() or gettext("Access limited by calendar") + }, 'urls': { 'changeLang': reverse('set_language'), 'login': reverse('page.login'), diff --git a/server/src/uds/web/util/services.py b/server/src/uds/web/util/services.py index 53b755b1e..63a13867c 100644 --- a/server/src/uds/web/util/services.py +++ b/server/src/uds/web/util/services.py @@ -33,7 +33,7 @@ from django.utils.translation import ugettext from django.utils import formats from django.urls.base import reverse -from uds.models import DeployedService, Transport, UserService, Network, ServicesPoolGroup +from uds.models import DeployedService, Transport, UserService, Network, ServicesPoolGroup, MetaPool from uds.core.util.Config import GlobalConfig from uds.core.util import html @@ -53,6 +53,7 @@ def getServicesData(request): # We look for services for this authenticator groups. User is logged in in just 1 authenticator, so his groups must coincide with those assigned to ds groups = list(request.user.getGroups()) availServices = DeployedService.getDeployedServicesForGroups(groups) + availMetas = MetaPool.getForGroups(groups) # Information for administrators nets = '' @@ -68,9 +69,64 @@ def getServicesData(request): tt.append(t.name) validTrans = ','.join(tt) + logger.debug('Checking meta pools: %s', availMetas) services = [] + # Add meta pools data first + for meta in availMetas: + # Check that we have access to at least one transport on some of its children + hasUsablePools = False + in_use = False + for pool in meta.pools.all(): + # if pool.isInMaintenance(): + # continue + for t in pool.transports.all(): + typeTrans = t.getType() + if t.getType() and t.validForIp(request.ip) and typeTrans.supportsOs(os['OS']) and t.validForOs(os['OS']): + hasUsablePools = True + break + + if not in_use: + assignedUserService = UserServiceManager.manager().getExistingAssignationForUser(pool, request.user) + if assignedUserService: + in_use = assignedUserService.in_use + + # Stop when 1 usable pool is found + if hasUsablePools: + break + + # If no usable pools, this is not visible + if hasUsablePools: + group = meta.servicesPoolGroup.as_dict if meta.servicesPoolGroup else ServicesPoolGroup.default().as_dict + + services.append({ + 'id': 'M' + meta.uuid, + 'name': meta.name, + 'visual_name': meta.visual_name, + 'description': meta.comments, + 'group': group, + 'transports': [{ + 'id': 'meta', + 'name': 'meta', + 'link': html.udsMetaLink(request, meta.uuid), + 'priority': 0 + }], + 'imageId': meta.image and meta.image.uuid or 'x', + 'show_transports': False, + 'allow_users_remove': False, + 'allow_users_reset': False, + 'maintenance': meta.isInMaintenance(), + 'not_accesible': not meta.isAccessAllowed(), + 'in_use': in_use, + 'to_be_replaced': None, + 'to_be_replaced_text': '', + }) + # Now generic user service for svr in availServices: + # Skip pools that are part of meta pools + if svr.is_meta: + continue + trans = [] for t in svr.transports.all().order_by('priority'): typeTrans = t.getType() @@ -106,7 +162,7 @@ def getServicesData(request): else: in_use = ads.in_use - group = svr.servicesPoolGroup.as_dict if svr.servicesPoolGroup is not None else ServicesPoolGroup.default().as_dict + group = svr.servicesPoolGroup.as_dict if svr.servicesPoolGroup else ServicesPoolGroup.default().as_dict tbr = svr.toBeReplaced(request.user) if tbr: @@ -131,7 +187,6 @@ def getServicesData(request): 'in_use': in_use, 'to_be_replaced': tbr, 'to_be_replaced_text': tbrt, - 'comments': svr.comments, }) logger.debug('Services: {0}'.format(services)) diff --git a/server/src/uds/web/views/__init__.py b/server/src/uds/web/views/__init__.py index db486f02d..ccb676aae 100644 --- a/server/src/uds/web/views/__init__.py +++ b/server/src/uds/web/views/__init__.py @@ -33,7 +33,7 @@ from __future__ import unicode_literals import logging # from .login import login, logout -from .service import transportOwnLink, transportIcon, clientEnabler, serviceImage, action +from .service import transportOwnLink, transportIcon, userServiceEnabler, serviceImage, action from .auth import authCallback, authInfo, ticketAuth, customAuth from .download import download from uds.web.util.errors import error diff --git a/server/src/uds/web/views/login.py b/server/src/uds/web/views/login.py deleted file mode 100644 index 662e464a3..000000000 --- a/server/src/uds/web/views/login.py +++ /dev/null @@ -1,103 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (c) 2012-2018 Virtual Cable S.L. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of Virtual Cable S.L. nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -""" -@author: Adolfo Gómez, dkmaster at dkmon dot com -""" - -from django.http import HttpResponse, HttpResponseRedirect -from django.shortcuts import render -from django.urls import reverse - -from uds.core.auths.auth import webLogin, authLogLogout, getUDSCookie, webLoginRequired, webLogout -from uds.models import Authenticator -from uds.web.forms.LoginForm import LoginForm -from uds.core.util.Config import GlobalConfig -from uds.core.util.model import processUuid - -from uds.web.authentication import checkLogin - -from uds.core.ui import theme -from uds.core import VERSION - -import uds.web.util.errors as errors -import logging - -logger = logging.getLogger(__name__) -__updated__ = '2018-09-12' - - -# Allow cross-domain login -# @csrf_exempt -def login(request, tag=None): - """ - View responsible of logging in an user - :param request: http request - :param tag: tag of login auth - """ - # request.session.set_expiry(GlobalConfig.USER_SESSION_LENGTH.getInt()) - response = None - - # Default empty form - form = LoginForm(tag=tag) - - if request.method == 'POST': - form = LoginForm(request.POST, tag=tag) - user, data = checkLogin(request, form, tag) - if user: - response = HttpResponseRedirect(reverse('uds.web.views.index')) - webLogin(request, response, user, data) # data is user password here - else: # error, data = error - if isinstance(data, int): - return errors.errorView(request, data) - # Error to notify - form.add_error(None, data) - - if response is None: - response = render(request, - theme.template('login.html'), - { - 'form': form, - 'authenticators': Authenticator.getByTag(tag), - 'customHtml': GlobalConfig.CUSTOM_HTML_LOGIN.get(True), - 'version': VERSION - - } - ) - - getUDSCookie(request, response) - - return response - - -@webLoginRequired(admin=False) -def logout(request): - authLogLogout(request) - logoutUrl = request.user.logout() - if logoutUrl is None: - logoutUrl = request.session.get('logouturl', None) - return webLogout(request, logoutUrl) diff --git a/server/src/uds/web/views/service.py b/server/src/uds/web/views/service.py index d2c1188e9..085ea2f2d 100644 --- a/server/src/uds/web/views/service.py +++ b/server/src/uds/web/views/service.py @@ -51,7 +51,7 @@ import logging logger = logging.getLogger(__name__) -__updated__ = '2018-10-07' +__updated__ = '2019-02-05' @webLoginRequired(admin=False) @@ -97,13 +97,20 @@ def serviceImage(request, idImage): @webLoginRequired(admin=False) @never_cache -def clientEnabler(request, idService, idTransport): +def userServiceEnabler(request, idService, idTransport): # Maybe we could even protect this even more by limiting referer to own server /? (just a meditation..) logger.debug('idService: {}, idTransport: {}'.format(idService, idTransport)) url = '' error = _('Service not ready. Please, try again in a while.') + + # If meta service, process and rebuild idService & idTransport + try: - res = userServiceManager().getService(request.user, request.ip, idService, idTransport, doTest=False) + res = ( + idTransport == 'meta' and + userServiceManager().getMeta(request.user, request.ip, request.os, idService) or + userServiceManager().getService(request.user, request.ip, idService, idTransport, doTest=False) + ) scrambler = cryptoManager().randomString(32) password = cryptoManager().symCrypt(webPassword(request), scrambler)