mirror of
https://github.com/dkmstr/openuds.git
synced 2025-01-10 01:17:59 +03:00
* Added creation date to user & group, so we can include "auto clean by age" mechanichs
* Added changelogs to Publications, so we can "store" if we like a text with every publication * Added "ServiceNotReadyError" as method of controlling if a service is ready, instead of returning None * Merged several migrations into one * Updated message error so we include a "code" when service is not ready * Added user getService to userServiceManager, that is where it must be
This commit is contained in:
parent
1dac61ea69
commit
a34de035cb
@ -40,9 +40,9 @@ from uds.REST import RequestError
|
||||
from uds.models import TicketStore
|
||||
from uds.models import User
|
||||
from uds.web import errors
|
||||
from uds.web.views.service import getService
|
||||
from uds.core.managers import cryptoManager
|
||||
from uds.core.managers import cryptoManager, userServiceManager
|
||||
from uds.core.util.Config import GlobalConfig
|
||||
from uds.core.services.Exceptions import ServiceNotReadyError
|
||||
|
||||
import six
|
||||
|
||||
@ -62,7 +62,7 @@ class Client(Handler):
|
||||
authenticated = False # Client requests are not authenticated
|
||||
|
||||
@staticmethod
|
||||
def result(result=None, error=None):
|
||||
def result(result=None, error=None, errorCode=0):
|
||||
'''
|
||||
Helper method to create a "result" set for actor response
|
||||
:param result: Result value to return (can be None, in which case it is converted to empty string '')
|
||||
@ -74,6 +74,9 @@ class Client(Handler):
|
||||
if error is not None:
|
||||
if isinstance(error, int):
|
||||
error = errors.errorString(error)
|
||||
if errorCode != 0:
|
||||
error += ' (code {0:04X})'.format(errorCode)
|
||||
|
||||
res['error'] = error
|
||||
return res
|
||||
|
||||
@ -123,21 +126,23 @@ class Client(Handler):
|
||||
|
||||
try:
|
||||
logger.debug(data)
|
||||
res = getService(self._request, data['service'], data['transport'])
|
||||
res = userServiceManager().getService(self._request.user, self._request.ip, data['service'], data['transport'])
|
||||
logger.debug('Res: {}'.format(res))
|
||||
if res is not None:
|
||||
ip, userService, userServiceInstance, transport, transportInstance = res
|
||||
password = cryptoManager().xor(data['password'], scrambler).decode('utf-8')
|
||||
ip, userService, userServiceInstance, transport, transportInstance = res
|
||||
password = cryptoManager().xor(data['password'], scrambler).decode('utf-8')
|
||||
|
||||
userService.setConnectionSource(srcIp, hostname) # Store where we are accessing from so we can notify Service
|
||||
userService.setConnectionSource(srcIp, hostname) # Store where we are accessing from so we can notify Service
|
||||
|
||||
transportScript = transportInstance.getUDSTransportScript(userService, transport, ip, self._request.os, self._request.user, password, self._request)
|
||||
transportScript = transportInstance.getUDSTransportScript(userService, transport, ip, self._request.os, self._request.user, password, self._request)
|
||||
|
||||
logger.debug('Script:\n{}'.format(transportScript))
|
||||
logger.debug('Script:\n{}'.format(transportScript))
|
||||
|
||||
return Client.result(result=transportScript.encode('bz2').encode('base64'))
|
||||
return Client.result(result=transportScript.encode('bz2').encode('base64'))
|
||||
except ServiceNotReadyError as e:
|
||||
return Client.result(error=errors.SERVICE_NOT_READY, errorCode=e.code)
|
||||
except Exception as e:
|
||||
logger.exception("Exception")
|
||||
return Client.result(error=six.text_type(e))
|
||||
|
||||
return Client.result(error=errors.SERVICE_NOT_READY)
|
||||
# Will never reach this
|
||||
raise RuntimeError('Unreachable point reached!!!')
|
||||
|
@ -53,7 +53,7 @@ from uds.models import User
|
||||
import logging
|
||||
import six
|
||||
|
||||
__updated__ = '2015-03-27'
|
||||
__updated__ = '2015-04-30'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
authLogger = logging.getLogger('authLog')
|
||||
@ -232,7 +232,7 @@ def authenticateViaCallback(authenticator, params):
|
||||
username = authInstance.authCallback(params, gm)
|
||||
|
||||
if username is None or username == '' or gm.hasValidGroups() is False:
|
||||
raise auths.Exceptions.InvalidUserException('User don\'t has access to UDS')
|
||||
raise auths.Exceptions.InvalidUserException('User doesn\'t has access to UDS')
|
||||
|
||||
return __registerUser(authenticator, authInstance, username)
|
||||
|
||||
|
@ -41,11 +41,11 @@ 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 MaxServicesReachedException
|
||||
from uds.models import UserService, getSqlDatetime
|
||||
from uds.core.services.Exceptions import MaxServicesReachedError, ServiceInMaintenanceMode, InvalidServiceException, ServiceNotReadyError
|
||||
from uds.models import ServicePool, UserService, getSqlDatetime, Transport
|
||||
from uds.core import services
|
||||
from uds.core.services import Service
|
||||
from uds.core.util.stats.events import addEvent, ET_CACHE_HIT, ET_CACHE_MISS
|
||||
from uds.core.util.stats import events
|
||||
|
||||
import requests
|
||||
import json
|
||||
@ -201,7 +201,7 @@ class UserServiceManager(object):
|
||||
numberOfServices = deployedService.userServices.filter(state__in=[State.PREPARING, State.USABLE]).count()
|
||||
|
||||
if serviceInstance.maxDeployed <= numberOfServices:
|
||||
raise MaxServicesReachedException('Max number of allowed deployments for service reached')
|
||||
raise MaxServicesReachedError('Max number of allowed deployments for service reached')
|
||||
|
||||
def __createCacheAtDb(self, deployedServicePublication, cacheLevel):
|
||||
'''
|
||||
@ -377,7 +377,7 @@ class UserServiceManager(object):
|
||||
# Out of atomic transaction
|
||||
if cache is not None:
|
||||
logger.debug('Found a cached-ready service from {0} for user {1}, item {2}'.format(ds, user, cache))
|
||||
addEvent(ds, ET_CACHE_HIT, fld1=ds.cachedUserServices().filter(cache_level=services.UserDeployment.L1_CACHE, state=State.USABLE).count())
|
||||
events.addEvent(ds, events.ET_CACHE_HIT, fld1=ds.cachedUserServices().filter(cache_level=services.UserDeployment.L1_CACHE, state=State.USABLE).count())
|
||||
ci = cache.getInstance() # User Deployment instance
|
||||
ci.assignToUser(user)
|
||||
cache.updateData(ci)
|
||||
@ -399,7 +399,7 @@ class UserServiceManager(object):
|
||||
# Out of atomic transaction
|
||||
if cache is not None:
|
||||
logger.debug('Found a cached-preparing service from {0} for user {1}, item {2}'.format(ds, user, cache))
|
||||
addEvent(ds, ET_CACHE_MISS, fld1=ds.cachedUserServices().filter(cache_level=services.UserDeployment.L1_CACHE, state=State.PREPARING).count())
|
||||
events.addEvent(ds, events.ET_CACHE_MISS, fld1=ds.cachedUserServices().filter(cache_level=services.UserDeployment.L1_CACHE, state=State.PREPARING).count())
|
||||
ci = cache.getInstance() # User Deployment instance
|
||||
ci.assignToUser(user)
|
||||
cache.updateData(ci)
|
||||
@ -413,9 +413,9 @@ class UserServiceManager(object):
|
||||
inAssigned = ds.assignedUserServices().filter(UserServiceManager.getStateFilter()).count()
|
||||
# totalL1Assigned = inCacheL1 + inAssigned
|
||||
if inAssigned >= ds.max_srvs: # cacheUpdater will drop necesary L1 machines, so it's not neccesary to check against inCacheL1
|
||||
raise MaxServicesReachedException()
|
||||
raise MaxServicesReachedError()
|
||||
# Can create new service, create it
|
||||
addEvent(ds, ET_CACHE_MISS, fld1=0)
|
||||
events.addEvent(ds, events.ET_CACHE_MISS, fld1=0)
|
||||
return self.createAssignedFor(ds, user)
|
||||
|
||||
def getServicesInStateForProvider(self, provider_id, state):
|
||||
@ -524,3 +524,67 @@ class UserServiceManager(object):
|
||||
elif uService.state in (State.USABLE, State.PREPARING): # We don't want to get active deleting or deleted machines...
|
||||
uService.setState(State.PREPARING)
|
||||
UserServiceOpChecker.makeUnique(uService, ui, state)
|
||||
|
||||
def getService(self, user, srcIp, idService, idTransport, doTest=True):
|
||||
'''
|
||||
Get service info from
|
||||
'''
|
||||
kind, idService = idService[0], idService[1:]
|
||||
|
||||
logger.debug('Kind of service: {0}, idService: {1}'.format(kind, idService))
|
||||
if kind == 'A': # This is an assigned service
|
||||
logger.debug('Getting A service {}'.format(idService))
|
||||
userService = UserService.objects.get(uuid=idService)
|
||||
userService.deployed_service.validateUser(user)
|
||||
else:
|
||||
ds = ServicePool.objects.get(uuid=idService)
|
||||
# We first do a sanity check for this, if the user has access to this service
|
||||
# If it fails, will raise an exception
|
||||
ds.validateUser(user)
|
||||
# Now we have to locate an instance of the service, so we can assign it to user.
|
||||
userService = self.getAssignationForUser(ds, user)
|
||||
|
||||
if userService.isInMaintenance() is True:
|
||||
raise ServiceInMaintenanceMode()
|
||||
|
||||
logger.debug('Found service: {0}'.format(userService))
|
||||
trans = Transport.objects.get(uuid=idTransport)
|
||||
|
||||
# Ensures that the transport is allowed for this service
|
||||
if trans not in userService.deployed_service.transports.all():
|
||||
raise InvalidServiceException()
|
||||
|
||||
# If transport is not available for the request IP...
|
||||
if trans.validForIp(srcIp) is False:
|
||||
raise InvalidServiceException()
|
||||
|
||||
if doTest is False:
|
||||
return (None, userService, None, trans, None)
|
||||
|
||||
serviceNotReadyCode = 0x0001
|
||||
|
||||
# Test if the service is ready
|
||||
if userService.isReady():
|
||||
serviceNotReadyCode = 0x0002
|
||||
log.doLog(userService, log.INFO, "User {0} from {1} has initiated access".format(user.name, srcIp), log.WEB)
|
||||
# If ready, show transport for this service, if also ready ofc
|
||||
iads = userService.getInstance()
|
||||
ip = iads.getIp()
|
||||
events.addEvent(userService.deployed_service, events.ET_ACCESS, username=user.name, srcip=srcIp, dstip=ip, uniqueid=userService.unique_id)
|
||||
if ip is not None:
|
||||
serviceNotReadyCode = 0x0003
|
||||
itrans = trans.getInstance()
|
||||
if itrans.isAvailableFor(ip):
|
||||
userService.setConnectionSource(srcIp, 'unknown')
|
||||
log.doLog(userService, log.INFO, "User service ready", log.WEB)
|
||||
UserServiceManager.manager().notifyPreconnect(userService, itrans.processedUser(userService, user), itrans.protocol)
|
||||
return (ip, userService, iads, trans, itrans)
|
||||
else:
|
||||
log.doLog(userService, log.WARN, "User service is not accessible (ip {0})".format(ip), log.TRANSPORT)
|
||||
logger.debug('Transport is not ready for user service {0}'.format(userService))
|
||||
else:
|
||||
logger.debug('Ip not available from user service {0}'.format(userService))
|
||||
else:
|
||||
log.doLog(userService, log.WARN, "User {0} from {1} tried to access, but service was not ready".format(user.name, srcIp), log.WEB)
|
||||
|
||||
raise ServiceNotReadyError(code=serviceNotReadyCode)
|
||||
|
@ -34,7 +34,7 @@ UDS managers (downloads, users preferences, publications, ...)
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
__updated__ = '2014-02-19'
|
||||
__updated__ = '2015-04-30'
|
||||
|
||||
|
||||
def cryptoManager():
|
||||
@ -60,3 +60,8 @@ def logManager():
|
||||
def statsManager():
|
||||
from StatsManager import StatsManager
|
||||
return StatsManager.manager()
|
||||
|
||||
|
||||
def userServiceManager():
|
||||
from UserServiceManager import UserServiceManager
|
||||
return UserServiceManager.manager()
|
||||
|
@ -32,51 +32,56 @@
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
__updated__ = '2015-02-10'
|
||||
__updated__ = '2015-04-30'
|
||||
|
||||
|
||||
class UnsupportedException(Exception):
|
||||
class ServiceException(Exception):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ServiceException, self).__init__(*args)
|
||||
|
||||
|
||||
class UnsupportedException(ServiceException):
|
||||
'''
|
||||
Reflects that we request an operation that is not supported, i.e. Cancel a publication with snapshots
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class OperationException(Exception):
|
||||
class OperationException(ServiceException):
|
||||
'''
|
||||
Reflects that the operation requested can't be acomplished, i.e. remove an snapshot without snapshot reference, cancel non running operation, etc...
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class PublishException(Exception):
|
||||
class PublishException(ServiceException):
|
||||
'''
|
||||
Reflects thate the publication can't be done for causes we don't know in advance
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class DeploymentException(Exception):
|
||||
class DeploymentException(ServiceException):
|
||||
'''
|
||||
Reflects that a deployment of a service (at cache, or assigned to user) can't be done for causes we don't know in advance
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class CancelException(Exception):
|
||||
class CancelException(ServiceException):
|
||||
'''
|
||||
Reflects that a "cancel" operation can't be done for some reason
|
||||
'''
|
||||
|
||||
|
||||
class InvalidServiceException(Exception):
|
||||
class InvalidServiceException(ServiceException):
|
||||
'''
|
||||
Invalid service specified. The service is not ready
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class MaxServicesReachedException(Exception):
|
||||
class MaxServicesReachedError(ServiceException):
|
||||
'''
|
||||
Number of maximum services has been reached, and no more services
|
||||
can be created for users.
|
||||
@ -84,8 +89,18 @@ class MaxServicesReachedException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ServiceInMaintenanceMode(Exception):
|
||||
class ServiceInMaintenanceMode(ServiceException):
|
||||
'''
|
||||
The service is in maintenance mode and can't be accesed right now
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class ServiceNotReadyError(ServiceException):
|
||||
'''
|
||||
The service is not ready
|
||||
Can include an optional code error
|
||||
'''
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ServiceNotReadyError, self).__init__(*args, **kwargs)
|
||||
self.code = kwargs.get('code', 0x0000)
|
||||
|
@ -37,7 +37,7 @@ from django.db.models import Q
|
||||
from uds.core.util.Config import GlobalConfig
|
||||
from uds.core.util.State import State
|
||||
from uds.core.managers.UserServiceManager import UserServiceManager
|
||||
from uds.core.services.Exceptions import MaxServicesReachedException
|
||||
from uds.core.services.Exceptions import MaxServicesReachedError
|
||||
from uds.models import DeployedService
|
||||
from uds.core import services
|
||||
from uds.core.util import log
|
||||
@ -173,7 +173,7 @@ class ServiceCacheUpdater(Job):
|
||||
return
|
||||
try:
|
||||
UserServiceManager.manager().createCacheFor(sp.activePublication(), services.UserDeployment.L1_CACHE)
|
||||
except MaxServicesReachedException as e:
|
||||
except MaxServicesReachedError as e:
|
||||
log.doLog(sp, log.ERROR, 'Max number of services reached for this service', log.INTERNAL)
|
||||
logger.error(str(e))
|
||||
except:
|
||||
@ -190,7 +190,7 @@ class ServiceCacheUpdater(Job):
|
||||
logger.debug("Growing L2 cache creating a new service for {0}".format(sp))
|
||||
try:
|
||||
UserServiceManager.manager().createCacheFor(sp.activePublication(), services.UserDeployment.L2_CACHE)
|
||||
except MaxServicesReachedException as e:
|
||||
except MaxServicesReachedError as e:
|
||||
logger.error(str(e))
|
||||
# TODO: When alerts are ready, notify this
|
||||
|
||||
|
@ -1,31 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import django.db.models.deletion
|
||||
import uds.models.Util
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('uds', '0015_ticketstore'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='deployedservice',
|
||||
name='image',
|
||||
field=models.ForeignKey(related_name='deployedServices', on_delete=django.db.models.deletion.SET_NULL, blank=True, to='uds.Image', null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='group',
|
||||
name='manager',
|
||||
field=uds.models.Util.UnsavedForeignKey(related_name='groups', to='uds.Authenticator'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='user',
|
||||
name='manager',
|
||||
field=uds.models.Util.UnsavedForeignKey(related_name='users', to='uds.Authenticator'),
|
||||
),
|
||||
]
|
54
server/src/uds/migrations/0016_auto_20150430_1257.py
Normal file
54
server/src/uds/migrations/0016_auto_20150430_1257.py
Normal file
@ -0,0 +1,54 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import django.db.models.deletion
|
||||
import uds.models.Util
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('uds', '0015_ticketstore'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='DeployedServicePublicationChangelog',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('revision', models.PositiveIntegerField(default=1)),
|
||||
('log', models.TextField(default='')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='group',
|
||||
name='created',
|
||||
field=models.DateTimeField(default=uds.models.Util.getSqlDatetime, blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='created',
|
||||
field=models.DateTimeField(default=uds.models.Util.getSqlDatetime, blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='deployedservice',
|
||||
name='image',
|
||||
field=models.ForeignKey(related_name='deployedServices', on_delete=django.db.models.deletion.SET_NULL, blank=True, to='uds.Image', null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='group',
|
||||
name='manager',
|
||||
field=uds.models.Util.UnsavedForeignKey(related_name='groups', to='uds.Authenticator'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='user',
|
||||
name='manager',
|
||||
field=uds.models.Util.UnsavedForeignKey(related_name='users', to='uds.Authenticator'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='deployedservicepublicationchangelog',
|
||||
name='publication',
|
||||
field=models.ForeignKey(related_name='changelog', to='uds.DeployedService'),
|
||||
),
|
||||
]
|
@ -44,13 +44,13 @@ from uds.models.UUIDModel import UUIDModel
|
||||
|
||||
from uds.models.Authenticator import Authenticator
|
||||
from uds.models.User import User
|
||||
from uds.models.Util import UnsavedForeignKey
|
||||
from uds.models.Util import UnsavedForeignKey, getSqlDatetime
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__updated__ = '2015-04-27'
|
||||
__updated__ = '2015-04-30'
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
@ -67,6 +67,7 @@ class Group(UUIDModel):
|
||||
is_meta = models.BooleanField(default=False, db_index=True)
|
||||
meta_if_any = models.BooleanField(default=False)
|
||||
groups = models.ManyToManyField('self', symmetrical=False)
|
||||
created = models.DateTimeField(default=getSqlDatetime, blank=True)
|
||||
|
||||
class Meta(UUIDModel.Meta):
|
||||
'''
|
||||
|
@ -33,8 +33,6 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
__updated__ = '2014-09-16'
|
||||
|
||||
from django.db import models
|
||||
from django.db.models import signals
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
@ -49,9 +47,22 @@ from uds.models.UUIDModel import UUIDModel
|
||||
|
||||
import logging
|
||||
|
||||
__updated__ = '2015-04-30'
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class DeployedServicePublicationChangelog(models.Model):
|
||||
publication = models.ForeignKey(DeployedService, on_delete=models.CASCADE, related_name='changelog')
|
||||
revision = models.PositiveIntegerField(default=1)
|
||||
log = models.TextField(default='')
|
||||
|
||||
def __str__(self):
|
||||
return 'Revision log for publication {0}, rev {1}: {2}'.format(self.publication.name, self.revision, self.log)
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class DeployedServicePublication(UUIDModel):
|
||||
'''
|
||||
@ -188,3 +199,6 @@ class DeployedServicePublication(UUIDModel):
|
||||
|
||||
# Connects a pre deletion signal to Authenticator
|
||||
signals.pre_delete.connect(DeployedServicePublication.beforeDelete, sender=DeployedServicePublication)
|
||||
|
||||
ServicePoolPublication = DeployedServicePublication
|
||||
|
||||
|
@ -48,7 +48,7 @@ import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__updated__ = '2015-04-27'
|
||||
__updated__ = '2015-04-30'
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
@ -67,6 +67,7 @@ class User(UUIDModel):
|
||||
is_admin = models.BooleanField(default=False) # is true, this is a super-admin
|
||||
last_access = models.DateTimeField(default=NEVER)
|
||||
parent = models.CharField(max_length=50, default=None, null=True)
|
||||
created = models.DateTimeField(default=getSqlDatetime, blank=True)
|
||||
|
||||
class Meta(UUIDModel.Meta):
|
||||
'''
|
||||
|
@ -42,7 +42,7 @@ from .transformers import scrambleId, transformId
|
||||
|
||||
from uds.models import DeployedService, Transport, UserService, Authenticator
|
||||
from uds.core.auths.Exceptions import InvalidUserException, InvalidAuthenticatorException
|
||||
from uds.core.services.Exceptions import InvalidServiceException, MaxServicesReachedException, ServiceInMaintenanceMode
|
||||
from uds.core.services.Exceptions import InvalidServiceException, MaxServicesReachedError, ServiceInMaintenanceMode, ServiceNotReadyError
|
||||
from uds.core.ui import theme
|
||||
|
||||
import traceback
|
||||
@ -115,12 +115,15 @@ def exceptionView(request, exception):
|
||||
return errorView(request, ACCESS_DENIED)
|
||||
except InvalidServiceException:
|
||||
return errorView(request, INVALID_SERVICE)
|
||||
except MaxServicesReachedException:
|
||||
except MaxServicesReachedError:
|
||||
return errorView(request, MAX_SERVICES_REACHED)
|
||||
except InvalidAuthenticatorException:
|
||||
return errorView(request, INVALID_CALLBACK)
|
||||
except ServiceInMaintenanceMode:
|
||||
return errorView(request, SERVICE_IN_MAINTENANCE)
|
||||
except ServiceNotReadyError as e:
|
||||
# add code as high bits of idError
|
||||
return errorView(request, e.code << 8 | SERVICE_NOT_READY)
|
||||
except Exception as e:
|
||||
logger.exception('Exception cautgh at view!!!')
|
||||
raise e
|
||||
@ -133,4 +136,11 @@ def error(request, idError):
|
||||
:param request:
|
||||
:param idError:
|
||||
'''
|
||||
return render_to_response(theme.template('error.html'), {'errorString': errorString(idError)}, context_instance=RequestContext(request))
|
||||
code = idError >> 8
|
||||
idError = idError & 0xFF
|
||||
|
||||
errStr = errorString(idError)
|
||||
if code != 0:
|
||||
errStr += ' (code {0:04X})'.format(code)
|
||||
|
||||
return render_to_response(theme.template('error.html'), {'errorString': errStr}, context_instance=RequestContext(request))
|
||||
|
@ -40,6 +40,7 @@ from django.template import RequestContext
|
||||
|
||||
from uds.core.auths.auth import webLogin, webLogout, authenticateViaCallback, authLogLogin, getUDSCookie
|
||||
from uds.models import Authenticator, DeployedService
|
||||
from uds.core.managers import userServiceManager
|
||||
from uds.core.util import html
|
||||
from uds.core.util import OsDetector
|
||||
from uds.core.util.State import State
|
||||
@ -48,17 +49,16 @@ from uds.core.ui import theme
|
||||
from uds.models import TicketStore
|
||||
|
||||
from uds.core.auths.Exceptions import InvalidUserException
|
||||
from uds.core.services.Exceptions import InvalidServiceException
|
||||
from uds.core.services.Exceptions import InvalidServiceException, ServiceNotReadyError
|
||||
|
||||
import uds.web.errors as errors
|
||||
from uds.web.views.service import getService
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
__updated__ = '2015-04-27'
|
||||
__updated__ = '2015-04-30'
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
@ -105,6 +105,9 @@ def authCallback(request, authName):
|
||||
logger.exception('authCallback')
|
||||
return errors.exceptionView(request, e)
|
||||
|
||||
# Will never reach this
|
||||
raise RuntimeError('Unreachable point reached!!!')
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
def authInfo(request, authName):
|
||||
@ -192,16 +195,7 @@ def ticketAuth(request, ticketId):
|
||||
# Check if servicePool is part of the ticket
|
||||
if servicePool is not None:
|
||||
# If service pool is in there, also is transport
|
||||
res = getService(request, 'F' + servicePool, transport)
|
||||
if res is None:
|
||||
return render_to_response(
|
||||
theme.template('service_not_ready.html'),
|
||||
{
|
||||
'fromLauncher': True
|
||||
},
|
||||
context_instance=RequestContext(request)
|
||||
)
|
||||
|
||||
res = userServiceManager().getService(request.user, request.ip, 'F' + servicePool, transport)
|
||||
ip, userService, userServiceInstance, transport, transportInstance = res
|
||||
|
||||
if transportInstance.ownLink is True:
|
||||
@ -222,6 +216,16 @@ def ticketAuth(request, ticketId):
|
||||
# Now ensure uds cookie is at response
|
||||
getUDSCookie(request, response, True)
|
||||
return response
|
||||
except ServiceNotReadyError as e:
|
||||
return render_to_response(
|
||||
theme.template('service_not_ready.html'),
|
||||
{
|
||||
'fromLauncher': True,
|
||||
'code': e.code
|
||||
},
|
||||
context_instance=RequestContext(request)
|
||||
)
|
||||
|
||||
except TicketStore.InvalidTicket:
|
||||
return render_to_response(
|
||||
theme.template('simpleLauncherAlreadyLaunched.html'),
|
||||
|
@ -37,100 +37,47 @@ from django.template import RequestContext
|
||||
from django.views.decorators.cache import cache_page, never_cache
|
||||
|
||||
from uds.core.auths.auth import webLoginRequired, webPassword
|
||||
from uds.core.services.Exceptions import ServiceInMaintenanceMode, InvalidServiceException
|
||||
from uds.core.managers.UserServiceManager import UserServiceManager
|
||||
from uds.core.managers import userServiceManager, cryptoManager
|
||||
from uds.models import TicketStore
|
||||
from uds.core.ui.images import DEFAULT_IMAGE
|
||||
from uds.core.ui import theme
|
||||
from uds.core.util.Config import GlobalConfig
|
||||
from uds.core.util.stats import events
|
||||
from uds.core.util import log
|
||||
from uds.core.util import OsDetector
|
||||
from uds.models import DeployedService, Transport, UserService, Image
|
||||
from uds.models import Transport, Image
|
||||
from uds.core.util import html
|
||||
from uds.core.services.Exceptions import ServiceNotReadyError, MaxServicesReachedError
|
||||
|
||||
import uds.web.errors as errors
|
||||
from uds.core.managers import cryptoManager
|
||||
|
||||
import six
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__updated__ = '2015-04-27'
|
||||
|
||||
|
||||
def getService(request, idService, idTransport, doTest=True):
|
||||
kind, idService = idService[0], idService[1:]
|
||||
|
||||
logger.debug('Kind of service: {0}, idService: {1}'.format(kind, idService))
|
||||
if kind == 'A': # This is an assigned service
|
||||
logger.debug('Getting A service {}'.format(idService))
|
||||
userService = UserService.objects.get(uuid=idService)
|
||||
userService.deployed_service.validateUser(request.user)
|
||||
else:
|
||||
ds = DeployedService.objects.get(uuid=idService)
|
||||
# We first do a sanity check for this, if the user has access to this service
|
||||
# If it fails, will raise an exception
|
||||
ds.validateUser(request.user)
|
||||
# Now we have to locate an instance of the service, so we can assign it to user.
|
||||
userService = UserServiceManager.manager().getAssignationForUser(ds, request.user)
|
||||
|
||||
if userService.isInMaintenance() is True:
|
||||
raise ServiceInMaintenanceMode()
|
||||
|
||||
logger.debug('Found service: {0}'.format(userService))
|
||||
trans = Transport.objects.get(uuid=idTransport)
|
||||
|
||||
# Ensures that the transport is allowed for this service
|
||||
if trans not in userService.deployed_service.transports.all():
|
||||
raise InvalidServiceException()
|
||||
|
||||
# If transport is not available for the request IP...
|
||||
if trans.validForIp(request.ip) is False:
|
||||
raise InvalidServiceException()
|
||||
|
||||
if doTest is False:
|
||||
return (None, userService, None, trans, None)
|
||||
|
||||
# Test if the service is ready
|
||||
if userService.isReady():
|
||||
log.doLog(userService, log.INFO, "User {0} from {1} has initiated access".format(request.user.name, request.ip), log.WEB)
|
||||
# If ready, show transport for this service, if also ready ofc
|
||||
iads = userService.getInstance()
|
||||
ip = iads.getIp()
|
||||
events.addEvent(userService.deployed_service, events.ET_ACCESS, username=request.user.name, srcip=request.ip, dstip=ip, uniqueid=userService.unique_id)
|
||||
if ip is not None:
|
||||
itrans = trans.getInstance()
|
||||
if itrans.isAvailableFor(ip):
|
||||
userService.setConnectionSource(request.ip, 'unknown')
|
||||
log.doLog(userService, log.INFO, "User service ready", log.WEB)
|
||||
UserServiceManager.manager().notifyPreconnect(userService, itrans.processedUser(userService, request.user), itrans.protocol)
|
||||
return (ip, userService, iads, trans, itrans)
|
||||
else:
|
||||
log.doLog(userService, log.WARN, "User service is not accessible (ip {0})".format(ip), log.TRANSPORT)
|
||||
logger.debug('Transport is not ready for user service {0}'.format(userService))
|
||||
else:
|
||||
logger.debug('Ip not available from user service {0}'.format(userService))
|
||||
else:
|
||||
log.doLog(userService, log.WARN, "User {0} from {1} tried to access, but machine was not ready".format(request.user.name, request.ip), log.WEB)
|
||||
|
||||
return None
|
||||
__updated__ = '2015-04-30'
|
||||
|
||||
|
||||
@webLoginRequired(admin=False)
|
||||
def transportOwnLink(request, idService, idTransport):
|
||||
try:
|
||||
res = getService(request, idService, idTransport)
|
||||
if res is not None:
|
||||
ip, userService, iads, trans, itrans = res
|
||||
# This returns a response object in fact
|
||||
return itrans.getLink(userService, trans, ip, request.os, request.user, webPassword(request), request)
|
||||
except Exception, e:
|
||||
res = userServiceManager().getService(request.user, request.ip, idService, idTransport)
|
||||
ip, userService, iads, trans, itrans = res # @UnusedVariable
|
||||
# This returns a response object in fact
|
||||
return itrans.getLink(userService, trans, ip, request.os, request.user, webPassword(request), request)
|
||||
except ServiceNotReadyError as e:
|
||||
return render_to_response(
|
||||
theme.template('service_not_ready.html'),
|
||||
{
|
||||
'fromLauncher': False,
|
||||
'code': e.code
|
||||
},
|
||||
context_instance=RequestContext(request)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.exception("Exception")
|
||||
return errors.exceptionView(request, e)
|
||||
|
||||
return render_to_response(theme.template('service_not_ready.html'), context_instance=RequestContext(request))
|
||||
# Will never reach this
|
||||
raise RuntimeError('Unreachable point reached!!!')
|
||||
|
||||
|
||||
@webLoginRequired(admin=False)
|
||||
@ -179,26 +126,34 @@ def clientEnabler(request, idService, idTransport):
|
||||
url = ''
|
||||
error = _('Service not ready. Please, try again in a while.')
|
||||
try:
|
||||
res = getService(request, idService, idTransport, doTest=False)
|
||||
if res is not None:
|
||||
res = userServiceManager().getService(request.user, request.ip, idService, idTransport, doTest=False)
|
||||
scrambler = cryptoManager().randomString(32)
|
||||
password = cryptoManager().xor(webPassword(request), scrambler)
|
||||
|
||||
scrambler = cryptoManager().randomString(32)
|
||||
password = cryptoManager().xor(webPassword(request), scrambler)
|
||||
_x, userService, _x, trans, _x = res
|
||||
|
||||
_x, userService, _x, trans, _x = res
|
||||
data = {
|
||||
'service': 'A' + userService.uuid,
|
||||
'transport': trans.uuid,
|
||||
'user': request.user.uuid,
|
||||
'password': password
|
||||
}
|
||||
|
||||
data = {
|
||||
'service': 'A' + userService.uuid,
|
||||
'transport': trans.uuid,
|
||||
'user': request.user.uuid,
|
||||
'password': password
|
||||
}
|
||||
|
||||
ticket = TicketStore.create(data)
|
||||
error = ''
|
||||
url = html.udsLink(request, ticket, scrambler)
|
||||
ticket = TicketStore.create(data)
|
||||
error = ''
|
||||
url = html.udsLink(request, ticket, scrambler)
|
||||
except ServiceNotReadyError as e:
|
||||
logger.debug('Service not ready')
|
||||
# Not ready, show message and return to this page in a while
|
||||
error += ' (code {0:04X})'.format(e.code)
|
||||
except MaxServicesReachedError:
|
||||
logger.info('Number of service reached MAX for service pool "{}"'.format(idService))
|
||||
error = _('Maximum number of services reached. Contact your administrator')
|
||||
except Exception as e:
|
||||
logger.exception('Error')
|
||||
error = six.text_type(e)
|
||||
|
||||
# Not ready, show message and return to this page in a while
|
||||
return HttpResponse('{{ "url": "{}", "error": "{}" }}'.format(url, error), content_type='application/json')
|
||||
return HttpResponse(
|
||||
'{{ "url": "{}", "error": "{}" }}'.format(url, error),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user