Preparing meta pools

This commit is contained in:
Adolfo Gómez García 2018-09-28 12:09:17 +02:00
commit 816dde8aca
20 changed files with 378 additions and 171 deletions

View File

@ -102,7 +102,7 @@ class Client(Handler):
logger.debug("Client args for GET: {0}".format(self._args))
if len(self._args) == 0: # Gets version
url = self._request.build_absolute_uri(reverse('uds.web.views.client_downloads'))
url = self._request.build_absolute_uri(reverse('page.client-download'))
return Client.result({
'availableVersion': CLIENT_VERSION,
'requiredVersion': REQUIRED_CLIENT_VERSION,

View File

@ -108,10 +108,19 @@ class AccessCalendars(DetailHandler):
else:
CalendarAccess.objects.create(calendar=calendar, service_pool=parent, access=access, priority=priority)
log.doLog(parent, log.INFO, "Added access calendar {}/{} by {}".format(calendar.name, access, self._user.pretty_name), log.ADMIN)
return self.success()
def deleteItem(self, parent, item):
CalendarAccess.objects.get(uuid=processUuid(self._args[0])).delete()
calendarAccess = CalendarAccess.objects.get(uuid=processUuid(self._args[0]))
logStr = "Removed access calendar {} by {}".format(calendarAccess.calendar.name, self._user.pretty_name)
calendarAccess.delete()
log.doLog(parent, log.INFO, logStr, log.ADMIN)
return self.success()
class ActionsCalendars(DetailHandler):
@ -172,7 +181,11 @@ class ActionsCalendars(DetailHandler):
atStart = self._params['atStart'] not in ('false', False, '0', 0)
params = json.dumps(self._params['params'])
logger.debug('Got parameters: {} {} {} {} ----> {}'.format(calendar, action, eventsOffset, atStart, params))
# logger.debug('Got parameters: {} {} {} {} ----> {}'.format(calendar, action, eventsOffset, atStart, params))
logStr = "Added scheduled action \"{},{},{},{},{}\" by {}".format(
calendar.name, action, eventsOffset,
atStart and 'Start' or 'End', params, self._user.pretty_name
)
if uuid is not None:
calAction = CalendarAction.objects.get(uuid=uuid)
@ -186,16 +199,37 @@ class ActionsCalendars(DetailHandler):
else:
CalendarAction.objects.create(calendar=calendar, service_pool=parent, action=action, at_start=atStart, events_offset=eventsOffset, params=params)
log.doLog(parent, log.INFO, logStr, log.ADMIN)
return self.success()
def deleteItem(self, parent, item):
CalendarAction.objects.get(uuid=processUuid(self._args[0])).delete()
calendarAction = CalendarAction.objects.get(uuid=processUuid(self._args[0]))
logStr = "Removed scheduled action \"{},{},{},{},{}\" by {}".format(
calendarAction.calendar.name, calendarAction.action,
calendarAction.events_offset, calendarAction.at_start and 'Start' or 'End', calendarAction.params,
self._user.pretty_name
)
calendarAction.delete()
log.doLog(parent, log.INFO, logStr, log.ADMIN)
return self.success()
def execute(self, parent, item):
self.ensureAccess(item, permissions.PERMISSION_MANAGEMENT)
logger.debug('Launching action')
uuid = processUuid(item)
calAction = CalendarAction.objects.get(uuid=uuid)
calAction.execute()
calendarAction = CalendarAction.objects.get(uuid=uuid)
logStr = "Launched scheduled action \"{},{},{},{},{}\" by {}".format(
calendarAction.calendar.name, calendarAction.action,
calendarAction.events_offset, calendarAction.at_start and 'Start' or 'End', calendarAction.params,
self._user.pretty_name
)
calendarAction.execute()
log.doLog(parent, log.INFO, logStr, log.ADMIN)
return self.success()

View File

@ -155,7 +155,11 @@ class AssignedService(DetailHandler):
logger.exception('deleteItem')
self.invalidItemException()
logger.debug('Deleting assigned service')
if service.user:
logStr = 'Deleted assigned service {} to user {} by {}'.format(service.friendly_name, service.user.pretty_name, self._user.pretty_name)
else:
logStr = 'Deleted cached service {} by {}'.format(service.friendly_name, self._user.pretty_name)
if service.state in (State.USABLE, State.REMOVING):
service.remove()
elif service.state == State.PREPARING:
@ -165,15 +169,18 @@ class AssignedService(DetailHandler):
else:
self.invalidItemException(_('Item is not removable'))
log.doLog(parent, log.INFO, logStr, log.ADMIN)
return self.success()
# Only owner is allowed to change right now
def saveItem(self, parent, item):
fields = self.readFieldsFromParams(['auth_id', 'user_id'])
logger.debug('Saving userService {} / {} ({})'.format(parent, item, fields))
service = parent.userServices.get(uuid=processUuid(item))
user = User.objects.get(uuid=processUuid(fields['user_id']))
logStr = 'Changing ownership of service from {} to {} by {}'.format(service.user.pretty_name, user.pretty_name, self._user.pretty_name)
# If there is another service that has this same owner, raise an exception
if parent.userServices.filter(user=user).exclude(uuid=service.uuid).count() > 0:
raise self.invalidResponseException('There is already another user service assigned to {}'.format(user.pretty_name))
@ -181,7 +188,10 @@ class AssignedService(DetailHandler):
service.user = user
service.save()
return service
# Log change
log.doLog(service, log.INFO, logStr, log.ADMIN)
return self.success()
class CachedService(AssignedService):
@ -256,11 +266,18 @@ class Groups(DetailHandler):
return {'field': 'state', 'prefix': 'row-state-'}
def saveItem(self, parent, item):
parent.assignedGroups.add(Group.objects.get(uuid=processUuid(self._params['id'])))
grp = Group.objects.get(uuid=processUuid(self._params['id']))
parent.assignedGroups.add(grp)
log.doLog(parent, log.INFO, "Added group {} by {}".format(grp.pretty_name, self._user.pretty_name), log.ADMIN)
return self.success()
def deleteItem(self, parent, item):
parent.assignedGroups.remove(Group.objects.get(uuid=processUuid(self._args[0])))
grp = Group.objects.get(uuid=processUuid(self._args[0]))
parent.assignedGroups.remove(grp)
log.doLog(parent, log.INFO, "Removed group {} by {}".format(grp.pretty_name, self._user.pretty_name), log.ADMIN)
return self.success()
class Transports(DetailHandler):
@ -288,11 +305,18 @@ class Transports(DetailHandler):
]
def saveItem(self, parent, item):
parent.transports.add(Transport.objects.get(uuid=processUuid(self._params['id'])))
transport = Transport.objects.get(uuid=processUuid(self._params['id']))
parent.transports.add(transport)
log.doLog(parent, log.INFO, "Added transport {} by {}".format(transport.name, self._user.pretty_name), log.ADMIN)
return self.success()
def deleteItem(self, parent, item):
parent.transports.remove(Transport.objects.get(uuid=processUuid(self._args[0])))
transport = Transport.objects.get(uuid=processUuid(self._args[0]))
parent.transports.remove(transport)
log.doLog(parent, log.INFO, "Removed transport {} by {}".format(transport.name, self._user.pretty_name), log.ADMIN)
return self.success()
class Publications(DetailHandler):
@ -314,6 +338,9 @@ class Publications(DetailHandler):
logger.debug('Custom "publish" invoked for {}'.format(parent))
parent.publish(changeLog) # Can raise exceptions that will be processed on response
log.doLog(parent, log.INFO, "Initated publication v{} by {}".format(parent.current_pub_revision, self._user.pretty_name), log.ADMIN)
return self.success()
def cancel(self, parent, uuid):
@ -333,6 +360,8 @@ class Publications(DetailHandler):
except Exception as e:
raise ResponseError("{}".format(e))
log.doLog(parent, log.INFO, "Canceled publication v{} by {}".format(parent.current_pub_revision, self._user.pretty_name), log.ADMIN)
return self.success()
def getItems(self, parent, item):

View File

@ -0,0 +1,82 @@
# Generated by Django 2.1.1 on 2018-09-28 10:20
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('uds', '0028_auto_20180316_1001'),
]
operations = [
migrations.CreateModel(
name='CalendarAccessMeta',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('uuid', models.CharField(default=None, max_length=50, null=True, unique=True)),
('access', models.CharField(default='DENY', max_length=8)),
('priority', models.IntegerField(db_index=True, default=0)),
('calendar', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='uds.Calendar')),
],
options={
'db_table': 'uds_cal_maccess',
'ordering': ('priority',),
},
),
migrations.CreateModel(
name='MetaPool',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('uuid', models.CharField(default=None, max_length=50, null=True, unique=True)),
('name', models.CharField(default='', max_length=128)),
('short_name', models.CharField(default='', max_length=32)),
('comments', models.CharField(default='', max_length=256)),
('visible', models.BooleanField(default=True)),
('fallbackAccess', models.CharField(default='ALLOW', max_length=8)),
('accessCalendars', models.ManyToManyField(related_name='accessMeta', through='uds.CalendarAccessMeta', to='uds.Calendar')),
('assignedGroups', models.ManyToManyField(db_table='uds__meta_grps', related_name='metaPools', to='uds.Group')),
('image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='metaPools', to='uds.Image')),
],
options={
'abstract': False,
'db_table': 'uds__pool_meta',
},
),
migrations.CreateModel(
name='MetaPoolMember',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('uuid', models.CharField(default=None, max_length=50, null=True, unique=True)),
('priority', models.PositiveIntegerField(default=0)),
('enabled', models.BooleanField(default=True)),
('meta_pool', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='metaPool', to='uds.MetaPool')),
('pool', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pool', to='uds.DeployedService')),
],
options={
'abstract': False,
'db_table': 'uds__meta_pool_member',
},
),
migrations.AddField(
model_name='metapool',
name='pools',
field=models.ManyToManyField(related_name='meta', through='uds.MetaPoolMember', to='uds.DeployedService'),
),
migrations.AddField(
model_name='metapool',
name='servicesPoolGroup',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='metaPools', to='uds.ServicesPoolGroup'),
),
migrations.AddField(
model_name='metapool',
name='tags',
field=models.ManyToManyField(to='uds.Tag'),
),
migrations.AddField(
model_name='calendaraccessmeta',
name='meta_pool',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='uds.MetaPool'),
),
]

