diff --git a/CHANGELOG.md b/CHANGELOG.md index e858fb95..4eeb3023 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,22 +6,52 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.17.0] - 2022-12-06 +### Added +- Cancel button in contribution edit page. [#986](https://github.com/rokwire/rokwire-building-blocks-api/issues/986) +- Add group ids and user ids fields in events yaml file. [#1017](https://github.com/rokwire/rokwire-building-blocks-api/issues/1017) +- Compound text indexes for contribution collection. [#1004](https://github.com/rokwire/rokwire-building-blocks-api/issues/1004) +- Hide data deletion api key in capability view page. [#1010](https://github.com/rokwire/rokwire-building-blocks-api/issues/1010) +- Support multiple group ids in post endpoint in events building block. [#1020](https://github.com/rokwire/rokwire-building-blocks-api/issues/1020) +- User confirmation on cancel contribution. [#1022](https://github.com/rokwire/rokwire-building-blocks-api/issues/1022) +- Close button to remove environment key value pairs. [#980](https://github.com/rokwire/rokwire-building-blocks-api/issues/980) +- Make environmentVariable key required if present in Catalog. [#1028](https://github.com/rokwire/rokwire-building-blocks-api/issues/1028) +- Added set and get functions for ApiBaseUrl in catalog. [#1047](https://github.com/rokwire/rokwire-building-blocks-api/issues/1047) -## [1.16.0] - 2022-08-29 +### Changed +- Show appropriate error message when catalog cannot display a contribution. [#961](https://github.com/rokwire/rokwire-building-blocks-api/issues/961) +- Position of Add capability and talent buttons in catalog form. [#971](https://github.com/rokwire/rokwire-building-blocks-api/issues/971) +- Page re-direct after contribution edit. [#976](https://github.com/rokwire/rokwire-building-blocks-api/issues/976) +- Add more fields button changed to Add environment variables. [#975](https://github.com/rokwire/rokwire-building-blocks-api/issues/975) +- Edit contribution button color changed to grey. [#981](https://github.com/rokwire/rokwire-building-blocks-api/issues/981) +- Heading for add a talent or capability in contribution edit page if talent or capability exists. [#984](https://github.com/rokwire/rokwire-building-blocks-api/issues/984) +- Arrange environment variables into single row in capability view page. [#993](https://github.com/rokwire/rokwire-building-blocks-api/issues/993) +- Arrange environment variables and data deletion endpoint into single row in capability. [#989](https://github.com/rokwire/rokwire-building-blocks-api/issues/989) +- API Doc Dockerfile URLs to include new building blocks and remove unsupported building blocks. [#831](https://github.com/rokwire/rokwire-building-blocks-api/issues/831) +- Talent fields yaml configuration [#949](https://github.com/rokwire/rokwire-building-blocks-api/issues/949) +- Drop old indexes in contributions collection in mongodb. [#1029](https://github.com/rokwire/rokwire-building-blocks-api/issues/1029) +### Fixed +- Fix Core BB service token support in events [#994](https://github.com/rokwire/rokwire-building-blocks-api/issues/994) +- Updated gevent in contributions. [#1003](https://github.com/rokwire/rokwire-building-blocks-api/issues/1003) +- Updated gevent in catalog. [#1007](https://github.com/rokwire/rokwire-building-blocks-api/issues/1007) +- Delete capability and talent functionality in catalog. [#1009](https://github.com/rokwire/rokwire-building-blocks-api/issues/1009) +- Edit database detail field in catalog. [#1048](https://github.com/rokwire/rokwire-building-blocks-api/issues/1048) +- Display multiple contribution admins in catalog. [#1050](https://github.com/rokwire/rokwire-building-blocks-api/issues/1050) +- VersionUrl field name in contribution edit page. [#1056](https://github.com/rokwire/rokwire-building-blocks-api/issues/1056) +- SourceUrl field display on IsOpenSourceUrl radio button in catalog. [#1053](https://github.com/rokwire/rokwire-building-blocks-api/issues/1053) + +## [1.16.0] - 2022-08-29 ### Added - Ability to delete a capability or talent from contribution. [#951](https://github.com/rokwire/rokwire-building-blocks-api/issues/951) - Hide sensitive data in capability view page. [#950](https://github.com/rokwire/rokwire-building-blocks-api/issues/950) - Minimum user privacy level in talent form. [#970](https://github.com/rokwire/rokwire-building-blocks-api/issues/970) -### Security -- Upgrade Swagger UI base Docker image to v4.13.2. [#991](https://github.com/rokwire/rokwire-building-blocks-api/issues/991) - ### Changed - Change to allow all group admins to manage group events. [#996](https://github.com/rokwire/rokwire-building-blocks-api/issues/996) -### Fixed - +### Security +- Upgrade Swagger UI base Docker image to v4.13.2. [#991](https://github.com/rokwire/rokwire-building-blocks-api/issues/991) ## [1.15.0] - 2022-07-11 ### Added @@ -518,7 +548,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed - References to AWS keys and variables in the Events Building Block. -[Unreleased]: https://github.com/rokwire/rokwire-building-blocks-api/compare/1.16.0...HEAD +[Unreleased]: https://github.com/rokwire/rokwire-building-blocks-api/compare/1.17.0...HEAD +[1.17.0]: https://github.com/rokwire/rokwire-building-blocks-api/compare/1.16.0...1.17.0 [1.16.0]: https://github.com/rokwire/rokwire-building-blocks-api/compare/1.15.0...1.16.0 [1.15.0]: https://github.com/rokwire/rokwire-building-blocks-api/compare/1.14.1...1.15.0 [1.14.1]: https://github.com/rokwire/rokwire-building-blocks-api/compare/1.14.0...1.14.1 diff --git a/Dockerfile b/Dockerfile index e569444c..5996549c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,14 +14,8 @@ FROM swaggerapi/swagger-ui:v4.13.2 -COPY appconfigservice/appconfig.yaml /usr/share/nginx/html/app/ -COPY authservice/auth.yaml /usr/share/nginx/html/app/ -COPY eventservice/events.yaml /usr/share/nginx/html/app/ -COPY profileservice/profile.yaml /usr/share/nginx/html/app/ -COPY loggingservice/logging.yaml /usr/share/nginx/html/app/ +COPY appconfigservice/appconfig.yaml eventservice/events.yaml profileservice/profile.yaml loggingservice/logging.yaml /usr/share/nginx/html/app/ ENV URLS "[{url: 'app/appconfig.yaml', name: 'App Config Building Block'}, {url: 'app/auth.yaml', name: 'Authentication Building Block'}, {url: 'app/events.yaml', name: 'Events Building Block'}, {url: 'app/profile.yaml', name: 'Profile Building Block'}, {url: 'app/logging.yaml', name: 'Logging Building Block'}, {url: 'https://api.rokwire.illinois.edu/health/doc', name: 'Health Building Block'}, {url: 'https://api.rokwire.illinois.edu/talent-chooser/doc', name: 'Talent Chooser Building Block'} ]" VOLUME /usr/share/nginx/html/app/ - -ENV BASE_URL="/docs" diff --git a/SECURITY.md b/SECURITY.md index eb30f09e..73292cab 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,6 +6,7 @@ Patches for **Rokwire Building Blocks** in this repository will only be applied | Version | Supported | |----------| ------------------ | +| 1.17.0 | :white_check_mark: | | 1.16.0 | :white_check_mark: | | 1.15.0 | :white_check_mark: | | 1.14.1 | :white_check_mark: | diff --git a/contributions/api/controllers/contributions.py b/contributions/api/controllers/contributions.py index 8c7b57a7..621107a6 100644 --- a/contributions/api/controllers/contributions.py +++ b/contributions/api/controllers/contributions.py @@ -227,6 +227,7 @@ def search(token_info=None, name=None): # return the list of all records out_json = mongoutils.get_result(coll_contribution, query) else: + # search based on query try: query = query_params.format_query_contribution(name, query) except Exception as ex: @@ -444,95 +445,43 @@ def delete(token_info, id): # logging.error("DELETE " + json.dumps(msg_json)) # return rs_handlers.not_found(msg_json) -def allcapabilitiessearch(token_info=None, name=None): +def allcapabilitiessearch(token_info=None): + # returns a list of all capabilities query = dict() - is_list = False - login_id, is_login = otherutils.get_login(token_info) - query = query_params.format_query_status_login(query, login_id, is_login) - if name is None: - is_list = True - - if is_list: + try: out_json = mongoutils.get_result(coll_contribution, query) - else: - try: - query = query_params.format_query_capability(name, query) - except Exception as ex: - msg = { - "reason": "The query is wrong or bad argument", - "error": "Bad Request: " + request.url, - } - msg_json = jsonutils.create_log_json("Capability", "SEARCH", msg) - logging.error("Capability SEARCH " + json.dumps(msg_json)) - return rs_handlers.bad_request(msg_json) - - try: - out_json = mongoutils.get_result(coll_contribution, query) - except Exception as ex: - msg = { - "reason": "The query is wrong or bad argument", - "error": "Bad Request: " + request.url, - } - msg_json = jsonutils.create_log_json("Capability", "SEARCH", msg) - logging.error("Capability SEARCH " + json.dumps(msg_json)) - return rs_handlers.bad_request(msg_json) + except Exception as ex: + msg = { + "reason": "The query is wrong or bad argument", + "error": "Bad Request: " + request.url, + } + msg_json = jsonutils.create_log_json("Contribution", "SEARCH", msg) + logging.error("Contribution SEARCH " + json.dumps(msg_json)) + return rs_handlers.bad_request(msg_json) return_json = [] if out_json is None: return_json = [] else: - if is_list: # list all - if isinstance(out_json, list): - for in_json in out_json: - contribution_id = in_json["id"] - if in_json['capabilities'] is not None: - for capability in in_json['capabilities']: - capability["contributionId"] = contribution_id - return_json.append(capability) - else: - contribution_id = out_json["id"] - capability = out_json['capabilities'] - capability["contributionId"] = contribution_id - return_json.append(capability) - else: # extract out capabilities with the given name - if isinstance(out_json, list): - for tmp_json in out_json: - capabilities_json = tmp_json["capabilities"] - contribution_id = tmp_json["id"] - # TODO this is the case of only 1 args that is name. - # If there are more args this should be updated - for tmp_capability_json in capabilities_json: - capability_json = None - if tmp_capability_json["name"] == name: - capability_json = tmp_capability_json - capability_json["contributionId"] = contribution_id - return_json.append(capability_json) - else: - capabilities_json = out_json["capabilities"] - contribution_id = out_json["id"] - # TODO this is the case of only 1 args that is name. - # If there are more args this should be updated - for tmp_capability_json in capabilities_json: - capability_json = None - if tmp_capability_json["name"] == name: - capability_json = tmp_capability_json - capability_json["contributionId"] = contribution_id - return_json.append(capability_json) - if is_list: - msg = { - "GET": "Capabilities list" - } - msg_json = jsonutils.create_log_json("Capabilities", "GET", msg) - logging.info("Capabilities GET " + json.dumps(msg_json)) - else: - msg = { - "search": "Capability search performed with " + str(name) - } - msg_json = jsonutils.create_log_json("Capability", "SEARCH", msg) - logging.info("Capability SEARCH " + json.dumps(msg_json)) + if isinstance(out_json, list): + for in_json in out_json: + contribution_id = in_json["id"] + if in_json['capabilities'] is not None: + for capability in in_json['capabilities']: + capability["contributionId"] = contribution_id + return_json.append(capability) + else: + contribution_id = out_json["id"] + capability = out_json['capabilities'] + capability["contributionId"] = contribution_id + return_json.append(capability) + + msg = {"GET": "Capabilities list"} + msg_json = jsonutils.create_log_json("Capabilities", "GET", msg) + logging.info("Capabilities GET " + json.dumps(msg_json)) return return_json @@ -599,95 +548,43 @@ def capabilities_search(token_info=None, id=None): return capability_dataset -def alltalentssearch(token_info=None, name=None): +def alltalentssearch(token_info=None): + # returns list of all talents query = dict() - is_list = False - login_id, is_login = otherutils.get_login(token_info) - query = query_params.format_query_status_login(query, login_id, is_login) - if name is None: - is_list = True - - if is_list: + try: out_json = mongoutils.get_result(coll_contribution, query) - else: - try: - query = query_params.format_query_talent(name, query) - except Exception as ex: - msg = { - "reason": "The query is wrong or bad argument", - "error": "Bad Request: " + request.url, - } - msg_json = jsonutils.create_log_json("Talent", "SEARCH", msg) - logging.error("Talent SEARCH " + json.dumps(msg_json)) - return rs_handlers.bad_request(msg_json) - - try: - out_json = mongoutils.get_result(coll_contribution, query) - except Exception as ex: - msg = { - "reason": "The query is wrong or bad argument", - "error": "Bad Request: " + request.url, - } - msg_json = jsonutils.create_log_json("Talent", "SEARCH", msg) - logging.error("Talent SEARCH " + json.dumps(msg_json)) - return rs_handlers.bad_request(msg_json) + except Exception as ex: + msg = { + "reason": "The query is wrong or bad argument", + "error": "Bad Request: " + request.url, + } + msg_json = jsonutils.create_log_json("Contribution", "SEARCH", msg) + logging.error("Contribution SEARCH " + json.dumps(msg_json)) + return rs_handlers.bad_request(msg_json) return_json = [] if out_json is None: return_json = [] else: - if is_list: # list all - if isinstance(out_json, list): - for in_json in out_json: - contribution_id = in_json["id"] - if in_json['talents'] is not None: - for talent in in_json['talents']: - talent["contributionId"] = contribution_id - return_json.append(talent) - else: - contribution_id = out_json["id"] - talent = out_json['talents'] - talent["contributionId"] = contribution_id - return_json.append(talent) - else: # extract out talent with the given name - if isinstance(out_json, list): - for tmp_json in out_json: - contribution_id = tmp_json["id"] - talents_json = tmp_json["talents"] - # TODO this is the case of only 1 args that is name. - # If there are more args this should be updated - for tmp_talent_json in talents_json: - talent_json = None - if tmp_talent_json["name"] == name: - talent_json = tmp_talent_json - talent_json["contributionId"] = contribution_id - return_json.append(talent_json) - else: - talents_json = out_json["talents"] - contribution_id = out_json["id"] - # TODO this is the case of only 1 args that is name. - # If there are more args this should be updated - for tmp_talent_json in talents_json: - talent_json = None - if tmp_talent_json["name"] == name: - talent_json = tmp_talent_json - talent_json["contributionId"] = contribution_id - return_json.append(talent_json) - if is_list: - msg = { - "GET": "Talent list" - } - msg_json = jsonutils.create_log_json("Talent", "GET", msg) - logging.info("Talent GET " + json.dumps(msg_json)) - else: - msg = { - "search": "Talent search performed with " + str(name) - } - msg_json = jsonutils.create_log_json("Talent", "SEARCH", msg) - logging.info("Talent SEARCH " + json.dumps(msg_json)) + if isinstance(out_json, list): + for in_json in out_json: + contribution_id = in_json["id"] + if in_json['talents'] is not None: + for talent in in_json['talents']: + talent["contributionId"] = contribution_id + return_json.append(talent) + else: + contribution_id = out_json["id"] + talent = out_json['talents'] + talent["contributionId"] = contribution_id + return_json.append(talent) + + msg = {"GET": "Talent list"} + msg_json = jsonutils.create_log_json("Talent", "GET", msg) + logging.info("Talent GET " + json.dumps(msg_json)) return return_json diff --git a/contributions/api/models/capabilities/capability.py b/contributions/api/models/capabilities/capability.py index 8f484571..ab285a4b 100644 --- a/contributions/api/models/capabilities/capability.py +++ b/contributions/api/models/capabilities/capability.py @@ -76,6 +76,12 @@ def set_api_doc_url(self, apiDocUrl): def get_api_doc_url(self): return self.apiDocUrl + def set_api_base_url(self, apiBaseUrl): + self.apiBaseUrl = apiBaseUrl + + def get_api_base_url(self): + return self.apiBaseUrl + def set_deployment_details(self, deploymentDetails): self.deploymentDetails = deploymentDetails diff --git a/contributions/api/models/contribution.py b/contributions/api/models/contribution.py index 4c4f2b97..810026f6 100644 --- a/contributions/api/models/contribution.py +++ b/contributions/api/models/contribution.py @@ -17,7 +17,7 @@ class Contribution(): def __init__(self, injson): self.name = None - self.contributionAdmins = None + self.contributionAdmins = [] self.shortDescription = None self.longDescription = None self.contributors = None diff --git a/contributions/api/utils/datasetutils.py b/contributions/api/utils/datasetutils.py index c2557560..016f71f8 100644 --- a/contributions/api/utils/datasetutils.py +++ b/contributions/api/utils/datasetutils.py @@ -180,9 +180,11 @@ def update_capability_dataset_from_json(dataset, injson): environment_variable = EnvironmentVariable() key = env_var["key"] value = env_var["value"] - environment_variable.set_key(key) - environment_variable.set_value(value) - env_var_list.append(environment_variable) + # check if non-empty key + if key: + environment_variable.set_key(key) + environment_variable.set_value(value) + env_var_list.append(environment_variable) deployment_details.set_environment_variables(env_var_list) del outjson["environmentVariables"] except Exception as e: diff --git a/contributions/api/utils/mongoutils.py b/contributions/api/utils/mongoutils.py index d3d928b1..2d8f3dc8 100644 --- a/contributions/api/utils/mongoutils.py +++ b/contributions/api/utils/mongoutils.py @@ -19,7 +19,7 @@ from bson import ObjectId from flask import make_response, json from bson.json_util import dumps -from pymongo import MongoClient, ASCENDING +from pymongo import MongoClient, ASCENDING, TEXT from models.contribution import Contribution from utils import query_params from utils import jsonutils @@ -27,13 +27,21 @@ client_contribution = MongoClient(cfg.MONGO_CONTRIBUTION_URL, connect=False) db_contribution = client_contribution[cfg.CONTRIBUTION_DB_NAME] -coll_contribution = db_contribution[cfg.CONTRIBUTION_COLL_NAME] -coll_contribution.create_index([("name", ASCENDING)], background=True) -coll_contribution.create_index([("capabilities.name", ASCENDING)], background=True) -coll_contribution.create_index([("talents.name", ASCENDING)], background=True) - -coll_reviewer = db_contribution[cfg.REVIEWER_COLL_NAME] -coll_reviewer.create_index([("name", ASCENDING)], background=True) +coll_contribution = db_contribution[cfg.CONTRIBUTION_COLL_NAME] # set contribution collection +# drop old indexes in contribution collection +coll_contribution_indexes = coll_contribution.index_information().keys() +# get old indexes +coll_contribution_old_indexes = [index for index in coll_contribution_indexes if index in ['name', 'capabilities.name', 'talents.name']] +for index_name in coll_contribution_old_indexes: + coll_contribution.drop_index(index_name) +# create compound text indexes with equal weightage +coll_contribution.create_index([("name", TEXT), ("shortDescription", TEXT), + ("capabilities.name", TEXT), ("capabilities.description", TEXT), + ("talents.name", TEXT), ("talents.shortDescription", TEXT)], + name='text_index', default_language='english') + +coll_reviewer = db_contribution[cfg.REVIEWER_COLL_NAME] # set reviewer collection +coll_reviewer.create_index([("name", TEXT)]) """ get json of all the contributions list diff --git a/contributions/api/utils/query_params.py b/contributions/api/utils/query_params.py index 1ea40477..1210a625 100644 --- a/contributions/api/utils/query_params.py +++ b/contributions/api/utils/query_params.py @@ -22,36 +22,13 @@ def format_query_status_login(query, login, is_login): return query -def format_query_contribution(name, query): - query_parts = [] +def format_query_contribution(search_string, query): + query_parts = {} - if name is not None: - query_parts.append({'name': name}) + if search_string is not None: + query_parts['$search'] = search_string if query_parts: - query['$and'] = query_parts - + query['$text'] = query_parts return query - -def format_query_capability(name, query): - query_parts = [] - - if name is not None: - query_parts.append({'capabilities.name': name}) - - if query_parts: - query['$and'] = query_parts - - return query - -def format_query_talent(name, query): - query_parts = [] - - if name is not None: - query_parts.append({'talents.name': name}) - - if query_parts: - query['$and'] = query_parts - - return query diff --git a/contributions/catalog/controllers/contribute.py b/contributions/catalog/controllers/contribute.py index 2858c08e..6e682eba 100644 --- a/contributions/catalog/controllers/contribute.py +++ b/contributions/catalog/controllers/contribute.py @@ -160,9 +160,17 @@ def contribution_details(contribution_id): username = session["username"] name = session["name"] headers = requestutil.get_header_using_session(session) + # check if the user is reviewer by requesting to endpoint + is_reviewer = adminutil.check_if_reviewer(username, headers) + result = requests.get(cfg.CONTRIBUTION_BUILDING_BLOCK_URL + "/" + str(contribution_id), + headers=headers) + if result.status_code != 200: + err_json = parse_response_error(result) + logging.error("Contribution GET " + json.dumps(err_json)) + msg = "Error: " + err_json['reason'] + return render_template('contribute/error.html', error_msg=msg) - the_json_res = get_contribution(contribution_id) - + the_json_res = result.json() # check if the logged in user is the editor is_superuser = adminutil.check_if_superuser(username) if is_superuser: @@ -170,13 +178,19 @@ def contribution_details(contribution_id): elif username in the_json_res["contributionAdmins"]: is_editor = True - # check if the user is reviewer by requesting to endpoint - is_reviewer = adminutil.check_if_reviewer(username, headers) else: - the_json_res = get_contribution_with_api_key(contribution_id) + headers = requestutil.get_header_using_api_key() + result = requests.get(cfg.CONTRIBUTION_BUILDING_BLOCK_URL + "/" + str(contribution_id), + headers=headers) + the_json_res = result.json() + if result.status_code != 200: + err_json = parse_response_error(result) + logging.error("Contribution GET " + json.dumps(err_json)) + msg = "Error: " + err_json['reason'] + return render_template('contribute/error.html', error_msg=msg) return render_template("contribute/contribution_details.html", is_reviewer=is_reviewer, is_editable=is_editor, - post=the_json_res, user=name) + post=the_json_res, user=name) @bp.route('/contributions//edit', methods=['GET', 'POST']) @login_required @@ -204,8 +218,7 @@ def contribution_edit(contribution_id): if response: if "name" in session: - return render_template('contribute/submitted.html', user=session["name"], - token=session['oauth_token']['access_token']) + return redirect(url_for('contribute.contribution_details', contribution_id=contribution_id)) else: return render_template('contribute/submitted.html') elif not response: @@ -643,17 +656,21 @@ def get_contribution(contribution_id): result = requests.get(cfg.CONTRIBUTION_BUILDING_BLOCK_URL + "/" + str(contribution_id), headers=headers) - if result.status_code != 200: - err_json = parse_response_error(result) - logging.error("Contribution GET " + json.dumps(err_json)) - return {} + if result.status_code != 200: + err_json = parse_response_error(result) + logging.error("Contribution GET " + json.dumps(err_json)) + return {} + else: + print("GET ok." + str(contribution_id)) + return result.json() else: - print("GET ok.".format(contribution_id)) + logging.error("GET method fails. Incorrect contribution ID" + str(contribution_id)) + return {} except Exception: # traceback.print_exc() return False - return result.json() + def get_contribution_with_api_key(contribution_id): headers = requestutil.get_header_using_api_key() @@ -662,18 +679,18 @@ def get_contribution_with_api_key(contribution_id): if contribution_id: result = requests.get(cfg.CONTRIBUTION_BUILDING_BLOCK_URL + "/" + str(contribution_id), headers=headers) - - if result.status_code != 200: - print("GET method fails".format(contribution_id)) - print("with error code:", result.status_code) - return {} + if result.status_code != 200: + print("GET method fails" + str(contribution_id) + "with error code:" + result.status_code) + return {} + else: + print("GET ok.".format(contribution_id)) + return result.json() else: - print("GET ok.".format(contribution_id)) - + logging.error("GET method fails. Incorrect contribution ID" + str(contribution_id)) + return {} except Exception: # traceback.print_exc() return False - return result.json() def get_capability(contribution_id, cid): headers = requestutil.get_header_using_session(session) diff --git a/contributions/catalog/requirements.txt b/contributions/catalog/requirements.txt index 7b2e2d0d..ffd96d4c 100644 --- a/contributions/catalog/requirements.txt +++ b/contributions/catalog/requirements.txt @@ -6,6 +6,6 @@ pymongo==3.7.2 gunicorn==19.9.0 requests==2.22.0 requests-oauthlib==1.3.0 -gevent==20.9.0 +gevent==21.12.0 python-dotenv>=0.15.0 FormEncode>=2.0.0 diff --git a/contributions/catalog/utils/jsonutil.py b/contributions/catalog/utils/jsonutil.py index 7ad4af84..5983f73d 100644 --- a/contributions/catalog/utils/jsonutil.py +++ b/contributions/catalog/utils/jsonutil.py @@ -26,7 +26,7 @@ def add_contribution_admins(in_json, is_edit=False): contribution_admins = [] # if the form input is not empty, then we want to filter out those names from there if admin_input: - contribution_admins = [admin_name for admin_name in admin_input.split(',') if admin_name] + contribution_admins = [admin_name.strip() for admin_name in admin_input.split(',') if len(admin_name)>1] if is_edit: updated_json = {"contributionAdmins": contribution_admins} diff --git a/contributions/catalog/webapps/static/css/style.css b/contributions/catalog/webapps/static/css/style.css index 0792e327..abff5451 100644 --- a/contributions/catalog/webapps/static/css/style.css +++ b/contributions/catalog/webapps/static/css/style.css @@ -308,8 +308,8 @@ hr.dotted { border-top: 5px dotted #919590; } -/* The Modal (background) */ -.modal { +/* Submit Modal (background) */ +#submit-modal { display: none; /* Hidden by default */ position: fixed; /* Stay in place */ z-index: 1; /* Sit on top */ @@ -386,9 +386,37 @@ hr.dotted { #togglePassword { cursor: pointer; - position: absolute; - margin-left: -20px; - margin-top: -20px; + position: relative; +} + +#env-var-close-btn { + cursor: pointer; + position: relative; + margin-left: 1%; +} + +input.envvar-key[type=text] { + width: 47%; + display: table-cell; +} + +input.envvar-value { + width: 47%; + margin-left: 1%; + margin-right: 1%; + display: table-cell; +} + +input.datadel-endpoint[type=text] { + width: 47%; + display: inline-block; +} + +input.datadel-api { + width: 47%; + margin-left: 1%; + margin-right: 1%; + display: inline-block; } .hidetext { -webkit-text-security: disc; } diff --git a/contributions/catalog/webapps/templates/contribute/capability_details.html b/contributions/catalog/webapps/templates/contribute/capability_details.html index ec05e03e..fc8d0628 100644 --- a/contributions/catalog/webapps/templates/contribute/capability_details.html +++ b/contributions/catalog/webapps/templates/contribute/capability_details.html @@ -15,6 +15,11 @@ Capability Details + +
@@ -94,9 +99,10 @@

