Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions src/plugin/ssp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import {FastifyInstance, FastifyRequest} from 'fastify';
import fp from 'fastify-plugin';

import {SspConfig, SspParamType} from '@/interfaces/config';

export default fp(
async (fastify: FastifyInstance) => {
function enforceSSP(request: FastifyRequest): void {
const apiIdentifier = request.routeOptions?.config?.apiIdentifier;
if (!apiIdentifier) {
return;
}

const ssps: SspConfig[] =
fastify.appConfig.apis?.[apiIdentifier]?.ssp ?? [];
if (!ssps.length) return;

const apply = (val: unknown, type: SspParamType) => {
if (val && typeof val === 'object' && !Array.isArray(val)) {
const record = val as Record<string, unknown>;
ssps.forEach(ssp => {
if (ssp.paramType === type) {
if (ssp.value === '[userId]') {
record[ssp.paramName] = request.user?.id;
} else if (ssp.value === '[userEmail]') {
record[ssp.paramName] = request.user?.email;
} else {
record[ssp.paramName] = ssp.value;
}
}
});
}
};

// 1. replace request.query values based on ssp
apply(request.query, 'query');

// 2. replace request.body
apply(request.body, 'body');

// 3. finally request.params (path params)
apply(request.params, 'path');
}

fastify.decorate('enforceSSP', enforceSSP);
},
{
name: 'ssp-plugin',
},
);
5 changes: 1 addition & 4 deletions src/routes/aggregate/aggregate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
SupportedAggregationOperation,
} from '@/interfaces/config';

import {enforceSSP} from '@/utils/ssp';
import {capitalizeFirstLetter} from '@/utils/string';

/**
Expand Down Expand Up @@ -40,8 +39,6 @@ export function registerAggregateRoutes(
// construct the api identifier
const apiIdentifier = `aggregateAPIs->${model.name}->${field.name}->getAggregation`;

// extract the api configs based on the api identifier
const sspConfig = config.apis?.[apiIdentifier]?.ssp ?? [];
// calculating the authroization based on auth flag, it can be true
// if the api level auth is enabled, or if the app level auth is enabled
const authorization =
Expand Down Expand Up @@ -82,7 +79,7 @@ export function registerAggregateRoutes(
);
}
}
enforceSSP(sspConfig, request);
app.enforceSSP(request);
},
preHandler: async request => {
await app.callWebhook('request', request, null);
Expand Down
6 changes: 1 addition & 5 deletions src/routes/custom-queries/custom-queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import {

import {AppConfig, DataType} from '@/interfaces/config';

import {enforceSSP} from '@/utils/ssp';

type ParamSource = {
body?: Record<string, unknown>;
params?: Record<string, unknown>;
Expand Down Expand Up @@ -92,8 +90,6 @@ export function registerCustomQueryRoutes(
// constructing the api identifier
const apiIdentifier = `customAPIs->customQueries->all->${cq.name}`;

// extracting the api configs based on the api identifier
const sspConfig = config.apis?.[apiIdentifier]?.ssp ?? [];
// calculating the authroization based on auth flag, it can be true
// if the api level auth is enabled, or if the app level auth is enabled
const authorization =
Expand Down Expand Up @@ -250,7 +246,7 @@ export function registerCustomQueryRoutes(
);
}
}
enforceSSP(sspConfig, request);
app.enforceSSP(request);
},
preHandler: async request => {
await app.callWebhook('request', request, null);
Expand Down
6 changes: 1 addition & 5 deletions src/routes/operations/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {

import {AppConfig, ModelConfig, ModelFieldConfig} from '@/interfaces/config';

import {enforceSSP} from '@/utils/ssp';
import {capitalizeFirstLetter} from '@/utils/string';

/**
Expand Down Expand Up @@ -39,9 +38,6 @@ export function registerDeleteRoutes(
// constructing the api identifier
const apiIdentifier = `modelAPIs->${model.name}->${field.name}->delete`;

// extracting the api configs based on the api identifier
const sspConfig = config.apis?.[apiIdentifier]?.ssp ?? [];

// calculating the authroization based on auth flag, it can be true
// if the api level auth is enabled, or if the app level auth is enabled
const authorization =
Expand Down Expand Up @@ -77,7 +73,7 @@ export function registerDeleteRoutes(
);
}
}
enforceSSP(sspConfig, request);
app.enforceSSP(request);
},
preHandler: async request => {
await app.callWebhook('request', request, null);
Expand Down
8 changes: 2 additions & 6 deletions src/routes/operations/edit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {

import {AppConfig, ModelBody} from '@/interfaces/config';

import {enforceSSP} from '@/utils/ssp';
import {capitalizeFirstLetter} from '@/utils/string';

/**
Expand Down Expand Up @@ -41,9 +40,6 @@ export function registerEditRoutes(
// constructing the api identifier
const apiIdentifier = `modelAPIs->${model.name}->${field.name}->edit`;

// extracting the api configs based on the api identifier
const sspConfig = config.apis?.[apiIdentifier]?.ssp ?? [];

// calculating the authroization based on auth flag, it can be true
// if the api level auth is enabled, or if the app level auth is enabled
const authorization =
Expand Down Expand Up @@ -244,7 +240,7 @@ export function registerEditRoutes(
);
}
}
enforceSSP(sspConfig, request);
app.enforceSSP(request);
},
preHandler: async request => {
await app.callWebhook('request', request, null);
Expand Down Expand Up @@ -277,7 +273,7 @@ export function registerEditRoutes(
);
}
}
enforceSSP(sspConfig, request);
app.enforceSSP(request);
},
preHandler: async request => {
await app.callWebhook('request', request, null);
Expand Down
6 changes: 1 addition & 5 deletions src/routes/operations/get-all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {

import {AppConfig, ModelConfig} from '@/interfaces/config';

import {enforceSSP} from '@/utils/ssp';
import {capitalizeFirstLetter} from '@/utils/string';

/**
Expand All @@ -37,9 +36,6 @@ export function registerGetAllRoutes(
// constructing the api identifier
const apiIdentifier = `modelAPIs->${model.name}->all->getAll`;

// extracting the api configs based on the api identifier
const sspConfig = config.apis?.[apiIdentifier]?.ssp ?? [];

// calculating the authroization based on auth flag, it can be true
// if the api level auth is enabled, or if the app level auth is enabled
const authorization =
Expand Down Expand Up @@ -74,7 +70,7 @@ export function registerGetAllRoutes(
);
}
}
enforceSSP(sspConfig, request);
app.enforceSSP(request);
},
preHandler: async request => {
await app.callWebhook('request', request, null);
Expand Down
6 changes: 1 addition & 5 deletions src/routes/operations/index-route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {

import {AppConfig, ModelConfig, ModelFieldConfig} from '@/interfaces/config';

import {enforceSSP} from '@/utils/ssp';
import {capitalizeFirstLetter} from '@/utils/string';

/**
Expand Down Expand Up @@ -49,9 +48,6 @@ export function registerIndexRoutes(
// constructing the api identifier
const apiIdentifier = `modelAPIs->${model.name}->${field.name}->index`;

// extracting the api configs based on the api identifier
const sspConfig = config.apis?.[apiIdentifier]?.ssp ?? [];

// calculating the authroization based on auth flag, it can be true
// if the api level auth is enabled, or if the app level auth is enabled
const authorization =
Expand Down Expand Up @@ -85,7 +81,7 @@ export function registerIndexRoutes(
);
}
}
enforceSSP(sspConfig, request);
app.enforceSSP(request);
},
preHandler: async request => {
await app.callWebhook('request', request, null);
Expand Down
6 changes: 1 addition & 5 deletions src/routes/operations/post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {

import {AppConfig, ModelBody, ModelConfig} from '@/interfaces/config';

import {enforceSSP} from '@/utils/ssp';
import {capitalizeFirstLetter} from '@/utils/string';

/**
Expand All @@ -29,9 +28,6 @@ export function registerPostRoutes(
// constructing the api identifier
const apiIdentifier = `modelAPIs->${model.name}->all->insert`;

// extracting the api configs based on the api identifier
const sspConfig = config.apis?.[apiIdentifier]?.ssp ?? [];

// calculating the authroization based on auth flag, it can be true
// if the api level auth is enabled, or if the app level auth is enabled
const authorization =
Expand Down Expand Up @@ -69,7 +65,7 @@ export function registerPostRoutes(
);
}
}
enforceSSP(sspConfig, request);
app.enforceSSP(request);
},
preHandler: async request => {
await app.callWebhook('request', request, null);
Expand Down
6 changes: 1 addition & 5 deletions src/routes/operations/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {

import {AppConfig, ModelConfig, ModelFieldConfig} from '@/interfaces/config';

import {enforceSSP} from '@/utils/ssp';
import {capitalizeFirstLetter} from '@/utils/string';

/**
Expand Down Expand Up @@ -41,9 +40,6 @@ export function registerSearchRoutes(
// constructing the api identifier
const apiIdentifier = `modelAPIs->${model.name}->${field.name}->search`;

// extracting the api configs based on the api identifier
const sspConfig = config.apis?.[apiIdentifier]?.ssp ?? [];

// calculating the authroization based on auth flag, it can be true
// if the api level auth is enabled, or if the app level auth is enabled
const authorization =
Expand Down Expand Up @@ -81,7 +77,7 @@ export function registerSearchRoutes(
);
}
}
enforceSSP(sspConfig, request);
app.enforceSSP(request);
},
preHandler: async request => {
await app.callWebhook('request', request, null);
Expand Down
2 changes: 2 additions & 0 deletions src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import dbPlugin from '@/plugin/database';
import rateLimitPlugin from '@/plugin/rate-limit';
import redisPlugin from '@/plugin/redis';
import responsePlugin from '@/plugin/response';
import sspPlugin from '@/plugin/ssp';
import webhookPlugin from '@/plugin/webhook';

import {registerRoutes} from '@/routes';
Expand Down Expand Up @@ -135,6 +136,7 @@ export async function startServer(
}

await app.register(responsePlugin);
await app.register(sspPlugin);
await app.register(webhookPlugin);
if (config.auth) {
await app.register(authPlugin);
Expand Down
1 change: 1 addition & 0 deletions src/types/fastify.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ declare module 'fastify' {
request: import('fastify').FastifyRequest,
payload: unknown,
) => Promise<void>;
enforceSSP: (request: import('fastify').FastifyRequest) => void;
}
}
36 changes: 0 additions & 36 deletions src/utils/ssp.ts

This file was deleted.

2 changes: 2 additions & 0 deletions tests/helpers/test-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Fastify, {FastifyInstance} from 'fastify';
import authPlugin from '@/plugin/auth';
import databasePlugin from '@/plugin/database';
import responsePlugin from '@/plugin/response';
import sspPlugin from '@/plugin/ssp';
import webhookPlugin from '@/plugin/webhook';

import {registerRoutes} from '@/routes';
Expand Down Expand Up @@ -67,6 +68,7 @@ export async function createTestApp(

await fastify.register(databasePlugin, dbConfig);
await fastify.register(responsePlugin);
await fastify.register(sspPlugin);
await fastify.register(webhookPlugin);
await fastify.register(authPlugin);

Expand Down
Loading
Loading