forked from shaba/openuds
* Advancing on metapools
* Removed non used old code
This commit is contained in:
parent
e88256a892
commit
4509400605
@ -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'
|
||||
|
@ -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]
|
||||
|
@ -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'}},
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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()
|
||||
|
@ -107,7 +107,7 @@ urlpatterns = [
|
||||
re_path(r'^uds/webapi/img/transport/(?P<idTrans>[a-zA-Z0-9-]+)$', uds.web.views.transportIcon, name='webapi.transportIcon'),
|
||||
re_path(r'^uds/webapi/img/gallery/(?P<idImage>[a-zA-Z0-9-]+)$', uds.web.views.image, name='webapi.galleryImage'),
|
||||
|
||||
re_path(r'^uds/webapi/action/(?P<idService>.+)/enable/(?P<idTransport>[a-zA-Z0-9-]+)$', uds.web.views.clientEnabler, name='webapi.enabler'),
|
||||
re_path(r'^uds/webapi/action/(?P<idService>.+)/enable/(?P<idTransport>[a-zA-Z0-9-]+)$', uds.web.views.userServiceEnabler, name='webapi.enabler'),
|
||||
|
||||
re_path(r'^uds/webapi/action/(?P<idService>.+)/(?P<action>[a-zA-Z0-9-]+)$', uds.web.views.action, name='webapi.action'),
|
||||
|
||||
|
@ -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'),
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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)
|
@ -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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user