2023-09-14 05:39:11 +02:00
|
|
|
import { getConfig } from "@config";
|
|
|
|
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
|
|
|
import { AppDataSource } from "~database/datasource";
|
|
|
|
|
import { RawActivity } from "~database/entities/RawActivity";
|
|
|
|
|
import { Token } from "~database/entities/Token";
|
|
|
|
|
import { User } from "~database/entities/User";
|
|
|
|
|
|
|
|
|
|
const config = getConfig();
|
|
|
|
|
|
|
|
|
|
beforeAll(async () => {
|
|
|
|
|
if (!AppDataSource.isInitialized) await AppDataSource.initialize();
|
|
|
|
|
|
|
|
|
|
// Initialize test user
|
2023-10-08 22:20:42 +02:00
|
|
|
await User.createNewLocal({
|
2023-09-22 00:42:59 +02:00
|
|
|
email: "test@test.com",
|
|
|
|
|
username: "test",
|
|
|
|
|
password: "test",
|
|
|
|
|
display_name: "",
|
|
|
|
|
});
|
2023-09-14 05:39:11 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe("POST /@test/inbox", () => {
|
|
|
|
|
test("should store a new Note object", async () => {
|
2023-09-22 00:42:59 +02:00
|
|
|
const activityId = `https://example.com/objects/${crypto.randomUUID()}`;
|
|
|
|
|
|
2023-10-16 20:50:10 +02:00
|
|
|
const response = await fetch(
|
|
|
|
|
`${config.http.base_url}/users/test/inbox/`,
|
|
|
|
|
{
|
|
|
|
|
method: "POST",
|
|
|
|
|
headers: {
|
|
|
|
|
"Content-Type": "application/activity+json",
|
|
|
|
|
Origin: "http://lysand-test.localhost",
|
2023-09-14 05:39:11 +02:00
|
|
|
},
|
2023-10-16 20:50:10 +02:00
|
|
|
body: JSON.stringify({
|
2023-09-14 05:39:11 +02:00
|
|
|
"@context": "https://www.w3.org/ns/activitystreams",
|
2023-10-16 20:50:10 +02:00
|
|
|
type: "Create",
|
|
|
|
|
id: activityId,
|
|
|
|
|
actor: {
|
|
|
|
|
id: `${config.http.base_url}/users/test`,
|
|
|
|
|
type: "Person",
|
|
|
|
|
preferredUsername: "test",
|
|
|
|
|
},
|
|
|
|
|
to: ["https://www.w3.org/ns/activitystreams#Public"],
|
|
|
|
|
cc: [],
|
2023-09-14 05:39:11 +02:00
|
|
|
published: "2021-01-01T00:00:00.000Z",
|
2023-10-16 20:50:10 +02:00
|
|
|
object: {
|
|
|
|
|
"@context": "https://www.w3.org/ns/activitystreams",
|
|
|
|
|
id: "https://example.com/notes/1",
|
|
|
|
|
type: "Note",
|
|
|
|
|
content: "Hello, world!",
|
|
|
|
|
summary: null,
|
|
|
|
|
inReplyTo: null,
|
|
|
|
|
published: "2021-01-01T00:00:00.000Z",
|
|
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
}
|
|
|
|
|
);
|
2023-09-14 05:39:11 +02:00
|
|
|
|
|
|
|
|
expect(response.status).toBe(200);
|
|
|
|
|
expect(response.headers.get("content-type")).toBe("application/json");
|
|
|
|
|
|
2023-09-22 00:42:59 +02:00
|
|
|
const activity = await RawActivity.getLatestById(activityId);
|
2023-09-14 05:39:11 +02:00
|
|
|
|
|
|
|
|
expect(activity).not.toBeUndefined();
|
|
|
|
|
expect(activity?.data).toEqual({
|
|
|
|
|
"@context": "https://www.w3.org/ns/activitystreams",
|
|
|
|
|
type: "Create",
|
2023-09-22 00:42:59 +02:00
|
|
|
id: activityId,
|
2023-09-14 05:39:11 +02:00
|
|
|
to: ["https://www.w3.org/ns/activitystreams#Public"],
|
|
|
|
|
cc: [],
|
|
|
|
|
published: "2021-01-01T00:00:00.000Z",
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
expect(activity?.objects).toHaveLength(1);
|
|
|
|
|
expect(activity?.objects[0].data).toEqual({
|
|
|
|
|
"@context": "https://www.w3.org/ns/activitystreams",
|
|
|
|
|
id: "https://example.com/notes/1",
|
|
|
|
|
type: "Note",
|
|
|
|
|
content: "Hello, world!",
|
|
|
|
|
summary: null,
|
|
|
|
|
inReplyTo: null,
|
|
|
|
|
published: "2021-01-01T00:00:00.000Z",
|
|
|
|
|
});
|
|
|
|
|
});
|
2023-09-14 08:12:54 +02:00
|
|
|
|
|
|
|
|
test("should try to update that Note object", async () => {
|
2023-09-22 00:42:59 +02:00
|
|
|
const activityId = `https://example.com/objects/${crypto.randomUUID()}`;
|
|
|
|
|
|
2023-10-16 20:50:10 +02:00
|
|
|
const response = await fetch(
|
|
|
|
|
`${config.http.base_url}/users/test/inbox/`,
|
|
|
|
|
{
|
|
|
|
|
method: "POST",
|
|
|
|
|
headers: {
|
|
|
|
|
"Content-Type": "application/activity+json",
|
|
|
|
|
Origin: "http://lysand-test.localhost",
|
2023-09-14 08:12:54 +02:00
|
|
|
},
|
2023-10-16 20:50:10 +02:00
|
|
|
body: JSON.stringify({
|
2023-09-14 08:12:54 +02:00
|
|
|
"@context": "https://www.w3.org/ns/activitystreams",
|
2023-10-16 20:50:10 +02:00
|
|
|
type: "Update",
|
|
|
|
|
id: activityId,
|
|
|
|
|
actor: {
|
|
|
|
|
id: `${config.http.base_url}/users/test`,
|
|
|
|
|
type: "Person",
|
|
|
|
|
preferredUsername: "test",
|
|
|
|
|
},
|
|
|
|
|
to: ["https://www.w3.org/ns/activitystreams#Public"],
|
|
|
|
|
cc: [],
|
|
|
|
|
published: "2021-01-02T00:00:00.000Z",
|
|
|
|
|
object: {
|
|
|
|
|
"@context": "https://www.w3.org/ns/activitystreams",
|
|
|
|
|
id: "https://example.com/notes/1",
|
|
|
|
|
type: "Note",
|
|
|
|
|
content: "This note has been edited!",
|
|
|
|
|
summary: null,
|
|
|
|
|
inReplyTo: null,
|
|
|
|
|
published: "2021-01-01T00:00:00.000Z",
|
|
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
}
|
|
|
|
|
);
|
2023-09-14 08:12:54 +02:00
|
|
|
|
|
|
|
|
expect(response.status).toBe(200);
|
|
|
|
|
expect(response.headers.get("content-type")).toBe("application/json");
|
|
|
|
|
|
2023-09-22 00:42:59 +02:00
|
|
|
const activity = await RawActivity.getLatestById(activityId);
|
2023-09-14 08:12:54 +02:00
|
|
|
|
|
|
|
|
expect(activity).not.toBeUndefined();
|
|
|
|
|
expect(activity?.data).toEqual({
|
|
|
|
|
"@context": "https://www.w3.org/ns/activitystreams",
|
|
|
|
|
type: "Update",
|
2023-09-22 00:42:59 +02:00
|
|
|
id: activityId,
|
2023-09-14 08:12:54 +02:00
|
|
|
to: ["https://www.w3.org/ns/activitystreams#Public"],
|
|
|
|
|
cc: [],
|
|
|
|
|
published: "2021-01-02T00:00:00.000Z",
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
expect(activity?.objects).toHaveLength(1);
|
|
|
|
|
expect(activity?.objects[0].data).toEqual({
|
|
|
|
|
"@context": "https://www.w3.org/ns/activitystreams",
|
|
|
|
|
id: "https://example.com/notes/1",
|
|
|
|
|
type: "Note",
|
|
|
|
|
content: "This note has been edited!",
|
|
|
|
|
summary: null,
|
|
|
|
|
inReplyTo: null,
|
|
|
|
|
published: "2021-01-01T00:00:00.000Z",
|
|
|
|
|
});
|
|
|
|
|
});
|
2023-09-15 03:22:27 +02:00
|
|
|
|
|
|
|
|
test("should delete the Note object", async () => {
|
2023-09-22 00:42:59 +02:00
|
|
|
const activityId = `https://example.com/objects/${crypto.randomUUID()}`;
|
2023-10-16 20:50:10 +02:00
|
|
|
const response = await fetch(
|
|
|
|
|
`${config.http.base_url}/users/test/inbox/`,
|
|
|
|
|
{
|
|
|
|
|
method: "POST",
|
|
|
|
|
headers: {
|
|
|
|
|
"Content-Type": "application/activity+json",
|
|
|
|
|
Origin: "http://lysand-test.localhost",
|
2023-09-15 03:22:27 +02:00
|
|
|
},
|
2023-10-16 20:50:10 +02:00
|
|
|
body: JSON.stringify({
|
2023-09-15 03:22:27 +02:00
|
|
|
"@context": "https://www.w3.org/ns/activitystreams",
|
2023-10-16 20:50:10 +02:00
|
|
|
type: "Delete",
|
|
|
|
|
id: activityId,
|
|
|
|
|
actor: {
|
|
|
|
|
id: `${config.http.base_url}/users/test`,
|
|
|
|
|
type: "Person",
|
|
|
|
|
preferredUsername: "test",
|
|
|
|
|
},
|
|
|
|
|
to: ["https://www.w3.org/ns/activitystreams#Public"],
|
|
|
|
|
cc: [],
|
|
|
|
|
published: "2021-01-03T00:00:00.000Z",
|
|
|
|
|
object: {
|
|
|
|
|
"@context": "https://www.w3.org/ns/activitystreams",
|
|
|
|
|
id: "https://example.com/notes/1",
|
|
|
|
|
type: "Note",
|
|
|
|
|
content: "This note has been edited!",
|
|
|
|
|
summary: null,
|
|
|
|
|
inReplyTo: null,
|
|
|
|
|
published: "2021-01-01T00:00:00.000Z",
|
|
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
}
|
|
|
|
|
);
|
2023-09-15 03:22:27 +02:00
|
|
|
|
|
|
|
|
expect(response.status).toBe(200);
|
|
|
|
|
expect(response.headers.get("content-type")).toBe("application/json");
|
|
|
|
|
|
2023-09-22 00:42:59 +02:00
|
|
|
const activity = await RawActivity.getLatestById(activityId);
|
2023-09-15 03:22:27 +02:00
|
|
|
|
|
|
|
|
expect(activity).not.toBeUndefined();
|
|
|
|
|
expect(activity?.data).toEqual({
|
|
|
|
|
"@context": "https://www.w3.org/ns/activitystreams",
|
|
|
|
|
type: "Delete",
|
2023-09-22 00:42:59 +02:00
|
|
|
id: activityId,
|
2023-09-15 03:22:27 +02:00
|
|
|
to: ["https://www.w3.org/ns/activitystreams#Public"],
|
|
|
|
|
cc: [],
|
|
|
|
|
published: "2021-01-03T00:00:00.000Z",
|
|
|
|
|
});
|
|
|
|
|
|
2023-09-22 00:42:59 +02:00
|
|
|
expect(activity?.actors).toHaveLength(1);
|
|
|
|
|
expect(activity?.actors[0].data).toEqual({
|
|
|
|
|
preferredUsername: "test",
|
2023-10-16 08:04:03 +02:00
|
|
|
id: `${config.http.base_url}/users/test`,
|
2023-09-27 01:08:05 +02:00
|
|
|
summary: "",
|
|
|
|
|
publicKey: {
|
2023-10-16 08:04:03 +02:00
|
|
|
id: `${config.http.base_url}/users/test/actor#main-key`,
|
|
|
|
|
owner: `${config.http.base_url}/users/test/actor`,
|
2023-09-27 01:08:05 +02:00
|
|
|
publicKeyPem: expect.any(String),
|
|
|
|
|
},
|
2023-10-16 08:04:03 +02:00
|
|
|
outbox: `${config.http.base_url}/users/test/outbox`,
|
2023-09-27 01:08:05 +02:00
|
|
|
manuallyApprovesFollowers: false,
|
2023-10-16 08:04:03 +02:00
|
|
|
followers: `${config.http.base_url}/users/test/followers`,
|
|
|
|
|
following: `${config.http.base_url}/users/test/following`,
|
2023-10-19 21:53:59 +02:00
|
|
|
published: expect.any(String),
|
2023-09-27 01:08:05 +02:00
|
|
|
name: "",
|
|
|
|
|
"@context": [
|
|
|
|
|
"https://www.w3.org/ns/activitystreams",
|
|
|
|
|
"https://w3id.org/security/v1",
|
|
|
|
|
],
|
|
|
|
|
icon: {
|
|
|
|
|
type: "Image",
|
2023-10-19 21:53:59 +02:00
|
|
|
url: expect.any(String),
|
2023-09-27 01:08:05 +02:00
|
|
|
},
|
|
|
|
|
image: {
|
|
|
|
|
type: "Image",
|
2023-10-19 21:53:59 +02:00
|
|
|
url: expect.any(String),
|
2023-09-27 01:08:05 +02:00
|
|
|
},
|
2023-10-16 08:04:03 +02:00
|
|
|
inbox: `${config.http.base_url}/users/test/inbox`,
|
2023-09-22 00:42:59 +02:00
|
|
|
type: "Person",
|
|
|
|
|
});
|
|
|
|
|
|
2023-09-15 05:42:52 +02:00
|
|
|
// Can be 0 or 1 length depending on whether config.activitypub.use_tombstone is true or false
|
|
|
|
|
if (config.activitypub.use_tombstones) {
|
|
|
|
|
expect(activity?.objects).toHaveLength(1);
|
|
|
|
|
} else {
|
|
|
|
|
expect(activity?.objects).toHaveLength(0);
|
|
|
|
|
}
|
2023-09-15 03:22:27 +02:00
|
|
|
});
|
2023-09-22 00:42:59 +02:00
|
|
|
|
|
|
|
|
test("should return a 404 error when trying to delete a non-existent Note object", async () => {
|
|
|
|
|
const activityId = `https://example.com/objects/${crypto.randomUUID()}`;
|
|
|
|
|
|
2023-10-16 20:50:10 +02:00
|
|
|
const response = await fetch(
|
|
|
|
|
`${config.http.base_url}/users/test/inbox/`,
|
|
|
|
|
{
|
|
|
|
|
method: "POST",
|
|
|
|
|
headers: {
|
|
|
|
|
"Content-Type": "application/activity+json",
|
|
|
|
|
Origin: "http://lysand-test.localhost",
|
2023-09-22 00:42:59 +02:00
|
|
|
},
|
2023-10-16 20:50:10 +02:00
|
|
|
body: JSON.stringify({
|
2023-09-22 00:42:59 +02:00
|
|
|
"@context": "https://www.w3.org/ns/activitystreams",
|
2023-10-16 20:50:10 +02:00
|
|
|
type: "Delete",
|
|
|
|
|
id: activityId,
|
|
|
|
|
actor: {
|
|
|
|
|
id: `${config.http.base_url}/users/test`,
|
|
|
|
|
type: "Person",
|
|
|
|
|
preferredUsername: "test",
|
|
|
|
|
},
|
|
|
|
|
to: ["https://www.w3.org/ns/activitystreams#Public"],
|
|
|
|
|
cc: [],
|
|
|
|
|
published: "2021-01-03T00:00:00.000Z",
|
|
|
|
|
object: {
|
|
|
|
|
"@context": "https://www.w3.org/ns/activitystreams",
|
|
|
|
|
id: "https://example.com/notes/2345678909876543",
|
|
|
|
|
type: "Note",
|
|
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
}
|
|
|
|
|
);
|
2023-09-22 00:42:59 +02:00
|
|
|
|
|
|
|
|
expect(response.status).toBe(404);
|
|
|
|
|
expect(response.headers.get("content-type")).toBe("application/json");
|
|
|
|
|
});
|
2023-09-14 05:39:11 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
afterAll(async () => {
|
|
|
|
|
// Clean up user
|
|
|
|
|
const user = await User.findOneBy({
|
|
|
|
|
username: "test",
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Clean up tokens
|
|
|
|
|
const tokens = await Token.findBy({
|
|
|
|
|
user: {
|
|
|
|
|
username: "test",
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const activities = await RawActivity.createQueryBuilder("activity")
|
2023-09-22 00:42:59 +02:00
|
|
|
// Join objects
|
2023-09-14 05:39:11 +02:00
|
|
|
.leftJoinAndSelect("activity.objects", "objects")
|
2023-09-22 00:42:59 +02:00
|
|
|
.leftJoinAndSelect("activity.actors", "actors")
|
|
|
|
|
// activity.actors is a many-to-many relationship with Actor objects (it is an array of Actor objects)
|
2023-10-16 08:04:03 +02:00
|
|
|
// Get the actors of the activity that have data.id as `${config.http.base_url}/users/test`
|
2023-09-22 00:42:59 +02:00
|
|
|
.where("actors.data @> :data", {
|
|
|
|
|
data: JSON.stringify({
|
2023-10-16 08:04:03 +02:00
|
|
|
id: `${config.http.base_url}/users/test`,
|
2023-09-22 00:42:59 +02:00
|
|
|
}),
|
|
|
|
|
})
|
2023-09-14 05:39:11 +02:00
|
|
|
.getMany();
|
|
|
|
|
|
|
|
|
|
// Delete all created objects and activities as part of testing
|
|
|
|
|
await Promise.all(
|
|
|
|
|
activities.map(async activity => {
|
|
|
|
|
await Promise.all(
|
|
|
|
|
activity.objects.map(async object => await object.remove())
|
|
|
|
|
);
|
|
|
|
|
await activity.remove();
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await Promise.all(tokens.map(async token => await token.remove()));
|
|
|
|
|
|
|
|
|
|
if (user) await user.remove();
|
2023-10-19 21:53:59 +02:00
|
|
|
|
|
|
|
|
await AppDataSource.destroy();
|
2023-09-14 05:39:11 +02:00
|
|
|
});
|