Federation Refactoring & Architecture Improvements (#930)

* initial commit

* add lists

* update permissions

* fix waypoint create

* needs_full_sync for activitypub trails

* fixes build issues

* fix list get

* further CSRF protection

* update API docs

* adds rate limiter

* fix tiptap mentions

* a bit more cleanup of main.go

* Fix migration order

* fixes reviewed notes

* require context for activitpub server calls

* improve hashing for identifier

* fix copy paste error

* fix sync trail/list issues

* fix summit log/comment duplicates

* adaptions after trail merge

* fix dockerignore

---------

Co-authored-by: Christian Beutel <>
Co-authored-by: slothful-vassal <89943360+slothful-vassal@users.noreply.github.com>
This commit is contained in:
Flomp
2026-05-09 17:30:34 +02:00
committed by GitHub
parent 992ebfc0c4
commit d2ac49470a
73 changed files with 3773 additions and 2153 deletions

View File

@@ -1,25 +1,17 @@
import { Comment } from "$lib/models/comment";
import type { Trail } from "$lib/models/trail";
import { APIError } from "$lib/util/api_util";
import { type ListResult } from "pocketbase";
import { get, writable, type Writable } from "svelte/store";
import { currentUser } from "./user_store";
import { isURL } from "$lib/util/file_util";
export const comments: Writable<Comment[]> = writable([])
export async function comments_index(trailId: string, handle?: string) {
export async function comments_index(trailId: string) {
let filter: string;
if (isURL(trailId)) {
filter = `trail="${trailId}"||trail.iri="${trailId}"||trail="${trailId.substring(trailId.length - 15)}"`
} else {
filter = `trail="${trailId}"`
}
let r = await fetch(`/api/v1/comment?` + new URLSearchParams({
filter,
let r = await fetch(`/api/v1/trail/${trailId}/comment?` + new URLSearchParams({
expand: "author",
sort: "-created",
...(handle ? { handle } : {})
}), {
method: 'GET',
})

View File

@@ -5,11 +5,9 @@ import { type ListResult } from "pocketbase";
let follows: Actor[] = [];
export async function follows_index(data: { username: string, type: "followers" | "following" }, page: number = 1, perPage: number = 10, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
export async function follows_index(page: number = 1, perPage: number = 10, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
const r = await f(`/api/v1/follow?` + new URLSearchParams({
handle: data.username,
type: data.type,
page: page.toString(),
perPage: perPage.toString(),
}), {
@@ -25,7 +23,7 @@ export async function follows_index(data: { username: string, type: "followers"
const result = page > 1 ? [...follows, ...fetchedFollows.items] : fetchedFollows.items
follows = result;
follows = result;
return { ...fetchedFollows, items: result };
}

View File

@@ -9,9 +9,10 @@ import { searchResultToLists } from "./list_store";
import type { ListSearchResult } from "./search_store";
import { buildFilterText } from "./summit_log_store";
import { searchResultToTrailList } from "./trail_store";
import type { Actor } from "$lib/models/activitypub/actor";
let feed: FeedItem[] = []
let follows: Actor[] = [];
export async function profile_show(handle: string, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
let r = await f('/api/v1/profile/' + handle, {
@@ -132,4 +133,26 @@ export async function profile_stats_index(handle: string, filter: SummitLogFilte
return result;
}
export async function profile_follows_index(handle: string, type: "followers" | "following", page: number, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
const r = await f(`/api/v1/profile/${handle}/follows?` + new URLSearchParams({
type,
page: page.toString(),
}), {
method: 'GET',
})
if (!r.ok) {
const response = await r.json();
throw new APIError(r.status, response.message, response.detail)
}
const fetchedFollows: ListResult<Actor> = await r.json();
const result = page > 1 ? [...follows, ...fetchedFollows.items] : fetchedFollows.items
follows = result;
return { ...fetchedFollows, items: result };
}

View File

@@ -12,7 +12,7 @@ export async function waypoints_create(waypoint: Waypoint, f: (url: RequestInfo
throw Error("Unauthenticated")
}
waypoint.author = user.id
waypoint.author = user.actor
let r = await f('/api/v1/waypoint', {
method: 'PUT',