From 109cf38be440e15676e53ec1458ff9efe7d4a395 Mon Sep 17 00:00:00 2001 From: Marco Donadoni Date: Tue, 19 Mar 2024 16:15:44 +0100 Subject: [PATCH] feat(gitlab): add search query parameter to filter projects (#681) Closes #518 --- docs/openapi.json | 16 +++++++++++++ reana_server/rest/gitlab.py | 46 +++++++++++++++++++++++++++++-------- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/docs/openapi.json b/docs/openapi.json index 6ffacc2a..2ca1471e 100644 --- a/docs/openapi.json +++ b/docs/openapi.json @@ -148,6 +148,22 @@ "get": { "description": "Retrieve projects from GitLab.", "operationId": "gitlab_projects", + "parameters": [ + { + "description": "The API access_token of the current user.", + "in": "query", + "name": "access_token", + "required": false, + "type": "string" + }, + { + "description": "The search string to filter the project list.", + "in": "query", + "name": "search", + "required": false, + "type": "string" + } + ], "produces": [ "application/json" ], diff --git a/reana_server/rest/gitlab.py b/reana_server/rest/gitlab.py index 00d69eae..f2e8d984 100644 --- a/reana_server/rest/gitlab.py +++ b/reana_server/rest/gitlab.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # This file is part of REANA. -# Copyright (C) 2019, 2020, 2021, 2022, 2023 CERN. +# Copyright (C) 2019, 2020, 2021, 2022, 2023, 2024 CERN. # # REANA is free software; you can redistribute it and/or modify it # under the terms of the MIT License; see LICENSE file for more details. @@ -10,6 +10,8 @@ import logging import traceback +from typing import Optional +from urllib.parse import urljoin import requests from flask import ( @@ -25,6 +27,9 @@ from itsdangerous import BadData, TimedJSONWebSignatureSerializer from reana_commons.k8s.secrets import REANAUserSecretsStore from werkzeug.local import LocalProxy +from webargs import fields +from webargs.flaskparser import use_kwargs + from reana_server.config import ( REANA_GITLAB_OAUTH_APP_ID, @@ -182,8 +187,9 @@ def gitlab_oauth(user): # noqa @blueprint.route("/gitlab/projects", methods=["GET"]) +@use_kwargs({"search": fields.Str(location="query")}) @signin_required() -def gitlab_projects(user): # noqa +def gitlab_projects(user, search: Optional[str] = None): # noqa r"""Endpoint to retrieve GitLab projects. --- get: @@ -193,6 +199,17 @@ def gitlab_projects(user): # noqa Retrieve projects from GitLab. produces: - application/json + parameters: + - name: access_token + in: query + description: The API access_token of the current user. + required: false + type: string + - name: search + in: query + description: The search string to filter the project list. + required: false + type: string responses: 200: description: >- @@ -228,16 +245,25 @@ def gitlab_projects(user): # noqa try: secrets_store = REANAUserSecretsStore(str(user.id_)) gitlab_token = secrets_store.get_secret_value("gitlab_access_token") - gitlab_url = ( - f"{REANA_GITLAB_URL}/api/v4/projects/" + + if not gitlab_token: + return jsonify({"message": "Missing GitLab access token."}), 401 + + gitlab_url = urljoin(REANA_GITLAB_URL, "/api/v4/projects") + params = { + "access_token": gitlab_token, # show projects in which user is at least a `Maintainer` - "?min_access_level=40" + # as that's the minimum access level needed to create webhooks + "min_access_level": 40, + "per_page": 100, + "search": search, + # include ancestor namespaces when matching search criteria + "search_namespaces": "true", # return only basic information about the projects - "&simple=true" - "&per_page=100" - f"&access_token={gitlab_token}" - ) - response = requests.get(gitlab_url) + "simple": "true", + } + + response = requests.get(gitlab_url, params=params) projects = dict() if response.status_code == 200: for gitlab_project in response.json():