mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 08:28:19 +01:00
feat(federation): ✨ Handle instances not existing
This commit is contained in:
parent
deee65ad6d
commit
91da99c934
|
|
@ -106,6 +106,13 @@ export default apiRoute((app) =>
|
||||||
// Try to fetch it from database
|
// Try to fetch it from database
|
||||||
const instance = await Instance.resolveFromHost(instanceHost);
|
const instance = await Instance.resolveFromHost(instanceHost);
|
||||||
|
|
||||||
|
if (!instance) {
|
||||||
|
return context.json(
|
||||||
|
{ error: `Instance ${instanceHost} not found` },
|
||||||
|
404,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const account = await User.fromSql(
|
const account = await User.fromSql(
|
||||||
and(
|
and(
|
||||||
eq(Users.username, username),
|
eq(Users.username, username),
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ export class Emoji extends BaseInterface<typeof Emojis, EmojiWithInstance> {
|
||||||
visible_in_picker: z.boolean(),
|
visible_in_picker: z.boolean(),
|
||||||
category: z.string().optional(),
|
category: z.string().optional(),
|
||||||
static_url: z.string(),
|
static_url: z.string(),
|
||||||
|
global: z.boolean(),
|
||||||
});
|
});
|
||||||
|
|
||||||
public static $type: EmojiWithInstance;
|
public static $type: EmojiWithInstance;
|
||||||
|
|
|
||||||
|
|
@ -319,7 +319,7 @@ export class Instance extends BaseInterface<typeof Instances> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static resolveFromHost(host: string): Promise<Instance> {
|
public static resolveFromHost(host: string): Promise<Instance | null> {
|
||||||
if (host.startsWith("http")) {
|
if (host.startsWith("http")) {
|
||||||
const url = new URL(host).host;
|
const url = new URL(host).host;
|
||||||
|
|
||||||
|
|
@ -331,7 +331,7 @@ export class Instance extends BaseInterface<typeof Instances> {
|
||||||
return Instance.resolve(url.origin);
|
return Instance.resolve(url.origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async resolve(url: string): Promise<Instance> {
|
public static async resolve(url: string): Promise<Instance | null> {
|
||||||
const logger = getLogger(["federation", "resolvers"]);
|
const logger = getLogger(["federation", "resolvers"]);
|
||||||
const host = new URL(url).host;
|
const host = new URL(url).host;
|
||||||
|
|
||||||
|
|
@ -347,7 +347,7 @@ export class Instance extends BaseInterface<typeof Instances> {
|
||||||
|
|
||||||
if (!output) {
|
if (!output) {
|
||||||
logger.error`Failed to resolve instance ${chalk.bold(host)}`;
|
logger.error`Failed to resolve instance ${chalk.bold(host)}`;
|
||||||
throw new Error("Failed to resolve instance");
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { metadata, protocol } = output;
|
const { metadata, protocol } = output;
|
||||||
|
|
|
||||||
|
|
@ -599,18 +599,26 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
||||||
|
|
||||||
const updated = await User.saveFromRemote(this.getUri());
|
const updated = await User.saveFromRemote(this.getUri());
|
||||||
|
|
||||||
|
if (!updated) {
|
||||||
|
throw new Error("Failed to update user from remote");
|
||||||
|
}
|
||||||
|
|
||||||
this.data = updated.data;
|
this.data = updated.data;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async saveFromRemote(uri: string): Promise<User> {
|
public static async saveFromRemote(uri: string): Promise<User | null> {
|
||||||
if (!URL.canParse(uri)) {
|
if (!URL.canParse(uri)) {
|
||||||
throw new Error(`Invalid URI: ${uri}`);
|
throw new Error(`Invalid URI: ${uri}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const instance = await Instance.resolve(uri);
|
const instance = await Instance.resolve(uri);
|
||||||
|
|
||||||
|
if (!instance) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (instance.data.protocol === "versia") {
|
if (instance.data.protocol === "versia") {
|
||||||
return await User.saveFromVersia(uri, instance);
|
return await User.saveFromVersia(uri, instance);
|
||||||
}
|
}
|
||||||
|
|
@ -636,12 +644,20 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
||||||
private static async saveFromVersia(
|
private static async saveFromVersia(
|
||||||
uri: string,
|
uri: string,
|
||||||
instance: Instance,
|
instance: Instance,
|
||||||
): Promise<User> {
|
): Promise<User | null> {
|
||||||
const requester = await User.getFederationRequester();
|
const requester = await User.getFederationRequester();
|
||||||
const { data: json } = await requester.get<Partial<VersiaUser>>(uri, {
|
const output = await requester
|
||||||
|
.get<Partial<VersiaUser>>(uri, {
|
||||||
// @ts-expect-error Bun extension
|
// @ts-expect-error Bun extension
|
||||||
proxy: config.http.proxy.address,
|
proxy: config.http.proxy.address,
|
||||||
});
|
})
|
||||||
|
.catch(() => null);
|
||||||
|
|
||||||
|
if (!output) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: json } = output;
|
||||||
|
|
||||||
const validator = new EntityValidator();
|
const validator = new EntityValidator();
|
||||||
const data = await validator.User(json);
|
const data = await validator.User(json);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue