@@ -9,6 +9,8 @@ use common::{
99 components:: {
1010 CanonicalizedComponentFunctionPath ,
1111 ComponentId ,
12+ ComponentPath ,
13+ ExportPath ,
1214 } ,
1315 http:: ResolvedHost ,
1416 pause:: PauseClient ,
@@ -96,7 +98,25 @@ pub trait ApplicationApi: Send + Sync {
9698 auth_token : AuthenticationToken ,
9799 ) -> anyhow:: Result < Identity > ;
98100
101+ /// Execute a public query on the root app. This method is used by the sync
102+ /// worker and HTTP API for the majority of traffic as the main entry point
103+ /// for queries.
99104 async fn execute_public_query (
105+ & self ,
106+ host : & ResolvedHost ,
107+ request_id : RequestId ,
108+ identity : Identity ,
109+ path : ExportPath ,
110+ args : Vec < JsonValue > ,
111+ caller : FunctionCaller ,
112+ ts : ExecuteQueryTimestamp ,
113+ journal : Option < SerializedQueryJournal > ,
114+ ) -> anyhow:: Result < RedactedQueryReturn > ;
115+
116+ /// Execute an admin query for a particular component. This method is used
117+ /// by the sync worker for running queries for the dashboard and only works
118+ /// for admin or system identity.
119+ async fn execute_admin_query (
100120 & self ,
101121 host : & ResolvedHost ,
102122 request_id : RequestId ,
@@ -108,44 +128,54 @@ pub trait ApplicationApi: Send + Sync {
108128 journal : Option < SerializedQueryJournal > ,
109129 ) -> anyhow:: Result < RedactedQueryReturn > ;
110130
131+ /// Execute a public mutation on the root app.
111132 async fn execute_public_mutation (
112133 & self ,
113134 host : & ResolvedHost ,
114135 request_id : RequestId ,
115136 identity : Identity ,
116- path : CanonicalizedComponentFunctionPath ,
137+ path : ExportPath ,
117138 args : Vec < JsonValue > ,
118139 caller : FunctionCaller ,
119140 // Identifier used to make this mutation idempotent.
120141 mutation_identifier : Option < SessionRequestIdentifier > ,
121142 ) -> anyhow:: Result < Result < RedactedMutationReturn , RedactedMutationError > > ;
122143
123- async fn execute_public_action (
144+ /// Execute an admin mutation for a particular component for the dashboard.
145+ async fn execute_admin_mutation (
124146 & self ,
125147 host : & ResolvedHost ,
126148 request_id : RequestId ,
127149 identity : Identity ,
128150 path : CanonicalizedComponentFunctionPath ,
129151 args : Vec < JsonValue > ,
130152 caller : FunctionCaller ,
131- ) -> anyhow:: Result < Result < RedactedActionReturn , RedactedActionError > > ;
153+ mutation_identifier : Option < SessionRequestIdentifier > ,
154+ ) -> anyhow:: Result < Result < RedactedMutationReturn , RedactedMutationError > > ;
132155
133- async fn execute_any_function (
156+ /// Execute a public action on the root app.
157+ async fn execute_public_action (
134158 & self ,
135159 host : & ResolvedHost ,
136160 request_id : RequestId ,
137161 identity : Identity ,
138- path : CanonicalizedComponentFunctionPath ,
162+ path : ExportPath ,
139163 args : Vec < JsonValue > ,
140164 caller : FunctionCaller ,
141- ) -> anyhow:: Result < Result < FunctionReturn , FunctionError > > ;
165+ ) -> anyhow:: Result < Result < RedactedActionReturn , RedactedActionError > > ;
142166
143- async fn latest_timestamp (
167+ /// Execute an admin action for a particular component for the dashboard.
168+ async fn execute_admin_action (
144169 & self ,
145170 host : & ResolvedHost ,
146171 request_id : RequestId ,
147- ) -> anyhow:: Result < RepeatableTimestamp > ;
172+ identity : Identity ,
173+ path : CanonicalizedComponentFunctionPath ,
174+ args : Vec < JsonValue > ,
175+ caller : FunctionCaller ,
176+ ) -> anyhow:: Result < Result < RedactedActionReturn , RedactedActionError > > ;
148177
178+ /// Execute an HTTP action on the root app.
149179 async fn execute_http_action (
150180 & self ,
151181 host : & ResolvedHost ,
@@ -156,6 +186,25 @@ pub trait ApplicationApi: Send + Sync {
156186 response_streamer : HttpActionResponseStreamer ,
157187 ) -> anyhow:: Result < ( ) > ;
158188
189+ /// For the dashboard (and the CLI), run any function in any component
190+ /// without knowing its type. This function requires admin identity for
191+ /// calling functions outside the root component.
192+ async fn execute_any_function (
193+ & self ,
194+ host : & ResolvedHost ,
195+ request_id : RequestId ,
196+ identity : Identity ,
197+ path : CanonicalizedComponentFunctionPath ,
198+ args : Vec < JsonValue > ,
199+ caller : FunctionCaller ,
200+ ) -> anyhow:: Result < Result < FunctionReturn , FunctionError > > ;
201+
202+ async fn latest_timestamp (
203+ & self ,
204+ host : & ResolvedHost ,
205+ request_id : RequestId ,
206+ ) -> anyhow:: Result < RepeatableTimestamp > ;
207+
159208 async fn check_store_file_authorization (
160209 & self ,
161210 host : & ResolvedHost ,
@@ -226,7 +275,7 @@ impl<RT: Runtime> ApplicationApi for Application<RT> {
226275 _host : & ResolvedHost ,
227276 request_id : RequestId ,
228277 identity : Identity ,
229- path : CanonicalizedComponentFunctionPath ,
278+ path : ExportPath ,
230279 args : Vec < JsonValue > ,
231280 caller : FunctionCaller ,
232281 ts : ExecuteQueryTimestamp ,
@@ -236,7 +285,34 @@ impl<RT: Runtime> ApplicationApi for Application<RT> {
236285 caller. allowed_visibility( ) == AllowedVisibility :: PublicOnly ,
237286 "This method should not be used by internal callers."
238287 ) ;
288+ let ts = match ts {
289+ ExecuteQueryTimestamp :: Latest => * self . now_ts_for_reads ( ) ,
290+ ExecuteQueryTimestamp :: At ( ts) => ts,
291+ } ;
292+ // Public queries always start with the root component.
293+ let path = CanonicalizedComponentFunctionPath {
294+ component : ComponentPath :: root ( ) ,
295+ udf_path : path. into ( ) ,
296+ } ;
297+ self . read_only_udf_at_ts ( request_id, path, args, identity, ts, journal, caller)
298+ . await
299+ }
239300
301+ async fn execute_admin_query (
302+ & self ,
303+ _host : & ResolvedHost ,
304+ request_id : RequestId ,
305+ identity : Identity ,
306+ path : CanonicalizedComponentFunctionPath ,
307+ args : Vec < JsonValue > ,
308+ caller : FunctionCaller ,
309+ ts : ExecuteQueryTimestamp ,
310+ journal : Option < SerializedQueryJournal > ,
311+ ) -> anyhow:: Result < RedactedQueryReturn > {
312+ anyhow:: ensure!(
313+ path. component. is_root( ) || identity. is_admin( ) || identity. is_system( ) ,
314+ "Only admin or system users can call functions on non-root components directly"
315+ ) ;
240316 let ts = match ts {
241317 ExecuteQueryTimestamp :: Latest => * self . now_ts_for_reads ( ) ,
242318 ExecuteQueryTimestamp :: At ( ts) => ts,
@@ -250,7 +326,7 @@ impl<RT: Runtime> ApplicationApi for Application<RT> {
250326 _host : & ResolvedHost ,
251327 request_id : RequestId ,
252328 identity : Identity ,
253- path : CanonicalizedComponentFunctionPath ,
329+ path : ExportPath ,
254330 args : Vec < JsonValue > ,
255331 caller : FunctionCaller ,
256332 // Identifier used to make this mutation idempotent.
@@ -260,7 +336,36 @@ impl<RT: Runtime> ApplicationApi for Application<RT> {
260336 caller. allowed_visibility( ) == AllowedVisibility :: PublicOnly ,
261337 "This method should not be used by internal callers."
262338 ) ;
339+ let path = CanonicalizedComponentFunctionPath {
340+ component : ComponentPath :: root ( ) ,
341+ udf_path : path. into ( ) ,
342+ } ;
343+ self . mutation_udf (
344+ request_id,
345+ path,
346+ args,
347+ identity,
348+ mutation_identifier,
349+ caller,
350+ PauseClient :: new ( ) ,
351+ )
352+ . await
353+ }
263354
355+ async fn execute_admin_mutation (
356+ & self ,
357+ _host : & ResolvedHost ,
358+ request_id : RequestId ,
359+ identity : Identity ,
360+ path : CanonicalizedComponentFunctionPath ,
361+ args : Vec < JsonValue > ,
362+ caller : FunctionCaller ,
363+ mutation_identifier : Option < SessionRequestIdentifier > ,
364+ ) -> anyhow:: Result < Result < RedactedMutationReturn , RedactedMutationError > > {
365+ anyhow:: ensure!(
366+ path. component. is_root( ) || identity. is_admin( ) || identity. is_system( ) ,
367+ "Only admin or system users can call functions on non-root components directly"
368+ ) ;
264369 self . mutation_udf (
265370 request_id,
266371 path,
@@ -278,15 +383,35 @@ impl<RT: Runtime> ApplicationApi for Application<RT> {
278383 _host : & ResolvedHost ,
279384 request_id : RequestId ,
280385 identity : Identity ,
281- path : CanonicalizedComponentFunctionPath ,
386+ path : ExportPath ,
282387 args : Vec < JsonValue > ,
283388 caller : FunctionCaller ,
284389 ) -> anyhow:: Result < Result < RedactedActionReturn , RedactedActionError > > {
285390 anyhow:: ensure!(
286391 caller. allowed_visibility( ) == AllowedVisibility :: PublicOnly ,
287392 "This method should not be used by internal callers."
288393 ) ;
394+ let path = CanonicalizedComponentFunctionPath {
395+ component : ComponentPath :: root ( ) ,
396+ udf_path : path. into ( ) ,
397+ } ;
398+ self . action_udf ( request_id, path, args, identity, caller)
399+ . await
400+ }
289401
402+ async fn execute_admin_action (
403+ & self ,
404+ _host : & ResolvedHost ,
405+ request_id : RequestId ,
406+ identity : Identity ,
407+ path : CanonicalizedComponentFunctionPath ,
408+ args : Vec < JsonValue > ,
409+ caller : FunctionCaller ,
410+ ) -> anyhow:: Result < Result < RedactedActionReturn , RedactedActionError > > {
411+ anyhow:: ensure!(
412+ path. component. is_root( ) || identity. is_admin( ) || identity. is_system( ) ,
413+ "Only admin or system users can call functions on non-root components directly"
414+ ) ;
290415 self . action_udf ( request_id, path, args, identity, caller)
291416 . await
292417 }
@@ -300,6 +425,10 @@ impl<RT: Runtime> ApplicationApi for Application<RT> {
300425 args : Vec < JsonValue > ,
301426 caller : FunctionCaller ,
302427 ) -> anyhow:: Result < Result < FunctionReturn , FunctionError > > {
428+ anyhow:: ensure!(
429+ path. component. is_root( ) || identity. is_admin( ) || identity. is_system( ) ,
430+ "Only admin or system users can call functions on non-root components directly"
431+ ) ;
303432 self . any_udf ( request_id, path, args, identity, caller) . await
304433 }
305434
0 commit comments