feat: add actual user for trpc wss-dev-server (#261)
* feat: add actual user for trpc wss-dev-server #233 * chore: address pull request feedback * fix: deepsource issue
This commit is contained in:
@@ -155,9 +155,9 @@ export const boardRouter = createTRPCRouter({
|
||||
save: publicProcedure
|
||||
.input(validation.board.save)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
await ctx.db.transaction(async (tx) => {
|
||||
await ctx.db.transaction(async (transaction) => {
|
||||
const dbBoard = await getFullBoardWithWhere(
|
||||
tx,
|
||||
transaction,
|
||||
eq(boards.id, input.id),
|
||||
);
|
||||
|
||||
@@ -167,7 +167,7 @@ export const boardRouter = createTRPCRouter({
|
||||
);
|
||||
|
||||
if (addedSections.length > 0) {
|
||||
await tx.insert(sections).values(
|
||||
await transaction.insert(sections).values(
|
||||
addedSections.map((section) => ({
|
||||
id: section.id,
|
||||
kind: section.kind,
|
||||
@@ -188,7 +188,7 @@ export const boardRouter = createTRPCRouter({
|
||||
const addedItems = filterAddedItems(inputItems, dbItems);
|
||||
|
||||
if (addedItems.length > 0) {
|
||||
await tx.insert(items).values(
|
||||
await transaction.insert(items).values(
|
||||
addedItems.map((item) => ({
|
||||
id: item.id,
|
||||
kind: item.kind,
|
||||
@@ -226,7 +226,7 @@ export const boardRouter = createTRPCRouter({
|
||||
);
|
||||
|
||||
if (addedIntegrationRelations.length > 0) {
|
||||
await tx.insert(integrationItems).values(
|
||||
await transaction.insert(integrationItems).values(
|
||||
addedIntegrationRelations.map((relation) => ({
|
||||
itemId: relation.itemId,
|
||||
integrationId: relation.integrationId,
|
||||
@@ -237,7 +237,7 @@ export const boardRouter = createTRPCRouter({
|
||||
const updatedItems = filterUpdatedItems(inputItems, dbItems);
|
||||
|
||||
for (const item of updatedItems) {
|
||||
await tx
|
||||
await transaction
|
||||
.update(items)
|
||||
.set({
|
||||
kind: item.kind,
|
||||
@@ -260,7 +260,7 @@ export const boardRouter = createTRPCRouter({
|
||||
const prev = dbBoard.sections.find(
|
||||
(dbSection) => dbSection.id === section.id,
|
||||
);
|
||||
await tx
|
||||
await transaction
|
||||
.update(sections)
|
||||
.set({
|
||||
position: section.position,
|
||||
@@ -282,7 +282,7 @@ export const boardRouter = createTRPCRouter({
|
||||
);
|
||||
|
||||
for (const relation of removedIntegrationRelations) {
|
||||
await tx
|
||||
await transaction
|
||||
.delete(integrationItems)
|
||||
.where(
|
||||
and(
|
||||
@@ -296,7 +296,7 @@ export const boardRouter = createTRPCRouter({
|
||||
|
||||
const itemIds = removedItems.map((item) => item.id);
|
||||
if (itemIds.length > 0) {
|
||||
await tx.delete(items).where(inArray(items.id, itemIds));
|
||||
await transaction.delete(items).where(inArray(items.id, itemIds));
|
||||
}
|
||||
|
||||
const removedSections = filterRemovedItems(
|
||||
@@ -306,7 +306,9 @@ export const boardRouter = createTRPCRouter({
|
||||
const sectionIds = removedSections.map((section) => section.id);
|
||||
|
||||
if (sectionIds.length > 0) {
|
||||
await tx.delete(sections).where(inArray(sections.id, sectionIds));
|
||||
await transaction
|
||||
.delete(sections)
|
||||
.where(inArray(sections.id, sectionIds));
|
||||
}
|
||||
});
|
||||
}),
|
||||
@@ -340,14 +342,14 @@ export const boardRouter = createTRPCRouter({
|
||||
savePermissions: publicProcedure
|
||||
.input(validation.board.savePermissions)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
await ctx.db.transaction(async (tx) => {
|
||||
await tx
|
||||
await ctx.db.transaction(async (transaction) => {
|
||||
await transaction
|
||||
.delete(boardPermissions)
|
||||
.where(eq(boardPermissions.boardId, input.id));
|
||||
if (input.permissions.length === 0) {
|
||||
return;
|
||||
}
|
||||
await tx.insert(boardPermissions).values(
|
||||
await transaction.insert(boardPermissions).values(
|
||||
input.permissions.map((permission) => ({
|
||||
userId: permission.user.id,
|
||||
permission: permission.permission,
|
||||
|
||||
@@ -245,19 +245,27 @@ const key = Buffer.from(
|
||||
|
||||
//Encrypting text
|
||||
export function encryptSecret(text: string): `${string}.${string}` {
|
||||
const iv = crypto.randomBytes(16);
|
||||
const cipher = crypto.createCipheriv(algorithm, Buffer.from(key), iv);
|
||||
const initializationVector = crypto.randomBytes(16);
|
||||
const cipher = crypto.createCipheriv(
|
||||
algorithm,
|
||||
Buffer.from(key),
|
||||
initializationVector,
|
||||
);
|
||||
let encrypted = cipher.update(text);
|
||||
encrypted = Buffer.concat([encrypted, cipher.final()]);
|
||||
return `${encrypted.toString("hex")}.${iv.toString("hex")}`;
|
||||
return `${encrypted.toString("hex")}.${initializationVector.toString("hex")}`;
|
||||
}
|
||||
|
||||
// Decrypting text
|
||||
function decryptSecret(value: `${string}.${string}`) {
|
||||
const [data, dataIv] = value.split(".") as [string, string];
|
||||
const iv = Buffer.from(dataIv, "hex");
|
||||
const initializationVector = Buffer.from(dataIv, "hex");
|
||||
const encryptedText = Buffer.from(data, "hex");
|
||||
const decipher = crypto.createDecipheriv(algorithm, Buffer.from(key), iv);
|
||||
const decipher = crypto.createDecipheriv(
|
||||
algorithm,
|
||||
Buffer.from(key),
|
||||
initializationVector,
|
||||
);
|
||||
let decrypted = decipher.update(encryptedText);
|
||||
decrypted = Buffer.concat([decrypted, decipher.final()]);
|
||||
return decrypted.toString();
|
||||
|
||||
@@ -10,7 +10,6 @@ import { initTRPC, TRPCError } from "@trpc/server";
|
||||
import superjson from "superjson";
|
||||
|
||||
import type { Session } from "@homarr/auth";
|
||||
import { auth } from "@homarr/auth";
|
||||
import { db } from "@homarr/db";
|
||||
import { logger } from "@homarr/log";
|
||||
import { ZodError } from "@homarr/validation";
|
||||
@@ -27,11 +26,11 @@ import { ZodError } from "@homarr/validation";
|
||||
*
|
||||
* @see https://trpc.io/docs/server/context
|
||||
*/
|
||||
export const createTRPCContext = async (opts: {
|
||||
export const createTRPCContext = (opts: {
|
||||
headers: Headers;
|
||||
session: Session | null;
|
||||
}) => {
|
||||
const session = opts.session ?? (await auth());
|
||||
const session = opts.session;
|
||||
const source = opts.headers.get("x-trpc-source") ?? "unknown";
|
||||
|
||||
logger.info(
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { applyWSSHandler } from "@trpc/server/adapters/ws";
|
||||
import { WebSocketServer } from "ws";
|
||||
|
||||
import { getSessionFromToken, sessionTokenCookieName } from "@homarr/auth";
|
||||
import { parseCookies } from "@homarr/common";
|
||||
import { db } from "@homarr/db";
|
||||
import { logger } from "@homarr/log";
|
||||
|
||||
import { appRouter } from "./root";
|
||||
@@ -12,33 +15,41 @@ const wss = new WebSocketServer({
|
||||
const handler = applyWSSHandler({
|
||||
wss,
|
||||
router: appRouter,
|
||||
createContext: ({ req }) => {
|
||||
return createTRPCContext({
|
||||
headers: {
|
||||
...req.headers,
|
||||
get(key: string) {
|
||||
const item = req.headers[key];
|
||||
return typeof item === "string" ? item ?? null : item?.at(0) ?? null;
|
||||
},
|
||||
} as Headers,
|
||||
session: {
|
||||
// TODO: replace with actual session
|
||||
user: {
|
||||
id: "1",
|
||||
name: "Test User",
|
||||
email: "",
|
||||
},
|
||||
expires: new Date().toISOString(),
|
||||
},
|
||||
});
|
||||
createContext: async ({ req }) => {
|
||||
try {
|
||||
const headers = Object.entries(req.headers).map(
|
||||
([key, value]) =>
|
||||
[key, typeof value === "string" ? value : value?.[0]] as [
|
||||
string,
|
||||
string,
|
||||
],
|
||||
);
|
||||
const nextHeaders = new Headers(headers);
|
||||
|
||||
const store = parseCookies(nextHeaders.get("cookie") ?? "");
|
||||
const sessionToken = store[sessionTokenCookieName];
|
||||
|
||||
const session = await getSessionFromToken(db, sessionToken);
|
||||
|
||||
return createTRPCContext({
|
||||
headers: nextHeaders,
|
||||
session,
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
return createTRPCContext({
|
||||
headers: new Headers(),
|
||||
session: null,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
wss.on("connection", (ws, incomingMessage) => {
|
||||
wss.on("connection", (websocket, incomingMessage) => {
|
||||
logger.info(
|
||||
`➕ Connection (${wss.clients.size}) ${incomingMessage.method} ${incomingMessage.url}`,
|
||||
);
|
||||
ws.once("close", (code, reason) => {
|
||||
websocket.once("close", (code, reason) => {
|
||||
logger.info(
|
||||
`➖ Connection (${wss.clients.size}) ${code} ${reason.toString()}`,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user