Skip to content

Commit 004b917

Browse files
authored
Apply security policy to auth controller (#2084)
Fixes OPS-3876.
1 parent 36ffb8b commit 004b917

3 files changed

Lines changed: 43 additions & 15 deletions

File tree

packages/server/api/src/app/authentication/authentication.controller.ts

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,18 @@ import {
88
ALL_PRINCIPAL_TYPES,
99
createAuthResponse,
1010
OpsEdition,
11+
Permission,
1112
PrincipalType,
1213
Provider,
1314
PUBLIC_ROUTE_POLICY,
1415
SignInRequest,
1516
SignUpRequest,
1617
} from '@openops/shared';
1718
import { StatusCodes } from 'http-status-codes';
19+
import {
20+
getOrganizationScopedRoutePolicy,
21+
getProjectScopedRoutePolicy,
22+
} from '../core/security/route-policies/route-security-policy-factory';
1823
import { analyticsDashboardService } from '../openops-analytics/analytics-dashboard-service';
1924
import { resolveOrganizationIdForAuthnRequest } from '../organization/organization-utils';
2025
import { userService } from '../user/user-service';
@@ -35,6 +40,10 @@ export const GetBlockRequestParams = Type.Object({
3540
const AnalyticsGuestTokenRequestOptions = {
3641
config: {
3742
allowedPrincipals: [PrincipalType.USER],
43+
security: getProjectScopedRoutePolicy({
44+
allowedPrincipals: [PrincipalType.USER],
45+
permission: Permission.WRITE_ANALYTICS,
46+
}),
3847
},
3948
schema: {
4049
description:
@@ -66,20 +75,32 @@ export const authenticationController: FastifyPluginAsyncTypebox = async (
6675
);
6776

6877
if (analyticsEnabled) {
69-
app.get('/analytics-embed-id', async (request, reply) => {
70-
const { access_token } =
71-
await analyticsAuthenticationService.authenticateAnalyticsRequest(
72-
request.principal.id,
73-
request.principal.projectId,
74-
);
75-
76-
const embedId =
77-
await analyticsDashboardService.fetchFinopsDashboardEmbedId(
78-
access_token,
79-
);
80-
81-
return reply.send(embedId);
82-
});
78+
app.get(
79+
'/analytics-embed-id',
80+
{
81+
config: {
82+
allowedPrincipals: [PrincipalType.USER],
83+
security: getProjectScopedRoutePolicy({
84+
allowedPrincipals: [PrincipalType.USER],
85+
permission: Permission.WRITE_ANALYTICS,
86+
}),
87+
},
88+
},
89+
async (request, reply) => {
90+
const { access_token } =
91+
await analyticsAuthenticationService.authenticateAnalyticsRequest(
92+
request.principal.id,
93+
request.principal.projectId,
94+
);
95+
96+
const embedId =
97+
await analyticsDashboardService.fetchFinopsDashboardEmbedId(
98+
access_token,
99+
);
100+
101+
return reply.send(embedId);
102+
},
103+
);
83104

84105
app.get(
85106
'/analytics-guest-token',
@@ -159,6 +180,10 @@ const rateLimitOptions: RateLimitOptions = {
159180
const SignUpRequestOptions = {
160181
config: {
161182
allowedPrincipals: [PrincipalType.USER],
183+
security: getOrganizationScopedRoutePolicy({
184+
allowedPrincipals: [PrincipalType.USER],
185+
permission: Permission.WRITE_USER,
186+
}),
162187
rateLimit: rateLimitOptions,
163188
},
164189
schema: {

packages/server/api/test/unit/authentication/authentication.controller.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ describe('authenticationController analytics routes', () => {
108108
([path]) => path === '/analytics-embed-id',
109109
);
110110
expect(embedRoute).toBeDefined();
111-
expect(embedRoute?.[1]).toEqual(expect.any(Function));
111+
expect(embedRoute?.[2]).toEqual(expect.any(Function));
112112

113113
const guestRoute = app.get.mock.calls.find(
114114
([path]) => path === '/analytics-guest-token',

packages/shared/src/lib/common/security/permission.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,7 @@ export enum Permission {
2727

2828
// Tables
2929
WRITE_TABLE = 'table:write',
30+
31+
// Analytics
32+
WRITE_ANALYTICS = 'analytics:write',
3033
}

0 commit comments

Comments
 (0)