Skip to content

Commit

Permalink
feat: add more rate limits
Browse files Browse the repository at this point in the history
  • Loading branch information
bigint committed Jul 11, 2024
1 parent 3d75e5c commit 3aed94e
Show file tree
Hide file tree
Showing 22 changed files with 381 additions and 311 deletions.
96 changes: 50 additions & 46 deletions apps/api/src/routes/avatar.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Handler } from 'express';
import type { Request, Response } from 'express';

import { LensHub } from '@hey/abis';
import { IPFS_GATEWAY, IS_MAINNET, LENS_HUB } from '@hey/data/constants';
Expand All @@ -7,6 +7,7 @@ import logger from '@hey/helpers/logger';
import randomNumber from '@hey/helpers/randomNumber';
import { CACHE_AGE_INDEFINITE_ON_DISK } from 'src/helpers/constants';
import getRpc from 'src/helpers/getRpc';
import { rateLimiter } from 'src/helpers/middlewares/rateLimiter';
import { getRedis, setRedis } from 'src/helpers/redisClient';
import { noBody } from 'src/helpers/responses';
import { createPublicClient } from 'viem';
Expand All @@ -15,58 +16,61 @@ import { polygon, polygonAmoy } from 'viem/chains';
const getSvgImage = (base64Image: string) =>
Buffer.from(base64Image, 'base64').toString('utf-8');