View File

@ -39,6 +39,7 @@ from uds.core.util import states
from uds.models.UUIDModel import UUIDModel
from uds.models.Calendar import Calendar
from uds.models.ServicesPool import ServicePool
from uds.models.MetaPool import MetaPool
# from django.utils.translation import ugettext_lazy as _, ugettext
import logging
@ -60,3 +61,18 @@ class CalendarAccess(UUIDModel):
ordering = ('priority',)
app_label = 'uds'
class CalendarAccessMeta(UUIDModel):
calendar = models.ForeignKey(Calendar, on_delete=models.CASCADE)
meta_pool = models.ForeignKey(MetaPool, on_delete=models.CASCADE)
access = models.CharField(max_length=8, default=states.action.DENY)
priority = models.IntegerField(default=0, db_index=True)
class Meta:
"""
Meta class to declare db table
"""
db_table = 'uds_cal_maccess'
ordering = ('priority',)
app_label = 'uds'

View File

@ -37,7 +37,6 @@ from django.db import models
from django.db.models import signals
from django.utils.encoding import python_2_unicode_compatible
from uds.core.util.State import State
from uds.core.util import log
from .UUIDModel import UUIDModel
@ -50,7 +49,7 @@ import logging
logger = logging.getLogger(__name__)
__updated__ = '2015-09-07'
__updated__ = '2018-09-24'
@python_2_unicode_compatible
@ -77,6 +76,10 @@ class Group(UUIDModel):
ordering = ('name',)
app_label = 'uds'
@property
def pretty_name(self):
return self.name + '@' + self.manager.name
def getManager(self):
"""
Returns the authenticator object that owns this user.

View File

@ -0,0 +1,123 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2018 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.
"""
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
"""
from __future__ import unicode_literals
from django.db import models
from django.db.models import signals
from uds.core.util import log
from uds.core.util import states
from uds.models.UUIDModel import UUIDModel
from uds.models.Tag import TaggingMixin
from uds.models.Image import Image
from uds.models.ServicesPoolGroup import ServicesPoolGroup
from uds.models.ServicesPool import ServicePool
from uds.models.Group import Group
from uds.models.Calendar import Calendar
import logging
__updated__ = '2018-09-28'
logger = logging.getLogger(__name__)
class MetaPool(UUIDModel, TaggingMixin):
"""
A deployed service is the Service produced element that is assigned finally to an user (i.e. a Virtual Machine, etc..)
"""
name = models.CharField(max_length=128, default='')
short_name = models.CharField(max_length=32, default='')
comments = models.CharField(max_length=256, default='')
visible = models.BooleanField(default=True)
image = models.ForeignKey(Image, null=True, blank=True, related_name='metaPools', on_delete=models.SET_NULL)
servicesPoolGroup = models.ForeignKey(ServicesPoolGroup, null=True, blank=True, related_name='metaPools', on_delete=models.SET_NULL)
assignedGroups = models.ManyToManyField(Group, related_name='metaPools', db_table='uds__meta_grps')
accessCalendars = models.ManyToManyField(Calendar, related_name='accessMeta', through='CalendarAccessMeta')
# Default fallback action for access
fallbackAccess = models.CharField(default=states.action.ALLOW, max_length=8)
pools = models.ManyToManyField(ServicePool, through='MetapoolMember', related_name='meta')
class Meta(UUIDModel.Meta):
"""
Meta class to declare the name of the table at database
"""
db_table = 'uds__pool_meta'
app_label = 'uds'
@staticmethod
def beforeDelete(sender, **kwargs):
"""
Used to invoke the Service class "Destroy" before deleting it from database.
The main purpuse of this hook is to call the "destroy" method of the object to delete and
to clear related data of the object (environment data such as own storage, cache, etc...
:note: If destroy raises an exception, the deletion is not taken.
"""
from uds.core.util.permissions import clean
toDelete = kwargs['instance']
# Clears related logs
log.clearLogs(toDelete)
# Clears related permissions
clean(toDelete)
def __str__(self):
return ''
# Connects a pre deletion signal
signals.pre_delete.connect(MetaPool.beforeDelete, sender=MetaPool)
class MetaPoolMember(UUIDModel):
pool = models.ForeignKey(ServicePool, related_name='pool', on_delete=models.CASCADE)
meta_pool = models.ForeignKey(MetaPool, related_name='metaPool', on_delete=models.CASCADE)
priority = models.PositiveIntegerField(default=0)
enabled = models.BooleanField(default=True)
class Meta(UUIDModel.Meta):
"""
Meta class to declare the name of the table at database
"""
db_table = 'uds__meta_pool_member'
app_label = 'uds'
def __str__(self):
return ''

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012 Virtual Cable S.L.
# Copyright (c) 2012-2018 Virtual Cable S.L.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@ -63,7 +63,7 @@ import logging
import pickle
import six
__updated__ = '2018-09-20'
__updated__ = '2018-09-27'
logger = logging.getLogger(__name__)

View File

@ -57,7 +57,7 @@ from uds.core.services import UserDeployment
import logging
__updated__ = '2018-09-19'
__updated__ = '2018-09-26'
logger = logging.getLogger(__name__)
@ -457,7 +457,7 @@ class UserService(UUIDModel):
Return DeployedUserServices (not deployed services) that this user owns and are assignable
For this to happen, we locate all user services assigned to this user, and we keep those that:
* Must assign service manually
This method is probably slow, but i don't think a user will have more than a bunch of services assigned
This method is probably not the best in performance, but the number of assigned services will never be "high" (maybe a couple dozens at most?)
@returns and array of dicts with id, name and transports
"""
logger.debug("Filtering assigned services for user {0}".format(user))

View File

@ -63,7 +63,7 @@ from .Group import Group
# Provisioned services
from .ServicesPool import DeployedService # Old name, will continue here for a while already
from .ServicesPool import ServicePool # New name
# from .MetaServicePool import
from .MetaPool import MetaPool
from .ServicesPoolGroup import ServicesPoolGroup
from .ServicesPoolPublication import DeployedServicePublication
from .UserService import UserService
@ -97,7 +97,7 @@ from .TicketStore import TicketStore
from .Calendar import Calendar
from .CalendarRule import CalendarRule
from .CalendarAccess import CalendarAccess
from .CalendarAccess import CalendarAccess, CalendarAccessMeta
from .CalendarAction import CalendarAction
# Accounting
@ -113,7 +113,7 @@ from .Tag import Tag
# Utility
from .DBFile import DBFile
__updated__ = '2018-02-14'
__updated__ = '2018-09-28'
logger = logging.getLogger(__name__)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -6,17 +6,23 @@ gettext("Learn more");
gettext("Launching service");
gettext("Please wait");
gettext("Remember that UDS Plugin is required in order for this service to be launched");
gettext("Error launching service");
gettext("Warning");
gettext("Service is in maintenance and cannot be executed");
gettext("Invalid error string");
gettext("seconds");
gettext("Service is in maintenance");
gettext("Access to the service is restricted at this time");
gettext("This service is currently not accessible due to schedule restrictions.");
gettext("Launcher");
gettext("Service is in maintenance and cannot be launched");
gettext("This service is currently not accesible due to schedule restrictions.");
gettext("Access limited by calendar");
gettext("Please, retry access in a while.");
gettext("Release service: ");
gettext("Reset service: ");
gettext("Service released");
gettext("Service reseted");
gettext("Are you sure?");
// HTML
gettext("UDS Client");
gettext("Download UDS client for your platform");
@ -30,12 +36,13 @@ gettext("Login");
gettext("An error has occurred");
gettext("Return");
gettext("Dashboard");
gettext("Preferences");
gettext("Downloads");
gettext("Logout");
gettext("About");
gettext("About");
gettext("Close");
gettext("Yes");
gettext("No");
gettext(" Release service");
gettext(" Reset service");
gettext("Transports");

View File

@ -110,6 +110,7 @@ def udsJs(context):
'customAuth': reverse('uds.web.views.customAuth', kwargs={'idAuth': ''}),
'services': reverse('webapi.services'),
'enabler': reverse('webapi.enabler', kwargs={ 'idService': 'param1', 'idTransport': 'param2' }),
'action': reverse('webapi.action', kwargs={ 'idService': 'param1', 'action': 'param2' }),
'galleryImage': reverse('webapi.galleryImage', kwargs={ 'idImage': 'param1' }),
'transportIcon': reverse('webapi.transportIcon', kwargs={'idTrans': 'param1'}),
'static': static(''),
@ -137,11 +138,6 @@ def udsJs(context):
actors = [{'url': reverse('utility.downloader', kwargs={'idDownload': key}), 'name': val['name'], 'description': gettext(val['comment'])} for key, val in downloadsManager().getDownloadables().items()]
config['urls']['admin'] = reverse('uds.admin.views.index')
if request.user:
prefs = request.user.prefs('_uds')
# Update bypass configuration with user information
config['bypassPluginDetection'] = prefs.get('bypassPluginDetection') == '1'
errors = []
if 'errors' in request.session:
errors = request.session['errors']

View File

@ -60,7 +60,7 @@ urlpatterns = [
re_path(r'^authinfo/(?P<authName>.+)', uds.web.views.authInfo, name='page.auth.info.compat'),
# Ticket authentication
re_path(r'^tkauth/(?P<ticketId>.+)$', uds.web.views.ticketAuth, name='page,auth.ticket.compat'),
re_path(r'^tkauth/(?P<ticketId>[a-zA-Z0-9-])$', uds.web.views.ticketAuth, name='page,auth.ticket.compat'),
# END COMPAT
@ -69,19 +69,21 @@ urlpatterns = [
# Login/logout
path(r'uds/page/login/', uds.web.views.modern.login, name='page.login'),
re_path(r'^uds/page/login/(?P<tag>.+)$', uds.web.views.modern.login, name='page.login.tag'),
re_path(r'^uds/page/login/(?P<tag>[a-zA-Z0-9-])$', uds.web.views.modern.login, name='page.login.tag'),
path(r'uds/page/logout/', uds.web.views.modern.logout, name='page.logout'),
# Error URL
re_path(r'^uds/page/error/(?P<error>.+)$', uds.web.views.error, name='page.error'),
# Error URL (just a placeholder, calls index with data on url for angular)
re_path(r'^uds/page/error/(?P<error>[a-zA-Z0-9=-]+)$', uds.web.views.error, name='page.error'),
# Download plugins URL (just a placeholder, calls index with data on url for angular)
path(r'uds/page/client-download', uds.web.views.modern.index, name='page.client-download'),
# Federated authentication
re_path(r'^uds/page/auth/(?P<authName>[^/]+)$', uds.web.views.authCallback, name='page.auth.callback'),
re_path(r'^uds/page/auth/info/(?P<authName>.+)$', uds.web.views.authInfo, name='page.auth.info'),
re_path(r'^uds/page/auth/info/(?P<authName>[a-zA-Z0-9-])$', uds.web.views.authInfo, name='page.auth.info'),
# Ticket authentication related
re_path(r'^uds/page/ticket/auth/(?P<ticketId>.+)$', uds.web.views.ticketAuth, name='page.ticket.auth'),
re_path(r'^uds/page/ticket/auth/(?P<ticketId>[a-zA-Z0-9-])$', uds.web.views.ticketAuth, name='page.ticket.auth'),
path(r'uds/page/ticket/launcher', uds.web.views.modern.index, name='page.ticket.launcher'),
# This must be the last, so any patition will be managed by client in fact
@ -102,13 +104,12 @@ urlpatterns = [
re_path(r'^uds/utility/files/(?P<uuid>.+)', uds.web.views.file_storage, name='utility.file_storage'),
# WEB API path (not REST api, frontend)
re_path(r'^uds/webapi/img/transport/(?P<idTrans>.+)$', uds.web.views.transportIcon, name='webapi.transportIcon'),
re_path(r'^uds/webapi/img/gallery/(?P<idImage>.+)$', uds.web.views.image, name='webapi.galleryImage'),
re_path(r'^uds/webapi/img/transport/(?P<idTrans>[a-zA-Z0-9-]+)$', uds.web.views.transportIcon, name='webapi.transportIcon'),
re_path(r'^uds/webapi/img/gallery/(?P<idImage>[a-zA-Z0-9-]+)$', uds.web.views.image, name='webapi.galleryImage'),
re_path(r'^uds/webapi/enable/(?P<idService>.+)/(?P<idTransport>.+)$', uds.web.views.clientEnabler, name='webapi.enabler'),
re_path(r'^uds/webapi/action/(?P<idService>.+)/enable/(?P<idTransport>[a-zA-Z0-9-]+)$', uds.web.views.clientEnabler, name='webapi.enabler'),
re_path(r'^release/(?P<idService>.+)$', uds.web.views.release, name='webapi.releaser'),
re_path(r'^reset/(?P<idService>.+)$', uds.web.views.reset, name='webapi.resetter'),
re_path(r'^uds/webapi/action/(?P<idService>.+)/(?P<action>[a-zA-Z0-9-]+)$', uds.web.views.action, name='webapi.action'),
# Services list, ...
path(r'uds/webapi/services', uds.web.views.modern.servicesData, name='webapi.services'),

View File

@ -33,16 +33,14 @@ from __future__ import unicode_literals
import logging
# from .login import login, logout
from .prefs import prefs
from .service import transportOwnLink, transportIcon, clientEnabler, serviceImage, release, reset
from .service import transportOwnLink, transportIcon, clientEnabler, serviceImage, action
from .auth import authCallback, authInfo, ticketAuth, customAuth
from .download import download
from .client_download import client_downloads, plugin_detection
from ..errors import error
from .images import image
from .file_storage import file_storage
from . import modern
__updated__ = '2018-09-20'
__updated__ = '2018-09-28'
logger = logging.getLogger(__name__)

View File

@ -34,7 +34,6 @@ import logging
from django.urls import reverse
from django.http import HttpResponse, HttpResponseRedirect, HttpResponsePermanentRedirect
from django.shortcuts import render
from django.utils.translation import ugettext as _
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_exempt
@ -43,8 +42,7 @@ import uds.web.errors as errors
from uds.core.auths.Exceptions import InvalidUserException
from uds.core.auths.auth import webLogin, webLogout, authenticateViaCallback, authLogLogin, getUDSCookie
from uds.core.managers import userServiceManager, cryptoManager
from uds.core.services.Exceptions import InvalidServiceException, ServiceNotReadyError
from uds.core.ui import theme
from uds.core.services.Exceptions import ServiceNotReadyError
from uds.core.util import OsDetector
from uds.core.util import html
from uds.core.util.State import State
@ -54,7 +52,7 @@ from uds.models import TicketStore
logger = logging.getLogger(__name__)
__updated__ = '2018-09-20'
__updated__ = '2018-09-28'
@csrf_exempt

View File

@ -1,79 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012-2016 Virtual Cable S.L.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
@author: Adolfo Gómez, dkmaster at dkmon dot com
"""
from __future__ import unicode_literals
from django.http import HttpResponse
from django.utils.translation import ugettext_noop
from django.shortcuts import render
from django.template import RequestContext
from uds.core.managers.UserPrefsManager import UserPrefsManager, CommonPrefs
from uds.core.auths.auth import webLoginRequired
from uds.core.ui import theme
from uds.core.util.OsDetector import desktopOss
import logging
logger = logging.getLogger(__name__)
__updated__ = '2018-09-10'
UserPrefsManager.manager().registerPrefs(
'_uds',
ugettext_noop('UDS Plugin preferences'),
[
CommonPrefs.bypassPluginDetectionPref
]
)
def client_downloads(request, os=None):
"""
Download page for UDS plugins
"""
if os not in desktopOss:
os = request.os['OS']
logger.debug('User: {}'.format(request.user))
os = os.lower()
return render(
request,
theme.template('download_client.html'),
{'os': os, 'user': request.user}
)
@webLoginRequired(admin=False)
def plugin_detection(request, detection):
if detection != '0':
detection = '1'
UserPrefsManager.manager().setPreferenceForUser(request.user, '_uds', CommonPrefs.BYPASS_PREF, detection)
return HttpResponse(content='', content_type='text/plain')

View File

@ -30,18 +30,15 @@
"""
from __future__ import unicode_literals
from django.shortcuts import render
from django.utils.translation import ugettext as _
from uds.core.auths.auth import webLoginRequired
from uds.core.managers.DownloadsManager import DownloadsManager
from uds.core.ui import theme
from .modern import index
import logging
logger = logging.getLogger(__name__)
__updated__ = '2018-05-18'
__updated__ = '2018-09-28'
@webLoginRequired(admin=True)
@ -49,9 +46,7 @@ def download(request, idDownload):
"""
Downloadables management
"""
if idDownload == '':
files = [{'id': key, 'name': val['name'], 'comment': _(val['comment'])} for key, val in DownloadsManager.manager().getDownloadables().items()]
logger.debug('Files: {0}'.format(files))
return render(request, theme.template('downloads.html'), {'files': files})
if idDownload.strip() == '':
return index(request)
return DownloadsManager.manager().send(request, idDownload)

View File

@ -43,14 +43,15 @@ from uds.models import Transport, Image
from uds.core.util import html, log
from uds.core.services.Exceptions import ServiceNotReadyError, MaxServicesReachedError, ServiceAccessDeniedByCalendar
import uds.web.errors as errors
from uds.web import errors
from uds.web import services
import json
import logging
logger = logging.getLogger(__name__)
__updated__ = '2018-09-20'
__updated__ = '2018-09-27'
@webLoginRequired(admin=False)
@ -143,39 +144,42 @@ def clientEnabler(request, idService, idTransport):
@webLoginRequired(admin=False)
@never_cache
def release(request, idService):
def action(request, idService, action):
logger.debug('ID Service: {}'.format(idService))
userService = userServiceManager().locateUserService(request.user, idService, create=False)
logger.debug('UserService: >{}<'.format(userService))
if userService is not None and userService.deployed_service.allow_users_remove:
log.doLog(
userService.deployed_service,
log.INFO,
"Removing User Service {} as requested by {} from {}".format(userService.friendly_name, request.user.pretty_name, request.ip),
log.WEB
)
userServiceManager().requestLogoff(userService)
userService.release()
response = None
rebuild = False
if userService:
if action == 'release' and userService.deployed_service.allow_users_remove:
rebuild = True
log.doLog(
userService.deployed_service,
log.INFO,
"Removing User Service {} as requested by {} from {}".format(userService.friendly_name, request.user.pretty_name, request.ip),
log.WEB
)
userServiceManager().requestLogoff(userService)
userService.release()
elif (action == 'reset'
and userService.deployed_service.allow_users_reset
and userService.deployed_service.service.getType().canReset):
rebuild = True
log.doLog(
userService.deployed_service,
log.INFO,
"Reseting User Service {} as requested by {} from {}".format(userService.friendly_name, request.user.pretty_name, request.ip),
log.WEB
)
# userServiceManager().requestLogoff(userService)
userServiceManager().reset(userService)
return HttpResponse('"ok"', content_type="application/json")
@webLoginRequired(admin=False)
@never_cache
def reset(request, idService):
logger.debug('ID Service: {}'.format(idService))
userService = userServiceManager().locateUserService(request.user, idService, create=False)
logger.debug('UserService: >{}<'.format(userService))
if (userService is not None and userService.deployed_service.allow_users_reset
and userService.deployed_service.service.getType().canReset):
log.doLog(
userService.deployed_service,
log.INFO,
"Reseting User Service {} as requested by {} from {}".format(userService.friendly_name, request.user.pretty_name, request.ip),
log.WEB
)
# userServiceManager().requestLogoff(userService)
userServiceManager().reset(userService)
return HttpResponse('"ok"', content_type="application/json")
if rebuild:
# Rebuild services data, but return only "this" service
for v in services.getServicesData(request)['services']:
logger.debug('{} ==? {}'.format(v['id'], idService))
if v['id'] == idService:
response = v
break
return HttpResponse(json.dumps(response), content_type="application/json")