forked from shaba/openuds
Advancing admin (in fact already playing around with components, but made some advances.. :-) )
This commit is contained in:
parent
d68822eaf7
commit
0a0772a7c6
@ -12,7 +12,10 @@ encoding//src/uds/REST/__init__.py=utf-8
|
|||||||
encoding//src/uds/REST/handlers.py=utf-8
|
encoding//src/uds/REST/handlers.py=utf-8
|
||||||
encoding//src/uds/REST/methods/authentication.py=utf-8
|
encoding//src/uds/REST/methods/authentication.py=utf-8
|
||||||
encoding//src/uds/REST/methods/authenticators.py=utf-8
|
encoding//src/uds/REST/methods/authenticators.py=utf-8
|
||||||
|
encoding//src/uds/REST/methods/networks.py=utf-8
|
||||||
|
encoding//src/uds/REST/methods/osmanagers.py=utf-8
|
||||||
encoding//src/uds/REST/methods/providers.py=utf-8
|
encoding//src/uds/REST/methods/providers.py=utf-8
|
||||||
|
encoding//src/uds/REST/methods/transports.py=utf-8
|
||||||
encoding//src/uds/REST/mixins.py=utf-8
|
encoding//src/uds/REST/mixins.py=utf-8
|
||||||
encoding//src/uds/REST/processors.py=utf-8
|
encoding//src/uds/REST/processors.py=utf-8
|
||||||
encoding//src/uds/__init__.py=utf-8
|
encoding//src/uds/__init__.py=utf-8
|
||||||
|
@ -55,14 +55,10 @@ class Authenticators(ModelHandlerMixin, Handler):
|
|||||||
'users_count': auth.users.count(),
|
'users_count': auth.users.count(),
|
||||||
'type': type_.type(),
|
'type': type_.type(),
|
||||||
'comments': auth.comments,
|
'comments': auth.comments,
|
||||||
'type_name': type_.name(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Types(ModelTypeHandlerMixin, Handler):
|
class Types(ModelTypeHandlerMixin, Handler):
|
||||||
path = 'authenticators'
|
path = 'authenticators'
|
||||||
model = Authenticator
|
|
||||||
|
|
||||||
def enum_types(self):
|
def enum_types(self):
|
||||||
return auths.factory().providers().values()
|
return auths.factory().providers().values()
|
||||||
|
72
server/src/uds/REST/methods/networks.py
Normal file
72
server/src/uds/REST/methods/networks.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright (c) 2014 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.
|
||||||
|
|
||||||
|
'''
|
||||||
|
@itemor: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from uds.models import Network
|
||||||
|
|
||||||
|
from uds.REST import Handler, HandlerError
|
||||||
|
from uds.REST.mixins import ModelHandlerMixin, ModelTypeHandlerMixin, ModelTableHandlerMixin, ModelFakeType
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# Enclosed methods under /item path
|
||||||
|
|
||||||
|
class Networks(ModelHandlerMixin, Handler):
|
||||||
|
model = Network
|
||||||
|
|
||||||
|
def item_as_dict(self, item):
|
||||||
|
return { 'id': item.id,
|
||||||
|
'name': item.name,
|
||||||
|
'net_string': item.net_string,
|
||||||
|
'networks_count': item.transports.count(),
|
||||||
|
'type': 'NetworkType',
|
||||||
|
}
|
||||||
|
|
||||||
|
class Types(ModelTypeHandlerMixin, Handler):
|
||||||
|
path = 'networks'
|
||||||
|
|
||||||
|
# Fake mathods, to yield self on enum types and get a "fake" type for Network
|
||||||
|
def enum_types(self):
|
||||||
|
yield ModelFakeType('Network', 'NetworkType', 'A description of a network', '')
|
||||||
|
|
||||||
|
class TableInfo(ModelTableHandlerMixin, Handler):
|
||||||
|
path = 'networks'
|
||||||
|
title = _('Current Networks')
|
||||||
|
fields = [
|
||||||
|
{ 'name': {'title': _('Name'), 'visible': True } },
|
||||||
|
{ 'net_string': {'title': _('Networks')}},
|
||||||
|
{ 'networks_count': {'title': _('Used by'), 'type': 'numeric', 'width': '8em'}}
|
||||||
|
]
|
74
server/src/uds/REST/methods/osmanagers.py
Normal file
74
server/src/uds/REST/methods/osmanagers.py
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright (c) 2014 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.
|
||||||
|
|
||||||
|
'''
|
||||||
|
@osmor: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from uds.models import OSManager
|
||||||
|
from uds.core.osmanagers import factory
|
||||||
|
|
||||||
|
from uds.REST import Handler, HandlerError
|
||||||
|
from uds.REST.mixins import ModelHandlerMixin, ModelTypeHandlerMixin, ModelTableHandlerMixin
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# Enclosed methods under /osm path
|
||||||
|
|
||||||
|
class OsManagers(ModelHandlerMixin, Handler):
|
||||||
|
model = OSManager
|
||||||
|
|
||||||
|
def item_as_dict(self, osm):
|
||||||
|
type_ = osm.getType()
|
||||||
|
return { 'id': osm.id,
|
||||||
|
'name': osm.name,
|
||||||
|
'deployed_count': osm.deployedServices.count(),
|
||||||
|
'type': type_.type(),
|
||||||
|
'comments': osm.comments,
|
||||||
|
}
|
||||||
|
|
||||||
|
class Types(ModelTypeHandlerMixin, Handler):
|
||||||
|
path = 'osmanagers'
|
||||||
|
model = OsManagers
|
||||||
|
|
||||||
|
def enum_types(self):
|
||||||
|
return factory().providers().values()
|
||||||
|
|
||||||
|
class TableInfo(ModelTableHandlerMixin, Handler):
|
||||||
|
path = 'osmanagers'
|
||||||
|
title = _('Current OS Managers')
|
||||||
|
fields = [
|
||||||
|
{ 'name': {'title': _('Name'), 'visible': True } },
|
||||||
|
{ 'comments': {'title': _('Comments')}},
|
||||||
|
{ 'deployed_count': {'title': _('Used by'), 'type': 'numeric', 'width': '8em'}}
|
||||||
|
]
|
@ -54,12 +54,10 @@ class Providers(ModelHandlerMixin, Handler):
|
|||||||
'services_count': provider.services.count(),
|
'services_count': provider.services.count(),
|
||||||
'type': type_.type(),
|
'type': type_.type(),
|
||||||
'comments': provider.comments,
|
'comments': provider.comments,
|
||||||
'type_name': type_.name(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Types(ModelTypeHandlerMixin, Handler):
|
class Types(ModelTypeHandlerMixin, Handler):
|
||||||
path = 'providers'
|
path = 'providers'
|
||||||
model = Provider
|
|
||||||
|
|
||||||
def enum_types(self):
|
def enum_types(self):
|
||||||
return services.factory().providers().values()
|
return services.factory().providers().values()
|
||||||
@ -68,7 +66,7 @@ class TableInfo(ModelTableHandlerMixin, Handler):
|
|||||||
path = 'providers'
|
path = 'providers'
|
||||||
title = _('Current service providers')
|
title = _('Current service providers')
|
||||||
fields = [
|
fields = [
|
||||||
{ 'name': {'title': _('Name')} },
|
{ 'name': {'title': _('Name') } },
|
||||||
{ 'comments': {'title': _('Comments')}},
|
{ 'comments': {'title': _('Comments')}},
|
||||||
{ 'services_count': {'title': _('Services'), 'type': 'numeric', 'width': '5em'}}
|
{ 'services_count': {'title': _('Services'), 'type': 'numeric', 'width': '5em'}}
|
||||||
]
|
]
|
||||||
|
74
server/src/uds/REST/methods/transports.py
Normal file
74
server/src/uds/REST/methods/transports.py
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright (c) 2014 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.
|
||||||
|
|
||||||
|
'''
|
||||||
|
@itemor: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
|
'''
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from uds.models import Transport
|
||||||
|
from uds.core.transports import factory
|
||||||
|
|
||||||
|
from uds.REST import Handler, HandlerError
|
||||||
|
from uds.REST.mixins import ModelHandlerMixin, ModelTypeHandlerMixin, ModelTableHandlerMixin
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# Enclosed methods under /item path
|
||||||
|
|
||||||
|
class Transports(ModelHandlerMixin, Handler):
|
||||||
|
model = Transport
|
||||||
|
|
||||||
|
def item_as_dict(self, item):
|
||||||
|
type_ = item.getType()
|
||||||
|
return { 'id': item.id,
|
||||||
|
'name': item.name,
|
||||||
|
'priority': item.priority,
|
||||||
|
'deployed_count': item.deployedServices.count(),
|
||||||
|
'type': type_.type(),
|
||||||
|
'comments': item.comments
|
||||||
|
}
|
||||||
|
|
||||||
|
class Types(ModelTypeHandlerMixin, Handler):
|
||||||
|
path = 'transports'
|
||||||
|
|
||||||
|
def enum_types(self):
|
||||||
|
return factory().providers().values()
|
||||||
|
|
||||||
|
class TableInfo(ModelTableHandlerMixin, Handler):
|
||||||
|
path = 'transports'
|
||||||
|
title = _('Current Transports')
|
||||||
|
fields = [
|
||||||
|
{ 'name': {'title': _('Name'), 'visible': True } },
|
||||||
|
{ 'comments': {'title': _('Comments')}},
|
||||||
|
{ 'deployed_count': {'title': _('Used by'), 'type': 'numeric', 'width': '8em'}}
|
||||||
|
]
|
@ -54,7 +54,10 @@ class ModelHandlerMixin(object):
|
|||||||
|
|
||||||
def getItems(self, *args, **kwargs):
|
def getItems(self, *args, **kwargs):
|
||||||
for item in self.model.objects.filter(*args, **kwargs):
|
for item in self.model.objects.filter(*args, **kwargs):
|
||||||
yield self.item_as_dict(item)
|
try:
|
||||||
|
yield self.item_as_dict(item)
|
||||||
|
except:
|
||||||
|
logger.exception('Exception getting item from {0}'.format(self.model))
|
||||||
|
|
||||||
def get(self):
|
def get(self):
|
||||||
logger.debug('methot GET for {0}'.format(self.__class__.__name__))
|
logger.debug('methot GET for {0}'.format(self.__class__.__name__))
|
||||||
@ -72,7 +75,6 @@ class ModelTypeHandlerMixin(object):
|
|||||||
'''
|
'''
|
||||||
authenticated = True
|
authenticated = True
|
||||||
needs_staff = True
|
needs_staff = True
|
||||||
model = None
|
|
||||||
|
|
||||||
def enum_types(self):
|
def enum_types(self):
|
||||||
pass
|
pass
|
||||||
@ -86,7 +88,10 @@ class ModelTypeHandlerMixin(object):
|
|||||||
|
|
||||||
def getTypes(self, *args, **kwargs):
|
def getTypes(self, *args, **kwargs):
|
||||||
for type_ in self.enum_types():
|
for type_ in self.enum_types():
|
||||||
yield self.type_as_dict(type_)
|
try:
|
||||||
|
yield self.type_as_dict(type_)
|
||||||
|
except:
|
||||||
|
logger.exception('Exception enumerating types')
|
||||||
|
|
||||||
def get(self):
|
def get(self):
|
||||||
return list(self.getTypes())
|
return list(self.getTypes())
|
||||||
@ -121,3 +126,13 @@ class ModelTableHandlerMixin(object):
|
|||||||
fields.append({k1: dct})
|
fields.append({k1: dct})
|
||||||
return { 'title': unicode(self.title), 'fields': fields };
|
return { 'title': unicode(self.title), 'fields': fields };
|
||||||
|
|
||||||
|
|
||||||
|
# Fake type for models that do not needs typing
|
||||||
|
class ModelFakeType(object):
|
||||||
|
def __init__(self, name, type_, description, icon):
|
||||||
|
self._name, self._type, self._description, self._icon = name, type_, description, icon
|
||||||
|
|
||||||
|
def name(self): return self._name
|
||||||
|
def type(self): return self._type
|
||||||
|
def description(self): return self._description
|
||||||
|
def icon(self): return self._icon
|
||||||
|
@ -100,4 +100,6 @@ BasicModelRest.prototype = {
|
|||||||
api.providers = new BasicModelRest('providers');
|
api.providers = new BasicModelRest('providers');
|
||||||
//api.services = new BasicModelRest('services');
|
//api.services = new BasicModelRest('services');
|
||||||
api.authenticators = new BasicModelRest('authenticators');
|
api.authenticators = new BasicModelRest('authenticators');
|
||||||
|
api.osmanagers = new BasicModelRest('osmanagers');
|
||||||
|
api.transports = new BasicModelRest('transports');
|
||||||
|
api.networks = new BasicModelRest('networks');
|
@ -38,9 +38,9 @@
|
|||||||
if( options.icon == undefined )
|
if( options.icon == undefined )
|
||||||
options.icon = 'table';
|
options.icon = 'table';
|
||||||
|
|
||||||
return '<div class="col-lg-' + options.size + '"><div class="panel panel-primary"><div class="panel-heading">'+
|
return '<div class="panel panel-primary"><div class="panel-heading">'+
|
||||||
'<h3 class="panel-title"><span class="fa fa-'+ options.icon + '"></span> ' + title + '</h3></div>'+
|
'<h3 class="panel-title"><span class="fa fa-'+ options.icon + '"></span> ' + title + '</h3></div>'+
|
||||||
'<div class="panel-body"><table class="display" id="' + table_id + '"></table></div></div></div>';
|
'<div class="panel-body"><table class="display" id="' + table_id + '"></table></div></div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.breadcrumbs = function(path) {
|
gui.breadcrumbs = function(path) {
|
||||||
@ -72,17 +72,6 @@
|
|||||||
gui.doLog(this);
|
gui.doLog(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
gui.osmanagers = function() {
|
|
||||||
gui.clearWorkspace();
|
|
||||||
gui.appendToWorkspace(gui.breadcrumbs('OS Managers'));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
gui.connectivity = function() {
|
|
||||||
gui.clearWorkspace();
|
|
||||||
gui.appendToWorkspace(gui.breadcrumbs(gettext('Connectivity')));
|
|
||||||
}
|
|
||||||
|
|
||||||
gui.deployed_services = function() {
|
gui.deployed_services = function() {
|
||||||
gui.clearWorkspace();
|
gui.clearWorkspace();
|
||||||
gui.appendToWorkspace(gui.breadcrumbs(gettext('Deployed services')));
|
gui.appendToWorkspace(gui.breadcrumbs(gettext('Deployed services')));
|
||||||
@ -93,8 +82,8 @@
|
|||||||
{ id: 'lnk-dashboard', exec: gui.dashboard },
|
{ id: 'lnk-dashboard', exec: gui.dashboard },
|
||||||
{ id: 'lnk-service_providers', exec: gui.providers.link },
|
{ id: 'lnk-service_providers', exec: gui.providers.link },
|
||||||
{ id: 'lnk-authenticators', exec: gui.authenticators.link },
|
{ id: 'lnk-authenticators', exec: gui.authenticators.link },
|
||||||
{ id: 'lnk-osmanagers', exec: gui.osmanagers },
|
{ id: 'lnk-osmanagers', exec: gui.osmanagers.link },
|
||||||
{ id: 'lnk-connectivity', exec: gui.connectivity },
|
{ id: 'lnk-connectivity', exec: gui.connectivity.link },
|
||||||
{ id: 'lnk-deployed_services', exec: gui.deployed_services },
|
{ id: 'lnk-deployed_services', exec: gui.deployed_services },
|
||||||
];
|
];
|
||||||
$.each(sidebarLinks, function(index, value){
|
$.each(sidebarLinks, function(index, value){
|
||||||
@ -112,19 +101,24 @@
|
|||||||
gui.debug = true;
|
gui.debug = true;
|
||||||
}(window.gui = window.gui || {}, jQuery));
|
}(window.gui = window.gui || {}, jQuery));
|
||||||
|
|
||||||
function GuiElement(restItem) {
|
function GuiElement(restItem, name) {
|
||||||
this.rest = restItem;
|
this.rest = restItem;
|
||||||
|
this.name = name;
|
||||||
|
this.types = {}
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// all gui elements has, at least, name && type
|
||||||
|
// Types must include, at least: type, icon
|
||||||
GuiElement.prototype = {
|
GuiElement.prototype = {
|
||||||
init: function() {
|
init: function() {
|
||||||
gui.doLog('Initializing ' + this.rest.path);
|
gui.doLog('Initializing ' + this.name);
|
||||||
var $this = this;
|
var $this = this;
|
||||||
this.rest.types(function(data){
|
this.rest.types(function(data){
|
||||||
var styles = '<style media="screen">';
|
var styles = '<style media="screen">';
|
||||||
$.each(data, function(index, value){
|
$.each(data, function(index, value){
|
||||||
var className = $this.rest.path + '-' + value.type;
|
var className = $this.name + '-' + value.type;
|
||||||
|
$this.types[value.type] = { css: className, name: value.name || '', description: value.description || '' };
|
||||||
gui.doLog('Creating style for ' + className )
|
gui.doLog('Creating style for ' + className )
|
||||||
var style = '.' + className +
|
var style = '.' + className +
|
||||||
' { display:inline-block; background: url(data:image/png;base64,' + value.icon + '); ' +
|
' { display:inline-block; background: url(data:image/png;base64,' + value.icon + '); ' +
|
||||||
@ -135,15 +129,15 @@ GuiElement.prototype = {
|
|||||||
$(styles).appendTo('head');
|
$(styles).appendTo('head');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
table: function(options) {
|
table: function(container_id) {
|
||||||
// Empty container_id first
|
// Empty container_id first
|
||||||
gui.doLog('Composing table for ' + this.rest.path);
|
gui.doLog('Composing table for ' + this.name);
|
||||||
var tableId = this.rest.path + '-table';
|
var tableId = this.name + '-table';
|
||||||
var $this = this;
|
var $this = this;
|
||||||
this.rest.tableInfo(function(data){
|
this.rest.tableInfo(function(data){
|
||||||
var title = data.title;
|
var title = data.title;
|
||||||
var columns = [];
|
var columns = [];
|
||||||
$.each(data.fields,function(index, value) {
|
$.each(data.fields,function(index, value) {
|
||||||
for( var v in value ){
|
for( var v in value ){
|
||||||
var options = value[v];
|
var options = value[v];
|
||||||
gui.doLog(options);
|
gui.doLog(options);
|
||||||
@ -155,19 +149,38 @@ GuiElement.prototype = {
|
|||||||
column.sWidth = options.width;
|
column.sWidth = options.width;
|
||||||
if( options.visible != undefined )
|
if( options.visible != undefined )
|
||||||
column.bVisible = options.visible;
|
column.bVisible = options.visible;
|
||||||
|
if( options.sortable != undefined )
|
||||||
|
column.bSortable = options.sortable;
|
||||||
|
|
||||||
|
// Fix name columm so we can add a class icon
|
||||||
|
if( v == 'name' ) {
|
||||||
|
column.sType ='html'
|
||||||
|
}
|
||||||
|
|
||||||
columns.push(column);
|
columns.push(column);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
gui.doLog(columns);
|
gui.doLog(columns);
|
||||||
$this.rest.get({
|
$this.rest.get({
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
var table = gui.table(title, tableId, options);
|
$.each(data, function(index, value){
|
||||||
gui.appendToWorkspace('<div class="row">' + table + '</div>');
|
var type = $this.types[value.type];
|
||||||
$('#' + tableId).dataTable( {
|
data[index].name = '<span class="' + type.css + '"></span> ' + value.name
|
||||||
|
});
|
||||||
|
|
||||||
|
var table = gui.table(title, tableId);
|
||||||
|
if( container_id == undefined ) {
|
||||||
|
gui.appendToWorkspace('<div class="row"><div class="col-lg-12">' + table + '</div></div>');
|
||||||
|
} else {
|
||||||
|
$('#'+container_id).empty();
|
||||||
|
$('#'+container_id).append(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#' + tableId).dataTable({
|
||||||
"aaData": data,
|
"aaData": data,
|
||||||
"aoColumns": columns,
|
"aoColumns": columns,
|
||||||
"oLanguage": gui.dataTablesLanguage,
|
"oLanguage": gui.dataTablesLanguage,
|
||||||
} )
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -179,7 +192,7 @@ GuiElement.prototype = {
|
|||||||
// Compose gui API
|
// Compose gui API
|
||||||
|
|
||||||
// Service providers
|
// Service providers
|
||||||
gui.providers = new GuiElement(api.providers);
|
gui.providers = new GuiElement(api.providers, 'prov'); // Tha 'name' must be the same as uses on REST api
|
||||||
gui.providers.link = function(event) {
|
gui.providers.link = function(event) {
|
||||||
gui.clearWorkspace();
|
gui.clearWorkspace();
|
||||||
gui.appendToWorkspace(gui.breadcrumbs(gettext('Service Providers')));
|
gui.appendToWorkspace(gui.breadcrumbs(gettext('Service Providers')));
|
||||||
@ -189,7 +202,7 @@ gui.providers.link = function(event) {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
gui.authenticators = new GuiElement(api.authenticators);
|
gui.authenticators = new GuiElement(api.authenticators, 'auth');
|
||||||
gui.authenticators.link = function(event) {
|
gui.authenticators.link = function(event) {
|
||||||
gui.clearWorkspace();
|
gui.clearWorkspace();
|
||||||
gui.appendToWorkspace(gui.breadcrumbs(gettext('Authenticators')));
|
gui.appendToWorkspace(gui.breadcrumbs(gettext('Authenticators')));
|
||||||
@ -197,4 +210,28 @@ gui.authenticators.link = function(event) {
|
|||||||
gui.authenticators.table();
|
gui.authenticators.table();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
gui.osmanagers = new GuiElement(api.osmanagers, 'osm');
|
||||||
|
gui.osmanagers.link = function(event) {
|
||||||
|
gui.clearWorkspace();
|
||||||
|
gui.appendToWorkspace(gui.breadcrumbs('Os Managers'));
|
||||||
|
|
||||||
|
gui.osmanagers.table();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
gui.connectivity = {
|
||||||
|
transports: new GuiElement(api.transports, 'trans'),
|
||||||
|
networks: new GuiElement(api.networks, 'nets'),
|
||||||
|
};
|
||||||
|
|
||||||
|
gui.connectivity.link = function(event) {
|
||||||
|
gui.clearWorkspace();
|
||||||
|
gui.appendToWorkspace(gui.breadcrumbs(gettext('Connectivity')));
|
||||||
|
gui.appendToWorkspace('<div class="row"><div class="col-lg-6" id="ttbl"></div><div class="col-lg-6" id="ntbl"></div></div>');
|
||||||
|
|
||||||
|
gui.connectivity.transports.table('ttbl');
|
||||||
|
gui.connectivity.networks.table('ntbl');
|
||||||
|
}
|
||||||
|
204
server/src/uds/transports/NX/TSNXTransport.py
Normal file
204
server/src/uds/transports/NX/TSNXTransport.py
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
# -*- 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.
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
Created on Jul 29, 2011
|
||||||
|
|
||||||
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
|
'''
|
||||||
|
from django.utils.translation import ugettext_noop as _
|
||||||
|
from uds.core.managers.UserPrefsManager import CommonPrefs
|
||||||
|
from uds.core.ui.UserInterface import gui
|
||||||
|
from uds.core.transports.BaseTransport import Transport
|
||||||
|
from uds.core.util.Cache import Cache
|
||||||
|
from uds.core.util import connection
|
||||||
|
from web import generateHtmlForNX, getHtmlComponent
|
||||||
|
|
||||||
|
import logging, random, string, time
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
READY_CACHE_TIMEOUT = 30
|
||||||
|
|
||||||
|
class TSNXTransport(Transport):
|
||||||
|
'''
|
||||||
|
Provides access via RDP to service.
|
||||||
|
This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
|
||||||
|
'''
|
||||||
|
typeName = _('NX Transport (tunneled)')
|
||||||
|
typeType = 'TSNXTransport'
|
||||||
|
typeDescription = _('NX Transport for tunneled connection')
|
||||||
|
iconFile = 'nx.png'
|
||||||
|
needsJava = True # If this transport needs java for rendering
|
||||||
|
supportedOss = ['Windows', 'Macintosh', 'Linux']
|
||||||
|
|
||||||
|
tunnelServer = gui.TextField(label=_('Tunnel server'), order = 1, tooltip = _('IP or Hostname of tunnel server send to client device ("public" ip) and port. (use HOST:PORT format)'))
|
||||||
|
tunnelCheckServer = gui.TextField(label=_('Tunnel host check'), order = 2, tooltip = _('If not empty, this server will be used to check if service is running before assigning it to user. (use HOST:PORT format)'))
|
||||||
|
|
||||||
|
useEmptyCreds = gui.CheckBoxField(label = _('Empty creds'), order = 3, tooltip = _('If checked, the credentials used to connect will be emtpy'))
|
||||||
|
fixedName = gui.TextField(label=_('Username'), order = 4, tooltip = _('If not empty, this username will be always used as credential'))
|
||||||
|
fixedPassword = gui.PasswordField(label=_('Password'), order = 5, tooltip = _('If not empty, this password will be always used as credential'))
|
||||||
|
listenPort = gui.NumericField(label=_('Listen port'), length = 5, order = 6, tooltip = _('Listening port of NX (ssh) at client machine'), defvalue = '22')
|
||||||
|
connection = gui.ChoiceField(label=_('Connection'), order = 7, tooltip = _('Connection speed for this transport (quality)'), values = [
|
||||||
|
{'id' : 'modem', 'text' : 'modem'},
|
||||||
|
{'id' : 'isdn', 'text' : 'isdn'},
|
||||||
|
{'id' : 'adsl', 'text' : 'adsl'},
|
||||||
|
{'id' : 'wan', 'text' : 'wan'},
|
||||||
|
{'id' : 'lan', 'text' : 'lan'},
|
||||||
|
] )
|
||||||
|
session = gui.ChoiceField(label=_('Session'), order = 8, tooltip = _('Desktop session'), values = [
|
||||||
|
{'id' : 'gnome', 'text' : 'gnome'},
|
||||||
|
{'id' : 'kde', 'text' : 'kde'},
|
||||||
|
{'id' : 'cde', 'text' : 'cde'},
|
||||||
|
] )
|
||||||
|
cacheDisk = gui.ChoiceField(label=_('Disk Cache'), order = 9, tooltip = _('Cache size en Mb stored at disk'), values = [
|
||||||
|
{'id' : '0', 'text' : '0 Mb'},
|
||||||
|
{'id' : '32', 'text' : '32 Mb'},
|
||||||
|
{'id' : '64', 'text' : '64 Mb'},
|
||||||
|
{'id' : '128', 'text' : '128 Mb'},
|
||||||
|
{'id' : '256', 'text' : '256 Mb'},
|
||||||
|
{'id' : '512', 'text' : '512 Mb'},
|
||||||
|
] )
|
||||||
|
cacheMem = gui.ChoiceField(label=_('Memory Cache'), order = 10, tooltip = _('Cache size en Mb keept at memory'), values = [
|
||||||
|
{'id' : '4', 'text' : '4 Mb'},
|
||||||
|
{'id' : '8', 'text' : '8 Mb'},
|
||||||
|
{'id' : '16', 'text' : '16 Mb'},
|
||||||
|
{'id' : '32', 'text' : '32 Mb'},
|
||||||
|
{'id' : '64', 'text' : '64 Mb'},
|
||||||
|
{'id' : '128', 'text' : '128 Mb'},
|
||||||
|
] )
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, environment, values = None):
|
||||||
|
super(TSNXTransport, self).__init__(environment, values)
|
||||||
|
if values != None:
|
||||||
|
if values['tunnelServer'].find(':') == -1:
|
||||||
|
raise Transport.ValidationException(_('Must use HOST:PORT in Tunnel Server Field'))
|
||||||
|
self._tunnelServer = values['tunnelServer']
|
||||||
|
self._tunnelCheckServer = values['tunnelCheckServer']
|
||||||
|
self._useEmptyCreds = gui.strToBool(values['useEmptyCreds'])
|
||||||
|
self._fixedName = values['fixedName']
|
||||||
|
self._fixedPassword = values['fixedPassword']
|
||||||
|
self._listenPort = values['listenPort']
|
||||||
|
self._connection = values['connection']
|
||||||
|
self._session = values['session']
|
||||||
|
self._cacheDisk = values['cacheDisk']
|
||||||
|
self._cacheMem = values['cacheMem']
|
||||||
|
else:
|
||||||
|
self._tunnelServer = ''
|
||||||
|
self._tunnelCheckServer = ''
|
||||||
|
self._useEmptyCreds = ''
|
||||||
|
self._fixedName = ''
|
||||||
|
self._fixedPassword = ''
|
||||||
|
self._listenPort = ''
|
||||||
|
self._connection = ''
|
||||||
|
self._session = ''
|
||||||
|
self._cacheDisk = ''
|
||||||
|
self._cacheMem = ''
|
||||||
|
|
||||||
|
def marshal(self):
|
||||||
|
'''
|
||||||
|
Serializes the transport data so we can store it in database
|
||||||
|
'''
|
||||||
|
return str.join( '\t', [ 'v1', gui.boolToStr(self._useEmptyCreds), self._fixedName, self._fixedPassword, self._listenPort,
|
||||||
|
self._connection, self._session, self._cacheDisk, self._cacheMem, self._tunnelServer, self._tunnelCheckServer ] )
|
||||||
|
|
||||||
|
def unmarshal(self, string):
|
||||||
|
data = string.split('\t')
|
||||||
|
if data[0] == 'v1':
|
||||||
|
self._useEmptyCreds = gui.strToBool(data[1])
|
||||||
|
self._fixedName, self._fixedPassword, self._listenPort, self._connection, self._session, self._cacheDisk, self._cacheMem, self._tunnelServer, self._tunnelCheckServer = data[2:]
|
||||||
|
|
||||||
|
|
||||||
|
def valuesDict(self):
|
||||||
|
return { 'useEmptyCreds' : gui.boolToStr(self._useEmptyCreds), 'fixedName' : self._fixedName,
|
||||||
|
'fixedPassword' : self._fixedPassword, 'listenPort': self._listenPort,
|
||||||
|
'connection' : self._connection, 'session' : self._session, 'cacheDisk' : self._cacheDisk,
|
||||||
|
'cacheMem' : self._cacheMem, 'tunnelServer' : self._tunnelServer,
|
||||||
|
'tunnelCheckServer' : self._tunnelCheckServer }
|
||||||
|
|
||||||
|
def isAvailableFor(self, ip):
|
||||||
|
'''
|
||||||
|
Checks if the transport is available for the requested destination ip
|
||||||
|
Override this in yours transports
|
||||||
|
'''
|
||||||
|
logger.debug('Checking availability for {0}'.format(ip))
|
||||||
|
ready = self.cache().get(ip)
|
||||||
|
if ready is None:
|
||||||
|
# Check again for readyness
|
||||||
|
if connection.testServer(ip, self._listenPort) == True:
|
||||||
|
self.cache().put(ip, 'Y', READY_CACHE_TIMEOUT)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
self.cache().put(ip, 'N', READY_CACHE_TIMEOUT)
|
||||||
|
return ready == 'Y'
|
||||||
|
|
||||||
|
def renderForHtml(self, userService, idUserService, idTransport, ip, os, user, password):
|
||||||
|
|
||||||
|
prefs = user.prefs('nx')
|
||||||
|
|
||||||
|
username = user.getUsernameForAuth()
|
||||||
|
proc = username.split('@')
|
||||||
|
username = proc[0]
|
||||||
|
if self._fixedName is not '':
|
||||||
|
username = self._fixedName
|
||||||
|
if self._fixedPassword is not '':
|
||||||
|
password = self._fixedPassword
|
||||||
|
if self._useEmptyCreds is True:
|
||||||
|
username, password = '',''
|
||||||
|
|
||||||
|
width, height = CommonPrefs.getWidthHeight(prefs)
|
||||||
|
cache = Cache('pam')
|
||||||
|
|
||||||
|
|
||||||
|
tunuser = ''.join(random.choice(string.letters + string.digits) for i in xrange(12)) + ("%f" % time.time()).split('.')[1]
|
||||||
|
tunpass = ''.join(random.choice(string.letters + string.digits) for i in xrange(12))
|
||||||
|
cache.put(tunuser, tunpass, 60*10) # Credential valid for ten minutes, and for 1 use only
|
||||||
|
|
||||||
|
sshHost, sshPort = self._tunnelServer.split(':')
|
||||||
|
|
||||||
|
logger.debug('Username generated: {0}, password: {1}'.format(tunuser, tunpass))
|
||||||
|
tun = "{0} {1} {2} {3} {4} {5} {6}".format(tunuser, tunpass, sshHost, sshPort, ip, self._listenPort, '9')
|
||||||
|
|
||||||
|
# Extra data
|
||||||
|
extra = { 'width': width, 'height' : height,
|
||||||
|
'connection' : self._connection,
|
||||||
|
'session' : self._session, 'cacheDisk': self._cacheDisk,
|
||||||
|
'cacheMem' : self._cacheMem, 'tun' : tun }
|
||||||
|
|
||||||
|
# Fix username/password acording to os manager
|
||||||
|
username, password = userService.processUserPassword(username, password)
|
||||||
|
|
||||||
|
return generateHtmlForNX(self, idUserService, idTransport, os, username, password, extra)
|
||||||
|
|
||||||
|
def getHtmlComponent(self, theId, os, componentId):
|
||||||
|
# We use helper to keep this clean
|
||||||
|
return getHtmlComponent(self.__module__, componentId)
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 857 B |
@ -55,7 +55,7 @@ class TSNXTransport(Transport):
|
|||||||
typeName = _('NX Transport (tunneled)')
|
typeName = _('NX Transport (tunneled)')
|
||||||
typeType = 'TSNXTransport'
|
typeType = 'TSNXTransport'
|
||||||
typeDescription = _('NX Transport for tunneled connection')
|
typeDescription = _('NX Transport for tunneled connection')
|
||||||
iconFile = 'tsnx.png'
|
iconFile = 'nx.png'
|
||||||
needsJava = True # If this transport needs java for rendering
|
needsJava = True # If this transport needs java for rendering
|
||||||
supportedOss = ['Windows', 'Macintosh', 'Linux']
|
supportedOss = ['Windows', 'Macintosh', 'Linux']
|
||||||
|
|
||||||
|
BIN
server/src/uds/transports/TSNX/nx.png
Normal file
BIN
server/src/uds/transports/TSNX/nx.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 857 B |
Binary file not shown.
Before Width: | Height: | Size: 1.0 KiB |
Loading…
Reference in New Issue
Block a user