forked from shaba/openuds
Fixed connection client working
This commit is contained in:
parent
9a7afe7839
commit
e920628395
@ -243,6 +243,7 @@ class Handler:
|
|||||||
session.save()
|
session.save()
|
||||||
self._authToken = session.session_key
|
self._authToken = session.session_key
|
||||||
self._session = session
|
self._session = session
|
||||||
|
|
||||||
return self._authToken
|
return self._authToken
|
||||||
|
|
||||||
def cleanAuthToken(self) -> None:
|
def cleanAuthToken(self) -> None:
|
||||||
|
@ -39,7 +39,7 @@ from uds.REST import RequestError
|
|||||||
from uds.core.managers import userServiceManager
|
from uds.core.managers import userServiceManager
|
||||||
from uds.core.managers import cryptoManager
|
from uds.core.managers import cryptoManager
|
||||||
from uds.core.services.exceptions import ServiceNotReadyError
|
from uds.core.services.exceptions import ServiceNotReadyError
|
||||||
from uds.web.util import errors
|
from uds.web.util import errors, services
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -50,7 +50,8 @@ class Connection(Handler):
|
|||||||
"""
|
"""
|
||||||
Processes actor requests
|
Processes actor requests
|
||||||
"""
|
"""
|
||||||
authenticated = True # Actor requests are not authenticated
|
|
||||||
|
authenticated = True # Connection requests are authenticated
|
||||||
needs_admin = False
|
needs_admin = False
|
||||||
needs_staff = False
|
needs_staff = False
|
||||||
|
|
||||||
@ -59,7 +60,7 @@ class Connection(Handler):
|
|||||||
result: typing.Any = None,
|
result: typing.Any = None,
|
||||||
error: typing.Optional[typing.Union[str, int]] = None,
|
error: typing.Optional[typing.Union[str, int]] = None,
|
||||||
errorCode: int = 0,
|
errorCode: int = 0,
|
||||||
retryable: bool = False
|
retryable: bool = False,
|
||||||
) -> typing.Dict[str, typing.Any]:
|
) -> typing.Dict[str, typing.Any]:
|
||||||
"""
|
"""
|
||||||
Helper method to create a "result" set for connection response
|
Helper method to create a "result" set for connection response
|
||||||
@ -83,33 +84,44 @@ class Connection(Handler):
|
|||||||
|
|
||||||
def serviceList(self):
|
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
|
# 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
|
||||||
from uds.web.util.services import getServicesData
|
|
||||||
|
|
||||||
# Ensure user is present on request, used by web views methods
|
# Ensure user is present on request, used by web views methods
|
||||||
self._request.user = self._user
|
self._request.user = self._user # type: ignore
|
||||||
|
|
||||||
return Connection.result(result=getServicesData(self._request))
|
return Connection.result(result=services.getServicesData(self._request))
|
||||||
|
|
||||||
def connection(self, doNotCheck: bool = False):
|
def connection(self, doNotCheck: bool = False):
|
||||||
idService = self._args[0]
|
idService = self._args[0]
|
||||||
idTransport = self._args[1]
|
idTransport = self._args[1]
|
||||||
try:
|
try:
|
||||||
ip, userService, iads, trans, itrans = userServiceManager().getService( # pylint: disable=unused-variable
|
(
|
||||||
self._user, self._request.os, self._request.ip, idService, idTransport, not doNotCheck
|
ip,
|
||||||
|
userService,
|
||||||
|
iads,
|
||||||
|
trans,
|
||||||
|
itrans,
|
||||||
|
) = userServiceManager().getService( # pylint: disable=unused-variable
|
||||||
|
self._user,
|
||||||
|
self._request.os, # type: ignore
|
||||||
|
self._request.ip, # type: ignore
|
||||||
|
idService,
|
||||||
|
idTransport,
|
||||||
|
not doNotCheck,
|
||||||
)
|
)
|
||||||
ci = {
|
ci = {
|
||||||
'username': '',
|
'username': '',
|
||||||
'password': '',
|
'password': '',
|
||||||
'domain': '',
|
'domain': '',
|
||||||
'protocol': 'unknown',
|
'protocol': 'unknown',
|
||||||
'ip': ip
|
'ip': ip,
|
||||||
}
|
}
|
||||||
if itrans: # only will be available id doNotCheck is False
|
if itrans: # only will be available id doNotCheck is False
|
||||||
ci.update(itrans.getConnectionInfo(userService, self._user, 'UNKNOWN'))
|
ci.update(itrans.getConnectionInfo(userService, self._user, 'UNKNOWN'))
|
||||||
return Connection.result(result=ci)
|
return Connection.result(result=ci)
|
||||||
except ServiceNotReadyError as e:
|
except ServiceNotReadyError as e:
|
||||||
# Refresh ticket and make this retrayable
|
# Refresh ticket and make this retrayable
|
||||||
return Connection.result(error=errors.SERVICE_IN_PREPARATION, errorCode=e.code, retryable=True)
|
return Connection.result(
|
||||||
|
error=errors.SERVICE_IN_PREPARATION, errorCode=e.code, retryable=True
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception("Exception")
|
logger.exception("Exception")
|
||||||
return Connection.result(error=str(e))
|
return Connection.result(error=str(e))
|
||||||
@ -122,23 +134,59 @@ class Connection(Handler):
|
|||||||
hostname = self._args[3]
|
hostname = self._args[3]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
res = userServiceManager().getService(self._user, self._request.os, self._request.ip, idService, idTransport)
|
res = userServiceManager().getService(
|
||||||
|
self._user, self._request.os, self._request.ip, idService, idTransport # type: ignore
|
||||||
|
)
|
||||||
logger.debug('Res: %s', res)
|
logger.debug('Res: %s', res)
|
||||||
ip, userService, userServiceInstance, transport, transportInstance = res # pylint: disable=unused-variable
|
(
|
||||||
|
ip,
|
||||||
|
userService,
|
||||||
|
userServiceInstance,
|
||||||
|
transport,
|
||||||
|
transportInstance,
|
||||||
|
) = res # pylint: disable=unused-variable
|
||||||
password = cryptoManager().symDecrpyt(self.getValue('password'), scrambler)
|
password = cryptoManager().symDecrpyt(self.getValue('password'), scrambler)
|
||||||
|
|
||||||
userService.setConnectionSource(self._request.ip, hostname) # Store where we are accessing from so we can notify Service
|
userService.setConnectionSource(
|
||||||
|
self._request.ip, hostname # type: ignore
|
||||||
|
) # Store where we are accessing from so we can notify Service
|
||||||
|
|
||||||
transportScript = transportInstance.getEncodedTransportScript(userService, transport, ip, self._request.os, self._user, password, self._request)
|
if not ip:
|
||||||
|
raise ServiceNotReadyError()
|
||||||
|
|
||||||
|
transportScript = transportInstance.getEncodedTransportScript(
|
||||||
|
userService,
|
||||||
|
transport,
|
||||||
|
ip,
|
||||||
|
self._request.os, # type: ignore
|
||||||
|
self._user,
|
||||||
|
password,
|
||||||
|
self._request,
|
||||||
|
)
|
||||||
|
|
||||||
return Connection.result(result=transportScript)
|
return Connection.result(result=transportScript)
|
||||||
except ServiceNotReadyError as e:
|
except ServiceNotReadyError as e:
|
||||||
# Refresh ticket and make this retrayable
|
# Refresh ticket and make this retrayable
|
||||||
return Connection.result(error=errors.SERVICE_IN_PREPARATION, errorCode=e.code, retryable=True)
|
return Connection.result(
|
||||||
|
error=errors.SERVICE_IN_PREPARATION, errorCode=e.code, retryable=True
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception("Exception")
|
logger.exception("Exception")
|
||||||
return Connection.result(error=str(e))
|
return Connection.result(error=str(e))
|
||||||
|
|
||||||
|
def getTicketContent(self):
|
||||||
|
return {} # TODO: use this for something?
|
||||||
|
|
||||||
|
def getUdsLink(self):
|
||||||
|
# Returns the UDS link for the user & transport
|
||||||
|
self._request.user = self._user # type: ignore
|
||||||
|
self._request._cryptedpass = self._session['REST']['password'] # type: ignore
|
||||||
|
self._request._scrambler = self._request.META['HTTP_SCRAMBLER'] # type: ignore
|
||||||
|
linkInfo = services.enableService(self._request, idService=self._args[0], idTransport=self._args[1])
|
||||||
|
if linkInfo['error']:
|
||||||
|
return Connection.result(error=linkInfo['error'])
|
||||||
|
return Connection.result(result=linkInfo['url'])
|
||||||
|
|
||||||
def get(self):
|
def get(self):
|
||||||
"""
|
"""
|
||||||
Processes get requests
|
Processes get requests
|
||||||
@ -157,9 +205,12 @@ class Connection(Handler):
|
|||||||
return self.connection()
|
return self.connection()
|
||||||
|
|
||||||
if len(self._args) == 3:
|
if len(self._args) == 3:
|
||||||
# /connection/idService/idTransport/skipChecking
|
# /connection/idService/idTransport/skipcheck
|
||||||
if self._args[2] == 'skipChecking':
|
if self._args[2] == 'skipcheck':
|
||||||
return self.connection(True)
|
return self.connection(True)
|
||||||
|
# /connection/idService/idTransport/udslink
|
||||||
|
elif self._args[2] == 'udslink':
|
||||||
|
return self.getUdsLink()
|
||||||
|
|
||||||
if len(self._args) == 4:
|
if len(self._args) == 4:
|
||||||
# /connection/idService/idTransport/scrambler/hostname
|
# /connection/idService/idTransport/scrambler/hostname
|
||||||
|
@ -311,7 +311,11 @@ def webPassword(request: HttpRequest) -> str:
|
|||||||
session (db) and client browser cookies. This method uses this two values to recompose the user password
|
session (db) and client browser cookies. This method uses this two values to recompose the user password
|
||||||
so we can provide it to remote sessions.
|
so we can provide it to remote sessions.
|
||||||
"""
|
"""
|
||||||
|
if hasattr(request, 'session'):
|
||||||
return cryptoManager().symDecrpyt(request.session.get(PASS_KEY, ''), getUDSCookie(request)) # recover as original unicode string
|
return cryptoManager().symDecrpyt(request.session.get(PASS_KEY, ''), getUDSCookie(request)) # recover as original unicode string
|
||||||
|
else: # No session, get from _session instead, this is an "client" REST request
|
||||||
|
return cryptoManager().symDecrpyt(request._cryptedpass, request._scrambler) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def webLogout(request: HttpRequest, exit_url: typing.Optional[str] = None) -> HttpResponse:
|
def webLogout(request: HttpRequest, exit_url: typing.Optional[str] = None) -> HttpResponse:
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
'''
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
@ -35,15 +36,19 @@ from django.utils.translation import ugettext
|
|||||||
from django.utils import formats
|
from django.utils import formats
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from uds.models import ServicePool, Transport, Network, ServicePoolGroup, MetaPool, getSqlDatetime
|
|
||||||
|
from uds.models import ServicePool, Transport, Network, ServicePoolGroup, MetaPool, getSqlDatetime, TicketStore
|
||||||
from uds.core.util.config import GlobalConfig
|
from uds.core.util.config import GlobalConfig
|
||||||
|
from uds.core.services.exceptions import ServiceNotReadyError, MaxServicesReachedError, ServiceAccessDeniedByCalendar
|
||||||
|
from uds.core.auths.auth import webPassword
|
||||||
|
from uds.web.util import errors
|
||||||
from uds.core.util import html
|
from uds.core.util import html
|
||||||
|
|
||||||
from uds.core.managers import userServiceManager
|
from uds.core.managers import userServiceManager, cryptoManager
|
||||||
|
|
||||||
# Not imported at runtime, just for type checking
|
# Not imported at runtime, just for type checking
|
||||||
if typing.TYPE_CHECKING:
|
if typing.TYPE_CHECKING:
|
||||||
from django.http import HttpRequest # pylint: disable=ungrouped-imports
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -242,3 +247,54 @@ def getServicesData(request: 'HttpRequest') -> typing.Dict[str, typing.Any]: #
|
|||||||
'transports': validTrans,
|
'transports': validTrans,
|
||||||
'autorun': autorun
|
'autorun': autorun
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def enableService(request: 'HttpRequest', idService: str, idTransport: str) -> typing.Mapping[str, typing.Any]:
|
||||||
|
# Maybe we could even protect this even more by limiting referer to own server /? (just a meditation..)
|
||||||
|
logger.debug('idService: %s, idTransport: %s', idService, idTransport)
|
||||||
|
url = ''
|
||||||
|
error = ugettext('Service not ready. Please, try again in a while.')
|
||||||
|
|
||||||
|
# If meta service, process and rebuild idService & idTransport
|
||||||
|
|
||||||
|
try:
|
||||||
|
res = userServiceManager().getService(request.user, request.os, request.ip, idService, idTransport, doTest=False)
|
||||||
|
scrambler = cryptoManager().randomString(32)
|
||||||
|
password = cryptoManager().symCrypt(webPassword(request), scrambler)
|
||||||
|
|
||||||
|
userService, trans = res[1], res[3]
|
||||||
|
|
||||||
|
typeTrans = trans.getType()
|
||||||
|
|
||||||
|
error = '' # No error
|
||||||
|
|
||||||
|
if typeTrans.ownLink:
|
||||||
|
url = reverse('TransportOwnLink', args=('A' + userService.uuid, trans.uuid))
|
||||||
|
else:
|
||||||
|
data = {
|
||||||
|
'service': 'A' + userService.uuid,
|
||||||
|
'transport': trans.uuid,
|
||||||
|
'user': request.user.uuid,
|
||||||
|
'password': password
|
||||||
|
}
|
||||||
|
|
||||||
|
ticket = TicketStore.create(data)
|
||||||
|
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)
|
||||||
|
error = ugettext('Your service is being created, please, wait for a few seconds while we complete it.)') + '({}%)'.format(int(e.code * 25))
|
||||||
|
except MaxServicesReachedError:
|
||||||
|
logger.info('Number of service reached MAX for service pool "%s"', idService)
|
||||||
|
error = errors.errorString(errors.MAX_SERVICES_REACHED)
|
||||||
|
except ServiceAccessDeniedByCalendar:
|
||||||
|
logger.info('Access tried to a calendar limited access pool "%s"', idService)
|
||||||
|
error = errors.errorString(errors.SERVICE_CALENDAR_DENIED)
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception('Error')
|
||||||
|
error = str(e)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'url': str(url),
|
||||||
|
'error': str(error)
|
||||||
|
}
|
||||||
|
@ -33,18 +33,16 @@ import logging
|
|||||||
import typing
|
import typing
|
||||||
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.urls import reverse
|
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.views.decorators.cache import cache_page, never_cache
|
from django.views.decorators.cache import cache_page, never_cache
|
||||||
|
|
||||||
from uds.core.auths.auth import webLoginRequired, webPassword
|
from uds.core.auths.auth import webLoginRequired, webPassword
|
||||||
from uds.core.managers import userServiceManager, cryptoManager
|
from uds.core.managers import userServiceManager
|
||||||
from uds.models import TicketStore
|
|
||||||
from uds.core.ui.images import DEFAULT_IMAGE
|
from uds.core.ui.images import DEFAULT_IMAGE
|
||||||
from uds.core.util.model import processUuid
|
from uds.core.util.model import processUuid
|
||||||
from uds.models import Transport, Image
|
from uds.models import Transport, Image
|
||||||
from uds.core.util import html, log
|
from uds.core.util import log
|
||||||
from uds.core.services.exceptions import ServiceNotReadyError, MaxServicesReachedError, ServiceAccessDeniedByCalendar
|
from uds.core.services.exceptions import ServiceNotReadyError
|
||||||
|
|
||||||
from uds.web.util import errors
|
from uds.web.util import errors
|
||||||
from uds.web.util import services
|
from uds.web.util import services
|
||||||
@ -113,59 +111,12 @@ def serviceImage(request: 'HttpRequest', idImage: str) -> HttpResponse:
|
|||||||
@webLoginRequired(admin=False)
|
@webLoginRequired(admin=False)
|
||||||
@never_cache
|
@never_cache
|
||||||
def userServiceEnabler(request: 'HttpRequest', idService: str, idTransport: str) -> HttpResponse:
|
def userServiceEnabler(request: 'HttpRequest', idService: str, idTransport: str) -> HttpResponse:
|
||||||
# Maybe we could even protect this even more by limiting referer to own server /? (just a meditation..)
|
|
||||||
logger.debug('idService: %s, idTransport: %s', 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.os, request.ip, idService, idTransport, doTest=False)
|
|
||||||
scrambler = cryptoManager().randomString(32)
|
|
||||||
password = cryptoManager().symCrypt(webPassword(request), scrambler)
|
|
||||||
|
|
||||||
userService, trans = res[1], res[3]
|
|
||||||
|
|
||||||
typeTrans = trans.getType()
|
|
||||||
|
|
||||||
error = '' # No error
|
|
||||||
|
|
||||||
if typeTrans.ownLink:
|
|
||||||
url = reverse('TransportOwnLink', args=('A' + userService.uuid, trans.uuid))
|
|
||||||
else:
|
|
||||||
data = {
|
|
||||||
'service': 'A' + userService.uuid,
|
|
||||||
'transport': trans.uuid,
|
|
||||||
'user': request.user.uuid,
|
|
||||||
'password': password
|
|
||||||
}
|
|
||||||
|
|
||||||
ticket = TicketStore.create(data)
|
|
||||||
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)
|
|
||||||
error = _('Your service is being created, please, wait for a few seconds while we complete it.)') + '({}%)'.format(int(e.code * 25))
|
|
||||||
except MaxServicesReachedError:
|
|
||||||
logger.info('Number of service reached MAX for service pool "%s"', idService)
|
|
||||||
error = errors.errorString(errors.MAX_SERVICES_REACHED)
|
|
||||||
except ServiceAccessDeniedByCalendar:
|
|
||||||
logger.info('Access tried to a calendar limited access pool "%s"', idService)
|
|
||||||
error = errors.errorString(errors.SERVICE_CALENDAR_DENIED)
|
|
||||||
except Exception as e:
|
|
||||||
logger.exception('Error')
|
|
||||||
error = str(e)
|
|
||||||
|
|
||||||
return HttpResponse(
|
return HttpResponse(
|
||||||
json.dumps({
|
json.dumps(services.enableService(request, idService=idService, idTransport=idTransport)),
|
||||||
'url': str(url),
|
|
||||||
'error': str(error)
|
|
||||||
}),
|
|
||||||
content_type='application/json'
|
content_type='application/json'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def closer(request: 'HttpRequest') -> HttpResponse:
|
def closer(request: 'HttpRequest') -> HttpResponse:
|
||||||
return HttpResponse('<html><body onload="window.close()"></body></html>')
|
return HttpResponse('<html><body onload="window.close()"></body></html>')
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user