Skip to content

Commit 26713b5

Browse files
committed
Add wrapper for dataSourceView, added permission checks
1 parent ed3a71a commit 26713b5

File tree

33 files changed

+191
-159
lines changed

33 files changed

+191
-159
lines changed

front/lib/api/resource_wrappers.ts

Lines changed: 123 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ import type { SessionWithUser } from "@app/lib/iam/provider";
66
import { DataSourceResource } from "@app/lib/resources/data_source_resource";
77
import { SpaceResource } from "@app/lib/resources/space_resource";
88
import { apiError } from "@app/logger/withlogging";
9+
import { DataSourceViewResource } from "@app/lib/resources/data_source_view_resource";
910

1011
// This is a type that represents the resources that can be extracted from an API route
1112
type KeyToResource = {
1213
space: SpaceResource;
1314
dataSource: DataSourceResource;
15+
dataSourceView: DataSourceViewResource;
1416
};
1517

1618
type ResourceMap<U extends ResourceKey> = {
@@ -23,7 +25,12 @@ type OptionsMap<U extends ResourceKey> = {
2325

2426
type ResourceKey = keyof KeyToResource;
2527

26-
const resolvers = [withSpaceFromRoute, withDataSourceFromRoute];
28+
// Resolvers must be in reverse order : last one is applied first.
29+
const resolvers = [
30+
withDataSourceViewFromRoute,
31+
withDataSourceFromRoute,
32+
withSpaceFromRoute,
33+
];
2734

2835
type SessionOrKeyAuthType = Authenticator | SessionWithUser | null;
2936

@@ -98,13 +105,13 @@ export function withResourceFetchingFromRoute<
98105
);
99106
}
100107
);
101-
const resources = {} as ResourceMap<U>;
108+
102109
return (
103110
req: NextApiRequest,
104111
res: NextApiResponse<WithAPIErrorResponse<T>>,
105112
auth: Authenticator,
106113
sessionOrKeyAuth: A
107-
) => wrappedHandler(req, res, auth, resources, options, sessionOrKeyAuth);
114+
) => wrappedHandler(req, res, auth, {}, options, sessionOrKeyAuth);
108115
}
109116

110117
/**
@@ -147,7 +154,7 @@ function withSpaceFromRoute<T, A extends SessionOrKeyAuthType>(
147154
// possibility of `spaceId` being undefined
148155
await SpaceResource.fetchById(auth, spaceId as string);
149156

150-
if (!space || !space.canList(auth) || space.isConversations()) {
157+
if (!space || space.isConversations()) {
151158
return apiError(req, res, {
152159
status_code: 404,
153160
api_error: {
@@ -157,6 +164,22 @@ function withSpaceFromRoute<T, A extends SessionOrKeyAuthType>(
157164
});
158165
}
159166

167+
const opts = options.space;
168+
if (typeof opts === "object") {
169+
if (
170+
(opts.requireCanRead === true && !space.canRead(auth)) ||
171+
(opts.requireCanList === true && !space.canList(auth))
172+
) {
173+
return apiError(req, res, {
174+
status_code: 404,
175+
api_error: {
176+
type: "space_not_found",
177+
message: "The space you requested was not found.",
178+
},
179+
});
180+
}
181+
}
182+
160183
resources.space = space;
161184
}
162185

@@ -248,15 +271,109 @@ function withDataSourceFromRoute<T, A extends SessionOrKeyAuthType>(
248271
return apiError(req, res, {
249272
status_code: 404,
250273
api_error: {
251-
type: "space_not_found",
252-
message: "The space you requested was not found.",
274+
type: "data_source_not_found",
275+
message: "The data source you requested was not found.",
253276
},
254277
});
255278
}
256279

280+
const opts = options.dataSource;
281+
if (typeof opts === "object") {
282+
if (
283+
(opts.requireCanRead === true && !dataSource.canRead(auth)) ||
284+
(opts.requireCanList === true && !dataSource.canList(auth))
285+
) {
286+
return apiError(req, res, {
287+
status_code: 404,
288+
api_error: {
289+
type: "data_source_not_found",
290+
message: "The data source you requested was not found.",
291+
},
292+
});
293+
}
294+
}
295+
257296
resources.dataSource = dataSource;
258297
}
259298

260299
return handler(req, res, auth, resources, options, sessionOrKeyAuth);
261300
};
262301
}
302+
303+
/**
304+
* for /w/[wId]/spaces/[spaceId]/data_source_view/[dsvId]/ => check the data source exists,
305+
* that it's not in a conversation space, etc. and provide the data source resource to the handler.
306+
* also supports the legacy usage of connectors with /w/[wId]/data_source/[dsId]/
307+
*/
308+
function withDataSourceViewFromRoute<T, A extends SessionOrKeyAuthType>(
309+
handler: ResourceHandler<T, A>
310+
): ResourceHandler<T, A> {
311+
return async (
312+
req: NextApiRequest,
313+
res: NextApiResponse<WithAPIErrorResponse<T>>,
314+
auth: Authenticator,
315+
resources: Partial<ResourceMap<ResourceKey>>,
316+
options: Partial<OptionsMap<ResourceKey>>,
317+
sessionOrKeyAuth: A
318+
) => {
319+
const { dsvId } = req.query;
320+
321+
if (dsvId) {
322+
if (typeof dsvId !== "string") {
323+
return apiError(req, res, {
324+
status_code: 400,
325+
api_error: {
326+
type: "invalid_request_error",
327+
message: "Invalid path parameters.",
328+
},
329+
});
330+
}
331+
332+
const dataSourceView = await DataSourceViewResource.fetchById(
333+
auth,
334+
dsvId
335+
);
336+
337+
let { space } = resources;
338+
if (!space) {
339+
return apiError(req, res, {
340+
status_code: 400,
341+
api_error: {
342+
type: "invalid_request_error",
343+
message: "Invalid space id.",
344+
},
345+
});
346+
}
347+
348+
if (!dataSourceView || dataSourceView.space.sId !== space.sId) {
349+
return apiError(req, res, {
350+
status_code: 404,
351+
api_error: {
352+
type: "data_source_view_not_found",
353+
message: "The data source view you requested was not found.",
354+
},
355+
});
356+
}
357+
358+
const opts = options.dataSourceView;
359+
if (typeof opts === "object") {
360+
if (
361+
(opts.requireCanRead === true && !dataSourceView.canRead(auth)) ||
362+
(opts.requireCanList === true && !dataSourceView.canList(auth))
363+
) {
364+
return apiError(req, res, {
365+
status_code: 404,
366+
api_error: {
367+
type: "data_source_view_not_found",
368+
message: "The data source view you requested was not found.",
369+
},
370+
});
371+
}
372+
}
373+
374+
resources.dataSourceView = dataSourceView;
375+
}
376+
377+
return handler(req, res, auth, resources, options, sessionOrKeyAuth);
378+
};
379+
}