Data Deletion Endpoint Details

{% if post.dataDeletionEndpointDetails.apiKey %} - + - + + {% endif %} {% if post.dataDeletionEndpointDetails.deletionEndpoint %} @@ -140,16 +146,18 @@

Deployment Details

Api Key  {{post.dataDeletionEndpointDetails.apiKey}}{{post.dataDeletionEndpointDetails.apiKey}}    
{% for envvar in post.deploymentDetails.environmentVariables %} - {% for key,val in envvar.items() %} - - {% if loop.index %2 == 0 %} - - - - {% else %} - - - {% endif %} + {% for key_val in envvar.items() | batch(4) %} + + {% for item in key_val %} + {% if loop.index %2 == 0 %} + + + + {% else %} + + + {% endif %} + {% endfor %} {% endfor %}
{{key}}:   {{val}}    {{key}}: {{val}}
{{item[0]}}: {{item[1]}}     {{item[0]}}: {{item[1]}}
@@ -208,16 +216,23 @@

Deployment Details

let icon = $(this); icon.toggleClass("bi-eye"); // get the current row - var current_row = icon.closest("tr"); - // get the current row 2nd cell value - var $cell_value = current_row.find("td:eq(1)"); + let current_row = icon.closest("tr"); + let cell_value; + if (current_row.attr("id") == "envvar_row") { + // get the current row 3rd cell value + cell_value = current_row.find("td:eq(3)"); + } + else if (current_row.attr("id") == "datadeletion_row") { + // get the current row 1st cell value + cell_value = current_row.find("td:eq(1)"); + } if (icon.hasClass('bi-eye')) { - $cell_value.removeClass("hidetext"); - $cell_value.addClass("showtext"); + cell_value.removeClass("hidetext"); + cell_value.addClass("showtext"); } else if (icon.hasClass('bi-eye-slash')) { - $cell_value.removeClass("showtext"); - $cell_value.addClass("hidetext"); + cell_value.removeClass("showtext"); + cell_value.addClass("hidetext"); } }); }); diff --git a/contributions/catalog/webapps/templates/contribute/contribute.html b/contributions/catalog/webapps/templates/contribute/contribute.html index 489064cd..71a1681c 100644 --- a/contributions/catalog/webapps/templates/contribute/contribute.html +++ b/contributions/catalog/webapps/templates/contribute/contribute.html @@ -75,7 +75,7 @@