mirror of
https://github.com/versia-pub/server.git
synced 2025-12-07 16:58:20 +01:00
feat(federation): ✨ Add bridge support to Lysand
This commit is contained in:
parent
a603b602e6
commit
7a591a024e
|
|
@ -288,6 +288,16 @@ reactions = []
|
||||||
banners = []
|
banners = []
|
||||||
avatars = []
|
avatars = []
|
||||||
|
|
||||||
|
# For bridge software, such as lysand-org/activitypub
|
||||||
|
# Bridges must be hosted separately from the main Lysand process
|
||||||
|
[federation.bridge]
|
||||||
|
enabled = false
|
||||||
|
# Only lysand-ap exists for now
|
||||||
|
software = "lysand-ap"
|
||||||
|
# WARNING: These IPs will have signature checks disabled.
|
||||||
|
# Only use the bridge software if you trust it.
|
||||||
|
allowed_ips = ["192.168.1.0/24"]
|
||||||
|
|
||||||
[instance]
|
[instance]
|
||||||
name = "Lysand"
|
name = "Lysand"
|
||||||
description = "A Lysand instance"
|
description = "A Lysand instance"
|
||||||
|
|
|
||||||
|
|
@ -430,6 +430,17 @@ export const configValidator = z.object({
|
||||||
banners: z.array(zUrl).default([]),
|
banners: z.array(zUrl).default([]),
|
||||||
avatars: z.array(zUrl).default([]),
|
avatars: z.array(zUrl).default([]),
|
||||||
}),
|
}),
|
||||||
|
bridge: z
|
||||||
|
.object({
|
||||||
|
enabled: z.boolean().default(false),
|
||||||
|
software: z.enum(["lysand-ap"]).or(z.string()),
|
||||||
|
allowed_ips: z.array(z.string().trim()).default([]),
|
||||||
|
})
|
||||||
|
.default({
|
||||||
|
enabled: false,
|
||||||
|
software: "lysand-ap",
|
||||||
|
allowed_ips: [],
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
.default({
|
.default({
|
||||||
blocked: [],
|
blocked: [],
|
||||||
|
|
@ -445,6 +456,11 @@ export const configValidator = z.object({
|
||||||
banners: [],
|
banners: [],
|
||||||
avatars: [],
|
avatars: [],
|
||||||
},
|
},
|
||||||
|
bridge: {
|
||||||
|
enabled: false,
|
||||||
|
software: "lysand-ap",
|
||||||
|
allowed_ips: [],
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
instance: z
|
instance: z
|
||||||
.object({
|
.object({
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,10 @@ import { zValidator } from "@hono/zod-validator";
|
||||||
import { dualLogger } from "@loggers";
|
import { dualLogger } from "@loggers";
|
||||||
import { EntityValidator, SignatureValidator } from "@lysand-org/federation";
|
import { EntityValidator, SignatureValidator } from "@lysand-org/federation";
|
||||||
import { errorResponse, jsonResponse, response } from "@response";
|
import { errorResponse, jsonResponse, response } from "@response";
|
||||||
|
import type { SocketAddress } from "bun";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import type { Hono } from "hono";
|
import type { Hono } from "hono";
|
||||||
|
import { matches } from "ip-matching";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { isValidationError } from "zod-validation-error";
|
import { isValidationError } from "zod-validation-error";
|
||||||
import { resolveNote } from "~database/entities/Status";
|
import { resolveNote } from "~database/entities/Status";
|
||||||
|
|
@ -14,6 +16,7 @@ import {
|
||||||
} from "~database/entities/User";
|
} from "~database/entities/User";
|
||||||
import { db } from "~drizzle/db";
|
import { db } from "~drizzle/db";
|
||||||
import { Notifications, Relationships } from "~drizzle/schema";
|
import { Notifications, Relationships } from "~drizzle/schema";
|
||||||
|
import { config } from "~packages/config-manager";
|
||||||
import { User } from "~packages/database-interface/user";
|
import { User } from "~packages/database-interface/user";
|
||||||
import { LogLevel } from "~packages/log-manager";
|
import { LogLevel } from "~packages/log-manager";
|
||||||
|
|
||||||
|
|
@ -57,11 +60,27 @@ export default (app: Hono) =>
|
||||||
return errorResponse("User not found", 404);
|
return errorResponse("User not found", 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-expect-error IP attribute is not in types
|
||||||
|
const request_ip = context.env?.ip as
|
||||||
|
| SocketAddress
|
||||||
|
| undefined
|
||||||
|
| null;
|
||||||
|
|
||||||
|
let checkSignature = true;
|
||||||
|
|
||||||
|
if (request_ip?.address && config.federation.bridge.enabled) {
|
||||||
|
for (const ip of config.federation.bridge.allowed_ips) {
|
||||||
|
if (matches(ip, request_ip?.address)) {
|
||||||
|
checkSignature = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Verify request signature
|
// Verify request signature
|
||||||
// TODO: Check if instance is defederated
|
// TODO: Check if instance is defederated
|
||||||
// TODO: Reverse DNS lookup with Origin header
|
// TODO: Reverse DNS lookup with Origin header
|
||||||
// biome-ignore lint/correctness/noConstantCondition: Temporary
|
if (checkSignature) {
|
||||||
if (true) {
|
|
||||||
if (!signature) {
|
if (!signature) {
|
||||||
return errorResponse("Missing Signature header", 400);
|
return errorResponse("Missing Signature header", 400);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue