refactor(federation): Make references always have domains
Some checks failed
CodeQL Scan / Analyze (push) Failing after 0s
Deploy Docs to GitHub Pages / build (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s
Build Docker Images / lint (push) Has been cancelled
Build Docker Images / check (push) Has been cancelled
Build Docker Images / tests (push) Has been cancelled
Build Docker Images / detect-circular (push) Has been cancelled
Mirror to Codeberg / Mirror (push) Has been cancelled
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been cancelled
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been cancelled

This commit is contained in:
Jesse Wierzbinski 2026-04-03 13:34:19 +02:00
parent df2a5ce260
commit 709e1c6087
No known key found for this signature in database
22 changed files with 688 additions and 477 deletions

View file

@ -4,6 +4,7 @@ import {
EntitySchema,
URICollectionSchema,
} from "@versia/sdk/schemas";
import { config } from "@versia-server/config";
import { ApiError } from "@versia-server/kit";
import { apiRoute, handleZodError } from "@versia-server/kit/api";
import { db, Instance, Note, User } from "@versia-server/kit/db";
@ -112,13 +113,16 @@ export default apiRoute((app) =>
),
);
entity = new VersiaEntities.URICollection({
author: note.author.id,
total: replyCount,
items: replies.map((reply) =>
reply.reference.toString(),
),
});
entity = new VersiaEntities.URICollection(
{
author: note.author.id,
total: replyCount,
items: replies.map((reply) =>
reply.reference.toString(),
),
},
config.http.base_url.hostname,
);
break;
}
case "quotes": {
@ -146,13 +150,16 @@ export default apiRoute((app) =>
),
);
entity = new VersiaEntities.URICollection({
author: note.author.id,
total: quoteCount,
items: quotes.map((quote) =>
quote.reference.toString(),
),
});
entity = new VersiaEntities.URICollection(
{
author: note.author.id,
total: quoteCount,
items: quotes.map((quote) =>
quote.reference.toString(),
),
},
config.http.base_url.hostname,
);
break;
}
case "pub.versia:share/Shares": {
@ -180,13 +187,16 @@ export default apiRoute((app) =>
),
);
entity = new VersiaEntities.URICollection({
author: note.author.id,
total: shareCount,
items: shares.map((share) =>
share.reference.toString(),
),
});
entity = new VersiaEntities.URICollection(
{
author: note.author.id,
total: shareCount,
items: shares.map((share) =>
share.reference.toString(),
),
},
config.http.base_url.hostname,
);
break;
}
}
@ -226,23 +236,29 @@ export default apiRoute((app) =>
offset,
);
entity = new VersiaEntities.Collection({
author: user.id,
total,
items: outboxItems.map((note) =>
note.toVersia(),
),
});
entity = new VersiaEntities.Collection(
{
author: user.id,
total,
items: outboxItems.map((note) =>
note.toVersia(),
),
},
config.http.base_url.hostname,
);
break;
}
case "followers": {
if (user.data.isHidingCollections) {
entity = new VersiaEntities.URICollection({
author: user.id,
items: [],
total: 0,
});
entity = new VersiaEntities.URICollection(
{
author: user.id,
items: [],
total: 0,
},
config.http.base_url.hostname,
);
break;
}
@ -258,23 +274,29 @@ export default apiRoute((app) =>
offset,
);
entity = new VersiaEntities.URICollection({
author: user.id,
items: followers.map((follower) =>
follower.reference.toString(),
),
total,
});
entity = new VersiaEntities.URICollection(
{
author: user.id,
items: followers.map((follower) =>
follower.reference.toString(),
),
total,
},
config.http.base_url.hostname,
);
break;
}
case "following": {
if (user.data.isHidingCollections) {
entity = new VersiaEntities.URICollection({
author: user.id,
items: [],
total: 0,
});
entity = new VersiaEntities.URICollection(
{
author: user.id,
items: [],
total: 0,
},
config.http.base_url.hostname,
);
break;
}
@ -290,13 +312,16 @@ export default apiRoute((app) =>
offset,
);
entity = new VersiaEntities.URICollection({
author: user.id,
items: following.map((followed) =>
followed.reference.toString(),
),
total,
});
entity = new VersiaEntities.URICollection(
{
author: user.id,
items: following.map((followed) =>
followed.reference.toString(),
),
total,
},
config.http.base_url.hostname,
);
break;
}

View file