front/pages/api/v1/w/[wId]/spaces/[spaceId]/apps/[aId]/runs/[runId]/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,5 +145,5 @@ async function handler(
145145
}
146146

147147
export default withPublicAPIAuthentication(
148-
withResourceFetchingFromRoute(handler, { space: true })
148+
withResourceFetchingFromRoute(handler, { space: { requireCanList: true } })
149149
);

front/pages/api/v1/w/[wId]/spaces/[spaceId]/apps/[aId]/runs/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ async function handler(
506506
}
507507

508508
export default withPublicAPIAuthentication(
509-
withResourceFetchingFromRoute(handler, { space: true }),
509+
withResourceFetchingFromRoute(handler, { space: { requireCanList: true } }),
510510
{
511511
allowUserOutsideCurrentWorkspace: true,
512512
}

front/pages/api/v1/w/[wId]/spaces/[spaceId]/apps/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,5 +120,5 @@ async function handler(
120120
}
121121

122122
export default withPublicAPIAuthentication(
123-
withResourceFetchingFromRoute(handler, { space: true })
123+
withResourceFetchingFromRoute(handler, { space: { requireCanList: true } })
124124
);

front/pages/api/v1/w/[wId]/spaces/[spaceId]/data_source_views/[dsvId]/index.ts

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -152,35 +152,9 @@ async function handler(
152152
req: NextApiRequest,
153153
res: NextApiResponse<WithAPIErrorResponse<DataSourceViewsResponseType>>,
154154
auth: Authenticator,
155-
{ space }: { space: SpaceResource }
155+
{ dataSourceView }: { dataSourceView: DataSourceViewResource }
156156
): Promise<void> {
157-
const { dsvId } = req.query;
158-
if (typeof dsvId !== "string") {
159-
return apiError(req, res, {
160-
status_code: 400,
161-
api_error: {
162-
type: "invalid_request_error",
163-
message: "Invalid path parameters.",
164-
},
165-
});
166-
}
167-
168-
const dataSourceView = await DataSourceViewResource.fetchById(auth, dsvId);
169-
if (!dataSourceView || dataSourceView.space.sId !== space.sId) {
170-
return apiError(req, res, {
171-
status_code: 404,
172-
api_error: {
173-
type: "data_source_view_not_found",
174-
message: "The data source view you requested was not found.",
175-
},
176-
});
177-
}
178-
179-
if (
180-
!dataSourceView ||
181-
req.query.vId !== dataSourceView.space.sId ||
182-
!dataSourceView.canList(auth)
183-
) {
157+
if (!dataSourceView.canList(auth)) {
184158
return apiError(req, res, {
185159
status_code: 404,
186160
api_error: {
@@ -255,5 +229,7 @@ async function handler(
255229
}
256230

257231
export default withPublicAPIAuthentication(
258-
withResourceFetchingFromRoute(handler, { space: true })
232+
withResourceFetchingFromRoute(handler, {
233+
dataSourceView: { requireCanList: true },
234+
})
259235
);

front/pages/api/v1/w/[wId]/spaces/[spaceId]/data_source_views/[dsvId]/search.ts

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -152,25 +152,9 @@ async function handler(
152152
req: NextApiRequest,
153153
res: NextApiResponse<WithAPIErrorResponse<DataSourceSearchResponseType>>,
154154
auth: Authenticator,
155-
{ space }: { space: SpaceResource }
155+
{ dataSourceView }: { dataSourceView: DataSourceViewResource }
156156
): Promise<void> {
157-
const { dsvId } = req.query;
158-
if (typeof dsvId !== "string") {
159-
return apiError(req, res, {
160-
status_code: 400,
161-
api_error: {
162-
type: "invalid_request_error",
163-
message: "Invalid path parameters.",
164-
},
165-
});
166-
}
167-
168-
const dataSourceView = await DataSourceViewResource.fetchById(auth, dsvId);
169-
if (
170-
!dataSourceView ||
171-
dataSourceView.space.sId !== space.sId ||
172-
!dataSourceView.canRead(auth)
173-
) {
157+
if (!dataSourceView.canRead(auth)) {
174158
return apiError(req, res, {
175159
status_code: 404,
176160
api_error: {
@@ -243,5 +227,5 @@ async function handler(
243227
}
244228

245229
export default withPublicAPIAuthentication(
246-
withResourceFetchingFromRoute(handler, { space: true })
230+
withResourceFetchingFromRoute(handler, { space: { requireCanList: true } })
247231
);

front/pages/api/v1/w/[wId]/spaces/[spaceId]/data_source_views/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,5 +95,5 @@ async function handler(
9595
}
9696

9797
export default withPublicAPIAuthentication(
98-
withResourceFetchingFromRoute(handler, { space: true })
98+
withResourceFetchingFromRoute(handler, { space: { requireCanList: true } })
9999
);

front/pages/api/v1/w/[wId]/spaces/[spaceId]/data_sources/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,5 +87,5 @@ async function handler(
8787
}
8888

8989
export default withPublicAPIAuthentication(
90-
withResourceFetchingFromRoute(handler, { space: true })
90+
withResourceFetchingFromRoute(handler, { space: { requireCanList: true } })
9191
);

front/pages/api/w/[wId]/spaces/[spaceId]/apps/[aId]/datasets/[name]/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,5 +232,5 @@ async function handler(
232232
}
233233

234234
export default withSessionAuthenticationForWorkspace(
235-
withResourceFetchingFromRoute(handler, { space: true })
235+
withResourceFetchingFromRoute(handler, { space: { requireCanList: true } })
236236
);

front/pages/api/w/[wId]/spaces/[spaceId]/apps/[aId]/datasets/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,5 +211,5 @@ async function handler(
211211
}
212212

213213
export default withSessionAuthenticationForWorkspace(
214-
withResourceFetchingFromRoute(handler, { space: true })
214+
withResourceFetchingFromRoute(handler, { space: { requireCanList: true } })
215215
);

front/pages/api/w/[wId]/spaces/[spaceId]/apps/[aId]/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,5 +134,5 @@ async function handler(
134134
}
135135

136136
export default withSessionAuthenticationForWorkspace(
137-
withResourceFetchingFromRoute(handler, { space: true })
137+
withResourceFetchingFromRoute(handler, { space: { requireCanList: true } })
138138
);

front/pages/api/w/[wId]/spaces/[spaceId]/apps/[aId]/runs/[runId]/blocks/[type]/[name]/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,5 +107,5 @@ async function handler(
107107
}
108108

109109
export default withSessionAuthenticationForWorkspace(
110-
withResourceFetchingFromRoute(handler, { space: true })
110+
withResourceFetchingFromRoute(handler, { space: { requireCanList: true } })
111111
);

front/pages/api/w/[wId]/spaces/[spaceId]/apps/[aId]/runs/[runId]/status.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,5 +108,5 @@ async function handler(
108108
}
109109

110110
export default withSessionAuthenticationForWorkspace(
111-
withResourceFetchingFromRoute(handler, { space: true })
111+
withResourceFetchingFromRoute(handler, { space: { requireCanList: true } })
112112
);

front/pages/api/w/[wId]/spaces/[spaceId]/apps/[aId]/runs/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,5 +265,5 @@ async function handler(
265265
}
266266

267267
export default withSessionAuthenticationForWorkspace(
268-
withResourceFetchingFromRoute(handler, { space: true })
268+
withResourceFetchingFromRoute(handler, { space: { requireCanList: true } })
269269
);

front/pages/api/w/[wId]/spaces/[spaceId]/apps/[aId]/state.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,5 +109,5 @@ async function handler(
109109
}
110110

111111
export default withSessionAuthenticationForWorkspace(
112-
withResourceFetchingFromRoute(handler, { space: true })
112+
withResourceFetchingFromRoute(handler, { space: { requireCanList: true } })
113113
);

front/pages/api/w/[wId]/spaces/[spaceId]/apps/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,5 +117,5 @@ async function handler(
117117
}
118118

119119
export default withSessionAuthenticationForWorkspace(
120-
withResourceFetchingFromRoute(handler, { space: true })
120+
withResourceFetchingFromRoute(handler, { space: { requireCanList: true } })
121121
);

0 commit comments

Comments
 (0)