mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-27 07:14:56 +00:00
docs: nextjs,frontends,get (5 files)
This commit is contained in:
@@ -61,6 +61,12 @@ const verified = scram(password, storedHash);
|
||||
- Tokens expire after inactivity
|
||||
- Tokens can be revoked immediately
|
||||
|
||||
### Login Lockout & Backoff
|
||||
|
||||
- Failed login attempts are tracked per username and rate-limited.
|
||||
- After `MB_AUTH_LOCKOUT_MAX_ATTEMPTS` within `MB_AUTH_LOCKOUT_WINDOW_MS`, logins lock for `MB_AUTH_LOCKOUT_MS`.
|
||||
- When locked, the API returns `429` with `Retry-After` to guide clients.
|
||||
|
||||
## 🏢 Multi-Tenant Isolation
|
||||
|
||||
### Tenant Boundaries
|
||||
@@ -257,8 +263,7 @@ const hashedKey = sha512(API_KEY); // Hash for storage
|
||||
|
||||
## 🔗 Related Documentation
|
||||
|
||||
TODO: Security guidelines live at ../security/SECURITY.md; update this link.
|
||||
- [Security Guidelines](../SECURITY.md) - Security policy
|
||||
- [Security Guidelines](../security/SECURITY.md) - Security policy
|
||||
- [5-Level System](./5-level-system.md) - Permission model
|
||||
- [Database Architecture](./database.md) - Data storage
|
||||
- [API Development](../guides/api-development.md) - API security
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
export { GET } from './handlers/get-package-data'
|
||||
export { PUT } from './handlers/put-package-data'
|
||||
export { DELETE } from './handlers/delete-package-data'
|
||||
@@ -0,0 +1,40 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import type { NextRequest } from 'next/server'
|
||||
import { getInstalledPackages } from '@/lib/db/packages/get-installed-packages'
|
||||
import { uninstallPackage } from '@/lib/db/packages/uninstall-package'
|
||||
import { getPackageCatalogEntry } from '@/lib/packages/server/get-package-catalog-entry'
|
||||
import { uninstallPackageContent } from '@/lib/packages/server/uninstall-package-content'
|
||||
|
||||
interface RouteParams {
|
||||
params: {
|
||||
packageId: string
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(_request: NextRequest, { params }: RouteParams) {
|
||||
try {
|
||||
const entry = getPackageCatalogEntry(params.packageId)
|
||||
if (!entry) {
|
||||
return NextResponse.json({ error: 'Package not found' }, { status: 404 })
|
||||
}
|
||||
|
||||
const installed = await getInstalledPackages()
|
||||
if (!installed.some((pkg) => pkg.packageId === params.packageId)) {
|
||||
return NextResponse.json({ error: 'Package not installed' }, { status: 404 })
|
||||
}
|
||||
|
||||
await uninstallPackageContent(params.packageId, entry.content)
|
||||
await uninstallPackage(params.packageId)
|
||||
|
||||
return NextResponse.json({ deleted: true })
|
||||
} catch (error) {
|
||||
console.error('Error uninstalling package:', error)
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: 'Failed to uninstall package',
|
||||
details: error instanceof Error ? error.message : 'Unknown error',
|
||||
},
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { getAdapter } from '../dbal-client'
|
||||
import type { User } from '../../types/level-types'
|
||||
import { mapUserRecord } from './map-user-record'
|
||||
|
||||
/**
|
||||
* Get the SuperGod user (instance owner)
|
||||
@@ -9,17 +10,5 @@ export async function getSuperGod(): Promise<User | null> {
|
||||
const result = await adapter.list('User', { filter: { isInstanceOwner: true } })
|
||||
|
||||
if (result.data.length === 0) return null
|
||||
const user = result.data[0] as any
|
||||
|
||||
return {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
email: user.email,
|
||||
role: user.role as any,
|
||||
profilePicture: user.profilePicture || undefined,
|
||||
bio: user.bio || undefined,
|
||||
createdAt: Number(user.createdAt),
|
||||
tenantId: user.tenantId || undefined,
|
||||
isInstanceOwner: user.isInstanceOwner,
|
||||
}
|
||||
return mapUserRecord(result.data[0] as Record<string, unknown>)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { getAdapter } from '../dbal-client'
|
||||
import type { User } from '../../types/level-types'
|
||||
import { mapUserRecord } from './map-user-record'
|
||||
|
||||
export type GetUsersOptions =
|
||||
| { tenantId: string }
|
||||
@@ -13,15 +14,5 @@ export async function getUsers(options: GetUsersOptions): Promise<User[]> {
|
||||
const adapter = getAdapter()
|
||||
const listOptions = 'tenantId' in options ? { filter: { tenantId: options.tenantId } } : undefined
|
||||
const result = listOptions ? await adapter.list('User', listOptions) : await adapter.list('User')
|
||||
return (result.data as any[]).map((u) => ({
|
||||
id: u.id,
|
||||
username: u.username,
|
||||
email: u.email,
|
||||
role: u.role as any,
|
||||
profilePicture: u.profilePicture || undefined,
|
||||
bio: u.bio || undefined,
|
||||
createdAt: Number(u.createdAt),
|
||||
tenantId: u.tenantId || undefined,
|
||||
isInstanceOwner: u.isInstanceOwner,
|
||||
}))
|
||||
return (result.data as Record<string, unknown>[]).map((user) => mapUserRecord(user))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user