Fixed 267U.pre2
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import { MastoApiError } from "./catch-errors.js";
|
||||
import { OAuthTokens } from "../../../../models/index.js";
|
||||
import authenticate from "../../authenticate.js";
|
||||
import { AuthHelpers } from "../helpers/auth.js";
|
||||
export async function AuthMiddleware(ctx, next) {
|
||||
const token = await getTokenFromOAuth(ctx.headers.authorization);
|
||||
ctx.appId = token?.appId;
|
||||
ctx.user = token?.user ?? null;
|
||||
ctx.scopes = token?.scopes ?? [];
|
||||
await next();
|
||||
}
|
||||
export async function getTokenFromOAuth(authorization) {
|
||||
if (authorization == null) return null;
|
||||
if (authorization.substring(0, 7).toLowerCase() === "bearer ") authorization = authorization.substring(7);
|
||||
return OAuthTokens.findOne({
|
||||
where: {
|
||||
token: authorization,
|
||||
active: true
|
||||
},
|
||||
relations: [
|
||||
'user'
|
||||
]
|
||||
}).then((token)=>{
|
||||
if (!token) return null;
|
||||
return {
|
||||
...token,
|
||||
scopes: AuthHelpers.expandScopes(token.scopes)
|
||||
};
|
||||
});
|
||||
}
|
||||
export function auth(required, scopes = []) {
|
||||
return async function auth(ctx, next) {
|
||||
if (required && !ctx.user) throw new MastoApiError(401, "This method requires an authenticated user");
|
||||
if (!scopes.every((p)=>ctx.scopes.includes(p))) {
|
||||
if (required) throw new MastoApiError(403, "This action is outside the authorized scopes");
|
||||
ctx.user = null;
|
||||
ctx.scopes = [];
|
||||
}
|
||||
await next();
|
||||
};
|
||||
}
|
||||
export function MiAuth(required) {
|
||||
return async function MiAuth(ctx, next) {
|
||||
ctx.miauth = await authenticate(ctx.headers.authorization, null, true).catch((_)=>[
|
||||
null,
|
||||
null
|
||||
]);
|
||||
if (required && !ctx.miauth[0]) throw new MastoApiError(401, "Unauthorized");
|
||||
await next();
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { UserHelpers } from "../helpers/user.js";
|
||||
export async function CacheMiddleware(ctx, next) {
|
||||
ctx.cache = UserHelpers.getFreshAccountCache();
|
||||
await next();
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import { logger } from "../index.js";
|
||||
import { IdentifiableError } from "../../../../misc/identifiable-error.js";
|
||||
import { ApiError } from "../../error.js";
|
||||
export class MastoApiError extends Error {
|
||||
statusCode;
|
||||
errorDescription;
|
||||
constructor(statusCode, message, description){
|
||||
if (message == null) {
|
||||
switch(statusCode){
|
||||
case 404:
|
||||
message = 'Record not found';
|
||||
break;
|
||||
default:
|
||||
message = 'Unknown error occurred';
|
||||
break;
|
||||
}
|
||||
}
|
||||
super(message);
|
||||
this.errorDescription = description;
|
||||
this.statusCode = statusCode;
|
||||
}
|
||||
}
|
||||
export async function CatchErrorsMiddleware(ctx, next) {
|
||||
try {
|
||||
await next();
|
||||
} catch (e) {
|
||||
if (e instanceof MastoApiError) {
|
||||
ctx.status = e.statusCode;
|
||||
ctx.body = {
|
||||
error: e.message,
|
||||
error_description: e.errorDescription
|
||||
};
|
||||
return;
|
||||
} else if (e instanceof IdentifiableError) {
|
||||
if (e.message.length < 1) e.message = e.id;
|
||||
ctx.status = 400;
|
||||
} else if (e instanceof ApiError) {
|
||||
ctx.status = e.httpStatusCode ?? 500;
|
||||
} else {
|
||||
logger.error(`Error occured in ${ctx.method} ${ctx.path}:`);
|
||||
if (e instanceof Error) {
|
||||
if (e.stack) logger.error(e.stack);
|
||||
else logger.error(`${e.name}: ${e.message}`);
|
||||
} else {
|
||||
logger.error(e);
|
||||
}
|
||||
ctx.status = 500;
|
||||
}
|
||||
ctx.body = {
|
||||
error: e.message ?? e
|
||||
};
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
export function filterContext(context) {
|
||||
return async function filterContext(ctx, next) {
|
||||
ctx.filterContext = context;
|
||||
await next();
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { HttpMethodEnum, koaBody } from "koa-body";
|
||||
export function KoaBodyMiddleware() {
|
||||
const options = {
|
||||
multipart: true,
|
||||
urlencoded: true,
|
||||
parsedMethods: [
|
||||
HttpMethodEnum.POST,
|
||||
HttpMethodEnum.PUT,
|
||||
HttpMethodEnum.PATCH,
|
||||
HttpMethodEnum.DELETE
|
||||
] // dear god mastodon why
|
||||
};
|
||||
return koaBody(options);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
export async function NormalizeQueryMiddleware(ctx, next) {
|
||||
if (ctx.request.query) {
|
||||
if (!ctx.request.body || Object.keys(ctx.request.body).length === 0) {
|
||||
ctx.request.body = ctx.request.query;
|
||||
} else {
|
||||
ctx.request.body = {
|
||||
...ctx.request.body,
|
||||
...ctx.request.query
|
||||
};
|
||||
}
|
||||
}
|
||||
await next();
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import config from "../../../../config/index.js";
|
||||
export async function PaginationMiddleware(ctx, next) {
|
||||
await next();
|
||||
if (!ctx.pagination) return;
|
||||
const link = [];
|
||||
const limit = ctx.pagination.limit;
|
||||
if (ctx.pagination.maxId) {
|
||||
const l = `<${config.url}/api${ctx.path}?limit=${limit}&max_id=${ctx.pagination.maxId}>; rel="next"`;
|
||||
link.push(l);
|
||||
}
|
||||
if (ctx.pagination.minId) {
|
||||
const l = `<${config.url}/api${ctx.path}?limit=${limit}&min_id=${ctx.pagination.minId}>; rel="prev"`;
|
||||
link.push(l);
|
||||
}
|
||||
if (link.length > 0) {
|
||||
ctx.response.append('Link', link.join(', '));
|
||||
}
|
||||
}
|
||||
export function generatePaginationData(ids, limit) {
|
||||
if (ids.length < 1) return undefined;
|
||||
return {
|
||||
limit: limit,
|
||||
maxId: ids.length < limit ? undefined : ids.at(-1),
|
||||
minId: ids.at(0)
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
const headers = {
|
||||
"Access-Control-Expose-Headers": "Link,Connection,Sec-Websocket-Accept,Upgrade"
|
||||
};
|
||||
export async function SetHeadersMiddleware(ctx, next) {
|
||||
ctx.set(headers);
|
||||
await next();
|
||||
}
|
||||
Reference in New Issue
Block a user