mirror of
https://github.com/svemagie/indiekit-endpoint-activitypub.git
synced 2026-04-02 15:44:58 +02:00
Add a dedicated fediverse reader view with: - Timeline view showing posts from followed accounts with threading, content warnings, boosts, and media display - Compose form with dual-path posting (quick AP reply + Micropub blog post) - Native AP interactions (like, boost, reply, follow/unfollow) - Notifications view for likes, boosts, follows, mentions, replies - Moderation tools (mute/block actors, keyword filters) - Remote actor profile pages with follow state - Automatic timeline cleanup with configurable retention - CSRF protection, XSS prevention, input validation throughout Removes Microsub bridge dependency — AP content now lives in its own MongoDB collections (ap_timeline, ap_notifications, ap_interactions, ap_muted, ap_blocked). Bumps version to 1.1.0.
50 lines
1.1 KiB
JavaScript
50 lines
1.1 KiB
JavaScript
/**
|
|
* Simple CSRF token generation and validation.
|
|
* Tokens are stored in the Express session.
|
|
*/
|
|
|
|
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
|
|
/**
|
|
* Get or generate a CSRF token for the current session.
|
|
* @param {object} session - Express session object
|
|
* @returns {string} CSRF token
|
|
*/
|
|
export function getToken(session) {
|
|
if (!session._csrfToken) {
|
|
session._csrfToken = randomBytes(32).toString("hex");
|
|
}
|
|
|
|
return session._csrfToken;
|
|
}
|
|
|
|
/**
|
|
* Validate a CSRF token from a request.
|
|
* Checks both the request body `_csrf` field and the `X-CSRF-Token` header.
|
|
* @param {object} request - Express request object
|
|
* @returns {boolean} Whether the token is valid
|
|
*/
|
|
export function validateToken(request) {
|
|
const sessionToken = request.session?._csrfToken;
|
|
|
|
if (!sessionToken) {
|
|
return false;
|
|
}
|
|
|
|
const requestToken =
|
|
request.body?._csrf || request.headers["x-csrf-token"];
|
|
|
|
if (!requestToken) {
|
|
return false;
|
|
}
|
|
|
|
if (sessionToken.length !== requestToken.length) {
|
|
return false;
|
|
}
|
|
|
|
return timingSafeEqual(
|
|
Buffer.from(sessionToken),
|
|
Buffer.from(requestToken),
|
|
);
|
|
}
|