grafana/pkg/server
Mihai Turdean b005fb3c2a
Folders: Wire the ResourcePermission API into embedded mode for default permissions (#125927)
* Folders: Set default permissions via the resource-permission API path

In embedded/monolith mode the folder API was registered with the legacy
folderPermissionsSvc (SQL + GetSignedInUser), whose default-permission step
runs inside the apiserver create hook where there is no web request context.
For root folders this failed with "user not found", so the folder was created
but its default permissions were never written.

When kubernetesAuthzResourcePermissionApis is enabled, register the folder API
with the App Platform path instead: build a loopback ResourcePermission
dynamic client (lazily, from the eventual rest config) and leave
folderPermissionsSvc unwired so the legacy folderStorage wrapper isn't
installed. Default permissions are then written as a ResourcePermission
(Editor/Viewer) which goes to unified storage and syncs to Zanzana — no legacy
SQL and no GetSignedInUser. Creator-admin continues to come from the basic
Admin role.

Also set the grafana.app/grant-permissions=default annotation on root-folder
creation in the unified store, since the legacy /api/folders path (still used
by the frontend) does not set it and the App Platform permission setter is
driven by that annotation. Nested folders are unaffected — they inherit from
the parent via the Zanzana folder hierarchy.

Regenerates the wire graph.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Folders: Fix data race and sticky-error in lazy resource-permission client

Replace sync.Once with a mutex in resourcePermissionsClient:
- The Once approach read resourcePermissionsSvc on the fast path outside
  any synchronization while the Once body wrote it, racing on concurrent
  first-time folder creates (go test -race would flag it).
- sync.Once also cached a transient failure (e.g. a cancelled request
  context in GetRestConfig) permanently, poisoning all later creates.

Branch on restConfigProvider first so the MT path (client injected, field
never mutated) reads without locking, and the monolith path always builds
under the mutex and only caches on success.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Folders: Trim verbose comments

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Add comment for agents

* Folders: Use resourcePermissionsClient in afterDelete hook

In embedded mode the ResourcePermission client is built lazily and the
field is nil until the first create, so afterDelete reading the field
directly would skip permission cleanup. Route through
resourcePermissionsClient so the lazy-build path is used.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Folders: Request default permissions for root folders in resource-permission integration test

The integration tests create root folders directly via /apis, bypassing the
folderimpl layer that requests default permissions on the legacy /api/folders
path. Default permissions are opt-in via the grant-permissions annotation, so
without it no default ResourcePermission was created and
createRootFolderWithoutDefaultPermissions failed when trying to delete one.

Set the grant-permissions=default annotation when the helper creates a root
folder, mirroring the production folder-creation flow.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Folders: Request default permissions for root test folders in dashboard API test

The dashboard integration test created its root test folder without the
grant-permissions annotation, so Editors/Viewers never received default
access via the resource-permission path and dashboard creation in the
folder was denied. Set the annotation for root folders, matching the
resource-permission integration test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Folders: set default permissions as a service identity with creator admin

When an editor (or any non-admin) created a root folder, setDefaultFolderPermissions
wrote the ResourcePermission through the loopback API server using the requester's
identity. The creator does not yet hold set-permissions on the brand-new folder, so the
ResourcePermission authorizer's parent fetch was denied and folder creation failed with
500 "create root permissions".

Setting the default permissions is a system operation triggered by folder creation, not
an action the requester performs directly. Run it under a service identity (mirroring the
dashboard path and MT, where the injected client uses a service token), and grant the
creator admin on the new folder in addition to the default basic-role permissions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Folders: add default case to identity type switch for exhaustive lint

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 12:28:00 -06:00
..
doc.go feat: add ability to launch targeted dskit modules in the grafana server CLI command (#74188) 2023-09-01 08:09:54 -04:00
health.go Operators: add liveness and readiness check to instrumentation (#118175) 2026-02-24 08:14:19 +01:00
health_test.go Operators: add liveness and readiness check to instrumentation (#118175) 2026-02-24 08:14:19 +01:00
instrumentation_service.go Operators: add liveness and readiness check to instrumentation (#118175) 2026-02-24 08:14:19 +01:00
instrumentation_service_test.go unified-storage: setup ring to shard requests (#103783) 2025-04-25 13:08:44 -04:00
memberlist.go unified-storage: Add integration tests for distributor (#105771) 2025-06-30 09:31:58 -04:00
module_registerer.go Server: Add possibility to register build-specific targets (#111988) 2025-10-06 11:50:02 +02:00
module_runner.go feat: add ability to launch targeted dskit modules in the grafana server CLI command (#74188) 2023-09-01 08:09:54 -04:00
module_server.go Unified Storage: Search client uses authlib gRPC interceptor (#125242) 2026-06-08 22:26:11 +00:00
module_server_test.go Replace check for integration tests. (#110707) 2025-09-08 15:49:49 +02:00
operator.go Operators: Cleanup shutdown mechanisms. (#125326) 2026-05-22 13:15:09 +02:00
ring.go unified-storage: fix ring and distributor racing on startup (#120480) 2026-03-16 22:04:58 +00:00
runner.go Chore: Deprecate legacy encryption package for MT apps (#124337) 2026-05-07 09:38:09 +02:00
search_server_distributor_test.go Storage: wire KVRemoteIndexStore behind index_snapshot_storage_kv toggle (#126043) 2026-06-09 14:49:06 +02:00
server.go chore : Deprecating FeatureToggles.IsEnabledGlobally (#112885) 2025-10-24 12:02:53 -04:00
server_test.go chore: Fix flaky TestServer_Run_Error (#121724) 2026-04-03 13:17:32 +03:00
service.go Add ConfigProvider and modify quota.Service to use it (#109395) 2025-08-12 09:42:10 +03:00
test_env.go Provisioning: wire quota getter so it can be dynamically update during integration tests (#118691) 2026-03-04 09:12:20 +01:00
wire.go AuthZ: Feat: BRA for ST on mode-5 (#125557) 2026-06-01 21:03:56 +02:00
wire_gen.go Folders: Wire the ResourcePermission API into embedded mode for default permissions (#125927) 2026-06-09 12:28:00 -06:00
wireexts_oss.go Unified Storage: extract KV and resource DB construction into Wire providers (#124842) 2026-05-22 11:14:03 -06:00