Make WebFinger resolve work

This commit is contained in:
Jesse Wierzbinski 2024-04-09 19:13:13 -10:00
parent fcf952e1f3
commit 4acc04cd93
No known key found for this signature in database
3 changed files with 48 additions and 39 deletions

View file

@ -1,6 +1,6 @@
import type { Instance } from "@prisma/client"; import type { Instance } from "@prisma/client";
import { client } from "~database/datasource"; import { client } from "~database/datasource";
import type { ServerMetadata } from "~types/lysand/Object"; import type * as Lysand from "lysand-types";
/** /**
* Represents an instance in the database. * Represents an instance in the database.
@ -15,32 +15,32 @@ export const addInstanceIfNotExists = async (
url: string, url: string,
): Promise<Instance> => { ): Promise<Instance> => {
const origin = new URL(url).origin; const origin = new URL(url).origin;
const hostname = new URL(url).hostname; const host = new URL(url).host;
const found = await client.instance.findFirst({ const found = await client.instance.findFirst({
where: { where: {
base_url: hostname, base_url: host,
}, },
}); });
if (found) return found; if (found) return found;
// Fetch the instance configuration // Fetch the instance configuration
const metadata = (await fetch(`${origin}/.well-known/lysand`).then((res) => const metadata = (await fetch(new URL("/.well-known/lysand", origin)).then(
res.json(), (res) => res.json(),
)) as Partial<ServerMetadata>; )) as Lysand.ServerMetadata;
if (metadata.type !== "ServerMetadata") { if (metadata.type !== "ServerMetadata") {
throw new Error("Invalid instance metadata"); throw new Error("Invalid instance metadata (wrong type)");
} }
if (!(metadata.name && metadata.version)) { if (!(metadata.name && metadata.version)) {
throw new Error("Invalid instance metadata"); throw new Error("Invalid instance metadata (missing name or version)");
} }
return await client.instance.create({ return await client.instance.create({
data: { data: {
base_url: hostname, base_url: host,
name: metadata.name, name: metadata.name,
version: metadata.version, version: metadata.version,
logo: metadata.logo, logo: metadata.logo,

View file

@ -11,7 +11,7 @@ import { addEmojiIfNotExists, emojiToAPI, emojiToLysand } from "./Emoji";
import { addInstanceIfNotExists } from "./Instance"; import { addInstanceIfNotExists } from "./Instance";
import { userRelations } from "./relations"; import { userRelations } from "./relations";
import { createNewRelationship } from "./Relationship"; import { createNewRelationship } from "./Relationship";
import { urlToContentFormat } from "@content_types"; import { getBestContentType, urlToContentFormat } from "@content_types";
export interface AuthData { export interface AuthData {
user: UserWithRelations | null; user: UserWithRelations | null;
@ -172,6 +172,14 @@ export const resolveUser = async (uri: string) => {
const userEmojis = const userEmojis =
data.extensions?.["org.lysand:custom_emojis"]?.emojis ?? []; data.extensions?.["org.lysand:custom_emojis"]?.emojis ?? [];
const instance = await addInstanceIfNotExists(data.uri);
const emojis = [];
for (const emoji of userEmojis) {
emojis.push(await addEmojiIfNotExists(emoji));
}
const user = await client.user.create({ const user = await client.user.create({
data: { data: {
username: data.username, username: data.username,
@ -186,10 +194,20 @@ export const resolveUser = async (uri: string) => {
inbox: data.inbox, inbox: data.inbox,
outbox: data.outbox, outbox: data.outbox,
}, },
avatar: data.avatar?.[0].content || "", emojis: {
header: data.header?.[0].content || "", connect: emojis.map((emoji) => ({
id: emoji.id,
})),
},
instanceId: instance.id,
avatar: data.avatar
? Object.entries(data.avatar)[0][1].content
: "",
header: data.header
? Object.entries(data.header)[0][1].content
: "",
displayName: data.display_name ?? "", displayName: data.display_name ?? "",
note: data.bio?.[0].content ?? "", note: getBestContentType(data.bio).content,
publicKey: data.public_key.public_key, publicKey: data.public_key.public_key,
source: { source: {
language: null, language: null,
@ -199,33 +217,13 @@ export const resolveUser = async (uri: string) => {
fields: [], fields: [],
}, },
}, },
include: userRelations,
}); });
// Add to Meilisearch // Add to Meilisearch
await addUserToMeilisearch(user); await addUserToMeilisearch(user);
const emojis = []; return user;
for (const emoji of userEmojis) {
emojis.push(await addEmojiIfNotExists(emoji));
}
const uriData = new URL(data.uri);
return await client.user.update({
where: {
id: user.id,
},
data: {
emojis: {
connect: emojis.map((emoji) => ({
id: emoji.id,
})),
},
instanceId: (await addInstanceIfNotExists(uriData.origin)).id,
},
include: userRelations,
});
}; };
/** /**
@ -258,7 +256,6 @@ export const resolveWebFinger = async (identifier: string, host: string) => {
{ {
method: "GET", method: "GET",
headers: { headers: {
"Content-Type": "application/json",
Accept: "application/json", Accept: "application/json",
}, },
}, },

View file

@ -76,8 +76,17 @@ export default apiRoute<{
if (!type || type === "accounts") { if (!type || type === "accounts") {
// Check if q is matching format username@domain.com or @username@domain.com // Check if q is matching format username@domain.com or @username@domain.com
if (q?.trim().match(/@?[a-zA-Z0-9_]+(@[a-zA-Z0-9_.:]+)/g)) { const accountMatches = q
const [username, domain] = q.trim().split("@"); ?.trim()
.match(/@?[a-zA-Z0-9_]+(@[a-zA-Z0-9_.:]+)/g);
if (accountMatches) {
// Remove leading @ if it exists
if (accountMatches[0].startsWith("@")) {
accountMatches[0] = accountMatches[0].slice(1);
}
const [username, domain] = accountMatches[0].split("@");
const account = await client.user.findFirst({ const account = await client.user.findFirst({
where: { where: {
username, username,
@ -98,7 +107,10 @@ export default apiRoute<{
if (resolve) { if (resolve) {
const newUser = await resolveWebFinger(username, domain).catch( const newUser = await resolveWebFinger(username, domain).catch(
() => null, (e) => {
console.error(e);
return null;
},
); );
if (newUser) { if (newUser) {