forked from shaba/openuds
Needs more testing, but permission delegation seems to work right now.
This commit is contained in:
parent
6387629e7e
commit
2435f589b9
@ -37,11 +37,13 @@ from django.views.decorators.csrf import csrf_exempt
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils.translation import ugettext as _, activate
|
||||
from django.conf import settings
|
||||
from uds.REST.handlers import Handler, HandlerError, AccessDenied, NotFound, RequestError, ResponseError
|
||||
from uds.REST.handlers import Handler, HandlerError, AccessDenied, NotFound, RequestError, ResponseError, NotSupportedError
|
||||
|
||||
import time
|
||||
import logging
|
||||
|
||||
import six
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__all__ = [str(v) for v in ['Handler', 'Dispatcher']]
|
||||
@ -142,18 +144,20 @@ class Dispatcher(View):
|
||||
response[k] = val
|
||||
return response
|
||||
except RequestError as e:
|
||||
return http.HttpResponseBadRequest(unicode(e))
|
||||
return http.HttpResponseBadRequest(six.text_type(e))
|
||||
except ResponseError as e:
|
||||
return http.HttpResponseServerError(unicode(e))
|
||||
return http.HttpResponseServerError(six.text_type(e))
|
||||
except NotSupportedError as e:
|
||||
return http.HttpResponseBadRequest(six.text_type(e))
|
||||
except AccessDenied as e:
|
||||
return http.HttpResponseForbidden(unicode(e))
|
||||
return http.HttpResponseForbidden(six.text_type(e))
|
||||
except NotFound as e:
|
||||
return http.HttpResponseNotFound(unicode(e))
|
||||
return http.HttpResponseNotFound(six.text_type(e))
|
||||
except HandlerError as e:
|
||||
return http.HttpResponseBadRequest(unicode(e))
|
||||
return http.HttpResponseBadRequest(six.text_type(e))
|
||||
except Exception as e:
|
||||
logger.exception('Error processing request')
|
||||
return http.HttpResponseServerError(unicode(e))
|
||||
return http.HttpResponseServerError(six.text_type(e))
|
||||
|
||||
@staticmethod
|
||||
def registerSubclasses(classes):
|
||||
|
@ -82,6 +82,13 @@ class ResponseError(HandlerError):
|
||||
pass
|
||||
|
||||
|
||||
class NotSupportedError(HandlerError):
|
||||
'''
|
||||
Some elements do not support some operations (as searching over an authenticator that does not supports it)
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class Handler(object):
|
||||
'''
|
||||
REST requests handler base class
|
||||
@ -110,6 +117,7 @@ class Handler(object):
|
||||
self._kwargs = kwargs
|
||||
self._headers = {}
|
||||
self._authToken = None
|
||||
self._user = None
|
||||
if self.authenticated: # Only retrieve auth related data on authenticated handlers
|
||||
try:
|
||||
self._authToken = self._request.META.get(AUTH_TOKEN_HEADER, '')
|
||||
@ -129,6 +137,8 @@ class Handler(object):
|
||||
if self.needs_staff and not self.getValue('staff_member'):
|
||||
raise AccessDenied()
|
||||
|
||||
self._user = self.getUser()
|
||||
|
||||
def headers(self):
|
||||
'''
|
||||
Returns the headers of the REST request (all)
|
||||
@ -253,6 +263,7 @@ class Handler(object):
|
||||
'''
|
||||
If user is staff member, returns his Associated user on auth
|
||||
'''
|
||||
logger.debug('REST : {}'.format(self._session))
|
||||
authId = self.getValue('auth')
|
||||
username = self.getValue('username')
|
||||
# Maybe it's root user??
|
||||
|
@ -39,6 +39,7 @@ from uds.core import auths
|
||||
from users_groups import Users, Groups
|
||||
from uds.REST import NotFound
|
||||
from uds.REST.model import ModelHandler
|
||||
from uds.core.util import permissions
|
||||
|
||||
import logging
|
||||
|
||||
@ -93,10 +94,12 @@ class Authenticators(ModelHandler):
|
||||
'small_name': auth.small_name,
|
||||
'users_count': auth.users.count(),
|
||||
'type': type_.type(),
|
||||
'permission': permissions.getEffectivePermission(self._user, auth)
|
||||
}
|
||||
|
||||
# Custom "search" method
|
||||
def search(self, item):
|
||||
self.ensureAccess(item, permissions.PERMISSION_READ)
|
||||
try:
|
||||
type_ = self._params['type']
|
||||
if type_ not in ('user', 'group'):
|
||||
@ -108,7 +111,7 @@ class Authenticators(ModelHandler):
|
||||
|
||||
canDoSearch = type_ == 'user' and (auth.searchUsers != auths.Authenticator.searchUsers) or (auth.searchGroups != auths.Authenticator.searchGroups)
|
||||
if canDoSearch is False:
|
||||
self.invalidRequestException()
|
||||
self.notSupported()
|
||||
|
||||
if type_ == 'user':
|
||||
return auth.searchUsers(term)
|
||||
@ -121,6 +124,8 @@ class Authenticators(ModelHandler):
|
||||
from uds.core.Environment import Environment
|
||||
|
||||
authType = auths.factory().lookup(type_)
|
||||
self.ensureAccess(authType, permissions.PERMISSION_MANAGEMENT, root=True)
|
||||
|
||||
dct = self._params.copy()
|
||||
dct['_request'] = self._request
|
||||
res = authType.test(Environment.getTempEnv(), dct)
|
||||
|
@ -35,6 +35,7 @@ from __future__ import unicode_literals
|
||||
from django.utils.translation import ugettext_lazy as _, ugettext
|
||||
from uds.models import Network
|
||||
from uds.core.util import net
|
||||
from uds.core.util import permissions
|
||||
from uds.core.ui.UserInterface import gui
|
||||
|
||||
from uds.REST.model import ModelHandler, SaveException
|
||||
@ -89,4 +90,5 @@ class Networks(ModelHandler):
|
||||
'name': item.name,
|
||||
'net_string': item.net_string,
|
||||
'networks_count': item.transports.count(),
|
||||
'permission': permissions.getEffectivePermission(self._user, item)
|
||||
}
|
||||
|
@ -33,8 +33,8 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||
from django.conf import settings
|
||||
from uds.models import OSManager
|
||||
from uds.core.util import permissions
|
||||
|
||||
from uds.REST import NotFound, RequestError
|
||||
from uds.core.osmanagers import factory
|
||||
@ -59,8 +59,7 @@ class OsManagers(ModelHandler):
|
||||
{'deployed_count': {'title': _('Used by'), 'type': 'numeric', 'width': '8em'}}
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def osmToDict(osm):
|
||||
def osmToDict(self, osm):
|
||||
type_ = osm.getType()
|
||||
return {
|
||||
'id': osm.uuid,
|
||||
@ -68,10 +67,11 @@ class OsManagers(ModelHandler):
|
||||
'deployed_count': osm.deployedServices.count(),
|
||||
'type': type_.type(),
|
||||
'comments': osm.comments,
|
||||
'permission': permissions.getEffectivePermission(self._user, osm)
|
||||
}
|
||||
|
||||
def item_as_dict(self, item):
|
||||
return OsManagers.osmToDict(item)
|
||||
return self.osmToDict(item)
|
||||
|
||||
def checkDelete(self, item):
|
||||
if item.deployedServices.count() > 0:
|
||||
|
@ -38,7 +38,7 @@ from uds.REST import Handler
|
||||
from uds.REST import RequestError
|
||||
from uds.core.util import permissions
|
||||
|
||||
from uds.models import Provider, Service, Authenticator, OSManager, Transport, Network, ServicesPool
|
||||
from uds.models import Provider, Service, Authenticator, OSManager, Transport, Network, ServicePool
|
||||
from uds.models import User, Group
|
||||
|
||||
import six
|
||||
@ -64,7 +64,7 @@ class Permissions(Handler):
|
||||
'osmanagers': OSManager,
|
||||
'transports': Transport,
|
||||
'networks': Network,
|
||||
'servicespools': ServicesPool
|
||||
'servicespools': ServicePool
|
||||
}.get(arg, None)
|
||||
|
||||
if cls is None:
|
||||
@ -84,16 +84,17 @@ class Permissions(Handler):
|
||||
entity = perm.user
|
||||
|
||||
res.append({
|
||||
'id': perm.uuid,
|
||||
'type': kind,
|
||||
'auth': entity.manager.uuid,
|
||||
'auth_name': entity.manager.name,
|
||||
'id': entity.uuid,
|
||||
'name': entity.name,
|
||||
'entity_id': entity.uuid,
|
||||
'entity_name': entity.name,
|
||||
'perm': perm.permission,
|
||||
'perm_name': perm.permission_as_string
|
||||
})
|
||||
|
||||
return sorted(res, key=lambda v: v['auth_name'] + v['name'])
|
||||
return sorted(res, key=lambda v: v['auth_name'] + v['entity_name'])
|
||||
|
||||
def get(self):
|
||||
'''
|
||||
@ -115,28 +116,36 @@ class Permissions(Handler):
|
||||
'''
|
||||
Processes post requests
|
||||
'''
|
||||
if len(self._args) != 4:
|
||||
raise RequestError('Invalid request')
|
||||
|
||||
logger.debug('Put args: {}'.format(self._args))
|
||||
|
||||
perm = {
|
||||
'0': permissions.PERMISSION_NONE,
|
||||
'1': permissions.PERMISSION_READ,
|
||||
'2': permissions.PERMISSION_ALL
|
||||
}.get(self._params.get('perm', '0'), permissions.PERMISSION_NONE)
|
||||
la = len(self._args)
|
||||
|
||||
cls = Permissions.getClass(self._args[0])
|
||||
if la == 5 and self._args[3] == 'add':
|
||||
perm = {
|
||||
'0': permissions.PERMISSION_NONE,
|
||||
'1': permissions.PERMISSION_READ,
|
||||
'2': permissions.PERMISSION_MANAGEMENT,
|
||||
'3': permissions.PERMISSION_ALL
|
||||
}.get(self._params.get('perm', '0'), permissions.PERMISSION_NONE)
|
||||
|
||||
obj = cls.objects.get(uuid=self._args[1])
|
||||
cls = Permissions.getClass(self._args[0])
|
||||
|
||||
if self._args[2] == 'users':
|
||||
user = User.objects.get(uuid=self._args[3])
|
||||
permissions.addUserPermission(user, obj, perm)
|
||||
elif self._args[2] == 'groups':
|
||||
group = Group.objects.get(uuid=self._args[3])
|
||||
permissions.addGroupPermission(group, obj, perm)
|
||||
obj = cls.objects.get(uuid=self._args[1])
|
||||
|
||||
if self._args[2] == 'users':
|
||||
user = User.objects.get(uuid=self._args[4])
|
||||
permissions.addUserPermission(user, obj, perm)
|
||||
elif self._args[2] == 'groups':
|
||||
group = Group.objects.get(uuid=self._args[4])
|
||||
permissions.addGroupPermission(group, obj, perm)
|
||||
else:
|
||||
raise RequestError('Ivalid request')
|
||||
|
||||
return Permissions.permsToDict(permissions.getPermissions(obj))
|
||||
elif la == 1 and self._args[0] == 'revoke':
|
||||
items = self._params.get('items', [])
|
||||
for permId in items:
|
||||
permissions.revokePermissionById(permId)
|
||||
return {}
|
||||
else:
|
||||
raise RequestError('Ivalid request')
|
||||
|
||||
return Permissions.permsToDict(permissions.getPermissions(obj))
|
||||
raise RequestError('Invalid request')
|
||||
|
@ -36,6 +36,7 @@ from django.utils.translation import ugettext, ugettext_lazy as _
|
||||
from uds.models import Provider, Service, UserService
|
||||
from uds.REST.methods.services import Services as DetailServices
|
||||
from uds.core import services
|
||||
from uds.core.util import permissions
|
||||
|
||||
from uds.REST import NotFound, RequestError
|
||||
from uds.REST.model import ModelHandler
|
||||
@ -87,6 +88,7 @@ class Providers(ModelHandler):
|
||||
'offers': offers,
|
||||
'type': type_.type(),
|
||||
'comments': provider.comments,
|
||||
'permission': permissions.getEffectivePermission(self._user, provider)
|
||||
}
|
||||
|
||||
def checkDelete(self, item):
|
||||
@ -110,7 +112,9 @@ class Providers(ModelHandler):
|
||||
'''
|
||||
for s in Service.objects.all():
|
||||
try:
|
||||
yield DetailServices.serviceToDict(s, True)
|
||||
perm = permissions.getEffectivePermission(self._user, s)
|
||||
if perm >= permissions.PERMISSION_READ:
|
||||
yield DetailServices.serviceToDict(s, perm, True)
|
||||
except Exception:
|
||||
logger.exception('Passed service cause type is unknown')
|
||||
|
||||
@ -119,7 +123,9 @@ class Providers(ModelHandler):
|
||||
Custom method that returns a service by its uuid, no matter who's his daddy
|
||||
'''
|
||||
try:
|
||||
return DetailServices.serviceToDict(Service.objects.get(uuid=self._args[1]), True)
|
||||
service = Service.objects.get(uuid=self._args[1])
|
||||
perm = self.ensureAccess(service, permissions.PERMISSION_READ) # Ensures that we can read this item
|
||||
return DetailServices.serviceToDict(service, perm, True)
|
||||
except Exception:
|
||||
raise RequestError(ugettext('Service not found'))
|
||||
|
||||
@ -128,6 +134,7 @@ class Providers(ModelHandler):
|
||||
Custom method that swaps maintenance mode state for a provider
|
||||
:param item:
|
||||
'''
|
||||
self.ensureAccess(item, permissions.PERMISSION_MANAGEMENT)
|
||||
item.maintenance_mode = not item.maintenance_mode
|
||||
item.save()
|
||||
return self.item_as_dict(item)
|
||||
@ -137,6 +144,9 @@ class Providers(ModelHandler):
|
||||
|
||||
logger.debug('Type: {}'.format(type_))
|
||||
spType = services.factory().lookup(type_)
|
||||
|
||||
self.ensureAccess(spType, permissions.PERMISSION_MANAGEMENT, root=True)
|
||||
|
||||
logger.debug('spType: {}'.format(spType))
|
||||
res = spType.test(Environment.getTempEnv(), self._params)
|
||||
if res[0]:
|
||||
|
@ -39,6 +39,7 @@ from uds.models import Service, UserService
|
||||
|
||||
from uds.core.services import Service as coreService
|
||||
from uds.core.util import log
|
||||
from uds.core.util import permissions
|
||||
from uds.core.Environment import Environment
|
||||
from uds.REST.model import DetailHandler
|
||||
from uds.REST import NotFound, ResponseError, RequestError
|
||||
@ -55,7 +56,22 @@ class Services(DetailHandler): # pylint: disable=too-many-public-methods
|
||||
'''
|
||||
|
||||
@staticmethod
|
||||
def serviceToDict(item, full=False):
|
||||
def serviceInfo(item):
|
||||
info = item.getType()
|
||||
return {
|
||||
'icon': info.icon().replace('\n', ''),
|
||||
'needs_publication': info.publicationType is not None,
|
||||
'max_deployed': info.maxDeployed,
|
||||
'uses_cache': info.usesCache,
|
||||
'uses_cache_l2': info.usesCache_L2,
|
||||
'cache_tooltip': _(info.cacheTooltip),
|
||||
'cache_tooltip_l2': _(info.cacheTooltip_L2),
|
||||
'needs_manager': info.needsManager,
|
||||
'must_assign_manually': info.mustAssignManually,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def serviceToDict(item, perm, full=False):
|
||||
'''
|
||||
Convert a service db item to a dict for a rest response
|
||||
:param item: Service item (db)
|
||||
@ -70,31 +86,22 @@ class Services(DetailHandler): # pylint: disable=too-many-public-methods
|
||||
'deployed_services_count': item.deployedServices.count(),
|
||||
'user_services_count': UserService.objects.filter(deployed_service__service=item).count(),
|
||||
'maintenance_mode': item.provider.maintenance_mode,
|
||||
'permission': perm
|
||||
}
|
||||
if full:
|
||||
info = item.getType()
|
||||
retVal['info'] = {
|
||||
'icon': info.icon().replace('\n', ''),
|
||||
'needs_publication': info.publicationType is not None,
|
||||
'max_deployed': info.maxDeployed,
|
||||
'uses_cache': info.usesCache,
|
||||
'uses_cache_l2': info.usesCache_L2,
|
||||
'cache_tooltip': _(info.cacheTooltip),
|
||||
'cache_tooltip_l2': _(info.cacheTooltip_L2),
|
||||
'needs_manager': info.needsManager,
|
||||
'must_assign_manually': info.mustAssignManually,
|
||||
}
|
||||
retVal['info'] = Services.serviceInfo(item)
|
||||
|
||||
return retVal
|
||||
|
||||
def getItems(self, parent, item):
|
||||
# Extract provider
|
||||
# Check what kind of access do we have to parent provider
|
||||
perm = permissions.getEffectivePermission(self._user, parent)
|
||||
try:
|
||||
if item is None:
|
||||
return [Services.serviceToDict(k) for k in parent.services.all()]
|
||||
return [Services.serviceToDict(k, perm) for k in parent.services.all()]
|
||||
else:
|
||||
k = parent.services.get(uuid=item)
|
||||
val = Services.serviceToDict(k)
|
||||
val = Services.serviceToDict(k, perm, full=True)
|
||||
return self.fillIntanceFields(k, val)
|
||||
except Exception:
|
||||
logger.exception('itemId {}'.format(item))
|
||||
|
@ -37,10 +37,12 @@ from uds.models import DeployedService, OSManager, Service, Image
|
||||
from uds.core.ui.images import DEFAULT_THUMB_BASE64
|
||||
from uds.core.util.State import State
|
||||
from uds.core.util import log
|
||||
from uds.core.util import permissions
|
||||
from uds.REST.model import ModelHandler
|
||||
from uds.REST import RequestError, ResponseError
|
||||
from uds.core.ui.UserInterface import gui
|
||||
from uds.REST.methods.user_services import AssignedService, CachedService, Groups, Transports, Publications
|
||||
from .user_services import AssignedService, CachedService, Groups, Transports, Publications
|
||||
from .services import Services
|
||||
|
||||
import logging
|
||||
|
||||
@ -80,6 +82,7 @@ class ServicesPools(ModelHandler):
|
||||
val = {
|
||||
'id': item.uuid,
|
||||
'name': item.name,
|
||||
'parent': item.service.name,
|
||||
'comments': item.comments,
|
||||
'state': item.state if item.service.provider.maintenance_mode is False else State.MAINTENANCE,
|
||||
'thumb': item.image.thumb64 if item.image is not None else DEFAULT_THUMB_BASE64,
|
||||
@ -93,6 +96,8 @@ class ServicesPools(ModelHandler):
|
||||
'user_services_count': item.userServices.count(),
|
||||
'restrained': item.isRestrained(),
|
||||
'show_transports': item.show_transports,
|
||||
'permission': permissions.getEffectivePermission(self._user, item),
|
||||
'info': Services.serviceInfo(item.service)
|
||||
}
|
||||
|
||||
if item.osmanager is not None:
|
||||
|
@ -35,6 +35,7 @@ from __future__ import unicode_literals
|
||||
from django.utils.translation import ugettext_lazy as _, ugettext
|
||||
from uds.models import Transport, Network
|
||||
from uds.core.transports import factory
|
||||
from uds.core.util import permissions
|
||||
|
||||
from uds.REST.model import ModelHandler
|
||||
|
||||
@ -93,6 +94,7 @@ class Transports(ModelHandler):
|
||||
'networks': [{'id': n.id} for n in item.networks.all()],
|
||||
'deployed_count': item.deployedServices.count(),
|
||||
'type': type_.type(),
|
||||
'permission': permissions.getEffectivePermission(self._user, item)
|
||||
}
|
||||
|
||||
def afterSave(self, item):
|
||||
|
@ -33,13 +33,14 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from uds.REST.handlers import NotFound, RequestError, ResponseError
|
||||
from uds.REST.handlers import NotFound, RequestError, ResponseError, AccessDenied, NotSupportedError
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.db import IntegrityError
|
||||
|
||||
from uds.core.ui.UserInterface import gui as uiGui
|
||||
from uds.REST.handlers import Handler, HandlerError
|
||||
from uds.core.util import log
|
||||
from uds.core.util import permissions
|
||||
|
||||
import fnmatch
|
||||
import re
|
||||
@ -50,7 +51,7 @@ import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__updated__ = '2015-02-16'
|
||||
__updated__ = '2015-03-05'
|
||||
|
||||
|
||||
# a few constants
|
||||
@ -150,6 +151,12 @@ class BaseModelHandler(Handler):
|
||||
|
||||
return gui
|
||||
|
||||
def ensureAccess(self, obj, permission, root=False):
|
||||
perm = permissions.getEffectivePermission(self._user, obj, root)
|
||||
if perm < permission:
|
||||
self.accessDenied()
|
||||
return perm
|
||||
|
||||
def typeInfo(self, type_): # pylint: disable=no-self-use
|
||||
'''
|
||||
Returns info about the type
|
||||
@ -233,6 +240,12 @@ class BaseModelHandler(Handler):
|
||||
message = _('Item not found') if message is None else None
|
||||
raise NotFound('{} {}: {}'.format(message, self.__class__, self._args))
|
||||
|
||||
def accessDenied(self, message=None):
|
||||
raise AccessDenied(message or _('Access denied'))
|
||||
|
||||
def notSupported(self, message=None):
|
||||
raise NotSupportedError(message or _('Operation not supported'))
|
||||
|
||||
# Success methods
|
||||
def success(self):
|
||||
'''
|
||||
@ -284,6 +297,7 @@ class DetailHandler(BaseModelHandler): # pylint: disable=abstract-class-not-use
|
||||
self._params = params
|
||||
self._args = args
|
||||
self._kwargs = kwargs
|
||||
self._user = kwargs.get('user', None)
|
||||
|
||||
def __checkCustom(self, check, parent, arg=None):
|
||||
'''
|
||||
@ -312,6 +326,7 @@ class DetailHandler(BaseModelHandler): # pylint: disable=abstract-class-not-use
|
||||
nArgs = len(self._args)
|
||||
|
||||
parent = self._kwargs['parent']
|
||||
|
||||
if nArgs == 0:
|
||||
return self.getItems(parent, None)
|
||||
|
||||
@ -578,6 +593,7 @@ class ModelHandler(BaseModelHandler):
|
||||
|
||||
# log related
|
||||
def getLogs(self, item):
|
||||
self.ensureAccess(item, permissions.PERMISSION_READ)
|
||||
logger.debug('Default getLogs invoked')
|
||||
return log.getLogs(item)
|
||||
|
||||
@ -656,14 +672,26 @@ class ModelHandler(BaseModelHandler):
|
||||
return data
|
||||
|
||||
# Helper to process detail
|
||||
# Details can be managed (writen) by any user that has MANAGEMENT permission over parent
|
||||
def processDetail(self):
|
||||
logger.debug('Processing detail {0}'.format(self._path))
|
||||
logger.debug('Processing detail {} for user {}'.format(self._path, self._user))
|
||||
try:
|
||||
item = self.model.objects.filter(uuid=self._args[0])[0]
|
||||
# If we do not have access to parent to, at least, read...
|
||||
|
||||
if self._operation in ('put', 'post', 'delete'):
|
||||
requiredPermission = permissions.PERMISSION_MANAGEMENT
|
||||
else:
|
||||
requiredPermission = permissions.PERMISSION_READ
|
||||
|
||||
if permissions.checkPermissions(self._user, item, requiredPermission) is False:
|
||||
logger.debug('Permission for user {} does not comply with {}'.format(self._user, requiredPermission))
|
||||
self.accessDenied()
|
||||
|
||||
detailCls = self.detail[self._args[1]]
|
||||
args = list(self._args[2:])
|
||||
path = self._path + '/'.join(args[:2])
|
||||
detail = detailCls(self, path, self._params, *args, parent=item)
|
||||
detail = detailCls(self, path, self._params, *args, parent=item, user=self._user)
|
||||
method = getattr(detail, self._operation)
|
||||
except KeyError:
|
||||
self.invalidMethodException()
|
||||
@ -672,10 +700,17 @@ class ModelHandler(BaseModelHandler):
|
||||
|
||||
return method()
|
||||
|
||||
def getItems(self, *args, **kwargs):
|
||||
def getItems(self, overview=True, *args, **kwargs):
|
||||
for item in self.model.objects.filter(*args, **kwargs):
|
||||
try:
|
||||
yield self.item_as_dict_overview(item)
|
||||
if permissions.checkPermissions(self._user, item, permissions.PERMISSION_READ) is False:
|
||||
continue
|
||||
if overview:
|
||||
yield self.item_as_dict_overview(item)
|
||||
else:
|
||||
res = self.item_as_dict(item)
|
||||
self.fillIntanceFields(item, res)
|
||||
yield res
|
||||
except Exception: # maybe an exception is thrown to skip an item
|
||||
# logger.exception('Exception getting item from {0}'.format(self.model))
|
||||
pass
|
||||
@ -693,15 +728,7 @@ class ModelHandler(BaseModelHandler):
|
||||
nArgs = len(self._args)
|
||||
|
||||
if nArgs == 0:
|
||||
result = []
|
||||
for val in self.model.objects.all():
|
||||
try:
|
||||
res = self.item_as_dict(val)
|
||||
self.fillIntanceFields(val, res)
|
||||
result.append(res)
|
||||
except Exception: # maybe an exception is thrown to skip an item
|
||||
pass
|
||||
return result
|
||||
return list(self.getItems(overview=False))
|
||||
|
||||
# if has custom methods, look for if this request matches any of them
|
||||
for cm in self.custom_methods:
|
||||
@ -735,6 +762,9 @@ class ModelHandler(BaseModelHandler):
|
||||
# get item ID
|
||||
try:
|
||||
val = self.model.objects.get(uuid=self._args[0].lower())
|
||||
|
||||
self.ensureAccess(val, permissions.PERMISSION_READ)
|
||||
|
||||
res = self.item_as_dict(val)
|
||||
self.fillIntanceFields(val, res)
|
||||
return res
|
||||
@ -793,6 +823,9 @@ class ModelHandler(BaseModelHandler):
|
||||
|
||||
if len(self._args) > 1: # Detail?
|
||||
return self.processDetail()
|
||||
|
||||
self.ensureAccess(self.model(), permissions.PERMISSION_ALL, root=True) # Must have write permissions to create, modify, etc..
|
||||
|
||||
try:
|
||||
# Extract fields
|
||||
args = self.readFieldsFromParams(self.save_fields)
|
||||
@ -854,6 +887,9 @@ class ModelHandler(BaseModelHandler):
|
||||
|
||||
if len(self._args) != 1:
|
||||
raise RequestError('Delete need one and only one argument')
|
||||
|
||||
self.ensureAccess(self.model(), permissions.PERMISSION_ALL, root=True) # Must have write permissions to delete
|
||||
|
||||
try:
|
||||
item = self.model.objects.get(uuid=self._args[0].lower())
|
||||
self.checkDelete(item)
|
||||
|
@ -32,7 +32,7 @@
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
__updated__ = '2015-03-01'
|
||||
__updated__ = '2015-03-05'
|
||||
|
||||
from uds.models import Provider, Service, OSManager, Transport, Network, ServicePool, UserService, Authenticator, User, Group, StatsCounters, StatsEvents
|
||||
import logging
|
||||
|
@ -32,7 +32,7 @@
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
__updated__ = '2015-03-04'
|
||||
__updated__ = '2015-03-05'
|
||||
|
||||
from uds.models import Permissions
|
||||
from uds.core.util import ot
|
||||
@ -43,6 +43,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
PERMISSION_ALL = Permissions.PERMISSION_ALL
|
||||
PERMISSION_READ = Permissions.PERMISSION_READ
|
||||
PERMISSION_MANAGEMENT = Permissions.PERMISSION_MANAGEMENT
|
||||
PERMISSION_NONE = Permissions.PERMISSION_NONE
|
||||
|
||||
|
||||
@ -54,6 +55,19 @@ def getPermissions(obj):
|
||||
return list(Permissions.enumeratePermissions(object_type=ot.getObjectType(obj), object_id=obj.pk))
|
||||
|
||||
|
||||
def getEffectivePermission(user, obj, root=False):
|
||||
if user.is_admin is True:
|
||||
return PERMISSION_ALL
|
||||
|
||||
if user.staff_member is False:
|
||||
return PERMISSION_NONE
|
||||
|
||||
if root is False:
|
||||
return Permissions.getPermissions(user=user, groups=user.groups.all(), object_type=ot.getObjectType(obj), object_id=obj.pk)
|
||||
else:
|
||||
return Permissions.getPermissions(user=user, groups=user.groups.all(), object_type=ot.getObjectType(obj))
|
||||
|
||||
|
||||
def addUserPermission(user, obj, permission=PERMISSION_READ):
|
||||
# Some permissions added to some object types needs at least READ_PERMISSION on parent
|
||||
Permissions.addPermission(user=user, object_type=ot.getObjectType(obj), object_id=obj.pk, permission=permission)
|
||||
@ -63,15 +77,16 @@ def addGroupPermission(group, obj, permission=PERMISSION_READ):
|
||||
Permissions.addPermission(group=group, object_type=ot.getObjectType(obj), object_id=obj.pk, permission=permission)
|
||||
|
||||
|
||||
def checkPermissions(user, obj, permission=PERMISSION_ALL):
|
||||
if user.is_admin is True:
|
||||
return True
|
||||
|
||||
if user.is_staff is False:
|
||||
return False
|
||||
|
||||
return Permissions.getPermissions(user=user, groups=user.groups.all(), object_type=ot.getObjectType(obj), object_id=obj.pk) >= permission
|
||||
def checkPermissions(user, obj, permission=PERMISSION_ALL, root=False):
|
||||
return getEffectivePermission(user, obj, root) >= permission
|
||||
|
||||
|
||||
def getPermissionName(perm):
|
||||
return Permissions.permissionAsString(perm)
|
||||
|
||||
|
||||
def revokePermissionById(permId):
|
||||
try:
|
||||
return Permissions.objects.get(uuid=permId).delete()
|
||||
except Exception:
|
||||
return None
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
__updated__ = '2015-03-04'
|
||||
__updated__ = '2015-03-05'
|
||||
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
from django.utils.translation import ugettext as _
|
||||
@ -58,8 +58,9 @@ class Permissions(UUIDModel):
|
||||
# pylint: disable=model-missing-unicode
|
||||
# Allowed permissions
|
||||
PERMISSION_NONE = 0
|
||||
PERMISSION_READ = 16
|
||||
PERMISSION_ALL = 32
|
||||
PERMISSION_READ = 32
|
||||
PERMISSION_MANAGEMENT = 64
|
||||
PERMISSION_ALL = 96
|
||||
|
||||
created = models.DateTimeField(db_index=True)
|
||||
ends = models.DateTimeField(db_index=True, null=True, blank=True, default=None) # Future "permisions ends at this moment", not assigned right now
|
||||
@ -77,6 +78,7 @@ class Permissions(UUIDModel):
|
||||
return {
|
||||
Permissions.PERMISSION_NONE: _('None'),
|
||||
Permissions.PERMISSION_READ: _('Read'),
|
||||
Permissions.PERMISSION_MANAGEMENT: _('Management'),
|
||||
Permissions.PERMISSION_ALL: _('All')
|
||||
}.get(perm, _('None'))
|
||||
|
||||
|
@ -6,6 +6,13 @@ api = @api
|
||||
|
||||
api.debug = on
|
||||
|
||||
api.permissions = {
|
||||
NONE: 0
|
||||
READ: 32
|
||||
MANAGEMENT: 64
|
||||
ALL: 96
|
||||
}
|
||||
|
||||
api.doLog = (args...) ->
|
||||
if api.debug
|
||||
try
|
||||
@ -267,6 +274,12 @@ class BasicModelRest
|
||||
|
||||
return
|
||||
|
||||
permission: () ->
|
||||
if api.config.admin is true
|
||||
return api.permissions.ALL
|
||||
|
||||
return api.permissions.NONE
|
||||
|
||||
getPermissions: (id, success_fnc, fail_fnc) ->
|
||||
path = "permissions/" + @path + '/' + id
|
||||
@_requestPath path,
|
||||
@ -275,17 +288,17 @@ class BasicModelRest
|
||||
fail: fail_fnc
|
||||
|
||||
addPermission: (id, type, itemId, perm, success_fnc, fail_fnc) ->
|
||||
path = "permissions/" + @path + '/' + id + '/' + type + '/' + itemId
|
||||
path = "permissions/" + @path + '/' + id + '/' + type + '/add/' + itemId
|
||||
data =
|
||||
perm: perm
|
||||
api.putJson path, data,
|
||||
success: success_fnc
|
||||
fail: fail_fnc
|
||||
|
||||
revokePermissions: (id, type, itemIds, success_fnc, fail_fnc)->
|
||||
path = "permissions/revoke/" + @path + '/' + id + '/' + type
|
||||
revokePermissions: (itemIds, success_fnc, fail_fnc)->
|
||||
path = "permissions/revoke"
|
||||
data =
|
||||
ids: itemIds
|
||||
items: itemIds
|
||||
api.putJson path, data,
|
||||
success: success_fnc
|
||||
fail: fail_fnc
|
||||
@ -337,13 +350,15 @@ class DetailModelRestApi extends BasicModelRest
|
||||
model
|
||||
].join("/")
|
||||
@moptions = options
|
||||
|
||||
permission: () ->
|
||||
if @moptions.permission? then @moptions.permission else api.permissions.ALL
|
||||
|
||||
create: (data, success_fnc, fail_fnc) ->
|
||||
@put data,
|
||||
success: success_fnc
|
||||
fail: fail_fnc
|
||||
|
||||
|
||||
save: (data, success_fnc, fail_fnc) ->
|
||||
@put data,
|
||||
id: data.id
|
||||
|
@ -125,6 +125,7 @@ gui.authenticators.link = (event) ->
|
||||
"edit"
|
||||
"delete"
|
||||
"xls"
|
||||
"permissions"
|
||||
]
|
||||
onRowDeselect: ->
|
||||
clearDetails()
|
||||
@ -141,8 +142,8 @@ gui.authenticators.link = (event) ->
|
||||
id = selected[0].id
|
||||
type = gui.authenticators.types[selected[0].type]
|
||||
gui.doLog "Type", type
|
||||
user = new GuiElement(api.authenticators.detail(id, "users"), "users")
|
||||
group = new GuiElement(api.authenticators.detail(id, "groups"), "groups")
|
||||
user = new GuiElement(api.authenticators.detail(id, "users", { permission: selected[0].permission }), "users")
|
||||
group = new GuiElement(api.authenticators.detail(id, "groups", { permission: selected[0].permission }), "groups")
|
||||
grpTable = group.table(
|
||||
container: "groups-placeholder"
|
||||
rowSelect: "single"
|
||||
|
@ -19,6 +19,7 @@ gui.connectivity.link = (event) ->
|
||||
"edit"
|
||||
"delete"
|
||||
"xls"
|
||||
"permissions"
|
||||
]
|
||||
onNew: gui.methods.typedNew(gui.connectivity.transports, gettext("New transport"), gettext("Transport creation error"))
|
||||
onEdit: gui.methods.typedEdit(gui.connectivity.transports, gettext("Edit transport"), gettext("Transport saving error"))
|
||||
@ -32,6 +33,7 @@ gui.connectivity.link = (event) ->
|
||||
"edit"
|
||||
"delete"
|
||||
"xls"
|
||||
"permissions"
|
||||
]
|
||||
onNew: gui.methods.typedNew(gui.connectivity.networks, gettext("New network"), gettext("Network creation error"))
|
||||
onEdit: gui.methods.typedEdit(gui.connectivity.networks, gettext("Edit network"), gettext("Network saving error"))
|
||||
|
@ -17,6 +17,7 @@ gui.osmanagers.link = (event) ->
|
||||
"edit"
|
||||
"delete"
|
||||
"xls"
|
||||
"permissions"
|
||||
]
|
||||
onNew: gui.methods.typedNew(gui.osmanagers, gettext("New OSManager"), gettext("OSManager creation error"))
|
||||
onEdit: gui.methods.typedEdit(gui.osmanagers, gettext("Edit OSManager"), gettext("OSManager saving error"))
|
||||
|
@ -54,6 +54,8 @@ gui.providers.link = (event) ->
|
||||
return
|
||||
|
||||
tableId = gui.providers.table(
|
||||
getPermission: (selected) ->
|
||||
gui.doLog "Selected", selected
|
||||
container: "providers-placeholder"
|
||||
rowSelect: "single"
|
||||
onCheck: (check, items) -> # Check if item can be deleted
|
||||
@ -84,9 +86,9 @@ gui.providers.link = (event) ->
|
||||
clearDetails()
|
||||
$("#detail-placeholder").removeClass "hidden"
|
||||
id = selected[0].id
|
||||
|
||||
|
||||
# Giving the name compossed with type, will ensure that only styles will be reattached once
|
||||
services = new GuiElement(api.providers.detail(id, "services"), "services-" + selected[0].type)
|
||||
services = new GuiElement(api.providers.detail(id, "services", { permission: selected[0].permission }), "services-" + selected[0].type)
|
||||
tmpLogTable = undefined
|
||||
servicesTable = services.table(
|
||||
container: "services-placeholder"
|
||||
@ -120,7 +122,6 @@ gui.providers.link = (event) ->
|
||||
"edit"
|
||||
"delete"
|
||||
"xls"
|
||||
"permissions"
|
||||
]
|
||||
onEdit: gui.methods.typedEdit(services, gettext("Edit service"), gettext("Service creation error"))
|
||||
onNew: gui.methods.typedNew(services, gettext("New service"), gettext("Service saving error"))
|
||||
@ -141,6 +142,7 @@ gui.providers.link = (event) ->
|
||||
"new"
|
||||
"edit"
|
||||
{
|
||||
permission: api.permissions.MANAGEMENT
|
||||
text: gettext("Maintenance")
|
||||
css: "disabled"
|
||||
click: (val, value, btn, tbl, refreshFnc) ->
|
||||
|
@ -79,243 +79,114 @@ gui.servicesPools.link = (event) ->
|
||||
return
|
||||
return
|
||||
|
||||
# Fills up the list of available services
|
||||
api.providers.allServices (services) ->
|
||||
availableServices = {}
|
||||
$.each services, (undefined_, service) ->
|
||||
availableServices[service.id] = service
|
||||
api.templates.get "services_pool", (tmpl) ->
|
||||
gui.appendToWorkspace api.templates.evaluate(tmpl,
|
||||
deployed_services: "deployed-services-placeholder"
|
||||
assigned_services: "assigned-services-placeholder"
|
||||
cache: "cache-placeholder"
|
||||
groups: "groups-placeholder"
|
||||
transports: "transports-placeholder"
|
||||
publications: "publications-placeholder"
|
||||
logs: "logs-placeholder"
|
||||
)
|
||||
gui.setLinksEvents()
|
||||
|
||||
# Append tabs click events
|
||||
$(".bottom_tabs").on "click", (event) ->
|
||||
gui.doLog event.target
|
||||
setTimeout (->
|
||||
$($(event.target).attr("href") + " span.fa-refresh").click()
|
||||
return
|
||||
), 10
|
||||
return
|
||||
|
||||
gui.doLog "Available services", availableServices
|
||||
api.templates.get "services_pool", (tmpl) ->
|
||||
gui.appendToWorkspace api.templates.evaluate(tmpl,
|
||||
deployed_services: "deployed-services-placeholder"
|
||||
assigned_services: "assigned-services-placeholder"
|
||||
cache: "cache-placeholder"
|
||||
groups: "groups-placeholder"
|
||||
transports: "transports-placeholder"
|
||||
publications: "publications-placeholder"
|
||||
logs: "logs-placeholder"
|
||||
)
|
||||
gui.setLinksEvents()
|
||||
|
||||
# Append tabs click events
|
||||
$(".bottom_tabs").on "click", (event) ->
|
||||
gui.doLog event.target
|
||||
setTimeout (->
|
||||
$($(event.target).attr("href") + " span.fa-refresh").click()
|
||||
return
|
||||
), 10
|
||||
|
||||
#
|
||||
# * Services pools part
|
||||
#
|
||||
servicesPoolsTable = gui.servicesPools.table(
|
||||
container: "deployed-services-placeholder"
|
||||
rowSelect: "single"
|
||||
buttons: [
|
||||
"new"
|
||||
"edit"
|
||||
"delete"
|
||||
"xls"
|
||||
"permissions"
|
||||
]
|
||||
onRowDeselect: ->
|
||||
clearDetails()
|
||||
return
|
||||
|
||||
|
||||
#
|
||||
# * Services pools part
|
||||
#
|
||||
servicesPoolsTable = gui.servicesPools.table(
|
||||
container: "deployed-services-placeholder"
|
||||
rowSelect: "single"
|
||||
buttons: [
|
||||
"new"
|
||||
"edit"
|
||||
"delete"
|
||||
"xls"
|
||||
]
|
||||
onRowDeselect: ->
|
||||
clearDetails()
|
||||
onRowSelect: (selected) ->
|
||||
servPool = selected[0]
|
||||
gui.doLog "Selected services pool", servPool
|
||||
clearDetails()
|
||||
service = null
|
||||
try
|
||||
info = servPool.info
|
||||
catch e
|
||||
gui.doLog "Exception on rowSelect", e
|
||||
gui.notify "Service pool " + gettext("error"), "danger"
|
||||
return
|
||||
|
||||
onRowSelect: (selected) ->
|
||||
servPool = selected[0]
|
||||
gui.doLog "Selected services pool", servPool
|
||||
clearDetails()
|
||||
service = null
|
||||
try
|
||||
service = availableServices[servPool.service_id]
|
||||
catch e
|
||||
gui.doLog "Exception on rowSelect", e
|
||||
gui.notify "Service pool " + gettext("error"), "danger"
|
||||
return
|
||||
if service?
|
||||
$("#detail-placeholder").removeClass "hidden"
|
||||
else
|
||||
$("#detail-placeholder").addClass "hidden"
|
||||
return
|
||||
$("#detail-placeholder").removeClass "hidden"
|
||||
|
||||
#
|
||||
# * Cache Part
|
||||
#
|
||||
cachedItems = null
|
||||
|
||||
# If service does not supports cache, do not show it
|
||||
# Shows/hides cache
|
||||
if info.uses_cache or info.uses_cache_l2
|
||||
$("#cache-placeholder_tab").removeClass "hidden"
|
||||
cachedItems = new GuiElement(api.servicesPools.detail(servPool.id, "cache", { permission: servPool.permission }), "cache")
|
||||
|
||||
#
|
||||
# * Cache Part
|
||||
#
|
||||
cachedItems = null
|
||||
|
||||
# If service does not supports cache, do not show it
|
||||
# Shows/hides cache
|
||||
if service.info.uses_cache or service.info.uses_cache_l2
|
||||
$("#cache-placeholder_tab").removeClass "hidden"
|
||||
cachedItems = new GuiElement(api.servicesPools.detail(servPool.id, "cache"), "cache")
|
||||
|
||||
# Cached items table
|
||||
prevCacheLogTbl = null
|
||||
cachedItemsTable = cachedItems.table(
|
||||
container: "cache-placeholder_tbl"
|
||||
buttons: [
|
||||
"delete"
|
||||
"xls"
|
||||
]
|
||||
rowSelect: "single"
|
||||
onData: (data) ->
|
||||
fillState data
|
||||
return
|
||||
|
||||
onRowSelect: (selected) ->
|
||||
gui.do
|
||||
cached = selected[0]
|
||||
if prevCacheLogTbl
|
||||
$tbl = $(prevCacheLogTbl).dataTable()
|
||||
$tbl.fnClearTable()
|
||||
$tbl.fnDestroy()
|
||||
prevCacheLogTbl = cachedItems.logTable(cached.id,
|
||||
container: "cache-placeholder_log"
|
||||
)
|
||||
return
|
||||
|
||||
onDelete: gui.methods.del(cachedItems, gettext("Remove Cache element"), gettext("Deletion error"))
|
||||
)
|
||||
prevTables.push cachedItemsTable
|
||||
else
|
||||
$("#cache-placeholder_tab").addClass "hidden"
|
||||
|
||||
#
|
||||
# * Groups part
|
||||
#
|
||||
groups = null
|
||||
|
||||
# Shows/hides groups
|
||||
if service.info.must_assign_manually is false
|
||||
$("#groups-placeholder_tab").removeClass "hidden"
|
||||
groups = new GuiElement(api.servicesPools.detail(servPool.id, "groups"), "groups")
|
||||
|
||||
# Groups items table
|
||||
groupsTable = groups.table(
|
||||
container: "groups-placeholder"
|
||||
rowSelect: "single"
|
||||
buttons: [
|
||||
"new"
|
||||
"delete"
|
||||
"xls"
|
||||
]
|
||||
onNew: (value, table, refreshFnc) ->
|
||||
api.templates.get "pool_add_group", (tmpl) ->
|
||||
api.authenticators.overview (data) ->
|
||||
# Sorts groups, expression means that "if a > b returns 1, if b > a returns -1, else returns 0"
|
||||
|
||||
modalId = gui.launchModal(gettext("Add group"), api.templates.evaluate(tmpl,
|
||||
auths: data
|
||||
))
|
||||
$(modalId + " #id_auth_select").on "change", (event) ->
|
||||
auth = $(modalId + " #id_auth_select").val()
|
||||
api.authenticators.detail(auth, "groups").overview (data) ->
|
||||
$select = $(modalId + " #id_group_select")
|
||||
$select.empty()
|
||||
# Sorts groups, expression means that "if a > b returns 1, if b > a returns -1, else returns 0"
|
||||
$.each data, (undefined_, value) ->
|
||||
$select.append "<option value=\"" + value.id + "\">" + value.name + "</option>"
|
||||
return
|
||||
|
||||
|
||||
# Refresh selectpicker if item is such
|
||||
$select.selectpicker "refresh" if $select.hasClass("selectpicker")
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
$(modalId + " .button-accept").on "click", (event) ->
|
||||
auth = $(modalId + " #id_auth_select").val()
|
||||
group = $(modalId + " #id_group_select").val()
|
||||
if auth is -1 or group is -1
|
||||
gui.notify gettext("You must provide authenticator and group"), "danger"
|
||||
else # Save & close modal
|
||||
groups.rest.create
|
||||
id: group
|
||||
, (data) ->
|
||||
$(modalId).modal "hide"
|
||||
refreshFnc()
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
|
||||
# Makes form "beautyfull" :-)
|
||||
gui.tools.applyCustoms modalId
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
onDelete: gui.methods.del(groups, gettext("Remove group"), gettext("Group removal error"))
|
||||
onData: (data) ->
|
||||
$.each data, (undefined_, value) ->
|
||||
value.group_name = "<b>" + value.auth_name + "</b>\\" + value.name
|
||||
return
|
||||
|
||||
return
|
||||
)
|
||||
prevTables.push groupsTable
|
||||
else
|
||||
$("#groups-placeholder_tab").addClass "hidden"
|
||||
|
||||
#
|
||||
# * Assigned services part
|
||||
#
|
||||
prevAssignedLogTbl = null
|
||||
assignedServices = new GuiElement(api.servicesPools.detail(servPool.id, "services"), "services")
|
||||
assignedServicesTable = assignedServices.table(
|
||||
container: "assigned-services-placeholder_tbl"
|
||||
# Cached items table
|
||||
prevCacheLogTbl = null
|
||||
cachedItemsTable = cachedItems.table(
|
||||
container: "cache-placeholder_tbl"
|
||||
buttons: [
|
||||
"delete"
|
||||
"xls"
|
||||
]
|
||||
rowSelect: "single"
|
||||
buttons: (if service.info.must_assign_manually then [
|
||||
"new"
|
||||
"delete"
|
||||
"xls"
|
||||
] else [
|
||||
"delete"
|
||||
"xls"
|
||||
])
|
||||
|
||||
onData: (data) ->
|
||||
fillState data
|
||||
$.each data, (index, value) ->
|
||||
if value.in_use is true
|
||||
value.in_use = gettext('Yes')
|
||||
else
|
||||
value.in_use = gettext('No')
|
||||
|
||||
return
|
||||
|
||||
onRowSelect: (selected) ->
|
||||
service = selected[0]
|
||||
if prevAssignedLogTbl
|
||||
$tbl = $(prevAssignedLogTbl).dataTable()
|
||||
gui.do
|
||||
cached = selected[0]
|
||||
if prevCacheLogTbl
|
||||
$tbl = $(prevCacheLogTbl).dataTable()
|
||||
$tbl.fnClearTable()
|
||||
$tbl.fnDestroy()
|
||||
prevAssignedLogTbl = assignedServices.logTable(service.id,
|
||||
container: "assigned-services-placeholder_log"
|
||||
prevCacheLogTbl = cachedItems.logTable(cached.id,
|
||||
container: "cache-placeholder_log"
|
||||
)
|
||||
return
|
||||
|
||||
onDelete: gui.methods.del(assignedServices, gettext("Remove Assigned service"), gettext("Deletion error"))
|
||||
onDelete: gui.methods.del(cachedItems, gettext("Remove Cache element"), gettext("Deletion error"))
|
||||
)
|
||||
prevTables.push cachedItemsTable
|
||||
else
|
||||
$("#cache-placeholder_tab").addClass "hidden"
|
||||
|
||||
#
|
||||
# * Groups part
|
||||
#
|
||||
groups = null
|
||||
|
||||
# Shows/hides groups
|
||||
if info.must_assign_manually is false
|
||||
$("#groups-placeholder_tab").removeClass "hidden"
|
||||
groups = new GuiElement(api.servicesPools.detail(servPool.id, "groups", { permission: servPool.permission }), "groups")
|
||||
|
||||
# Log of assigned services (right under assigned services)
|
||||
prevTables.push assignedServicesTable
|
||||
|
||||
#
|
||||
# * Transports part
|
||||
#
|
||||
transports = new GuiElement(api.servicesPools.detail(servPool.id, "transports"), "transports")
|
||||
|
||||
# Transports items table
|
||||
transportsTable = transports.table(
|
||||
container: "transports-placeholder"
|
||||
# Groups items table
|
||||
groupsTable = groups.table(
|
||||
container: "groups-placeholder"
|
||||
rowSelect: "single"
|
||||
buttons: [
|
||||
"new"
|
||||
@ -323,18 +194,38 @@ gui.servicesPools.link = (event) ->
|
||||
"xls"
|
||||
]
|
||||
onNew: (value, table, refreshFnc) ->
|
||||
api.templates.get "pool_add_transport", (tmpl) ->
|
||||
api.transports.overview (data) ->
|
||||
modalId = gui.launchModal(gettext("Add transport"), api.templates.evaluate(tmpl,
|
||||
transports: data
|
||||
api.templates.get "pool_add_group", (tmpl) ->
|
||||
api.authenticators.overview (data) ->
|
||||
# Sorts groups, expression means that "if a > b returns 1, if b > a returns -1, else returns 0"
|
||||
|
||||
modalId = gui.launchModal(gettext("Add group"), api.templates.evaluate(tmpl,
|
||||
auths: data
|
||||
))
|
||||
$(modalId + " #id_auth_select").on "change", (event) ->
|
||||
auth = $(modalId + " #id_auth_select").val()
|
||||
api.authenticators.detail(auth, "groups").overview (data) ->
|
||||
$select = $(modalId + " #id_group_select")
|
||||
$select.empty()
|
||||
# Sorts groups, expression means that "if a > b returns 1, if b > a returns -1, else returns 0"
|
||||
$.each data, (undefined_, value) ->
|
||||
$select.append "<option value=\"" + value.id + "\">" + value.name + "</option>"
|
||||
return
|
||||
|
||||
|
||||
# Refresh selectpicker if item is such
|
||||
$select.selectpicker "refresh" if $select.hasClass("selectpicker")
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
$(modalId + " .button-accept").on "click", (event) ->
|
||||
transport = $(modalId + " #id_transport_select").val()
|
||||
if transport is -1
|
||||
gui.notify gettext("You must provide a transport"), "danger"
|
||||
auth = $(modalId + " #id_auth_select").val()
|
||||
group = $(modalId + " #id_group_select").val()
|
||||
if auth is -1 or group is -1
|
||||
gui.notify gettext("You must provide authenticator and group"), "danger"
|
||||
else # Save & close modal
|
||||
transports.rest.create
|
||||
id: transport
|
||||
groups.rest.create
|
||||
id: group
|
||||
, (data) ->
|
||||
$(modalId).modal "hide"
|
||||
refreshFnc()
|
||||
@ -351,142 +242,232 @@ gui.servicesPools.link = (event) ->
|
||||
|
||||
return
|
||||
|
||||
onDelete: gui.methods.del(transports, gettext("Remove transport"), gettext("Transport removal error"))
|
||||
onDelete: gui.methods.del(groups, gettext("Remove group"), gettext("Group removal error"))
|
||||
onData: (data) ->
|
||||
$.each data, (undefined_, value) ->
|
||||
style = "display:inline-block; background: url(data:image/png;base64," + value.type.icon + "); ; background-size: 16px 16px; background-repeat: no-repeat; width: 16px; height: 16px; vertical-align: middle;"
|
||||
value.trans_type = value.type.name
|
||||
value.name = "<span style=\"" + style + "\"></span> " + value.name
|
||||
value.group_name = "<b>" + value.auth_name + "</b>\\" + value.name
|
||||
return
|
||||
|
||||
return
|
||||
)
|
||||
prevTables.push transportsTable
|
||||
|
||||
#
|
||||
# * Publications part
|
||||
#
|
||||
publications = null
|
||||
if service.info.needs_publication
|
||||
$("#publications-placeholder_tab").removeClass "hidden"
|
||||
pubApi = api.servicesPools.detail(servPool.id, "publications")
|
||||
publications = new GuiElement(pubApi, "publications")
|
||||
|
||||
# Publications table
|
||||
publicationsTable = publications.table(
|
||||
container: "publications-placeholder"
|
||||
rowSelect: "single"
|
||||
buttons: [
|
||||
"new"
|
||||
{
|
||||
text: gettext("Cancel")
|
||||
css: "disabled"
|
||||
click: (val, value, btn, tbl, refreshFnc) ->
|
||||
gui.promptModal gettext("Publish"), gettext("Cancel publication"),
|
||||
onYes: ->
|
||||
pubApi.invoke val.id + "/cancel", ->
|
||||
refreshFnc()
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
select: (val, value, btn, tbl, refreshFnc) ->
|
||||
unless val
|
||||
$(btn).removeClass("btn3d-warning").addClass "disabled"
|
||||
return
|
||||
|
||||
if val.state == 'K'
|
||||
$(btn).empty().append(gettext("Force Cancel"))
|
||||
else
|
||||
$(btn).empty().append(gettext("Cancel"))
|
||||
|
||||
# Waiting for publication, Preparing or running
|
||||
gui.doLog "State: ", val.state
|
||||
$(btn).removeClass("disabled").addClass "btn3d-warning" if [
|
||||
"P"
|
||||
"W"
|
||||
"L"
|
||||
"K"
|
||||
].indexOf(val.state) != -1
|
||||
|
||||
return
|
||||
}
|
||||
"xls"
|
||||
]
|
||||
onNew: (action, tbl, refreshFnc) ->
|
||||
gui.promptModal gettext("Publish"), gettext("Launch new publication?"),
|
||||
onYes: ->
|
||||
pubApi.invoke "publish", (->
|
||||
refreshFnc()
|
||||
return
|
||||
), gui.failRequestModalFnc(gettext("Failed creating publication"))
|
||||
return
|
||||
|
||||
return
|
||||
)
|
||||
prevTables.push publicationsTable
|
||||
else
|
||||
$("#publications-placeholder_tab").addClass "hidden"
|
||||
|
||||
#
|
||||
# * Log table
|
||||
#
|
||||
logTable = gui.servicesPools.logTable(servPool.id,
|
||||
container: "logs-placeholder"
|
||||
)
|
||||
prevTables.push logTable
|
||||
return
|
||||
|
||||
prevTables.push groupsTable
|
||||
else
|
||||
$("#groups-placeholder_tab").addClass "hidden"
|
||||
|
||||
# Pre-process data received to add "icon" to deployed service
|
||||
onData: (data) ->
|
||||
gui.doLog "onData", data
|
||||
$.each data, (index, value) ->
|
||||
gui.doLog value.thumb
|
||||
try
|
||||
service = availableServices[value.service_id]
|
||||
if not service?
|
||||
value.parent = gettext("undefined")
|
||||
return
|
||||
style = "display:inline-block; background: url(data:image/png;base64," + value.thumb + "); background-size: 16px 16px; background-repeat: no-repeat; width: 16px; height: 16px; vertical-align: middle;"
|
||||
gui.doLog style
|
||||
if value.restrained
|
||||
value.name = "<span class=\"fa fa-exclamation text-danger\"></span> " + value.name
|
||||
value.state = gettext("Restrained")
|
||||
value.name = "<span style=\"" + style + "\"></span> " + value.name
|
||||
value.parent = service.name
|
||||
catch e
|
||||
value.name = "<span class=\"fa fa-asterisk text-alert\"></span> " + value.name
|
||||
value.parent = gettext("unknown (needs reload)")
|
||||
#
|
||||
# * Assigned services part
|
||||
#
|
||||
prevAssignedLogTbl = null
|
||||
assignedServices = new GuiElement(api.servicesPools.detail(servPool.id, "services", { permission: servPool.permission }), "services")
|
||||
assignedServicesTable = assignedServices.table(
|
||||
container: "assigned-services-placeholder_tbl"
|
||||
rowSelect: "single"
|
||||
buttons: (if info.must_assign_manually then [
|
||||
"new"
|
||||
"delete"
|
||||
"xls"
|
||||
] else [
|
||||
"delete"
|
||||
"xls"
|
||||
])
|
||||
|
||||
onData: (data) ->
|
||||
fillState data
|
||||
$.each data, (index, value) ->
|
||||
if value.in_use is true
|
||||
value.in_use = gettext('Yes')
|
||||
else
|
||||
value.in_use = gettext('No')
|
||||
|
||||
return
|
||||
|
||||
onRowSelect: (selected) ->
|
||||
svr = selected[0]
|
||||
if prevAssignedLogTbl
|
||||
$tbl = $(prevAssignedLogTbl).dataTable()
|
||||
$tbl.fnClearTable()
|
||||
$tbl.fnDestroy()
|
||||
prevAssignedLogTbl = assignedServices.logTable(svr.id,
|
||||
container: "assigned-services-placeholder_log"
|
||||
)
|
||||
return
|
||||
|
||||
onDelete: gui.methods.del(assignedServices, gettext("Remove Assigned service"), gettext("Deletion error"))
|
||||
)
|
||||
|
||||
# Log of assigned services (right under assigned services)
|
||||
prevTables.push assignedServicesTable
|
||||
|
||||
#
|
||||
# * Transports part
|
||||
#
|
||||
transports = new GuiElement(api.servicesPools.detail(servPool.id, "transports", { permission: servPool.permission }), "transports")
|
||||
|
||||
# Transports items table
|
||||
transportsTable = transports.table(
|
||||
container: "transports-placeholder"
|
||||
rowSelect: "single"
|
||||
buttons: [
|
||||
"new"
|
||||
"delete"
|
||||
"xls"
|
||||
]
|
||||
onNew: (value, table, refreshFnc) ->
|
||||
api.templates.get "pool_add_transport", (tmpl) ->
|
||||
api.transports.overview (data) ->
|
||||
modalId = gui.launchModal(gettext("Add transport"), api.templates.evaluate(tmpl,
|
||||
transports: data
|
||||
))
|
||||
$(modalId + " .button-accept").on "click", (event) ->
|
||||
transport = $(modalId + " #id_transport_select").val()
|
||||
if transport is -1
|
||||
gui.notify gettext("You must provide a transport"), "danger"
|
||||
else # Save & close modal
|
||||
transports.rest.create
|
||||
id: transport
|
||||
, (data) ->
|
||||
$(modalId).modal "hide"
|
||||
refreshFnc()
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
|
||||
# Makes form "beautyfull" :-)
|
||||
gui.tools.applyCustoms modalId
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
onDelete: gui.methods.del(transports, gettext("Remove transport"), gettext("Transport removal error"))
|
||||
onData: (data) ->
|
||||
$.each data, (undefined_, value) ->
|
||||
style = "display:inline-block; background: url(data:image/png;base64," + value.type.icon + "); ; background-size: 16px 16px; background-repeat: no-repeat; width: 16px; height: 16px; vertical-align: middle;"
|
||||
value.trans_type = value.type.name
|
||||
value.name = "<span style=\"" + style + "\"></span> " + value.name
|
||||
return
|
||||
|
||||
return
|
||||
)
|
||||
prevTables.push transportsTable
|
||||
|
||||
#
|
||||
# * Publications part
|
||||
#
|
||||
publications = null
|
||||
if info.needs_publication
|
||||
$("#publications-placeholder_tab").removeClass "hidden"
|
||||
pubApi = api.servicesPools.detail(servPool.id, "publications")
|
||||
publications = new GuiElement(pubApi, "publications", { permission: servPool.permission })
|
||||
|
||||
# Publications table
|
||||
publicationsTable = publications.table(
|
||||
container: "publications-placeholder"
|
||||
rowSelect: "single"
|
||||
buttons: [
|
||||
"new"
|
||||
{
|
||||
text: gettext("Cancel")
|
||||
css: "disabled"
|
||||
click: (val, value, btn, tbl, refreshFnc) ->
|
||||
gui.promptModal gettext("Publish"), gettext("Cancel publication"),
|
||||
onYes: ->
|
||||
pubApi.invoke val.id + "/cancel", ->
|
||||
refreshFnc()
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
select: (val, value, btn, tbl, refreshFnc) ->
|
||||
unless val
|
||||
$(btn).removeClass("btn3d-warning").addClass "disabled"
|
||||
return
|
||||
|
||||
if val.state == 'K'
|
||||
$(btn).empty().append(gettext("Force Cancel"))
|
||||
else
|
||||
$(btn).empty().append(gettext("Cancel"))
|
||||
|
||||
# Waiting for publication, Preparing or running
|
||||
gui.doLog "State: ", val.state
|
||||
$(btn).removeClass("disabled").addClass "btn3d-warning" if [
|
||||
"P"
|
||||
"W"
|
||||
"L"
|
||||
"K"
|
||||
].indexOf(val.state) != -1
|
||||
|
||||
return
|
||||
}
|
||||
"xls"
|
||||
]
|
||||
onNew: (action, tbl, refreshFnc) ->
|
||||
gui.promptModal gettext("Publish"), gettext("Launch new publication?"),
|
||||
onYes: ->
|
||||
pubApi.invoke "publish", (->
|
||||
refreshFnc()
|
||||
return
|
||||
), gui.failRequestModalFnc(gettext("Failed creating publication"))
|
||||
return
|
||||
|
||||
return
|
||||
)
|
||||
prevTables.push publicationsTable
|
||||
else
|
||||
$("#publications-placeholder_tab").addClass "hidden"
|
||||
|
||||
#
|
||||
# * Log table
|
||||
#
|
||||
logTable = gui.servicesPools.logTable(servPool.id,
|
||||
container: "logs-placeholder"
|
||||
)
|
||||
prevTables.push logTable
|
||||
return
|
||||
|
||||
|
||||
# Pre-process data received to add "icon" to deployed service
|
||||
onData: (data) ->
|
||||
gui.doLog "onData", data
|
||||
$.each data, (index, value) ->
|
||||
gui.doLog value.thumb
|
||||
try
|
||||
style = "display:inline-block; background: url(data:image/png;base64," + value.thumb + "); background-size: 16px 16px; background-repeat: no-repeat; width: 16px; height: 16px; vertical-align: middle;"
|
||||
gui.doLog style
|
||||
if value.restrained
|
||||
value.name = "<span class=\"fa fa-exclamation text-danger\"></span> " + value.name
|
||||
value.state = gettext("Restrained")
|
||||
value.name = "<span style=\"" + style + "\"></span> " + value.name
|
||||
catch e
|
||||
value.name = "<span class=\"fa fa-asterisk text-alert\"></span> " + value.name
|
||||
return
|
||||
|
||||
onNew: gui.methods.typedNew(gui.servicesPools, gettext("New service pool"), "Service pool " + gettext("creation error"),
|
||||
guiProcessor: (guiDef) -> # Create has "save on publish" field
|
||||
gui.doLog guiDef
|
||||
newDef = [].concat(guiDef).concat([
|
||||
name: "publish_on_save"
|
||||
value: true
|
||||
gui:
|
||||
label: gettext("Publish on creation")
|
||||
tooltip: gettext("If selected, will initiate the publication inmediatly after creation")
|
||||
type: "checkbox"
|
||||
order: 150
|
||||
defvalue: true
|
||||
])
|
||||
gui.doLog newDef
|
||||
newDef
|
||||
return
|
||||
|
||||
preprocessor: preFnc
|
||||
)
|
||||
onEdit: gui.methods.typedEdit(gui.servicesPools, gettext("Edit") + " service pool", "Service pool " + gettext("saving error"))
|
||||
onDelete: gui.methods.del(gui.servicesPools, gettext("Delete") + " service pool", "Service pool " + gettext("deletion error"))
|
||||
onNew: gui.methods.typedNew(gui.servicesPools, gettext("New service pool"), "Service pool " + gettext("creation error"),
|
||||
guiProcessor: (guiDef) -> # Create has "save on publish" field
|
||||
gui.doLog guiDef
|
||||
newDef = [].concat(guiDef).concat([
|
||||
name: "publish_on_save"
|
||||
value: true
|
||||
gui:
|
||||
label: gettext("Publish on creation")
|
||||
tooltip: gettext("If selected, will initiate the publication inmediatly after creation")
|
||||
type: "checkbox"
|
||||
order: 150
|
||||
defvalue: true
|
||||
])
|
||||
gui.doLog newDef
|
||||
newDef
|
||||
|
||||
preprocessor: preFnc
|
||||
)
|
||||
return
|
||||
|
||||
onEdit: gui.methods.typedEdit(gui.servicesPools, gettext("Edit") + " service pool", "Service pool " + gettext("saving error"))
|
||||
onDelete: gui.methods.del(gui.servicesPools, gettext("Delete") + " service pool", "Service pool " + gettext("deletion error"))
|
||||
)
|
||||
return
|
||||
|
||||
return
|
@ -276,52 +276,56 @@
|
||||
$.each tblParams.buttons, (index, value) -> # Iterate through button definition
|
||||
btn = null
|
||||
switch value
|
||||
|
||||
when "new"
|
||||
if Object.keys(self.types).length isnt 0
|
||||
menuId = gui.genRamdonId("dd-")
|
||||
ordered = []
|
||||
$.each self.types, (k, v) ->
|
||||
ordered.push
|
||||
type: k
|
||||
css: v.css
|
||||
name: v.name
|
||||
description: v.description
|
||||
if self.rest.permission() >= api.permissions.MANAGEMENT
|
||||
if Object.keys(self.types).length isnt 0
|
||||
menuId = gui.genRamdonId("dd-")
|
||||
ordered = []
|
||||
$.each self.types, (k, v) ->
|
||||
ordered.push
|
||||
type: k
|
||||
css: v.css
|
||||
name: v.name
|
||||
description: v.description
|
||||
|
||||
return
|
||||
return
|
||||
|
||||
ordered = ordered.sort((a, b) ->
|
||||
a.name.localeCompare b.name
|
||||
)
|
||||
btn =
|
||||
sExtends: "div"
|
||||
sButtonText: api.templates.evaluate("tmpl_comp_dropdown",
|
||||
label: gui.config.dataTableButtons["new"].text
|
||||
css: gui.config.dataTableButtons["new"].css
|
||||
id: menuId
|
||||
tableId: tableId
|
||||
columns: columns
|
||||
menu: ordered
|
||||
ordered = ordered.sort((a, b) ->
|
||||
a.name.localeCompare b.name
|
||||
)
|
||||
else
|
||||
btn =
|
||||
sExtends: "div"
|
||||
sButtonText: api.templates.evaluate("tmpl_comp_dropdown",
|
||||
label: gui.config.dataTableButtons["new"].text
|
||||
css: gui.config.dataTableButtons["new"].css
|
||||
id: menuId
|
||||
tableId: tableId
|
||||
columns: columns
|
||||
menu: ordered
|
||||
)
|
||||
else
|
||||
btn =
|
||||
sExtends: "text"
|
||||
sButtonText: gui.config.dataTableButtons["new"].text
|
||||
sButtonClass: gui.config.dataTableButtons["new"].css
|
||||
fnClick: clickHandlerFor(tblParams.onNew, "new", true)
|
||||
when "edit"
|
||||
if self.rest.permission() >= api.permissions.MANAGEMENT
|
||||
btn =
|
||||
sExtends: "text"
|
||||
sButtonText: gui.config.dataTableButtons["new"].text
|
||||
sButtonClass: gui.config.dataTableButtons["new"].css
|
||||
fnClick: clickHandlerFor(tblParams.onNew, "new", true)
|
||||
when "edit"
|
||||
btn =
|
||||
sExtends: "text"
|
||||
sButtonText: gui.config.dataTableButtons.edit.text
|
||||
fnSelect: editSelected
|
||||
fnClick: clickHandlerFor(tblParams.onEdit, "edit")
|
||||
sButtonClass: gui.config.dataTableButtons.edit.css
|
||||
sButtonText: gui.config.dataTableButtons.edit.text
|
||||
fnSelect: editSelected
|
||||
fnClick: clickHandlerFor(tblParams.onEdit, "edit")
|
||||
sButtonClass: gui.config.dataTableButtons.edit.css
|
||||
when "delete"
|
||||
btn =
|
||||
sExtends: "text"
|
||||
sButtonText: gui.config.dataTableButtons["delete"].text
|
||||
fnSelect: deleteSelected
|
||||
fnClick: clickHandlerFor(tblParams.onDelete, "delete")
|
||||
sButtonClass: gui.config.dataTableButtons["delete"].css
|
||||
if self.rest.permission() >= api.permissions.MANAGEMENT
|
||||
btn =
|
||||
sExtends: "text"
|
||||
sButtonText: gui.config.dataTableButtons["delete"].text
|
||||
fnSelect: deleteSelected
|
||||
fnClick: clickHandlerFor(tblParams.onDelete, "delete")
|
||||
sButtonClass: gui.config.dataTableButtons["delete"].css
|
||||
when "refresh"
|
||||
btn =
|
||||
sExtends: "text"
|
||||
@ -329,7 +333,7 @@
|
||||
fnClick: refreshFnc
|
||||
sButtonClass: gui.config.dataTableButtons.refresh.css
|
||||
when "permissions"
|
||||
if api.config.admin
|
||||
if self.rest.permission() == api.permissions.ALL
|
||||
btn =
|
||||
sExtends: "text"
|
||||
sButtonText: gui.config.dataTableButtons.permissions.text
|
||||
@ -346,33 +350,35 @@
|
||||
# End export to excell
|
||||
sButtonClass: gui.config.dataTableButtons.xls.css
|
||||
else # Custom button, this has to be
|
||||
try
|
||||
css = ((if value.css then value.css + " " else "")) + gui.config.dataTableButtons.custom.css
|
||||
btn =
|
||||
sExtends: "text"
|
||||
sButtonText: value.text
|
||||
sButtonClass: css
|
||||
perm = if value.permission? then value.permission else api.permissions.NONE
|
||||
if self.rest.permission() >= perm
|
||||
try
|
||||
css = ((if value.css then value.css + " " else "")) + gui.config.dataTableButtons.custom.css
|
||||
btn =
|
||||
sExtends: "text"
|
||||
sButtonText: value.text
|
||||
sButtonClass: css
|
||||
|
||||
if value.click
|
||||
btn.fnClick = (btn) ->
|
||||
tbl = $("#" + tableId).dataTable()
|
||||
val = @fnGetSelectedData()[0]
|
||||
setTimeout (->
|
||||
value.click val, value, btn, tbl, refreshFnc
|
||||
if value.click
|
||||
btn.fnClick = (btn) ->
|
||||
tbl = $("#" + tableId).dataTable()
|
||||
val = @fnGetSelectedData()[0]
|
||||
setTimeout (->
|
||||
value.click val, value, btn, tbl, refreshFnc
|
||||
return
|
||||
), 0
|
||||
return
|
||||
), 0
|
||||
return
|
||||
if value.select
|
||||
btn.fnSelect = (btn) ->
|
||||
tbl = $("#" + tableId).dataTable()
|
||||
val = @fnGetSelectedData()[0]
|
||||
setTimeout (->
|
||||
value.select val, value, btn, tbl, refreshFnc
|
||||
if value.select
|
||||
btn.fnSelect = (btn) ->
|
||||
tbl = $("#" + tableId).dataTable()
|
||||
val = @fnGetSelectedData()[0]
|
||||
setTimeout (->
|
||||
value.select val, value, btn, tbl, refreshFnc
|
||||
return
|
||||
), 0
|
||||
return
|
||||
), 0
|
||||
return
|
||||
catch e
|
||||
gui.doLog "Button", value, e
|
||||
catch e
|
||||
gui.doLog "Button", value, e
|
||||
btns.push btn if btn
|
||||
return
|
||||
|
||||
|
@ -1,4 +1,18 @@
|
||||
gui.permissions = (val, rest, tbl, refreshFnc) ->
|
||||
baseId = gui.genRamdonId('perms-')
|
||||
|
||||
fillSelect = (perms, forUser) ->
|
||||
$select = $('#' + baseId + (if forUser then '_user_select' else '_group_select'))
|
||||
$select.empty()
|
||||
|
||||
padRight = (str, len)->
|
||||
numPads = len - str.length
|
||||
if (numPads > 0) then str + Array(numPads+1).join(' ') else str
|
||||
|
||||
for item in perms
|
||||
if (forUser is true and item.type is 'user') or (forUser is false and item.type is 'group')
|
||||
$select.append('<option value="' + item.id + '">' + padRight(item.auth_name + '\\' + item.entity_name, 28) + ' | ' + item.perm_name)
|
||||
|
||||
|
||||
addModal = (forUser) ->
|
||||
if forUser
|
||||
@ -39,14 +53,18 @@ gui.permissions = (val, rest, tbl, refreshFnc) ->
|
||||
if auth is -1 or item is -1
|
||||
gui.notify gettext("You must provide authenticator and") + " " + label, "danger"
|
||||
else # Save & close modal
|
||||
rest.addPermission val.id, items, item, perm
|
||||
$(modalId).modal "hide"
|
||||
rest.addPermission val.id, items, item, perm, (
|
||||
(perms) ->
|
||||
$(modalId).modal "hide"
|
||||
fillSelect perms, forUser
|
||||
)
|
||||
return
|
||||
|
||||
# Makes form "beautyfull" :-)
|
||||
gui.tools.applyCustoms modalId
|
||||
return
|
||||
|
||||
|
||||
delModal = (forUser, selectedItems) ->
|
||||
if forUser
|
||||
label = gettext('User')
|
||||
@ -64,30 +82,19 @@ gui.permissions = (val, rest, tbl, refreshFnc) ->
|
||||
|
||||
gui.doLog modalId
|
||||
$(modalId + ' .button-revoke').on('click', () ->
|
||||
rest.revokePermissions val.id, items, toDel
|
||||
$(modalId).modal "hide"
|
||||
rest.revokePermissions toDel, (
|
||||
(perms) ->
|
||||
$(modalId).modal "hide"
|
||||
for v in selectedItems
|
||||
$(v).remove()
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
fillSelect = (baseId, perms, forUser) ->
|
||||
$select = $('#' + baseId + (if forUser then '_user_select' else '_group_select'))
|
||||
$select.empty()
|
||||
|
||||
padRight = (str, len)->
|
||||
numPads = len - str.length
|
||||
if (numPads > 0) then str + Array(numPads+1).join(' ') else str
|
||||
|
||||
for item in perms
|
||||
if (forUser is true and item.type is 'user') or (forUser is false and item.type is 'group')
|
||||
$select.append('<option value="' + item.id + '">' + padRight(item.auth_name + '\\' + item.name, 28) + ' | ' + item.perm_name)
|
||||
|
||||
|
||||
api.templates.get "permissions", (tmpl) ->
|
||||
rest.getPermissions val.id, (perms) ->
|
||||
id = gui.genRamdonId('perms-')
|
||||
content = api.templates.evaluate(tmpl,
|
||||
id: id
|
||||
id: baseId
|
||||
perms: perms
|
||||
)
|
||||
modalId = gui.launchModal gettext("Permissions for") + " " + val.name, content,
|
||||
@ -95,31 +102,31 @@ gui.permissions = (val, rest, tbl, refreshFnc) ->
|
||||
closeButton: '<button type="button" class="btn btn-default" data-dismiss="modal">Ok</button>'
|
||||
|
||||
# Fills user select
|
||||
fillSelect id, perms, true
|
||||
fillSelect id, perms, false
|
||||
fillSelect perms, true
|
||||
fillSelect perms, false
|
||||
|
||||
|
||||
$('#' + id + '_user_del').on('click', () ->
|
||||
$select = $('#' + id + '_user_select')
|
||||
$('#' + baseId + '_user_del').on('click', () ->
|
||||
$select = $('#' + baseId + '_user_select')
|
||||
selected = $select.find(":selected")
|
||||
return if selected.length is 0
|
||||
|
||||
delModal true, selected
|
||||
)
|
||||
|
||||
$('#' + id + '_user_add').on('click', () ->
|
||||
$('#' + baseId + '_user_add').on('click', () ->
|
||||
addModal yes
|
||||
)
|
||||
|
||||
$('#' + id + '_group_del').on('click', () ->
|
||||
$select = $('#' + id + '_group_select')
|
||||
$('#' + baseId + '_group_del').on('click', () ->
|
||||
$select = $('#' + baseId + '_group_select')
|
||||
selected = $select.find(":selected")
|
||||
return if selected.length is 0
|
||||
|
||||
delModal false, selected
|
||||
)
|
||||
|
||||
$('#' + id + '_group_add').on('click', () ->
|
||||
$('#' + baseId + '_group_add').on('click', () ->
|
||||
addModal no
|
||||
)
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
<div class="col-md-6 column">
|
||||
<div class="form-group">
|
||||
<label for="{{ id }}_select">{% endverbatim %}{% trans 'Users' %}{% verbatim %}</label>
|
||||
<select class="form-control" multiple size="8" id="{{ id }}_user_select" style='font-family: "Courier New"'>
|
||||
<select class="form-control" multiple size="12" id="{{ id }}_user_select" style='font-family: "Courier New"'>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@ -20,7 +20,7 @@
|
||||
<div class="col-md-6 column">
|
||||
<div class="form-group">
|
||||
<label for="{{ id }}_select">{% endverbatim %}{% trans 'Groups' %}{% verbatim %}</label>
|
||||
<select class="form-control" multiple size="8" id="{{ id }}_group_select" style='font-family: "Courier New"'>
|
||||
<select class="form-control" multiple size="12" id="{{ id }}_group_select" style='font-family: "Courier New"'>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -25,8 +25,9 @@
|
||||
<label for="id_perm_select" class="col-sm-2 control-label">{% endverbatim %}{% trans 'Permission' %}{% verbatim %}</label>
|
||||
<div class="col-sm-10">
|
||||
<select id="id_perm_select" name="group" class="selectpicker show-menu-arrow show-tick modal_field_data" data-style="btn-default" data-width="100%">
|
||||
<option value="1">Read only</option>
|
||||
<option value="2">All Access</option>
|
||||
<option value="1">{% endverbatim %}{% trans 'Read only' %}{% verbatim %}</option>
|
||||
<option value="2">{% endverbatim %}{% trans 'Management Access' %}{% verbatim %}</option>
|
||||
<option value="2">{% endverbatim %}{% trans 'Full Access' %}{% verbatim %}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user