mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 08:28:19 +01:00
115 lines
2.6 KiB
TypeScript
115 lines
2.6 KiB
TypeScript
import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from "typeorm";
|
|
import { APActor } from "activitypub-types";
|
|
import { getConfig } from "@config";
|
|
import { appendFile } from "fs/promises";
|
|
import { errorResponse } from "@response";
|
|
|
|
/**
|
|
* Stores an ActivityPub actor as raw JSON-LD data
|
|
*/
|
|
@Entity({
|
|
name: "actors",
|
|
})
|
|
export class RawActor extends BaseEntity {
|
|
@PrimaryGeneratedColumn("uuid")
|
|
id!: string;
|
|
|
|
@Column("jsonb")
|
|
data!: APActor;
|
|
|
|
static async getById(id: string) {
|
|
return await RawActor.createQueryBuilder("actor")
|
|
.where("actor.data->>'id' = :id", {
|
|
id,
|
|
})
|
|
.getOne();
|
|
}
|
|
|
|
static async addIfNotExists(data: APActor) {
|
|
if (!(await RawActor.exists(data.id ?? ""))) {
|
|
const actor = new RawActor();
|
|
actor.data = data;
|
|
|
|
const config = getConfig();
|
|
|
|
if (
|
|
config.activitypub.discard_avatars.find(instance =>
|
|
actor.id.includes(instance)
|
|
)
|
|
) {
|
|
actor.data.icon = undefined;
|
|
}
|
|
|
|
if (
|
|
config.activitypub.discard_banners.find(instance =>
|
|
actor.id.includes(instance)
|
|
)
|
|
) {
|
|
actor.data.image = undefined;
|
|
}
|
|
|
|
if (await actor.isObjectFiltered()) {
|
|
return errorResponse("Actor filtered", 409);
|
|
}
|
|
|
|
await actor.save();
|
|
|
|
return actor;
|
|
}
|
|
return errorResponse("Actor already exists", 409);
|
|
}
|
|
|
|
async isObjectFiltered() {
|
|
const config = getConfig();
|
|
|
|
const usernameFilterResult = await Promise.all(
|
|
config.filters.username_filters.map(async filter => {
|
|
if (
|
|
this.data.type === "Person" &&
|
|
this.data.preferredUsername?.match(filter)
|
|
) {
|
|
// Log filter
|
|
|
|
if (config.logging.log_filters)
|
|
await appendFile(
|
|
process.cwd() + "/logs/filters.log",
|
|
`${new Date().toISOString()} Filtered actor username: "${
|
|
this.data.preferredUsername
|
|
}" (ID: ${this.data.id}) based on rule: ${filter}\n`
|
|
);
|
|
return true;
|
|
}
|
|
})
|
|
);
|
|
|
|
const displayNameFilterResult = await Promise.all(
|
|
config.filters.displayname_filters.map(async filter => {
|
|
if (
|
|
this.data.type === "Person" &&
|
|
this.data.name?.match(filter)
|
|
) {
|
|
// Log filter
|
|
|
|
if (config.logging.log_filters)
|
|
await appendFile(
|
|
process.cwd() + "/logs/filters.log",
|
|
`${new Date().toISOString()} Filtered actor username: "${
|
|
this.data.preferredUsername
|
|
}" (ID: ${this.data.id}) based on rule: ${filter}\n`
|
|
);
|
|
return true;
|
|
}
|
|
})
|
|
);
|
|
|
|
return (
|
|
usernameFilterResult.includes(true) ||
|
|
displayNameFilterResult.includes(true)
|
|
);
|
|
}
|
|
|
|
static async exists(id: string) {
|
|
return !!(await RawActor.getById(id));
|
|
}
|
|
}
|