Let a super admin read the database from the app
A new super admin settings page, /admin/settings/database, lists every table with its record count and size, and one page of the open table's records newest key first. Values are cut inside SQL (400 characters, with a flag saying so) and a record opens whole in a modal, so a table of long texts reads without shipping it all. A search matches every column's text, word by word or as a phrase, which is the one thing that also works on a virtual table. Nothing in it writes: the catalog, the records and the single record are all reads, GET only.
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
import AppError from "@/src/utils/app-error";
|
||||
import grabDatabaseTables from "./grab-database-tables";
|
||||
import type { DatabaseTableSummary } from "@/src/types";
|
||||
|
||||
type Params = {
|
||||
/**
|
||||
* The table asked for, as it came in the query string. The first table
|
||||
* is used when nothing is asked for.
|
||||
*/
|
||||
table?: string | null;
|
||||
};
|
||||
|
||||
/**
|
||||
* One table, or the first one when nothing is asked for. Anything else is
|
||||
* refused with a message safe to show: the browser only ever reads tables
|
||||
* that are in the database, never a name it built itself.
|
||||
*/
|
||||
export default async function grabTableCatalogEntry({ table }: Params): Promise<DatabaseTableSummary> {
|
||||
const tables = await grabDatabaseTables();
|
||||
|
||||
if (!tables.length) {
|
||||
throw new AppError(`Couldn't read the database's tables.`);
|
||||
}
|
||||
|
||||
const first = tables[0];
|
||||
|
||||
if (!table && first) return first;
|
||||
|
||||
const entry = tables.find((candidate) => candidate.name == table);
|
||||
|
||||
if (!entry) {
|
||||
throw new AppError(`There's no table called "${table}".`);
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
Reference in New Issue
Block a user