export const get: Handler = async (req, res) => {
const { id } = req.query;
export const get = [
rateLimiter({ requests: 2000, within: 1 }),
async (req: Request, res: Response) => {
const { id } = req.query;

if (!id) {
return noBody(res);
}
if (!id) {
return noBody(res);
}

try {
const cacheKey = `avatar:${id}`;
const cachedData = await getRedis(cacheKey);
try {
const cacheKey = `avatar:${id}`;
const cachedData = await getRedis(cacheKey);

if (cachedData) {
logger.info(`(cached) Downloaded Lenny avatar for ${id}`);
return res
.status(200)
.setHeader('Cache-Control', CACHE_AGE_INDEFINITE_ON_DISK)
.type('svg')
.send(getSvgImage(cachedData));
}
if (cachedData) {
logger.info(`(cached) Downloaded Lenny avatar for ${id}`);
return res
.status(200)
.setHeader('Cache-Control', CACHE_AGE_INDEFINITE_ON_DISK)
.type('svg')
.send(getSvgImage(cachedData));
}

const client = createPublicClient({
chain: IS_MAINNET ? polygon : polygonAmoy,
transport: getRpc({ mainnet: IS_MAINNET })
});
const client = createPublicClient({
chain: IS_MAINNET ? polygon : polygonAmoy,
transport: getRpc({ mainnet: IS_MAINNET })
});

const data: any = await client.readContract({
abi: LensHub,
address: LENS_HUB,
args: [id],
functionName: 'tokenURI'
});
const data: any = await client.readContract({
abi: LensHub,
address: LENS_HUB,
args: [id],
functionName: 'tokenURI'
});

const jsonData = JSON.parse(
Buffer.from(data.split(',')[1], 'base64').toString()
);
const jsonData = JSON.parse(
Buffer.from(data.split(',')[1], 'base64').toString()
);

const base64Image = jsonData.image.split(';base64,').pop();
const base64Image = jsonData.image.split(';base64,').pop();

await setRedis(
cacheKey,
base64Image,
randomNumber(daysToSeconds(400), daysToSeconds(600))
);
logger.info(`Downloaded Lenny avatar for ${id}`);
await setRedis(
cacheKey,
base64Image,
randomNumber(daysToSeconds(400), daysToSeconds(600))
);
logger.info(`Downloaded Lenny avatar for ${id}`);

return res
.status(200)
.setHeader('Cache-Control', CACHE_AGE_INDEFINITE_ON_DISK)
.type('svg')
.send(getSvgImage(base64Image));
} catch {
const url = `${IPFS_GATEWAY}/Qmb4XppdMDCsS7KCL8nCJo8pukEWeqL4bTghURYwYiG83i/cropped_image.png`;
return res.status(302).redirect(url);
return res
.status(200)
.setHeader('Cache-Control', CACHE_AGE_INDEFINITE_ON_DISK)
.type('svg')
.send(getSvgImage(base64Image));
} catch {
const url = `${IPFS_GATEWAY}/Qmb4XppdMDCsS7KCL8nCJo8pukEWeqL4bTghURYwYiG83i/cropped_image.png`;
return res.status(302).redirect(url);
}
}
};
];
2 changes: 1 addition & 1 deletion apps/api/src/routes/badges/hasHeyNft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { noBody } from 'src/helpers/responses';
import { getAddress } from 'viem';

export const get = [
rateLimiter({ requests: 50, within: 1 }),
rateLimiter({ requests: 100, within: 1 }),
async (req: Request, res: Response) => {
const { address, id } = req.query;

Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/routes/badges/isHeyProfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { noBody } from 'src/helpers/responses';
import { getAddress } from 'viem';

export const get = [
rateLimiter({ requests: 50, within: 1 }),
rateLimiter({ requests: 100, within: 1 }),
async (req: Request, res: Response) => {
const { address, id } = req.query;

Expand Down
2 changes: 2 additions & 0 deletions apps/api/src/routes/drafts/all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import logger from '@hey/helpers/logger';
import parseJwt from '@hey/helpers/parseJwt';
import heyPg from 'src/db/heyPg';
import catchedError from 'src/helpers/catchedError';
import { rateLimiter } from 'src/helpers/middlewares/rateLimiter';
import validateLensAccount from 'src/helpers/middlewares/validateLensAccount';

// TODO: add tests
export const get = [
rateLimiter({ requests: 100, within: 1 }),
validateLensAccount,
async (req: Request, res: Response) => {
try {
Expand Down
2 changes: 2 additions & 0 deletions apps/api/src/routes/drafts/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { Request, Response } from 'express';
import logger from '@hey/helpers/logger';
import heyPg from 'src/db/heyPg';
import catchedError from 'src/helpers/catchedError';
import { rateLimiter } from 'src/helpers/middlewares/rateLimiter';
import validateLensAccount from 'src/helpers/middlewares/validateLensAccount';
import { invalidBody, noBody } from 'src/helpers/responses';
import { object, string } from 'zod';
Expand All @@ -17,6 +18,7 @@ const validationSchema = object({

// TODO: add tests
export const post = [
rateLimiter({ requests: 50, within: 1 }),
validateLensAccount,
async (req: Request, res: Response) => {
const { body } = req;
Expand Down
2 changes: 2 additions & 0 deletions apps/api/src/routes/drafts/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import logger from '@hey/helpers/logger';
import parseJwt from '@hey/helpers/parseJwt';
import heyPg from 'src/db/heyPg';
import catchedError from 'src/helpers/catchedError';
import { rateLimiter } from 'src/helpers/middlewares/rateLimiter';
import validateLensAccount from 'src/helpers/middlewares/validateLensAccount';
import { invalidBody, noBody } from 'src/helpers/responses';
import { object, string } from 'zod';
Expand All @@ -21,6 +22,7 @@ const validationSchema = object({
});

export const post = [
rateLimiter({ requests: 50, within: 1 }),
validateLensAccount,
async (req: Request, res: Response) => {
const { body } = req;
Expand Down
2 changes: 2 additions & 0 deletions apps/api/src/routes/email/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { APP_NAME } from '@hey/data/constants';
import logger from '@hey/helpers/logger';
import parseJwt from '@hey/helpers/parseJwt';
import catchedError from 'src/helpers/catchedError';
import { rateLimiter } from 'src/helpers/middlewares/rateLimiter';
import validateLensAccount from 'src/helpers/middlewares/validateLensAccount';
import prisma from 'src/helpers/prisma';
import { invalidBody, noBody } from 'src/helpers/responses';
Expand All @@ -22,6 +23,7 @@ const validationSchema = object({
});

export const post = [
rateLimiter({ requests: 5, within: 60 }),
validateLensAccount,
async (req: Request, res: Response) => {
const { body } = req;
Expand Down
82 changes: 43 additions & 39 deletions apps/api/src/routes/ens/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { Handler } from 'express';
import type { Request, Response } from 'express';

import logger from '@hey/helpers/logger';
import catchedError from 'src/helpers/catchedError';
import { resolverAbi } from 'src/helpers/ens/resolverAbi';
import { rateLimiter } from 'src/helpers/middlewares/rateLimiter';
import { invalidBody, noBody } from 'src/helpers/responses';
import { createPublicClient, fallback, http } from 'viem';
import { mainnet } from 'viem/chains';
Expand All @@ -18,42 +19,45 @@ const validationSchema = object({
})
});

export const post: Handler = async (req, res) => {
const { body } = req;

if (!body) {
return noBody(res);
}

const validation = validationSchema.safeParse(body);

if (!validation.success) {
return invalidBody(res);
export const post = [
rateLimiter({ requests: 100, within: 1 }),
async (req: Request, res: Response) => {
const { body } = req;

if (!body) {
return noBody(res);
}

const validation = validationSchema.safeParse(body);

if (!validation.success) {
return invalidBody(res);
}

const { addresses } = body as ExtensionRequest;

try {
const client = createPublicClient({
chain: mainnet,
transport: fallback([
http('https://ethereum.publicnode.com'),
http('https://rpc.ankr.com/eth'),
http('https://cloudflare-eth.com'),
http('https://eth.merkle.io')
])
});

const result = await client.readContract({
abi: resolverAbi,
address: '0x3671ae578e63fdf66ad4f3e12cc0c0d71ac7510c',
args: [addresses],
functionName: 'getNames'
});
logger.info('ENS names fetched');

return res.status(200).json({ result, success: true });
} catch (error) {
return catchedError(res, error);
}
}

const { addresses } = body as ExtensionRequest;

try {
const client = createPublicClient({
chain: mainnet,
transport: fallback([
http('https://ethereum.publicnode.com'),
http('https://rpc.ankr.com/eth'),
http('https://cloudflare-eth.com'),
http('https://eth.merkle.io')
])
});

const result = await client.readContract({
abi: resolverAbi,
address: '0x3671ae578e63fdf66ad4f3e12cc0c0d71ac7510c',
args: [addresses],
functionName: 'getNames'
});
logger.info('ENS names fetched');

return res.status(200).json({ result, success: true });
} catch (error) {
return catchedError(res, error);
}
};
];
2 changes: 2 additions & 0 deletions apps/api/src/routes/frames/post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { parseHTML } from 'linkedom';
import catchedError from 'src/helpers/catchedError';
import { HEY_USER_AGENT } from 'src/helpers/constants';
import signFrameAction from 'src/helpers/frames/signFrameAction';
import { rateLimiter } from 'src/helpers/middlewares/rateLimiter';
import validateLensAccount from 'src/helpers/middlewares/validateLensAccount';
import getFrame from 'src/helpers/oembed/meta/getFrame';
import { invalidBody, noBody } from 'src/helpers/responses';
Expand All @@ -31,6 +32,7 @@ const validationSchema = object({
});

export const post = [
rateLimiter({ requests: 100, within: 1 }),
validateLensAccount,
async (req: Request, res: Response) => {
const { body } = req;
Expand Down
Loading

0 comments on commit 3aed94e

Please sign in to comment.