feat: add basic webui
This commit is contained in:
45
packages/security/index.ts
Normal file
45
packages/security/index.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import arcjet, {
|
||||
type ArcjetBotCategory,
|
||||
type ArcjetWellKnownBot,
|
||||
detectBot,
|
||||
request,
|
||||
shield,
|
||||
} from '@arcjet/next';
|
||||
import { env } from '@konobangu/env';
|
||||
|
||||
// Create a base Arcjet instance which can be imported and extended in each route.
|
||||
const base = arcjet({
|
||||
// Get your site key from https://app.arcjet.com
|
||||
key: env.ARCJET_KEY,
|
||||
// Identify the user by their IP address
|
||||
characteristics: ['ip.src'],
|
||||
rules: [
|
||||
// Protect against common attacks with Arcjet Shield
|
||||
shield({
|
||||
// Will block requests. Use "DRY_RUN" to log only
|
||||
mode: 'LIVE',
|
||||
}),
|
||||
// Other rules are added in different routes
|
||||
],
|
||||
});
|
||||
|
||||
export const secure = async (
|
||||
allow: (ArcjetWellKnownBot | ArcjetBotCategory)[],
|
||||
sourceRequest?: Request
|
||||
) => {
|
||||
const req = sourceRequest ?? (await request());
|
||||
const aj = base.withRule(detectBot({ mode: 'LIVE', allow }));
|
||||
const decision = await aj.protect(req);
|
||||
|
||||
if (decision.isDenied()) {
|
||||
if (decision.reason.isBot()) {
|
||||
throw new Error('No bots allowed');
|
||||
}
|
||||
|
||||
if (decision.reason.isRateLimit()) {
|
||||
throw new Error('Rate limit exceeded');
|
||||
}
|
||||
|
||||
throw new Error('Access denied');
|
||||
}
|
||||
};
|
||||
23
packages/security/middleware.ts
Normal file
23
packages/security/middleware.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { env } from '@konobangu/env';
|
||||
import {
|
||||
type NoseconeOptions,
|
||||
defaults,
|
||||
withVercelToolbar,
|
||||
} from '@nosecone/next';
|
||||
export { createMiddleware as noseconeMiddleware } from '@nosecone/next';
|
||||
|
||||
// Nosecone security headers configuration
|
||||
// https://docs.arcjet.com/nosecone/quick-start
|
||||
const noseconeOptions: NoseconeOptions = {
|
||||
...defaults,
|
||||
// Content Security Policy (CSP) is disabled by default because the values
|
||||
// depend on which Next Forge features are enabled. See
|
||||
// https://docs.next-forge.com/features/security/headers for guidance on how
|
||||
// to configure it.
|
||||
contentSecurityPolicy: false,
|
||||
};
|
||||
|
||||
export const noseconeConfig: NoseconeOptions =
|
||||
env.NODE_ENV === 'development' && env.FLAGS_SECRET
|
||||
? withVercelToolbar(noseconeOptions)
|
||||
: noseconeOptions;
|
||||
20
packages/security/package.json
Normal file
20
packages/security/package.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "@konobangu/security",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"clean": "git clean -xdf .cache .turbo dist node_modules",
|
||||
"typecheck": "tsc --noEmit --emitDeclarationOnly false"
|
||||
},
|
||||
"dependencies": {
|
||||
"@arcjet/next": "1.0.0-alpha.34",
|
||||
"@nosecone/next": "1.0.0-alpha.34",
|
||||
"@konobangu/env": "workspace:*",
|
||||
"@konobangu/database": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@konobangu/typescript-config": "workspace:*",
|
||||
"typescript": "^5.7.2"
|
||||
}
|
||||
}
|
||||
8
packages/security/tsconfig.json
Normal file
8
packages/security/tsconfig.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "@konobangu/typescript-config/react-library.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "."
|
||||
},
|
||||
"include": ["**/*.ts", "**/*.tsx"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
Reference in New Issue
Block a user