3333
3434class ApplicationsController extends Controller
3535{
36+ private function exposeFileStorageContentIfAllowed (LocalFileVolume |LocalPersistentVolume $ storage ): LocalFileVolume |LocalPersistentVolume
37+ {
38+ if (request ()->attributes ->get ('can_read_sensitive ' , false ) === true ) {
39+ $ storage ->makeVisible (['content ' ]);
40+ }
41+
42+ return $ storage ;
43+ }
44+
3645 private function removeSensitiveData ($ application )
3746 {
3847 $ application ->makeHidden ([
@@ -41,8 +50,8 @@ private function removeSensitiveData($application)
4150 'resourceable_id ' ,
4251 'resourceable_type ' ,
4352 ]);
44- if (request ()->attributes ->get ('can_read_sensitive ' , false ) === false ) {
45- $ application ->makeHidden ([
53+ if (request ()->attributes ->get ('can_read_sensitive ' , false ) === true ) {
54+ $ application ->makeVisible ([
4655 'custom_labels ' ,
4756 'dockerfile ' ,
4857 'docker_compose ' ,
@@ -51,10 +60,14 @@ private function removeSensitiveData($application)
5160 'manual_webhook_secret_gitea ' ,
5261 'manual_webhook_secret_github ' ,
5362 'manual_webhook_secret_gitlab ' ,
54- 'private_key_id ' ,
63+ 'http_basic_auth_password ' ,
5564 'value ' ,
5665 'real_value ' ,
57- 'http_basic_auth_password ' ,
66+ ]);
67+ $ this ->exposeNestedServerSecrets ($ application );
68+ } else {
69+ $ application ->makeHidden ([
70+ 'private_key_id ' ,
5871 ]);
5972 }
6073
@@ -65,6 +78,34 @@ private function removeSensitiveData($application)
6578 return serializeApiResponse ($ application );
6679 }
6780
81+ /**
82+ * Expose sensitive fields on eager-loaded nested Server + ServerSetting
83+ * relations for callers with the `read:sensitive` or `root` token ability.
84+ * Models hide these by default via $hidden; this re-exposes them per-request.
85+ */
86+ private function exposeNestedServerSecrets ($ model ): void
87+ {
88+ $ server = $ model ->destination ?->server ?? null ;
89+ if (! $ server ) {
90+ return ;
91+ }
92+ $ server ->makeVisible ([
93+ 'logdrain_axiom_api_key ' ,
94+ 'logdrain_newrelic_license_key ' ,
95+ ]);
96+ $ settings = $ server ->settings ?? null ;
97+ if ($ settings ) {
98+ $ settings ->makeVisible ([
99+ 'sentinel_token ' ,
100+ 'sentinel_custom_url ' ,
101+ 'logdrain_newrelic_license_key ' ,
102+ 'logdrain_axiom_api_key ' ,
103+ 'logdrain_custom_config ' ,
104+ 'logdrain_custom_config_parser ' ,
105+ ]);
106+ }
107+ }
108+
68109 #[OA \Get(
69110 summary: 'List ' ,
70111 description: 'List all applications. ' ,
@@ -117,8 +158,12 @@ public function applications(Request $request)
117158 }
118159
119160 $ tagName = $ request ->query ('tag ' );
161+ $ applicationRelations = $ request ->attributes ->get ('can_read_sensitive ' , false ) === true
162+ ? ['destination.server.settings ' ]
163+ : [];
120164
121165 $ applications = Application::ownedByCurrentTeamAPI ($ teamId )
166+ ->with ($ applicationRelations )
122167 ->when ($ tagName , function ($ query , $ tagName ) {
123168 $ query ->whereHas ('tags ' , function ($ query ) use ($ tagName ) {
124169 $ query ->where ('name ' , $ tagName );
@@ -2003,7 +2048,7 @@ public function application_by_uuid(Request $request)
20032048 if (! $ uuid ) {
20042049 return response ()->json (['message ' => 'UUID is required. ' ], 400 );
20052050 }
2006- $ application = Application::ownedByCurrentTeamAPI ($ teamId )->where ('uuid ' , $ request ->uuid )->first ();
2051+ $ application = Application::ownedByCurrentTeamAPI ($ teamId )->where ('uuid ' , $ request ->route ( ' uuid ' ) )->first ();
20072052 if (! $ application ) {
20082053 return response ()->json (['message ' => 'Application not found. ' ], 404 );
20092054 }
@@ -2091,7 +2136,7 @@ public function logs_by_uuid(Request $request)
20912136 if (! $ uuid ) {
20922137 return response ()->json (['message ' => 'UUID is required. ' ], 400 );
20932138 }
2094- $ application = Application::ownedByCurrentTeamAPI ($ teamId )->where ('uuid ' , $ request ->uuid )->first ();
2139+ $ application = Application::ownedByCurrentTeamAPI ($ teamId )->where ('uuid ' , $ request ->route ( ' uuid ' ) )->first ();
20952140 if (! $ application ) {
20962141 return response ()->json (['message ' => 'Application not found. ' ], 404 );
20972142 }
@@ -2185,7 +2230,7 @@ public function delete_by_uuid(Request $request)
21852230 if (! $ request ->uuid ) {
21862231 return response ()->json (['message ' => 'UUID is required. ' ], 404 );
21872232 }
2188- $ application = Application::ownedByCurrentTeamAPI ($ teamId )->where ('uuid ' , $ request ->uuid )->first ();
2233+ $ application = Application::ownedByCurrentTeamAPI ($ teamId )->where ('uuid ' , $ request ->route ( ' uuid ' ) )->first ();
21892234
21902235 if (! $ application ) {
21912236 return response ()->json ([
@@ -2398,7 +2443,7 @@ public function update_by_uuid(Request $request)
23982443 return $ return ;
23992444 }
24002445
2401- $ application = Application::ownedByCurrentTeamAPI ($ teamId )->where ('uuid ' , $ request ->uuid )->first ();
2446+ $ application = Application::ownedByCurrentTeamAPI ($ teamId )->where ('uuid ' , $ request ->route ( ' uuid ' ) )->first ();
24022447 if (! $ application ) {
24032448 return response ()->json ([
24042449 'message ' => 'Application not found ' ,
@@ -3998,6 +4043,7 @@ public function storages(Request $request): JsonResponse
39984043
39994044 $ persistentStorages = $ application ->persistentStorages ->sortBy ('id ' )->values ();
40004045 $ fileStorages = $ application ->fileStorages ->sortBy ('id ' )->values ();
4046+ $ fileStorages ->each (fn (LocalFileVolume $ storage ) => $ this ->exposeFileStorageContentIfAllowed ($ storage ));
40014047
40024048 return response ()->json ([
40034049 'persistent_storages ' => $ persistentStorages ,
@@ -4212,7 +4258,7 @@ public function update_storage(Request $request): JsonResponse
42124258 'mount_path ' => $ storage ->mount_path ?? null ,
42134259 ]);
42144260
4215- return response ()->json ($ storage );
4261+ return response ()->json ($ this -> exposeFileStorageContentIfAllowed ( $ storage) );
42164262 }
42174263
42184264 #[OA \Post(
@@ -4446,7 +4492,7 @@ public function create_storage(Request $request): JsonResponse
44464492 'mount_path ' => $ storage ->mount_path ,
44474493 ]);
44484494
4449- return response ()->json ($ storage , 201 );
4495+ return response ()->json ($ this -> exposeFileStorageContentIfAllowed ( $ storage) , 201 );
44504496 }
44514497
44524498 #[OA \Delete(
0 commit comments