forked from shaba/openuds
Preparing meta pools
This commit is contained in:
commit
816dde8aca
@ -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,
|
||||
|
@ -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()
|
||||
|
@ -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):
|
||||
|
82
server/src/uds/migrations/0029_auto_20180928_1020.py
Normal file
82
server/src/uds/migrations/0029_auto_20180928_1020.py
Normal 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'),
|
||||
),
|
||||
]
|
@ -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'
|
||||
|
||||
|
@ -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.
|
||||
|
123
server/src/uds/models/MetaPool.py
Normal file
123
server/src/uds/models/MetaPool.py
Normal 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 ''
|
@ -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__)
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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
@ -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");
|
||||
|
@ -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']
|
||||
|
@ -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'),
|
||||
|
@ -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__)
|
||||
|
@ -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
|
||||
|
@ -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')
|
@ -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)
|
||||
|
@ -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")
|
||||
|
Loading…
Reference in New Issue
Block a user