refactor: 🚨 Turn every linter rule on and fix issues (there were a LOT :3)

This commit is contained in:
Jesse Wierzbinski 2024-06-12 16:26:43 -10:00
parent 2e98859153
commit a1e02d0d78
No known key found for this signature in database
177 changed files with 1826 additions and 1248 deletions

View file

@ -20,13 +20,13 @@ import {
import { parse } from "qs";
import type { z } from "zod";
import { fromZodError } from "zod-validation-error";
import type { Application } from "~/database/entities/Application";
import { getFromHeader } from "~/database/entities/User";
import type { Application } from "~/database/entities/application";
import { type AuthData, getFromHeader } from "~/database/entities/user";
import type { User } from "~/packages/database-interface/user";
import { LogLevel, LogManager } from "~/packages/log-manager";
import type { APIRouteMetadata, HttpVerb } from "~/types/api";
import type { ApiRouteMetadata, HttpVerb } from "~/types/api";
export const applyConfig = (routeMeta: APIRouteMetadata) => {
export const applyConfig = (routeMeta: ApiRouteMetadata) => {
const newMeta = routeMeta;
// Apply ratelimits from config
@ -94,16 +94,113 @@ export const handleZodError = (
result:
| { success: true; data?: object }
| { success: false; error: z.ZodError<z.AnyZodObject>; data?: object },
context: Context,
_context: Context,
) => {
if (!result.success) {
return errorResponse(fromZodError(result.error).message, 422);
}
};
const getAuth = async (value: Record<string, string>) => {
return value.authorization
? await getFromHeader(value.authorization)
: null;
};
const checkPermissions = (
auth: AuthData | null,
permissionData: ApiRouteMetadata["permissions"],
context: Context,
) => {
const userPerms = auth?.user
? auth.user.getAllPermissions()
: config.permissions.anonymous;
const requiredPerms =
permissionData?.methodOverrides?.[context.req.method as HttpVerb] ??
permissionData?.required ??
[];
const error = errorResponse("Unauthorized", 401);
if (!requiredPerms.every((perm) => userPerms.includes(perm))) {
const missingPerms = requiredPerms.filter(
(perm) => !userPerms.includes(perm),
);
return context.json(
{
error: `You do not have the required permissions to access this route. Missing: ${missingPerms.join(", ")}`,
},
403,
error.headers.toJSON(),
);
}
};
const checkRouteNeedsAuth = (
auth: AuthData | null,
authData: ApiRouteMetadata["auth"],
context: Context,
) => {
const error = errorResponse("Unauthorized", 401);
if (auth?.user) {
return {
user: auth.user as User,
token: auth.token as string,
application: auth.application as Application | null,
};
}
if (authData.required) {
return context.json(
{
error: "Unauthorized",
},
401,
error.headers.toJSON(),
);
}
if (authData.requiredOnMethods?.includes(context.req.method as HttpVerb)) {
return context.json(
{
error: "Unauthorized",
},
401,
error.headers.toJSON(),
);
}
return {
user: null,
token: null,
application: null,
};
};
export const auth = (
authData: APIRouteMetadata["auth"],
permissionData?: APIRouteMetadata["permissions"],
authData: ApiRouteMetadata["auth"],
permissionData?: ApiRouteMetadata["permissions"],
) =>
validator("header", async (value, context) => {
const auth = await getAuth(value);
// Permissions check
if (permissionData) {
const permissionCheck = checkPermissions(
auth,
permissionData,
context,
);
if (permissionCheck) {
return permissionCheck;
}
}
return checkRouteNeedsAuth(auth, authData, context);
});
/* export const auth = (
authData: ApiRouteMetadata["auth"],
permissionData?: ApiRouteMetadata["permissions"],
) =>
validator("header", async (value, context) => {
const auth = value.authorization
@ -140,46 +237,41 @@ export const auth = (
}
}
if (!auth?.user) {
if (authData.required) {
return context.json(
{
error: "Unauthorized",
},
401,
error.headers.toJSON(),
);
}
if (
authData.requiredOnMethods?.includes(
context.req.method as HttpVerb,
)
) {
return context.json(
{
error: "Unauthorized",
},
401,
error.headers.toJSON(),
);
}
// Check role permissions
} else {
if (auth?.user) {
return {
user: auth.user as User,
token: auth.token as string,
application: auth.application as Application | null,
};
}
if (authData.required) {
return context.json(
{
error: "Unauthorized",
},
401,
error.headers.toJSON(),
);
}
if (
authData.requiredOnMethods?.includes(context.req.method as HttpVerb)
) {
return context.json(
{
error: "Unauthorized",
},
401,
error.headers.toJSON(),
);
}
return {
user: null,
token: null,
application: null,
};
});
}); */
/**
* Middleware to magically unfuck forms
@ -200,12 +292,12 @@ export const qs = () => {
for (const val of value) {
urlparams.append(key, val);
}
} else if (!(value instanceof File)) {
urlparams.append(key, String(value));
} else {
} else if (value instanceof File) {
if (!files.has(key)) {
files.set(key, value);
}
} else {
urlparams.append(key, String(value));
}
}
@ -297,12 +389,12 @@ export const jsonOrForm = () => {
for (const val of value) {
urlparams.append(key, val);
}
} else if (!(value instanceof File)) {
urlparams.append(key, String(value));
} else {
} else if (value instanceof File) {
if (!files.has(key)) {
files.set(key, value);
}
} else {
urlparams.append(key, String(value));
}
}
@ -341,7 +433,7 @@ export const debugRequest = async (
) => {
const body = await req.clone().text();
await logger.log(
LogLevel.DEBUG,
LogLevel.Debug,
"RequestDebugger",
`\n${chalk.green(req.method)} ${chalk.blue(req.url)}\n${chalk.bold(
"Hash",

View file

@ -4,7 +4,9 @@ import { lookup } from "mime-types";
export const getBestContentType = (
content?: typeof EntityValidator.$ContentFormat,
) => {
if (!content) return { content: "", format: "text/plain" };
if (!content) {
return { content: "", format: "text/plain" };
}
const bestFormatsRanked = [
"text/x.misskeymarkdown",
@ -14,8 +16,9 @@ export const getBestContentType = (
];
for (const format of bestFormatsRanked) {
if (content[format])
if (content[format]) {
return { content: content[format].content, format };
}
}
return { content: "", format: "text/plain" };
@ -24,7 +27,9 @@ export const getBestContentType = (
export const urlToContentFormat = (
url?: string,
): typeof EntityValidator.$ContentFormat | null => {
if (!url) return null;
if (!url) {
return null;
}
if (url.startsWith("https://api.dicebear.com/")) {
return {
"image/svg+xml": {
@ -46,7 +51,9 @@ export const urlToContentFormat = (
export const mimeLookup = async (url: string) => {
const naiveLookup = lookup(url.replace(new URL(url).search, ""));
if (naiveLookup) return naiveLookup;
if (naiveLookup) {
return naiveLookup;
}
const fetchLookup = fetch(url, { method: "HEAD" }).then(
(response) => response.headers.get("content-type") || "",

View file

@ -4,11 +4,11 @@ import { config } from "~/packages/config-manager";
const noColors = process.env.NO_COLORS === "true";
const noFancyDates = process.env.NO_FANCY_DATES === "true";
const requests_log = Bun.file(config.logging.storage.requests);
const requestsLog = Bun.file(config.logging.storage.requests);
const isEntry = true;
export const logger = new LogManager(
isEntry ? requests_log : Bun.file("/dev/null"),
isEntry ? requestsLog : Bun.file("/dev/null"),
);
export const consoleLogger = new LogManager(

View file

@ -1,4 +1,4 @@
import { markdownParse } from "~/database/entities/Status";
import { markdownParse } from "~/database/entities/status";
import { LogLevel } from "~/packages/log-manager";
import { dualLogger } from "./loggers";
@ -9,19 +9,19 @@ export const renderMarkdownInPath = async (
let content = await markdownParse(defaultText ?? "");
let lastModified = new Date(1970, 0, 0);
const extended_description_file = Bun.file(path || "");
const extendedDescriptionFile = Bun.file(path || "");
if (path && (await extended_description_file.exists())) {
if (path && (await extendedDescriptionFile.exists())) {
content =
(await markdownParse(
(await extended_description_file.text().catch(async (e) => {
await dualLogger.logError(LogLevel.ERROR, "Routes", e);
(await extendedDescriptionFile.text().catch(async (e) => {
await dualLogger.logError(LogLevel.Error, "Routes", e);
return "";
})) ||
defaultText ||
"",
)) || "";
lastModified = new Date(extended_description_file.lastModified);
lastModified = new Date(extendedDescriptionFile.lastModified);
}
return {

View file

@ -1,4 +1,3 @@
import chalk from "chalk";
import { config } from "config-manager";
import { count } from "drizzle-orm";
import { LogLevel, type LogManager, type MultiLogManager } from "log-manager";
@ -13,7 +12,9 @@ export const meilisearch = new Meilisearch({
});
export const connectMeili = async (logger: MultiLogManager | LogManager) => {
if (!config.meilisearch.enabled) return;
if (!config.meilisearch.enabled) {
return;
}
if (await meilisearch.isHealthy()) {
await meilisearch
@ -33,13 +34,13 @@ export const connectMeili = async (logger: MultiLogManager | LogManager) => {
.updateSearchableAttributes(["content"]);
await logger.log(
LogLevel.INFO,
LogLevel.Info,
"Meilisearch",
"Connected to Meilisearch",
);
} else {
await logger.log(
LogLevel.CRITICAL,
LogLevel.Critical,
"Meilisearch",
"Error while connecting to Meilisearch",
);
@ -53,7 +54,9 @@ export enum MeiliIndexType {
}
export const addUserToMeilisearch = async (user: User) => {
if (!config.meilisearch.enabled) return;
if (!config.meilisearch.enabled) {
return;
}
await meilisearch.index(MeiliIndexType.Accounts).addDocuments([
{
@ -116,25 +119,19 @@ export const rebuildSearchIndexes = async (
for (let i = 0; i < accountCount / batchSize; i++) {
const accounts = await getNthDatabaseAccountBatch(i, batchSize);
const progress = Math.round((i / (accountCount / batchSize)) * 100);
console.log(`${chalk.green("✓")} ${progress}%`);
/* const _progress = Math.round(
(i / (accountCount / batchSize)) * 100,
);
*/
// Sync with Meilisearch
await meilisearch
.index(MeiliIndexType.Accounts)
.addDocuments(accounts);
}
const meiliAccountCount = (
/* const _meiliAccountCount = (
await meilisearch.index(MeiliIndexType.Accounts).getStats()
).numberOfDocuments;
console.log(
`${chalk.green("✓")} ${chalk.bold(
`Done! ${meiliAccountCount} accounts indexed`,
)}`,
);
).numberOfDocuments; */
}
if (indexes.includes(MeiliIndexType.Statuses)) {
@ -149,9 +146,7 @@ export const rebuildSearchIndexes = async (
for (let i = 0; i < statusCount / batchSize; i++) {
const statuses = await getNthDatabaseStatusBatch(i, batchSize);
const progress = Math.round((i / (statusCount / batchSize)) * 100);
console.log(`${chalk.green("✓")} ${progress}%`);
/* const _progress = Math.round((i / (statusCount / batchSize)) * 100); */
// Sync with Meilisearch
await meilisearch
@ -159,14 +154,8 @@ export const rebuildSearchIndexes = async (
.addDocuments(statuses);
}
const meiliStatusCount = (
/* const _meiliStatusCount = (
await meilisearch.index(MeiliIndexType.Statuses).getStats()
).numberOfDocuments;
console.log(
`${chalk.green("✓")} ${chalk.bold(
`Done! ${meiliStatusCount} statuses indexed`,
)}`,
);
).numberOfDocuments; */
}
};

View file

@ -1,4 +1,4 @@
import type { Application } from "~/database/entities/Application";
import type { Application } from "~/database/entities/application";
/**
* Check if an OAuth application is valid for a route

View file

@ -7,7 +7,7 @@ export const sanitizedHtmlStrip = (html: string) => {
});
};
export const sanitizeHtmlInline = async (
export const sanitizeHtmlInline = (
html: string,
extraConfig?: IFilterXSSOptions,
) => {

View file

@ -2,9 +2,9 @@ import { config } from "config-manager";
import type {
Notification,
findManyNotifications,
} from "~/database/entities/Notification";
import type { Status, findManyNotes } from "~/database/entities/Status";
import type { UserType, findManyUsers } from "~/database/entities/User";
} from "~/database/entities/notification";
import type { Status, findManyNotes } from "~/database/entities/status";
import type { UserType, findManyUsers } from "~/database/entities/user";
import type { db } from "~/drizzle/db";
export async function fetchTimeline<T extends UserType | Status | Notification>(