Skip to content

Add REST-API to project#62

Open
renao wants to merge 25 commits intodevelopfrom
add-rest-api
Open

Add REST-API to project#62
renao wants to merge 25 commits intodevelopfrom
add-rest-api

Conversation

@renao
Copy link
Copy Markdown
Owner

@renao renao commented Mar 4, 2026

Closes #55

Summary by CodeRabbit

  • New Features

    • Added an automated API specification downloader that retrieves specs from multiple servers, validates and normalizes their metadata, extracts API versions, organizes per-server spec files, and logs progress and errors while continuing on failures.
  • Documentation

    • Updated environment example to include WORDPRESS_DEBUG=true for local configuration guidance.

@renao renao added this to the SAMS Plugin 3.0 milestone Mar 4, 2026
@renao renao self-assigned this Mar 4, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 4, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6d22b7b3-e734-4563-8cba-683012eef554

📥 Commits

Reviewing files that changed from the base of the PR and between e5c927e and bde0b17.

⛔ Files ignored due to path filters (164)
  • _Generated/js/RestClient/.babelrc is excluded by !**/_generated/**
  • _Generated/js/RestClient/.gitignore is excluded by !**/_generated/**
  • _Generated/js/RestClient/.openapi-generator-ignore is excluded by !**/_generated/**
  • _Generated/js/RestClient/.openapi-generator/FILES is excluded by !**/_generated/**
  • _Generated/js/RestClient/.openapi-generator/VERSION is excluded by !**/_generated/**
  • _Generated/js/RestClient/.travis.yml is excluded by !**/_generated/**
  • _Generated/js/RestClient/README.md is excluded by !**/_generated/**
  • _Generated/js/RestClient/git_push.sh is excluded by !**/_generated/**
  • _Generated/js/RestClient/mocha.opts is excluded by !**/_generated/**
  • _Generated/js/RestClient/package.json is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/ApiClient.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/api/SAMSAssociationsAPIApi.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/api/SAMSCommitteesAPIApi.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/api/SAMSCompetitionMatchesAPIApi.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/api/SAMSCompetitionsAPIApi.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/api/SAMSEventTypesAPIApi.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/api/SAMSEventsAPIApi.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/api/SAMSLeagueHierarchiesAPIApi.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/api/SAMSLeagueMatchesAPIApi.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/api/SAMSLeaguesAPIApi.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/api/SAMSLocationsAPIApi.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/api/SAMSMatchDaysAPIApi.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/api/SAMSMatchGroupsAPIApi.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/api/SAMSRESTAPIV2Api.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/api/SAMSSeasonsAPIApi.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/api/SAMSSportsClubsAPIApi.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/api/SAMSSuperCompetitionsAPIApi.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/api/SAMSTeamsAPIApi.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/api/SAMSUserAPIApi.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/index.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/Address.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/Association.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/AssociationResourcePage.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/Committee.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/CommitteeMember.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/CommitteePage.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/CompetitionDto.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/CompetitionMatchDto.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/CompetitionMatchGroupDto.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/CompetitionMatchGroupPage.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/CompetitionMatchGroupRankingsDto.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/CompetitionMatchPage.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/CompetitionPage.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/CompetitionRankingsResourcePage.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/ConstraintViolation.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/Embedded.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/Event.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/EventPage.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/EventType.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/HalRepresentation.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/LeagueDto.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/LeagueHierarchyDto.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/LeagueHierarchyPage.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/LeagueMatchDayDto.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/LeagueMatchDayPage.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/LeagueMatchDto.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/LeagueMatchPage.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/LeaguePage.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/LeagueRankingsEntryDto.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/LeagueRankingsResourcePage.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/LinkDto.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/Links.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/Location.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/LocationResourcePage.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/MatchResultTypeCount.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/RefereeTeamDto.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/ResponseException.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/ResponseExceptionMessage.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/SeasonDto.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/SportsclubDto.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/SportsclubPage.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/SuperCompetitionDto.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/SuperCompetitionPage.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/TeamDto.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/TeamPage.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/UserDetailsDto.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/ValidationError.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/VolleyballMatchResultsDto.js is excluded by !**/_generated/**
  • _Generated/js/RestClient/src/model/VolleyballMatchSetRestDto.js is excluded by !**/_generated/**
  • _Generated/php/RestClient/.gitignore is excluded by !**/_generated/**
  • _Generated/php/RestClient/.openapi-generator-ignore is excluded by !**/_generated/**
  • _Generated/php/RestClient/.openapi-generator/FILES is excluded by !**/_generated/**
  • _Generated/php/RestClient/.openapi-generator/VERSION is excluded by !**/_generated/**
  • _Generated/php/RestClient/.php-cs-fixer.dist.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/.travis.yml is excluded by !**/_generated/**
  • _Generated/php/RestClient/README.md is excluded by !**/_generated/**
  • _Generated/php/RestClient/composer.json is excluded by !**/_generated/**
  • _Generated/php/RestClient/git_push.sh is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Api/SAMSAssociationsAPIApi.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Api/SAMSCommitteesAPIApi.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Api/SAMSCompetitionMatchesAPIApi.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Api/SAMSCompetitionsAPIApi.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Api/SAMSEventTypesAPIApi.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Api/SAMSEventsAPIApi.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Api/SAMSLeagueHierarchiesAPIApi.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Api/SAMSLeagueMatchesAPIApi.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Api/SAMSLeaguesAPIApi.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Api/SAMSLocationsAPIApi.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Api/SAMSMatchDaysAPIApi.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Api/SAMSMatchGroupsAPIApi.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Api/SAMSRESTAPIV2Api.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Api/SAMSSeasonsAPIApi.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Api/SAMSSportsClubsAPIApi.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Api/SAMSSuperCompetitionsAPIApi.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Api/SAMSTeamsAPIApi.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Api/SAMSUserAPIApi.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/ApiException.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Configuration.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/FormDataProcessor.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/HeaderSelector.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/Address.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/Association.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/AssociationResourcePage.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/Committee.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/CommitteeMember.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/CommitteePage.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/CompetitionDto.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/CompetitionMatchDto.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/CompetitionMatchGroupDto.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/CompetitionMatchGroupPage.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/CompetitionMatchGroupRankingsDto.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/CompetitionMatchPage.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/CompetitionPage.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/CompetitionRankingsResourcePage.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/ConstraintViolation.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/Embedded.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/Event.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/EventPage.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/EventType.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/HalRepresentation.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/LeagueDto.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/LeagueHierarchyDto.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/LeagueHierarchyPage.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/LeagueMatchDayDto.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/LeagueMatchDayPage.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/LeagueMatchDto.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/LeagueMatchPage.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/LeaguePage.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/LeagueRankingsEntryDto.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/LeagueRankingsResourcePage.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/LinkDto.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/Links.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/Location.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/LocationResourcePage.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/MatchResultTypeCount.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/ModelInterface.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/RefereeTeamDto.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/ResponseException.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/ResponseExceptionMessage.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/SeasonDto.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/SportsclubDto.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/SportsclubPage.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/SuperCompetitionDto.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/SuperCompetitionPage.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/TeamDto.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/TeamPage.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/UserDetailsDto.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/ValidationError.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/VolleyballMatchResultsDto.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/Model/VolleyballMatchSetRestDto.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/lib/ObjectSerializer.php is excluded by !**/_generated/**
  • _Generated/php/RestClient/phpunit.xml.dist is excluded by !**/_generated/**
  • composer.lock is excluded by !**/*.lock
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (31)
  • .env-example
  • api-specs/hessen-volley.de/2.1.json
  • api-specs/nwvv.sams-server.de/2.1.json
  • api-specs/vvb.sams-server.de/2.1.json
  • api-specs/vvsa.sams-server.de/2.1.json
  • api-specs/wvv.sams-server.de/2.1.json
  • api-specs/www.dvv-ligen.de/2.1.json
  • api-specs/www.shvv.de/2.1.json
  • api-specs/www.ssvb.org/2.1.json
  • api-specs/www.tv-v.de/2.1.json
  • api-specs/www.vlw-online.de/2.1.json
  • api-specs/www.volley-saar.de/2.1.json
  • api-specs/www.volleyball-baden.de/2.1.json
  • api-specs/www.vvrp.de/2.1.json
  • build-plugin.sh
  • composer.json
  • docker-compose.yml
  • download-api-specs.sh
  • generate-restclients.sh
  • package.json
  • release-plugin-directory/trunk/readme.txt
  • sams-integration.php
  • src/blocks/sams-ranking/block.json
  • src/blocks/sams-ranking/edit.js
  • src/blocks/sams-ranking/render.php
  • src/php/Base/SAMSHostConfig/Reader.php
  • src/php/Base/SAMSProxy/AssociationsProxy.php
  • src/php/Base/SAMSProxy/BaseConfig.php
  • src/php/Base/SAMSProxy/Initializer.php
  • src/php/Editor/Models/RankingConfig.php
  • src/php/Editor/Models/SAMSHostConfig.php
✅ Files skipped from review due to trivial changes (1)
  • .env-example

📝 Walkthrough

Walkthrough

Adds a new Bash utility that downloads and normalizes OpenAPI specs from multiple SAMS server URLs and stores them by sanitized server folder and API version; also updates .env-example to enable WORDPRESS_DEBUG=true.

Changes

Cohort / File(s) Summary
API Specifications Download Script
download-api-specs.sh
New Bash script that iterates SAMS server base URLs, fetches /api/v2/swagger.json, validates non-empty content, normalizes the servers field to a single base URL, extracts info.version, creates sanitized folder names, and writes <version>.json into api-specs/<sanitized-url>/. Logs progress and errors.
Environment example
.env-example
Added WORDPRESS_DEBUG=true entry.

Sequence Diagram(s)

sequenceDiagram
    participant Script as "download-api-specs.sh"
    participant SAMS as "SAMS Server (swagger.json)"
    participant FS as "Local Filesystem (api-specs/)"
    Script->>SAMS: HTTP GET /api/v2/swagger.json
    SAMS-->>Script: swagger.json (JSON)
    Script->>Script: validate content\nextract info.version\nnormalize servers\nsanitize URL -> folder
    Script->>FS: mkdir -p api-specs/<sanitized-url>
    Script->>FS: write <version>.json
    alt empty/invalid response
        Script->>Script: log error (German message)\ncontinue
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped through URLs, swift and spry,
Fetched swagger tales from sky to sky,
I cleaned the servers, named each nest,
And tucked their versions in a tidy rest. ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 4

