Fixes on api rate limits

This commit is contained in:
urania-dev
2024-02-26 22:45:48 +01:00
parent 831944d1a0
commit 6a74a76193
10 changed files with 26 additions and 24 deletions

View File

@@ -1,4 +1,5 @@
# .dockerignore
.vscode
node_modules
.env

View File

@@ -1,4 +1,4 @@
AUTH_SECRET=lFNiU7T98/44Qlqb4hMUkVcLOpijEI7z722Kxhv4O2Y=
AUTH_SECRET= ## openssl rand -base64 32
DB_HOST=
DB_PASS=
DB_PORT=6379

View File

@@ -25,7 +25,7 @@ import isWhiteListed from './users/isWhiteListed';
import isBlackListed from './users/isBlackListed';
import isBlackListedEmail from './users/isEmailBlackListed';
import trackMaxURLs from './settings/trackMaxURLs';
import trackRPDandRPM from './settings/trackRDPandRPM';
import trackRPDandRPM from './settings/trackRPDandRPM';
import hasWhiteList from './snapps/has_whitelist';
export const domainZList = 'settings:app:banlists:website' as const;

View File

@@ -10,7 +10,6 @@ export default async function checkRPDLimit(this: Database, userId: string, rpdL
// Check if the user has already made a request on the current date
const count = await this.redis.get(key);
if (count && parseInt(count) >= rpdLimit) {
// User has exceeded the RPD limit
return false;

View File

@@ -4,12 +4,12 @@ import { error } from '@sveltejs/kit';
import type { Database } from '..';
export default async function trackMaxURLs(this: Database, apiKey: DBAPIKey, _EN?: Translation) {
if (apiKey.roles.includes('admin') || apiKey.roles.includes('superadmin')) return true;
if (apiKey.roles.includes('admin') || apiKey.roles.includes('superadmin')) return false;
const is_limited = await this.getSetting('settings:app:limits:enabled').then(
(res) => res === 'true' || false
);
if (!is_limited) return true;
if (!is_limited) return false;
const EN = _EN ? _EN : await getLanguage();
@@ -28,6 +28,6 @@ export default async function trackMaxURLs(this: Database, apiKey: DBAPIKey, _EN
const limit = user_limit?.urls ?? global_limit_urls;
if (!limit || urls_by_this_user <= limit) {
return true;
} else throw error(401, { message: EN['api:error:too:many:shorturl'] });
return false;
} else true;
}

View File

@@ -4,14 +4,13 @@ import { error } from 'console';
import type { Database } from '..';
export default async function trackRPDandRPM(this: Database, apiKey: DBAPIKey, _EN?: Translation) {
if (apiKey.roles.includes('admin') || apiKey.roles.includes('superadmin')) return true;
if (apiKey.roles.includes('admin') || apiKey.roles.includes('superadmin')) return false;
const is_limited = await this.getSetting('settings:app:limits:enabled').then(
(res) => res === 'true' || false
);
if (!is_limited) return true;
if (!is_limited) return false;
const EN = _EN ? _EN : await getLanguage();
const global_limit_rpm = await parseNumber(this.getSetting('settings:app:limits:max:rpm'));
const global_limit_rpd = await parseNumber(this.getSetting('settings:app:limits:max:rpd'));
const user_limit = (
@@ -23,5 +22,6 @@ export default async function trackRPDandRPM(this: Database, apiKey: DBAPIKey, _
const under_the_max_request_limit =
(await this.rpm(apiKey.user_id, rpm)) && (await this.rpd(apiKey.user_id, rpd));
if (!under_the_max_request_limit) throw error(429, { message: EN['api:error:too:many:request'] });
if (!under_the_max_request_limit) return true;
return false
}

View File

@@ -12,7 +12,7 @@
import type { SubmitFunction } from './$types';
import { toast } from 'svelte-sonner';
import { signIn } from '@auth/sveltekit/client';
import { invalidateAll } from '$app/navigation';
import { goto, invalidateAll } from '$app/navigation';
import EyeIcon from 'lucide-svelte/icons/eye';
import EyeOffIcon from 'lucide-svelte/icons/eye-off';
let show_password = false;
@@ -51,6 +51,7 @@
callbackUrl: '/'
});
await invalidateAll();
goto('/');
}
};
};
@@ -59,7 +60,6 @@
show_password = !show_password;
}
function handle_submit_enter(e: KeyboardEvent) {
const keyEvent = e as KeyboardEvent;
if (keyEvent.code !== 'Enter' && keyEvent.code !== 'NumpadEnter') return;
e.preventDefault();

View File

@@ -110,7 +110,7 @@ export const actions = {
emailForm.set('email_footer', EMAIL_FOOTER);
emailForm.set('outer_text', OUT_TEXT);
const send_mail = await fetch('/api/smtp/send', {
await fetch('/api/smtp/send', {
headers: {
authorization: 'Bearer ' + token.id
},

View File

@@ -3,8 +3,6 @@ import type SnappError from '$lib/db/utils/snappError.js';
import { error, fail, redirect, type NumericRange } from '@sveltejs/kit';
import { randomUUID } from 'crypto';
import type { Actions } from './$types';
import { generateRandomString } from '$lib/utils/randomString';
import { createTransport, type TransportOptions } from 'nodemailer';
import { env } from '$env/dynamic/public';
import getLanguage from '$lib/api/utils/getLanguage';
@@ -124,7 +122,7 @@ export const actions: Actions = {
const APP_NAME = EN['global:appname'];
const EMAIL_OBJECT = EN['emails:invited:object'].replace('{app_name}', APP_NAME);
const EMAIL_DESCRIPTION = EN['emails:invited:text']
.replace('{url}', `${env.PUBLIC_URL}/auth/recover-password?token=${token}`)
.replace('{url}', `${env.PUBLIC_URL}/auth/recover-password?token=${token.id}`)
.replace('{username}', user.username);
const EMAIL_FOOTER = EN['emails:invited:footer'].replace('{url}', url.origin);

View File

@@ -10,11 +10,11 @@ import { extractDomain } from '$lib/db/snapps/shorten.js';
import { randomUUID } from 'crypto';
export async function GET({ request, url }) {
console.log('get');
const EN = await getLanguage();
const apiKey = await authenticate(request, EN);
await db.trackRPDandRPM(apiKey, EN);
const isLimited = await db.trackRPDandRPM(apiKey, EN);
if (isLimited) throw error(429, { message: EN['api:error:too:many:request'] });
const { page, limit, search, sort, sortDir, offset } = getUrlParams(url);
let query = db.snapps.search();
@@ -40,7 +40,7 @@ export async function GET({ request, url }) {
headers: {
'Content-Type': 'application/json',
'cache-control': 'max-age=' + 60 * 60,
'Access-Control-Allowed-Origins':"*"
'Access-Control-Allowed-Origins': '*'
}
}
);
@@ -53,8 +53,10 @@ export async function POST({ request, fetch }) {
const EN = await getLanguage();
const apiKey = await authenticate(request, EN);
await db.trackRPDandRPM(apiKey, EN);
await db.trackMaxURLs(apiKey, EN);
const isLimited = await db.trackRPDandRPM(apiKey, EN);
if (isLimited) throw error(429, { message: EN['api:error:too:many:request'] });
const hasReachedMaxLimit = await db.trackMaxURLs(apiKey, EN);
if (hasReachedMaxLimit) throw error(401, { message: EN['api:error:too:many:shorturl'] });
const form = await request.formData();
const { user_id } = apiKey;
@@ -107,7 +109,8 @@ export async function PATCH({ request, fetch }) {
const EN = await getLanguage();
const apiKey = await authenticate(request, EN);
await db.trackRPDandRPM(apiKey, EN);
const isLimited = await db.trackRPDandRPM(apiKey, EN);
if (isLimited) throw error(429, { message: EN['api:error:too:many:request'] });
const form = await request.formData();
const id = form.get('id')?.toString();
@@ -171,7 +174,8 @@ export async function DELETE({ request, url }) {
const EN = await getLanguage();
const apiKey = await authenticate(request, EN);
await db.trackRPDandRPM(apiKey, EN);
const isLimited = await db.trackRPDandRPM(apiKey, EN);
if (isLimited) throw error(429, { message: EN['api:error:too:many:request'] });
const { user_id } = apiKey;