mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 16:38:19 +01:00
fix(api): 🐛 Don't use URL in Versia entity schemas, fixes OpenAPI
This commit is contained in:
parent
0a712128a5
commit
a2e907390f
|
|
@ -86,11 +86,11 @@ export default apiRoute((app) =>
|
||||||
);
|
);
|
||||||
|
|
||||||
const uriCollection = new VersiaEntities.URICollection({
|
const uriCollection = new VersiaEntities.URICollection({
|
||||||
author: note.author.uri,
|
author: note.author.uri.href,
|
||||||
first: new URL(
|
first: new URL(
|
||||||
`/notes/${note.id}/quotes?offset=0`,
|
`/notes/${note.id}/quotes?offset=0`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
),
|
).href,
|
||||||
last:
|
last:
|
||||||
replyCount > limit
|
replyCount > limit
|
||||||
? new URL(
|
? new URL(
|
||||||
|
|
@ -98,11 +98,11 @@ export default apiRoute((app) =>
|
||||||
replyCount - limit
|
replyCount - limit
|
||||||
}`,
|
}`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
)
|
).href
|
||||||
: new URL(
|
: new URL(
|
||||||
`/notes/${note.id}/quotes`,
|
`/notes/${note.id}/quotes`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
),
|
).href,
|
||||||
next:
|
next:
|
||||||
offset + limit < replyCount
|
offset + limit < replyCount
|
||||||
? new URL(
|
? new URL(
|
||||||
|
|
@ -110,7 +110,7 @@ export default apiRoute((app) =>
|
||||||
offset + limit
|
offset + limit
|
||||||
}`,
|
}`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
)
|
).href
|
||||||
: null,
|
: null,
|
||||||
previous:
|
previous:
|
||||||
offset - limit >= 0
|
offset - limit >= 0
|
||||||
|
|
@ -119,10 +119,10 @@ export default apiRoute((app) =>
|
||||||
offset - limit
|
offset - limit
|
||||||
}`,
|
}`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
)
|
).href
|
||||||
: null,
|
: null,
|
||||||
total: replyCount,
|
total: replyCount,
|
||||||
items: replies.map((reply) => reply.getUri()),
|
items: replies.map((reply) => reply.getUri().href),
|
||||||
});
|
});
|
||||||
|
|
||||||
// If base_url uses https and request uses http, rewrite request to use https
|
// If base_url uses https and request uses http, rewrite request to use https
|
||||||
|
|
|
||||||
|
|
@ -84,11 +84,11 @@ export default apiRoute((app) =>
|
||||||
);
|
);
|
||||||
|
|
||||||
const uriCollection = new VersiaEntities.URICollection({
|
const uriCollection = new VersiaEntities.URICollection({
|
||||||
author: note.author.uri,
|
author: note.author.uri.href,
|
||||||
first: new URL(
|
first: new URL(
|
||||||
`/notes/${note.id}/replies?offset=0`,
|
`/notes/${note.id}/replies?offset=0`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
),
|
).href,
|
||||||
last:
|
last:
|
||||||
replyCount > limit
|
replyCount > limit
|
||||||
? new URL(
|
? new URL(
|
||||||
|
|
@ -96,11 +96,11 @@ export default apiRoute((app) =>
|
||||||
replyCount - limit
|
replyCount - limit
|
||||||
}`,
|
}`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
)
|
).href
|
||||||
: new URL(
|
: new URL(
|
||||||
`/notes/${note.id}/replies`,
|
`/notes/${note.id}/replies`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
),
|
).href,
|
||||||
next:
|
next:
|
||||||
offset + limit < replyCount
|
offset + limit < replyCount
|
||||||
? new URL(
|
? new URL(
|
||||||
|
|
@ -108,7 +108,7 @@ export default apiRoute((app) =>
|
||||||
offset + limit
|
offset + limit
|
||||||
}`,
|
}`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
)
|
).href
|
||||||
: null,
|
: null,
|
||||||
previous:
|
previous:
|
||||||
offset - limit >= 0
|
offset - limit >= 0
|
||||||
|
|
@ -117,10 +117,10 @@ export default apiRoute((app) =>
|
||||||
offset - limit
|
offset - limit
|
||||||
}`,
|
}`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
)
|
).href
|
||||||
: null,
|
: null,
|
||||||
total: replyCount,
|
total: replyCount,
|
||||||
items: replies.map((reply) => reply.getUri()),
|
items: replies.map((reply) => reply.getUri().href),
|
||||||
});
|
});
|
||||||
|
|
||||||
// If base_url uses https and request uses http, rewrite request to use https
|
// If base_url uses https and request uses http, rewrite request to use https
|
||||||
|
|
|
||||||
|
|
@ -98,28 +98,28 @@ export default apiRoute((app) =>
|
||||||
first: new URL(
|
first: new URL(
|
||||||
`/users/${uuid}/outbox?page=1`,
|
`/users/${uuid}/outbox?page=1`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
),
|
).href,
|
||||||
last: new URL(
|
last: new URL(
|
||||||
`/users/${uuid}/outbox?page=${Math.ceil(
|
`/users/${uuid}/outbox?page=${Math.ceil(
|
||||||
totalNotes / NOTES_PER_PAGE,
|
totalNotes / NOTES_PER_PAGE,
|
||||||
)}`,
|
)}`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
),
|
).href,
|
||||||
total: totalNotes,
|
total: totalNotes,
|
||||||
author: author.uri,
|
author: author.uri.href,
|
||||||
next:
|
next:
|
||||||
notes.length === NOTES_PER_PAGE
|
notes.length === NOTES_PER_PAGE
|
||||||
? new URL(
|
? new URL(
|
||||||
`/users/${uuid}/outbox?page=${pageNumber + 1}`,
|
`/users/${uuid}/outbox?page=${pageNumber + 1}`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
)
|
).href
|
||||||
: null,
|
: null,
|
||||||
previous:
|
previous:
|
||||||
pageNumber > 1
|
pageNumber > 1
|
||||||
? new URL(
|
? new URL(
|
||||||
`/users/${uuid}/outbox?page=${pageNumber - 1}`,
|
`/users/${uuid}/outbox?page=${pageNumber - 1}`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
)
|
).href
|
||||||
: null,
|
: null,
|
||||||
items: notes.map((note) => note.toVersia()),
|
items: notes.map((note) => note.toVersia()),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -306,7 +306,7 @@ export class Instance extends BaseInterface<typeof Instances> {
|
||||||
logo: metadata.data.logo,
|
logo: metadata.data.logo,
|
||||||
protocol,
|
protocol,
|
||||||
publicKey: metadata.data.public_key,
|
publicKey: metadata.data.public_key,
|
||||||
inbox: metadata.data.shared_inbox?.href ?? null,
|
inbox: metadata.data.shared_inbox ?? null,
|
||||||
extensions: metadata.data.extensions ?? null,
|
extensions: metadata.data.extensions ?? null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -333,7 +333,7 @@ export class Instance extends BaseInterface<typeof Instances> {
|
||||||
logo: metadata.data.logo,
|
logo: metadata.data.logo,
|
||||||
protocol,
|
protocol,
|
||||||
publicKey: metadata.data.public_key,
|
publicKey: metadata.data.public_key,
|
||||||
inbox: metadata.data.shared_inbox?.href ?? null,
|
inbox: metadata.data.shared_inbox ?? null,
|
||||||
extensions: metadata.data.extensions ?? null,
|
extensions: metadata.data.extensions ?? null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -155,13 +155,14 @@ export class Like extends BaseInterface<typeof Likes, LikeType> {
|
||||||
author: User.getUri(
|
author: User.getUri(
|
||||||
this.data.liker.id,
|
this.data.liker.id,
|
||||||
this.data.liker.uri ? new URL(this.data.liker.uri) : null,
|
this.data.liker.uri ? new URL(this.data.liker.uri) : null,
|
||||||
),
|
).href,
|
||||||
type: "pub.versia:likes/Like",
|
type: "pub.versia:likes/Like",
|
||||||
created_at: new Date(this.data.createdAt).toISOString(),
|
created_at: new Date(this.data.createdAt).toISOString(),
|
||||||
liked: this.data.liked.uri
|
liked: this.data.liked.uri
|
||||||
? new URL(this.data.liked.uri)
|
? new URL(this.data.liked.uri).href
|
||||||
: new URL(`/notes/${this.data.liked.id}`, config.http.base_url),
|
: new URL(`/notes/${this.data.liked.id}`, config.http.base_url)
|
||||||
uri: this.getUri(),
|
.href,
|
||||||
|
uri: this.getUri().href,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -177,9 +178,9 @@ export class Like extends BaseInterface<typeof Likes, LikeType> {
|
||||||
: this.data.liker.uri
|
: this.data.liker.uri
|
||||||
? new URL(this.data.liker.uri)
|
? new URL(this.data.liker.uri)
|
||||||
: null,
|
: null,
|
||||||
),
|
).href,
|
||||||
deleted_type: "pub.versia:likes/Like",
|
deleted_type: "pub.versia:likes/Like",
|
||||||
deleted: this.getUri(),
|
deleted: this.getUri().href,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -449,14 +449,14 @@ export class Note extends BaseInterface<typeof Notes, NoteTypeWithRelations> {
|
||||||
replies_to,
|
replies_to,
|
||||||
subject,
|
subject,
|
||||||
} = versiaNote.data;
|
} = versiaNote.data;
|
||||||
const instance = await Instance.resolve(authorUrl);
|
const instance = await Instance.resolve(new URL(authorUrl));
|
||||||
const author = await User.resolve(authorUrl);
|
const author = await User.resolve(new URL(authorUrl));
|
||||||
|
|
||||||
if (!author) {
|
if (!author) {
|
||||||
throw new Error("Entity author could not be resolved");
|
throw new Error("Entity author could not be resolved");
|
||||||
}
|
}
|
||||||
|
|
||||||
const existingNote = await Note.fromSql(eq(Notes.uri, uri.href));
|
const existingNote = await Note.fromSql(eq(Notes.uri, uri));
|
||||||
|
|
||||||
const note =
|
const note =
|
||||||
existingNote ??
|
existingNote ??
|
||||||
|
|
@ -464,7 +464,7 @@ export class Note extends BaseInterface<typeof Notes, NoteTypeWithRelations> {
|
||||||
id: randomUUIDv7(),
|
id: randomUUIDv7(),
|
||||||
authorId: author.id,
|
authorId: author.id,
|
||||||
visibility: "public",
|
visibility: "public",
|
||||||
uri: uri.href,
|
uri,
|
||||||
createdAt: new Date(created_at).toISOString(),
|
createdAt: new Date(created_at).toISOString(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
@ -480,15 +480,22 @@ export class Note extends BaseInterface<typeof Notes, NoteTypeWithRelations> {
|
||||||
|
|
||||||
const mentions = (
|
const mentions = (
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
noteMentions?.map((mention) => User.resolve(mention)) ?? [],
|
noteMentions?.map((mention) =>
|
||||||
|
User.resolve(new URL(mention)),
|
||||||
|
) ?? [],
|
||||||
)
|
)
|
||||||
).filter((m) => m !== null);
|
).filter((m) => m !== null);
|
||||||
|
|
||||||
// TODO: Implement groups
|
// TODO: Implement groups
|
||||||
const visibility = !group || group instanceof URL ? "direct" : group;
|
const visibility =
|
||||||
|
!group || URL.canParse(group)
|
||||||
|
? "direct"
|
||||||
|
: (group as "public" | "followers" | "unlisted");
|
||||||
|
|
||||||
const reply = replies_to ? await Note.resolve(replies_to) : null;
|
const reply = replies_to
|
||||||
const quote = quotes ? await Note.resolve(quotes) : null;
|
? await Note.resolve(new URL(replies_to))
|
||||||
|
: null;
|
||||||
|
const quote = quotes ? await Note.resolve(new URL(quotes)) : null;
|
||||||
const spoiler = subject ? await sanitizedHtmlStrip(subject) : undefined;
|
const spoiler = subject ? await sanitizedHtmlStrip(subject) : undefined;
|
||||||
|
|
||||||
await note.update({
|
await note.update({
|
||||||
|
|
@ -694,9 +701,9 @@ export class Note extends BaseInterface<typeof Notes, NoteTypeWithRelations> {
|
||||||
return new VersiaEntities.Delete({
|
return new VersiaEntities.Delete({
|
||||||
type: "Delete",
|
type: "Delete",
|
||||||
id,
|
id,
|
||||||
author: this.author.uri,
|
author: this.author.uri.href,
|
||||||
deleted_type: "Note",
|
deleted_type: "Note",
|
||||||
deleted: this.getUri(),
|
deleted: this.getUri().href,
|
||||||
created_at: new Date().toISOString(),
|
created_at: new Date().toISOString(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -711,8 +718,8 @@ export class Note extends BaseInterface<typeof Notes, NoteTypeWithRelations> {
|
||||||
type: "Note",
|
type: "Note",
|
||||||
created_at: new Date(status.createdAt).toISOString(),
|
created_at: new Date(status.createdAt).toISOString(),
|
||||||
id: status.id,
|
id: status.id,
|
||||||
author: this.author.uri,
|
author: this.author.uri.href,
|
||||||
uri: this.getUri(),
|
uri: this.getUri().href,
|
||||||
content: {
|
content: {
|
||||||
"text/html": {
|
"text/html": {
|
||||||
content: status.content,
|
content: status.content,
|
||||||
|
|
@ -727,11 +734,11 @@ export class Note extends BaseInterface<typeof Notes, NoteTypeWithRelations> {
|
||||||
replies: new URL(
|
replies: new URL(
|
||||||
`/notes/${status.id}/replies`,
|
`/notes/${status.id}/replies`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
),
|
).href,
|
||||||
quotes: new URL(
|
quotes: new URL(
|
||||||
`/notes/${status.id}/quotes`,
|
`/notes/${status.id}/quotes`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
),
|
).href,
|
||||||
},
|
},
|
||||||
attachments: status.attachments.map(
|
attachments: status.attachments.map(
|
||||||
(attachment) =>
|
(attachment) =>
|
||||||
|
|
@ -740,21 +747,24 @@ export class Note extends BaseInterface<typeof Notes, NoteTypeWithRelations> {
|
||||||
>,
|
>,
|
||||||
),
|
),
|
||||||
is_sensitive: status.sensitive,
|
is_sensitive: status.sensitive,
|
||||||
mentions: status.mentions.map((mention) =>
|
mentions: status.mentions.map(
|
||||||
User.getUri(
|
(mention) =>
|
||||||
mention.id,
|
User.getUri(
|
||||||
mention.uri ? new URL(mention.uri) : null,
|
mention.id,
|
||||||
),
|
mention.uri ? new URL(mention.uri) : null,
|
||||||
|
).href,
|
||||||
),
|
),
|
||||||
quotes: status.quote
|
quotes: status.quote
|
||||||
? status.quote.uri
|
? status.quote.uri
|
||||||
? new URL(status.quote.uri)
|
? new URL(status.quote.uri).href
|
||||||
: new URL(`/notes/${status.quote.id}`, config.http.base_url)
|
: new URL(`/notes/${status.quote.id}`, config.http.base_url)
|
||||||
|
.href
|
||||||
: null,
|
: null,
|
||||||
replies_to: status.reply
|
replies_to: status.reply
|
||||||
? status.reply.uri
|
? status.reply.uri
|
||||||
? new URL(status.reply.uri)
|
? new URL(status.reply.uri).href
|
||||||
: new URL(`/notes/${status.reply.id}`, config.http.base_url)
|
: new URL(`/notes/${status.reply.id}`, config.http.base_url)
|
||||||
|
.href
|
||||||
: null,
|
: null,
|
||||||
subject: status.spoilerText,
|
subject: status.spoilerText,
|
||||||
// TODO: Refactor as part of groups
|
// TODO: Refactor as part of groups
|
||||||
|
|
|
||||||
|
|
@ -179,17 +179,18 @@ export class Reaction extends BaseInterface<typeof Reactions, ReactionType> {
|
||||||
}
|
}
|
||||||
|
|
||||||
return new VersiaEntities.Reaction({
|
return new VersiaEntities.Reaction({
|
||||||
uri: this.getUri(config.http.base_url),
|
uri: this.getUri(config.http.base_url).href,
|
||||||
type: "pub.versia:reactions/Reaction",
|
type: "pub.versia:reactions/Reaction",
|
||||||
author: User.getUri(
|
author: User.getUri(
|
||||||
this.data.authorId,
|
this.data.authorId,
|
||||||
this.data.author.uri ? new URL(this.data.author.uri) : null,
|
this.data.author.uri ? new URL(this.data.author.uri) : null,
|
||||||
),
|
).href,
|
||||||
created_at: new Date(this.data.createdAt).toISOString(),
|
created_at: new Date(this.data.createdAt).toISOString(),
|
||||||
id: this.id,
|
id: this.id,
|
||||||
object: this.data.note.uri
|
object: this.data.note.uri
|
||||||
? new URL(this.data.note.uri)
|
? new URL(this.data.note.uri).href
|
||||||
: new URL(`/notes/${this.data.noteId}`, config.http.base_url),
|
: new URL(`/notes/${this.data.noteId}`, config.http.base_url)
|
||||||
|
.href,
|
||||||
content: this.hasCustomEmoji()
|
content: this.hasCustomEmoji()
|
||||||
? `:${this.data.emoji?.shortcode}:`
|
? `:${this.data.emoji?.shortcode}:`
|
||||||
: this.data.emojiText || "",
|
: this.data.emojiText || "",
|
||||||
|
|
@ -232,7 +233,7 @@ export class Reaction extends BaseInterface<typeof Reactions, ReactionType> {
|
||||||
|
|
||||||
return Reaction.insert({
|
return Reaction.insert({
|
||||||
id: randomUUIDv7(),
|
id: randomUUIDv7(),
|
||||||
uri: reactionToConvert.data.uri.href,
|
uri: reactionToConvert.data.uri,
|
||||||
authorId: author.id,
|
authorId: author.id,
|
||||||
noteId: note.id,
|
noteId: note.id,
|
||||||
emojiId: emoji ? emoji.id : null,
|
emojiId: emoji ? emoji.id : null,
|
||||||
|
|
|
||||||
|
|
@ -247,9 +247,9 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
||||||
return new VersiaEntities.Unfollow({
|
return new VersiaEntities.Unfollow({
|
||||||
type: "Unfollow",
|
type: "Unfollow",
|
||||||
id,
|
id,
|
||||||
author: this.uri,
|
author: this.uri.href,
|
||||||
created_at: new Date().toISOString(),
|
created_at: new Date().toISOString(),
|
||||||
followee: followee.uri,
|
followee: followee.uri.href,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -265,9 +265,9 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
||||||
const entity = new VersiaEntities.FollowAccept({
|
const entity = new VersiaEntities.FollowAccept({
|
||||||
type: "FollowAccept",
|
type: "FollowAccept",
|
||||||
id: crypto.randomUUID(),
|
id: crypto.randomUUID(),
|
||||||
author: this.uri,
|
author: this.uri.href,
|
||||||
created_at: new Date().toISOString(),
|
created_at: new Date().toISOString(),
|
||||||
follower: follower.uri,
|
follower: follower.uri.href,
|
||||||
});
|
});
|
||||||
|
|
||||||
await deliveryQueue.add(DeliveryJobType.FederateEntity, {
|
await deliveryQueue.add(DeliveryJobType.FederateEntity, {
|
||||||
|
|
@ -289,9 +289,9 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
||||||
const entity = new VersiaEntities.FollowReject({
|
const entity = new VersiaEntities.FollowReject({
|
||||||
type: "FollowReject",
|
type: "FollowReject",
|
||||||
id: crypto.randomUUID(),
|
id: crypto.randomUUID(),
|
||||||
author: this.uri,
|
author: this.uri.href,
|
||||||
created_at: new Date().toISOString(),
|
created_at: new Date().toISOString(),
|
||||||
follower: follower.uri,
|
follower: follower.uri.href,
|
||||||
});
|
});
|
||||||
|
|
||||||
await deliveryQueue.add(DeliveryJobType.FederateEntity, {
|
await deliveryQueue.add(DeliveryJobType.FederateEntity, {
|
||||||
|
|
@ -675,9 +675,9 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
||||||
uri,
|
uri,
|
||||||
extensions,
|
extensions,
|
||||||
} = versiaUser.data;
|
} = versiaUser.data;
|
||||||
const instance = await Instance.resolve(versiaUser.data.uri);
|
const instance = await Instance.resolve(new URL(versiaUser.data.uri));
|
||||||
const existingUser = await User.fromSql(
|
const existingUser = await User.fromSql(
|
||||||
eq(Users.uri, versiaUser.data.uri.href),
|
eq(Users.uri, versiaUser.data.uri),
|
||||||
);
|
);
|
||||||
|
|
||||||
const user =
|
const user =
|
||||||
|
|
@ -686,7 +686,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
||||||
username,
|
username,
|
||||||
id: randomUUIDv7(),
|
id: randomUUIDv7(),
|
||||||
publicKey: public_key.key,
|
publicKey: public_key.key,
|
||||||
uri: uri.href,
|
uri,
|
||||||
instanceId: instance.id,
|
instanceId: instance.id,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
@ -727,13 +727,13 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
||||||
await user.update({
|
await user.update({
|
||||||
createdAt: new Date(created_at).toISOString(),
|
createdAt: new Date(created_at).toISOString(),
|
||||||
endpoints: {
|
endpoints: {
|
||||||
inbox: inbox.href,
|
inbox,
|
||||||
outbox: collections.outbox.href,
|
outbox: collections.outbox,
|
||||||
followers: collections.followers.href,
|
followers: collections.followers,
|
||||||
following: collections.following.href,
|
following: collections.following,
|
||||||
featured: collections.featured.href,
|
featured: collections.featured,
|
||||||
likes: collections["pub.versia:likes/Likes"]?.href,
|
likes: collections["pub.versia:likes/Likes"] ?? undefined,
|
||||||
dislikes: collections["pub.versia:likes/Dislikes"]?.href,
|
dislikes: collections["pub.versia:likes/Dislikes"] ?? undefined,
|
||||||
},
|
},
|
||||||
avatarId: userAvatar?.id,
|
avatarId: userAvatar?.id,
|
||||||
headerId: userHeader?.id,
|
headerId: userHeader?.id,
|
||||||
|
|
@ -1097,7 +1097,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
||||||
return new VersiaEntities.User({
|
return new VersiaEntities.User({
|
||||||
id: user.id,
|
id: user.id,
|
||||||
type: "User",
|
type: "User",
|
||||||
uri: this.uri,
|
uri: this.uri.href,
|
||||||
bio: {
|
bio: {
|
||||||
"text/html": {
|
"text/html": {
|
||||||
content: user.note,
|
content: user.note,
|
||||||
|
|
@ -1113,29 +1113,30 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
||||||
featured: new URL(
|
featured: new URL(
|
||||||
`/users/${user.id}/featured`,
|
`/users/${user.id}/featured`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
),
|
).href,
|
||||||
"pub.versia:likes/Likes": new URL(
|
"pub.versia:likes/Likes": new URL(
|
||||||
`/users/${user.id}/likes`,
|
`/users/${user.id}/likes`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
),
|
).href,
|
||||||
"pub.versia:likes/Dislikes": new URL(
|
"pub.versia:likes/Dislikes": new URL(
|
||||||
`/users/${user.id}/dislikes`,
|
`/users/${user.id}/dislikes`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
),
|
).href,
|
||||||
followers: new URL(
|
followers: new URL(
|
||||||
`/users/${user.id}/followers`,
|
`/users/${user.id}/followers`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
),
|
).href,
|
||||||
following: new URL(
|
following: new URL(
|
||||||
`/users/${user.id}/following`,
|
`/users/${user.id}/following`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
),
|
).href,
|
||||||
outbox: new URL(
|
outbox: new URL(
|
||||||
`/users/${user.id}/outbox`,
|
`/users/${user.id}/outbox`,
|
||||||
config.http.base_url,
|
config.http.base_url,
|
||||||
),
|
).href,
|
||||||
},
|
},
|
||||||
inbox: new URL(`/users/${user.id}/inbox`, config.http.base_url),
|
inbox: new URL(`/users/${user.id}/inbox`, config.http.base_url)
|
||||||
|
.href,
|
||||||
indexable: this.data.isIndexable,
|
indexable: this.data.isIndexable,
|
||||||
username: user.username,
|
username: user.username,
|
||||||
manually_approves_followers: this.data.isLocked,
|
manually_approves_followers: this.data.isLocked,
|
||||||
|
|
@ -1148,7 +1149,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
||||||
display_name: user.displayName,
|
display_name: user.displayName,
|
||||||
fields: user.fields,
|
fields: user.fields,
|
||||||
public_key: {
|
public_key: {
|
||||||
actor: new URL(`/users/${user.id}`, config.http.base_url),
|
actor: new URL(`/users/${user.id}`, config.http.base_url).href,
|
||||||
key: user.publicKey,
|
key: user.publicKey,
|
||||||
algorithm: "ed25519",
|
algorithm: "ed25519",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -219,8 +219,8 @@ export class InboxProcessor {
|
||||||
private static async processFollowRequest(
|
private static async processFollowRequest(
|
||||||
follow: VersiaEntities.Follow,
|
follow: VersiaEntities.Follow,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const author = await User.resolve(follow.data.author);
|
const author = await User.resolve(new URL(follow.data.author));
|
||||||
const followee = await User.resolve(follow.data.followee);
|
const followee = await User.resolve(new URL(follow.data.followee));
|
||||||
|
|
||||||
if (!author) {
|
if (!author) {
|
||||||
throw new ApiError(404, "Author not found");
|
throw new ApiError(404, "Author not found");
|
||||||
|
|
@ -267,8 +267,10 @@ export class InboxProcessor {
|
||||||
private static async processFollowAccept(
|
private static async processFollowAccept(
|
||||||
followAccept: VersiaEntities.FollowAccept,
|
followAccept: VersiaEntities.FollowAccept,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const author = await User.resolve(followAccept.data.author);
|
const author = await User.resolve(new URL(followAccept.data.author));
|
||||||
const follower = await User.resolve(followAccept.data.follower);
|
const follower = await User.resolve(
|
||||||
|
new URL(followAccept.data.follower),
|
||||||
|
);
|
||||||
|
|
||||||
if (!author) {
|
if (!author) {
|
||||||
throw new ApiError(404, "Author not found");
|
throw new ApiError(404, "Author not found");
|
||||||
|
|
@ -302,8 +304,10 @@ export class InboxProcessor {
|
||||||
private static async processFollowReject(
|
private static async processFollowReject(
|
||||||
followReject: VersiaEntities.FollowReject,
|
followReject: VersiaEntities.FollowReject,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const author = await User.resolve(followReject.data.author);
|
const author = await User.resolve(new URL(followReject.data.author));
|
||||||
const follower = await User.resolve(followReject.data.follower);
|
const follower = await User.resolve(
|
||||||
|
new URL(followReject.data.follower),
|
||||||
|
);
|
||||||
|
|
||||||
if (!author) {
|
if (!author) {
|
||||||
throw new ApiError(404, "Author not found");
|
throw new ApiError(404, "Author not found");
|
||||||
|
|
@ -340,13 +344,13 @@ export class InboxProcessor {
|
||||||
const toDelete = delete_.data.deleted;
|
const toDelete = delete_.data.deleted;
|
||||||
|
|
||||||
const author = delete_.data.author
|
const author = delete_.data.author
|
||||||
? await User.resolve(delete_.data.author)
|
? await User.resolve(new URL(delete_.data.author))
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
switch (delete_.data.deleted_type) {
|
switch (delete_.data.deleted_type) {
|
||||||
case "Note": {
|
case "Note": {
|
||||||
const note = await Note.fromSql(
|
const note = await Note.fromSql(
|
||||||
eq(Notes.uri, toDelete.href),
|
eq(Notes.uri, toDelete),
|
||||||
author ? eq(Notes.authorId, author.id) : undefined,
|
author ? eq(Notes.authorId, author.id) : undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -361,7 +365,7 @@ export class InboxProcessor {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case "User": {
|
case "User": {
|
||||||
const userToDelete = await User.resolve(toDelete);
|
const userToDelete = await User.resolve(new URL(toDelete));
|
||||||
|
|
||||||
if (!userToDelete) {
|
if (!userToDelete) {
|
||||||
throw new ApiError(404, "User to delete not found");
|
throw new ApiError(404, "User to delete not found");
|
||||||
|
|
@ -376,7 +380,7 @@ export class InboxProcessor {
|
||||||
}
|
}
|
||||||
case "pub.versia:likes/Like": {
|
case "pub.versia:likes/Like": {
|
||||||
const like = await Like.fromSql(
|
const like = await Like.fromSql(
|
||||||
eq(Likes.uri, toDelete.href),
|
eq(Likes.uri, toDelete),
|
||||||
author ? eq(Likes.likerId, author.id) : undefined,
|
author ? eq(Likes.likerId, author.id) : undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -393,7 +397,7 @@ export class InboxProcessor {
|
||||||
default: {
|
default: {
|
||||||
throw new ApiError(
|
throw new ApiError(
|
||||||
400,
|
400,
|
||||||
`Deletion of object ${toDelete.href} not implemented`,
|
`Deletion of object ${toDelete} not implemented`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -408,8 +412,8 @@ export class InboxProcessor {
|
||||||
private static async processLikeRequest(
|
private static async processLikeRequest(
|
||||||
like: VersiaEntities.Like,
|
like: VersiaEntities.Like,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const author = await User.resolve(like.data.author);
|
const author = await User.resolve(new URL(like.data.author));
|
||||||
const likedNote = await Note.resolve(like.data.liked);
|
const likedNote = await Note.resolve(new URL(like.data.liked));
|
||||||
|
|
||||||
if (!author) {
|
if (!author) {
|
||||||
throw new ApiError(404, "Author not found");
|
throw new ApiError(404, "Author not found");
|
||||||
|
|
@ -419,7 +423,7 @@ export class InboxProcessor {
|
||||||
throw new ApiError(404, "Liked Note not found");
|
throw new ApiError(404, "Liked Note not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
await author.like(likedNote, like.data.uri);
|
await author.like(likedNote, new URL(like.data.uri));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,16 @@ export const getPushWorker = (): Worker<PushJobData, void, PushJobType> =>
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!(
|
||||||
|
config.notifications.push.vapid_keys.private ||
|
||||||
|
config.notifications.push.vapid_keys.public
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
await job.log("Push notifications are not configured");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await job.log(
|
await job.log(
|
||||||
`Sending push notification for note [${notificationId}]`,
|
`Sending push notification for note [${notificationId}]`,
|
||||||
);
|
);
|
||||||
|
|
@ -132,8 +142,9 @@ export const getPushWorker = (): Worker<PushJobData, void, PushJobType> =>
|
||||||
config.notifications.push.subject ||
|
config.notifications.push.subject ||
|
||||||
config.http.base_url.origin,
|
config.http.base_url.origin,
|
||||||
privateKey:
|
privateKey:
|
||||||
config.notifications.push.vapid_keys.private,
|
config.notifications.push.vapid_keys.private ?? "",
|
||||||
publicKey: config.notifications.push.vapid_keys.public,
|
publicKey:
|
||||||
|
config.notifications.push.vapid_keys.public ?? "",
|
||||||
},
|
},
|
||||||
contentEncoding: "aesgcm",
|
contentEncoding: "aesgcm",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,9 @@ export class FederationRequester {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nextUrl = collection.data.next;
|
nextUrl = collection.data.next
|
||||||
|
? new URL(collection.data.next)
|
||||||
|
: null;
|
||||||
limit -= collection.data.items.length;
|
limit -= collection.data.items.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,7 +138,7 @@ export class FederationRequester {
|
||||||
limit?: number;
|
limit?: number;
|
||||||
},
|
},
|
||||||
): Promise<URL[]> {
|
): Promise<URL[]> {
|
||||||
const entities: URL[] = [];
|
const entities: string[] = [];
|
||||||
let nextUrl: URL | null = url;
|
let nextUrl: URL | null = url;
|
||||||
let limit = options?.limit ?? Number.POSITIVE_INFINITY;
|
let limit = options?.limit ?? Number.POSITIVE_INFINITY;
|
||||||
|
|
||||||
|
|
@ -147,11 +149,13 @@ export class FederationRequester {
|
||||||
);
|
);
|
||||||
|
|
||||||
entities.push(...collection.data.items);
|
entities.push(...collection.data.items);
|
||||||
nextUrl = collection.data.next;
|
nextUrl = collection.data.next
|
||||||
|
? new URL(collection.data.next)
|
||||||
|
: null;
|
||||||
limit -= collection.data.items.length;
|
limit -= collection.data.items.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
return entities;
|
return entities.map((u) => new URL(u));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,4 @@ export const u64 = z
|
||||||
.nonnegative()
|
.nonnegative()
|
||||||
.max(2 ** 64 - 1);
|
.max(2 ** 64 - 1);
|
||||||
|
|
||||||
export const url = z
|
export const url = z.string().url();
|
||||||
.string()
|
|
||||||
.url()
|
|
||||||
.transform((z) => new URL(z));
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue