mirror of
https://github.com/dkmstr/openuds.git
synced 2024-12-22 13:34:04 +03:00
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/methods/authentication.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/transports.py=utf-8
|
||||
encoding//src/uds/REST/mixins.py=utf-8
|
||||
encoding//src/uds/REST/processors.py=utf-8
|
||||
encoding//src/uds/__init__.py=utf-8
|
||||
|
@ -55,14 +55,10 @@ class Authenticators(ModelHandlerMixin, Handler):
|
||||
'users_count': auth.users.count(),
|
||||
'type': type_.type(),
|
||||
'comments': auth.comments,
|
||||
'type_name': type_.name(),
|
||||
}
|
||||
|
||||
|
||||
|
||||
class Types(ModelTypeHandlerMixin, Handler):
|
||||
path = 'authenticators'
|
||||
model = Authenticator
|
||||
|
||||
def enum_types(self):
|
||||
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(),
|
||||
'type': type_.type(),
|
||||
'comments': provider.comments,
|
||||
'type_name': type_.name(),
|
||||
}
|
||||
|
||||
class Types(ModelTypeHandlerMixin, Handler):
|
||||
path = 'providers'
|
||||
model = Provider
|
||||
|
||||
def enum_types(self):
|
||||
return services.factory().providers().values()
|
||||
@ -68,7 +66,7 @@ class TableInfo(ModelTableHandlerMixin, Handler):
|
||||
path = 'providers'
|
||||
title = _('Current service providers')
|
||||
fields = [
|
||||
{ 'name': {'title': _('Name')} },
|
||||
{ 'name': {'title': _('Name') } },
|
||||
{ 'comments': {'title': _('Comments')}},
|
||||
{ '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):
|
||||
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):
|
||||
logger.debug('methot GET for {0}'.format(self.__class__.__name__))
|
||||
@ -72,7 +75,6 @@ class ModelTypeHandlerMixin(object):
|
||||
'''
|
||||
authenticated = True
|
||||
needs_staff = True
|
||||
model = None
|
||||
|
||||
def enum_types(self):
|
||||
pass
|
||||
@ -86,7 +88,10 @@ class ModelTypeHandlerMixin(object):
|
||||
|
||||
def getTypes(self, *args, **kwargs):
|
||||
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):
|
||||
return list(self.getTypes())
|
||||
@ -121,3 +126,13 @@ class ModelTableHandlerMixin(object):
|
||||
fields.append({k1: dct})
|
||||
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.services = new BasicModelRest('services');
|
||||
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 )
|
||||
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>'+
|
||||
'<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) {
|
||||
@ -72,17 +72,6 @@
|
||||
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.clearWorkspace();
|
||||
gui.appendToWorkspace(gui.breadcrumbs(gettext('Deployed services')));
|
||||
@ -93,8 +82,8 @@
|
||||
{ id: 'lnk-dashboard', exec: gui.dashboard },
|
||||
{ id: 'lnk-service_providers', exec: gui.providers.link },
|
||||
{ id: 'lnk-authenticators', exec: gui.authenticators.link },
|
||||
{ id: 'lnk-osmanagers', exec: gui.osmanagers },
|
||||
{ id: 'lnk-connectivity', exec: gui.connectivity },
|
||||
{ id: 'lnk-osmanagers', exec: gui.osmanagers.link },
|
||||
{ id: 'lnk-connectivity', exec: gui.connectivity.link },
|
||||
{ id: 'lnk-deployed_services', exec: gui.deployed_services },
|
||||
];
|
||||
$.each(sidebarLinks, function(index, value){
|
||||
@ -112,19 +101,24 @@
|
||||
gui.debug = true;
|
||||
}(window.gui = window.gui || {}, jQuery));
|
||||
|
||||
function GuiElement(restItem) {
|
||||
function GuiElement(restItem, name) {
|
||||
this.rest = restItem;
|
||||
this.name = name;
|
||||
this.types = {}
|
||||
this.init();
|
||||
}
|
||||
|
||||
// all gui elements has, at least, name && type
|
||||
// Types must include, at least: type, icon
|
||||
GuiElement.prototype = {
|
||||
init: function() {
|
||||
gui.doLog('Initializing ' + this.rest.path);
|
||||
gui.doLog('Initializing ' + this.name);
|
||||
var $this = this;
|
||||
this.rest.types(function(data){
|
||||
var styles = '<style media="screen">';
|
||||
$.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 )
|
||||
var style = '.' + className +
|
||||
' { display:inline-block; background: url(data:image/png;base64,' + value.icon + '); ' +
|
||||
@ -135,15 +129,15 @@ GuiElement.prototype = {
|
||||
$(styles).appendTo('head');
|
||||
});
|
||||
},
|
||||
table: function(options) {
|
||||
table: function(container_id) {
|
||||
// Empty container_id first
|
||||
gui.doLog('Composing table for ' + this.rest.path);
|
||||
var tableId = this.rest.path + '-table';
|
||||
gui.doLog('Composing table for ' + this.name);
|
||||
var tableId = this.name + '-table';
|
||||
var $this = this;
|
||||
this.rest.tableInfo(function(data){
|
||||
var title = data.title;
|
||||
var columns = [];
|
||||
$.each(data.fields,function(index, value) {
|
||||
$.each(data.fields,function(index, value) {
|
||||
for( var v in value ){
|
||||
var options = value[v];
|
||||
gui.doLog(options);
|
||||
@ -155,19 +149,38 @@ GuiElement.prototype = {
|
||||
column.sWidth = options.width;
|
||||
if( options.visible != undefined )
|
||||
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);
|
||||
}
|
||||
});
|
||||
gui.doLog(columns);
|
||||
$this.rest.get({
|
||||
success: function(data) {
|
||||
var table = gui.table(title, tableId, options);
|
||||
gui.appendToWorkspace('<div class="row">' + table + '</div>');
|
||||
$('#' + tableId).dataTable( {
|
||||
$.each(data, function(index, value){
|
||||
var type = $this.types[value.type];
|
||||
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,
|
||||
"aoColumns": columns,
|
||||
"oLanguage": gui.dataTablesLanguage,
|
||||
} )
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -179,7 +192,7 @@ GuiElement.prototype = {
|
||||
// Compose gui API
|
||||
|
||||
// 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.clearWorkspace();
|
||||
gui.appendToWorkspace(gui.breadcrumbs(gettext('Service Providers')));
|
||||
@ -189,7 +202,7 @@ gui.providers.link = function(event) {
|
||||
return false;
|
||||
};
|
||||
|
||||
gui.authenticators = new GuiElement(api.authenticators);
|
||||
gui.authenticators = new GuiElement(api.authenticators, 'auth');
|
||||
gui.authenticators.link = function(event) {
|
||||
gui.clearWorkspace();
|
||||
gui.appendToWorkspace(gui.breadcrumbs(gettext('Authenticators')));
|
||||
@ -197,4 +210,28 @@ gui.authenticators.link = function(event) {
|
||||
gui.authenticators.table();
|
||||
|
||||
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)')
|
||||
typeType = 'TSNXTransport'
|
||||
typeDescription = _('NX Transport for tunneled connection')
|
||||
iconFile = 'tsnx.png'
|
||||
iconFile = 'nx.png'
|
||||
needsJava = True # If this transport needs java for rendering
|
||||
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