mirror of
https://github.com/lucaspalomodevelop/indico-plugins.git
synced 2026-03-12 23:27:22 +00:00
Remove vc_vidyo plugin
This commit is contained in:
parent
ec757d9f98
commit
a6625281d5
@ -30,6 +30,5 @@ install_requires =
|
||||
indico-plugin-previewer-jupyter>=3.0.dev0,<3.1.dev0
|
||||
indico-plugin-storage-s3>=3.0.dev0,<3.1.dev0
|
||||
indico-plugin-ursh>=3.0.dev0,<3.1.dev0
|
||||
indico-plugin-vc-vidyo>=3.0.dev0,<3.1.dev0
|
||||
indico-plugin-vc-zoom>=3.0.dev0,<3.1.dev0
|
||||
# END GENERATED REQUIREMENTS
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
graft indico_vc_vidyo/static
|
||||
graft indico_vc_vidyo/migrations
|
||||
graft indico_vc_vidyo/templates
|
||||
graft indico_vc_vidyo/translations
|
||||
|
||||
global-exclude *.pyc __pycache__ .keep
|
||||
@ -1,17 +0,0 @@
|
||||
# This file is part of the Indico plugins.
|
||||
# Copyright (C) 2002 - 2021 CERN
|
||||
#
|
||||
# The Indico plugins are free software; you can redistribute
|
||||
# them and/or modify them under the terms of the MIT License;
|
||||
# see the LICENSE file for more details.
|
||||
|
||||
from indico.core import signals
|
||||
from indico.util.i18n import make_bound_gettext
|
||||
|
||||
|
||||
_ = make_bound_gettext('vc_vidyo')
|
||||
|
||||
|
||||
@signals.import_tasks.connect
|
||||
def _import_tasks(sender, **kwargs):
|
||||
import indico_vc_vidyo.task # noqa: F401
|
||||
@ -1,11 +0,0 @@
|
||||
# This file is part of the Indico plugins.
|
||||
# Copyright (C) 2002 - 2021 CERN
|
||||
#
|
||||
# The Indico plugins are free software; you can redistribute
|
||||
# them and/or modify them under the terms of the MIT License;
|
||||
# see the LICENSE file for more details.
|
||||
|
||||
from .client import AdminClient, APIException, RoomNotFoundAPIException, UserClient
|
||||
|
||||
|
||||
__all__ = ['UserClient', 'AdminClient', 'APIException', 'RoomNotFoundAPIException']
|
||||
@ -1,27 +0,0 @@
|
||||
# This file is part of the Indico plugins.
|
||||
# Copyright (C) 2002 - 2021 CERN
|
||||
#
|
||||
# The Indico plugins are free software; you can redistribute
|
||||
# them and/or modify them under the terms of the MIT License;
|
||||
# see the LICENSE file for more details.
|
||||
|
||||
from zeep.cache import Base
|
||||
|
||||
from indico.core.cache import make_scoped_cache
|
||||
|
||||
|
||||
DEFAULT_CACHE_TTL = 24 * 3600
|
||||
|
||||
|
||||
class ZeepCache(Base):
|
||||
_instance = None
|
||||
|
||||
def __init__(self, duration=DEFAULT_CACHE_TTL):
|
||||
self._cache = make_scoped_cache('zeep')
|
||||
self._duration = duration
|
||||
|
||||
def get(self, url):
|
||||
self._cache.get(url)
|
||||
|
||||
def add(self, url, content):
|
||||
self._cache.set(url, content, timeout=self._duration)
|
||||
@ -1,119 +0,0 @@
|
||||
# This file is part of the Indico plugins.
|
||||
# Copyright (C) 2002 - 2021 CERN
|
||||
#
|
||||
# The Indico plugins are free software; you can redistribute
|
||||
# them and/or modify them under the terms of the MIT License;
|
||||
# see the LICENSE file for more details.
|
||||
|
||||
from requests import Session
|
||||
from requests.auth import HTTPBasicAuth
|
||||
from zeep import Client
|
||||
from zeep.exceptions import Fault
|
||||
from zeep.transports import Transport
|
||||
|
||||
from indico_vc_vidyo.api.cache import ZeepCache
|
||||
|
||||
|
||||
DEFAULT_CLIENT_TIMEOUT = 30
|
||||
AUTOMUTE_API_PROFILE = "NoAudioAndVideo"
|
||||
|
||||
|
||||
class APIException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class RoomNotFoundAPIException(APIException):
|
||||
pass
|
||||
|
||||
|
||||
def raises_api_error(wrapped):
|
||||
def _wrapper(*args, **kwargs):
|
||||
try:
|
||||
return wrapped(*args, **kwargs)
|
||||
except Fault as err:
|
||||
err_msg = err.message
|
||||
if err_msg.startswith('Room not found for roomID') or 'Invalid roomID' in err_msg:
|
||||
raise RoomNotFoundAPIException()
|
||||
else:
|
||||
raise APIException(err_msg)
|
||||
return _wrapper
|
||||
|
||||
|
||||
class ClientBase:
|
||||
def __init__(self, wsdl, settings):
|
||||
session = Session()
|
||||
transport = Transport(session=session, cache=ZeepCache())
|
||||
session.auth = HTTPBasicAuth(settings.get('username'), settings.get('password'))
|
||||
self.client = Client(wsdl, transport=transport)
|
||||
self.factory = self.client.type_factory('ns0')
|
||||
|
||||
@property
|
||||
def soap(self):
|
||||
return self.client.service
|
||||
|
||||
|
||||
class UserClient(ClientBase):
|
||||
def __init__(self, settings):
|
||||
super().__init__(settings.get('user_api_wsdl'), settings)
|
||||
|
||||
|
||||
class AdminClient(ClientBase):
|
||||
def __init__(self, settings):
|
||||
super().__init__(settings.get('admin_api_wsdl'), settings)
|
||||
|
||||
def create_room_object(self, **kwargs):
|
||||
return self.factory.Room(**kwargs)
|
||||
|
||||
@raises_api_error
|
||||
def find_room(self, extension):
|
||||
from indico_vc_vidyo.plugin import VidyoPlugin
|
||||
filter_ = {
|
||||
'query': extension,
|
||||
'limit': 40,
|
||||
'dir': 'DESC'
|
||||
}
|
||||
counter = 0
|
||||
|
||||
while True:
|
||||
filter_['start'] = counter * filter_['limit']
|
||||
response = self.soap.getRooms(filter_)
|
||||
if not response.total:
|
||||
return None
|
||||
for room in response.room:
|
||||
if int(room.extension) == int(extension):
|
||||
VidyoPlugin.logger.debug('Room: %s has been found.', room)
|
||||
return room
|
||||
else:
|
||||
VidyoPlugin.logger.debug('Dismissing room extension %s', room.extension)
|
||||
counter += 1
|
||||
|
||||
@raises_api_error
|
||||
def get_room(self, vidyo_id):
|
||||
return self.soap.getRoom(roomID=vidyo_id)
|
||||
|
||||
@raises_api_error
|
||||
def add_room(self, room_obj):
|
||||
self.soap.addRoom(room=room_obj)
|
||||
|
||||
@raises_api_error
|
||||
def update_room(self, room_id, room_obj):
|
||||
self.soap.updateRoom(roomID=room_id, room=room_obj)
|
||||
|
||||
@raises_api_error
|
||||
def delete_room(self, room_id):
|
||||
self.soap.deleteRoom(roomID=room_id)
|
||||
|
||||
@raises_api_error
|
||||
def get_automute(self, room_id):
|
||||
answer = self.soap.getRoomProfile(roomID=room_id)
|
||||
if answer:
|
||||
return answer.roomProfileName == AUTOMUTE_API_PROFILE
|
||||
else:
|
||||
return False
|
||||
|
||||
@raises_api_error
|
||||
def set_automute(self, room_id, status):
|
||||
if status:
|
||||
self.soap.setRoomProfile(roomID=room_id, roomProfileName=AUTOMUTE_API_PROFILE)
|
||||
else:
|
||||
self.soap.removeRoomProfile(roomID=room_id)
|
||||
@ -1,23 +0,0 @@
|
||||
# This file is part of the Indico plugins.
|
||||
# Copyright (C) 2002 - 2021 CERN
|
||||
#
|
||||
# The Indico plugins are free software; you can redistribute
|
||||
# them and/or modify them under the terms of the MIT License;
|
||||
# see the LICENSE file for more details.
|
||||
|
||||
from indico.core.plugins import IndicoPluginBlueprint
|
||||
|
||||
from indico_vc_vidyo.controllers import RHVidyoRoomOwner
|
||||
|
||||
|
||||
blueprint = IndicoPluginBlueprint('vc_vidyo', 'indico_vc_vidyo')
|
||||
|
||||
# Room management
|
||||
# using any(vidyo) instead of defaults since the event vc room locator
|
||||
# includes the service and normalization skips values provided in 'defaults'
|
||||
blueprint.add_url_rule(
|
||||
'/event/<int:event_id>/manage/videoconference/<any(vidyo):service>/<int:event_vc_room_id>/room-owner',
|
||||
'set_room_owner',
|
||||
RHVidyoRoomOwner,
|
||||
methods=('POST',)
|
||||
)
|
||||
@ -1,38 +0,0 @@
|
||||
# This file is part of the Indico plugins.
|
||||
# Copyright (C) 2002 - 2021 CERN
|
||||
#
|
||||
# The Indico plugins are free software; you can redistribute
|
||||
# them and/or modify them under the terms of the MIT License;
|
||||
# see the LICENSE file for more details.
|
||||
|
||||
import click
|
||||
from terminaltables import AsciiTable
|
||||
|
||||
from indico.cli.core import cli_group
|
||||
from indico.modules.vc.models.vc_rooms import VCRoom, VCRoomStatus
|
||||
|
||||
|
||||
@cli_group(name='vidyo')
|
||||
def cli():
|
||||
"""Manage the Vidyo plugin."""
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.option('--status', type=click.Choice(['deleted', 'created']))
|
||||
def rooms(status=None):
|
||||
"""Lists all Vidyo rooms"""
|
||||
|
||||
room_query = VCRoom.query.filter_by(type='vidyo')
|
||||
table_data = [['ID', 'Name', 'Status', 'Vidyo ID', 'Extension']]
|
||||
|
||||
if status:
|
||||
room_query = room_query.filter(VCRoom.status == VCRoomStatus.get(status))
|
||||
|
||||
for room in room_query:
|
||||
table_data.append([str(room.id), room.name, room.status.name,
|
||||
str(room.data['vidyo_id']), str(room.vidyo_extension.extension)])
|
||||
|
||||
table = AsciiTable(table_data)
|
||||
for col in (0, 3, 4):
|
||||
table.justify_columns[col] = 'right'
|
||||
print(table.table)
|
||||
@ -1,34 +0,0 @@
|
||||
// This file is part of the Indico plugins.
|
||||
// Copyright (C) 2002 - 2021 CERN
|
||||
//
|
||||
// The Indico plugins are free software; you can redistribute
|
||||
// them and/or modify them under the terms of the MIT License;
|
||||
// see the LICENSE file for more details.
|
||||
|
||||
$(function() {
|
||||
$('.vc-toolbar').dropdown({
|
||||
positioning: {
|
||||
level1: {my: 'right top', at: 'right bottom', offset: '0px 0px'},
|
||||
},
|
||||
});
|
||||
|
||||
$('.vc-toolbar .action-make-owner').click(function() {
|
||||
const $this = $(this);
|
||||
|
||||
$.ajax({
|
||||
url: $this.data('href'),
|
||||
method: 'POST',
|
||||
complete: IndicoUI.Dialogs.Util.progress(),
|
||||
})
|
||||
.done(function(result) {
|
||||
if (handleAjaxError(result)) {
|
||||
return;
|
||||
} else {
|
||||
location.reload();
|
||||
}
|
||||
})
|
||||
.fail(function(error) {
|
||||
handleAjaxError(error);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,29 +0,0 @@
|
||||
# This file is part of the Indico plugins.
|
||||
# Copyright (C) 2002 - 2021 CERN
|
||||
#
|
||||
# The Indico plugins are free software; you can redistribute
|
||||
# them and/or modify them under the terms of the MIT License;
|
||||
# see the LICENSE file for more details.
|
||||
|
||||
from flask import flash, jsonify, session
|
||||
|
||||
from indico.core.db import db
|
||||
from indico.modules.vc.controllers import RHVCSystemEventBase
|
||||
from indico.modules.vc.exceptions import VCRoomError
|
||||
from indico.util.i18n import _
|
||||
|
||||
|
||||
class RHVidyoRoomOwner(RHVCSystemEventBase):
|
||||
def _process(self):
|
||||
result = {}
|
||||
self.vc_room.vidyo_extension.owned_by_user = session.user
|
||||
try:
|
||||
self.plugin.update_room(self.vc_room, self.event)
|
||||
except VCRoomError as err:
|
||||
result['error'] = {'message': err.message}
|
||||
result['success'] = False
|
||||
db.session.rollback()
|
||||
else:
|
||||
flash(_("You are now the owner of the room '{room}'").format(room=self.vc_room.name), 'success')
|
||||
result['success'] = True
|
||||
return jsonify(result)
|
||||
@ -1,73 +0,0 @@
|
||||
# This file is part of the Indico plugins.
|
||||
# Copyright (C) 2002 - 2021 CERN
|
||||
#
|
||||
# The Indico plugins are free software; you can redistribute
|
||||
# them and/or modify them under the terms of the MIT License;
|
||||
# see the LICENSE file for more details.
|
||||
|
||||
from wtforms.fields.core import BooleanField
|
||||
from wtforms.fields.simple import TextAreaField
|
||||
from wtforms.validators import DataRequired, Length, Optional, Regexp, ValidationError
|
||||
|
||||
from indico.modules.vc.forms import VCRoomAttachFormBase, VCRoomFormBase
|
||||
from indico.web.forms.base import generated_data
|
||||
from indico.web.forms.fields import IndicoPasswordField, PrincipalField
|
||||
from indico.web.forms.widgets import SwitchWidget
|
||||
|
||||
from indico_vc_vidyo import _
|
||||
from indico_vc_vidyo.util import iter_user_identities, retrieve_principal
|
||||
|
||||
|
||||
PIN_VALIDATORS = [Optional(), Length(min=3, max=10), Regexp(r'^\d+$', message=_("The PIN must be a number"))]
|
||||
|
||||
|
||||
class VidyoAdvancedFormMixin:
|
||||
# Advanced options (per event)
|
||||
show_pin = BooleanField(_('Show PIN'),
|
||||
widget=SwitchWidget(),
|
||||
description=_("Show the VC Room PIN on the event page (insecure!)"))
|
||||
show_autojoin = BooleanField(_('Show Auto-join URL'),
|
||||
widget=SwitchWidget(),
|
||||
description=_("Show the auto-join URL on the event page"))
|
||||
show_phone_numbers = BooleanField(_('Show Phone Access numbers'),
|
||||
widget=SwitchWidget(),
|
||||
description=_("Show a link to the list of phone access numbers"))
|
||||
|
||||
|
||||
class VCRoomAttachForm(VCRoomAttachFormBase, VidyoAdvancedFormMixin):
|
||||
pass
|
||||
|
||||
|
||||
class VCRoomForm(VCRoomFormBase, VidyoAdvancedFormMixin):
|
||||
"""Contains all information concerning a Vidyo booking"""
|
||||
|
||||
advanced_fields = {'show_pin', 'show_autojoin', 'show_phone_numbers'} | VCRoomFormBase.advanced_fields
|
||||
skip_fields = advanced_fields | VCRoomFormBase.conditional_fields
|
||||
|
||||
description = TextAreaField(_('Description'), [DataRequired()], description=_('The description of the room'))
|
||||
owner_user = PrincipalField(_('Owner'), [DataRequired()], description=_('The owner of the room'))
|
||||
moderation_pin = IndicoPasswordField(_('Moderation PIN'), PIN_VALIDATORS, toggle=True,
|
||||
description=_('Used to moderate the VC Room. Only digits allowed.'))
|
||||
room_pin = IndicoPasswordField(_('Room PIN'), PIN_VALIDATORS, toggle=True,
|
||||
description=_('Used to protect the access to the VC Room (leave blank for open '
|
||||
'access). Only digits allowed.'))
|
||||
auto_mute = BooleanField(_('Auto mute'),
|
||||
widget=SwitchWidget(),
|
||||
description=_('The VidyoDesktop clients will join the VC room muted by default '
|
||||
'(audio and video)'))
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
defaults = kwargs['obj']
|
||||
if defaults.owner_user is None and defaults.owner is not None:
|
||||
defaults.owner_user = retrieve_principal(defaults.owner)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
@generated_data
|
||||
def owner(self):
|
||||
return self.owner_user.data.as_principal
|
||||
|
||||
def validate_owner_user(self, field):
|
||||
if not field.data:
|
||||
raise ValidationError(_("Unable to find this user in Indico."))
|
||||
if not next(iter_user_identities(field.data), None):
|
||||
raise ValidationError(_("This user does not have a suitable account to use Vidyo."))
|
||||
@ -1,56 +0,0 @@
|
||||
# This file is part of the Indico plugins.
|
||||
# Copyright (C) 2002 - 2021 CERN
|
||||
#
|
||||
# The Indico plugins are free software; you can redistribute
|
||||
# them and/or modify them under the terms of the MIT License;
|
||||
# see the LICENSE file for more details.
|
||||
|
||||
from flask import request
|
||||
|
||||
from indico.modules.vc.models.vc_rooms import VCRoom, VCRoomStatus
|
||||
from indico.web.http_api.hooks.base import HTTPAPIHook
|
||||
|
||||
|
||||
class DeleteVCRoomAPI(HTTPAPIHook):
|
||||
PREFIX = 'api'
|
||||
TYPES = ('deletevcroom',)
|
||||
RE = r'vidyo'
|
||||
GUEST_ALLOWED = False
|
||||
VALID_FORMATS = ('json',)
|
||||
COMMIT = True
|
||||
HTTP_POST = True
|
||||
|
||||
def _has_access(self, user):
|
||||
from indico_vc_vidyo.plugin import VidyoPlugin
|
||||
return user in VidyoPlugin.settings.acls.get('managers')
|
||||
|
||||
def _getParams(self):
|
||||
super()._getParams()
|
||||
self._room_ids = list(map(int, request.form.getlist('rid')))
|
||||
|
||||
def api_deletevcroom(self, user):
|
||||
from indico_vc_vidyo.api import APIException
|
||||
from indico_vc_vidyo.plugin import VidyoPlugin
|
||||
|
||||
success = []
|
||||
failed = []
|
||||
not_in_db = []
|
||||
|
||||
for rid in self._room_ids:
|
||||
room = VCRoom.query.filter(VCRoom.type == 'vidyo',
|
||||
VCRoom.status == VCRoomStatus.created,
|
||||
VCRoom.data.contains({'vidyo_id': str(rid)})).first()
|
||||
if not room:
|
||||
not_in_db.append(rid)
|
||||
continue
|
||||
try:
|
||||
room.plugin.delete_room(room, None)
|
||||
except APIException:
|
||||
failed.append(rid)
|
||||
VidyoPlugin.logger.exception('Could not delete VC room %s', room)
|
||||
else:
|
||||
room.status = VCRoomStatus.deleted
|
||||
success.append(rid)
|
||||
VidyoPlugin.logger.info('%s deleted', room)
|
||||
|
||||
return {'success': success, 'failed': failed, 'missing': not_in_db}
|
||||
@ -1,34 +0,0 @@
|
||||
"""Create tables
|
||||
|
||||
Revision ID: 6019621fea50
|
||||
Revises:
|
||||
Create Date: 2017-06-30 16:11:31.486845
|
||||
"""
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
from sqlalchemy.sql.ddl import CreateSchema, DropSchema
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '6019621fea50'
|
||||
down_revision = None
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.execute(CreateSchema('plugin_vc_vidyo'))
|
||||
op.create_table('vidyo_extensions',
|
||||
sa.Column('vc_room_id', sa.Integer(), nullable=False),
|
||||
sa.Column('extension', sa.BigInteger(), nullable=True, index=True),
|
||||
sa.Column('owned_by_id', sa.Integer(), nullable=False, index=True),
|
||||
sa.ForeignKeyConstraint(['owned_by_id'], ['users.users.id']),
|
||||
sa.ForeignKeyConstraint(['vc_room_id'], ['events.vc_rooms.id']),
|
||||
sa.PrimaryKeyConstraint('vc_room_id'),
|
||||
schema='plugin_vc_vidyo')
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_table('vidyo_extensions', schema='plugin_vc_vidyo')
|
||||
op.execute(DropSchema('plugin_vc_vidyo'))
|
||||
@ -1,74 +0,0 @@
|
||||
# This file is part of the Indico plugins.
|
||||
# Copyright (C) 2002 - 2021 CERN
|
||||
#
|
||||
# The Indico plugins are free software; you can redistribute
|
||||
# them and/or modify them under the terms of the MIT License;
|
||||
# see the LICENSE file for more details.
|
||||
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from sqlalchemy.event import listens_for
|
||||
from sqlalchemy.orm.attributes import flag_modified
|
||||
|
||||
from indico.core.db.sqlalchemy import db
|
||||
|
||||
|
||||
class VidyoExtension(db.Model):
|
||||
__tablename__ = 'vidyo_extensions'
|
||||
__table_args__ = {'schema': 'plugin_vc_vidyo'}
|
||||
|
||||
#: ID of the videoconference room
|
||||
vc_room_id = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey('events.vc_rooms.id'),
|
||||
primary_key=True
|
||||
)
|
||||
extension = db.Column(
|
||||
db.BigInteger,
|
||||
index=True
|
||||
)
|
||||
owned_by_id = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey('users.users.id'),
|
||||
index=True,
|
||||
nullable=False
|
||||
)
|
||||
vc_room = db.relationship(
|
||||
'VCRoom',
|
||||
lazy=False,
|
||||
backref=db.backref(
|
||||
'vidyo_extension',
|
||||
cascade='all, delete-orphan',
|
||||
uselist=False,
|
||||
lazy=False
|
||||
)
|
||||
)
|
||||
|
||||
#: The user who owns the Vidyo room
|
||||
owned_by_user = db.relationship(
|
||||
'User',
|
||||
lazy=True,
|
||||
backref=db.backref(
|
||||
'vc_rooms_vidyo',
|
||||
lazy='dynamic'
|
||||
)
|
||||
)
|
||||
|
||||
@property
|
||||
def join_url(self):
|
||||
from indico_vc_vidyo.plugin import VidyoPlugin
|
||||
url = self.vc_room.data['url']
|
||||
custom_url_tpl = VidyoPlugin.settings.get('client_chooser_url')
|
||||
if custom_url_tpl:
|
||||
return custom_url_tpl + '?' + urlencode({'url': url})
|
||||
return url
|
||||
|
||||
def __repr__(self):
|
||||
return f'<VidyoExtension({self.vc_room}, {self.extension}, {self.owned_by_user})>'
|
||||
|
||||
|
||||
@listens_for(VidyoExtension.owned_by_user, 'set')
|
||||
def _owned_by_user_set(target, user, *unused):
|
||||
if target.vc_room and user.as_principal != tuple(target.vc_room.data['owner']):
|
||||
target.vc_room.data['owner'] = user.as_principal
|
||||
flag_modified(target.vc_room, 'data')
|
||||
@ -1,330 +0,0 @@
|
||||
# This file is part of the Indico plugins.
|
||||
# Copyright (C) 2002 - 2021 CERN
|
||||
#
|
||||
# The Indico plugins are free software; you can redistribute
|
||||
# them and/or modify them under the terms of the MIT License;
|
||||
# see the LICENSE file for more details.
|
||||
|
||||
from flask import session
|
||||
from sqlalchemy.orm.attributes import flag_modified
|
||||
from wtforms.fields import IntegerField, TextAreaField
|
||||
from wtforms.fields.html5 import EmailField, URLField
|
||||
from wtforms.fields.simple import StringField
|
||||
from wtforms.validators import DataRequired, NumberRange
|
||||
|
||||
from indico.core import signals
|
||||
from indico.core.auth import multipass
|
||||
from indico.core.config import config
|
||||
from indico.core.plugins import IndicoPlugin, url_for_plugin
|
||||
from indico.modules.events.views import WPSimpleEventDisplay
|
||||
from indico.modules.vc import VCPluginMixin, VCPluginSettingsFormBase
|
||||
from indico.modules.vc.exceptions import VCRoomError, VCRoomNotFoundError
|
||||
from indico.modules.vc.views import WPVCEventPage, WPVCManageEvent
|
||||
from indico.web.forms.fields import IndicoPasswordField
|
||||
from indico.web.forms.widgets import CKEditorWidget
|
||||
from indico.web.http_api.hooks.base import HTTPAPIHook
|
||||
|
||||
from indico_vc_vidyo import _
|
||||
from indico_vc_vidyo.api import AdminClient, APIException, RoomNotFoundAPIException
|
||||
from indico_vc_vidyo.blueprint import blueprint
|
||||
from indico_vc_vidyo.cli import cli
|
||||
from indico_vc_vidyo.forms import VCRoomAttachForm, VCRoomForm
|
||||
from indico_vc_vidyo.http_api import DeleteVCRoomAPI
|
||||
from indico_vc_vidyo.models.vidyo_extensions import VidyoExtension
|
||||
from indico_vc_vidyo.util import iter_extensions, iter_user_identities, retrieve_principal, update_room_from_obj
|
||||
|
||||
|
||||
class PluginSettingsForm(VCPluginSettingsFormBase):
|
||||
support_email = EmailField(_('Vidyo email support'))
|
||||
username = StringField(_('Username'), [DataRequired()], description=_('Indico username for Vidyo'))
|
||||
password = IndicoPasswordField(_('Password'), [DataRequired()], toggle=True,
|
||||
description=_('Indico password for Vidyo'))
|
||||
admin_api_wsdl = URLField(_('Admin API WSDL URL'), [DataRequired()])
|
||||
user_api_wsdl = URLField(_('User API WSDL URL'), [DataRequired()])
|
||||
indico_room_prefix = IntegerField(_('Indico tenant prefix'), [NumberRange(min=0)],
|
||||
description=_('The tenant prefix for Indico rooms created on this server'))
|
||||
room_group_name = StringField(_("Public rooms' group name"), [DataRequired()],
|
||||
description=_('Group name for public videoconference rooms created by Indico'))
|
||||
authenticators = StringField(_('Authenticators'), [DataRequired()],
|
||||
description=_('Identity providers to convert Indico users to Vidyo accounts'))
|
||||
num_days_old = IntegerField(_('VC room age threshold'), [NumberRange(min=1), DataRequired()],
|
||||
description=_('Number of days after an Indico event when a videoconference room is '
|
||||
'considered old'))
|
||||
max_rooms_warning = IntegerField(_('Max. num. VC rooms before warning'), [NumberRange(min=1), DataRequired()],
|
||||
description=_('Maximum number of rooms until a warning is sent to the managers'))
|
||||
vidyo_phone_link = URLField(_('VidyoVoice phone number'),
|
||||
description=_('Link to the list of VidyoVoice phone numbers'))
|
||||
client_chooser_url = URLField(_('Client Chooser URL'),
|
||||
description=_("URL for client chooser interface. The room key will be passed as a "
|
||||
"'url' GET query argument"))
|
||||
creation_email_footer = TextAreaField(_('Creation email footer'), widget=CKEditorWidget(),
|
||||
description=_('Footer to append to emails sent upon creation of a VC room'))
|
||||
|
||||
|
||||
class VidyoPlugin(VCPluginMixin, IndicoPlugin):
|
||||
"""Vidyo
|
||||
|
||||
Videoconferencing with Vidyo
|
||||
"""
|
||||
configurable = True
|
||||
settings_form = PluginSettingsForm
|
||||
vc_room_form = VCRoomForm
|
||||
vc_room_attach_form = VCRoomAttachForm
|
||||
friendly_name = 'Vidyo'
|
||||
|
||||
def init(self):
|
||||
super().init()
|
||||
self.connect(signals.plugin.cli, self._extend_indico_cli)
|
||||
self.inject_bundle('main.js', WPSimpleEventDisplay)
|
||||
self.inject_bundle('main.js', WPVCEventPage)
|
||||
self.inject_bundle('main.js', WPVCManageEvent)
|
||||
HTTPAPIHook.register(DeleteVCRoomAPI)
|
||||
|
||||
@property
|
||||
def default_settings(self):
|
||||
return dict(VCPluginMixin.default_settings, **{
|
||||
'support_email': config.SUPPORT_EMAIL,
|
||||
'username': 'indico',
|
||||
'password': None,
|
||||
'admin_api_wsdl': 'https://yourvidyoportal/services/v1_1/VidyoPortalAdminService?wsdl',
|
||||
'user_api_wsdl': 'https://yourvidyoportal/services/v1_1/VidyoPortalUserService?wsdl',
|
||||
'indico_room_prefix': 10,
|
||||
'room_group_name': 'Indico',
|
||||
# we skip identity providers in the default list if they don't support get_identity.
|
||||
# these providers (local accounts, oauth) are unlikely be the correct ones to integrate
|
||||
# with the vidyo infrastructure.
|
||||
'authenticators': ', '.join(p.name for p in multipass.identity_providers.values() if p.supports_get),
|
||||
'num_days_old': 365,
|
||||
'max_rooms_warning': 5000,
|
||||
'vidyo_phone_link': None,
|
||||
'creation_email_footer': None,
|
||||
'client_chooser_url': None
|
||||
})
|
||||
|
||||
@property
|
||||
def logo_url(self):
|
||||
return url_for_plugin(self.name + '.static', filename='images/logo.png')
|
||||
|
||||
@property
|
||||
def icon_url(self):
|
||||
return url_for_plugin(self.name + '.static', filename='images/vidyo_logo_notext.png')
|
||||
|
||||
def _extend_indico_cli(self, sender, **kwargs):
|
||||
return cli
|
||||
|
||||
def update_data_association(self, event, vc_room, event_vc_room, data):
|
||||
super().update_data_association(event, vc_room, event_vc_room, data)
|
||||
|
||||
event_vc_room.data.update({key: data.pop(key) for key in [
|
||||
'show_pin',
|
||||
'show_autojoin',
|
||||
'show_phone_numbers'
|
||||
]})
|
||||
|
||||
flag_modified(event_vc_room, 'data')
|
||||
|
||||
def update_data_vc_room(self, vc_room, data, is_new=False):
|
||||
super().update_data_vc_room(vc_room, data, is_new=is_new)
|
||||
|
||||
for key in ['description', 'owner', 'room_pin', 'moderation_pin', 'auto_mute']:
|
||||
if key in data:
|
||||
vc_room.data[key] = data.pop(key)
|
||||
|
||||
flag_modified(vc_room, 'data')
|
||||
|
||||
def create_room(self, vc_room, event):
|
||||
"""Create a new Vidyo room for an event, given a VC room.
|
||||
|
||||
In order to create the Vidyo room, the function will try to do so with
|
||||
all the available identities of the user based on the authenticators
|
||||
defined in Vidyo plugin's settings, in that order.
|
||||
|
||||
:param vc_room: VCRoom -- The VC room from which to create the Vidyo
|
||||
room
|
||||
:param event: Event -- The event to the Vidyo room will be attached
|
||||
"""
|
||||
client = AdminClient(self.settings)
|
||||
owner = retrieve_principal(vc_room.data['owner'])
|
||||
login_gen = iter_user_identities(owner)
|
||||
login = next(login_gen, None)
|
||||
if login is None:
|
||||
raise VCRoomError(_("No valid Vidyo account found for this user"), field='owner_user')
|
||||
|
||||
extension_gen = iter_extensions(self.settings.get('indico_room_prefix'), event.id)
|
||||
extension = next(extension_gen)
|
||||
|
||||
while True:
|
||||
room_mode = {
|
||||
'isLocked': False,
|
||||
'hasPIN': bool(vc_room.data['room_pin']),
|
||||
'hasModeratorPIN': bool(vc_room.data['moderation_pin'])
|
||||
}
|
||||
if room_mode['hasPIN']:
|
||||
room_mode['roomPIN'] = vc_room.data['room_pin']
|
||||
if room_mode['hasModeratorPIN']:
|
||||
room_mode['moderatorPIN'] = vc_room.data['moderation_pin']
|
||||
|
||||
room_obj = client.create_room_object(
|
||||
name=vc_room.name,
|
||||
RoomType='Public',
|
||||
ownerName=login,
|
||||
extension=extension,
|
||||
groupName=self.settings.get('room_group_name'),
|
||||
description=vc_room.data['description'],
|
||||
RoomMode=room_mode)
|
||||
|
||||
if room_obj.RoomMode.hasPIN:
|
||||
room_obj.RoomMode.roomPIN = vc_room.data['room_pin']
|
||||
if room_obj.RoomMode.hasModeratorPIN:
|
||||
room_obj.RoomMode.moderatorPIN = vc_room.data['moderation_pin']
|
||||
|
||||
try:
|
||||
client.add_room(room_obj)
|
||||
except APIException as err:
|
||||
err_msg = err.message
|
||||
|
||||
if err_msg.startswith('Room exist for name'):
|
||||
raise VCRoomError(_("Room name already in use"), field='name')
|
||||
elif err_msg.startswith('Member not found for ownerName'):
|
||||
login = next(login_gen, None)
|
||||
if login is None:
|
||||
raise VCRoomError(_("No valid Vidyo account found for this user"), field='owner_user')
|
||||
elif err_msg.startswith('Room exist for extension'):
|
||||
extension = next(extension_gen)
|
||||
else:
|
||||
raise
|
||||
|
||||
else:
|
||||
# get room back, in order to fetch Vidyo-set parameters
|
||||
created_room = client.find_room(extension)
|
||||
|
||||
if not created_room:
|
||||
raise VCRoomNotFoundError(_("Could not find newly created room in Vidyo"))
|
||||
vc_room.data.update({
|
||||
'vidyo_id': str(created_room.roomID),
|
||||
'url': created_room.RoomMode.roomURL,
|
||||
'owner_identity': created_room.ownerName
|
||||
})
|
||||
flag_modified(vc_room, 'data')
|
||||
vc_room.vidyo_extension = VidyoExtension(vc_room_id=vc_room.id, extension=int(created_room.extension),
|
||||
owned_by_user=owner)
|
||||
|
||||
client.set_automute(created_room.roomID, vc_room.data['auto_mute'])
|
||||
break
|
||||
|
||||
def update_room(self, vc_room, event):
|
||||
client = AdminClient(self.settings)
|
||||
|
||||
try:
|
||||
room_obj = self.get_room(vc_room)
|
||||
except RoomNotFoundAPIException:
|
||||
raise VCRoomNotFoundError(_("This room has been deleted from Vidyo"))
|
||||
|
||||
owner = retrieve_principal(vc_room.data['owner'])
|
||||
changed_owner = room_obj.ownerName not in iter_user_identities(owner)
|
||||
if changed_owner:
|
||||
login_gen = iter_user_identities(owner)
|
||||
login = next(login_gen, None)
|
||||
if login is None:
|
||||
raise VCRoomError(_("No valid Vidyo account found for this user"), field='owner_user')
|
||||
room_obj.ownerName = login
|
||||
|
||||
room_obj.name = vc_room.name
|
||||
room_obj.description = vc_room.data['description']
|
||||
|
||||
room_obj.RoomMode.hasPIN = bool(vc_room.data['room_pin'])
|
||||
room_obj.RoomMode.hasModeratorPIN = bool(vc_room.data['moderation_pin'])
|
||||
|
||||
if room_obj.RoomMode.hasPIN:
|
||||
room_obj.RoomMode.roomPIN = vc_room.data['room_pin']
|
||||
if room_obj.RoomMode.hasModeratorPIN:
|
||||
room_obj.RoomMode.moderatorPIN = vc_room.data['moderation_pin']
|
||||
|
||||
vidyo_id = vc_room.data['vidyo_id']
|
||||
while True:
|
||||
try:
|
||||
client.update_room(vidyo_id, room_obj)
|
||||
except RoomNotFoundAPIException:
|
||||
raise VCRoomNotFoundError(_("This room has been deleted from Vidyo"))
|
||||
except APIException as err:
|
||||
err_msg = err.message
|
||||
if err_msg.startswith('Room exist for name'):
|
||||
raise VCRoomError(_("Room name already in use"), field='name')
|
||||
|
||||
elif err_msg.startswith('Member not found for ownerName'):
|
||||
if changed_owner:
|
||||
login = next(login_gen, None)
|
||||
if not changed_owner or login is None:
|
||||
raise VCRoomError(_("No valid Vidyo account found for this user"), field='owner_user')
|
||||
room_obj.ownerName = login
|
||||
|
||||
else:
|
||||
raise
|
||||
else:
|
||||
updated_room_obj = self.get_room(vc_room)
|
||||
|
||||
update_room_from_obj(self.settings, vc_room, updated_room_obj)
|
||||
flag_modified(vc_room, 'data')
|
||||
|
||||
client.set_automute(vidyo_id, vc_room.data['auto_mute'])
|
||||
break
|
||||
|
||||
def refresh_room(self, vc_room, event):
|
||||
client = AdminClient(self.settings)
|
||||
try:
|
||||
room_obj = self.get_room(vc_room)
|
||||
except RoomNotFoundAPIException:
|
||||
raise VCRoomNotFoundError(_("This room has been deleted from Vidyo"))
|
||||
|
||||
update_room_from_obj(self.settings, vc_room, room_obj)
|
||||
vc_room.data['auto_mute'] = client.get_automute(room_obj.roomID)
|
||||
flag_modified(vc_room, 'data')
|
||||
|
||||
def delete_room(self, vc_room, event):
|
||||
client = AdminClient(self.settings)
|
||||
|
||||
vidyo_id = vc_room.data['vidyo_id']
|
||||
try:
|
||||
client.delete_room(vidyo_id)
|
||||
except RoomNotFoundAPIException:
|
||||
pass
|
||||
|
||||
def get_room(self, vc_room):
|
||||
client = AdminClient(self.settings)
|
||||
return client.get_room(vc_room.data['vidyo_id'])
|
||||
|
||||
def get_blueprints(self):
|
||||
return blueprint
|
||||
|
||||
def get_vc_room_form_defaults(self, event):
|
||||
defaults = super().get_vc_room_form_defaults(event)
|
||||
defaults.update({
|
||||
'auto_mute': True,
|
||||
'show_pin': False,
|
||||
'show_autojoin': True,
|
||||
'show_phone_numbers': True,
|
||||
'owner_user': session.user
|
||||
})
|
||||
|
||||
return defaults
|
||||
|
||||
def get_vc_room_attach_form_defaults(self, event):
|
||||
defaults = super().get_vc_room_attach_form_defaults(event)
|
||||
defaults.update({
|
||||
'show_pin': False,
|
||||
'show_autojoin': True,
|
||||
'show_phone_numbers': True
|
||||
})
|
||||
return defaults
|
||||
|
||||
def can_manage_vc_room(self, user, room):
|
||||
return user == room.vidyo_extension.owned_by_user or super().can_manage_vc_room(user, room)
|
||||
|
||||
def _merge_users(self, target, source, **kwargs):
|
||||
super()._merge_users(target, source, **kwargs)
|
||||
for ext in VidyoExtension.query.filter_by(owned_by_user=source):
|
||||
ext.owned_by_user = target
|
||||
flag_modified(ext.vc_room, 'data')
|
||||
|
||||
def get_notification_cc_list(self, action, vc_room, event):
|
||||
return {vc_room.vidyo_extension.owned_by_user.email}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.8 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.1 KiB |
@ -1,73 +0,0 @@
|
||||
# This file is part of the Indico plugins.
|
||||
# Copyright (C) 2002 - 2021 CERN
|
||||
#
|
||||
# The Indico plugins are free software; you can redistribute
|
||||
# them and/or modify them under the terms of the MIT License;
|
||||
# see the LICENSE file for more details.
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
from celery.schedules import crontab
|
||||
|
||||
from indico.core.celery import celery
|
||||
from indico.core.db import db
|
||||
from indico.core.plugins import get_plugin_template_module
|
||||
from indico.modules.events import Event
|
||||
from indico.modules.vc.models.vc_rooms import VCRoom, VCRoomEventAssociation, VCRoomStatus
|
||||
from indico.modules.vc.notifications import _send
|
||||
from indico.util.date_time import now_utc
|
||||
from indico.util.iterables import committing_iterator
|
||||
|
||||
from indico_vc_vidyo.api import APIException, RoomNotFoundAPIException
|
||||
|
||||
|
||||
def find_old_vidyo_rooms(max_room_event_age):
|
||||
"""Finds all Vidyo rooms that are:
|
||||
- linked to no events
|
||||
- linked only to events whose start date precedes today - max_room_event_age days
|
||||
"""
|
||||
recently_used = (db.session.query(VCRoom.id)
|
||||
.filter(VCRoom.type == 'vidyo',
|
||||
Event.end_dt > (now_utc() - timedelta(days=max_room_event_age)))
|
||||
.join(VCRoom.events)
|
||||
.join(VCRoomEventAssociation.event)
|
||||
.group_by(VCRoom.id))
|
||||
|
||||
# non-deleted rooms with no recent associations
|
||||
return VCRoom.query.filter(VCRoom.status != VCRoomStatus.deleted, ~VCRoom.id.in_(recently_used)).all()
|
||||
|
||||
|
||||
def notify_owner(plugin, vc_room):
|
||||
"""Notifies about the deletion of a Vidyo room from the Vidyo server."""
|
||||
user = vc_room.vidyo_extension.owned_by_user
|
||||
tpl = get_plugin_template_module('emails/remote_deleted.html', plugin=plugin, vc_room=vc_room, event=None,
|
||||
vc_room_event=None, user=user)
|
||||
_send('delete', user, plugin, None, vc_room, tpl)
|
||||
|
||||
|
||||
@celery.periodic_task(run_every=crontab(minute='0', hour='3', day_of_week='monday'), plugin='vc_vidyo')
|
||||
def vidyo_cleanup(dry_run=False):
|
||||
from indico_vc_vidyo.plugin import VidyoPlugin
|
||||
max_room_event_age = VidyoPlugin.settings.get('num_days_old')
|
||||
|
||||
VidyoPlugin.logger.info('Deleting Vidyo rooms that are not used or linked to events all older than %d days',
|
||||
max_room_event_age)
|
||||
candidate_rooms = find_old_vidyo_rooms(max_room_event_age)
|
||||
VidyoPlugin.logger.info('%d rooms found', len(candidate_rooms))
|
||||
|
||||
if dry_run:
|
||||
for vc_room in candidate_rooms:
|
||||
VidyoPlugin.logger.info('Would delete Vidyo room %s from server', vc_room)
|
||||
return
|
||||
|
||||
for vc_room in committing_iterator(candidate_rooms, n=20):
|
||||
try:
|
||||
VidyoPlugin.instance.delete_room(vc_room, None)
|
||||
VidyoPlugin.logger.info('Room %s deleted from Vidyo server', vc_room)
|
||||
notify_owner(VidyoPlugin.instance, vc_room)
|
||||
vc_room.status = VCRoomStatus.deleted
|
||||
except RoomNotFoundAPIException:
|
||||
VidyoPlugin.logger.warning('Room %s had been already deleted from the Vidyo server', vc_room)
|
||||
vc_room.status = VCRoomStatus.deleted
|
||||
except APIException:
|
||||
VidyoPlugin.logger.exception('Impossible to delete Vidyo room %s', vc_room)
|
||||
@ -1,21 +0,0 @@
|
||||
{% macro render_make_me_owner(event, vc_room, event_vc_room, extra_classes='') %}
|
||||
{% if session.user != vc_room.vidyo_extension.owned_by_user and event.can_manage(session.user) %}
|
||||
<a class="i-button highlight arrow {{ extra_classes }}" data-toggle="dropdown"></a>
|
||||
<ul class="i-dropdown" data-level="level1">
|
||||
<li>
|
||||
<a href="#"
|
||||
title="{% trans name=vc_room.data.owner_identity %}You will be the owner of this Vidyo room, replacing {{name}}.{% endtrans %}"
|
||||
class="action-make-owner" data-href="{{ url_for_plugin('vc_vidyo.set_room_owner', event_vc_room) }}">
|
||||
{% trans %}Make me owner{% endtrans %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_join_button(vc_room, extra_classes="") %}
|
||||
<a class="i-button highlight {{ extra_classes }}"
|
||||
href="{{ vc_room.vidyo_extension.join_url }}" target="_blank">
|
||||
{% trans %}Join{% endtrans %}
|
||||
</a>
|
||||
{% endmacro %}
|
||||
@ -1,16 +0,0 @@
|
||||
{% extends 'vc/emails/created.html' %}
|
||||
|
||||
{% block plugin_specific_info %}
|
||||
<li>
|
||||
<strong>Auto-join URL</strong>:
|
||||
<a href="{{ vc_room.vidyo_extension.join_url }}">{{ vc_room.vidyo_extension.join_url }}</a>
|
||||
</li>
|
||||
<li><strong>Owner:</strong> {{ vc_room.data.owner_identity }}</li>
|
||||
{% endblock %}
|
||||
|
||||
{% block custom_footer %}
|
||||
{% if plugin.settings.get('creation_email_footer') %}
|
||||
<hr>
|
||||
{{ plugin.settings.get('creation_email_footer') | sanitize_html }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@ -1 +0,0 @@
|
||||
{% extends 'vc/emails/deleted.html' %}
|
||||
@ -1,16 +0,0 @@
|
||||
{% extends 'emails/base.html' %}
|
||||
|
||||
{% block subject -%}
|
||||
[{{ plugin.friendly_name }}] Room deleted from server: {{ vc_room.name }}
|
||||
{%- endblock %}
|
||||
|
||||
{% block header -%}
|
||||
<p>
|
||||
The Vidyo room "{{ vc_room.name }}" has been deleted from the Vidyo server since it has not been used by any recent event.
|
||||
</p>
|
||||
<p>
|
||||
You won't be able to attach it to any future events. If you need to do so, please create a new room.
|
||||
</p>
|
||||
{% block custom_footer %}{% endblock %}
|
||||
|
||||
{%- endblock %}
|
||||
@ -1,7 +0,0 @@
|
||||
{% extends 'vc/event_buttons.html' %}
|
||||
{% from 'vc_vidyo:buttons.html' import render_join_button, render_make_me_owner %}
|
||||
|
||||
{% block buttons %}
|
||||
{{ render_join_button(vc_room, "i-button-small event-service-right-button join-button") }}
|
||||
{{ render_make_me_owner(event, vc_room, event_vc_room, extra_classes="i-button-small") }}
|
||||
{% endblock %}
|
||||
@ -1,37 +0,0 @@
|
||||
{% from '_clipboard_input.html' import clipboard_input %}
|
||||
{% set owner = vc_room.vidyo_extension.owned_by_user %}
|
||||
{% set phone_link = settings.get('vidyo_phone_link') %}
|
||||
<dl>
|
||||
<dt>{% trans %}Name{% endtrans %}</dt>
|
||||
<dd>{{ vc_room.name }}</dd>
|
||||
<dt>{% trans %}Description{% endtrans %}</dt>
|
||||
<dd>{{ vc_room.data.description }}</dd>
|
||||
{% if vc_room.vidyo_extension %}
|
||||
<dt>{% trans %}Extension{% endtrans %}</dt>
|
||||
<dd>{{ vc_room.vidyo_extension.extension }}</dd>
|
||||
{% endif %}
|
||||
{% if owner %}
|
||||
<dt>{% trans %}Owner{% endtrans %}</dt>
|
||||
<dd>{{ owner.full_name }}</dd>
|
||||
{% endif %}
|
||||
{% if event_vc_room.data.show_pin and vc_room.data.room_pin %}
|
||||
<dt>{% trans %}Room PIN{% endtrans %}</dt>
|
||||
<dd>{{ vc_room.data.room_pin }}</dd>
|
||||
{% endif %}
|
||||
{% if event_vc_room.data.show_autojoin %}
|
||||
<dt class="large-row">{% trans %}Auto-join URL{% endtrans %}</dt>
|
||||
<dd class="large-row">
|
||||
{{ clipboard_input(vc_room.vidyo_extension.join_url, name="vc-room-url-%s"|format(event_vc_room.id)) }}
|
||||
</dd>
|
||||
{% endif %}
|
||||
{% if event_vc_room.data.show_phone_numbers and phone_link %}
|
||||
<dt>
|
||||
{% trans %}Useful links{% endtrans %}
|
||||
</dt>
|
||||
<dd>
|
||||
<a href="{{ phone_link }}" target="_blank">
|
||||
{% trans %}Phone numbers{% endtrans %}
|
||||
</a>
|
||||
</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
@ -1,55 +0,0 @@
|
||||
{% from '_password.html' import password %}
|
||||
{% from '_clipboard_input.html' import clipboard_input %}
|
||||
{% set owner = vc_room.vidyo_extension.owned_by_user %}
|
||||
{% set phone_link = settings.get('vidyo_phone_link') %}
|
||||
<dl class="details-container">
|
||||
<dt>{% trans %}Description{% endtrans %}</dt>
|
||||
<dd>{{ vc_room.data.description }}</dd>
|
||||
<dt>{% trans %}Extension{% endtrans %}</dt>
|
||||
<dd>{{ vc_room.vidyo_extension.extension }}</dd>
|
||||
<dt>{% trans %}Owner{% endtrans %}</dt>
|
||||
<dd>
|
||||
{% if owner %}
|
||||
{{ owner.full_name }}
|
||||
{% else %}
|
||||
{{ vc_room.data.owner_account }} <em>(deleted)</em>
|
||||
{% endif %}
|
||||
</dd>
|
||||
<dt>{% trans %}Linked to{% endtrans %}</dt>
|
||||
<dd>
|
||||
{% set obj = event_vc_room.link_object %}
|
||||
{% if obj is none %}
|
||||
<em>(missing {{ event_vc_room.link_type.name }})</em>
|
||||
{% elif event_vc_room.link_type.name == 'event' %}
|
||||
{% trans %}the whole event{% endtrans %}
|
||||
{% elif event_vc_room.link_type.name == 'contribution' %}
|
||||
{% trans %}Contribution{% endtrans %}: {{ obj.title }}
|
||||
{% elif event_vc_room.link_type.name == 'block' %}
|
||||
{% trans %}Session{% endtrans %}: {{ obj.full_title }}
|
||||
{% endif %}
|
||||
</dd>
|
||||
{% if vc_room.data.room_pin %}
|
||||
<dt>{% trans %}Room PIN{% endtrans %}</dt>
|
||||
<dd>
|
||||
{{ password('vc-room-pin-%s'|format(event_vc_room.id), value=vc_room.data.room_pin, toggle=True,
|
||||
readonly=true) }}
|
||||
</dd>
|
||||
{% endif %}
|
||||
{% if vc_room.data.moderation_pin %}
|
||||
<dt>{% trans %}Moderation PIN{% endtrans %}</dt>
|
||||
<dd>
|
||||
{{ password('vc-moderation-pin-%s'|format(event_vc_room.id), value=vc_room.data.moderation_pin,
|
||||
toggle=True, readonly=true) }}
|
||||
</dd>
|
||||
{% endif %}
|
||||
<dt>{% trans %}Auto-join URL{% endtrans %}</dt>
|
||||
<dd>
|
||||
{{ clipboard_input(vc_room.vidyo_extension.join_url, name="vc-room-url") }}
|
||||
</dd>
|
||||
<dt>{% trans %}Created on{% endtrans %}</dt>
|
||||
<dd>{{ vc_room.created_dt | format_datetime(timezone=event.tzinfo) }}</dd>
|
||||
{% if vc_room.modified_dt %}
|
||||
<dt>{% trans %}Modified on{% endtrans %}</dt>
|
||||
<dd>{{ vc_room.modified_dt | format_datetime(timezone=event.tzinfo) }}</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
@ -1,7 +0,0 @@
|
||||
{% extends 'vc/management_buttons.html' %}
|
||||
{% from 'vc_vidyo:buttons.html' import render_join_button, render_make_me_owner %}
|
||||
|
||||
{% block buttons %}
|
||||
{{ render_join_button(vc_room, extra_classes="icon-play") }}
|
||||
{{ render_make_me_owner(event_vc_room.event, vc_room, event_vc_room) }}
|
||||
{% endblock %}
|
||||
@ -1,8 +0,0 @@
|
||||
{% extends 'vc/vc_room_timetable_buttons.html' %}
|
||||
{% from 'vc_vidyo:buttons.html' import render_join_button, render_make_me_owner %}
|
||||
{% set vc_room = event_vc_room.vc_room %}
|
||||
|
||||
{% block buttons %}
|
||||
{{ render_join_button(vc_room, "i-button-small event-service-right-button join-button") }}
|
||||
{{ render_make_me_owner(event, vc_room, event_vc_room, extra_classes="i-button-small") }}
|
||||
{% endblock %}
|
||||
@ -1,23 +0,0 @@
|
||||
# Translations template for PROJECT.
|
||||
# Copyright (C) 2015 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
#
|
||||
# Translators:
|
||||
# Thomas Baron <thomas.baron@cern.ch>, 2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Indico\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2015-03-11 16:21+0100\n"
|
||||
"PO-Revision-Date: 2015-03-12 12:52+0000\n"
|
||||
"Last-Translator: Thomas Baron <thomas.baron@cern.ch>\n"
|
||||
"Language-Team: French (France) (http://www.transifex.com/projects/p/indico/language/fr_FR/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 1.3\n"
|
||||
"Language: fr_FR\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
msgid "Indico"
|
||||
msgstr "Indico"
|
||||
@ -1,282 +0,0 @@
|
||||
# Translations template for PROJECT.
|
||||
# Copyright (C) 2021 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
#
|
||||
# Translators:
|
||||
# Adrian Mönnich, 2021
|
||||
# Thomas Baron <thomas.baron@cern.ch>, 2015,2017
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Indico\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2021-01-05 13:23+0100\n"
|
||||
"PO-Revision-Date: 2021-01-05 12:24+0000\n"
|
||||
"Last-Translator: Adrian Mönnich\n"
|
||||
"Language-Team: French (France) (http://www.transifex.com/indico/indico/language/fr_FR/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.8.0\n"
|
||||
"Language: fr_FR\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: indico_vc_vidyo/controllers.py:29
|
||||
msgid "You are now the owner of the room '{room}'"
|
||||
msgstr "Vous êtes maintenant responsable de la salle '{room}'"
|
||||
|
||||
#: indico_vc_vidyo/forms.py:23
|
||||
msgid "The PIN must be a number"
|
||||
msgstr "Le code confidentiel doit être un nombre entier"
|
||||
|
||||
#: indico_vc_vidyo/forms.py:28
|
||||
msgid "Show PIN"
|
||||
msgstr "Afficher le code confidentiel"
|
||||
|
||||
#: indico_vc_vidyo/forms.py:30
|
||||
msgid "Show the VC Room PIN on the event page (insecure!)"
|
||||
msgstr "Afficher le code confidentiel de la salle Vidyo sur la page de l'événement (peu sûr!)"
|
||||
|
||||
#: indico_vc_vidyo/forms.py:31
|
||||
msgid "Show Auto-join URL"
|
||||
msgstr "Afficher l'URL de connexion"
|
||||
|
||||
#: indico_vc_vidyo/forms.py:33
|
||||
msgid "Show the auto-join URL on the event page"
|
||||
msgstr "Afficher l'URL de connexion sur la page de l'événement"
|
||||
|
||||
#: indico_vc_vidyo/forms.py:34
|
||||
msgid "Show Phone Access numbers"
|
||||
msgstr "Afficher les numéros d'accès téléphonique"
|
||||
|
||||
#: indico_vc_vidyo/forms.py:36
|
||||
msgid "Show a link to the list of phone access numbers"
|
||||
msgstr "Afficher un lien vers la liste des numéros d'accès téléphonique"
|
||||
|
||||
#: indico_vc_vidyo/forms.py:49 indico_vc_vidyo/templates/info_box.html:7
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:6
|
||||
msgid "Description"
|
||||
msgstr "Description"
|
||||
|
||||
#: indico_vc_vidyo/forms.py:49
|
||||
msgid "The description of the room"
|
||||
msgstr "La description de la salle"
|
||||
|
||||
#: indico_vc_vidyo/forms.py:50 indico_vc_vidyo/templates/info_box.html:14
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:10
|
||||
msgid "Owner"
|
||||
msgstr "Responsable"
|
||||
|
||||
#: indico_vc_vidyo/forms.py:50
|
||||
msgid "The owner of the room"
|
||||
msgstr "Le responsable de la salle"
|
||||
|
||||
#: indico_vc_vidyo/forms.py:51
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:39
|
||||
msgid "Moderation PIN"
|
||||
msgstr "Code confidentiel de modération"
|
||||
|
||||
#: indico_vc_vidyo/forms.py:52
|
||||
msgid "Used to moderate the VC Room. Only digits allowed."
|
||||
msgstr "Utilisé pour modérer la salle de VC. Seuls les chiffres sont autorisés."
|
||||
|
||||
#: indico_vc_vidyo/forms.py:53 indico_vc_vidyo/templates/info_box.html:18
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:32
|
||||
msgid "Room PIN"
|
||||
msgstr "Code confidentiel de la salle"
|
||||
|
||||
#: indico_vc_vidyo/forms.py:54
|
||||
msgid ""
|
||||
"Used to protect the access to the VC Room (leave blank for open access). "
|
||||
"Only digits allowed."
|
||||
msgstr "Utilisé pour protéger l'accès à la salle de VC (laisser vide pour un accès ouvert). Seuls les chiffres sont autorisés."
|
||||
|
||||
#: indico_vc_vidyo/forms.py:56
|
||||
msgid "Auto mute"
|
||||
msgstr "Coupure automatique des périphériques d'entrée"
|
||||
|
||||
#: indico_vc_vidyo/forms.py:58
|
||||
msgid ""
|
||||
"The VidyoDesktop clients will join the VC room muted by default (audio and "
|
||||
"video)"
|
||||
msgstr "Les clients VidyoDesktop rejoindront la salle Vidyo avec le micro et la caméra coupés par défaut"
|
||||
|
||||
#: indico_vc_vidyo/forms.py:73
|
||||
msgid "Unable to find this user in Indico."
|
||||
msgstr "Impossible de trouver cet utilisateur dans Indico."
|
||||
|
||||
#: indico_vc_vidyo/forms.py:75
|
||||
msgid "This user does not have a suitable account to use Vidyo."
|
||||
msgstr "Cet utilisateur n'a pas de compte qui lui permet d'utiliser Vidyo."
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:40
|
||||
msgid "Vidyo email support"
|
||||
msgstr "Adresse électronique de l'assistance Vidyo"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:41
|
||||
msgid "Username"
|
||||
msgstr "Identifiant"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:41
|
||||
msgid "Indico username for Vidyo"
|
||||
msgstr "Identifiant Indico pour Vidyo"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:42
|
||||
msgid "Password"
|
||||
msgstr "Mot de passe"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:43
|
||||
msgid "Indico password for Vidyo"
|
||||
msgstr "Mot de passe utilisateur pour Vidyo"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:44
|
||||
msgid "Admin API WSDL URL"
|
||||
msgstr "URL WSDL pour l'API admin"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:45
|
||||
msgid "User API WSDL URL"
|
||||
msgstr "URL WSDL pour l'API utilisateur"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:46
|
||||
msgid "Indico tenant prefix"
|
||||
msgstr "Préfixe de tenant pour Indico"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:47
|
||||
msgid "The tenant prefix for Indico rooms created on this server"
|
||||
msgstr "Le préfixe de tenant pour les salles Vidyo créées sur ce serveur Indico"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:48
|
||||
msgid "Public rooms' group name"
|
||||
msgstr "Nom du groupe Vidyo pour les salles Vidyo"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:49
|
||||
msgid "Group name for public videoconference rooms created by Indico"
|
||||
msgstr "Nom du groupe pour les salles publiques de visioconférence créées par Indico"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:50
|
||||
msgid "Authenticators"
|
||||
msgstr "Services d'authentification"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:51
|
||||
msgid "Identity providers to convert Indico users to Vidyo accounts"
|
||||
msgstr "Fournisseurs d'identité pour convertir des utilisateurs Indico en comptes Vidyo"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:52
|
||||
msgid "VC room age threshold"
|
||||
msgstr "Limite d'âge pour les salles Vidyo"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:53
|
||||
msgid ""
|
||||
"Number of days after an Indico event when a videoconference room is "
|
||||
"considered old"
|
||||
msgstr "Nombre de jours à partir de la fin d'un événement dans Indico après lesquels une salle de visioconférence est considérée comme agée"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:55
|
||||
msgid "Max. num. VC rooms before warning"
|
||||
msgstr "Nombre maximum de salles Vidyo avant un message d'alerte"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:56
|
||||
msgid "Maximum number of rooms until a warning is sent to the managers"
|
||||
msgstr "Nombre maximum de salles Vidyo créées sur ce serveur avant qu'un message d'alerte soit envoyé aux administrateurs"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:57
|
||||
msgid "VidyoVoice phone number"
|
||||
msgstr "Numéros de téléphone VidyoVoice"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:58
|
||||
msgid "Link to the list of VidyoVoice phone numbers"
|
||||
msgstr "Lien vers la liste des numéros de téléphones VidyoVoice"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:59
|
||||
msgid "Client Chooser URL"
|
||||
msgstr "URL de sélection du client"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:60
|
||||
msgid ""
|
||||
"URL for client chooser interface. The room key will be passed as a 'url' GET"
|
||||
" query argument"
|
||||
msgstr "L'URL pour l'interface de sélection du client. Le code de la salle sera passé comme argument de requête GET."
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:62
|
||||
msgid "Creation email footer"
|
||||
msgstr "Pied de page du courriel de création"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:63
|
||||
msgid "Footer to append to emails sent upon creation of a VC room"
|
||||
msgstr "Pied de page ajouté au courriel envoyé à la création d'une nouvelle salle Vidyo"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:153 indico_vc_vidyo/plugin.py:193
|
||||
#: indico_vc_vidyo/plugin.py:231 indico_vc_vidyo/plugin.py:260
|
||||
msgid "No valid Vidyo account found for this user"
|
||||
msgstr "Pas de compte Vidyo valide pour cet utilisateur"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:189 indico_vc_vidyo/plugin.py:254
|
||||
msgid "Room name already in use"
|
||||
msgstr "Ce nom de salle est déjà utilisé"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:204
|
||||
msgid "Could not find newly created room in Vidyo"
|
||||
msgstr "Impossible de trouver la nouvelle salle dans Vidyo"
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:223 indico_vc_vidyo/plugin.py:250
|
||||
#: indico_vc_vidyo/plugin.py:279
|
||||
msgid "This room has been deleted from Vidyo"
|
||||
msgstr "Cette salle a été supprimée de Vidyo"
|
||||
|
||||
#: indico_vc_vidyo/templates/buttons.html:7
|
||||
#, python-format
|
||||
msgid "You will be the owner of this Vidyo room, replacing %(name)s."
|
||||
msgstr "Vous deviendrez le responsable de cette salle Vidyo, à la place de %(name)s."
|
||||
|
||||
#: indico_vc_vidyo/templates/buttons.html:9
|
||||
msgid "Make me owner"
|
||||
msgstr "Nommez moi responsable"
|
||||
|
||||
#: indico_vc_vidyo/templates/buttons.html:19
|
||||
msgid "Join"
|
||||
msgstr "Rejoindre"
|
||||
|
||||
#: indico_vc_vidyo/templates/info_box.html:5
|
||||
msgid "Name"
|
||||
msgstr "Nom"
|
||||
|
||||
#: indico_vc_vidyo/templates/info_box.html:10
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:8
|
||||
msgid "Extension"
|
||||
msgstr "Extension"
|
||||
|
||||
#: indico_vc_vidyo/templates/info_box.html:22
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:45
|
||||
msgid "Auto-join URL"
|
||||
msgstr "URL pour connexion à la salle"
|
||||
|
||||
#: indico_vc_vidyo/templates/info_box.html:29
|
||||
msgid "Useful links"
|
||||
msgstr "Liens utiles"
|
||||
|
||||
#: indico_vc_vidyo/templates/info_box.html:33
|
||||
msgid "Phone numbers"
|
||||
msgstr "Numéros de téléphone"
|
||||
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:18
|
||||
msgid "Linked to"
|
||||
msgstr "attachée à"
|
||||
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:24
|
||||
msgid "the whole event"
|
||||
msgstr "l'événement entier"
|
||||
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:26
|
||||
msgid "Contribution"
|
||||
msgstr "La contribution"
|
||||
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:28
|
||||
msgid "Session"
|
||||
msgstr "La session"
|
||||
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:49
|
||||
msgid "Created on"
|
||||
msgstr "Créée le "
|
||||
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:52
|
||||
msgid "Modified on"
|
||||
msgstr "Modifiée le "
|
||||
@ -1,280 +0,0 @@
|
||||
# Translations template for PROJECT.
|
||||
# Copyright (C) 2021 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2021.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2021-01-05 13:23+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.8.0\n"
|
||||
|
||||
#: indico_vc_vidyo/controllers.py:29
|
||||
msgid "You are now the owner of the room '{room}'"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/forms.py:23
|
||||
msgid "The PIN must be a number"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/forms.py:28
|
||||
msgid "Show PIN"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/forms.py:30
|
||||
msgid "Show the VC Room PIN on the event page (insecure!)"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/forms.py:31
|
||||
msgid "Show Auto-join URL"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/forms.py:33
|
||||
msgid "Show the auto-join URL on the event page"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/forms.py:34
|
||||
msgid "Show Phone Access numbers"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/forms.py:36
|
||||
msgid "Show a link to the list of phone access numbers"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/forms.py:49 indico_vc_vidyo/templates/info_box.html:7
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:6
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/forms.py:49
|
||||
msgid "The description of the room"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/forms.py:50 indico_vc_vidyo/templates/info_box.html:14
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:10
|
||||
msgid "Owner"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/forms.py:50
|
||||
msgid "The owner of the room"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/forms.py:51
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:39
|
||||
msgid "Moderation PIN"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/forms.py:52
|
||||
msgid "Used to moderate the VC Room. Only digits allowed."
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/forms.py:53 indico_vc_vidyo/templates/info_box.html:18
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:32
|
||||
msgid "Room PIN"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/forms.py:54
|
||||
msgid ""
|
||||
"Used to protect the access to the VC Room (leave blank for open access). "
|
||||
"Only digits allowed."
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/forms.py:56
|
||||
msgid "Auto mute"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/forms.py:58
|
||||
msgid ""
|
||||
"The VidyoDesktop clients will join the VC room muted by default (audio "
|
||||
"and video)"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/forms.py:73
|
||||
msgid "Unable to find this user in Indico."
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/forms.py:75
|
||||
msgid "This user does not have a suitable account to use Vidyo."
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:40
|
||||
msgid "Vidyo email support"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:41
|
||||
msgid "Username"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:41
|
||||
msgid "Indico username for Vidyo"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:42
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:43
|
||||
msgid "Indico password for Vidyo"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:44
|
||||
msgid "Admin API WSDL URL"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:45
|
||||
msgid "User API WSDL URL"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:46
|
||||
msgid "Indico tenant prefix"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:47
|
||||
msgid "The tenant prefix for Indico rooms created on this server"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:48
|
||||
msgid "Public rooms' group name"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:49
|
||||
msgid "Group name for public videoconference rooms created by Indico"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:50
|
||||
msgid "Authenticators"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:51
|
||||
msgid "Identity providers to convert Indico users to Vidyo accounts"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:52
|
||||
msgid "VC room age threshold"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:53
|
||||
msgid ""
|
||||
"Number of days after an Indico event when a videoconference room is "
|
||||
"considered old"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:55
|
||||
msgid "Max. num. VC rooms before warning"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:56
|
||||
msgid "Maximum number of rooms until a warning is sent to the managers"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:57
|
||||
msgid "VidyoVoice phone number"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:58
|
||||
msgid "Link to the list of VidyoVoice phone numbers"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:59
|
||||
msgid "Client Chooser URL"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:60
|
||||
msgid ""
|
||||
"URL for client chooser interface. The room key will be passed as a 'url' "
|
||||
"GET query argument"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:62
|
||||
msgid "Creation email footer"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:63
|
||||
msgid "Footer to append to emails sent upon creation of a VC room"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:153 indico_vc_vidyo/plugin.py:193
|
||||
#: indico_vc_vidyo/plugin.py:231 indico_vc_vidyo/plugin.py:260
|
||||
msgid "No valid Vidyo account found for this user"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:189 indico_vc_vidyo/plugin.py:254
|
||||
msgid "Room name already in use"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:204
|
||||
msgid "Could not find newly created room in Vidyo"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/plugin.py:223 indico_vc_vidyo/plugin.py:250
|
||||
#: indico_vc_vidyo/plugin.py:279
|
||||
msgid "This room has been deleted from Vidyo"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/templates/buttons.html:7
|
||||
#, python-format
|
||||
msgid "You will be the owner of this Vidyo room, replacing %(name)s."
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/templates/buttons.html:9
|
||||
msgid "Make me owner"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/templates/buttons.html:19
|
||||
msgid "Join"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/templates/info_box.html:5
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/templates/info_box.html:10
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:8
|
||||
msgid "Extension"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/templates/info_box.html:22
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:45
|
||||
msgid "Auto-join URL"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/templates/info_box.html:29
|
||||
msgid "Useful links"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/templates/info_box.html:33
|
||||
msgid "Phone numbers"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:18
|
||||
msgid "Linked to"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:24
|
||||
msgid "the whole event"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:26
|
||||
msgid "Contribution"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:28
|
||||
msgid "Session"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:49
|
||||
msgid "Created on"
|
||||
msgstr ""
|
||||
|
||||
#: indico_vc_vidyo/templates/manage_event_info_box.html:52
|
||||
msgid "Modified on"
|
||||
msgstr ""
|
||||
|
||||
@ -1,92 +0,0 @@
|
||||
# This file is part of the Indico plugins.
|
||||
# Copyright (C) 2002 - 2021 CERN
|
||||
#
|
||||
# The Indico plugins are free software; you can redistribute
|
||||
# them and/or modify them under the terms of the MIT License;
|
||||
# see the LICENSE file for more details.
|
||||
|
||||
import re
|
||||
|
||||
from flask_multipass import IdentityRetrievalFailed
|
||||
|
||||
from indico.core.auth import multipass
|
||||
from indico.modules.auth import Identity
|
||||
from indico.modules.users import User
|
||||
|
||||
|
||||
authenticators_re = re.compile(r'\s*,\s*')
|
||||
|
||||
|
||||
def iter_user_identities(user):
|
||||
"""Iterates over all existing user identities that can be used with Vidyo"""
|
||||
from indico_vc_vidyo.plugin import VidyoPlugin
|
||||
providers = authenticators_re.split(VidyoPlugin.settings.get('authenticators'))
|
||||
done = set()
|
||||
for provider in providers:
|
||||
for _, identifier in user.iter_identifiers(check_providers=True, providers={provider}):
|
||||
if identifier in done:
|
||||
continue
|
||||
done.add(identifier)
|
||||
yield identifier
|
||||
|
||||
|
||||
def get_user_from_identifier(settings, identifier):
|
||||
"""Get an actual User object from an identifier"""
|
||||
providers = list(auth.strip() for auth in settings.get('authenticators').split(','))
|
||||
identities = Identity.query.filter(Identity.provider.in_(providers), Identity.identifier == identifier).all()
|
||||
if identities:
|
||||
return sorted(identities, key=lambda x: providers.index(x.provider))[0].user
|
||||
for provider in providers:
|
||||
try:
|
||||
identity_info = multipass.get_identity(provider, identifier)
|
||||
except IdentityRetrievalFailed:
|
||||
continue
|
||||
if identity_info is None:
|
||||
continue
|
||||
if not identity_info.provider.settings.get('trusted_email'):
|
||||
continue
|
||||
emails = {email.lower() for email in identity_info.data.getlist('email') if email}
|
||||
if not emails:
|
||||
continue
|
||||
user = User.query.filter(~User.is_deleted, User.all_emails.in_(list(emails))).first()
|
||||
if user:
|
||||
return user
|
||||
|
||||
|
||||
def iter_extensions(prefix, event_id):
|
||||
"""Return extension (prefix + event_id) with an optional suffix which is
|
||||
incremented step by step in case of collision
|
||||
"""
|
||||
extension = f'{prefix}{event_id}'
|
||||
yield extension
|
||||
suffix = 1
|
||||
while True:
|
||||
yield f'{extension}{suffix}'
|
||||
suffix += 1
|
||||
|
||||
|
||||
def update_room_from_obj(settings, vc_room, room_obj):
|
||||
"""Updates a VCRoom DB object using a SOAP room object returned by the API"""
|
||||
vc_room.name = room_obj.name
|
||||
if room_obj.ownerName != vc_room.data['owner_identity']:
|
||||
owner = get_user_from_identifier(settings, room_obj.ownerName) or User.get_system_user()
|
||||
vc_room.vidyo_extension.owned_by_user = owner
|
||||
|
||||
vc_room.data.update({
|
||||
'description': room_obj.description,
|
||||
'vidyo_id': str(room_obj.roomID),
|
||||
'url': room_obj.RoomMode.roomURL,
|
||||
'owner_identity': room_obj.ownerName,
|
||||
'room_pin': room_obj.RoomMode.roomPIN if room_obj.RoomMode.hasPIN else "",
|
||||
'moderation_pin': room_obj.RoomMode.moderatorPIN if room_obj.RoomMode.hasModeratorPIN else "",
|
||||
})
|
||||
vc_room.vidyo_extension.extension = int(room_obj.extension)
|
||||
|
||||
|
||||
def retrieve_principal(principal):
|
||||
from indico.modules.users import User
|
||||
type_, id_ = principal
|
||||
if type_ in {'Avatar', 'User'}:
|
||||
return User.get(int(id_))
|
||||
else:
|
||||
raise ValueError(f'Unexpected type: {type_}')
|
||||
@ -1,31 +0,0 @@
|
||||
[metadata]
|
||||
name = indico-plugin-vc-vidyo
|
||||
version = 3.0-dev
|
||||
description = Vidyo video-conferencing plugin for Indico
|
||||
url = https://github.com/indico/indico-plugins
|
||||
license = MIT
|
||||
author = Indico Team
|
||||
author_email = indico-team@cern.ch
|
||||
classifiers =
|
||||
Environment :: Plugins
|
||||
Environment :: Web Environment
|
||||
License :: OSI Approved :: MIT License
|
||||
Programming Language :: Python :: 3.9
|
||||
|
||||
[options]
|
||||
packages = find:
|
||||
zip_safe = false
|
||||
include_package_data = true
|
||||
python_requires = ~=3.9
|
||||
install_requires =
|
||||
indico>=3.0.dev0
|
||||
zeep>=4.0.0,<5
|
||||
|
||||
[options.entry_points]
|
||||
indico.plugins =
|
||||
vc_vidyo = indico_vc_vidyo.plugin:VidyoPlugin
|
||||
|
||||
|
||||
|
||||
[pydocstyle]
|
||||
ignore = D100,D101,D102,D103,D104,D105,D107,D203,D213
|
||||
@ -1,11 +0,0 @@
|
||||
# This file is part of the Indico plugins.
|
||||
# Copyright (C) 2002 - 2021 CERN
|
||||
#
|
||||
# The Indico plugins are free software; you can redistribute
|
||||
# them and/or modify them under the terms of the MIT License;
|
||||
# see the LICENSE file for more details.
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
|
||||
setup()
|
||||
@ -1,68 +0,0 @@
|
||||
# This file is part of the Indico plugins.
|
||||
# Copyright (C) 2002 - 2021 CERN
|
||||
#
|
||||
# The Indico plugins are free software; you can redistribute
|
||||
# them and/or modify them under the terms of the MIT License;
|
||||
# see the LICENSE file for more details.
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
import pytest
|
||||
from pytz import utc
|
||||
|
||||
from indico.modules.vc.models.vc_rooms import VCRoom, VCRoomEventAssociation, VCRoomStatus
|
||||
|
||||
from indico_vc_vidyo.models.vidyo_extensions import VidyoExtension
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def create_dummy_room(db, dummy_user):
|
||||
"""Returns a callable which lets you create dummy Vidyo room occurrences"""
|
||||
def _create_room(name, extension, data, **kwargs):
|
||||
vc_room = VCRoom(
|
||||
name=name,
|
||||
data=data,
|
||||
type='vidyo',
|
||||
status=kwargs.pop('status', VCRoomStatus.created),
|
||||
created_by_user=dummy_user,
|
||||
**kwargs
|
||||
)
|
||||
db.session.add(vc_room)
|
||||
db.session.flush()
|
||||
extension = VidyoExtension(
|
||||
vc_room_id=vc_room.id,
|
||||
extension=extension,
|
||||
owned_by_user=dummy_user
|
||||
)
|
||||
vc_room.vidyo_extension = extension
|
||||
return vc_room
|
||||
|
||||
return _create_room
|
||||
|
||||
|
||||
def test_room_cleanup(create_event, create_dummy_room, freeze_time, db):
|
||||
"""Test that 'old' Vidyo rooms are correctly detected"""
|
||||
freeze_time(datetime(2015, 2, 1))
|
||||
|
||||
events = {}
|
||||
for id_, (evt_name, end_date) in enumerate((('Event one', datetime(2012, 1, 1, tzinfo=utc)),
|
||||
('Event two', datetime(2013, 1, 1, tzinfo=utc)),
|
||||
('Event three', datetime(2014, 1, 1, tzinfo=utc)),
|
||||
('Event four', datetime(2015, 1, 1, tzinfo=utc))), start=1):
|
||||
events[id_] = create_event(id_, title=evt_name, end_dt=end_date, start_dt=end_date)
|
||||
|
||||
for id_, (vidyo_id, extension, evt_ids) in enumerate(((1234, 5678, (1, 2, 3, 4)),
|
||||
(1235, 5679, (1, 2)),
|
||||
(1235, 5679, (2,)),
|
||||
(1236, 5670, (4,)),
|
||||
(1237, 5671, ())), start=1):
|
||||
room = create_dummy_room(f'test_room_{id_}', extension, {
|
||||
'vidyo_id': vidyo_id
|
||||
})
|
||||
for evt_id in evt_ids:
|
||||
VCRoomEventAssociation(vc_room=room, linked_event=events[evt_id], data={})
|
||||
db.session.flush()
|
||||
|
||||
from indico_vc_vidyo.task import find_old_vidyo_rooms
|
||||
|
||||
assert {r.id for r in find_old_vidyo_rooms(180)} == {2, 3, 5}
|
||||
@ -1,5 +0,0 @@
|
||||
{
|
||||
"entry": {
|
||||
"main": "./index.js"
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user