@ -83,15 +83,18 @@ mock(new URL(`/.versia/v0.6/entities/User/${userId}`, instanceUrl).href, {
headers: {
"Content-Type": "application/vnd.versia+json; charset=utf-8",
},
data: new VersiaEntities.User({
id: userId,
created_at: "2025-04-18T10:32:01.427Z",
type: "User",
username: "testuser",
fields: [],
manually_approves_followers: false,
indexable: true,
}).toJSON(),
data: new VersiaEntities.User(
{
id: userId,
created_at: "2025-04-18T10:32:01.427Z",
type: "User",
username: "testuser",
fields: [],
manually_approves_followers: false,
indexable: true,
},
instanceUrl.hostname,
).toJSON(),
},
});
@ -111,35 +114,38 @@ afterAll(async () => {
describe("Inbox Tests", () => {
test("should correctly process inbox request", async () => {
const exampleNote = new VersiaEntities.Note({
id: noteId,
created_at: "2025-04-18T10:32:01.427Z",
type: "Note",
extensions: {
"pub.versia:custom_emojis": {
emojis: [],
const exampleNote = new VersiaEntities.Note(
{
id: noteId,
created_at: "2025-04-18T10:32:01.427Z",
type: "Note",
extensions: {
"pub.versia:custom_emojis": {
emojis: [],
},
},
previews: [],
attachments: [],
author: userId,
content: {
"text/html": {
content: "<p>Hello!</p>",
remote: false,
},
"text/plain": {
content: "Hello!",
remote: false,
},
},
group: "public",
is_sensitive: false,
mentions: [],
quotes: null,
replies_to: null,
subject: "",
},
previews: [],
attachments: [],
author: userId,
content: {
"text/html": {
content: "<p>Hello!</p>",
remote: false,
},
"text/plain": {
content: "Hello!",
remote: false,
},
},
group: "public",
is_sensitive: false,
mentions: [],
quotes: null,
replies_to: null,
subject: "",
});
instanceUrl.hostname,
);
const signedRequest = await sign(
instanceKeys.privateKey,
@ -177,13 +183,16 @@ describe("Inbox Tests", () => {
});
test("should correctly process Share", async () => {
const exampleRequest = new VersiaEntities.Share({
id: shareId,
created_at: "2025-04-18T10:32:01.427Z",
type: "pub.versia:share/Share",
author: userId,
shared: noteId,
});
const exampleRequest = new VersiaEntities.Share(
{
id: shareId,
created_at: "2025-04-18T10:32:01.427Z",
type: "pub.versia:share/Share",
author: userId,
shared: noteId,
},
instanceUrl.hostname,
);
const signedRequest = await sign(
instanceKeys.privateKey,
@ -229,14 +238,17 @@ describe("Inbox Tests", () => {
});
test("should correctly process Reaction", async () => {
const exampleRequest = new VersiaEntities.Reaction({
id: reactionId,
created_at: "2025-04-18T10:32:01.427Z",
type: "pub.versia:reactions/Reaction",
author: userId,
object: noteId,
content: "👍",
});
const exampleRequest = new VersiaEntities.Reaction(
{
id: reactionId,
created_at: "2025-04-18T10:32:01.427Z",
type: "pub.versia:reactions/Reaction",
author: userId,
object: noteId,
content: "👍",
},
instanceUrl.hostname,
);
const signedRequest = await sign(
instanceKeys.privateKey,
@ -304,34 +316,37 @@ describe("Inbox Tests", () => {
});
test("should correctly process Reaction with custom emoji", async () => {
const exampleRequest = new VersiaEntities.Reaction({
id: reaction2Id,
created_at: "2025-04-18T10:32:01.427Z",
type: "pub.versia:reactions/Reaction",
author: userId,
object: noteId,
content: ":neocat:",
extensions: {
"pub.versia:custom_emojis": {
emojis: [
{
name: ":neocat:",
url: {
"image/webp": {
hash: "e06240155d2cb90e8dc05327d023585ab9d47216ff547ad72aaf75c485fe9649",
size: 4664,
width: 256,
height: 256,
remote: true,
content:
"https://cdn.cpluspatch.com/versia-cpp/e06240155d2cb90e8dc05327d023585ab9d47216ff547ad72aaf75c485fe9649/neocat.webp",
const exampleRequest = new VersiaEntities.Reaction(
{
id: reaction2Id,
created_at: "2025-04-18T10:32:01.427Z",
type: "pub.versia:reactions/Reaction",
author: userId,
object: noteId,
content: ":neocat:",
extensions: {
"pub.versia:custom_emojis": {
emojis: [
{
name: ":neocat:",
url: {
"image/webp": {
hash: "e06240155d2cb90e8dc05327d023585ab9d47216ff547ad72aaf75c485fe9649",
size: 4664,
width: 256,
height: 256,
remote: true,
content:
"https://cdn.cpluspatch.com/versia-cpp/e06240155d2cb90e8dc05327d023585ab9d47216ff547ad72aaf75c485fe9649/neocat.webp",
},
},
},
},
],
],
},
},
},
});
instanceUrl.hostname,
);
const signedRequest = await sign(
instanceKeys.privateKey,
@ -405,13 +420,16 @@ describe("Inbox Tests", () => {
expect(noteToDelete).not.toBeNull();
// Create a Delete request
const exampleRequest = new VersiaEntities.Delete({
created_at: new Date().toISOString(),
type: "Delete",
author: userId,
deleted_type: "Note",
deleted: noteId,
});
const exampleRequest = new VersiaEntities.Delete(
{
created_at: new Date().toISOString(),
type: "Delete",
author: userId,
deleted_type: "Note",
deleted: noteId,
},
instanceUrl.hostname,
);
const signedRequest = await sign(
instanceKeys.privateKey,