Skip to content

remove sprintf for prefixing scopes#519

Open
smarcet wants to merge 1 commit intomainfrom
feature/prefixed-const-scopes
Open

remove sprintf for prefixing scopes#519
smarcet wants to merge 1 commit intomainfrom
feature/prefixed-const-scopes

Conversation

@smarcet
Copy link
Collaborator

@smarcet smarcet commented Mar 14, 2026

Summary by CodeRabbit

  • New Features

    • Added Swagger UI preview generation for pull requests with interactive API documentation and automatic PR preview links.
  • Chores

    • Standardized security scope naming to use a centralized base realm constant across the app.
    • Added Teams scope entries and updated seed/test data to align with the new centralized scope constants.

@coderabbitai
Copy link

coderabbitai bot commented Mar 14, 2026

📝 Walkthrough

Walkthrough

Replaces sprintf-based realm scope strings with a global SCOPE_BASE_REALM constant across security scope classes, seeders, tests, and consumers; adds a new TeamScopes class; ensures SCOPE_BASE_REALM is defined in AppServiceProvider; and adds a Swagger UI build + PR-preview GitHub Actions workflow.

Changes

Cohort / File(s) Summary
Scope Constants Refactor
app/Security/CompanyScopes.php, app/Security/GroupsScopes.php, app/Security/MemberScopes.php, app/Security/OrganizationScopes.php, app/Security/SponsoredProjectScope.php, app/Security/SummitScopes.php, app/Security/TeamScopes.php
Replaced '%s/...' format placeholders with SCOPE_BASE_REALM.'/...' in public constants. SummitScopes gained many new constants; TeamScopes.php added a new class with Read/Write constants.
Scope Consumers
app/Http/Utils/FilterAvailableSummitsStrategy.php, app/ModelSerializers/Summit/SummitSerializer.php
Removed dynamic sprintf-based scope construction; now use fixed scope constants (e.g., SummitScopes::ReadAllSummitData) and dropped reliance on Config::get('app.scope_base_realm').
Bootstrap / Provider
app/Providers/AppServiceProvider.php
Added guard logic in boot() and register() to define the global SCOPE_BASE_REALM constant from config('app.scope_base_realm') if not already defined.
Seeders & Data
database/seeders/ApiScopesSeeder.php
Replaced sprintf-generated scope names with scope constants; updated imports to include new scope classes; switched some arrays to short syntax; adjusted descriptions and scope entries accordingly.
Tests
tests/ProtectedApiTestCase.php
Updated test access-token stubs to use scope constants (added imports for GroupsScopes, TeamScopes); modified token metadata in one stub (nullified user ids, set application_type to SERVICE, emptied user_groups).
CI / Docs Workflow
.github/workflows/l5-swagger-generate.yml
Added GitHub Actions steps to build a Swagger UI preview artifact, upload it, and a PR-preview workflow that downloads the artifact, publishes to GitHub Pages under openapi/pr-<PR_NUMBER>, and posts a PR comment with the preview URL.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰
From sprintf burrows to a single seam,
SCOPE_BASE_REALM guides the scope stream.
TeamScopes hops in, constants in tow,
Swagger previews ready to show.
A rabbit cheers — tidy scopes, on we go!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main refactoring: replacing sprintf-based dynamic scope string construction with predefined constant values using SCOPE_BASE_REALM.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/prefixed-const-scopes
📝 Coding Plan
  • Generate coding plan for human review comments

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

@smarcet smarcet force-pushed the feature/prefixed-const-scopes branch from 0c5d732 to dfbf1ab Compare March 14, 2026 03:54
Copy link

@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: 2

🧹 Nitpick comments (3)
tests/ProtectedApiTestCase.php (2)

30-31: GroupsScopes is imported but never used.

The import for GroupsScopes is added but no GroupsScopes constants are used in either AccessTokenServiceStub or AccessTokenServiceStub2.

🧹 Suggested fix: Either remove the unused import or add the scope

If the scope should be included in test tokens:

             SummitScopes::ReadBadgeScanValidate,
+            GroupsScopes::ReadData,
             RSVPInvitationsScopes::Write,

Or remove the unused import:

 use App\Security\SponsoredProjectScope;
-use App\Security\GroupsScopes;
 use App\Security\TeamScopes;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/ProtectedApiTestCase.php` around lines 30 - 31, The import for
GroupsScopes is unused; either remove the unused import line "use
App\Security\GroupsScopes;" or add the appropriate GroupsScopes constant(s) to
the test token scopes in the stub classes. Locate AccessTokenServiceStub and
AccessTokenServiceStub2 in this file and either append the relevant
GroupsScopes::<CONSTANT> value(s) to their scopes arrays used when building
tokens, or simply delete the GroupsScopes import if those stubs should not
include group scopes.

82-85: Consider creating scope constants to complete the migration.

The following scopes in ProtectedApiTestCase.php still use $url . '/...' concatenation instead of constants (lines 83-85, 99-100):

  • public-clouds/read
  • private-clouds/read
  • consultants/read
  • members/invitations/read
  • members/invitations/write

No scope constants currently exist for these. Creating dedicated scope classes (e.g., PublicCloudsScopes, PrivateCloudsScopes, ConsultantsScopes) would provide better consistency and maintainability alongside the existing SummitScopes, MemberScopes, and TeamScopes classes.

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

In `@tests/ProtectedApiTestCase.php` around lines 82 - 85, Replace the ad-hoc
"$url . '/...'" scope concatenations in ProtectedApiTestCase.php by introducing
and using dedicated scope constant classes for the missing domains: add
PublicCloudsScopes, PrivateCloudsScopes and ConsultantsScopes (each exposing
named constants such as READ) and add MembersInvitations or extend MembersScopes
to provide INVITATIONS_READ and INVITATIONS_WRITE constants; then update the
$scopes array and any other places currently using "$url .
'/public-clouds/read'", "$url . '/private-clouds/read'", "$url .
'/consultants/read'", "$url . '/members/invitations/read'", and "$url .
'/members/invitations/write'" to reference the new constants (e.g.,
PublicCloudsScopes::READ) instead of string concatenation.
app/Http/Utils/FilterAvailableSummitsStrategy.php (1)

15-15: Remove unused import.

The Config facade is no longer used in this file after the refactor.

🧹 Suggested fix
 use App\Security\SummitScopes;
-use Illuminate\Support\Facades\Config;
 use models\oauth2\IResourceServerContext;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/Http/Utils/FilterAvailableSummitsStrategy.php` at line 15, Remove the
