mirror of
https://github.com/versia-pub/server.git
synced 2026-03-13 05:49:16 +01:00
Purge ActivityPub from project to start implementing Lysand
This commit is contained in:
parent
3e86ffbf2d
commit
02b56f8fde
13 changed files with 9 additions and 1357 deletions
|
|
@ -1,97 +1 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { getConfig } from "@config";
|
||||
import { APActor } from "activitypub-types";
|
||||
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
||||
import { AppDataSource } from "~database/datasource";
|
||||
import { RawActivity } from "~database/entities/RawActivity";
|
||||
import { User, userRelations } from "~database/entities/User";
|
||||
|
||||
const config = getConfig();
|
||||
|
||||
beforeAll(async () => {
|
||||
if (!AppDataSource.isInitialized) await AppDataSource.initialize();
|
||||
|
||||
// Initialize test user
|
||||
await User.createNewLocal({
|
||||
email: "test@test.com",
|
||||
username: "test",
|
||||
password: "test",
|
||||
display_name: "",
|
||||
});
|
||||
});
|
||||
|
||||
describe("POST /@test/actor", () => {
|
||||
test("should return a valid ActivityPub Actor when querying an existing user", async () => {
|
||||
const response = await fetch(
|
||||
`${config.http.base_url}/users/test/actor`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
Accept: "application/activity+json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.headers.get("content-type")).toBe(
|
||||
"application/activity+json"
|
||||
);
|
||||
|
||||
const actor = (await response.json()) as APActor;
|
||||
|
||||
expect(actor.type).toBe("Person");
|
||||
expect(actor.id).toBe(`${config.http.base_url}/users/test`);
|
||||
expect(actor.preferredUsername).toBe("test");
|
||||
expect(actor.inbox).toBe(`${config.http.base_url}/users/test/inbox`);
|
||||
expect(actor.outbox).toBe(`${config.http.base_url}/users/test/outbox`);
|
||||
expect(actor.followers).toBe(
|
||||
`${config.http.base_url}/users/test/followers`
|
||||
);
|
||||
expect(actor.following).toBe(
|
||||
`${config.http.base_url}/users/test/following`
|
||||
);
|
||||
expect((actor as any).publicKey).toBeDefined();
|
||||
expect((actor as any).publicKey.id).toBeDefined();
|
||||
expect((actor as any).publicKey.owner).toBe(
|
||||
`${config.http.base_url}/users/test`
|
||||
);
|
||||
expect((actor as any).publicKey.publicKeyPem).toBeDefined();
|
||||
expect((actor as any).publicKey.publicKeyPem).toMatch(
|
||||
/(-----BEGIN PUBLIC KEY-----(\n|\r|\r\n)([0-9a-zA-Z+/=]{64}(\n|\r|\r\n))*([0-9a-zA-Z+/=]{1,63}(\n|\r|\r\n))?-----END PUBLIC KEY-----)|(-----BEGIN PRIVATE KEY-----(\n|\r|\r\n)([0-9a-zA-Z+/=]{64}(\n|\r|\r\n))*([0-9a-zA-Z+/=]{1,63}(\n|\r|\r\n))?-----END PRIVATE KEY-----)/
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// Clean up user
|
||||
const user = await User.findOne({
|
||||
where: {
|
||||
username: "test",
|
||||
},
|
||||
relations: userRelations,
|
||||
});
|
||||
|
||||
const activities = await RawActivity.createQueryBuilder("activity")
|
||||
.where("activity.data->>'actor' = :actor", {
|
||||
actor: `${config.http.base_url}/users/test`,
|
||||
})
|
||||
.leftJoinAndSelect("activity.objects", "objects")
|
||||
.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();
|
||||
})
|
||||
);
|
||||
|
||||
if (user) {
|
||||
await user.remove();
|
||||
}
|
||||
|
||||
await AppDataSource.destroy();
|
||||
});
|
||||
// Empty file
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|||
import { AppDataSource } from "~database/datasource";
|
||||
import { Application } from "~database/entities/Application";
|
||||
import { Emoji } from "~database/entities/Emoji";
|
||||
import { RawActivity } from "~database/entities/RawActivity";
|
||||
import { Token, TokenType } from "~database/entities/Token";
|
||||
import { User } from "~database/entities/User";
|
||||
import { APIEmoji } from "~types/entities/emoji";
|
||||
|
|
@ -63,21 +62,6 @@ describe("API Tests", () => {
|
|||
});
|
||||
|
||||
afterAll(async () => {
|
||||
const activities = await RawActivity.createQueryBuilder("activity")
|
||||
.where("activity.data->>'actor' = :actor", {
|
||||
actor: `${config.http.base_url}/users/test`,
|
||||
})
|
||||
.leftJoinAndSelect("activity.objects", "objects")
|
||||
.getMany();
|
||||
|
||||
// Delete all created objects and activities as part of testing
|
||||
for (const activity of activities) {
|
||||
for (const object of activity.objects) {
|
||||
await object.remove();
|
||||
}
|
||||
await activity.remove();
|
||||
}
|
||||
|
||||
await user.remove();
|
||||
await user2.remove();
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import { getConfig } from "@config";
|
|||
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
||||
import { AppDataSource } from "~database/datasource";
|
||||
import { Application } from "~database/entities/Application";
|
||||
import { RawActivity } from "~database/entities/RawActivity";
|
||||
import { Token, TokenType } from "~database/entities/Token";
|
||||
import { User } from "~database/entities/User";
|
||||
import { APIAccount } from "~types/entities/account";
|
||||
|
|
@ -63,21 +62,6 @@ describe("API Tests", () => {
|
|||
});
|
||||
|
||||
afterAll(async () => {
|
||||
const activities = await RawActivity.createQueryBuilder("activity")
|
||||
.where("activity.data->>'actor' = :actor", {
|
||||
actor: `${config.http.base_url}/users/test`,
|
||||
})
|
||||
.leftJoinAndSelect("activity.objects", "objects")
|
||||
.getMany();
|
||||
|
||||
// Delete all created objects and activities as part of testing
|
||||
for (const activity of activities) {
|
||||
for (const object of activity.objects) {
|
||||
await object.remove();
|
||||
}
|
||||
await activity.remove();
|
||||
}
|
||||
|
||||
await user.remove();
|
||||
await user2.remove();
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import { getConfig } from "@config";
|
|||
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
||||
import { AppDataSource } from "~database/datasource";
|
||||
import { Application } from "~database/entities/Application";
|
||||
import { RawActivity } from "~database/entities/RawActivity";
|
||||
import { Token, TokenType } from "~database/entities/Token";
|
||||
import { User } from "~database/entities/User";
|
||||
import { APIContext } from "~types/entities/context";
|
||||
|
|
@ -64,21 +63,6 @@ describe("API Tests", () => {
|
|||
});
|
||||
|
||||
afterAll(async () => {
|
||||
const activities = await RawActivity.createQueryBuilder("activity")
|
||||
.where("activity.data->>'actor' = :actor", {
|
||||
actor: `${config.http.base_url}/users/test`,
|
||||
})
|
||||
.leftJoinAndSelect("activity.objects", "objects")
|
||||
.getMany();
|
||||
|
||||
// Delete all created objects and activities as part of testing
|
||||
for (const activity of activities) {
|
||||
for (const object of activity.objects) {
|
||||
await object.remove();
|
||||
}
|
||||
await activity.remove();
|
||||
}
|
||||
|
||||
await user.remove();
|
||||
await user2.remove();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,320 +1 @@
|
|||
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, userRelations } from "~database/entities/User";
|
||||
|
||||
const config = getConfig();
|
||||
|
||||
beforeAll(async () => {
|
||||
if (!AppDataSource.isInitialized) await AppDataSource.initialize();
|
||||
|
||||
// Initialize test user
|
||||
await User.createNewLocal({
|
||||
email: "test@test.com",
|
||||
username: "test",
|
||||
password: "test",
|
||||
display_name: "",
|
||||
});
|
||||
});
|
||||
|
||||
describe("POST /@test/inbox", () => {
|
||||
test("should store a new Note object", async () => {
|
||||
const activityId = `https://example.com/objects/${crypto.randomUUID()}`;
|
||||
|
||||
const response = await fetch(
|
||||
`${config.http.base_url}/users/test/inbox/`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/activity+json",
|
||||
Origin: "http://lysand-test.localhost",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
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: [],
|
||||
published: "2021-01-01T00:00:00.000Z",
|
||||
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",
|
||||
},
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.headers.get("content-type")).toBe("application/json");
|
||||
|
||||
const activity = await RawActivity.getLatestById(activityId);
|
||||
|
||||
expect(activity).not.toBeUndefined();
|
||||
expect(activity?.data).toEqual({
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
type: "Create",
|
||||
id: activityId,
|
||||
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",
|
||||
});
|
||||
});
|
||||
|
||||
test("should try to update that Note object", async () => {
|
||||
const activityId = `https://example.com/objects/${crypto.randomUUID()}`;
|
||||
|
||||
const response = await fetch(
|
||||
`${config.http.base_url}/users/test/inbox/`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/activity+json",
|
||||
Origin: "http://lysand-test.localhost",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
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",
|
||||
},
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.headers.get("content-type")).toBe("application/json");
|
||||
|
||||
const activity = await RawActivity.getLatestById(activityId);
|
||||
|
||||
expect(activity).not.toBeUndefined();
|
||||
expect(activity?.data).toEqual({
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
type: "Update",
|
||||
id: activityId,
|
||||
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",
|
||||
});
|
||||
});
|
||||
|
||||
test("should delete the Note object", async () => {
|
||||
const activityId = `https://example.com/objects/${crypto.randomUUID()}`;
|
||||
const response = await fetch(
|
||||
`${config.http.base_url}/users/test/inbox/`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/activity+json",
|
||||
Origin: "http://lysand-test.localhost",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
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",
|
||||
},
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.headers.get("content-type")).toBe("application/json");
|
||||
|
||||
const activity = await RawActivity.getLatestById(activityId);
|
||||
|
||||
expect(activity).not.toBeUndefined();
|
||||
expect(activity?.data).toEqual({
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
type: "Delete",
|
||||
id: activityId,
|
||||
to: ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
cc: [],
|
||||
published: "2021-01-03T00:00:00.000Z",
|
||||
});
|
||||
|
||||
expect(activity?.actors).toHaveLength(1);
|
||||
expect(activity?.actors[0].data).toEqual({
|
||||
preferredUsername: "test",
|
||||
id: `${config.http.base_url}/users/test`,
|
||||
summary: "",
|
||||
publicKey: {
|
||||
id: `${config.http.base_url}/users/test/actor#main-key`,
|
||||
owner: `${config.http.base_url}/users/test/actor`,
|
||||
publicKeyPem: expect.any(String),
|
||||
},
|
||||
outbox: `${config.http.base_url}/users/test/outbox`,
|
||||
manuallyApprovesFollowers: false,
|
||||
followers: `${config.http.base_url}/users/test/followers`,
|
||||
following: `${config.http.base_url}/users/test/following`,
|
||||
published: expect.any(String),
|
||||
name: "",
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
],
|
||||
icon: {
|
||||
type: "Image",
|
||||
url: expect.any(String),
|
||||
},
|
||||
image: {
|
||||
type: "Image",
|
||||
url: expect.any(String),
|
||||
},
|
||||
inbox: `${config.http.base_url}/users/test/inbox`,
|
||||
type: "Person",
|
||||
});
|
||||
|
||||
// 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);
|
||||
}
|
||||
});
|
||||
|
||||
test("should return a 404 error when trying to delete a non-existent Note object", async () => {
|
||||
const activityId = `https://example.com/objects/${crypto.randomUUID()}`;
|
||||
|
||||
const response = await fetch(
|
||||
`${config.http.base_url}/users/test/inbox/`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/activity+json",
|
||||
Origin: "http://lysand-test.localhost",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
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",
|
||||
},
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
expect(response.status).toBe(404);
|
||||
expect(response.headers.get("content-type")).toBe("application/json");
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// Clean up user
|
||||
const user = await User.findOne({
|
||||
where: {
|
||||
username: "test",
|
||||
},
|
||||
relations: userRelations,
|
||||
});
|
||||
|
||||
// Clean up tokens
|
||||
const tokens = await Token.findBy({
|
||||
user: {
|
||||
username: "test",
|
||||
},
|
||||
});
|
||||
|
||||
const activities = await RawActivity.createQueryBuilder("activity")
|
||||
// Join objects
|
||||
.leftJoinAndSelect("activity.objects", "objects")
|
||||
.leftJoinAndSelect("activity.actors", "actors")
|
||||
// activity.actors is a many-to-many relationship with Actor objects (it is an array of Actor objects)
|
||||
// Get the actors of the activity that have data.id as `${config.http.base_url}/users/test`
|
||||
.where("actors.data @> :data", {
|
||||
data: JSON.stringify({
|
||||
id: `${config.http.base_url}/users/test`,
|
||||
}),
|
||||
})
|
||||
.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();
|
||||
|
||||
await AppDataSource.destroy();
|
||||
});
|
||||
// Empty file
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue