diff --git a/AUTHORS.rst b/AUTHORS.rst index 09205bc266811630dc031d2aa2bf82f69ba12792..cce4283a476ce425a3d219ec94c880f7571dd96d 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -20,9 +20,9 @@ .. You should have received a copy of the GNU Affero Public License along .. .. with the BEAT platform. If not, see http://www.gnu.org/licenses/. .. -=========================================================== - Authors of the Biometrics Evaluation and Testing Platform -=========================================================== +============================== + Authors of the BEAT Platform +============================== Andre Anjos <andre.anjos@idiap.ch> Flavio Tarsetti <flavio.tarsetti@idiap.ch> diff --git a/beat/web/algorithms/templates/algorithms/edition.html b/beat/web/algorithms/templates/algorithms/edition.html index 59c0a1759f49c7ad8c2283baa51af17751e56552..a64bdac14c474bedfda37ee99b0eb1c9e600ab8b 100644 --- a/beat/web/algorithms/templates/algorithms/edition.html +++ b/beat/web/algorithms/templates/algorithms/edition.html @@ -222,8 +222,9 @@ function setupEditor(algorithm, dataformats, libraries) } {% if not binary %} + var algorithm_type = type_sequential_selector[0].checked ? beat.contributions.editor.SEQUENTIAL : beat.contributions.editor.AUTONOMOUS source_code_editor.changeProcessMethod(checkbox_analyzer[0].checked, - type_sequential_selector[0].checked); + algorithm_type); {% endif %} inputs_editor.setAnalyzer(checkbox_analyzer[0].checked); }); diff --git a/beat/web/databases/management/__init__.py b/beat/web/databases/management/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/beat/web/databases/management/commands/__init__.py b/beat/web/databases/management/commands/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/beat/web/databases/management/commands/print_db_access_map.py b/beat/web/databases/management/commands/print_db_access_map.py new file mode 100644 index 0000000000000000000000000000000000000000..3445689de056b5190dfbac61dc707ae15f324bd2 --- /dev/null +++ b/beat/web/databases/management/commands/print_db_access_map.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +# vim: set fileencoding=utf-8 : + +############################################################################### +# # +# Copyright (c) 2019 Idiap Research Institute, http://www.idiap.ch/ # +# Contact: beat.support@idiap.ch # +# # +# This file is part of the beat.web module of the BEAT platform. # +# # +# Commercial License Usage # +# Licensees holding valid commercial BEAT licenses may use this file in # +# accordance with the terms contained in a written agreement between you # +# and Idiap. For further information contact tto@idiap.ch # +# # +# Alternatively, this file may be used under the terms of the GNU Affero # +# Public License version 3 as published by the Free Software and appearing # +# in the file LICENSE.AGPL included in the packaging of this file. # +# The BEAT platform is distributed in the hope that it will be useful, but # +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # +# or FITNESS FOR A PARTICULAR PURPOSE. # +# # +# You should have received a copy of the GNU Affero Public License along # +# with the BEAT platform. If not, see http://www.gnu.org/licenses/. # +# # +############################################################################### + +from django.core.management.base import BaseCommand + +from ...models import Database + + +class Command(BaseCommand): + + help = "Prints the list of databases with access level and user information" + + def add_arguments(self, parser): + parser.add_argument( + "--folder-filter", + action="store", + dest="folder_filter", + default=None, + help="Path element up to which the the string must be cleaned", + ) + + def handle(self, *ignored, **options): + + self.stdout.write("name, access, folder, user") + + for database in Database.objects.all(): + folder = database.declaration["root_folder"] + folder_filter = options["folder_filter"] + if folder_filter: + try: + start = folder.rindex(folder_filter) + len(folder_filter) + except ValueError: + start = 0 + folder = folder[start:] + + db_info = "{}, {}, {}".format( + database.fullname(), database.get_sharing_display(), folder + ) + + for user in [ + "{}: {} {}".format(user.username, user.first_name, user.last_name) + for user in database.all_shared_with_users() + ]: + self.stdout.write("{}, {}".format(db_info, user)) + else: + self.stdout.write(db_info) diff --git a/beat/web/experiments/api.py b/beat/web/experiments/api.py index ea7d6d27553963aa1671e94e5e840319a35e49ce..cdd76b830432d6dc25cbe03a377bc0f49e8f5adb 100755 --- a/beat/web/experiments/api.py +++ b/beat/web/experiments/api.py @@ -42,50 +42,56 @@ from rest_framework import generics from rest_framework import serializers from rest_framework.views import APIView from rest_framework.reverse import reverse +from rest_framework.exceptions import ParseError import beat.core.hash import beat.core.algorithm import beat.core.toolchain from .models import Experiment -from .models import Block, CachedFile from .serializers import ExperimentSerializer, ExperimentResultsSerializer from .permissions import IsDatabaseAccessible from ..common.responses import BadRequestResponse, ForbiddenResponse -from ..common.api import ShareView, ListContributionView, ListCreateContributionView, RetrieveUpdateDestroyContributionView +from ..common.api import ( + ShareView, + ListContributionView, + ListCreateContributionView, + RetrieveUpdateDestroyContributionView, +) from ..common.mixins import CommonContextMixin from ..common.exceptions import ShareError from ..common.serializers import SharingSerializer from ..common.utils import validate_restructuredtext, ensure_html -from ..backend.models import Environment - -from ..algorithms.models import Algorithm - from ..toolchains.models import Toolchain -#---------------------------------------------------------- +# ---------------------------------------------------------- class ListExperimentsView(ListContributionView): """ Return all accessible experiments """ + model = Experiment serializer_class = ExperimentSerializer def get(self, request, *args, **kwargs): fields_to_return = self.get_serializer_fields(request) - all_contributions = self.get_queryset().order_by('author__username', 'name').select_related() + all_contributions = ( + self.get_queryset().order_by("author__username", "name").select_related() + ) - serializer = self.get_serializer(all_contributions, many=True, fields=fields_to_return) + serializer = self.get_serializer( + all_contributions, many=True, fields=fields_to_return + ) return Response(serializer.data) -#---------------------------------------------------------- +# ---------------------------------------------------------- class ListCreateExperimentsView(ListCreateContributionView): @@ -93,6 +99,7 @@ class ListCreateExperimentsView(ListCreateContributionView): Read/Write end point that list the experiments available from a given author and allows the creation of new experiments """ + model = Experiment serializer_class = ExperimentSerializer @@ -100,7 +107,6 @@ class ListCreateExperimentsView(ListCreateContributionView): # happy if we don't declare one writing_serializer_class = ExperimentSerializer - def get(self, request, author_name): def _getStatusLabel(status): return [s for s in Experiment.STATUS if s[0] == status][0][1] @@ -119,37 +125,48 @@ class ListCreateExperimentsView(ListCreateContributionView): # Put the pending experiments first, the running/scheduled ones next and the # others at the end (ordered by end date) - if exp1['status'] == PENDING: - if exp2['status'] != PENDING: + if exp1["status"] == PENDING: + if exp2["status"] != PENDING: return -1 - elif exp1['creation_date'] != exp2['creation_date']: - return _cmp(exp1['creation_date'], exp2['creation_date']) + elif exp1["creation_date"] != exp2["creation_date"]: + return _cmp(exp1["creation_date"], exp2["creation_date"]) else: return 1 - elif exp2['status'] == PENDING: - if exp1['status'] != PENDING: + elif exp2["status"] == PENDING: + if exp1["status"] != PENDING: return 1 - tier3_states = [_getStatusLabel(Experiment.DONE), _getStatusLabel(Experiment.FAILED)] + tier3_states = [ + _getStatusLabel(Experiment.DONE), + _getStatusLabel(Experiment.FAILED), + ] - if (exp1['status'] in tier3_states) and (exp2['status'] in tier3_states): - return _cmp(exp2['end_date'], exp1['end_date']) - elif (exp1['status'] in tier3_states) and (exp2['status'] not in tier3_states): + if (exp1["status"] in tier3_states) and (exp2["status"] in tier3_states): + return _cmp(exp2["end_date"], exp1["end_date"]) + elif (exp1["status"] in tier3_states) and ( + exp2["status"] not in tier3_states + ): return -1 - elif (exp1['status'] not in tier3_states) and (exp2['status'] in tier3_states): + elif (exp1["status"] not in tier3_states) and ( + exp2["status"] in tier3_states + ): return 1 - return _cmp(exp1['start_date'], exp2['start_date']) + return _cmp(exp1["start_date"], exp2["start_date"]) # Retrieve the experiments fields_to_return_original = self.get_serializer_fields(request) - mandatory_fields = set(['status', 'creation_date', 'start_date', 'end_date']) + mandatory_fields = set(["status", "creation_date", "start_date", "end_date"]) fields_to_return = list(mandatory_fields.union(fields_to_return_original)) - experiments = self.model.objects.from_author_and_public(request.user, author_name).select_related() + experiments = self.model.objects.from_author_and_public( + request.user, author_name + ).select_related() - serializer = self.get_serializer(experiments, many=True, fields=fields_to_return) + serializer = self.get_serializer( + experiments, many=True, fields=fields_to_return + ) if six.PY2: result = sorted(serializer.data, cmp=_custom_compare) else: @@ -169,72 +186,83 @@ class ListCreateExperimentsView(ListCreateContributionView): def post(self, request, author_name): data = request.data - if 'name' in data: - if not(isinstance(data['name'], six.string_types)): - return BadRequestResponse('Invalid name') + if "name" in data: + if not (isinstance(data["name"], six.string_types)): + return BadRequestResponse("Invalid name") - max_length = self.model._meta.get_field('name').max_length - current_length = len(data['name']) + max_length = self.model._meta.get_field("name").max_length + current_length = len(data["name"]) if current_length > max_length: - return BadRequestResponse('name too long, max is {}, current is {}'.format(max_length, current_length)) + return BadRequestResponse( + "name too long, max is {}, current is {}".format( + max_length, current_length + ) + ) - name = re.sub(r'[\W]', '-', data['name']) + name = re.sub(r"[\W]", "-", data["name"]) else: name = None - if 'short_description' in data: - if not(isinstance(data['short_description'], six.string_types)): - return BadRequestResponse('Invalid short_description') + if "short_description" in data: + if not (isinstance(data["short_description"], six.string_types)): + return BadRequestResponse("Invalid short_description") - max_length = self.model._meta.get_field('short_description').max_length - current_length = len(data['short_description']) + max_length = self.model._meta.get_field("short_description").max_length + current_length = len(data["short_description"]) if current_length > max_length: - return BadRequestResponse('Short description too long, max is {}, current is {}'.format(max_length, current_length)) + return BadRequestResponse( + "Short description too long, max is {}, current is {}".format( + max_length, current_length + ) + ) - short_description = data['short_description'] + short_description = data["short_description"] else: - short_description = '' + short_description = "" - if 'description' in data: - if not(isinstance(data['description'], six.string_types)): - raise serializers.ValidationError({'description': 'Invalid description data'}) - description = data['description'] + if "description" in data: + if not (isinstance(data["description"], six.string_types)): + raise serializers.ValidationError( + {"description": "Invalid description data"} + ) + description = data["description"] try: validate_restructuredtext(description) except ValidationError as errors: - raise serializers.ValidationError({'description': [error for error in errors]}) + raise serializers.ValidationError( + {"description": [error for error in errors]} + ) else: description = None - if 'toolchain' not in data: - return BadRequestResponse('Must indicate a toolchain name') + if "toolchain" not in data: + return BadRequestResponse("Must indicate a toolchain name") - if not(isinstance(data['toolchain'], six.string_types)): - return BadRequestResponse('Invalid toolchain name') + if not (isinstance(data["toolchain"], six.string_types)): + return BadRequestResponse("Invalid toolchain name") - if 'declaration' not in data: - return BadRequestResponse('Must indicate a declaration') + if "declaration" not in data: + return BadRequestResponse("Must indicate a declaration") - if not(isinstance(data['declaration'], dict)) and \ - not(isinstance(data['declaration'], six.string_types)): - return BadRequestResponse('Invalid declaration') + if not (isinstance(data["declaration"], dict)) and not ( + isinstance(data["declaration"], six.string_types) + ): + return BadRequestResponse("Invalid declaration") - if isinstance(data['declaration'], dict): - declaration = data['declaration'] + if isinstance(data["declaration"], dict): + declaration = data["declaration"] else: - declaration_string = data['declaration'] + declaration_string = data["declaration"] try: declaration = simplejson.loads(declaration_string) - except: - return BadRequestResponse('Invalid declaration data') - + except simplejson.errors.JSONDecodeError: + return BadRequestResponse("Invalid declaration data") # Retrieve the toolchain - core_toolchain = beat.core.toolchain.Storage(settings.PREFIX, - data['toolchain']) + core_toolchain = beat.core.toolchain.Storage(settings.PREFIX, data["toolchain"]) - if core_toolchain.version == 'unknown': - return BadRequestResponse('Unknown toolchain version') + if core_toolchain.version == "unknown": + return BadRequestResponse("Unknown toolchain version") if core_toolchain.username is None: core_toolchain.username = request.user.username @@ -246,11 +274,13 @@ class ListCreateExperimentsView(ListCreateContributionView): version=core_toolchain.version, ) except Toolchain.DoesNotExist: - return Response('Toolchain %s not found' % data['toolchain'], status=404) - + return Response("Toolchain %s not found" % data["toolchain"], status=404) # Create the experiment object in the database - existing_names = map(lambda x: x.name, Experiment.objects.filter(author=request.user, toolchain=db_toolchain)) + existing_names = map( + lambda x: x.name, + Experiment.objects.filter(author=request.user, toolchain=db_toolchain), + ) if name is None: name = str(uuid.uuid4()) while name in existing_names: @@ -273,173 +303,202 @@ class ListCreateExperimentsView(ListCreateContributionView): # Send the result result = { - 'name': experiment.fullname(), - 'url': reverse('api_experiments:all') + experiment.fullname() + '/', + "name": experiment.fullname(), + "url": reverse("api_experiments:all") + experiment.fullname() + "/", } response = Response(result, status=201) - response['Location'] = result['url'] + response["Location"] = result["url"] return response -#---------------------------------------------------------- +# ---------------------------------------------------------- class RetrieveUpdateDestroyExperimentView(RetrieveUpdateDestroyContributionView): """ Read/Write/Delete endpoint for a given experiment """ + model = Experiment serializer_class = ExperimentResultsSerializer - def get_queryset(self): - author_name = self.kwargs.get('author_name') - object_name = self.kwargs.get('object_name') + author_name = self.kwargs.get("author_name") + object_name = self.kwargs.get("object_name") user = self.request.user - return self.model.objects.for_user(user, True).filter(author__username__iexact=author_name, name__iexact=object_name) - + return self.model.objects.for_user(user, True).filter( + author__username__iexact=author_name, name__iexact=object_name + ) - def get(self, request, author_name, toolchain_author_name, toolchain_name, version, name): + def get( + self, request, author_name, toolchain_author_name, toolchain_name, version, name + ): if toolchain_author_name is None: toolchain_author_name = author_name - experiment = get_object_or_404(self.model.objects.for_user(request.user, True), - author__username=author_name, - toolchain__author__username=toolchain_author_name, - toolchain__name=toolchain_name, - toolchain__version=version, - name=name - ) + experiment = get_object_or_404( + self.model.objects.for_user(request.user, True), + author__username=author_name, + toolchain__author__username=toolchain_author_name, + toolchain__name=toolchain_name, + toolchain__version=version, + name=name, + ) - fields_to_return = self.get_serializer_fields(request, allow_sharing=(request.user == experiment.author)) + fields_to_return = self.get_serializer_fields( + request, allow_sharing=(request.user == experiment.author) + ) serializer = self.get_serializer(experiment, fields=fields_to_return) return Response(serializer.data) - - def put(self, request, author_name, toolchain_author_name, toolchain_name, version, name): + def put( + self, request, author_name, toolchain_author_name, toolchain_name, version, name + ): if version is None: - raise ValidationError({'version': 'A version number must be provided'}) + raise ValidationError({"version": "A version number must be provided"}) if toolchain_author_name is None: toolchain_author_name = author_name - experiment = get_object_or_404(self.model, - author__username=author_name, - toolchain__author__username=toolchain_author_name, - toolchain__name=toolchain_name, - toolchain__version=version, - name=name - ) + experiment = get_object_or_404( + self.model, + author__username=author_name, + toolchain__author__username=toolchain_author_name, + toolchain__name=toolchain_name, + toolchain__version=version, + name=name, + ) try: data = request.data except ParseError as e: - raise serializers.ValidationError({'data': str(e)}) + raise serializers.ValidationError({"data": str(e)}) else: if not data: - raise serializers.ValidationError({'data': 'Empty'}) + raise serializers.ValidationError({"data": "Empty"}) if experiment.status != Experiment.PENDING: # We always allow documentation-only updates - allowed_fields = ['short_description', 'description'] + allowed_fields = ["short_description", "description"] # When an experiment is done/failed, allow to change its name if experiment.status in (Experiment.DONE, Experiment.FAILED): - allowed_fields.append('name') + allowed_fields.append("name") if len(data.keys()) > len(allowed_fields): - return BadRequestResponse('Experiment is not in pending state') + return BadRequestResponse("Experiment is not in pending state") for key in data.keys(): if key not in allowed_fields: - return BadRequestResponse('Experiment is not in pending state') + return BadRequestResponse("Experiment is not in pending state") # Available fields (not returned by default): # - html_description - if 'fields' in request.GET: - fields_to_return = request.GET['fields'].split(',') + if "fields" in request.GET: + fields_to_return = request.GET["fields"].split(",") else: fields_to_return = [] - if 'name' in data: - if not(isinstance(data['name'], six.string_types)): - raise serializers.ValidationError({'name': 'Invalid name'}) - name = data['name'].replace(' ', '_') + if "name" in data: + if not (isinstance(data["name"], six.string_types)): + raise serializers.ValidationError({"name": "Invalid name"}) + name = data["name"].replace(" ", "_") if name == experiment.name: name = None else: name = None - if 'short_description' in data: - if not(isinstance(data['short_description'], six.string_types)): - raise serializers.ValidationError({'short_description': 'Invalid short_description'}) - short_description = data['short_description'] + if "short_description" in data: + if not (isinstance(data["short_description"], six.string_types)): + raise serializers.ValidationError( + {"short_description": "Invalid short_description"} + ) + short_description = data["short_description"] else: short_description = None - if 'description' in data: - if not(isinstance(data['description'], six.string_types)): - raise serializers.ValidationError({'description': 'Invalid description data'}) - description = data['description'] + if "description" in data: + if not (isinstance(data["description"], six.string_types)): + raise serializers.ValidationError( + {"description": "Invalid description data"} + ) + description = data["description"] try: validate_restructuredtext(description) except ValidationError as errors: - raise serializers.ValidationError({'description': [error for error in errors]}) + raise serializers.ValidationError( + {"description": [error for error in errors]} + ) else: description = None - if 'declaration' in data: - if not(isinstance(data['declaration'], dict)) and \ - not(isinstance(data['declaration'], six.string_types)): - raise serializers.ValidationError({'declaration': 'Invalid declaration'}) + if "declaration" in data: + if not (isinstance(data["declaration"], dict)) and not ( + isinstance(data["declaration"], six.string_types) + ): + raise serializers.ValidationError( + {"declaration": "Invalid declaration"} + ) - if isinstance(data['declaration'], dict): - declaration = data['declaration'] + if isinstance(data["declaration"], dict): + declaration = data["declaration"] declaration_string = simplejson.dumps(declaration, indent=4) else: - declaration_string = data['declaration'] + declaration_string = data["declaration"] try: declaration = simplejson.loads(declaration_string) - except: - raise serializers.ValidationError({'declaration' :'Invalid declaration data'}) + except simplejson.errors.JSONDecodeError: + raise serializers.ValidationError( + {"declaration": "Invalid declaration data"} + ) - if 'description' in declaration: + if "description" in declaration: if short_description is not None: - raise serializers.ValidationError({'short_description': 'A short description is already provided in the experiment declaration'}) + raise serializers.ValidationError( + { + "short_description": "A short description is already provided in the experiment declaration" + } + ) - short_description = declaration['description'] + short_description = declaration["description"] elif short_description is not None: - declaration['description'] = short_description + declaration["description"] = short_description declaration_string = simplejson.dumps(declaration, indent=4) else: declaration = None - if (short_description is not None) and (len(short_description) > self.model._meta.get_field('short_description').max_length): - raise serializers.ValidationError({'short_description': 'Short description too long'}) - + if (short_description is not None) and ( + len(short_description) + > self.model._meta.get_field("short_description").max_length + ): + raise serializers.ValidationError( + {"short_description": "Short description too long"} + ) - if 'toolchain' in data: - if not(isinstance(data['toolchain'], six.string_types)): - raise serializers.ValidationError({'toolchain': 'Invalid toolchain name'}) + if "toolchain" in data: + if not (isinstance(data["toolchain"], six.string_types)): + raise serializers.ValidationError( + {"toolchain": "Invalid toolchain name"} + ) - toolchain_name = data['toolchain'] + toolchain_name = data["toolchain"] if toolchain_name == experiment.toolchain.fullname(): toolchain_name = None else: toolchain_name = None - # Handle the (optional) modification of the toolchain if toolchain_name is not None: - core_toolchain = beat.core.toolchain.Storage(settings.PREFIX, - toolchain_name) + core_toolchain = beat.core.toolchain.Storage( + settings.PREFIX, toolchain_name + ) - if core_toolchain.version == 'unknown': - return BadRequestResponse('Error, unknown toolchain version') + if core_toolchain.version == "unknown": + return BadRequestResponse("Error, unknown toolchain version") if core_toolchain.username is None: core_toolchain.username = request.user.username @@ -451,18 +510,22 @@ class RetrieveUpdateDestroyExperimentView(RetrieveUpdateDestroyContributionView) version=core_toolchain.version, ) except Toolchain.DoesNotExist: - return Response('Toolchain %s not found' % toolchain_name, status=404) + return Response("Toolchain %s not found" % toolchain_name, status=404) else: db_toolchain = experiment.toolchain - # Handle the (optional) modification of the name if (name is not None) or (toolchain_name is not None): - existing_names = map(lambda x: x.name, Experiment.objects.filter(author=request.user, toolchain=db_toolchain)) - name_to_check = (name if name is not None else experiment.name) + existing_names = map( + lambda x: x.name, + Experiment.objects.filter(author=request.user, toolchain=db_toolchain), + ) + name_to_check = name if name is not None else experiment.name if name_to_check in existing_names: - return BadRequestResponse("The name '" + name_to_check + "' is already used") + return BadRequestResponse( + "The name '" + name_to_check + "' is already used" + ) if name is not None: experiment.name = name @@ -470,7 +533,7 @@ class RetrieveUpdateDestroyExperimentView(RetrieveUpdateDestroyContributionView) # Handle the (optional) modification of the description if (short_description is not None) and (declaration is None): tmp_declaration = experiment.declaration - tmp_declaration['description'] = short_description + tmp_declaration["description"] = short_description experiment.declaration = tmp_declaration if description is not None: @@ -489,89 +552,101 @@ class RetrieveUpdateDestroyExperimentView(RetrieveUpdateDestroyContributionView) core_obj = experiment.core() if not core_obj.valid: - error_details = "The experiment isn't valid, due to the following errors:\n%s\n" % '\n'.join(core_obj.errors) + error_details = ( + "The experiment isn't valid, due to the following errors:\n%s\n" + % "\n".join(core_obj.errors) + ) return BadRequestResponse(error_details) # Send the result result = { - 'name': experiment.fullname(), - 'url': reverse('api_experiments:all') + experiment.fullname() + '/', - 'view_url': experiment.get_absolute_url(), + "name": experiment.fullname(), + "url": reverse("api_experiments:all") + experiment.fullname() + "/", + "view_url": experiment.get_absolute_url(), } # Retrieve the description in HTML format (if necessary) - if 'html_description' in fields_to_return: + if "html_description" in fields_to_return: description = experiment.description if len(description) > 0: - result['html_description'] = ensure_html(description) + result["html_description"] = ensure_html(description) else: - result['html_description'] = '' + result["html_description"] = "" response = Response(result) - response['Location'] = result['url'] + response["Location"] = result["url"] return response - - def delete(self, request, author_name, toolchain_author_name, toolchain_name, version, name): + def delete( + self, request, author_name, toolchain_author_name, toolchain_name, version, name + ): if toolchain_author_name is None: toolchain_author_name = author_name # Retrieve the experiment - experiment = get_object_or_404(Experiment, - author__username=author_name, - toolchain__author__username=toolchain_author_name, - toolchain__name=toolchain_name, - toolchain__version=version, - name=name - ) + experiment = get_object_or_404( + Experiment, + author__username=author_name, + toolchain__author__username=toolchain_author_name, + toolchain__name=toolchain_name, + toolchain__version=version, + name=name, + ) # Check that the experiment can still be deleted - if not(experiment.deletable()): - return ForbiddenResponse("The experiment isn't deletable anymore (needed by an attestation)") + if not (experiment.deletable()): + return ForbiddenResponse( + "The experiment isn't deletable anymore (needed by an attestation)" + ) # Deletion of the experiment experiment.delete() return Response(status=204) -#---------------------------------------------------------- +# ---------------------------------------------------------- class StartExperimentView(APIView): """ Start to run an experiment """ + permission_classes = [permissions.IsAuthenticated, IsDatabaseAccessible] - def post(self, request, author_name, toolchain_author_name, toolchain_name, version, name): + def post( + self, request, author_name, toolchain_author_name, toolchain_name, version, name + ): if toolchain_author_name is None: toolchain_author_name = author_name # Retrieve the experiment - experiment = get_object_or_404(Experiment.objects.for_user(request.user, True), - author__username=author_name, - toolchain__author__username=toolchain_author_name, - toolchain__name=toolchain_name, - toolchain__version=version, - name=name - ) + experiment = get_object_or_404( + Experiment.objects.for_user(request.user, True), + author__username=author_name, + toolchain__author__username=toolchain_author_name, + toolchain__name=toolchain_name, + toolchain__version=version, + name=name, + ) self.check_object_permissions(request, experiment) experiment.schedule() # Send the result - result = { 'name': experiment.fullname(), - 'url': reverse('api_experiments:all') + experiment.fullname() + '/', - } + result = { + "name": experiment.fullname(), + "url": reverse("api_experiments:all") + experiment.fullname() + "/", + } response = Response(result, status=200) - response['Location'] = result['url'] + response["Location"] = result["url"] return response -#---------------------------------------------------------- +# ---------------------------------------------------------- class CancelExperimentView(APIView): @@ -581,45 +656,85 @@ class CancelExperimentView(APIView): permission_classes = [permissions.IsAuthenticated] - def post(self, request, author_name, toolchain_author_name, toolchain_name, version, name): + def post( + self, request, author_name, toolchain_author_name, toolchain_name, version, name + ): if toolchain_author_name is None: toolchain_author_name = author_name # Retrieve the experiment - experiment = get_object_or_404(Experiment, - author__username=author_name, - toolchain__author__username=toolchain_author_name, - toolchain__name=toolchain_name, - toolchain__version=version, - name=name - ) + experiment = get_object_or_404( + Experiment, + author__username=author_name, + toolchain__author__username=toolchain_author_name, + toolchain__name=toolchain_name, + toolchain__version=version, + name=name, + ) experiment.cancel() return Response(status=200) -#---------------------------------------------------------- +# ---------------------------------------------------------- -class RetrieveExperimentResultsFromAttestationView(CommonContextMixin, generics.RetrieveAPIView): +class ResetExperimentView(APIView): + """ + Reset an experiment + """ + + permission_classes = [permissions.IsAuthenticated] + + def post( + self, request, author_name, toolchain_author_name, toolchain_name, version, name + ): + + if toolchain_author_name is None: + toolchain_author_name = author_name + + # Retrieve the experiment + experiment = get_object_or_404( + Experiment, + author__username=author_name, + toolchain__author__username=toolchain_author_name, + toolchain__name=toolchain_name, + toolchain__version=version, + name=name, + ) + + self.check_object_permissions(request, experiment) + + experiment.reset() + + return Response(status=200) + + +# ---------------------------------------------------------- + + +class RetrieveExperimentResultsFromAttestationView( + CommonContextMixin, generics.RetrieveAPIView +): """ Return the results of the experiment corresponding to given attestation """ + queryset = Experiment.objects.all() serializer_class = ExperimentResultsSerializer permission_classes = [permissions.AllowAny] - lookup_field = 'attestation__number' - lookup_url_kwarg = 'attestation_number' + lookup_field = "attestation__number" + lookup_url_kwarg = "attestation_number" def get(self, request, *args, **kwargs): - serializer = self.get_serializer(self.get_object(), fields=['results']) + serializer = self.get_serializer(self.get_object(), fields=["results"]) return Response(serializer.data) -#---------------------------------------------------------- +# ---------------------------------------------------------- class ShareExperimentView(ShareView): @@ -627,32 +742,35 @@ class ShareExperimentView(ShareView): This view allows to share an experiment with other users and/or teams """ + model = Experiment serializer_class = SharingSerializer - def post(self, request, author_name, toolchain_author_name, toolchain_name, version, name): - self.kwargs['object_name'] = toolchain_name + def post( + self, request, author_name, toolchain_author_name, toolchain_name, version, name + ): + self.kwargs["object_name"] = toolchain_name serializer = self.get_serializer(data=request.data) if not serializer.is_valid(): return BadRequestResponse(serializer.errors) data = serializer.data - users = data.get('users', None) - teams = data.get('teams', None) - algorithms_infos = request.data.get('algorithms_infos', None) + users = data.get("users", None) + teams = data.get("teams", None) + algorithms_infos = request.data.get("algorithms_infos", None) # Retrieve the experiment if toolchain_author_name is None: toolchain_author_name = author_name - experiment = get_object_or_404(self.model, - author__username=author_name, - toolchain__author__username=toolchain_author_name, - toolchain__name=toolchain_name, - toolchain__version=version, - name=name - ) - + experiment = get_object_or_404( + self.model, + author__username=author_name, + toolchain__author__username=toolchain_author_name, + toolchain__name=toolchain_name, + toolchain__version=version, + name=name, + ) # Check that the experiment is done if experiment.end_date is None: @@ -660,7 +778,9 @@ class ShareExperimentView(ShareView): # Share the experiment try: - experiment.share(users=users, teams=teams, algorithms_infos=algorithms_infos) + experiment.share( + users=users, teams=teams, algorithms_infos=algorithms_infos + ) except ShareError as e: return BadRequestResponse(e.errors) diff --git a/beat/web/experiments/api_urls.py b/beat/web/experiments/api_urls.py index e485156864432bd64020f6d87b9694bed90c54db..c0f08a197cfc9fbca71f0dcf4303f057f57bbc3f 100644 --- a/beat/web/experiments/api_urls.py +++ b/beat/web/experiments/api_urls.py @@ -30,83 +30,76 @@ from . import api urlpatterns = [ - url( - r'^$', - api.ListExperimentsView.as_view(), - name='all' - ), - - + url(r"^$", api.ListExperimentsView.as_view(), name="all"), # Sharing url( - r'^(?P<author_name>\w+)/(?P<toolchain_author_name>\w+)/(?P<toolchain_name>[-\w]+)/(?P<version>\d+)/(?P<name>[-\w]+)/share/$', + r"^(?P<author_name>\w+)/(?P<toolchain_author_name>\w+)/(?P<toolchain_name>[-\w]+)/(?P<version>\d+)/(?P<name>[-\w]+)/share/$", api.ShareExperimentView.as_view(), - name='share' + name="share", ), - url( - r'^(?P<author_name>\w+)/(?P<toolchain_name>[-\w]+)/(?P<version>\d+)/(?P<name>[-\w]+)/share/$', + r"^(?P<author_name>\w+)/(?P<toolchain_name>[-\w]+)/(?P<version>\d+)/(?P<name>[-\w]+)/share/$", api.ShareExperimentView.as_view(), - { 'toolchain_author_name': None }, - name='share' + {"toolchain_author_name": None}, + name="share", ), - - # Start url( - r'^(?P<author_name>\w+)/(?P<toolchain_author_name>\w+)/(?P<toolchain_name>[-\w]+)/(?P<version>\d+)/(?P<name>[-\w]+)/start/$', + r"^(?P<author_name>\w+)/(?P<toolchain_author_name>\w+)/(?P<toolchain_name>[-\w]+)/(?P<version>\d+)/(?P<name>[-\w]+)/start/$", api.StartExperimentView.as_view(), - name='start' + name="start", ), - url( - r'^(?P<author_name>\w+)/(?P<toolchain_name>[-\w]+)/(?P<version>\d+)/(?P<name>[-\w]+)/start/$', + r"^(?P<author_name>\w+)/(?P<toolchain_name>[-\w]+)/(?P<version>\d+)/(?P<name>[-\w]+)/start/$", api.StartExperimentView.as_view(), - { 'toolchain_author_name': None }, - name='start' + {"toolchain_author_name": None}, + name="start", ), - - # Cancelling url( - r'^(?P<author_name>\w+)/(?P<toolchain_author_name>\w+)/(?P<toolchain_name>[-\w]+)/(?P<version>\d+)/(?P<name>[-\w]+)/cancel/$', + r"^(?P<author_name>\w+)/(?P<toolchain_author_name>\w+)/(?P<toolchain_name>[-\w]+)/(?P<version>\d+)/(?P<name>[-\w]+)/cancel/$", api.CancelExperimentView.as_view(), - name='cancel' + name="cancel", ), - url( - r'^(?P<author_name>\w+)/(?P<toolchain_name>[-\w]+)/(?P<version>\d+)/(?P<name>[-\w]+)/cancel/$', + r"^(?P<author_name>\w+)/(?P<toolchain_name>[-\w]+)/(?P<version>\d+)/(?P<name>[-\w]+)/cancel/$", api.CancelExperimentView.as_view(), - { 'toolchain_author_name': None }, - name='cancel' + {"toolchain_author_name": None}, + name="cancel", + ), + # Reseting + url( + r"^(?P<author_name>\w+)/(?P<toolchain_author_name>\w+)/(?P<toolchain_name>[-\w]+)/(?P<version>\d+)/(?P<name>[-\w]+)/reset/$", + api.ResetExperimentView.as_view(), + name="reset", + ), + url( + r"^(?P<author_name>\w+)/(?P<toolchain_name>[-\w]+)/(?P<version>\d+)/(?P<name>[-\w]+)/reset/$", + api.ResetExperimentView.as_view(), + {"toolchain_author_name": None}, + name="reset", ), - - # Attestations url( - r'^(?P<attestation_number>\d+)/', + r"^(?P<attestation_number>\d+)/", api.RetrieveExperimentResultsFromAttestationView.as_view(), - name='attestations' + name="attestations", ), - - # Experiments url( - r'^(?P<author_name>\w+)/$', + r"^(?P<author_name>\w+)/$", api.ListCreateExperimentsView.as_view(), - name='list_create' + name="list_create", ), - url( - r'^(?P<author_name>\w+)/(?P<toolchain_author_name>\w+)/(?P<toolchain_name>[-\w]+)/(?P<version>\d+)/(?P<name>[-\w]+)/$', + r"^(?P<author_name>\w+)/(?P<toolchain_author_name>\w+)/(?P<toolchain_name>[-\w]+)/(?P<version>\d+)/(?P<name>[-\w]+)/$", api.RetrieveUpdateDestroyExperimentView.as_view(), - name='object' + name="object", ), - url( - r'^(?P<author_name>\w+)/(?P<toolchain_name>[-\w]+)/(?P<version>\d+)/(?P<name>[-\w]+)/$', + r"^(?P<author_name>\w+)/(?P<toolchain_name>[-\w]+)/(?P<version>\d+)/(?P<name>[-\w]+)/$", api.RetrieveUpdateDestroyExperimentView.as_view(), - { 'toolchain_author_name': None }, - name='object' + {"toolchain_author_name": None}, + name="object", ), ] diff --git a/beat/web/experiments/tests.py b/beat/web/experiments/tests/tests_api.py similarity index 95% rename from beat/web/experiments/tests.py rename to beat/web/experiments/tests/tests_api.py index d802fed3621cea9b88e4f7f2b9615c8c11ea074b..d6b6311e9307be6e634cf88a6ff48126e88e0480 100755 --- a/beat/web/experiments/tests.py +++ b/beat/web/experiments/tests/tests_api.py @@ -35,28 +35,28 @@ from django.conf import settings from django.contrib.auth.models import User from django.core.urlresolvers import reverse -from ..dataformats.models import DataFormat -from ..algorithms.models import Algorithm -from ..toolchains.models import Toolchain -from ..team.models import Team +from ...dataformats.models import DataFormat +from ...algorithms.models import Algorithm +from ...toolchains.models import Toolchain +from ...team.models import Team -from ..backend.models import Environment -from ..backend.models import Queue +from ...backend.models import Environment +from ...backend.models import Queue -from ..attestations.models import Attestation -from ..databases.models import Database +from ...attestations.models import Attestation +from ...databases.models import Database -from ..common.testutils import BaseTestCase -from ..common.testutils import ( # noqa test runner will call it, tearDownModule +from ...common.testutils import BaseTestCase +from ...common.testutils import ( # noqa test runner will call it, tearDownModule tearDownModule, ) -from .models import Experiment -from .models import CachedFile -from .models import Block -from .models import Result +from ..models import Experiment +from ..models import CachedFile +from ..models import Block +from ..models import Result -TEST_PWD = "1234" +TEST_PWD = "1234" # nosec HASHES = { "addition1": "ff59a471cec5c17b45d1dfa5aff3ed897ee2d7ed87de205365b372be1c726c87", @@ -1095,6 +1095,68 @@ class ExperimentStartingAPI(ExperimentTestBase): # ---------------------------------------------------------- +class ExperimentResetingAPI(ExperimentTestBase): + def setUp(self): + super(ExperimentResetingAPI, self).setUp() + + self.login_johndoe() + + url = reverse("api_experiments:list_create", args=["johndoe"]) + response = self.client.post( + url, + json.dumps( + { + "toolchain": "johndoe/toolchain1/1", + "declaration": ExperimentTestBase.DECLARATION1, + "name": "pending", + } + ), + content_type="application/json", + ) + + self.checkResponse(response, 201, content_type="application/json") + + self.client.logout() + + self.url = reverse( + "api_experiments:reset", + args=["johndoe", "johndoe", "toolchain1", 1, "pending"], + ) + + def test_no_access_for_anonymous_user(self): + response = self.client.post(self.url) + self.checkResponse(response, 403) + + def test_no_access_for_other_user(self): + self.login_jackdoe() + response = self.client.post(self.url) + self.checkResponse(response, 403) + + def test_reset_experiment(self): + self.login_johndoe() + + experiments = Experiment.objects.all() + self.assertEqual(experiments.count(), 1) + + experiment = experiments[0] + experiment.status = Experiment.DONE + experiment.start_date = datetime.now() + experiment.end_date = datetime.now() + experiment.save() + + response = self.client.post(self.url) + self.checkResponse(response, 200) + + experiment.refresh_from_db() + self.assertTrue(experiment.creation_date is not None) + self.assertTrue(experiment.start_date is None) + self.assertTrue(experiment.end_date is None) + self.assertEqual(experiment.status, Experiment.PENDING) + + +# ---------------------------------------------------------- + + class ResultsAPI(ExperimentTestBase): def setUp(self): super(ResultsAPI, self).setUp() diff --git a/beat/web/navigation/templates/navigation/legal_disclaimer.rst b/beat/web/navigation/templates/navigation/legal_disclaimer.rst index 3fbf9e9b87cd9addea1accbce2256fba052a363d..b84c7de399f66d79c6bcdd830e1b3d2aff7c146b 100644 --- a/beat/web/navigation/templates/navigation/legal_disclaimer.rst +++ b/beat/web/navigation/templates/navigation/legal_disclaimer.rst @@ -37,7 +37,7 @@ Version 1.0 (effective as of March 1st, 2014) -The Biometrics Evaluation and Testing ("**BEAT**") project is a four-year +The "**BEAT**" project is a four-year European research project led by THE FOUNDATION OF IDIAP RESEARCH INSTITUTE ("**IDIAP**"), Centre du Parc, Rue Marconi 19, PO Box 592, CH - 1920 Martigny, Switzerland, which aims at developing a platform for the testing, evaluation diff --git a/beat/web/navigation/templates/navigation/terms_of_service.rst b/beat/web/navigation/templates/navigation/terms_of_service.rst index d9792a1761dac49b0be4d06fb2aae655f9dfd5e3..57bd7ff2cffde79c7ea46814f026c418e0f10d8f 100644 --- a/beat/web/navigation/templates/navigation/terms_of_service.rst +++ b/beat/web/navigation/templates/navigation/terms_of_service.rst @@ -39,11 +39,11 @@ Version 1.0 (effective as of March 1st, 2014) -The Biometrics Evaluation and Testing ("**BEAT**") project is a four-year +The "**BEAT**" project is a four-year European research project led by THE FOUNDATION OF IDIAP RESEARCH INSTITUTE ("**IDIAP**"), Centre du Parc, Rue Marconi 19, PO Box 592, CH - 1920 Martigny, Switzerland, which aims at developing a platform for the testing, evaluation -and attestation of biometric systems, in particular by the sharing of open +and attestation of machine learning systems, in particular by the sharing of open source implementations of algorithms. ============= diff --git a/beat/web/reports/serializers.py b/beat/web/reports/serializers.py index 158db1c814a3dd26cbf96c0a891588660c9a6704..583667fcfdd6f0b476744aa615bc11fd42b197e9 100644 --- a/beat/web/reports/serializers.py +++ b/beat/web/reports/serializers.py @@ -51,6 +51,7 @@ class BasicReportSerializer(serializers.ModelSerializer): author = serializers.SerializerMethodField() experiments = serializers.SerializerMethodField() experiment_access_map = serializers.SerializerMethodField() + analyzers_access_map = serializers.SerializerMethodField() analyzer = serializers.SerializerMethodField() html_description = serializers.SerializerMethodField() add_url = serializers.SerializerMethodField() @@ -93,6 +94,16 @@ class BasicReportSerializer(serializers.ModelSerializer): obj.experiments.iterator())) return access_map + def get_analyzers_access_map(self, obj): + user = self.context['request'].user + access_map = list() + for exp in obj.experiments.iterator(): + # find analyzer + analyzers = exp.blocks.filter(analyzer=True) + if len(analyzers) > 0: + access_map.append(analyzers[0].algorithm.accessibility_for(user)[0]) + return access_map + def get_analyzer(self, obj): if obj.analyzer is not None: return obj.analyzer.fullname() @@ -125,7 +136,7 @@ class FullReportSerializer(BasicReportSerializer): class Meta(BasicReportSerializer.Meta): - fields = ['name', 'number', 'short_description', 'description', 'is_owner', 'author','status', 'creation_date', 'publication_date', 'experiments', 'analyzer', 'content', 'html_description', 'experiment_access_map'] + fields = ['name', 'number', 'short_description', 'description', 'is_owner', 'author','status', 'creation_date', 'publication_date', 'experiments', 'analyzer', 'content', 'html_description', 'experiment_access_map', 'analyzers_access_map'] #---------------------------------------------------------- diff --git a/beat/web/reports/static/reports/app/directives/experimentsTable.js b/beat/web/reports/static/reports/app/directives/experimentsTable.js index e9724588ce114d3ce05809b34db2e9f4420eed82..bac59abcb77394c8030d8370cde86a852cfab736 100644 --- a/beat/web/reports/static/reports/app/directives/experimentsTable.js +++ b/beat/web/reports/static/reports/app/directives/experimentsTable.js @@ -40,14 +40,33 @@ angular.module('reportApp') scope.ReportService = ReportService; scope.domId = `experiments-table`; scope.getAnalyzerFromExpName = ExperimentsService.getAnalyzerFromExpName; + scope.getAnalyzerShortName = (expName) => { + const name = scope.getAnalyzerFromExpName(expName); + return name.split('/').slice(1).join('/'); + }; scope.getExpUrl = UrlService.getExperimentUrl; scope.getBlockUrl = UrlService.getBlockUrl; scope.getDatabaseUrl = UrlService.getDatabaseUrl; scope.getExperimentListPath = UrlService.getExperimentListPath; scope.isViewmode = UrlService.isViewmode; + //expNames are either the full experiment names, or just the last segment scope.expNames = ExperimentsService.experimentNames; scope.exps = ExperimentsService.experiments; + scope.getFullExpName = (expName) => { + if(ReportService.experiments.includes(expName)){ + return expName; + } else { + return ReportService.experiments.find(n => n.split('/').pop() === expName); + } + }; + scope.getNoUserExpName = (eName) => { + let expName = scope.getFullExpName(eName); + const noUserName = expName.split('/').slice(1).join('/'); + return noUserName; + }; + scope.getAccessMap = (expName) => ReportService.accessMap[scope.getFullExpName(expName)]; + scope.getAnalyzerAccessMap = (expName) => ReportService.analyzerAccessMap[scope.getFullExpName(expName)]; scope.groups = GroupsService.groups; @@ -62,15 +81,15 @@ angular.module('reportApp') ExperimentsService.deleteExperiment(expName); }; - const getUnusedExperiments = (expNames, groups) => { - const usedExps = Array.from(new Set([].concat.apply([], groups.map(g => g.experiments)))); - const unusedExps = expNames.filter(n => !usedExps.includes(n)); - scope.unusedExps = unusedExps; - }; + const getUnusedExperiments = (expNames, groups) => { + const usedExps = Array.from(new Set([].concat.apply([], groups.map(g => g.experiments)))); + const unusedExps = expNames.filter(n => !usedExps.includes(n)); + scope.unusedExps = unusedExps; + }; - scope.$watchCollection('expNames', (names) => {getUnusedExperiments(names, scope.groups);}); - scope.$watch('groups', (gs) => {getUnusedExperiments(scope.expNames, gs);}, true); - getUnusedExperiments(scope.expNames, scope.groups); + scope.$watchCollection('expNames', (names) => {getUnusedExperiments(names, scope.groups);}); + scope.$watch('groups', (gs) => {getUnusedExperiments(scope.expNames, gs);}, true); + getUnusedExperiments(scope.expNames, scope.groups); }, template: ` <div id='{{ domId }}' class='panel panel-default'> @@ -120,7 +139,7 @@ angular.module('reportApp') </td> <td ng-if='!isViewmode()'> <span - ng-if='unusedExps.includes(expName)' + ng-if='unusedExps.includes(expName)' style='cursor: help;' title="Experiment needs to be added to a group"> <i class="fa fa-flag fa-lg text-warning"></i> @@ -131,14 +150,20 @@ angular.module('reportApp') {{ groups[0].aliases[expName] }} </span> </td> - <td><a href='{{ getExpUrl(expName) }}'>{{ expName }}</a></td> + <td> + <a ng-if='getAccessMap(expName)' href='{{ getExpUrl(getFullExpName(expName)) }}'>{{ getFullExpName(expName) }}</a> + <span ng-if='!getAccessMap(expName)' title='experiment not accessible for current user'>{{ getNoUserExpName(expName) }}</span> + </td> <td> <span ng-repeat='db in getExpDatabases(expName) track by db'> <a href='{{ getDatabaseUrl(db.split("@")[0]) }}'>{{ db }}</a> </span> </td> - <td>{{ getAnalyzerFromExpName(expName) }}</td> + <td> + <a ng-if='getAnalyzerAccessMap(expName)' href='{{ getBlockUrl(getAnalyzerFromExpName(expName)) }}'>{{ getAnalyzerFromExpName(expName) }}</a> + <span ng-if='!getAnalyzerAccessMap(expName)' title='analyzer not accessible for current user'>{{ getAnalyzerShortName(expName) }}</a> + </td> </tr> </tbody> </table> diff --git a/beat/web/reports/static/reports/app/directives/panelExperiments.js b/beat/web/reports/static/reports/app/directives/panelExperiments.js index 882c2d236fad589b92edc8ce791a0f77d106e52e..59d0e7bc3a4b362e6166edb8ea5549f78deacc52 100644 --- a/beat/web/reports/static/reports/app/directives/panelExperiments.js +++ b/beat/web/reports/static/reports/app/directives/panelExperiments.js @@ -36,8 +36,16 @@ angular.module('reportApp').directive("groupPanelExperiments", ['GroupsService', scope.experiments = ExperimentsService.experiments; scope.dropdownId = `${scope.group.name}_exp_add_dropdown`; scope.accessMap = ReportService.accessMap; + scope.getAnalyzerShortName = () => { + return scope.group.analyzer.split('/').slice(1).join('/'); + }; + scope.analyzerIsAccessible = () => ReportService.analyzerAccessMap[scope.group.experiments[0]]; scope.getExpName = (expName) => scope.experiments[expName] ? expName : expName.split('/').pop(); + scope.getNoUserExpName = (expName) => { + const noUserName = expName.split('/').slice(1).join('/'); + return noUserName; + }; const getExp = (expName) => scope.experiments[expName] || scope.experiments[expName.split('/').pop()]; // find experiments that are not in the group but are @@ -105,7 +113,9 @@ angular.module('reportApp').directive("groupPanelExperiments", ['GroupsService', </div> </div> <i style='margin-left: 5px;' ng-if='group.analyzer.length > 0'> - Analyzer: <a href='{{ getBlockUrl(group.analyzer) }}'>{{ group.analyzer }}</a> + Analyzer: + <a ng-if='analyzerIsAccessible()' href='{{ getBlockUrl(group.analyzer) }}'>{{ group.analyzer }}</a> + <span ng-if='!analyzerIsAccessible()' title='analyzer not accessible for current user'>{{ getAnalyzerShortName() }}</a> </i> </h4> </div> @@ -139,8 +149,8 @@ angular.module('reportApp').directive("groupPanelExperiments", ['GroupsService', <td ng-if='!isViewmode()'><input ng-model='group.aliases[expName]' ng-model-options="{ debounce: 500 }"></input></td> <td ng-if='isViewmode()'><span>{{ group.aliases[expName] }}</span></td> <td> - <a ng-if='accessMap[expName]' href='{{ getExpUrl(expName) }}'>{{ getExpName(expName) }}</a> - <i ng-if='!accessMap[expName]'><small>experiment not accessible for current user</small></i> + <a ng-if='accessMap[expName]' href='{{ getExpUrl(expName) }}'>{{ expName }}</a> + <span ng-if='!accessMap[expName]' title='experiment not accessible for current user'>{{ getNoUserExpName(expName) }}</span> </td> <td> <span ng-repeat='db in getExpDatabases(expName)'> diff --git a/beat/web/reports/static/reports/app/directives/tableItem.js b/beat/web/reports/static/reports/app/directives/tableItem.js index 1a9cae99a0efb168e4d0f57728e9d2c9c30df0ce..f5ea9e2df97043c51f381658af438cffed0aae71 100644 --- a/beat/web/reports/static/reports/app/directives/tableItem.js +++ b/beat/web/reports/static/reports/app/directives/tableItem.js @@ -284,10 +284,13 @@ angular.module('reportApp') <tbody> <tr ng-repeat="exp in group.experiments | orderBy:sortFunc:sortField.isReversed"> <td ng-repeat='field in fields'> - <a ng-if='$index == 0 && getExperimentUrl(exp) && accessMap[exp]' href='{{ getExperimentUrl(exp) }}'> + <a ng-if='$index == 0 && accessMap[exp]' href='{{ getExperimentUrl(exp) }}'> {{ getFieldVal(exp, field) }} </a> - <span ng-if='!$index == 0 || !getExperimentUrl(exp) || !accessMap[exp]'> + <span ng-if='$index == 0 && !accessMap[exp]' title='experiment not accessible for current user'> + {{ getFieldVal(exp, field) }} + </span> + <span ng-if='$index != 0'> {{ getFieldVal(exp, field) }} </span> </td> diff --git a/beat/web/reports/static/reports/app/services/reportService.js b/beat/web/reports/static/reports/app/services/reportService.js index cedaa6791717058199d133d166b2753b7ad5ae57..043498b362ad7256ad1b2e9cd4d799b4aaa4bb58 100644 --- a/beat/web/reports/static/reports/app/services/reportService.js +++ b/beat/web/reports/static/reports/app/services/reportService.js @@ -35,6 +35,9 @@ angular.module('reportApp').factory('ReportService', ['GroupsService', 'plotterF rs.number = undefined; rs.author = undefined; rs.name = undefined; + rs.experiments = undefined; + rs.accessMap = undefined; + rs.analyzerAccessMap = undefined; rs.plotters = []; rs.defaultPlotters = []; @@ -50,8 +53,9 @@ angular.module('reportApp').factory('ReportService', ['GroupsService', 'plotterF rs.number = report.number; rs.author = report.author; rs.name = report.name.split('/').length > 1 ? report.name.split('/')[1] : null; - rs.accessMap = report.experiments.reduce((o, expName, i) => - ({...o, [expName]: report.experiment_access_map[i]}), {}); + rs.accessMap = report.experiments.reduce((o, expName, i) => ({...o, [expName]: report.experiment_access_map[i]}), {}); + rs.analyzerAccessMap = report.experiments.reduce((o, expName, i) => ({...o, [expName]: report.analyzers_access_map[i]}), {}); + rs.experiments = report.experiments; // start up our GroupsService GroupsService.loadGroups(report.content.groups); diff --git a/beat/web/reports/tests.py b/beat/web/reports/tests.py index 65781d8639fdd6311da6fc7a809910af4cd32437..c0517b2c2ca1777d41111737ad218f77c8258800 100755 --- a/beat/web/reports/tests.py +++ b/beat/web/reports/tests.py @@ -892,6 +892,7 @@ class EditableReportRetrievalTestCase(ReportTestCase): "creation_date": self.report.creation_date.isoformat(), "publication_date": None, "experiment_access_map": [], + "analyzers_access_map": [], "experiments": [], "content": {}, "analyzer": None, @@ -944,6 +945,7 @@ class LockedReportRetrievalTestCase(ReportTestCase): "creation_date": self.report.creation_date.isoformat(), "publication_date": None, "experiment_access_map": [True], + "analyzers_access_map": [True], "experiments": [self.experiment_analyzer1.fullname()], "content": {}, "analyzer": None, @@ -992,6 +994,7 @@ class PublishedReportRetrievalTestCase(ReportTestCase): "creation_date": self.report.creation_date.isoformat(), "publication_date": self.report.publication_date.isoformat(), "experiment_access_map": [False], + "analyzers_access_map": [True], "experiments": [self.experiment_analyzer1.fullname()], "content": {}, "analyzer": None, @@ -1014,6 +1017,7 @@ class PublishedReportRetrievalTestCase(ReportTestCase): "creation_date": self.report.creation_date.isoformat(), "publication_date": self.report.publication_date.isoformat(), "experiment_access_map": [True], + "analyzers_access_map": [True], "experiments": [self.experiment_analyzer1.fullname()], "content": {}, "analyzer": None, @@ -1036,6 +1040,7 @@ class PublishedReportRetrievalTestCase(ReportTestCase): "author": self.johndoe.username, "status": "published", "experiment_access_map": [False], + "analyzers_access_map": [True], "creation_date": self.report.creation_date.isoformat(), "publication_date": self.report.publication_date.isoformat(), "experiments": [self.experiment_analyzer1.fullname()], diff --git a/beat/web/settings/settings.py b/beat/web/settings/settings.py index 678c1a12c5c1658f7a74d144a832f0ec174e1cce..ae452205540443fe77d3453adcc7899ef6d96501 100755 --- a/beat/web/settings/settings.py +++ b/beat/web/settings/settings.py @@ -338,7 +338,7 @@ INSTALLED_APPS = ( 'guardian', 'rest_framework', - 'rest_framework_swagger', + 'drf_yasg', 'rest_framework.authtoken', 'jsonfield', 'actstream', @@ -435,7 +435,10 @@ REST_FRAMEWORK = { ], 'DEFAULT_PARSER_CLASSES': [ 'rest_framework.parsers.JSONParser' - ] + ], + + # This setting is mandatory after DRF 3.10 + # 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema' } ############################################################################## diff --git a/beat/web/ui/templates/ui/bar.html b/beat/web/ui/templates/ui/bar.html index ee1c601398107793bda619db18fd18aad398aedd..3b3dcd5149e5db14fea82a6dab1696ed0c1ffa0d 100644 --- a/beat/web/ui/templates/ui/bar.html +++ b/beat/web/ui/templates/ui/bar.html @@ -139,7 +139,7 @@ </div> </li> <li class="visible-xs"><a href="{{ documentation_link }}" target="_blank"><i class="fa fa-book fa-fw"></i> User Guide</a></li> - <li class="hidden-xs"><a class="menu-icon" title="User Guide" data-toggle="tooltip" data-placement="bottom" href="{% static "guide/index.html" %}"><i class="fa fa-book fa-fw"></i></a></li> + <li class="hidden-xs"><a class="menu-icon" title="User Guide" data-toggle="tooltip" data-placement="bottom" href="{{ documentation_link }}"><i class="fa fa-book fa-fw"></i></a></li> {% if request.user.is_superuser %} <li class="visible-xs"><a href="{% url 'backend:scheduler' %}"><i class="fa fa-calendar fa-fw"></i> Scheduler</a></li> diff --git a/beat/web/urls.py b/beat/web/urls.py index 693ebe0e8a07f4b29dbb4dcfa1057eac1316b1bb..0b8b4dce94ec9bde3fd12c6da52308406e6653b1 100755 --- a/beat/web/urls.py +++ b/beat/web/urls.py @@ -30,7 +30,9 @@ from django.conf import settings from django.views.generic import TemplateView from django.contrib.staticfiles.urls import staticfiles_urlpatterns -from rest_framework_swagger.views import get_swagger_view +from rest_framework import permissions +from drf_yasg.views import get_schema_view +from drf_yasg import openapi from .ui import urls as ui_urls from .navigation import urls as navigation_urls @@ -43,7 +45,19 @@ except ImportError: from django.contrib import admin admin.autodiscover() -schema_view = get_swagger_view(title='BEAT API') + +schema_view = get_schema_view( + openapi.Info( + title="BEAT API", + default_version='v1', + description="REST API for BEAT platform", + terms_of_service="https://gitlab.idiap.ch/beat/beat.web/blob/master/LICENSE.AGPL", + contact=openapi.Contact(email="beat.support@idiap.ch"), + license=openapi.License(name="AGPLv3 License"), + ), + public=True, + permission_classes=(permissions.IsAuthenticated,), +) # Views unprefixed_patterns = ui_urls.urlpatterns @@ -53,55 +67,55 @@ unprefixed_patterns += [ url(r'^algorithms/', include('beat.web.algorithms.urls', namespace='algorithms'), - ), + ), url(r'^libraries/', include('beat.web.libraries.urls', namespace='libraries'), - ), + ), url(r'^attestations/', include('beat.web.attestations.urls', namespace='attestations'), - ), + ), url(r'^backend/', include('beat.web.backend.urls', namespace='backend'), - ), + ), url(r'^dataformats/', include('beat.web.dataformats.urls', namespace='dataformats'), - ), + ), url(r'^databases/', include('beat.web.databases.urls', namespace='databases'), - ), + ), url(r'^experiments/', include('beat.web.experiments.urls', namespace='experiments'), - ), + ), url(r'^search/', include('beat.web.search.urls', namespace='search'), - ), + ), url(r'^statistics/', include('beat.web.statistics.urls', namespace='statistics'), - ), + ), url(r'^toolchains/', include('beat.web.toolchains.urls', namespace='toolchains'), - ), + ), url(r'^teams/', include('beat.web.team.urls', namespace='teams'), - ), + ), url(r'^plotters/', include('beat.web.plotters.urls', namespace='plotters'), - ), + ), url(r'^reports/', include('beat.web.reports.urls', namespace='reports'), - ), + ), url(r'^accounts/', include('beat.web.accounts.urls', namespace='accounts'), @@ -109,9 +123,11 @@ unprefixed_patterns += [ url(r'^admin/', include(admin.site.urls)), - url(r'^docs/', - schema_view - ), + url(r'^swagger(?P<format>\.json|\.yaml)$', + schema_view.without_ui(cache_timeout=0), name='schema-json'), + + url(r'^swagger/$', + schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'), url(r'^activity/', include('actstream.urls'), @@ -125,47 +141,48 @@ unprefixed_patterns += [ url(r'^api/v1/teams/', include('beat.web.team.api_urls', namespace='api_teams'), - ), + ), url(r'^api/v1/algorithms/', include('beat.web.algorithms.api_urls', namespace='api_algorithms'), - ), + ), url(r'^api/v1/attestations/', - include('beat.web.attestations.api_urls', namespace='api_attestations'), - ), + include('beat.web.attestations.api_urls', + namespace='api_attestations'), + ), url(r'^api/v1/backend/', include('beat.web.backend.api_urls', namespace='api_backend'), - ), + ), url(r'^api/v1/databases/', include('beat.web.databases.api_urls', namespace='api_databases'), - ), + ), url(r'^api/v1/dataformats/', include('beat.web.dataformats.api_urls', namespace='api_dataformats'), - ), + ), url(r'^api/v1/experiments/', include('beat.web.experiments.api_urls', namespace='api_experiments'), - ), + ), url(r'^api/v1/libraries/', include('beat.web.libraries.api_urls', namespace='api_libraries'), - ), + ), url(r'^api/v1/search/', include('beat.web.search.api_urls', namespace='api_search'), - ), + ), url(r'^api/v1/toolchains/', include('beat.web.toolchains.api_urls', namespace='api_toolchains'), - ), + ), url(r'^api/v1/plotters/', include('beat.web.plotters.api_urls', namespace='api_plotters'), - ), + ), url(r'^api/v1/reports/', include('beat.web.reports.api_urls', namespace='api_reports'), @@ -181,11 +198,11 @@ unprefixed_patterns += [ # Process an eventual prefix in the URLs parsed_url = urlparse(settings.URL_PREFIX) if (parsed_url.path != '') and (parsed_url.path != '/'): - urlpatterns = [ - url(r'^%s/' % parsed_url.path[1:], include(unprefixed_patterns)), - ] + urlpatterns = [ + url(r'^%s/' % parsed_url.path[1:], include(unprefixed_patterns)), + ] else: - urlpatterns = unprefixed_patterns + urlpatterns = unprefixed_patterns # Static files (only working during development, when settings.DEBUG is True) urlpatterns += staticfiles_urlpatterns() @@ -193,4 +210,4 @@ urlpatterns += staticfiles_urlpatterns() # ONLY DURING THE TESTS: Custom error 500 view if getattr(settings, 'TEST_CONFIGURATION', False): - handler500 = 'beat.web.ui.views.empty_error500_for_tests' + handler500 = 'beat.web.ui.views.empty_error500_for_tests' diff --git a/common.cfg b/common.cfg index bf3dd1c2ec5ca8539783256614f886339ad90d8f..09bd0c7ce1a42d5f8de5fcc0c2ed5d35ad93b180 100644 --- a/common.cfg +++ b/common.cfg @@ -12,7 +12,7 @@ versions = versions [versions] django = >=1.11,<2.0 django-rest-swagger = >2.1 -django-guardian = >=1.3 +django-guardian = >=1.4,<2.0 djangorestframework = >3.7 django-activity-stream = >= 0.6.5 django-jsonfield = >= 1.0.1 diff --git a/dev.yml b/dev.yml index e5c291ccf87ebf298c7993f4fe5598ac542d0cef..60f3caef81231880db1de33a5f7aedcfba0113d1 100644 --- a/dev.yml +++ b/dev.yml @@ -4,13 +4,19 @@ channels: - http://www.idiap.ch/software/beat/conda - defaults dependencies: + - pip + # packages you may pin are here - python=3.6 - - bob-devel=2019.03.07 - - beat-devel=2019.03.07 + - bob-devel=2019.08.28 + - beat-devel=2019.08.28 + + # beat dependencies matching release.cfg + - beat.core=1.9.0 + - beat.backend.python=1.7.2 + - beat.cmdline=1.5.0 # requirements.txt, they are indirectly pinned through the above - - beat.core=1.8 - docopt - docutils - jinja2 @@ -21,7 +27,6 @@ dependencies: - simplejson # these are required for local development, they are not runtime - - beat.cmdline - bob.extension - nose - coverage @@ -36,9 +41,10 @@ dependencies: - pip: - django>=1.11,<2.0 - django-activity-stream>=0.6,<0.7 - - django-guardian>=1.4,<1.5 + - django-guardian>=1.4,<2.0 - django-jsonfield>=1.0,<1.1 - django-jsonfield-compat>=0.4,<0.5 - django-post_office>=3.1,<3.2 - - django-rest-swagger>=2.2,<2.3 + - drf-yasg>=1.16 - djangorestframework>=3.9,<3.10 + - sphinxcontrib-openapi>=0.5.0 diff --git a/doc/admin/index.rst b/doc/admin/index.rst index c8b16c0979efb7d95d651237dc8841cebd68b728..651620fd168e423fae03f15a7dd3d4690e1f0bb2 100644 --- a/doc/admin/index.rst +++ b/doc/admin/index.rst @@ -23,16 +23,15 @@ .. _beat_web_admin: -========================= -BEAT Administrator Guide -========================= +========================== + BEAT Administrator Guide +========================== -BEAT stands for "Biometrics Evaluation And Testing". It is a EC-FP7 sponsored -project to build a web-based, biometry-independent platform for Biometrics +BEAT is a EC-FP7 sponsored +project to build a web-based platform for machine learning research and certification. By making use of such a system, academic or industrial parties enable users to easily compare results from distinct -algorithms or/and parameterizations with minimal interaction using one or -potentially many biometric traits. +algorithms or/and parameterizations with minimal interaction. This document contains resources for system administrators regarding the conception, dimensioning, hardware implementation and installation of a @@ -46,5 +45,6 @@ BEAT platform. applications deployment_guidelines installation + validation backend platform_extension diff --git a/doc/admin/validation.rst b/doc/admin/validation.rst new file mode 100644 index 0000000000000000000000000000000000000000..8d6b45fbf8a889ae0c62d7dd28918efea450a708 --- /dev/null +++ b/doc/admin/validation.rst @@ -0,0 +1,203 @@ +.. vim: set fileencoding=utf-8 : + +.. Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/ .. +.. Contact: beat.support@idiap.ch .. +.. .. +.. This file is part of the beat.web module of the BEAT platform. .. +.. .. +.. Commercial License Usage .. +.. Licensees holding valid commercial BEAT licenses may use this file in .. +.. accordance with the terms contained in a written agreement between you .. +.. and Idiap. For further information contact tto@idiap.ch .. +.. .. +.. Alternatively, this file may be used under the terms of the GNU Affero .. +.. Public License version 3 as published by the Free Software and appearing .. +.. in the file LICENSE.AGPL included in the packaging of this file. .. +.. The BEAT platform is distributed in the hope that it will be useful, but .. +.. WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY .. +.. or FITNESS FOR A PARTICULAR PURPOSE. .. +.. .. +.. You should have received a copy of the GNU Affero Public License along .. +.. with the BEAT platform. If not, see http://www.gnu.org/licenses/. .. + + +.. _validation-web: + +Validation Procedure for web interface +====================================== + +In this section, we briefly explain some sort of "scripted" validation procedure for presentations/tutorials of the BEAT platform. This procedure should be executed ahead of possible presentations. Automated testing as, e.g., with Selenium (http://www.seleniumhq.org/) would be a plus. + + +.. _validation-web-front-page: + +Front page +---------- + +* Hit front page, all components should load (video tutorial), right bar with stats. +* A yellow banner gets the user attention to our terms of service +* The video tutorial should be playable +* The user should be able to browse all public resources on the platform from this page, selecting the link from the top-bar button +* The user should be able to search all public experiments on the platform from this page, using the search box +* The user should be able to login or sign-up using the buttons on this page - in particular, access to the user "tutorial" should be possible through the login page +* The user should be able to click on the "User Guide" button and a user guide should open + + +.. _validation-web-user-page: + +User page +--------- + +* By clicking on the "Home" button on the front page, after login, the user is taken to the "User page" +* The page should display 3 columns, on the left, shared material, on the centre, monitored searchers and on the right, own contributions +* The values for own contributions should make sense w.r.t. material developed by that user +* Clicking on one of the leaderboards should get the user to the related search. + + +.. _validation-web-search: + +Search +------ + +* The omni-search should work from any page +* The search for "eigenface" should lead to a page full of experiments +* It should be possible to configure this search to visualize aggregated results from this page, by narrowing down the analyzer list and hitting "Update" or the keyboard key `<ENTER>` +* Once narrowed down, it should be possible to display aggregated plots +* It should be possible to sort columns by any of the headers in result table and the sorting must work correctly +* It should be possible to register this search for repeating it later +* It should be possible to repeat a stored search +* It should be possible to register to a search creating a leaderboard + + +.. _validation-web-experiments: + +Experiments +----------- + +* It should be possible to fork an existing experiment (I typically use this one: https://www.beat-eu.org/platform/experiments/tutorial/tutorial/eigenface/1/atnt-eigenfaces-5-comp/) and run it by adjusting some parameter, the experiment name and clicking on the button "Run" +* It should be possible to go to the toolchain tab on the experiment configurator page, show the associated toolchain +* That experiment should run in a reasonable amount of time (less than 5 minutes) +* Once the experiment finishes, it should take the user to the experiment "done" page +* The user should receive an e-mail notification that the experiment finished +* It should be possible go from tab to tab in the experiment page +* It should be possible to click on the "Search similar" button on that page and search for similar experiments. When this happens, there should be a list of experiments to which we can compare the recently run experiment with +* The last point implies that updates on the environments, databases or related stuff should be followed up with the test execution of at least the following experiments: tutorial/tutorial/eigenface/1/atnt-eigenfaces-5-comp/, 6, 7, 8, 9 and 10 components +* It should be possible to parallelize blocks in experiments +* It should be possible to change the software environment for globally or on a per-block basis +* There must be more than one environment for selection (typically, a couple Python-based and a C++ based environment) +* It should be possible to change the processing queue either globally or locally in each block +* It should be possible configure block details on a per block basis, besides queue and software enviroment (e.g. parameters) +* Once an experiment is "Done", it should be possible to change its privacy settings +* Changing the privacy settings of an experiment affects all underlying components correctly +* It should be possible to share an experiment with a group, users or make it public +* It should be possible attest (certify) an experiment +* It should be possible to browse to the attestation of an attested experiment by clicking on the icon on the left of the experiment name (on the top of the page) +* If you re-run an experiment that was just executed, the execution of the new experiment is cached and it runs immediately +* During tutorials, it should be possible to run multiple experiments at once since multiple users will try to run concurrently +* Here is a list of experiments that should be checked if underlying changes are performed to the platform: + + * https://www.beat-eu.org/platform/experiments/tutorial/tutorial/eigenface/1/atnt-eigenfaces-5-comp/ + + * https://www.beat-eu.org/platform/experiments/tutorial/tutorial/eigenface_with_preprocessing/1/eigenface-with-preproc-15/ + + * https://www.beat-eu.org/platform/experiments/anjos/ivana7c/simple-antispoofing-updated/1/face-antipoofing-lbp-histogram-comparison/#exec + + * https://www.beat-eu.org/platform/experiments/smarcel/tutorial/digit/2/mnist-mlp-nhu10-niter100-seed2001/ + + + +.. _validation-web-toolchains: + +Toolchains +---------- + +* It should be possible to jump to the associate toolchain from the associated experiment page +* The chosen toolchain is normally this one: https://www.beat-eu.org/platform/toolchains/tutorial/eigenface/1/ +* The toolchain should be displayed. The colors on the links between blocks should be clearly visible +* It should be possible to visit all tabs on the toolchain page +* It should be possible to click on the "[compare]" button on one of the history links +* The documentation for the toolchain should display correctly +* The associated list of experiments should be non-empty +* It should be possible to fork the displayed toolchain +* The toolchain editor should work flawlessly. It should at least be possible to add a single block to the canvas +* It should be possible to create a new toolchain from scratch +* It should be possible to share a toolchain with a group, users or make it public +* Toolchains we normally use for tutorials: + + * https://www.beat-eu.org/platform/toolchains/tutorial/eigenface_with_preprocessing/1/ + + * https://www.beat-eu.org/platform/toolchains/tutorial/eigenface/1/ + + * https://www.beat-eu.org/platform/toolchains/tutorial/digit/2/ + + + +.. _validation-web-algorithms: + +Algorithms +---------- + +* It should be possible to list all algorithms +* It should be possible to fork an algorithm or create one from scratch +* It should be possible to edit an algorithm in Python +* The possibility to upload a C++ algorithm should be there +* It should be possible to share an algorithm with a group, users or make it public +* Algorithms we normally use for tutorials: + + * All from this experiment: https://www.beat-eu.org/platform/experiments/tutorial/tutorial/eigenface_with_preprocessing/1/eigenface-with-preproc-15/#exec + + +.. _validation-web-databases: + +Databases +--------- + +* It should be possible to select "Home" -> "Databases" and display all available databases on the platform. +* The list should be non-empty and contain a number of datasets pre-inserted +* Typically, I use this one: https://www.beat-eu.org/platform/databases/atnt/4/ +* The documentation should be correctly displayed, as well as the protocols page +* The sharing tab should be "Public" +* Databases we normally use for tutorials: + + * https://www.beat-eu.org/platform/databases/atnt/4/ + + +.. _validation-web-attestations: + +Attestations +------------ + +* All assets related to a certified experiment should be either public or "executable" (for algorithms) +* It should be possible to "unlock" an attestation +* It should be possible to delete a "locked" attestation +* The perma-link to a locked attestation should be visitable by an anonymous party + + +.. _validation-web-reports: + +Reports +------- + +(Considering we have moved the features on the staging to production) + +* It should be possible to create a new report and to populate it from the experiment list +* It should be possible to fill-in documentation +* It should be possible to create groups and associate experiments to these groups with aliases +* It should be possible to add documentation cells arbitrarily in each group +* It should be possible to add tables and figures to each group +* It should be possible to lock a report and ready it for publication +* It should be possible to unlock a report and make it return to editable mode +* It should be possible to make a report public and lock it permanently +* Reports we normally mention in tutorials (they must always be working): + + * https://www.beat-eu.org/platform/reports/429641009/ + + * https://www.beat-eu.org/platform/reports/1229989776/ + + * https://www.beat-eu.org/platform/reports/990149671/ + +* Make sure that a MR **DOES NOT** touch the API and breaks the logic which is well tested +* Check that a `locked` report **DOES NOT** have their full name experiments as reviewers are going through it as some point. Which brakes completely the `"blind"` review which would give hints to a reviewer to accept or reject a report due to a possible friendship or not with the person who created the report. +* On a `locked` report people shouldn't be able to click on the experiment names at all, only the alias should be visible +* When creating a table, verify that only the experiment alias is visible for `locked` reports +* When going to the experiments page and adding experiments to a report from there, the pop-up asks if we wish to go to the report with a button `View Report`. When clicking on that button, check that you are sent to the page `https://www.beat-eu.org/platform/reports/<username>/<report>/` diff --git a/doc/api/conf.py b/doc/api/conf.py index f27ad72c997acb219c85bf13a03bda4b5e8e291e..19920e6587f0aaea79519ae91f5fa2bc6fdca35f 100644 --- a/doc/api/conf.py +++ b/doc/api/conf.py @@ -61,6 +61,7 @@ extensions = [ 'sphinx.ext.viewcode', 'sphinxcontrib.programoutput', 'sphinxcontrib.httpdomain', + 'sphinxcontrib.openapi', ] # Always includes todos @@ -145,7 +146,7 @@ pygments_style = 'sphinx' # Some variables which are useful for generated material project_variable = project.replace('.', '_').replace(' ', '_') -short_description = u'Biometrics Evaluation and Testing Platform (Web Modules)' +short_description = u'BEAT Platform (Web Modules)' owner = [u'Idiap Research Institute'] diff --git a/doc/api/specs/swagger.yaml b/doc/api/specs/swagger.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3a81d8cb33057ce4f9f25da0cc1aa01d4a1d340e --- /dev/null +++ b/doc/api/specs/swagger.yaml @@ -0,0 +1,4690 @@ +swagger: '2.0' +info: + title: BEAT API + description: REST API for BEAT platform + termsOfService: https://gitlab.idiap.ch/beat/beat.web/blob/master/LICENSE.AGPL + contact: + email: beat.support@idiap.ch + license: + name: AGPLv3 License + version: v1 +host: 127.0.0.1:8000 +schemes: + - http +basePath: /api/v1 +consumes: + - application/json +produces: + - application/json +securityDefinitions: + Basic: + type: basic +security: + - Basic: [] +paths: + /accounts/: + get: + operationId: accounts_list + description: '' + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/FullSupervisionTrack' + tags: + - accounts + parameters: [] + /accounts/grant_supervisor_access/: + put: + operationId: accounts_grant_supervisor_access_update + description: '' + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + tags: + - accounts + patch: + operationId: accounts_grant_supervisor_access_partial_update + description: '' + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + tags: + - accounts + parameters: [] + /accounts/list_supervisor_candidates/: + get: + operationId: accounts_list_supervisor_candidates_list + description: '' + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/SupervisionTrackUpdate' + tags: + - accounts + parameters: [] + /accounts/remove_supervisor_mode/: + put: + operationId: accounts_remove_supervisor_mode_update + description: '' + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + tags: + - accounts + patch: + operationId: accounts_remove_supervisor_mode_partial_update + description: '' + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + tags: + - accounts + parameters: [] + /accounts/revalidate/: + put: + operationId: accounts_revalidate_update + description: '' + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + tags: + - accounts + patch: + operationId: accounts_revalidate_partial_update + description: '' + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + tags: + - accounts + parameters: [] + /accounts/set_supervisor_mode/: + put: + operationId: accounts_set_supervisor_mode_update + description: '' + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + tags: + - accounts + patch: + operationId: accounts_set_supervisor_mode_partial_update + description: '' + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + tags: + - accounts + parameters: [] + /accounts/{supervisee_name}/remove/: + put: + operationId: accounts_remove_update + description: '' + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + tags: + - accounts + patch: + operationId: accounts_remove_partial_update + description: '' + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + tags: + - accounts + parameters: + - name: supervisee_name + in: path + required: true + type: string + /accounts/{supervisee_name}/validate/: + put: + operationId: accounts_validate_update + description: '' + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + tags: + - accounts + patch: + operationId: accounts_validate_partial_update + description: '' + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + tags: + - accounts + parameters: + - name: supervisee_name + in: path + required: true + type: string + /accounts/{supervisor_name}/add/: + post: + operationId: accounts_add_create + description: '' + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/SupervisionTrackUpdate' + tags: + - accounts + parameters: + - name: supervisor_name + in: path + required: true + type: string + /algorithms/: + get: + operationId: algorithms_list + description: List all available algorithms + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/Algorithm' + tags: + - algorithms + parameters: [] + /algorithms/check_name/: + post: + operationId: algorithms_check_name_create + description: "This view sanitizes an algorithm name and\nchecks whether it is\ + \ already used." + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/CheckName' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/CheckName' + tags: + - algorithms + parameters: [] + /algorithms/diff/{author1}/{name1}/{version1}/{author2}/{name2}/{version2}/: + get: + operationId: algorithms_diff_read + description: This view shows the differences between two algorithms + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/CodeDiff' + tags: + - algorithms + parameters: + - name: author1 + in: path + required: true + type: string + - name: author2 + in: path + required: true + type: string + - name: name1 + in: path + required: true + type: string + - name: name2 + in: path + required: true + type: string + - name: version1 + in: path + required: true + type: string + - name: version2 + in: path + required: true + type: string + /algorithms/{author_name}/: + get: + operationId: algorithms_read + description: "Read/Write end point that list the algorithms available\nfrom\ + \ a given author and allows the creation of new algorithms" + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/Algorithm' + tags: + - algorithms + post: + operationId: algorithms_create + description: "Read/Write end point that list the algorithms available\nfrom\ + \ a given author and allows the creation of new algorithms" + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/AlgorithmCreation' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/AlgorithmCreation' + tags: + - algorithms + parameters: + - name: author_name + in: path + required: true + type: string + /algorithms/{author_name}/{object_name}/: + get: + operationId: algorithms_read + description: Read/Write/Delete endpoint for a given algorithm + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullAlgorithm' + tags: + - algorithms + put: + operationId: algorithms_update + description: Read/Write/Delete endpoint for a given algorithm + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/FullAlgorithm' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullAlgorithm' + tags: + - algorithms + patch: + operationId: algorithms_partial_update + description: Read/Write/Delete endpoint for a given algorithm + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/FullAlgorithm' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullAlgorithm' + tags: + - algorithms + delete: + operationId: algorithms_delete + description: Read/Write/Delete endpoint for a given algorithm + parameters: [] + responses: + '204': + description: '' + tags: + - algorithms + parameters: + - name: author_name + in: path + required: true + type: string + - name: object_name + in: path + required: true + type: string + /algorithms/{author_name}/{object_name}/{version}/: + get: + operationId: algorithms_read + description: Read/Write/Delete endpoint for a given algorithm + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullAlgorithm' + tags: + - algorithms + put: + operationId: algorithms_update + description: Read/Write/Delete endpoint for a given algorithm + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/FullAlgorithm' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullAlgorithm' + tags: + - algorithms + patch: + operationId: algorithms_partial_update + description: Read/Write/Delete endpoint for a given algorithm + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/FullAlgorithm' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullAlgorithm' + tags: + - algorithms + delete: + operationId: algorithms_delete + description: Read/Write/Delete endpoint for a given algorithm + parameters: [] + responses: + '204': + description: '' + tags: + - algorithms + parameters: + - name: author_name + in: path + required: true + type: string + - name: object_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /algorithms/{author_name}/{object_name}/{version}/share/: + post: + operationId: algorithms_share_create + description: "This view allows to share an algorithm with\nother users and/or\ + \ teams" + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/CodeSharing' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/CodeSharing' + tags: + - algorithms + parameters: + - name: author_name + in: path + required: true + type: string + - name: object_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /attestations/: + post: + operationId: attestations_create + description: Create a new attestation + parameters: [] + responses: + '201': + description: '' + tags: + - attestations + parameters: [] + /attestations/unlock/{number}/: + post: + operationId: attestations_unlock_create + description: Unlock a "locked" attestation + parameters: [] + responses: + '201': + description: '' + tags: + - attestations + parameters: + - name: number + in: path + required: true + type: string + /attestations/{number}/: + delete: + operationId: attestations_delete + description: Delete given attestation if locked + parameters: [] + responses: + '204': + description: '' + tags: + - attestations + parameters: + - name: number + in: path + required: true + type: string + /attestations/{username}/: + get: + operationId: attestations_read + description: List all attestations from a given user + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/Attestation' + tags: + - attestations + parameters: + - name: username + in: path + required: true + type: string + /backend/environments/: + get: + operationId: backend_environments_list + description: Returns all accessible environments for a given user + parameters: [] + responses: + '200': + description: '' + tags: + - backend + parameters: [] + /backend/local_scheduler/start/: + post: + operationId: backend_local_scheduler_start_create + description: Starts the local scheduler + parameters: [] + responses: + '201': + description: '' + tags: + - backend + parameters: [] + /backend/local_scheduler/stop/: + post: + operationId: backend_local_scheduler_stop_create + description: Starts the local scheduler + parameters: [] + responses: + '201': + description: '' + tags: + - backend + parameters: [] + /databases/: + get: + operationId: databases_list + description: "Read/Write end point that list the database available\nto a user\ + \ and allows the creation of new databases only to\nplatform administrator" + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/Database' + tags: + - databases + post: + operationId: databases_create + description: "Read/Write end point that list the database available\nto a user\ + \ and allows the creation of new databases only to\nplatform administrator" + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/DatabaseCreation' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/DatabaseCreation' + tags: + - databases + parameters: [] + /databases/templates/: + get: + operationId: databases_templates_list + description: List all templates available + parameters: [] + responses: + '200': + description: '' + tags: + - databases + parameters: [] + /databases/{database_name}/: + get: + operationId: databases_read + description: Returns the given database details + parameters: [] + responses: + '200': + description: '' + tags: + - databases + parameters: + - name: database_name + in: path + required: true + type: string + /databases/{database_name}/{version}/: + get: + operationId: databases_read + description: Returns the given database details + parameters: [] + responses: + '200': + description: '' + tags: + - databases + parameters: + - name: database_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /dataformats/: + get: + operationId: dataformats_list + description: List all available data formats + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/DataFormat' + tags: + - dataformats + parameters: [] + /dataformats/check_name/: + post: + operationId: dataformats_check_name_create + description: "This view sanitizes a data format name and\nchecks whether it\ + \ is already used." + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/CheckName' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/CheckName' + tags: + - dataformats + parameters: [] + /dataformats/diff/{author1}/{name1}/{version1}/{author2}/{name2}/{version2}/: + get: + operationId: dataformats_diff_read + description: This view shows the differences between two data formats + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/Diff' + tags: + - dataformats + parameters: + - name: author1 + in: path + required: true + type: string + - name: author2 + in: path + required: true + type: string + - name: name1 + in: path + required: true + type: string + - name: name2 + in: path + required: true + type: string + - name: version1 + in: path + required: true + type: string + - name: version2 + in: path + required: true + type: string + /dataformats/{author_name}/: + get: + operationId: dataformats_read + description: "Read/Write end point that list the data formats available\nfrom\ + \ a given author and allows the creation of new data formats" + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/DataFormat' + tags: + - dataformats + post: + operationId: dataformats_create + description: "Read/Write end point that list the data formats available\nfrom\ + \ a given author and allows the creation of new data formats" + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/DataFormatCreation' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/DataFormatCreation' + tags: + - dataformats + parameters: + - name: author_name + in: path + required: true + type: string + /dataformats/{author_name}/{object_name}/: + get: + operationId: dataformats_read + description: Read/Write/Delete endpoint for a given data format + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullDataFormat' + tags: + - dataformats + put: + operationId: dataformats_update + description: Read/Write/Delete endpoint for a given data format + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/FullDataFormat' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullDataFormat' + tags: + - dataformats + patch: + operationId: dataformats_partial_update + description: Read/Write/Delete endpoint for a given data format + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/FullDataFormat' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullDataFormat' + tags: + - dataformats + delete: + operationId: dataformats_delete + description: Read/Write/Delete endpoint for a given data format + parameters: [] + responses: + '204': + description: '' + tags: + - dataformats + parameters: + - name: author_name + in: path + required: true + type: string + - name: object_name + in: path + required: true + type: string + /dataformats/{author_name}/{object_name}/{version}/: + get: + operationId: dataformats_read + description: Read/Write/Delete endpoint for a given data format + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullDataFormat' + tags: + - dataformats + put: + operationId: dataformats_update + description: Read/Write/Delete endpoint for a given data format + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/FullDataFormat' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullDataFormat' + tags: + - dataformats + patch: + operationId: dataformats_partial_update + description: Read/Write/Delete endpoint for a given data format + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/FullDataFormat' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullDataFormat' + tags: + - dataformats + delete: + operationId: dataformats_delete + description: Read/Write/Delete endpoint for a given data format + parameters: [] + responses: + '204': + description: '' + tags: + - dataformats + parameters: + - name: author_name + in: path + required: true + type: string + - name: object_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /dataformats/{author_name}/{object_name}/{version}/share/: + post: + operationId: dataformats_share_create + description: "This view allows to share a data format with\nother users and/or\ + \ teams" + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/Sharing' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/Sharing' + tags: + - dataformats + parameters: + - name: author_name + in: path + required: true + type: string + - name: object_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /experiments/: + get: + operationId: experiments_list + description: Return all accessible experiments + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/Experiment' + tags: + - experiments + parameters: [] + /experiments/{attestation_number}/: + get: + operationId: experiments_read + description: "Return the results of the experiment corresponding to\ngiven attestation" + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/ExperimentResults' + tags: + - experiments + parameters: + - name: attestation_number + in: path + required: true + type: string + /experiments/{author_name}/: + get: + operationId: experiments_read + description: "Read/Write end point that list the experiments available\nfrom\ + \ a given author and allows the creation of new experiments" + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/Experiment' + tags: + - experiments + post: + operationId: experiments_create + description: "Read/Write end point that list the experiments available\nfrom\ + \ a given author and allows the creation of new experiments" + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/Experiment' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/Experiment' + tags: + - experiments + parameters: + - name: author_name + in: path + required: true + type: string + /experiments/{author_name}/{toolchain_author_name}/{toolchain_name}/{version}/{name}/: + get: + operationId: experiments_read + description: Read/Write/Delete endpoint for a given experiment + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/ExperimentResults' + tags: + - experiments + put: + operationId: experiments_update + description: Read/Write/Delete endpoint for a given experiment + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/ExperimentResults' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/ExperimentResults' + tags: + - experiments + patch: + operationId: experiments_partial_update + description: Read/Write/Delete endpoint for a given experiment + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/ExperimentResults' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/ExperimentResults' + tags: + - experiments + delete: + operationId: experiments_delete + description: Read/Write/Delete endpoint for a given experiment + parameters: [] + responses: + '204': + description: '' + tags: + - experiments + parameters: + - name: author_name + in: path + required: true + type: string + - name: name + in: path + required: true + type: string + - name: toolchain_author_name + in: path + required: true + type: string + - name: toolchain_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /experiments/{author_name}/{toolchain_author_name}/{toolchain_name}/{version}/{name}/cancel/: + post: + operationId: experiments_cancel_create + description: Cancel a running experiment + parameters: [] + responses: + '201': + description: '' + tags: + - experiments + parameters: + - name: author_name + in: path + required: true + type: string + - name: name + in: path + required: true + type: string + - name: toolchain_author_name + in: path + required: true + type: string + - name: toolchain_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /experiments/{author_name}/{toolchain_author_name}/{toolchain_name}/{version}/{name}/share/: + post: + operationId: experiments_share_create + description: "This view allows to share an experiment with\nother users and/or\ + \ teams" + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/Sharing' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/Sharing' + tags: + - experiments + parameters: + - name: author_name + in: path + required: true + type: string + - name: name + in: path + required: true + type: string + - name: toolchain_author_name + in: path + required: true + type: string + - name: toolchain_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /experiments/{author_name}/{toolchain_author_name}/{toolchain_name}/{version}/{name}/start/: + post: + operationId: experiments_start_create + description: Start to run an experiment + parameters: [] + responses: + '201': + description: '' + tags: + - experiments + parameters: + - name: author_name + in: path + required: true + type: string + - name: name + in: path + required: true + type: string + - name: toolchain_author_name + in: path + required: true + type: string + - name: toolchain_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /experiments/{author_name}/{toolchain_name}/{version}/{name}/: + get: + operationId: experiments_read + description: Read/Write/Delete endpoint for a given experiment + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/ExperimentResults' + tags: + - experiments + put: + operationId: experiments_update + description: Read/Write/Delete endpoint for a given experiment + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/ExperimentResults' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/ExperimentResults' + tags: + - experiments + patch: + operationId: experiments_partial_update + description: Read/Write/Delete endpoint for a given experiment + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/ExperimentResults' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/ExperimentResults' + tags: + - experiments + delete: + operationId: experiments_delete + description: Read/Write/Delete endpoint for a given experiment + parameters: [] + responses: + '204': + description: '' + tags: + - experiments + parameters: + - name: author_name + in: path + required: true + type: string + - name: name + in: path + required: true + type: string + - name: toolchain_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /experiments/{author_name}/{toolchain_name}/{version}/{name}/cancel/: + post: + operationId: experiments_cancel_create + description: Cancel a running experiment + parameters: [] + responses: + '201': + description: '' + tags: + - experiments + parameters: + - name: author_name + in: path + required: true + type: string + - name: name + in: path + required: true + type: string + - name: toolchain_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /experiments/{author_name}/{toolchain_name}/{version}/{name}/share/: + post: + operationId: experiments_share_create + description: "This view allows to share an experiment with\nother users and/or\ + \ teams" + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/Sharing' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/Sharing' + tags: + - experiments + parameters: + - name: author_name + in: path + required: true + type: string + - name: name + in: path + required: true + type: string + - name: toolchain_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /experiments/{author_name}/{toolchain_name}/{version}/{name}/start/: + post: + operationId: experiments_start_create + description: Start to run an experiment + parameters: [] + responses: + '201': + description: '' + tags: + - experiments + parameters: + - name: author_name + in: path + required: true + type: string + - name: name + in: path + required: true + type: string + - name: toolchain_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /libraries/: + get: + operationId: libraries_list + description: List all available libraries + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/Library' + tags: + - libraries + parameters: [] + /libraries/check_name/: + post: + operationId: libraries_check_name_create + description: "This view sanitizes a library name and\nchecks whether it is already\ + \ used." + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/CheckName' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/CheckName' + tags: + - libraries + parameters: [] + /libraries/diff/{author1}/{name1}/{version1}/{author2}/{name2}/{version2}/: + get: + operationId: libraries_diff_read + description: This view shows the differences between two libraries + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/CodeDiff' + tags: + - libraries + parameters: + - name: author1 + in: path + required: true + type: string + - name: author2 + in: path + required: true + type: string + - name: name1 + in: path + required: true + type: string + - name: name2 + in: path + required: true + type: string + - name: version1 + in: path + required: true + type: string + - name: version2 + in: path + required: true + type: string + /libraries/{author_name}/: + get: + operationId: libraries_read + description: "Read/Write end point that list the libraries available\nfrom a\ + \ given author and allows the creation of new libraries" + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/Library' + tags: + - libraries + post: + operationId: libraries_create + description: "Read/Write end point that list the libraries available\nfrom a\ + \ given author and allows the creation of new libraries" + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/LibraryCreation' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/LibraryCreation' + tags: + - libraries + parameters: + - name: author_name + in: path + required: true + type: string + /libraries/{author_name}/{object_name}/: + get: + operationId: libraries_read + description: Read/Write/Delete endpoint for a given library + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullLibrary' + tags: + - libraries + put: + operationId: libraries_update + description: Read/Write/Delete endpoint for a given library + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/FullLibrary' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullLibrary' + tags: + - libraries + patch: + operationId: libraries_partial_update + description: Read/Write/Delete endpoint for a given library + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/FullLibrary' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullLibrary' + tags: + - libraries + delete: + operationId: libraries_delete + description: Read/Write/Delete endpoint for a given library + parameters: [] + responses: + '204': + description: '' + tags: + - libraries + parameters: + - name: author_name + in: path + required: true + type: string + - name: object_name + in: path + required: true + type: string + /libraries/{author_name}/{object_name}/{version}/: + get: + operationId: libraries_read + description: Read/Write/Delete endpoint for a given library + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullLibrary' + tags: + - libraries + put: + operationId: libraries_update + description: Read/Write/Delete endpoint for a given library + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/FullLibrary' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullLibrary' + tags: + - libraries + patch: + operationId: libraries_partial_update + description: Read/Write/Delete endpoint for a given library + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/FullLibrary' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullLibrary' + tags: + - libraries + delete: + operationId: libraries_delete + description: Read/Write/Delete endpoint for a given library + parameters: [] + responses: + '204': + description: '' + tags: + - libraries + parameters: + - name: author_name + in: path + required: true + type: string + - name: object_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /libraries/{author_name}/{object_name}/{version}/share/: + post: + operationId: libraries_share_create + description: "This view allows to share a library with\nother users and/or teams" + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/CodeSharing' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/CodeSharing' + tags: + - libraries + parameters: + - name: author_name + in: path + required: true + type: string + - name: object_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /plotters/: + get: + operationId: plotters_list + description: List all available plotters + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/Plotter' + tags: + - plotters + parameters: [] + /plotters/check_name/: + post: + operationId: plotters_check_name_create + description: "This view sanitizes a Plotter name and\nchecks whether it is already\ + \ used." + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/CheckName' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/CheckName' + tags: + - plotters + parameters: [] + /plotters/defaultplotters/: + get: + operationId: plotters_defaultplotters_list + description: List all available plotters + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/DefaultPlotter' + tags: + - plotters + parameters: [] + /plotters/format/{author_name}/{dataformat_name}/{version}/: + get: + operationId: plotters_format_read + description: List all plotters corresponding to the given dataformat + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/Plotter' + tags: + - plotters + parameters: + - name: author_name + in: path + required: true + type: string + - name: dataformat_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /plotters/plotterparameter/{author_name}/{dataformat_name}/{version}/: + get: + operationId: plotters_plotterparameter_read + description: List all available plotters parameters + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/PlotterParameter' + tags: + - plotters + parameters: + - name: author_name + in: path + required: true + type: string + - name: dataformat_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /plotters/plotterparameters/: + get: + operationId: plotters_plotterparameters_list + description: List all available plotters parameters + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/PlotterParameter' + tags: + - plotters + parameters: [] + /plotters/plotterparameters/{author_name}/: + get: + operationId: plotters_plotterparameters_read + description: List all available PlotterParameters + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/FullPlotterParameter' + tags: + - plotters + post: + operationId: plotters_plotterparameters_create + description: List all available PlotterParameters + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/PlotterParameterCreation' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/PlotterParameterCreation' + tags: + - plotters + parameters: + - name: author_name + in: path + required: true + type: string + /plotters/plotterparameters/{author_name}/{object_name}/{version}/: + get: + operationId: plotters_plotterparameters_read + description: Read/Write/Delete endpoint for a given PlotterParameter + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullPlotterParameter' + tags: + - plotters + put: + operationId: plotters_plotterparameters_update + description: Read/Write/Delete endpoint for a given PlotterParameter + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/FullPlotterParameter' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullPlotterParameter' + tags: + - plotters + patch: + operationId: plotters_plotterparameters_partial_update + description: Read/Write/Delete endpoint for a given PlotterParameter + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/FullPlotterParameter' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullPlotterParameter' + tags: + - plotters + delete: + operationId: plotters_plotterparameters_delete + description: Read/Write/Delete endpoint for a given PlotterParameter + parameters: [] + responses: + '204': + description: '' + tags: + - plotters + parameters: + - name: author_name + in: path + required: true + type: string + - name: object_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /plotters/plotterparameters/{author_name}/{object_name}/{version}/share/: + post: + operationId: plotters_plotterparameters_share_create + description: "This view allows to share a PlotterParameter with\nother users\ + \ and/or teams" + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/Sharing' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/Sharing' + tags: + - plotters + parameters: + - name: author_name + in: path + required: true + type: string + - name: object_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /plotters/{author_name}/: + get: + operationId: plotters_read + description: "Read/Write end point that list the plotters available\nfrom a\ + \ given author and allows the creation of new plotters" + parameters: [] + responses: + '200': + description: '' + tags: + - plotters + post: + operationId: plotters_create + description: "Read/Write end point that list the plotters available\nfrom a\ + \ given author and allows the creation of new plotters" + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/PlotterCreation' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/PlotterCreation' + tags: + - plotters + parameters: + - name: author_name + in: path + required: true + type: string + /plotters/{author_name}/{object_name}/{version}/: + get: + operationId: plotters_read + description: Read/Write/Delete endpoint for a given plotter + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullPlotter' + tags: + - plotters + put: + operationId: plotters_update + description: Read/Write/Delete endpoint for a given plotter + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/FullPlotter' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullPlotter' + tags: + - plotters + patch: + operationId: plotters_partial_update + description: Read/Write/Delete endpoint for a given plotter + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/FullPlotter' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullPlotter' + tags: + - plotters + delete: + operationId: plotters_delete + description: Read/Write/Delete endpoint for a given plotter + parameters: [] + responses: + '204': + description: '' + tags: + - plotters + parameters: + - name: author_name + in: path + required: true + type: string + - name: object_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /reports/: + get: + operationId: reports_list + description: '' + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/SimpleReport' + tags: + - reports + parameters: [] + /reports/{number}/: + get: + operationId: reports_read + description: '' + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullReport' + tags: + - reports + put: + operationId: reports_update + description: '' + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/ReportUpdate' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/ReportUpdate' + tags: + - reports + patch: + operationId: reports_partial_update + description: '' + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/ReportUpdate' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/ReportUpdate' + tags: + - reports + delete: + operationId: reports_delete + description: '' + parameters: [] + responses: + '204': + description: '' + tags: + - reports + parameters: + - name: number + in: path + required: true + type: string + /reports/{number}/results/: + get: + operationId: reports_results_read + description: '' + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/ExperimentResults' + tags: + - reports + parameters: + - name: number + in: path + required: true + type: string + /reports/{number}/rst/: + post: + operationId: reports_rst_create + description: '' + parameters: [] + responses: + '201': + description: '' + tags: + - reports + parameters: + - name: number + in: path + required: true + type: string + /reports/{owner_name}/: + get: + operationId: reports_read + description: '' + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/SimpleReport' + tags: + - reports + post: + operationId: reports_create + description: '' + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/ReportCreation' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/ReportCreation' + tags: + - reports + parameters: + - name: owner_name + in: path + required: true + type: string + /reports/{owner_name}/{report_name}/: + get: + operationId: reports_read + description: '' + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullReport' + tags: + - reports + put: + operationId: reports_update + description: '' + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/ReportUpdate' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/ReportUpdate' + tags: + - reports + patch: + operationId: reports_partial_update + description: '' + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/ReportUpdate' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/ReportUpdate' + tags: + - reports + delete: + operationId: reports_delete + description: '' + parameters: [] + responses: + '204': + description: '' + tags: + - reports + parameters: + - name: owner_name + in: path + required: true + type: string + - name: report_name + in: path + required: true + type: string + /reports/{owner_name}/{report_name}/add/: + post: + operationId: reports_add_create + description: '' + parameters: [] + responses: + '201': + description: '' + tags: + - reports + parameters: + - name: owner_name + in: path + required: true + type: string + - name: report_name + in: path + required: true + type: string + /reports/{owner_name}/{report_name}/algorithms/: + get: + operationId: reports_algorithms_list + description: '' + parameters: [] + responses: + '200': + description: '' + tags: + - reports + parameters: + - name: owner_name + in: path + required: true + type: string + - name: report_name + in: path + required: true + type: string + /reports/{owner_name}/{report_name}/lock/: + post: + operationId: reports_lock_create + description: '' + parameters: [] + responses: + '201': + description: '' + tags: + - reports + parameters: + - name: owner_name + in: path + required: true + type: string + - name: report_name + in: path + required: true + type: string + /reports/{owner_name}/{report_name}/publish/: + post: + operationId: reports_publish_create + description: '' + parameters: [] + responses: + '201': + description: '' + tags: + - reports + parameters: + - name: owner_name + in: path + required: true + type: string + - name: report_name + in: path + required: true + type: string + /reports/{owner_name}/{report_name}/remove/: + post: + operationId: reports_remove_create + description: '' + parameters: [] + responses: + '201': + description: '' + tags: + - reports + parameters: + - name: owner_name + in: path + required: true + type: string + - name: report_name + in: path + required: true + type: string + /reports/{owner_name}/{report_name}/results_author/: + get: + operationId: reports_results_author_read + description: '' + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/ExperimentResults' + tags: + - reports + parameters: + - name: owner_name + in: path + required: true + type: string + - name: report_name + in: path + required: true + type: string + /reports/{owner_name}/{report_name}/rst/: + post: + operationId: reports_rst_create + description: '' + parameters: [] + responses: + '201': + description: '' + tags: + - reports + parameters: + - name: owner_name + in: path + required: true + type: string + - name: report_name + in: path + required: true + type: string + /search/: + post: + operationId: search_create + summary: Search endpoint + description: "This view allows to run a search through the various\nelements\ + \ composing the beat platform either using a\nquery which will run a global\ + \ search or by using filters\nthat will restrict the search to the given domains.\n\ + \nAvailable filters are:\n'results', 'toolchains', 'algorithms', 'dataformats',\ + \ 'databases', 'users'\nAvailable options are:\n'order-by'" + parameters: [] + responses: + '201': + description: '' + tags: + - search + parameters: [] + /search/list/{author_name}/: + get: + operationId: search_list_read + description: Lists all available search from a user + parameters: [] + responses: + '200': + description: '' + tags: + - search + parameters: + - name: author_name + in: path + required: true + type: string + /search/save/: + post: + operationId: search_save_create + summary: This endpoint allows to save and update a search query + description: "Saving a search allows to re-run the same query later\nwithout\ + \ having to redo the query/filtering which might get\ncomplex.\n\nNote that\ + \ two consecutive runs of a search might yield\ndifferent results" + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/SearchWrite' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/SearchWrite' + tags: + - search + put: + operationId: search_save_update + summary: This endpoint allows to save and update a search query + description: "Saving a search allows to re-run the same query later\nwithout\ + \ having to redo the query/filtering which might get\ncomplex.\n\nNote that\ + \ two consecutive runs of a search might yield\ndifferent results" + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/SearchWrite' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/SearchWrite' + tags: + - search + patch: + operationId: search_save_partial_update + summary: This endpoint allows to save and update a search query + description: "Saving a search allows to re-run the same query later\nwithout\ + \ having to redo the query/filtering which might get\ncomplex.\n\nNote that\ + \ two consecutive runs of a search might yield\ndifferent results" + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/SearchWrite' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/SearchWrite' + tags: + - search + parameters: [] + /search/save/{author_name}/{name}/: + post: + operationId: search_save_create + summary: This endpoint allows to save and update a search query + description: "Saving a search allows to re-run the same query later\nwithout\ + \ having to redo the query/filtering which might get\ncomplex.\n\nNote that\ + \ two consecutive runs of a search might yield\ndifferent results" + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/SearchWrite' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/SearchWrite' + tags: + - search + put: + operationId: search_save_update + summary: This endpoint allows to save and update a search query + description: "Saving a search allows to re-run the same query later\nwithout\ + \ having to redo the query/filtering which might get\ncomplex.\n\nNote that\ + \ two consecutive runs of a search might yield\ndifferent results" + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/SearchWrite' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/SearchWrite' + tags: + - search + patch: + operationId: search_save_partial_update + summary: This endpoint allows to save and update a search query + description: "Saving a search allows to re-run the same query later\nwithout\ + \ having to redo the query/filtering which might get\ncomplex.\n\nNote that\ + \ two consecutive runs of a search might yield\ndifferent results" + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/SearchWrite' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/SearchWrite' + tags: + - search + parameters: + - name: author_name + in: path + required: true + type: string + - name: name + in: path + required: true + type: string + /search/share/{author_name}/{object_name}/: + post: + operationId: search_share_create + description: Share the given search with other users/teams + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/Sharing' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/Sharing' + tags: + - search + parameters: + - name: author_name + in: path + required: true + type: string + - name: object_name + in: path + required: true + type: string + /search/{author_name}/{object_name}/: + get: + operationId: search_read + description: Delete the given search + parameters: [] + responses: + '200': + description: '' + tags: + - search + delete: + operationId: search_delete + description: Delete the given search + parameters: [] + responses: + '204': + description: '' + tags: + - search + parameters: + - name: author_name + in: path + required: true + type: string + - name: object_name + in: path + required: true + type: string + /teams/: + get: + operationId: teams_list + description: List all teams of the caller + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/SimpleTeam' + tags: + - teams + parameters: [] + /teams/{owner_name}/: + get: + operationId: teams_read + description: Lists the team from a user and create new teams + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/SimpleTeam' + tags: + - teams + post: + operationId: teams_create + description: Lists the team from a user and create new teams + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/TeamCreation' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/TeamCreation' + tags: + - teams + parameters: + - name: owner_name + in: path + required: true + type: string + /teams/{owner_name}/{team_name}/: + get: + operationId: teams_read + description: This view provides the details of a team + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullTeam' + tags: + - teams + put: + operationId: teams_update + description: This view provides the details of a team + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/TeamUpdate' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/TeamUpdate' + tags: + - teams + patch: + operationId: teams_partial_update + description: This view provides the details of a team + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/TeamUpdate' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/TeamUpdate' + tags: + - teams + delete: + operationId: teams_delete + description: This view provides the details of a team + parameters: [] + responses: + '204': + description: '' + tags: + - teams + parameters: + - name: owner_name + in: path + required: true + type: string + - name: team_name + in: path + required: true + type: string + /toolchains/: + get: + operationId: toolchains_list + description: List all available toolchains + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/Toolchain' + tags: + - toolchains + parameters: [] + /toolchains/check_name/: + post: + operationId: toolchains_check_name_create + description: "This view sanitizes a toolchain name and\nchecks whether it is\ + \ already used." + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/CheckName' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/CheckName' + tags: + - toolchains + parameters: [] + /toolchains/{author_name}/: + get: + operationId: toolchains_read + description: "Read/Write end point that list the toolchains available\nfrom\ + \ a given author and allows the creation of new toolchains" + parameters: [] + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/Toolchain' + tags: + - toolchains + post: + operationId: toolchains_create + description: "Read/Write end point that list the toolchains available\nfrom\ + \ a given author and allows the creation of new toolchains" + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/ToolchainCreation' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/ToolchainCreation' + tags: + - toolchains + parameters: + - name: author_name + in: path + required: true + type: string + /toolchains/{author_name}/{object_name}/: + get: + operationId: toolchains_read + description: Read/Write/Delete endpoint for a given toolchain + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullToolchain' + tags: + - toolchains + put: + operationId: toolchains_update + description: Read/Write/Delete endpoint for a given toolchain + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/FullToolchain' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullToolchain' + tags: + - toolchains + patch: + operationId: toolchains_partial_update + description: Read/Write/Delete endpoint for a given toolchain + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/FullToolchain' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullToolchain' + tags: + - toolchains + delete: + operationId: toolchains_delete + description: Read/Write/Delete endpoint for a given toolchain + parameters: [] + responses: + '204': + description: '' + tags: + - toolchains + parameters: + - name: author_name + in: path + required: true + type: string + - name: object_name + in: path + required: true + type: string + /toolchains/{author_name}/{object_name}/{version}/: + get: + operationId: toolchains_read + description: Read/Write/Delete endpoint for a given toolchain + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullToolchain' + tags: + - toolchains + put: + operationId: toolchains_update + description: Read/Write/Delete endpoint for a given toolchain + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/FullToolchain' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullToolchain' + tags: + - toolchains + patch: + operationId: toolchains_partial_update + description: Read/Write/Delete endpoint for a given toolchain + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/FullToolchain' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/FullToolchain' + tags: + - toolchains + delete: + operationId: toolchains_delete + description: Read/Write/Delete endpoint for a given toolchain + parameters: [] + responses: + '204': + description: '' + tags: + - toolchains + parameters: + - name: author_name + in: path + required: true + type: string + - name: object_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string + /toolchains/{author_name}/{object_name}/{version}/share/: + post: + operationId: toolchains_share_create + description: "This view allows to share a toolchain with\nother users and/or\ + \ teams" + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/Sharing' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/Sharing' + tags: + - toolchains + parameters: + - name: author_name + in: path + required: true + type: string + - name: object_name + in: path + required: true + type: string + - name: version + in: path + required: true + type: string +definitions: + User: + title: Supervisee + type: object + properties: + username: + title: Username + type: string + readOnly: true + email: + title: Email + type: string + readOnly: true + FullSupervisionTrack: + required: + - supervisee + - supervisor + type: object + properties: + supervisee: + $ref: '#/definitions/User' + supervisor: + $ref: '#/definitions/User' + is_valid: + title: Is valid + type: string + readOnly: true + start_date: + title: Start date + type: string + readOnly: true + expiration_date: + title: Expiration date + type: string + readOnly: true + last_validation_date: + title: Last validation date + type: string + readOnly: true + supervision_key: + title: Supervision key + type: string + readOnly: true + SupervisionTrackUpdate: + type: object + properties: + is_valid: + title: Is valid + type: string + readOnly: true + Algorithm: + required: + - modifiable + - deletable + - name + - short_description + - valid + type: object + properties: + accessibility: + title: Accessibility + type: string + readOnly: true + sharing: + title: Sharing + type: string + readOnly: true + modifiable: + title: Modifiable + type: boolean + deletable: + title: Deletable + type: boolean + is_owner: + title: Is owner + type: string + readOnly: true + name: + title: Name + type: string + minLength: 1 + fork_of: + title: Fork of + type: string + readOnly: true + last_version: + title: Last version + type: string + readOnly: true + previous_version: + title: Previous version + type: string + readOnly: true + short_description: + title: Short description + type: string + maxLength: 100 + minLength: 1 + opensource: + title: Opensource + type: string + readOnly: true + language: + title: Language + type: string + readOnly: true + valid: + title: Valid + type: boolean + version: + title: Version + description: The version of this object (an integer starting from 1) + type: integer + default: 1 + creation_date: + title: Creation date + type: string + format: date-time + readOnly: true + hash: + title: Hash + description: Hashed value of the object contents (<a href="https://docs.python.org/2/library/hashlib.html">SHA256, + hexadecimal digest</a>). This field is auto-generated and managed by the + platform. + type: string + readOnly: true + minLength: 1 + CheckName: + required: + - name + type: object + properties: + name: + title: Name + type: string + minLength: 1 + used: + title: Used + type: string + readOnly: true + CodeDiff: + type: object + properties: + diff: + title: Diff + type: string + readOnly: true + source_code_diff: + title: Source code diff + type: string + readOnly: true + AlgorithmCreation: + required: + - name + type: object + properties: + name: + title: Name + description: The name for this object (space-like characters will be automatically + replaced by dashes) + type: string + maxLength: 200 + minLength: 1 + short_description: + title: Short description + description: Describe the object succinctly (try to keep it under 80 characters) + type: string + maxLength: 100 + description: + title: Description + type: string + declaration: + title: Declaration + type: string + previous_version: + title: Previous version + type: string + minLength: 1 + fork_of: + title: Fork of + type: string + code: + title: Code + type: string + language: + title: Language + type: string + enum: + - U + - C + - M + - P + - R + FullAlgorithm: + required: + - modifiable + - deletable + - name + - short_description + - valid + type: object + properties: + accessibility: + title: Accessibility + type: string + readOnly: true + sharing: + title: Sharing + type: string + readOnly: true + modifiable: + title: Modifiable + type: boolean + deletable: + title: Deletable + type: boolean + is_owner: + title: Is owner + type: string + readOnly: true + name: + title: Name + type: string + minLength: 1 + fork_of: + title: Fork of + type: string + readOnly: true + last_version: + title: Last version + type: string + readOnly: true + previous_version: + title: Previous version + type: string + readOnly: true + short_description: + title: Short description + type: string + maxLength: 100 + minLength: 1 + code: + title: Code + type: string + readOnly: true + description: + title: Description + type: string + readOnly: true + declaration: + title: Declaration + type: string + readOnly: true + opensource: + title: Opensource + type: string + readOnly: true + language: + title: Language + type: string + readOnly: true + valid: + title: Valid + type: boolean + version: + title: Version + description: The version of this object (an integer starting from 1) + type: integer + default: 1 + creation_date: + title: Creation date + type: string + format: date-time + readOnly: true + hash: + title: Hash + description: Hashed value of the object contents (<a href="https://docs.python.org/2/library/hashlib.html">SHA256, + hexadecimal digest</a>). This field is auto-generated and managed by the + platform. + type: string + readOnly: true + minLength: 1 + CodeSharing: + required: + - status + type: object + properties: + users: + type: array + items: + type: string + minLength: 1 + teams: + type: array + items: + type: string + minLength: 1 + status: + title: Status + type: string + minLength: 1 + Attestation: + required: + - number + - experiment + - creation_date + - toolchain + - nb_dataformats + - nb_algorithms + type: object + properties: + number: + title: Number + type: integer + experiment: + title: Experiment + type: string + minLength: 1 + locked: + title: Locked + type: boolean + creation_date: + title: Creation date + type: string + format: date-time + expiration_date: + title: Expiration date + type: string + format: date-time + x-nullable: true + publication_date: + title: Publication date + type: string + format: date-time + x-nullable: true + toolchain: + title: Toolchain + type: string + minLength: 1 + nb_dataformats: + title: Nb dataformats + type: integer + nb_algorithms: + title: Nb algorithms + type: integer + Database: + required: + - modifiable + - deletable + - name + - short_description + type: object + properties: + accessibility: + title: Accessibility + type: string + readOnly: true + sharing: + title: Sharing + type: string + readOnly: true + modifiable: + title: Modifiable + type: boolean + deletable: + title: Deletable + type: boolean + is_owner: + title: Is owner + type: string + readOnly: true + name: + title: Name + type: string + minLength: 1 + fork_of: + title: Fork of + type: string + readOnly: true + last_version: + title: Last version + type: string + readOnly: true + previous_version: + title: Previous version + type: string + readOnly: true + short_description: + title: Short description + type: string + maxLength: 100 + minLength: 1 + version: + title: Version + description: The version of this object (an integer starting from 1) + type: integer + default: 1 + creation_date: + title: Creation date + type: string + format: date-time + readOnly: true + hash: + title: Hash + description: Hashed value of the object contents (<a href="https://docs.python.org/2/library/hashlib.html">SHA256, + hexadecimal digest</a>). This field is auto-generated and managed by the + platform. + type: string + readOnly: true + minLength: 1 + DatabaseCreation: + required: + - name + type: object + properties: + name: + title: Name + description: The name for this object (space-like characters will be automatically + replaced by dashes) + type: string + maxLength: 200 + minLength: 1 + short_description: + title: Short description + description: Describe the object succinctly (try to keep it under 80 characters) + type: string + maxLength: 100 + description: + title: Description + type: string + declaration: + title: Declaration + type: string + code: + title: Code + type: string + minLength: 1 + previous_version: + title: Previous version + type: string + minLength: 1 + DataFormat: + required: + - modifiable + - deletable + - name + - short_description + type: object + properties: + accessibility: + title: Accessibility + type: string + readOnly: true + sharing: + title: Sharing + type: string + readOnly: true + modifiable: + title: Modifiable + type: boolean + deletable: + title: Deletable + type: boolean + is_owner: + title: Is owner + type: string + readOnly: true + name: + title: Name + type: string + minLength: 1 + fork_of: + title: Fork of + type: string + readOnly: true + last_version: + title: Last version + type: string + readOnly: true + previous_version: + title: Previous version + type: string + readOnly: true + short_description: + title: Short description + type: string + maxLength: 100 + minLength: 1 + extend: + title: Extend + type: string + readOnly: true + version: + title: Version + description: The version of this object (an integer starting from 1) + type: integer + default: 1 + creation_date: + title: Creation date + type: string + format: date-time + readOnly: true + hash: + title: Hash + description: Hashed value of the object contents (<a href="https://docs.python.org/2/library/hashlib.html">SHA256, + hexadecimal digest</a>). This field is auto-generated and managed by the + platform. + type: string + readOnly: true + minLength: 1 + Diff: + type: object + properties: + diff: + title: Diff + type: string + readOnly: true + DataFormatCreation: + required: + - name + type: object + properties: + name: + title: Name + description: The name for this object (space-like characters will be automatically + replaced by dashes) + type: string + maxLength: 200 + minLength: 1 + short_description: + title: Short description + description: Describe the object succinctly (try to keep it under 80 characters) + type: string + maxLength: 100 + description: + title: Description + type: string + declaration: + title: Declaration + type: string + previous_version: + title: Previous version + type: string + minLength: 1 + fork_of: + title: Fork of + type: string + FullDataFormat: + required: + - modifiable + - deletable + - name + - short_description + type: object + properties: + accessibility: + title: Accessibility + type: string + readOnly: true + sharing: + title: Sharing + type: string + readOnly: true + modifiable: + title: Modifiable + type: boolean + deletable: + title: Deletable + type: boolean + is_owner: + title: Is owner + type: string + readOnly: true + name: + title: Name + type: string + minLength: 1 + fork_of: + title: Fork of + type: string + readOnly: true + last_version: + title: Last version + type: string + readOnly: true + previous_version: + title: Previous version + type: string + readOnly: true + short_description: + title: Short description + type: string + maxLength: 100 + minLength: 1 + description: + title: Description + type: string + readOnly: true + declaration: + title: Declaration + type: string + readOnly: true + extend: + title: Extend + type: string + readOnly: true + version: + title: Version + description: The version of this object (an integer starting from 1) + type: integer + default: 1 + creation_date: + title: Creation date + type: string + format: date-time + readOnly: true + hash: + title: Hash + description: Hashed value of the object contents (<a href="https://docs.python.org/2/library/hashlib.html">SHA256, + hexadecimal digest</a>). This field is auto-generated and managed by the + platform. + type: string + readOnly: true + minLength: 1 + Sharing: + type: object + properties: + users: + type: array + items: + type: string + minLength: 1 + teams: + type: array + items: + type: string + minLength: 1 + Experiment: + required: + - modifiable + - deletable + - name + - toolchain + - status + - attestation_number + - attestation_locked + type: object + properties: + accessibility: + title: Accessibility + type: string + readOnly: true + sharing: + title: Sharing + type: string + readOnly: true + modifiable: + title: Modifiable + type: boolean + deletable: + title: Deletable + type: boolean + is_owner: + title: Is owner + type: string + readOnly: true + name: + title: Name + type: string + minLength: 1 + toolchain: + title: Toolchain + type: string + minLength: 1 + datasets: + title: Datasets + type: string + readOnly: true + duration: + title: Duration + type: string + readOnly: true + status: + title: Status + type: string + minLength: 1 + attestation_number: + title: Attestation number + type: integer + attestation_locked: + title: Attestation locked + type: boolean + cpu_time: + title: Cpu time + type: string + readOnly: true + data_read: + title: Data read + type: string + readOnly: true + data_written: + title: Data written + type: string + readOnly: true + short_description: + title: Short description + description: Describe the object succinctly (try to keep it under 80 characters) + type: string + maxLength: 100 + creation_date: + title: Creation date + type: string + format: date-time + readOnly: true + start_date: + title: Start date + type: string + format: date-time + x-nullable: true + end_date: + title: End date + type: string + format: date-time + x-nullable: true + ExperimentResults: + required: + - attestation + - status + - declaration + type: object + properties: + accessibility: + title: Accessibility + type: string + readOnly: true + sharing: + title: Sharing + type: string + readOnly: true + started: + title: Started + type: string + readOnly: true + done: + title: Done + type: string + readOnly: true + failed: + title: Failed + type: string + readOnly: true + attestation: + title: Attestation + type: integer + blocks_status: + title: Blocks status + type: string + readOnly: true + execution_info: + title: Execution info + type: string + readOnly: true + execution_order: + title: Execution order + type: string + readOnly: true + status: + title: Status + type: string + minLength: 1 + results: + title: Results + type: string + readOnly: true + errors: + title: Errors + type: string + readOnly: true + declaration: + title: Declaration + type: string + Library: + required: + - modifiable + - deletable + - name + - short_description + - valid + type: object + properties: + accessibility: + title: Accessibility + type: string + readOnly: true + sharing: + title: Sharing + type: string + readOnly: true + modifiable: + title: Modifiable + type: boolean + deletable: + title: Deletable + type: boolean + is_owner: + title: Is owner + type: string + readOnly: true + name: + title: Name + type: string + minLength: 1 + fork_of: + title: Fork of + type: string + readOnly: true + last_version: + title: Last version + type: string + readOnly: true + previous_version: + title: Previous version + type: string + readOnly: true + short_description: + title: Short description + type: string + maxLength: 100 + minLength: 1 + opensource: + title: Opensource + type: string + readOnly: true + language: + title: Language + type: string + readOnly: true + valid: + title: Valid + type: boolean + version: + title: Version + description: The version of this object (an integer starting from 1) + type: integer + default: 1 + creation_date: + title: Creation date + type: string + format: date-time + readOnly: true + hash: + title: Hash + description: Hashed value of the object contents (<a href="https://docs.python.org/2/library/hashlib.html">SHA256, + hexadecimal digest</a>). This field is auto-generated and managed by the + platform. + type: string + readOnly: true + minLength: 1 + LibraryCreation: + required: + - name + type: object + properties: + name: + title: Name + description: The name for this object (space-like characters will be automatically + replaced by dashes) + type: string + maxLength: 200 + minLength: 1 + short_description: + title: Short description + description: Describe the object succinctly (try to keep it under 80 characters) + type: string + maxLength: 100 + description: + title: Description + type: string + declaration: + title: Declaration + type: string + previous_version: + title: Previous version + type: string + minLength: 1 + fork_of: + title: Fork of + type: string + code: + title: Code + type: string + language: + title: Language + type: string + enum: + - U + - C + - M + - P + - R + FullLibrary: + required: + - modifiable + - deletable + - name + - short_description + - valid + type: object + properties: + accessibility: + title: Accessibility + type: string + readOnly: true + sharing: + title: Sharing + type: string + readOnly: true + modifiable: + title: Modifiable + type: boolean + deletable: + title: Deletable + type: boolean + is_owner: + title: Is owner + type: string + readOnly: true + name: + title: Name + type: string + minLength: 1 + fork_of: + title: Fork of + type: string + readOnly: true + last_version: + title: Last version + type: string + readOnly: true + previous_version: + title: Previous version + type: string + readOnly: true + short_description: + title: Short description + type: string + maxLength: 100 + minLength: 1 + code: + title: Code + type: string + readOnly: true + description: + title: Description + type: string + readOnly: true + declaration: + title: Declaration + type: string + readOnly: true + opensource: + title: Opensource + type: string + readOnly: true + language: + title: Language + type: string + readOnly: true + valid: + title: Valid + type: boolean + version: + title: Version + description: The version of this object (an integer starting from 1) + type: integer + default: 1 + creation_date: + title: Creation date + type: string + format: date-time + readOnly: true + hash: + title: Hash + description: Hashed value of the object contents (<a href="https://docs.python.org/2/library/hashlib.html">SHA256, + hexadecimal digest</a>). This field is auto-generated and managed by the + platform. + type: string + readOnly: true + minLength: 1 + Plotter: + required: + - modifiable + - deletable + - name + - short_description + - dataformat + type: object + properties: + id: + title: ID + type: integer + readOnly: true + accessibility: + title: Accessibility + type: string + readOnly: true + modifiable: + title: Modifiable + type: boolean + deletable: + title: Deletable + type: boolean + is_owner: + title: Is owner + type: string + readOnly: true + name: + title: Name + type: string + minLength: 1 + fork_of: + title: Fork of + type: string + readOnly: true + last_version: + title: Last version + type: string + readOnly: true + previous_version: + title: Previous version + type: string + readOnly: true + short_description: + title: Short description + type: string + maxLength: 100 + minLength: 1 + description: + title: Description + type: string + readOnly: true + declaration: + title: Declaration + type: string + readOnly: true + dataformat: + title: Dataformat + type: string + minLength: 1 + version: + title: Version + description: The version of this object (an integer starting from 1) + type: integer + default: 1 + creation_date: + title: Creation date + type: string + format: date-time + readOnly: true + sample_data: + title: Sample data + type: string + DefaultPlotter: + required: + - dataformat + - plotter + - parameter + type: object + properties: + dataformat: + title: Dataformat + type: string + minLength: 1 + plotter: + title: Plotter + type: string + minLength: 1 + parameter: + title: Parameter + type: string + minLength: 1 + PlotterParameter: + required: + - name + type: object + properties: + name: + title: Name + type: string + minLength: 1 + plotter: + title: Plotter + type: integer + x-nullable: true + FullPlotterParameter: + required: + - modifiable + - deletable + - name + - short_description + type: object + properties: + id: + title: ID + type: integer + readOnly: true + accessibility: + title: Accessibility + type: string + readOnly: true + modifiable: + title: Modifiable + type: boolean + deletable: + title: Deletable + type: boolean + is_owner: + title: Is owner + type: string + readOnly: true + name: + title: Name + type: string + minLength: 1 + fork_of: + title: Fork of + type: string + readOnly: true + last_version: + title: Last version + type: string + readOnly: true + previous_version: + title: Previous version + type: string + readOnly: true + short_description: + title: Short description + type: string + maxLength: 100 + minLength: 1 + description: + title: Description + type: string + readOnly: true + data: + title: Data + type: string + readOnly: true + plotter: + title: Plotter + type: string + readOnly: true + plotters: + title: Plotters + type: string + readOnly: true + version: + title: Version + description: The version of this object (an integer starting from 1) + type: integer + default: 1 + creation_date: + title: Creation date + type: string + format: date-time + readOnly: true + PlotterParameterCreation: + required: + - name + type: object + properties: + name: + title: Name + description: The name for this object (space-like characters will be automatically + replaced by dashes) + type: string + maxLength: 200 + minLength: 1 + plotter: + title: Plotter + type: integer + x-nullable: true + data: + title: Data + type: string + version: + title: Version + description: The version of this object (an integer starting from 1) + type: integer + previous_version: + title: Previous version + type: string + minLength: 1 + short_description: + title: Short description + description: Describe the object succinctly (try to keep it under 80 characters) + type: string + maxLength: 100 + description: + title: Description + type: string + fork_of: + title: Fork of + type: string + PlotterCreation: + required: + - name + type: object + properties: + name: + title: Name + description: The name for this object (space-like characters will be automatically + replaced by dashes) + type: string + maxLength: 200 + minLength: 1 + short_description: + title: Short description + description: Describe the object succinctly (try to keep it under 80 characters) + type: string + maxLength: 100 + description: + title: Description + type: string + declaration: + title: Declaration + type: string + previous_version: + title: Previous version + type: string + minLength: 1 + fork_of: + title: Fork of + type: string + code: + title: Code + type: string + language: + title: Language + type: string + enum: + - U + - C + - M + - P + - R + FullPlotter: + required: + - modifiable + - deletable + - name + - short_description + - valid + type: object + properties: + accessibility: + title: Accessibility + type: string + readOnly: true + sharing: + title: Sharing + type: string + readOnly: true + modifiable: + title: Modifiable + type: boolean + deletable: + title: Deletable + type: boolean + is_owner: + title: Is owner + type: string + readOnly: true + name: + title: Name + type: string + minLength: 1 + fork_of: + title: Fork of + type: string + readOnly: true + last_version: + title: Last version + type: string + readOnly: true + previous_version: + title: Previous version + type: string + readOnly: true + short_description: + title: Short description + type: string + maxLength: 100 + minLength: 1 + code: + title: Code + type: string + readOnly: true + description: + title: Description + type: string + readOnly: true + declaration: + title: Declaration + type: string + readOnly: true + opensource: + title: Opensource + type: string + readOnly: true + language: + title: Language + type: string + readOnly: true + valid: + title: Valid + type: boolean + version: + title: Version + description: The version of this object (an integer starting from 1) + type: integer + default: 1 + creation_date: + title: Creation date + type: string + format: date-time + readOnly: true + hash: + title: Hash + description: Hashed value of the object contents (<a href="https://docs.python.org/2/library/hashlib.html">SHA256, + hexadecimal digest</a>). This field is auto-generated and managed by the + platform. + type: string + readOnly: true + minLength: 1 + SimpleReport: + required: + - creation_date + type: object + properties: + name: + title: Name + type: string + readOnly: true + number: + title: Number + type: integer + short_description: + title: Short description + description: Describe the object succinctly (try to keep it under 80 characters) + type: string + maxLength: 100 + is_owner: + title: Is owner + type: string + readOnly: true + author: + title: Author + type: string + readOnly: true + status: + title: Status + type: string + readOnly: true + description: + title: Description + type: string + creation_date: + title: Creation date + type: string + format: date-time + html_description: + title: Html description + type: string + readOnly: true + add_url: + title: Add url + type: string + readOnly: true + content: + title: Content + type: string + readOnly: true + FullReport: + required: + - creation_date + type: object + properties: + name: + title: Name + type: string + readOnly: true + number: + title: Number + type: integer + short_description: + title: Short description + description: Describe the object succinctly (try to keep it under 80 characters) + type: string + maxLength: 100 + description: + title: Description + type: string + is_owner: + title: Is owner + type: string + readOnly: true + author: + title: Author + type: string + readOnly: true + status: + title: Status + type: string + readOnly: true + creation_date: + title: Creation date + type: string + format: date-time + publication_date: + title: Publication date + type: string + format: date-time + x-nullable: true + experiments: + title: Experiments + type: string + readOnly: true + analyzer: + title: Analyzer + type: string + readOnly: true + content: + title: Content + type: string + readOnly: true + html_description: + title: Html description + type: string + readOnly: true + experiment_access_map: + title: Experiment access map + type: string + readOnly: true + ReportUpdate: + required: + - content + - experiments + type: object + properties: + short_description: + title: Short description + description: Describe the object succinctly (try to keep it under 80 characters) + type: string + maxLength: 100 + description: + title: Description + type: string + content: + title: Content + type: string + experiments: + type: array + items: + type: string + minLength: 1 + ReportCreation: + required: + - name + - content + - experiments + type: object + properties: + name: + title: Name + description: The name for this object (space-like characters will be automatically + replaced by dashes) + type: string + maxLength: 200 + minLength: 1 + short_description: + title: Short description + description: Describe the object succinctly (try to keep it under 80 characters) + type: string + maxLength: 100 + description: + title: Description + type: string + content: + title: Content + type: string + experiments: + type: array + items: + type: string + minLength: 1 + SearchWrite: + required: + - name + - filters + - settings + type: object + properties: + name: + title: Name + description: The name for this object (space-like characters will be automatically + replaced by dashes) + type: string + maxLength: 200 + minLength: 1 + short_description: + title: Short description + description: Describe the object succinctly (try to keep it under 80 characters) + type: string + maxLength: 100 + description: + title: Description + type: string + minLength: 1 + filters: + type: array + items: + type: object + additionalProperties: + type: string + settings: + type: array + items: + type: object + additionalProperties: + type: string + leaderboard: + title: Leaderboard + type: boolean + SimpleTeam: + type: object + properties: + name: + title: Name + type: string + readOnly: true + short_description: + title: Short description + type: string + maxLength: 100 + is_owner: + title: Is owner + type: string + readOnly: true + accessibility: + title: Accessibility + type: string + readOnly: true + TeamCreation: + required: + - name + - accessibility + - members + type: object + properties: + name: + title: Name + type: string + maxLength: 32 + minLength: 1 + short_description: + title: Short description + type: string + maxLength: 100 + accessibility: + title: Accessibility + type: string + minLength: 1 + members: + type: array + items: + type: string + minLength: 1 + FullTeam: + type: object + properties: + name: + title: Name + type: string + readOnly: true + short_description: + title: Short description + type: string + maxLength: 100 + is_owner: + title: Is owner + type: string + readOnly: true + accessibility: + title: Accessibility + type: string + readOnly: true + members: + title: Members + type: string + readOnly: true + TeamUpdate: + required: + - accessibility + - members + type: object + properties: + short_description: + title: Short description + type: string + maxLength: 100 + accessibility: + title: Accessibility + type: string + minLength: 1 + members: + type: array + items: + type: string + minLength: 1 + Toolchain: + required: + - modifiable + - deletable + - name + - short_description + type: object + properties: + accessibility: + title: Accessibility + type: string + readOnly: true + sharing: + title: Sharing + type: string + readOnly: true + modifiable: + title: Modifiable + type: boolean + deletable: + title: Deletable + type: boolean + is_owner: + title: Is owner + type: string + readOnly: true + name: + title: Name + type: string + minLength: 1 + fork_of: + title: Fork of + type: string + readOnly: true + last_version: + title: Last version + type: string + readOnly: true + previous_version: + title: Previous version + type: string + readOnly: true + short_description: + title: Short description + type: string + maxLength: 100 + minLength: 1 + version: + title: Version + description: The version of this object (an integer starting from 1) + type: integer + default: 1 + creation_date: + title: Creation date + type: string + format: date-time + readOnly: true + hash: + title: Hash + description: Hashed value of the object contents (<a href="https://docs.python.org/2/library/hashlib.html">SHA256, + hexadecimal digest</a>). This field is auto-generated and managed by the + platform. + type: string + readOnly: true + minLength: 1 + ToolchainCreation: + required: + - name + type: object + properties: + name: + title: Name + description: The name for this object (space-like characters will be automatically + replaced by dashes) + type: string + maxLength: 200 + minLength: 1 + short_description: + title: Short description + description: Describe the object succinctly (try to keep it under 80 characters) + type: string + maxLength: 100 + description: + title: Description + type: string + declaration: + title: Declaration + type: string + previous_version: + title: Previous version + type: string + minLength: 1 + fork_of: + title: Fork of + type: string + FullToolchain: + required: + - modifiable + - deletable + - name + - short_description + type: object + properties: + accessibility: + title: Accessibility + type: string + readOnly: true + sharing: + title: Sharing + type: string + readOnly: true + modifiable: + title: Modifiable + type: boolean + deletable: + title: Deletable + type: boolean + is_owner: + title: Is owner + type: string + readOnly: true + name: + title: Name + type: string + minLength: 1 + fork_of: + title: Fork of + type: string + readOnly: true + last_version: + title: Last version + type: string + readOnly: true + previous_version: + title: Previous version + type: string + readOnly: true + short_description: + title: Short description + type: string + maxLength: 100 + minLength: 1 + description: + title: Description + type: string + readOnly: true + declaration: + title: Declaration + type: string + readOnly: true + version: + title: Version + description: The version of this object (an integer starting from 1) + type: integer + default: 1 + creation_date: + title: Creation date + type: string + format: date-time + readOnly: true + hash: + title: Hash + description: Hashed value of the object contents (<a href="https://docs.python.org/2/library/hashlib.html">SHA256, + hexadecimal digest</a>). This field is auto-generated and managed by the + platform. + type: string + readOnly: true + minLength: 1 diff --git a/doc/api/web_api.rst b/doc/api/web_api.rst index e1d59eec5dea467846b8a1cadf141bf85ae425b7..1a206f6810a78ee58f4cc0b779b7eb42f5b48093 100644 --- a/doc/api/web_api.rst +++ b/doc/api/web_api.rst @@ -144,6 +144,8 @@ The following examples assumes that: Data Format API --------------- +.. (openapi: : specs/swagger.yaml) + Retrieving a list of all the data formats accessible by the user ................................................................ diff --git a/doc/conf.py b/doc/conf.py index f0b8bf544deaac2ab8769b6ed843be94351d20d0..850d53c3fbe1d7f5fdff54712d51556e08c5ff3e 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -48,6 +48,7 @@ extensions = [ 'sphinx.ext.viewcode', 'sphinxcontrib.programoutput', 'sphinxcontrib.httpdomain', + 'sphinxcontrib.openapi', ] # Be picky about warnings @@ -149,7 +150,7 @@ pygments_style = 'sphinx' # Some variables which are useful for generated material project_variable = project.replace('.', '_') -short_description = u'Biometrics Evaluation and Testing Platform (Web Modules)' +short_description = u'BEAT Platform (Web Modules)' owner = [u'Idiap Research Institute'] diff --git a/release.cfg b/release.cfg index 5f09b4484d1f7b04c6898bb29dae8ba8c38d1038..598df974cd524e025363f8aae51484b8f291ad5d 100644 --- a/release.cfg +++ b/release.cfg @@ -14,7 +14,7 @@ develop = src/beat.backend.python [versions] django = >=1.11,<2.0 django-rest-swagger = >2.1 -django-guardian = >=1.3 +django-guardian = >=1.4,<2.0 djangorestframework = >3.7 django-activity-stream = >= 0.6.5 django-jsonfield = >= 1.0.1 @@ -24,9 +24,9 @@ eggs = ${buildout:eggs} interpreter = python [sources] -beat.core = git https://gitlab.idiap.ch/beat/beat.core.git rev=v1.8.0 -beat.cmdline = git https://gitlab.idiap.ch/beat/beat.cmdline.git rev=v1.4.1 -beat.backend.python = git https://gitlab.idiap.ch/beat/beat.backend.python.git rev=v1.6.2 +beat.core = git https://gitlab.idiap.ch/beat/beat.core.git rev=v1.9.0 +beat.cmdline = git https://gitlab.idiap.ch/beat/beat.cmdline.git rev=v1.5.0 +beat.backend.python = git https://gitlab.idiap.ch/beat/beat.backend.python.git rev=v1.7.2 [uwsgi] recipe = buildout.recipe.uwsgi diff --git a/requirements.txt b/requirements.txt index f177b6f717740f5a56775ecd7939a88c2130c861..841e8cb38faccba48459b982c146b2f83b73cd65 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,14 +4,16 @@ django-activity-stream django-guardian django-jsonfield django-post_office -django-rest-swagger +drf-yasg djangorestframework docopt docutils jinja2 matplotlib +packaging psutil psycopg2 pytz setuptools +setuptools_scm simplejson diff --git a/setup.py b/setup.py index d5aa4e4bb296f7701bf3f6a9c62cc591d20ce3bd..b57afb99ad49516644321db6b0653522170cf9bb 100644 --- a/setup.py +++ b/setup.py @@ -38,7 +38,7 @@ def load_requirements(f): setup( name="beat.web", version=open("version.txt").read().rstrip(), - description="Biometrics Evaluation and Testing Platform (Web Modules)", + description="BEAT Platform (Web Modules)", url="https://gitlab.idiap.ch/beat/beat.web", license="AGPLv3", author="Idiap Research Institute", diff --git a/version.txt b/version.txt index 7dab572261f0fc72999c93ad1aec4cad40b07ca3..97728257436dbc6d0deaa954fe1f6d5592df0574 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.5.3b0 \ No newline at end of file +1.5.4b0 \ No newline at end of file