❌ Failed checks (3 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR adds a script to download API specifications but does not implement the core requirement from issue #55: adding a REST client to communicate with the REST API using OpenAPI Generator. Implement a REST client generated from the downloaded OpenAPI specifications using OpenAPI Generator, or add commits that demonstrate progress toward this objective.
Out of Scope Changes check ⚠️ Warning The addition of WORDPRESS_DEBUG=true to .env-example appears unrelated to the primary objective of adding REST API support or downloading API specifications. Remove the unrelated .env-example change or include it in a separate PR focused on WordPress debug configuration updates.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Add REST-API to project' is vague and generic, using non-descriptive phrasing that doesn't clearly convey the specific nature of the changes implemented. Consider using a more specific title like 'Add script to download OpenAPI specifications from SAMS servers' to better reflect the primary code changes.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-rest-api
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can suggest fixes for GitHub Check annotations.

Configure the reviews.tools.github-checks setting to adjust the time to wait for GitHub Checks to complete.

@renao renao marked this pull request as ready for review March 4, 2026 19:20
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 4, 2026

Note

Unit test generation is a public access feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@download-api-specs.sh`:
- Around line 28-32: The api_version value taken from the remote JSON (variable
api_version) is used directly to build filename/server_folder which allows
unsafe characters or path traversal; sanitize api_version before using it by
normalizing/restricting characters (e.g. replace slashes and backslashes with
'-', strip any ".." segments, and restrict to a safe whitelist like
[A-Za-z0-9._-], with a fallback value if empty) and then use the sanitized value
when constructing filename and server_folder so content is never written outside
the intended directory.
- Line 1: Add a Bash shebang as the very first line so the script runs under
Bash (it uses arrays and [[) — insert e.g. "#!/usr/bin/env bash" above the
existing "base_urls=(" line to ensure Bash is used instead of /bin/sh; no other
code changes required.
- Around line 21-28: The download/parsing path currently uses curl -s and jq -r
which can mask HTTP errors, hang without timeouts, and produce the literal
"null"; update the curl invocation that populates the variable content to use
fail-on-error and timeouts (e.g., enable -f plus --connect-timeout and
--max-time) and change the jq extraction for api_version to use jq -er
'.info.version // empty' so jq exits non-zero and emits nothing for missing/null
versions; after these changes, ensure the existing empty-check on content and
the handling that continues the loop when api_version is empty still apply
(variables: content, api_version).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 54fcc140-f9ed-44d8-9949-98b1bff889d9

📥 Commits

Reviewing files that changed from the base of the PR and between 9524f81 and d05850d.

📒 Files selected for processing (16)
  • api-specs/flvb.sams-server.de/2.1.json
  • api-specs/hessen-volley.de/2.1.json
  • api-specs/nwvv.sams-server.de/2.1.json
  • api-specs/vvb.sams-server.de/2.1.json
  • api-specs/vvsa.sams-server.de/2.1.json
  • api-specs/wvv.sams-server.de/2.1.json
  • api-specs/www.dvv-ligen.de/2.1.json
  • api-specs/www.shvv.de/2.1.json
  • api-specs/www.ssvb.org/2.1.json
  • api-specs/www.tv-v.de/2.1.json
  • api-specs/www.vlw-online.de/2.1.json
  • api-specs/www.volley-saar.de/2.1.json
  • api-specs/www.volleyball-baden.de/2.1.json
  • api-specs/www.volleyball-bundesliga.de/2.1.json
  • api-specs/www.vvrp.de/2.1.json
  • download-api-specs.sh

@@ -0,0 +1,36 @@
base_urls=(
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Read the file to check shebang, syntax, and content
cat -n download-api-specs.sh

Repository: renao/sams-integration

Length of output: 1324


🏁 Script executed:

# Run the proposed verification check from the review comment
#!/bin/bash
set -euo pipefail
# Parse checks only (read-only): bash should accept, sh should fail for bash-only syntax.
bash -n download-api-specs.sh
if sh -n download-api-specs.sh 2>&1; then
  echo "RESULT: Unexpected - POSIX sh parsed script successfully (may not use bash-only syntax)"
else
  echo "RESULT: Expected - POSIX sh parse failed (confirms bash-only syntax)"
fi

Repository: renao/sams-integration

Length of output: 189


Add Bash shebang (script uses Bash-only syntax and will fail under /bin/sh).

This script uses Bash arrays and [[ conditional syntax but has no shebang, making execution shell ambiguous. It fails to parse under POSIX sh with a "Syntax error: '(' unexpected".

Proposed fix
+#!/usr/bin/env bash
+set -euo pipefail
+
 base_urls=(
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
base_urls=(
#!/usr/bin/env bash
set -euo pipefail
base_urls=(
🧰 Tools
🪛 Shellcheck (0.11.0)

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@download-api-specs.sh` at line 1, Add a Bash shebang as the very first line
so the script runs under Bash (it uses arrays and [[) — insert e.g.
"#!/usr/bin/env bash" above the existing "base_urls=(" line to ensure Bash is
used instead of /bin/sh; no other code changes required.

Comment on lines +21 to +28
content=$(curl -s "$url/api/v2/swagger.json")

if [[ -z "$content" ]]; then
echo "Fehler: Kein Content von $url geladen!"
continue
fi

api_version=$(echo "$content" | jq -r '.info.version')
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "download-api-specs.sh" | head -20

Repository: renao/sams-integration

Length of output: 89


🏁 Script executed:

cat -n ./download-api-specs.sh

Repository: renao/sams-integration

Length of output: 1324


🏁 Script executed:

# Test 1: Verify jq -r behavior on missing field
echo '{"info": {}}' | jq -r '.info.version'
echo "Exit code: $?"

# Test 2: Verify jq -r behavior with missing top-level field
echo '{}' | jq -r '.info.version'
echo "Exit code: $?"

# Test 3: Verify proposed fix with jq -er
echo '{"info": {}}' | jq -er '.info.version // empty'
echo "Exit code: $?"

# Test 4: Verify proposed fix with valid data
echo '{"info": {"version": "1.0"}}' | jq -er '.info.version // empty'
echo "Exit code: $?"

Repository: renao/sams-integration

Length of output: 131


🏁 Script executed:

# Test curl -s behavior with HTTP error response
# We'll simulate this by checking what curl does
# First, let's verify curl exit codes with -s flag
echo "Testing curl -s behavior (using httpbin.org for testing):"
curl -s -w "\nHTTP Status: %{http_code}\n" https://httpbin.org/status/500 2>&1 | head -20
echo "---"
curl -s -w "\nHTTP Status: %{http_code}\n" https://httpbin.org/status/404 2>&1 | head -20

Repository: renao/sams-integration

Length of output: 163


Harden download/parsing path for HTTP and JSON failures.

curl -s hides HTTP errors without the -f flag, allowing non-2xx responses (e.g., HTML error pages) to pass the empty check; no timeout is set, risking indefinite hangs; jq -r outputs the literal string "null" when fields are missing, creating files like null.json with invalid content.

The proposed fix correctly addresses these issues:

  • curl -f makes curl exit non-zero on HTTP errors
  • --connect-timeout 10 --max-time 30 prevent hangs
  • jq -er '.info.version // empty' exits non-zero and outputs nothing when the field is missing or null, enabling proper error handling in bash
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@download-api-specs.sh` around lines 21 - 28, The download/parsing path
currently uses curl -s and jq -r which can mask HTTP errors, hang without
timeouts, and produce the literal "null"; update the curl invocation that
populates the variable content to use fail-on-error and timeouts (e.g., enable
-f plus --connect-timeout and --max-time) and change the jq extraction for
api_version to use jq -er '.info.version // empty' so jq exits non-zero and
emits nothing for missing/null versions; after these changes, ensure the
existing empty-check on content and the handling that continues the loop when
api_version is empty still apply (variables: content, api_version).

Comment on lines +28 to +32
api_version=$(echo "$content" | jq -r '.info.version')
server_folder="api-specs/$(echo $url | sed 's/https\?:\/\///g' | sed 's/\//-/g')"
filename="$server_folder/${api_version}.json"
mkdir -p "$server_folder"
echo "$content" > "$filename"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Sanitize remote api_version before using it in a filename.

api_version comes from remote JSON and is used directly in the path. Unsafe characters (including / or ..) can lead to unintended writes.

Proposed fix
     api_version=$(echo "$content" | jq -r '.info.version')
     server_folder="api-specs/$(echo $url | sed 's/https\?:\/\///g' | sed 's/\//-/g')"
-    filename="$server_folder/${api_version}.json"
+    safe_version=$(printf '%s' "$api_version" | sed -E 's/[^A-Za-z0-9._-]+/_/g')
+    if [[ -z "$safe_version" ]]; then
+        echo "Error: Unsafe API version '$api_version' from $url" >&2
+        continue
+    fi
+    filename="$server_folder/${safe_version}.json"
     mkdir -p "$server_folder"
     echo "$content" > "$filename"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
api_version=$(echo "$content" | jq -r '.info.version')
server_folder="api-specs/$(echo $url | sed 's/https\?:\/\///g' | sed 's/\//-/g')"
filename="$server_folder/${api_version}.json"
mkdir -p "$server_folder"
echo "$content" > "$filename"
api_version=$(echo "$content" | jq -r '.info.version')
server_folder="api-specs/$(echo $url | sed 's/https\?:\/\///g' | sed 's/\//-/g')"
safe_version=$(printf '%s' "$api_version" | sed -E 's/[^A-Za-z0-9._-]+/_/g')
if [[ -z "$safe_version" ]]; then
echo "Error: Unsafe API version '$api_version' from $url" >&2
continue
fi
filename="$server_folder/${safe_version}.json"
mkdir -p "$server_folder"
echo "$content" > "$filename"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@download-api-specs.sh` around lines 28 - 32, The api_version value taken from
the remote JSON (variable api_version) is used directly to build
filename/server_folder which allows unsafe characters or path traversal;
sanitize api_version before using it by normalizing/restricting characters (e.g.
replace slashes and backslashes with '-', strip any ".." segments, and restrict
to a safe whitelist like [A-Za-z0-9._-], with a fallback value if empty) and
then use the sanitized value when constructing filename and server_folder so
content is never written outside the intended directory.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 4, 2026

✅ Created PR with unit tests: #63

renao added 2 commits March 5, 2026 09:10
* Replace server.url with absolute url (for rest client generation)
* Save json files formatted (for better diffs in the future)
* Refactor
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (3)
download-api-specs.sh (3)

56-56: ⚠️ Potential issue | 🟠 Major

Sanitize remote api_version before building the filename.

Line [56] uses server-provided api_version directly in the path. Unsafe characters (including slashes) can write outside the intended location.

Proposed fix
-    filename="$server_folder/${api_version}.json"
+    safe_version=$(printf '%s' "$api_version" | sed -E 's/[^A-Za-z0-9._-]+/_/g')
+    if [[ -z "$safe_version" ]]; then
+        echo "Error: Unsafe API version '$api_version' from $url" >&2
+        continue
+    fi
+    filename="$server_folder/${safe_version}.json"
#!/usr/bin/env bash
set -euo pipefail

sanitize() {
  printf '%s' "$1" | sed -E 's/[^A-Za-z0-9._-]+/_/g'
}

for v in "v2.1.0" "../x" "2026/03" " "; do
  echo "$v -> $(sanitize "$v")"
done
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@download-api-specs.sh` at line 56, Sanitize the server-provided api_version
before using it to build filename (currently:
filename="$server_folder/${api_version}.json") to prevent directory traversal or
unsafe characters; add a helper (e.g., sanitize function) that replaces any
character not in [A-Za-z0-9._-] with an underscore and use the sanitized result
(e.g., sanitized_version) when composing filename and any file paths that
reference api_version, ensuring server_folder and filename concatenation only
uses the sanitized token.

30-33: ⚠️ Potential issue | 🟠 Major

Harden HTTP fetch and version extraction failure handling.

Line [44] uses curl -s (no fail-fast/timeouts), and Line [32] uses jq -r, which can return literal null. This can silently generate invalid outputs.

Proposed fix
 get_api_version() {
     local json_content="$1"
-    echo "$json_content" | jq -r '.info.version'
+    echo "$json_content" | jq -er '.info.version // empty'
 }
@@
-    content=$(curl -s "$api_base_url/swagger.json")
+    if ! content=$(curl -fsS --connect-timeout 10 --max-time 30 "$api_base_url/swagger.json"); then
+        echo "Error: Failed to download swagger.json from $url" >&2
+        continue
+    fi
@@
     api_version=$(get_api_version "$content")
+    if [[ -z "$api_version" ]]; then
+        echo "Error: Missing info.version in spec from $url" >&2
+        continue
+    fi
#!/usr/bin/env bash
set -euo pipefail

# jq behavior check: -r vs -er for missing value
echo '{}' | jq -r '.info.version'; echo " <- jq -r output"
if echo '{}' | jq -er '.info.version // empty' >/dev/null; then
  echo "Unexpected: jq -er succeeded for missing version"
else
  echo "Expected: jq -er fails for missing version"
fi

# curl behavior check for HTTP errors
code_no_fail=$(curl -s -o /dev/null -w '%{http_code}' https://httpbin.org/status/404 || true)
echo "curl -s status: $code_no_fail"
if curl -fsS https://httpbin.org/status/404 >/dev/null 2>&1; then
  echo "Unexpected: curl -f succeeded on 404"
else
  echo "Expected: curl -f fails on 404"
fi

Also applies to: 44-49, 53-54

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@download-api-specs.sh` around lines 30 - 33, The get_api_version function can
return the literal "null" silently; change it to use jq's strict-fail mode
(e.g., jq -er with a safe default like '.info.version // empty') and make the
function return a non-empty value or fail so callers can detect the error;
likewise harden the HTTP fetch that uses curl by adding fail-fast and error
output flags (use -fS), a sensible timeout (e.g., --max-time), and check exit
status / HTTP code so failures are handled instead of producing empty/invalid
JSON for get_api_version to parse.

1-1: ⚠️ Potential issue | 🔴 Critical

Fix the shebang syntax so Bash is actually used.

Line [1] uses # !/bin/bash, which is treated as a comment, not a shebang. This can execute under /bin/sh and fail on Bash array syntax.

Proposed fix
-# !/bin/bash
+#!/usr/bin/env bash
+set -euo pipefail
#!/usr/bin/env bash
set -euo pipefail

# Verify interpreter parsing behavior
bash -n download-api-specs.sh
if sh -n download-api-specs.sh; then
  echo "Unexpected: script parses in sh"
else
  echo "Expected: script requires bash syntax"
fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@download-api-specs.sh` at line 1, The leading shebang is malformed ("#
!/bin/bash") so the script may be run under /bin/sh; replace the first line with
a proper Bash shebang (for example "#!/usr/bin/env bash" or "#!/bin/bash") and
add strict mode (e.g., "set -euo pipefail") near the top; after updating,
validate the script with "bash -n download-api-specs.sh" (and optionally verify
it fails under sh with "sh -n download-api-specs.sh") to ensure it indeed
requires Bash-only syntax.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@download-api-specs.sh`:
- Line 56: Sanitize the server-provided api_version before using it to build
filename (currently: filename="$server_folder/${api_version}.json") to prevent
directory traversal or unsafe characters; add a helper (e.g., sanitize function)
that replaces any character not in [A-Za-z0-9._-] with an underscore and use the
sanitized result (e.g., sanitized_version) when composing filename and any file
paths that reference api_version, ensuring server_folder and filename
concatenation only uses the sanitized token.
- Around line 30-33: The get_api_version function can return the literal "null"
silently; change it to use jq's strict-fail mode (e.g., jq -er with a safe
default like '.info.version // empty') and make the function return a non-empty
value or fail so callers can detect the error; likewise harden the HTTP fetch
that uses curl by adding fail-fast and error output flags (use -fS), a sensible
timeout (e.g., --max-time), and check exit status / HTTP code so failures are
handled instead of producing empty/invalid JSON for get_api_version to parse.
- Line 1: The leading shebang is malformed ("# !/bin/bash") so the script may be
run under /bin/sh; replace the first line with a proper Bash shebang (for
example "#!/usr/bin/env bash" or "#!/bin/bash") and add strict mode (e.g., "set
-euo pipefail") near the top; after updating, validate the script with "bash -n
download-api-specs.sh" (and optionally verify it fails under sh with "sh -n
download-api-specs.sh") to ensure it indeed requires Bash-only syntax.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fd3afadb-79f4-4e85-869f-546668f48a24

📥 Commits

Reviewing files that changed from the base of the PR and between 9524f81 and e5c927e.

📒 Files selected for processing (16)
  • api-specs/flvb.sams-server.de/2.1.json
  • api-specs/hessen-volley.de/2.1.json
  • api-specs/nwvv.sams-server.de/2.1.json
  • api-specs/vvb.sams-server.de/2.1.json
  • api-specs/vvsa.sams-server.de/2.1.json
  • api-specs/wvv.sams-server.de/2.1.json
  • api-specs/www.dvv-ligen.de/2.1.json
  • api-specs/www.shvv.de/2.1.json
  • api-specs/www.ssvb.org/2.1.json
  • api-specs/www.tv-v.de/2.1.json
  • api-specs/www.vlw-online.de/2.1.json
  • api-specs/www.volley-saar.de/2.1.json
  • api-specs/www.volleyball-baden.de/2.1.json
  • api-specs/www.volleyball-bundesliga.de/2.1.json
  • api-specs/www.vvrp.de/2.1.json
  • download-api-specs.sh

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 10, 2026

✅ Created PR with unit tests: #64

Repository owner deleted a comment from coderabbitai bot Mar 11, 2026
Repository owner deleted a comment from coderabbitai bot Mar 11, 2026
Repository owner deleted a comment from coderabbitai bot Mar 11, 2026
* @type {String}
* @default https://wvv.sams-server.de/api/v2
*/
this.basePath = basePath.replace(/\/+$/, '');

Check failure

Code scanning / CodeQL

Polynomial regular expression used on uncontrolled data High

This
regular expression
that depends on
library input
may run slow on strings with many repetitions of '/'.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add RestClient to communicate with the new REST API

2 participants