[WEB-2729] chore: updated live server auth cookies handling (#5913)
* chore: updated live server auth cookies handling * chore: update token parsing logic * fix: types and better logical seperation between the existing two tokens * fix: better fallback to use request headers for cookies --------- Co-authored-by: Palanikannan M <akashmalinimurugu@gmail.com>
This commit is contained in:
parent
403482fa6e
commit
8ea34b5995
6 changed files with 54 additions and 33 deletions
|
|
@ -1,28 +1,26 @@
|
|||
// Third-party libraries
|
||||
import { Redis } from "ioredis";
|
||||
|
||||
// Hocuspocus extensions and core
|
||||
import { Database } from "@hocuspocus/extension-database";
|
||||
import { Extension } from "@hocuspocus/server";
|
||||
import { Logger } from "@hocuspocus/extension-logger";
|
||||
import { Redis as HocusPocusRedis } from "@hocuspocus/extension-redis";
|
||||
|
||||
// Core helpers and utilities
|
||||
// core helpers and utilities
|
||||
import { manualLogger } from "@/core/helpers/logger.js";
|
||||
import { getRedisUrl } from "@/core/lib/utils/redis-url.js";
|
||||
|
||||
// Core libraries
|
||||
// core libraries
|
||||
import {
|
||||
fetchPageDescriptionBinary,
|
||||
updatePageDescription,
|
||||
} from "@/core/lib/page.js";
|
||||
|
||||
// Core types
|
||||
import { TDocumentTypes } from "@/core/types/common.js";
|
||||
|
||||
// Plane live libraries
|
||||
// plane live libraries
|
||||
import { fetchDocument } from "@/plane-live/lib/fetch-document.js";
|
||||
import { updateDocument } from "@/plane-live/lib/update-document.js";
|
||||
// types
|
||||
import {
|
||||
type HocusPocusServerContext,
|
||||
type TDocumentTypes,
|
||||
} from "@/core/types/common.js";
|
||||
|
||||
export const getExtensions: () => Promise<Extension[]> = async () => {
|
||||
const extensions: Extension[] = [
|
||||
|
|
@ -33,13 +31,8 @@ export const getExtensions: () => Promise<Extension[]> = async () => {
|
|||
},
|
||||
}),
|
||||
new Database({
|
||||
fetch: async ({
|
||||
documentName: pageId,
|
||||
requestHeaders,
|
||||
requestParameters,
|
||||
}) => {
|
||||
// request headers
|
||||
const cookie = requestHeaders.cookie?.toString();
|
||||
fetch: async ({ context, documentName: pageId, requestParameters }) => {
|
||||
const cookie = (context as HocusPocusServerContext).cookie;
|
||||
// query params
|
||||
const params = requestParameters;
|
||||
const documentType = params.get("documentType")?.toString() as
|
||||
|
|
@ -54,7 +47,7 @@ export const getExtensions: () => Promise<Extension[]> = async () => {
|
|||
fetchedData = await fetchPageDescriptionBinary(
|
||||
params,
|
||||
pageId,
|
||||
cookie
|
||||
cookie,
|
||||
);
|
||||
} else {
|
||||
fetchedData = await fetchDocument({
|
||||
|
|
@ -71,13 +64,12 @@ export const getExtensions: () => Promise<Extension[]> = async () => {
|
|||
});
|
||||
},
|
||||
store: async ({
|
||||
context,
|
||||
state,
|
||||
documentName: pageId,
|
||||
requestHeaders,
|
||||
requestParameters,
|
||||
}) => {
|
||||
// request headers
|
||||
const cookie = requestHeaders.cookie?.toString();
|
||||
const cookie = (context as HocusPocusServerContext).cookie;
|
||||
// query params
|
||||
const params = requestParameters;
|
||||
const documentType = params.get("documentType")?.toString() as
|
||||
|
|
@ -124,7 +116,7 @@ export const getExtensions: () => Promise<Extension[]> = async () => {
|
|||
}
|
||||
manualLogger.warn(
|
||||
`Redis Client wasn't able to connect, continuing without Redis (you won't be able to sync data between multiple plane live servers)`,
|
||||
error
|
||||
error,
|
||||
);
|
||||
reject(error);
|
||||
});
|
||||
|
|
@ -138,12 +130,12 @@ export const getExtensions: () => Promise<Extension[]> = async () => {
|
|||
} catch (error) {
|
||||
manualLogger.warn(
|
||||
`Redis Client wasn't able to connect, continuing without Redis (you won't be able to sync data between multiple plane live servers)`,
|
||||
error
|
||||
error,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
manualLogger.warn(
|
||||
"Redis URL is not set, continuing without Redis (you won't be able to sync data between multiple plane live servers)"
|
||||
"Redis URL is not set, continuing without Redis (you won't be able to sync data between multiple plane live servers)",
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@ import { v4 as uuidv4 } from "uuid";
|
|||
import { handleAuthentication } from "@/core/lib/authentication.js";
|
||||
// extensions
|
||||
import { getExtensions } from "@/core/extensions/index.js";
|
||||
// editor types
|
||||
import { TUserDetails } from "@plane/editor";
|
||||
// types
|
||||
import { type HocusPocusServerContext } from "@/core/types/common.js";
|
||||
|
||||
export const getHocusPocusServer = async () => {
|
||||
const extensions = await getExtensions();
|
||||
|
|
@ -12,20 +16,40 @@ export const getHocusPocusServer = async () => {
|
|||
name: serverName,
|
||||
onAuthenticate: async ({
|
||||
requestHeaders,
|
||||
context,
|
||||
// user id used as token for authentication
|
||||
token,
|
||||
}) => {
|
||||
// request headers
|
||||
const cookie = requestHeaders.cookie?.toString();
|
||||
let cookie: string | undefined = undefined;
|
||||
let userId: string | undefined = undefined;
|
||||
|
||||
if (!cookie) {
|
||||
throw Error("Credentials not provided");
|
||||
// Extract cookie (fallback to request headers) and userId from token (for scenarios where
|
||||
// the cookies are not passed in the request headers)
|
||||
try {
|
||||
const parsedToken = JSON.parse(token) as TUserDetails;
|
||||
userId = parsedToken.id;
|
||||
cookie = parsedToken.cookie;
|
||||
} catch (error) {
|
||||
// If token parsing fails, fallback to request headers
|
||||
console.error("Token parsing failed, using request headers:", error);
|
||||
} finally {
|
||||
// If cookie is still not found, fallback to request headers
|
||||
if (!cookie) {
|
||||
cookie = requestHeaders.cookie?.toString();
|
||||
}
|
||||
}
|
||||
|
||||
if (!cookie || !userId) {
|
||||
throw new Error("Credentials not provided");
|
||||
}
|
||||
|
||||
// set cookie in context, so it can be used throughout the ws connection
|
||||
(context as HocusPocusServerContext).cookie = cookie;
|
||||
|
||||
try {
|
||||
await handleAuthentication({
|
||||
cookie,
|
||||
token,
|
||||
userId,
|
||||
});
|
||||
} catch (error) {
|
||||
throw Error("Authentication unsuccessful!");
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ const userService = new UserService();
|
|||
|
||||
type Props = {
|
||||
cookie: string;
|
||||
token: string;
|
||||
userId: string;
|
||||
};
|
||||
|
||||
export const handleAuthentication = async (props: Props) => {
|
||||
const { cookie, token } = props;
|
||||
const { cookie, userId } = props;
|
||||
// fetch current user info
|
||||
let response;
|
||||
try {
|
||||
|
|
@ -20,7 +20,7 @@ export const handleAuthentication = async (props: Props) => {
|
|||
manualLogger.error("Failed to fetch current user:", error);
|
||||
throw error;
|
||||
}
|
||||
if (response.id !== token) {
|
||||
if (response.id !== userId) {
|
||||
throw Error("Authentication failed: Token doesn't match the current user.");
|
||||
}
|
||||
|
||||
|
|
|
|||
4
live/src/core/types/common.d.ts
vendored
4
live/src/core/types/common.d.ts
vendored
|
|
@ -2,3 +2,7 @@
|
|||
import { TAdditionalDocumentTypes } from "@/plane-live/types/common.js";
|
||||
|
||||
export type TDocumentTypes = "project_page" | TAdditionalDocumentTypes;
|
||||
|
||||
export type HocusPocusServerContext = {
|
||||
cookie: string;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ export const useCollaborativeEditor = (props: TCollaborativeEditorProps) => {
|
|||
name: id,
|
||||
parameters: realtimeConfig.queryParams,
|
||||
// using user id as a token to verify the user on the server
|
||||
token: user.id,
|
||||
token: JSON.stringify(user),
|
||||
url: realtimeConfig.url,
|
||||
onAuthenticationFailed: () => {
|
||||
serverHandler?.onServerError?.();
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ export type TUserDetails = {
|
|||
color: string;
|
||||
id: string;
|
||||
name: string;
|
||||
cookie?: string;
|
||||
};
|
||||
|
||||
export type TRealtimeConfig = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue