mirror of
https://github.com/diced/zipline.git
synced 2026-04-28 10:43:06 -07:00
fix: rework passwd protected file logic
This commit is contained in:
@@ -1,13 +1,13 @@
|
|||||||
import * as cookie from 'cookie';
|
|
||||||
import { FastifyRequest } from 'fastify';
|
|
||||||
|
|
||||||
import { config as zConfig } from '@/lib/config';
|
import { config as zConfig } from '@/lib/config';
|
||||||
import { Config } from '@/lib/config/validate';
|
import { Config } from '@/lib/config/validate';
|
||||||
import { verifyPassword } from '@/lib/crypto';
|
import { verifyPassword } from '@/lib/crypto';
|
||||||
import { prisma } from '@/lib/db';
|
import { prisma } from '@/lib/db';
|
||||||
|
import { getPasswordCookie } from '@/lib/passwordCookie';
|
||||||
import { renderHtml } from '@/lib/ssr/renderHtml';
|
import { renderHtml } from '@/lib/ssr/renderHtml';
|
||||||
import { ZiplineTheme } from '@/lib/theme';
|
import { ZiplineTheme } from '@/lib/theme';
|
||||||
import { createRoutes } from './routes'; // This should include the `/url/:id` route
|
import * as cookie from 'cookie';
|
||||||
|
import { FastifyRequest } from 'fastify';
|
||||||
|
import { createRoutes } from './routes';
|
||||||
|
|
||||||
export async function render(
|
export async function render(
|
||||||
{
|
{
|
||||||
@@ -53,7 +53,7 @@ export async function render(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const cookies = cookie.parse(req.headers.cookie || '');
|
const cookies = cookie.parse(req.headers.cookie || '');
|
||||||
const pw = cookies[`url_pw_${urlEntry.id}`];
|
const pw = getPasswordCookie(cookies, 'url', urlEntry.id);
|
||||||
const hasPassword = !!urlEntry.password;
|
const hasPassword = !!urlEntry.password;
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ import { File, fileSelect } from '@/lib/db/models/file';
|
|||||||
import { User, userSelect } from '@/lib/db/models/user';
|
import { User, userSelect } from '@/lib/db/models/user';
|
||||||
import { parseString } from '@/lib/parser';
|
import { parseString } from '@/lib/parser';
|
||||||
import { parserMetrics } from '@/lib/parser/metrics';
|
import { parserMetrics } from '@/lib/parser/metrics';
|
||||||
|
import { getPasswordCookie } from '@/lib/passwordCookie';
|
||||||
import { createZiplineSsr } from '@/lib/ssr/createZiplineSsr';
|
import { createZiplineSsr } from '@/lib/ssr/createZiplineSsr';
|
||||||
|
import { stripHtml } from '@/lib/stripHtml';
|
||||||
import type { ZiplineTheme } from '@/lib/theme';
|
import type { ZiplineTheme } from '@/lib/theme';
|
||||||
import { readThemes } from '@/lib/theme/file';
|
import { readThemes } from '@/lib/theme/file';
|
||||||
import * as cookie from 'cookie';
|
import * as cookie from 'cookie';
|
||||||
@@ -22,7 +24,6 @@ import { FastifyRequest } from 'fastify';
|
|||||||
import { renderToString } from 'react-dom/server';
|
import { renderToString } from 'react-dom/server';
|
||||||
import { createStaticHandler, createStaticRouter, StaticRouterProvider } from 'react-router-dom';
|
import { createStaticHandler, createStaticRouter, StaticRouterProvider } from 'react-router-dom';
|
||||||
import { createRoutes } from './routes';
|
import { createRoutes } from './routes';
|
||||||
import { stripHtml } from '@/lib/stripHtml';
|
|
||||||
|
|
||||||
export const getFile = async (id: string) =>
|
export const getFile = async (id: string) =>
|
||||||
prisma.file.findFirst({
|
prisma.file.findFirst({
|
||||||
@@ -95,7 +96,7 @@ export async function render(
|
|||||||
const config = { website: { theme: zConfig.website.theme } };
|
const config = { website: { theme: zConfig.website.theme } };
|
||||||
|
|
||||||
const cookies = cookie.parse(req.headers.cookie || '');
|
const cookies = cookie.parse(req.headers.cookie || '');
|
||||||
const pw = cookies[`file_pw_${file.id}`];
|
const pw = getPasswordCookie(cookies, 'file', file.id);
|
||||||
const hasPassword = !!file.password;
|
const hasPassword = !!file.password;
|
||||||
|
|
||||||
if (hasPassword) {
|
if (hasPassword) {
|
||||||
|
|||||||
23
src/lib/passwordCookie.ts
Normal file
23
src/lib/passwordCookie.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { config } from '@/lib/config';
|
||||||
|
import { decrypt, encrypt } from '@/lib/crypto';
|
||||||
|
import { FastifyReply } from 'fastify';
|
||||||
|
|
||||||
|
export function setPasswordCookie(res: FastifyReply, kind: 'file' | 'url', id: string, password: string) {
|
||||||
|
res.cookie(`${kind}_pw_${id}`, encrypt(password, config.core.secret), {
|
||||||
|
sameSite: 'lax',
|
||||||
|
expires: new Date(Date.now() + 15 * 60_000),
|
||||||
|
httpOnly: true,
|
||||||
|
secure: config.core.returnHttpsUrls,
|
||||||
|
path: '/',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPasswordCookie(cookies: Record<string, string | undefined>, kind: 'file' | 'url', id: string) {
|
||||||
|
const cookie = cookies[`${kind}_pw_${id}`];
|
||||||
|
if (!cookie) return null;
|
||||||
|
try {
|
||||||
|
return decrypt(cookie, config.core.secret);
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import { prisma } from '@/lib/db';
|
|||||||
import { log } from '@/lib/logger';
|
import { log } from '@/lib/logger';
|
||||||
import { secondlyRatelimit } from '@/lib/ratelimits';
|
import { secondlyRatelimit } from '@/lib/ratelimits';
|
||||||
import { zStringTrimmed } from '@/lib/validation';
|
import { zStringTrimmed } from '@/lib/validation';
|
||||||
|
import { setPasswordCookie } from '@/lib/passwordCookie';
|
||||||
import typedPlugin from '@/server/typedPlugin';
|
import typedPlugin from '@/server/typedPlugin';
|
||||||
import z from 'zod';
|
import z from 'zod';
|
||||||
|
|
||||||
@@ -61,13 +62,7 @@ export default typedPlugin(
|
|||||||
}
|
}
|
||||||
logger.info(`${file.name} was accessed with the correct password`, { ua: req.headers['user-agent'] });
|
logger.info(`${file.name} was accessed with the correct password`, { ua: req.headers['user-agent'] });
|
||||||
|
|
||||||
res.cookie('file_pw_' + file.id, req.body.password, {
|
setPasswordCookie(res, 'file', file.id, req.body.password);
|
||||||
sameSite: 'lax',
|
|
||||||
maxAge: 60,
|
|
||||||
httpOnly: false,
|
|
||||||
secure: false,
|
|
||||||
path: '/',
|
|
||||||
});
|
|
||||||
|
|
||||||
return res.send({ success: true });
|
return res.send({ success: true });
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { prisma } from '@/lib/db';
|
|||||||
import { log } from '@/lib/logger';
|
import { log } from '@/lib/logger';
|
||||||
import { secondlyRatelimit } from '@/lib/ratelimits';
|
import { secondlyRatelimit } from '@/lib/ratelimits';
|
||||||
import { zStringTrimmed } from '@/lib/validation';
|
import { zStringTrimmed } from '@/lib/validation';
|
||||||
|
import { setPasswordCookie } from '@/lib/passwordCookie';
|
||||||
import typedPlugin from '@/server/typedPlugin';
|
import typedPlugin from '@/server/typedPlugin';
|
||||||
import z from 'zod';
|
import z from 'zod';
|
||||||
|
|
||||||
@@ -58,13 +59,7 @@ export default typedPlugin(
|
|||||||
ua: req.headers['user-agent'],
|
ua: req.headers['user-agent'],
|
||||||
});
|
});
|
||||||
|
|
||||||
res.cookie('url_pw_' + url.id, req.body.password, {
|
setPasswordCookie(res, 'url', url.id, req.body.password);
|
||||||
sameSite: 'lax',
|
|
||||||
maxAge: 60,
|
|
||||||
httpOnly: false,
|
|
||||||
secure: false,
|
|
||||||
path: '/',
|
|
||||||
});
|
|
||||||
|
|
||||||
return res.send({ success: true });
|
return res.send({ success: true });
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user