mirror of
https://github.com/dkmstr/openuds.git
synced 2025-01-03 01:17:56 +03:00
Started a REST api for UDS.
The idea is provide third party access to UDS, and try to use this as an starting point to make an web based administration, so we can deprecate .net administration tool (it is becoming an annoyance... :-) ), and web based admin is always more accesible than thin client admin
This commit is contained in:
parent
918259079a
commit
47dff34637
@ -1,8 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?eclipse-pydev version="1.0"?>
|
||||
|
||||
<pydev_project>
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">python2.7</pydev_property>
|
||||
<?eclipse-pydev version="1.0"?><pydev_project>
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
|
||||
<pydev_variables_property name="org.python.pydev.PROJECT_VARIABLE_SUBSTITUTION">
|
||||
<key>DJANGO_MANAGE_LOCATION</key>
|
||||
|
@ -8,6 +8,10 @@ encoding//documentation/_downloads/samples/services/__init__.py=utf-8
|
||||
encoding//documentation/conf.py=utf-8
|
||||
encoding//src/server/settings.py=utf-8
|
||||
encoding//src/server/urls.py=utf-8
|
||||
encoding//src/uds/REST/__init__.py=utf-8
|
||||
encoding//src/uds/REST/handlers.py=utf-8
|
||||
encoding//src/uds/REST/methods/authentication.py=utf-8
|
||||
encoding//src/uds/REST/processors.py=utf-8
|
||||
encoding//src/uds/__init__.py=utf-8
|
||||
encoding//src/uds/auths/ActiveDirectory/Authenticator.py=utf-8
|
||||
encoding//src/uds/auths/ActiveDirectory/__init__.py=utf-8
|
||||
|
1
server/requirements.txt
Normal file
1
server/requirements.txt
Normal file
@ -0,0 +1 @@
|
||||
django-compressor
|
@ -2,8 +2,7 @@
|
||||
'''
|
||||
Url patterns for UDS project (Django)
|
||||
'''
|
||||
|
||||
from django.conf.urls.defaults import patterns, include
|
||||
from django.conf.urls import patterns, include
|
||||
|
||||
# Uncomment the next two lines to enable the admin:
|
||||
# from django.contrib import admin
|
||||
|
175
server/src/uds/REST/__init__.py
Normal file
175
server/src/uds/REST/__init__.py
Normal file
@ -0,0 +1,175 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2012 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 __future__ import unicode_literals
|
||||
|
||||
from django import http
|
||||
from django.views.generic.base import View
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.conf import settings
|
||||
from handlers import Handler, HandlerError, AccessDenied
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__all__ = [ str(v) for v in ['Handler', 'Dispatcher'] ]
|
||||
|
||||
class Dispatcher(View):
|
||||
services = { '' : None } # Will include a default /rest handler, but rigth now this will be fine
|
||||
|
||||
@method_decorator(csrf_exempt)
|
||||
def dispatch(self, request, **kwargs):
|
||||
import processors
|
||||
|
||||
# Remove session, so response middelwares do nothing with this
|
||||
del request.session
|
||||
# Now we extract method and posible variables from path
|
||||
path = kwargs['arguments'].split('/')
|
||||
del kwargs['arguments']
|
||||
|
||||
# Transverse service nodes too look for path
|
||||
service = Dispatcher.services
|
||||
full_path = []
|
||||
# Last element will be
|
||||
do_break = False
|
||||
cls = None
|
||||
while len(path) > 0 and not do_break:
|
||||
# .json, .xml, ... will break path recursion
|
||||
do_break = path[0].find('.') != -1
|
||||
clean_path = path[0].split('.')[0]
|
||||
if service.has_key(clean_path):
|
||||
service = service[clean_path]
|
||||
full_path.append(path[0])
|
||||
path = path[1:]
|
||||
else:
|
||||
break
|
||||
|
||||
full_path = '/'.join(full_path)
|
||||
logger.debug(full_path)
|
||||
|
||||
cls = service['']
|
||||
if cls is None:
|
||||
return http.HttpResponseNotFound('method not found')
|
||||
|
||||
|
||||
# Guess content type from content type header or ".xxx" to method
|
||||
try:
|
||||
p = full_path.split('.')
|
||||
processor = processors.available_processors_ext_dict[p[1]](request)
|
||||
except:
|
||||
processor = processors.available_processors_mime_dict.get(request.META['CONTENT_TYPE'], processors.default_processor)(request)
|
||||
|
||||
|
||||
# Obtain method to be invoked
|
||||
http_method = request.method.lower()
|
||||
|
||||
args = path
|
||||
|
||||
# Inspect
|
||||
lang = None
|
||||
if len(args) > 0:
|
||||
for l in settings.LANGUAGES:
|
||||
if args[-1] == l[0]:
|
||||
lang = l[0]
|
||||
logger.error('Found lang {0}'.format(l))
|
||||
args = args[:-1]
|
||||
break
|
||||
# Intantiate method handler and locate http_method dispatcher
|
||||
try:
|
||||
handler = cls(request, full_path, http_method, processor.processParameters(), *args, **kwargs)
|
||||
|
||||
operation = getattr(handler, http_method)
|
||||
except processors.ParametersException as e:
|
||||
return http.HttpResponseServerError('Invalid parameters invoking {0}: {1}'.format(path[0], e))
|
||||
except AttributeError:
|
||||
allowedMethods = []
|
||||
for n in ['get', 'post', 'put', 'delete']:
|
||||
if hasattr(handler, n):
|
||||
allowedMethods.append(n)
|
||||
return http.HttpResponseNotAllowed(allowedMethods)
|
||||
except AccessDenied:
|
||||
return http.HttpResponseForbidden('method access denied')
|
||||
except:
|
||||
logger.exception('error accessing attribute')
|
||||
logger.debug('Getting attribute {0} for {1}'.format(http_method, full_path))
|
||||
return http.HttpResponseServerError('Unexcepected error')
|
||||
|
||||
# Invokes the handler's operation, add headers to response and returns
|
||||
try:
|
||||
response = processor.getResponse(operation())
|
||||
for k, v in handler.headers().iteritems():
|
||||
response[k] = v
|
||||
return response
|
||||
except HandlerError as e:
|
||||
return http.HttpResponseBadRequest(unicode(e))
|
||||
except Exception as e:
|
||||
logger.exception('Error processing request')
|
||||
return http.HttpResponseServerError(unicode(e))
|
||||
|
||||
# Initializes the dispatchers
|
||||
@staticmethod
|
||||
def initialize():
|
||||
'''
|
||||
This imports all packages that are descendant of this package, and, after that,
|
||||
it register all subclases of service provider as
|
||||
'''
|
||||
import os.path, pkgutil
|
||||
import sys
|
||||
|
||||
# Dinamycally import children of this package. The __init__.py files must register, if needed, inside ServiceProviderFactory
|
||||
package = 'methods'
|
||||
|
||||
pkgpath = os.path.join(os.path.dirname(sys.modules[__name__].__file__), package)
|
||||
for _, name, _ in pkgutil.iter_modules([pkgpath]):
|
||||
__import__(__name__ + '.' + package + '.' + name, globals(), locals(), [], -1)
|
||||
|
||||
for cls in Handler.__subclasses__(): # @UndefinedVariable
|
||||
# Skip ClusteredServiceProvider
|
||||
if cls.name is None:
|
||||
name = cls.__name__.lower()
|
||||
else:
|
||||
name = cls.name
|
||||
logger.debug('Adding handler {0} for method {1} in path {2}'.format(cls, name, cls.path))
|
||||
service_node = Dispatcher.services
|
||||
if cls.path is not None:
|
||||
for k in cls.path.split('/'):
|
||||
if service_node.get(k) is None:
|
||||
service_node[k] = { '' : None }
|
||||
service_node = service_node[k]
|
||||
if service_node.get(name) is None:
|
||||
service_node[name] = { '' : None }
|
||||
|
||||
service_node[name][''] = cls
|
||||
|
||||
Dispatcher.initialize()
|
132
server/src/uds/REST/handlers.py
Normal file
132
server/src/uds/REST/handlers.py
Normal file
@ -0,0 +1,132 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 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 __future__ import unicode_literals
|
||||
from django.contrib.sessions.backends.db import SessionStore
|
||||
from django.utils.translation import activate
|
||||
from django.conf import settings
|
||||
|
||||
from uds.core.util.Config import GlobalConfig
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
AUTH_TOKEN_HEADER = 'HTTP_X_AUTH_TOKEN'
|
||||
|
||||
class HandlerError(Exception):
|
||||
pass
|
||||
|
||||
class AccessDenied(HandlerError):
|
||||
pass
|
||||
|
||||
class Handler(object):
|
||||
name = None # If name is not used, name will be the class name in lower case
|
||||
path = None # Path for this method, so we can do /auth/login, /auth/logout, /auth/auths in a simple way
|
||||
authenticated = True # By default, all handlers needs authentication
|
||||
only_admin = False # By default, the methods will be accesible by anyone
|
||||
|
||||
# method names: 'get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'
|
||||
def __init__(self, request, path, operation, params, *args, **kwargs):
|
||||
|
||||
if self.only_admin:
|
||||
self.authenticated = True # If only_admin, must also be authenticated
|
||||
|
||||
self._request = request
|
||||
self._path = path
|
||||
self._operation = operation
|
||||
self._params = params
|
||||
self._args = args
|
||||
self._kwargs = kwargs
|
||||
self._headers = {}
|
||||
self._authToken = None
|
||||
if self.authenticated: # Only retrieve auth related data on authenticated handlers
|
||||
try:
|
||||
self._authToken = self._request.META.get(AUTH_TOKEN_HEADER, '')
|
||||
self._session = SessionStore(session_key = self._authToken)
|
||||
if not self._session.has_key('REST'):
|
||||
raise Exception() # No valid session, so auth_token is also invalid
|
||||
except:
|
||||
if settings.DEBUG:
|
||||
if self._authToken == 'a':
|
||||
self.genAuthToken(-1, 'root', 'es', True)
|
||||
else:
|
||||
self._authToken = None
|
||||
self._session = None
|
||||
|
||||
|
||||
if self._authToken is None:
|
||||
raise AccessDenied()
|
||||
|
||||
if self.only_admin and not self.getValue('is_admin'):
|
||||
raise AccessDenied()
|
||||
|
||||
def headers(self):
|
||||
return self._headers
|
||||
|
||||
def header(self, header_):
|
||||
return self._headers.get(header_)
|
||||
|
||||
def addHeader(self, header, value):
|
||||
self._headers[header] = value
|
||||
|
||||
def removeHeader(self, header):
|
||||
try:
|
||||
del self._headers[header]
|
||||
except:
|
||||
pass
|
||||
|
||||
# Auth related
|
||||
def getAuthToken(self):
|
||||
return self._authToken
|
||||
|
||||
def genAuthToken(self, id_auth, username, locale, is_admin):
|
||||
session = SessionStore()
|
||||
session.set_expiry(GlobalConfig.ADMIN_IDLE_TIME.getInt())
|
||||
session['REST'] = { 'auth': id_auth, 'username': username, 'locale': locale, 'is_admin': is_admin }
|
||||
session.save()
|
||||
self._authToken = session.session_key
|
||||
self._session = session
|
||||
return self._authToken
|
||||
|
||||
def cleanAuthToken(self):
|
||||
self._authToken = None
|
||||
if self._session:
|
||||
self._session.delete()
|
||||
self._session = None
|
||||
|
||||
# Session related (from auth token)
|
||||
def getValue(self, key):
|
||||
try:
|
||||
return self._session['REST'].get(key)
|
||||
except:
|
||||
return None
|
0
server/src/uds/REST/methods/__init__.py
Normal file
0
server/src/uds/REST/methods/__init__.py
Normal file
105
server/src/uds/REST/methods/authentication.py
Normal file
105
server/src/uds/REST/methods/authentication.py
Normal file
@ -0,0 +1,105 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 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 __future__ import unicode_literals
|
||||
|
||||
from uds.core.util.Config import GlobalConfig
|
||||
from uds.models import Authenticator, User
|
||||
|
||||
from uds.REST import Handler, HandlerError
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Login(Handler):
|
||||
path = 'auth'
|
||||
authenticated = False # By default, all handlers needs authentication
|
||||
admin_method = False # By default, the methods will be accesible by anyone
|
||||
|
||||
def post(self):
|
||||
'''
|
||||
This login uses parameters to generate auth token
|
||||
The alternative is to use the template tag inside "REST" that is called auth_token, that extracts an auth token from an user session
|
||||
We can use any of this forms due to the fact that the auth token is in fact a session key
|
||||
Parameters:
|
||||
mandatory:
|
||||
username:
|
||||
password:
|
||||
auth:
|
||||
optional:
|
||||
locale: (defaults to "en")
|
||||
Result:
|
||||
on success: { 'result': 'ok', 'auth': [auth_code] }
|
||||
on error: { 'result: 'error', 'error': [error string] }
|
||||
'''
|
||||
try:
|
||||
username, auth, password = self._params['username'], self._params['auth'], self._params['password']
|
||||
locale = self._params.get('locale', 'en')
|
||||
if auth == 'admin':
|
||||
if GlobalConfig.SUPER_USER_LOGIN.get(True) == username and GlobalConfig.SUPER_USER_PASS.get(True) == password:
|
||||
self.genAuthToken(-1, username, locale, True)
|
||||
return{'result': 'ok', 'token': self.getAuthToken()}
|
||||
else:
|
||||
raise Exception('Invalid credentials')
|
||||
except Exception as e:
|
||||
logger.exception('exception')
|
||||
return {'result': 'error', 'error': unicode(e)}
|
||||
|
||||
|
||||
class Logout(Handler):
|
||||
path = 'auth'
|
||||
authenticated = True # By default, all handlers needs authentication
|
||||
admin_method = False # By default, the methods will be accesible by anyone
|
||||
|
||||
def get(self):
|
||||
# Remove auth token
|
||||
self.cleanAuthToken()
|
||||
return 'done'
|
||||
|
||||
def post(self):
|
||||
return self.get()
|
||||
|
||||
class Auth(Handler):
|
||||
authenticated = False # By default, all handlers needs authentication
|
||||
admin_method = False # By default, the methods will be accesible by anyone
|
||||
|
||||
def auths(self):
|
||||
for a in Authenticator.all():
|
||||
if a.getType().isCustom() is False:
|
||||
yield { 'auth' : str(a.small_name), 'name' : a.name }
|
||||
|
||||
def get(self):
|
||||
return list(self.auths())
|
||||
|
||||
|
98
server/src/uds/REST/processors.py
Normal file
98
server/src/uds/REST/processors.py
Normal file
@ -0,0 +1,98 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 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 __future__ import unicode_literals
|
||||
|
||||
from django.utils import simplejson
|
||||
from django import http
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class ParametersException(Exception):
|
||||
pass
|
||||
|
||||
class ContentProcessor(object):
|
||||
mime_type = None
|
||||
extensions = None
|
||||
|
||||
def __init__(self, request):
|
||||
self._request = request
|
||||
|
||||
def processParameters(self):
|
||||
return ''
|
||||
|
||||
def getResponse(self, obj):
|
||||
return http.HttpResponse(content = self.render(obj), content_type=self.mime_type + "; charset=utf-8")
|
||||
|
||||
def render(self, obj):
|
||||
return unicode(obj)
|
||||
|
||||
# ---------------
|
||||
# Json Processor
|
||||
# ---------------
|
||||
class JsonProcessor(ContentProcessor):
|
||||
mime_type = 'application/json'
|
||||
extensions = ['json']
|
||||
|
||||
def processParameters(self):
|
||||
try:
|
||||
if len(self._request.body) == 0:
|
||||
return {}
|
||||
res = simplejson.loads(self._request.body)
|
||||
logger.debug(res)
|
||||
return res
|
||||
except Exception as e:
|
||||
logger.error('parsing json: {0}'.format(e))
|
||||
raise ParametersException(unicode(e))
|
||||
|
||||
def render(self, obj):
|
||||
return simplejson.dumps(obj)
|
||||
|
||||
# ---------------
|
||||
# Json Processor
|
||||
# ---------------
|
||||
class XMLProcessor(ContentProcessor):
|
||||
mime_type = 'application/xml'
|
||||
extensions = ['xml']
|
||||
|
||||
def processParameters(self):
|
||||
return ''
|
||||
|
||||
processors_list = (JsonProcessor,XMLProcessor)
|
||||
default_processor = JsonProcessor
|
||||
available_processors_mime_dict = dict((cls.mime_type, cls) for cls in processors_list)
|
||||
available_processors_ext_dict = {}
|
||||
for cls in processors_list:
|
||||
for ext in cls.extensions:
|
||||
available_processors_ext_dict[ext] = cls
|
@ -31,7 +31,7 @@
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
|
||||
from django.conf.urls.defaults import patterns, include
|
||||
from django.conf.urls import patterns
|
||||
|
||||
urlpatterns = patterns(__package__,
|
||||
(r'^guacamole/(?P<tunnelId>.+)$', 'views.guacamole'),
|
||||
|
@ -31,7 +31,7 @@
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
|
||||
from django.conf.urls.defaults import patterns, include
|
||||
from django.conf.urls import patterns
|
||||
|
||||
urlpatterns = patterns(__package__,
|
||||
(r'^pam$', 'views.pam'),
|
||||
|
@ -1,5 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
@ -32,8 +31,9 @@
|
||||
'''
|
||||
|
||||
from django.conf import settings
|
||||
from django.conf.urls.defaults import patterns, include
|
||||
from django.conf.urls import patterns, include
|
||||
from uds.core.util.modfinder import loadModulesUrls
|
||||
from uds import REST
|
||||
|
||||
urlpatterns = patterns('uds',
|
||||
(r'^$', 'web.views.index'),
|
||||
@ -64,8 +64,7 @@ urlpatterns = patterns('uds',
|
||||
(r'^authJava/(?P<idAuth>.+)/(?P<hasJava>.*)$', 'web.views.authJava'),
|
||||
(r'^authinfo/(?P<authName>.+)', 'web.views.authInfo'),
|
||||
(r'^about', 'web.views.about'),
|
||||
(r'^about', 'web.views.about'),
|
||||
|
||||
(r'^rest/(?P<arguments>.*)$', REST.Dispatcher.as_view()),
|
||||
)
|
||||
|
||||
# Append urls from special dispatcher
|
||||
|
@ -76,7 +76,7 @@ class XMLRPCDispatcher(SimpleXMLRPCDispatcher):
|
||||
|
||||
def dispatch(self, request, **kwargs):
|
||||
import xmlrpclib
|
||||
xml = request.raw_post_data
|
||||
xml = request.body
|
||||
try:
|
||||
params, method = xmlrpclib.loads(xml)
|
||||
try:
|
||||
|
Loading…
Reference in New Issue
Block a user