now-unused Config facade import from the top of
FilterAvailableSummitsStrategy.php: locate the use
Illuminate\Support\Facades\Config; statement in the file (used alongside the
FilterAvailableSummitsStrategy class) and delete that import line so the file
only retains necessary use statements.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/Providers/AppServiceProvider.php`:
- Around line 721-723: Normalize and validate the config value before defining
SCOPE_BASE_REALM: read config('app.scope_base_realm'), trim whitespace and
remove any trailing slashes, then ensure the resulting string is non-empty (or
fail loudly/log an error) before calling define('SCOPE_BASE_REALM', ...). Update
the code around the SCOPE_BASE_REALM definition in AppServiceProvider (where you
currently call define with the raw config value) to perform the trim/rtrim and
non-empty check first so generated scopes won't contain empty segments or
trailing slashes.

In `@tests/ProtectedApiTestCase.php`:
- Around line 194-195: The array of scopes contains a duplicate entry of
SummitScopes::WriteVideoData; remove the redundant SummitScopes::WriteVideoData
occurrence so the list only includes that scope once (locate the scope list
where SummitScopes::WriteVideoData appears twice and delete the duplicate
entry).

---

Nitpick comments:
In `@app/Http/Utils/FilterAvailableSummitsStrategy.php`:
- Line 15: Remove the now-unused Config facade import from the top of
FilterAvailableSummitsStrategy.php: locate the use
Illuminate\Support\Facades\Config; statement in the file (used alongside the
FilterAvailableSummitsStrategy class) and delete that import line so the file
only retains necessary use statements.

In `@tests/ProtectedApiTestCase.php`:
- Around line 30-31: The import for GroupsScopes is unused; either remove the
unused import line "use App\Security\GroupsScopes;" or add the appropriate
GroupsScopes constant(s) to the test token scopes in the stub classes. Locate
AccessTokenServiceStub and AccessTokenServiceStub2 in this file and either
append the relevant GroupsScopes::<CONSTANT> value(s) to their scopes arrays
used when building tokens, or simply delete the GroupsScopes import if those
stubs should not include group scopes.
- Around line 82-85: Replace the ad-hoc "$url . '/...'" scope concatenations in
ProtectedApiTestCase.php by introducing and using dedicated scope constant
classes for the missing domains: add PublicCloudsScopes, PrivateCloudsScopes and
ConsultantsScopes (each exposing named constants such as READ) and add
MembersInvitations or extend MembersScopes to provide INVITATIONS_READ and
INVITATIONS_WRITE constants; then update the $scopes array and any other places
currently using "$url . '/public-clouds/read'", "$url . '/private-clouds/read'",
"$url . '/consultants/read'", "$url . '/members/invitations/read'", and "$url .
'/members/invitations/write'" to reference the new constants (e.g.,
PublicCloudsScopes::READ) instead of string concatenation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2c6942ce-858e-4b11-87a4-6779f87ac002

📥 Commits

Reviewing files that changed from the base of the PR and between 8102c7a and 0c5d732.

📒 Files selected for processing (14)
  • .github/workflows/l5-swagger-generate.yml
  • app/Http/Utils/FilterAvailableSummitsStrategy.php
  • app/ModelSerializers/Summit/SummitSerializer.php
  • app/Providers/AppServiceProvider.php
  • app/Security/CompanyScopes.php
  • app/Security/GroupsScopes.php
  • app/Security/MemberScopes.php
  • app/Security/OrganizationScopes.php
  • app/Security/SponsoredProjectScope.php
  • app/Security/SummitScopes.php
  • app/Security/TeamScopes.php
  • database/seeders/ApiEndpointsSeeder.php
  • database/seeders/ApiScopesSeeder.php
  • tests/ProtectedApiTestCase.php

Comment on lines +721 to +723
if (!defined('SCOPE_BASE_REALM')) {
define('SCOPE_BASE_REALM', config('app.scope_base_realm'));
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Normalize and validate SCOPE_BASE_REALM before defining it.

Line 722 uses the raw config value directly. If it is empty or ends with /, generated scopes can become invalid/mismatched (e.g., /members/read or ...//members/read), which can break auth checks.

🔧 Proposed fix
         if (!defined('SCOPE_BASE_REALM')) {
-            define('SCOPE_BASE_REALM', config('app.scope_base_realm'));
+            $scopeBaseRealm = rtrim((string) config('app.scope_base_realm', ''), '/');
+            if ($scopeBaseRealm === '') {
+                throw new \RuntimeException('Missing required config: app.scope_base_realm');
+            }
+            define('SCOPE_BASE_REALM', $scopeBaseRealm);
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/Providers/AppServiceProvider.php` around lines 721 - 723, Normalize and
validate the config value before defining SCOPE_BASE_REALM: read
config('app.scope_base_realm'), trim whitespace and remove any trailing slashes,
then ensure the resulting string is non-empty (or fail loudly/log an error)
before calling define('SCOPE_BASE_REALM', ...). Update the code around the
SCOPE_BASE_REALM definition in AppServiceProvider (where you currently call
define with the raw config value) to perform the trim/rtrim and non-empty check
first so generated scopes won't contain empty segments or trailing slashes.

Comment on lines +194 to +195
SummitScopes::WriteVideoData,
SummitScopes::WriteVideoData,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Duplicate scope entry: SummitScopes::WriteVideoData appears twice.

This is likely a copy-paste error. The duplicate should be removed.

🐛 Proposed fix
             SummitScopes::WriteSummitsConfirmExternalOrders,
             SummitScopes::WriteVideoData,
