security advisory fixes opened by kolega-ai-dev

This commit is contained in:
Francis Cao 2026-01-22 09:24:08 -08:00
parent e5f794c329
commit 8f55ed9da9
7 changed files with 36 additions and 13 deletions

View file

@ -10,6 +10,7 @@ import {
TextField,
} from '@umami/react-zen';
import { useMessages, useUpdateQuery } from '@/components/hooks';
import { messages } from '@/components/messages';
import { ROLES } from '@/lib/constants';
export function UserAddForm({ onSave, onClose }) {
@ -37,7 +38,10 @@ export function UserAddForm({ onSave, onClose }) {
<FormField
label={formatMessage(labels.password)}
name="password"
rules={{ required: formatMessage(labels.required) }}
rules={{
required: formatMessage(labels.required),
minLength: { value: 8, message: formatMessage(messages.minPasswordLength, { n: '8' }) },
}}
>
<PasswordField autoComplete="new-password" data-test="input-password" />
</FormField>

View file

@ -1,7 +1,14 @@
import redis from '@/lib/redis';
import { parseRequest } from '@/lib/request';
import { ok } from '@/lib/response';
export async function POST(request: Request) {
const { error } = await parseRequest(request);
if (error) {
return error();
}
if (redis.enabled) {
const token = request.headers.get('authorization')?.split(' ')?.[1];

View file

@ -1,7 +1,7 @@
import { saveAuth } from '@/lib/auth';
import redis from '@/lib/redis';
import { parseRequest } from '@/lib/request';
import { json } from '@/lib/response';
import { json, serverError } from '@/lib/response';
export async function POST(request: Request) {
const { auth, error } = await parseRequest(request);
@ -10,9 +10,13 @@ export async function POST(request: Request) {
return error();
}
if (redis.enabled) {
const token = await saveAuth({ userId: auth.user.id }, 86400);
return json({ user: auth.user, token });
if (!redis.enabled) {
return serverError({
message: 'Redis is disabled',
});
}
const token = await saveAuth({ userId: auth.user.id }, 86400);
return json({ user: auth.user, token });
}

View file

@ -1,7 +1,7 @@
import { z } from 'zod';
import { hashPassword } from '@/lib/password';
import { parseRequest } from '@/lib/request';
import { badRequest, json, ok, unauthorized } from '@/lib/response';
import { badRequest, json, notFound, ok, unauthorized } from '@/lib/response';
import { userRoleParam } from '@/lib/schema';
import { canDeleteUser, canUpdateUser, canViewUser } from '@/permissions';
import { deleteUser, getUser, getUserByUsername, updateUser } from '@/queries/prisma';
@ -27,7 +27,7 @@ export async function GET(request: Request, { params }: { params: Promise<{ user
export async function POST(request: Request, { params }: { params: Promise<{ userId: string }> }) {
const schema = z.object({
username: z.string().max(255).optional(),
password: z.string().max(255).optional(),
password: z.string().min(8).max(255).optional(),
role: userRoleParam.optional(),
});
@ -47,6 +47,10 @@ export async function POST(request: Request, { params }: { params: Promise<{ use
const user = await getUser(userId);
if (!user) {
return notFound();
}
const data: any = {};
if (password) {

View file

@ -4,6 +4,7 @@ import { uuid } from '@/lib/crypto';
import { hashPassword } from '@/lib/password';
import { parseRequest } from '@/lib/request';
import { badRequest, json, unauthorized } from '@/lib/response';
import { userRoleParam } from '@/lib/schema';
import { canCreateUser } from '@/permissions';
import { createUser, getUserByUsername } from '@/queries/prisma';
@ -11,8 +12,8 @@ export async function POST(request: Request) {
const schema = z.object({
id: z.uuid().optional(),
username: z.string().max(255),
password: z.string(),
role: z.string().regex(/admin|user|view-only/i),
password: z.string().min(8).max(255),
role: userRoleParam,
});
const { auth, body, error } = await parseRequest(request, schema);