-            SummitScopes::WriteVideoData,
             SummitScopes::MeRead,
📝 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
SummitScopes::WriteVideoData,
SummitScopes::WriteVideoData,
SummitScopes::WriteSummitsConfirmExternalOrders,
SummitScopes::WriteVideoData,
SummitScopes::MeRead,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/ProtectedApiTestCase.php` around lines 194 - 195, The array of scopes
contains a duplicate entry of SummitScopes::WriteVideoData; remove the redundant
SummitScopes::WriteVideoData occurrence so the list only includes that scope
once (locate the scope list where SummitScopes::WriteVideoData appears twice and
delete the duplicate entry).

@github-actions
Copy link

📘 OpenAPI / Swagger preview

➡️ https://OpenStackweb.github.io/summit-api/openapi/pr-519/

This page is automatically updated on each push to this PR.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR standardizes OAuth scope strings across the app by removing sprintf-based realm prefixing and centralizing scope construction around a shared base realm constant. It also extends CI to generate and publish a Swagger UI preview for pull requests.

Changes:

  • Replaced sprintf($scope, $realm) patterns with scope constants that include the base realm (SCOPE_BASE_REALM).
  • Updated seed/test data to use the new centralized scope constants (and added Teams/Groups scope constants).
  • Added a GitHub Actions workflow job to publish Swagger UI previews to GitHub Pages and comment the preview URL on PRs.

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/ProtectedApiTestCase.php Switched hardcoded/sprintf scopes to centralized scope constants in protected API test stubs.
database/seeders/ApiScopesSeeder.php Seeds scopes using the new scope constants (no more realm sprintf).
app/Security/TeamScopes.php Introduces centralized Teams scope constants.
app/Security/SummitScopes.php Converts Summit scopes from format strings to realm-prefixed constants.
app/Security/SponsoredProjectScope.php Converts sponsored project scopes to realm-prefixed constants.
app/Security/OrganizationScopes.php Converts organization scopes to realm-prefixed constants.
app/Security/MemberScopes.php Converts member scopes to realm-prefixed constants.
app/Security/GroupsScopes.php Converts groups scope to realm-prefixed constant.
app/Security/CompanyScopes.php Converts company scopes to realm-prefixed constants.
app/Providers/AppServiceProvider.php Defines SCOPE_BASE_REALM from config('app.scope_base_realm') during registration.
app/ModelSerializers/Summit/SummitSerializer.php Uses centralized SummitScopes::ReadAllSummitData for access checks.
app/Http/Utils/FilterAvailableSummitsStrategy.php Uses centralized SummitScopes::ReadAllSummitData for access checks.
.github/workflows/l5-swagger-generate.yml Generates Swagger UI artifact and publishes a per-PR preview to GitHub Pages with PR comment.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +149 to +159
pages-preview:
name: Publish Swagger UI to GitHub Pages
needs: openapi-generate
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest

permissions:
contents: write
issues: write
pull-requests: write

Comment on lines +184 to +209
- name: Comment preview URL on PR
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prNumber = context.payload.pull_request.number;
const owner = context.repo.owner;
const repo = context.repo.repo;
const baseUrl = `https://${owner}.github.io/${repo}`;
const previewPath = `/openapi/pr-${prNumber}/`;
const url = `${baseUrl}${previewPath}`;

const body = [
'📘 **OpenAPI / Swagger preview**',
'',
`➡️ ${url}`,
'',
'This page is automatically updated on each push to this PR.'
].join('\n');

await github.rest.issues.createComment({
owner,
repo,
issue_number: prNumber,
body,
});
use App\Models\Foundation\Main\IGroup;
use App\Security\CompanyScopes;
use App\Security\SponsoredProjectScope;
use App\Security\GroupsScopes;
Comment on lines 28 to 31
static public function shouldReturnAllSummits(IResourceServerContext $resource_server_ctx){
$scopes = $resource_server_ctx->getCurrentScope();
$current_realm = Config::get('app.scope_base_realm');
$needed_scope = sprintf(SummitScopes::ReadAllSummitData, $current_realm);
$needed_scope = SummitScopes::ReadAllSummitData;
return in_array($needed_scope, $scopes);
Comment on lines +125 to +129
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist/swagger-ui.css" />
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js"></script>
Copy link

@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

♻️ Duplicate comments (1)
tests/ProtectedApiTestCase.php (1)

194-195: ⚠️ Potential issue | 🟡 Minor

SummitScopes::WriteVideoData is still duplicated here.

The fixture grants the same scope twice, so the test token no longer reflects a clean scope set.

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

In `@tests/ProtectedApiTestCase.php` around lines 194 - 195, The fixture
duplicates SummitScopes::WriteVideoData in the granted scopes array, producing a
non-unique scope set; update the fixture used in ProtectedApiTestCase by
removing the duplicate SummitScopes::WriteVideoData entry (or replace it with
the intended missing scope) so the test token reflects a clean, unique set of
scopes—look for the array that lists SummitScopes::WriteVideoData twice and
ensure each scope appears only once.
🧹 Nitpick comments (2)
.github/workflows/l5-swagger-generate.yml (2)

125-129: Pin the Swagger UI assets.

Line 125 and Line 129 pull swagger-ui-dist from floating unpkg URLs, so an upstream release can break this preview without any change in this repo. Pin an explicit version or publish the assets with the artifact.

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

In @.github/workflows/l5-swagger-generate.yml around lines 125 - 129, The
workflow currently loads Swagger UI assets from floating unpkg URLs in the HTML
snippet (the <link rel="stylesheet"
href="https://unpkg.com/swagger-ui-dist/swagger-ui.css" /> and <script
src="https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js"></script>), which
risks breakage; update these references to pin a specific version (e.g., replace
"unpkg.com/swagger-ui-dist/..." with "unpkg.com/swagger-ui-dist@<version>/...")
or serve the CSS/JS from a repository artifact or CDN with an immutable URL so
the preview cannot be broken by upstream releases.

184-209: Upsert the preview comment instead of creating a new one.

Line 204 calls createComment on every run, so active PRs will accumulate duplicate preview messages. Prefer updating one sticky bot comment.

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

In @.github/workflows/l5-swagger-generate.yml around lines 184 - 209, Replace
the unconditional github.rest.issues.createComment call with logic that first
lists existing comments for the PR (use github.rest.issues.listComments with
context.repo and context.payload.pull_request.number), search for a bot comment
that starts with the preview header text (e.g. '📘 **OpenAPI / Swagger
preview**'), and if found call github.rest.issues.update to replace that
comment’s body; only fall back to github.rest.issues.createComment when no
matching comment exists. Ensure you preserve the assembled body string and
reference the existing comment id (comment.id) when calling issues.update.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/l5-swagger-generate.yml:
- Around line 149-183: The pages-preview job runs on pull_request events but
will fail for forked PRs because the read-only GITHUB_TOKEN prevents
peaceiris/actions-gh-pages@v4 from pushing; update the job's if condition (job
name: pages-preview) to only run for same-repo PRs by adding a fork check, e.g.
change the existing if: github.event_name == 'pull_request' to include
github.event.pull_request.head.repo.fork == false (or equivalent comparison such
as github.event.pull_request.head.repo.full_name == github.repository) so the
peaceiris/actions-gh-pages@v4 step only executes for non-fork PRs.

In `@database/seeders/ApiScopesSeeder.php`:
- Around line 55-396: The seedSummitScopes() seeder is missing several new
SummitScopes constants so fresh DBs won't get corresponding ApiScope rows;
update the $scopes array in ApiScopesSeeder::seedSummitScopes() to include
entries for SummitScopes::WriteSubmissionInvitations,
SummitScopes::ReadSubmissionInvitations, SummitScopes::ReadBookableRoomsData,
SummitScopes::BookableRoomsReservation, SummitScopes::WriteBookableRoomsData,
SummitScopes::WriteNotifications, SummitScopes::WriteEventTypeData,
SummitScopes::WriteTracksData, SummitScopes::WriteTrackGroupsData,
SummitScopes::WriteRSVPTemplateData,
SummitScopes::WriteSummitSpeakerAssistanceData, and
SummitScopes::WriteTicketTypeData (use consistent short_description/description
patterns used by other entries and reference SummitScopes.php for exact constant
names).
- Around line 510-523: The organization scopes are being attached to the wrong
API because seedOrganizationScopes() resolves the API with ['name' =>
'companies']; update the lookup so $api =
EntityManager::getRepository(\App\Models\ResourceServer\Api::class)->findOneBy(['name'
=> 'organizations']) (or the exact resource-server name used for organizations)
so OrganizationScopes::ReadOrganizationData and
OrganizationScopes::WriteOrganizationData are persisted against the correct API;
verify subsequent use of $api in this method still assigns scopes to that $api.

---

Duplicate comments:
In `@tests/ProtectedApiTestCase.php`:
- Around line 194-195: The fixture duplicates SummitScopes::WriteVideoData in
the granted scopes array, producing a non-unique scope set; update the fixture
used in ProtectedApiTestCase by removing the duplicate
SummitScopes::WriteVideoData entry (or replace it with the intended missing
scope) so the test token reflects a clean, unique set of scopes—look for the
array that lists SummitScopes::WriteVideoData twice and ensure each scope
appears only once.

---

Nitpick comments:
In @.github/workflows/l5-swagger-generate.yml:
- Around line 125-129: The workflow currently loads Swagger UI assets from
floating unpkg URLs in the HTML snippet (the <link rel="stylesheet"
href="https://unpkg.com/swagger-ui-dist/swagger-ui.css" /> and <script
src="https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js"></script>), which
risks breakage; update these references to pin a specific version (e.g., replace
"unpkg.com/swagger-ui-dist/..." with "unpkg.com/swagger-ui-dist@<version>/...")
or serve the CSS/JS from a repository artifact or CDN with an immutable URL so
the preview cannot be broken by upstream releases.
- Around line 184-209: Replace the unconditional
github.rest.issues.createComment call with logic that first lists existing
comments for the PR (use github.rest.issues.listComments with context.repo and
context.payload.pull_request.number), search for a bot comment that starts with
the preview header text (e.g. '📘 **OpenAPI / Swagger preview**'), and if found
call github.rest.issues.update to replace that comment’s body; only fall back to
github.rest.issues.createComment when no matching comment exists. Ensure you
preserve the assembled body string and reference the existing comment id
(comment.id) when calling issues.update.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ad32f831-4cf6-4bb1-9c02-0be36d2c5a9e

📥 Commits

Reviewing files that changed from the base of the PR and between 0c5d732 and dfbf1ab.

📒 Files selected for processing (14)
  • .github/workflows/l5-swagger-generate.yml
  • app/Http/Utils/FilterAvailableSummitsStrategy.php
  • app/ModelSerializers/Summit/SummitSerializer.php
  • app/Providers/AppServiceProvider.php
  • app/Security/CompanyScopes.php
  • app/Security/GroupsScopes.php
  • app/Security/MemberScopes.php
  • app/Security/OrganizationScopes.php
  • app/Security/SponsoredProjectScope.php
  • app/Security/SummitScopes.php
  • app/Security/TeamScopes.php
  • database/seeders/ApiEndpointsSeeder.php
  • database/seeders/ApiScopesSeeder.php
  • tests/ProtectedApiTestCase.php
🚧 Files skipped from review as they are similar to previous changes (5)
  • app/ModelSerializers/Summit/SummitSerializer.php
  • app/Security/SponsoredProjectScope.php
  • app/Providers/AppServiceProvider.php
  • app/Security/TeamScopes.php
  • app/Security/MemberScopes.php

Comment on lines +149 to +183
pages-preview:
name: Publish Swagger UI to GitHub Pages
needs: openapi-generate
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest

permissions:
contents: write
issues: write
pull-requests: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Download Swagger UI artifact
uses: actions/download-artifact@v4
with:
name: swagger-ui
path: swagger-ui

- name: Build public directory for GitHub Pages
run: |
PR_PATH="openapi/pr-${{ github.event.number }}"
mkdir -p "public/${PR_PATH}"
cp -R swagger-ui/* "public/${PR_PATH}/"
echo "Built GitHub Pages content at public/${PR_PATH}"

- name: Publish to GitHub Pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public
keep_files: true

Copy link

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

🌐 Web query:

GitHub Actions GITHUB_TOKEN fork pull request read-only permissions

💡 Result:

For workflows triggered by pull_request events from a fork, GitHub deliberately downgrades GITHUB_TOKEN to read-only and does not pass repository secrets (this is not overrideable via permissions: in the workflow). [1][2]

Key implications / options:

  • You can’t “grant write” to GITHUB_TOKEN for fork PR runs on pull_request; GitHub caps it at read-only for safety. [1][2]
  • If you need privileged automation on PRs (labeling, commenting, etc.), many repos use pull_request_target, which runs in the base repo context and therefore can have read/write GITHUB_TOKEN and access to secrets unless you restrict it—but this is security-sensitive (don’t run untrusted fork code in that context). [1]
  • For private/internal repos, there are repository/enterprise settings to allow fork PR workflows and (optionally) “send write tokens” and/or “send secrets” to fork PR workflows. [3]

Sources: GitHub Actions docs on fork PR restrictions and pull_request_target behavior [1], GitHub changelog noting fork PR tokens are always read-only [2], and GitHub settings/policy docs for fork PR workflows in private repos (including “send write tokens”) [3].

References:
[1] (docs.github.com)
[2] (github.blog)
[3] (docs.github.com)

Citations:


🌐 Web query:

peaceiris/actions-gh-pages write permissions requirements

💡 Result:

To use peaceiris/actions-gh-pages with GITHUB_TOKEN, your workflow/job must grant the token write access to repository contents (so it can push commits/tags to the publishing branch, usually gh-pages). The README explicitly calls out fixing 403 Write access to repository not granted by adding: permissions: contents: write. (github.com)

Example:

jobs:
  deploy:
    permissions:
      contents: write
    steps:
      - uses: peaceiris/actions-gh-pages@v4
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./public

(github.com)

If you still get “permission denied” errors, also check the repository setting Settings → Actions → General → Workflow permissions and ensure it’s not restricted to read-only (many repos/orgs default to read-only). (stackoverflow.com)

If you deploy to an external repository (external_repository:), GITHUB_TOKEN won’t work; you must use a deploy key or a personal access token instead. (github.com)

Citations:


Guard the deploy job for same-repo PRs.

pull_request runs from forks receive a read-only GITHUB_TOKEN, which peaceiris/actions-gh-pages@v4 cannot use to push to the repository. This job will fail for external contributors. Add a guard condition to prevent execution on fork PRs:

-        if: github.event_name == 'pull_request'
+        if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository

If fork previews are required, use pull_request_target in a separate, trusted workflow instead.

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

In @.github/workflows/l5-swagger-generate.yml around lines 149 - 183, The
pages-preview job runs on pull_request events but will fail for forked PRs
because the read-only GITHUB_TOKEN prevents peaceiris/actions-gh-pages@v4 from
pushing; update the job's if condition (job name: pages-preview) to only run for
same-repo PRs by adding a fork check, e.g. change the existing if:
github.event_name == 'pull_request' to include
github.event.pull_request.head.repo.fork == false (or equivalent comparison such
as github.event.pull_request.head.repo.full_name == github.repository) so the
peaceiris/actions-gh-pages@v4 step only executes for non-fork PRs.

Comment on lines 55 to 396
$scopes = [
[
'name' => sprintf(SummitScopes::ReadSummitData, $current_realm),
'name' => SummitScopes::ReadSummitData,
'short_description' => 'Get Summit Data',
'description' => 'Grants read only access for Summits Data',
],
[
'name' => sprintf(SummitScopes::ReadAllSummitData, $current_realm),
'name' => SummitScopes::ReadAllSummitData,
'short_description' => 'Get All Summits Data',
'description' => 'Grants read only access for All Summits Data',
],
[
'name' => sprintf(SummitScopes::MeRead, $current_realm),
'name' => SummitScopes::MeRead,
'short_description' => 'Get own summit member data',
'description' => 'Grants read only access for our own summit member data',
],
[
'name' => sprintf(SummitScopes::AddMyFavorites, $current_realm),
'name' => SummitScopes::AddMyFavorites,
'short_description' => 'Allows to add Summit events as favorite',
'description' => 'Allows to add Summit events as favorite',
],
[
'name' => sprintf(SummitScopes::DeleteMyFavorites, $current_realm),
'name' => SummitScopes::DeleteMyFavorites,
'short_description' => 'Allows to remove Summit events as favorite',
'description' => 'Allows to remove Summit events as favorite',
],
// enter/leave event
[
'name' => sprintf(SummitScopes::EnterEvent, $current_realm),
'name' => SummitScopes::EnterEvent,
'short_description' => '',
'description' => '',
],
[
'name' => sprintf(SummitScopes::LeaveEvent, $current_realm),
'name' => SummitScopes::LeaveEvent,
'short_description' => '',
'description' => '',
],
[
'name' => sprintf(SummitScopes::WriteMetrics, $current_realm),
'name' => SummitScopes::WriteMetrics,
'short_description' => '',
'description' => '',
],
[
'name' => sprintf(SummitScopes::ReadMetrics, $current_realm),
'name' => SummitScopes::ReadMetrics,
'short_description' => '',
'description' => '',
],
[
'name' => sprintf(SummitScopes::AddMyRSVP, $current_realm),
'name' => SummitScopes::AddMyRSVP,
'short_description' => 'Allows to add Summit events as RSVP',
'description' => 'Allows to add Summit events as RSVP',
],
[
'name' => sprintf(SummitScopes::DeleteMyRSVP, $current_realm),
'name' => SummitScopes::DeleteMyRSVP,
'short_description' => 'Allows to remove Summit events from RSVP',
'description' => 'Allows to remove Summit events from RSVP',
],
[
'name' => sprintf(SummitScopes::AddMySchedule, $current_realm),
'name' => SummitScopes::AddMySchedule,
'short_description' => 'Allows to add Summit events to my schedule',
'description' => 'Allows to add Summit events to my schedule',
],
[
'name' => sprintf(SummitScopes::DeleteMySchedule, $current_realm),
'name' => SummitScopes::DeleteMySchedule,
'short_description' => 'Allows to remove Summit events from my schedule',
'description' => 'Allows to remove Summit events from my schedule',
],
[
'name' => sprintf(SummitScopes::AddMyScheduleShareable, $current_realm),
'name' => SummitScopes::AddMyScheduleShareable,
'short_description' => 'Allows create a shareable link from my schedule',
'description' => 'Allows create a shareable link from my schedule',
],
[
'name' => sprintf(SummitScopes::DeleteMyScheduleShareable, $current_realm),
'name' => SummitScopes::DeleteMyScheduleShareable,
'short_description' => 'Allows to delete shareable links from my schedule',
'description' => 'Allows to delete shareable links from my schedule',
],
[
'name' => sprintf(SummitScopes::AddMyEventFeedback, $current_realm),
'name' => SummitScopes::AddMyEventFeedback,
'short_description' => 'Allows to create event feedback',
'description' => 'Allows to create event feedback',
],
[
'name' => sprintf(SummitScopes::DeleteMyEventFeedback, $current_realm),
'name' => SummitScopes::DeleteMyEventFeedback,
'short_description' => 'Allows to delete event feedback',
'description' => 'Allows to delete event feedback',
],
[
'name' => sprintf(SummitScopes::SendMyScheduleMail, $current_realm),
'name' => SummitScopes::SendMyScheduleMail,
'short_description' => 'Allows to send my schedule share email',
'description' => 'Allows to send my schedule share email',
],
[
'name' => sprintf(SummitScopes::WriteSummitData, $current_realm),
'name' => SummitScopes::WriteSummitData,
'short_description' => 'Write Summit Data',
'description' => 'Grants write access for Summits Data',
],
[
'name' => sprintf(SummitScopes::WriteRegistrationData, $current_realm),
'name' => SummitScopes::WriteRegistrationData,
'short_description' => 'Write Registration Data',
'description' => 'Grants write access for Registration Data',
],
[
'name' => sprintf(SummitScopes::WriteEventData, $current_realm),
'name' => SummitScopes::WriteEventData,
'short_description' => 'Write Summit Events',
'description' => 'Grants write access for Summits Events',
],
[
'name' => sprintf(SummitScopes::WritePresentationData, $current_realm),
'name' => SummitScopes::WritePresentationData,
'short_description' => 'Write Summit Presentations',
'description' => 'Grants write access for Summits Presentations',
],
array(
'name' => sprintf('%s/summits/delete-event', $current_realm),
[
'name' => SummitScopes::DeleteEventData,
'short_description' => 'Delete Summit Events',
'description' => 'Grants delete access for Summits Events',
),
array(
'name' => sprintf('%s/summits/publish-event', $current_realm),
],
[
'name' => SummitScopes::PublishEventData,
'short_description' => 'Publish/UnPublish Summit Events',
'description' => 'Grants Publish/UnPublish access for Summits Events',
),
],
[
'name' => sprintf('%s/summits/read-external-orders', $current_realm),
'name' => SummitScopes::ReadSummitsConfirmExternalOrders,
'short_description' => 'Allow to read External Orders',
'description' => 'Allow to read External Orders',
],
[
'name' => sprintf('%s/summits/confirm-external-orders', $current_realm),
'name' => SummitScopes::WriteSummitsConfirmExternalOrders,
'short_description' => 'Allow to confirm External Orders',
'description' => 'Allow to confirm External Orders',
],
[
'name' => sprintf('%s/summits/write-videos', $current_realm),
'name' => SummitScopes::WriteVideoData,
'short_description' => 'Allow to write presentation videos',
'description' => 'Allow to write presentation videos',
],
[
'name' => sprintf('%s/summits/read-notifications', $current_realm),
'name' => SummitScopes::ReadNotifications,
'short_description' => 'Allow to read summit notifications',
'description' => 'Allow to read summit notifications',
],
[
'name' => sprintf(SummitScopes::WriteSpeakersData, $current_realm),
'name' => SummitScopes::WriteSpeakersData,
'short_description' => 'Write Speakers Data',
'description' => 'Grants write access for Speakers Data',
],
[
'name' => sprintf(SummitScopes::ReadSpeakersData, $current_realm),
'name' => SummitScopes::ReadSpeakersData,
'short_description' => 'Read Speakers Data',
'description' => 'Grants read access for Speakers Data',
],
[
'name' => sprintf(SummitScopes::WriteMySpeakersData, $current_realm),
'name' => SummitScopes::WriteMySpeakersData,
'short_description' => 'Write My Speakers Profile Data',
'description' => 'Grants write access for My Speaker Profile Data',
],
[
'name' => sprintf(SummitScopes::ReadMySpeakersData, $current_realm),
'name' => SummitScopes::ReadMySpeakersData,
'short_description' => 'Read My Speakers Profile Data',
'description' => 'Grants read access for My Speaker Profile Data',
],
[
'name' => sprintf(SummitScopes::WriteAttendeesData, $current_realm),
'name' => SummitScopes::WriteAttendeesData,
'short_description' => 'Write Attendees Data',
'description' => 'Grants write access for Attendees Data',
],
[
'name' => sprintf(SummitScopes::WritePromoCodeData, $current_realm),
'name' => SummitScopes::WritePromoCodeData,
'short_description' => 'Write Promo Codes Data',
'description' => 'Grants write access for Promo Codes Data',
],
[
'name' => sprintf(SummitScopes::WriteLocationsData, $current_realm),
'name' => SummitScopes::WriteLocationsData,
'short_description' => 'Write Summit Locations Data',
'description' => 'Grants write access for Summit Locations Data',
],
[
'name' => sprintf(SummitScopes::WriteLocationBannersData, $current_realm),
'name' => SummitScopes::WriteLocationBannersData,
'short_description' => 'Write Summit Location Banners Data',
'description' => 'Grants write access for Summit Location Banners Data',
],
[
'name' => sprintf(SummitScopes::WriteTrackTagGroupsData, $current_realm),
'name' => SummitScopes::WriteTrackTagGroupsData,
'short_description' => 'Write Summit Track Tag Groups Data',
'description' => 'Grants write access for Summit Track Tag Groups Data',
],
[
'name' => sprintf(SummitScopes::WriteTrackQuestionTemplateData, $current_realm),
'name' => SummitScopes::WriteTrackQuestionTemplateData,
'short_description' => 'Write Summit Track Question Template Data',
'description' => 'Grants write access for Summit Track Question Template Data',
],
[
'name' => sprintf(SummitScopes::WritePresentationVideosData, $current_realm),
'name' => SummitScopes::WritePresentationVideosData,
'short_description' => 'Write Summit Presentation Videos Data',
'description' => 'Grants write access for Summit Presentation Videos Data',
],
[
'name' => sprintf(SummitScopes::WritePresentationSlidesData, $current_realm),
'name' => SummitScopes::WritePresentationSlidesData,
'short_description' => 'Write Summit Presentation Slides Data',
'description' => 'Grants write access for Summit Presentation Slides Data',
],
[
'name' => sprintf(SummitScopes::WritePresentationLinksData, $current_realm),
'name' => SummitScopes::WritePresentationLinksData,
'short_description' => 'Write Summit Presentation Links Data',
'description' => 'Grants write access for Summit Presentation Links Data',
],
[
'name' => sprintf(SummitScopes::WritePresentationMaterialsData, $current_realm),
'name' => SummitScopes::WritePresentationMaterialsData,
'short_description' => 'Write Summit Presentation Materials Data',
'description' => 'Grants write access for Summit Materials Links Data',
],
[
'name' => sprintf(SummitScopes::ReadMyBookableRoomsReservationData, $current_realm),
'name' => SummitScopes::ReadMyBookableRoomsReservationData,
'short_description' => 'Read my bookable rooms reservations',
'description' => 'Read my bookable rooms reservations',
],
[
'name' => sprintf(SummitScopes::WriteMyBookableRoomsReservationData, $current_realm),
'name' => SummitScopes::WriteMyBookableRoomsReservationData,
'short_description' => 'Write my bookable rooms reservations',
'description' => 'Write my bookable rooms reservations',
],
[
'name' => sprintf(SummitScopes::CreateOfflineRegistrationOrders, $current_realm),
'name' => SummitScopes::CreateOfflineRegistrationOrders,
'short_description' => 'Create summit offline registration orders',
'description' => 'Create summit offline registration orders',
],
[
'name' => sprintf(SummitScopes::CreateRegistrationOrders, $current_realm),
'name' => SummitScopes::CreateRegistrationOrders,
'short_description' => 'Create summit registration orders',
'description' => 'Create summit registration orders',
],
[
'name' => sprintf(SummitScopes::DeleteRegistrationOrders, $current_realm),
'name' => SummitScopes::DeleteRegistrationOrders,
'short_description' => 'Delete summit registration orders',
'description' => 'Delete summit registration orders',
],
[
'name' => sprintf(SummitScopes::DeleteMyRegistrationOrders, $current_realm),
'name' => SummitScopes::DeleteMyRegistrationOrders,
'short_description' => 'Delete my summit registration orders',
'description' => 'Delete my summit registration orders',
],
[
'name' => sprintf(SummitScopes::ReadMyRegistrationOrders, $current_realm),
'name' => SummitScopes::ReadMyRegistrationOrders,
'short_description' => 'Read my summit registration orders',
'description' => 'Read my summit registration orders',
],
[
'name' => sprintf(SummitScopes::ReadRegistrationOrders, $current_realm),
'name' => SummitScopes::ReadRegistrationOrders,
'short_description' => 'Read summit registration orders',
'description' => 'Read summit registration orders',
],
[
'name' => sprintf(SummitScopes::UpdateRegistrationOrders, $current_realm),
'name' => SummitScopes::UpdateRegistrationOrders,
'short_description' => 'Update summit registration orders',
'description' => 'Update summit registration orders',
],
[
'name' => sprintf(SummitScopes::UpdateMyRegistrationOrders, $current_realm),
'name' => SummitScopes::UpdateMyRegistrationOrders,
'short_description' => 'Update my summit registration orders',
'description' => 'Update my summit registration orders',
],
[
'name' => sprintf(SummitScopes::UpdateRegistrationOrdersBadges, $current_realm),
'name' => SummitScopes::UpdateRegistrationOrdersBadges,
'short_description' => 'Update summit registration orders badges',
'description' => 'Update summit registration orders badges',
],
[
'name' => sprintf(SummitScopes::PrintRegistrationOrdersBadges, $current_realm),
'name' => SummitScopes::PrintRegistrationOrdersBadges,
'short_description' => 'print summit registration orders badges',
'description' => 'print summit registration orders badges',
],
[
'name' => sprintf(SummitScopes::ReadMyBadgeScan, $current_realm),
'name' => SummitScopes::ReadMyBadgeScan,
'short_description' => 'read my badge scans',
'description' => 'read my badge scans',
],
[
'name' => sprintf(SummitScopes::ReadBadgeScanValidate, $current_realm),
'name' => SummitScopes::ReadBadgeScanValidate,
'short_description' => 'validate badge scan',
'description' => 'validate badge scan',
],
[
'name' => sprintf(SummitScopes::WriteMyBadgeScan, $current_realm),
'name' => SummitScopes::WriteMyBadgeScan,
'short_description' => 'allow to share my badge with sponsors',
'description' => 'allow to share my badge with sponsors',
],
[
'name' => sprintf(SummitScopes::ReadBadgeScan, $current_realm),
'name' => SummitScopes::ReadBadgeScan,
'short_description' => 'read badge scans',
'description' => 'read badge scans',
],
[
'name' => sprintf(SummitScopes::WriteBadgeScan, $current_realm),
'name' => SummitScopes::WriteBadgeScan,
'short_description' => 'write badge scans',
'description' => 'write badge scans',
],
[
'name' => sprintf(SummitScopes::ReadPaymentProfiles, $current_realm),
'name' => SummitScopes::ReadPaymentProfiles,
'short_description' => 'read summit payment profiles',
'description' => 'read summit payment profiles',
],
[
'name' => sprintf(SummitScopes::WritePaymentProfiles, $current_realm),
'name' => SummitScopes::WritePaymentProfiles,
'short_description' => 'write summit payment profiles',
'description' => 'write summit payment profiles',
],
[
'name' => sprintf(SummitScopes::WriteRegistrationInvitations, $current_realm),
'name' => SummitScopes::WriteRegistrationInvitations,
'short_description' => 'write summit registration invitation',
'description' => 'write summit registration invitation',
],
[
'name' => sprintf(SummitScopes::ReadRegistrationInvitations, $current_realm),
'name' => SummitScopes::ReadRegistrationInvitations,
'short_description' => 'read summit registration invitation',
'description' => 'read summit registration invitation',
],
[
'name' => sprintf(SummitScopes::ReadMyRegistrationInvitations, $current_realm),
'name' => SummitScopes::ReadMyRegistrationInvitations,
'short_description' => 'read my summit registration invitation',
'description' => 'read my summit registration invitation',
],
[
'name' => sprintf(SummitScopes::DoVirtualCheckIn, $current_realm),
'name' => SummitScopes::DoVirtualCheckIn,
'short_description' => 'Allow virtual Check In',
'description' => 'Allow virtual Check In',
],
[
'name' => sprintf(SummitScopes::Allow2PresentationAttendeeVote, $current_realm),
'name' => SummitScopes::Allow2PresentationAttendeeVote,
'short_description' => 'Allow Attendee Vote on Presentation',
'description' => 'Allow Attendee Vote on Presentation',
],
[
'name' => sprintf(SummitScopes::ReadAttendeeNotesData, $current_realm),
'name' => SummitScopes::ReadAttendeeNotesData,
'short_description' => 'Read Attendee Notes Data',
'description' => 'Grants read access for Attendee Notes Data',
],
[
'name' => sprintf(SummitScopes::WriteAttendeeNotesData, $current_realm),
'name' => SummitScopes::WriteAttendeeNotesData,
'short_description' => 'Write Attendee Notes Data',
'description' => 'Grants write access for Attendee Notes Data',
]
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Sync seedSummitScopes() with the new constants.

This list still omits several constants added in app/Security/SummitScopes.php: WriteSubmissionInvitations, ReadSubmissionInvitations, ReadBookableRoomsData, BookableRoomsReservation, WriteBookableRoomsData, WriteNotifications, WriteEventTypeData, WriteTracksData, WriteTrackGroupsData, WriteRSVPTemplateData, WriteSummitSpeakerAssistanceData, and WriteTicketTypeData. Fresh databases won't have ApiScope rows for them, so those permissions cannot be granted.

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

In `@database/seeders/ApiScopesSeeder.php` around lines 55 - 396, The
seedSummitScopes() seeder is missing several new SummitScopes constants so fresh
DBs won't get corresponding ApiScope rows; update the $scopes array in
ApiScopesSeeder::seedSummitScopes() to include entries for
SummitScopes::WriteSubmissionInvitations,
SummitScopes::ReadSubmissionInvitations, SummitScopes::ReadBookableRoomsData,
SummitScopes::BookableRoomsReservation, SummitScopes::WriteBookableRoomsData,
SummitScopes::WriteNotifications, SummitScopes::WriteEventTypeData,
SummitScopes::WriteTracksData, SummitScopes::WriteTrackGroupsData,
SummitScopes::WriteRSVPTemplateData,
SummitScopes::WriteSummitSpeakerAssistanceData, and
SummitScopes::WriteTicketTypeData (use consistent short_description/description
patterns used by other entries and reference SummitScopes.php for exact constant
names).

Comment on lines 510 to 523
private function seedOrganizationScopes(){
$current_realm = Config::get('app.scope_base_realm');

$api = EntityManager::getRepository(\App\Models\ResourceServer\Api::class)->findOneBy(['name' => 'companies']);

$scopes = [
[
'name' => sprintf(OrganizationScopes::ReadOrganizationData, $current_realm),
'name' => OrganizationScopes::ReadOrganizationData,
'short_description' => 'Get Organizations Data',
'description' => 'Grants read only access for Organization Data',
],
[
'name' => sprintf(OrganizationScopes::WriteOrganizationData, $current_realm),
'name' => OrganizationScopes::WriteOrganizationData,
'short_description' => 'Write Companies Data',
'description' => 'Grants write access for Organization Data',
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Attach organization scopes to the organizations API.

Line 512 still resolves ['name' => 'companies'] inside seedOrganizationScopes(), so both organization scopes are persisted under the wrong resource server.

🛠️ Suggested fix
-        $api           = EntityManager::getRepository(\App\Models\ResourceServer\Api::class)->findOneBy(['name' => 'companies']);
+        $api           = EntityManager::getRepository(\App\Models\ResourceServer\Api::class)->findOneBy(['name' => 'organizations']);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@database/seeders/ApiScopesSeeder.php` around lines 510 - 523, The
organization scopes are being attached to the wrong API because
seedOrganizationScopes() resolves the API with ['name' => 'companies']; update
the lookup so $api =
EntityManager::getRepository(\App\Models\ResourceServer\Api::class)->findOneBy(['name'
=> 'organizations']) (or the exact resource-server name used for organizations)
so OrganizationScopes::ReadOrganizationData and
OrganizationScopes::WriteOrganizationData are persisted against the correct API;
verify subsequent use of $api in this method still assigns scopes to that $api.

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.

2 participants