fix(security): update dependencies to avoid RCE and other exploits
Обновлены зависимости Node.js, которые были уязвимы с разной степенью критичности. Обновлен Next.js, так как его предыдущая используемая версия привнесла в production-среду постоянную борьбу с майнерами. К сожалению, в этом коммите парсер расписания сломан.
This commit is contained in:
@@ -364,8 +364,8 @@ export default function AdminPage({ groups: initialGroups, settings: initialSett
|
||||
try {
|
||||
const res = await fetch('/api/admin/logs')
|
||||
const data = await res.json()
|
||||
if (data.success && data.logs) {
|
||||
setLogs(data.logs)
|
||||
if (data.success) {
|
||||
setLogs(data.logs ?? '')
|
||||
} else {
|
||||
setLogs(data.error || 'Не удалось загрузить логи')
|
||||
}
|
||||
@@ -533,6 +533,19 @@ export default function AdminPage({ groups: initialGroups, settings: initialSett
|
||||
disabled={loading}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center justify-between p-4 border rounded-lg">
|
||||
<div>
|
||||
<div className="font-semibold">Кнопка "Преподаватели"</div>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
Отображать кнопку перехода к расписанию преподавателей на главной странице
|
||||
</div>
|
||||
</div>
|
||||
<ToggleSwitch
|
||||
checked={settings.showTeachersButton ?? true}
|
||||
onChange={(checked) => handleUpdateSettings({ ...settings, showTeachersButton: checked })}
|
||||
disabled={loading}
|
||||
/>
|
||||
</div>
|
||||
<div className="p-4 border rounded-lg">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<div>
|
||||
@@ -892,7 +905,7 @@ export default function AdminPage({ groups: initialGroups, settings: initialSett
|
||||
<DialogHeader>
|
||||
<DialogTitle>Логи ошибок</DialogTitle>
|
||||
<DialogDescription>
|
||||
Содержимое файла error.log
|
||||
Ошибки парсинга записываются в error.log. Если записей пока нет — здесь будет пусто.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="mt-4">
|
||||
|
||||
@@ -14,18 +14,18 @@ async function handler(
|
||||
// Путь к файлу логов (в корне проекта)
|
||||
const logPath = path.join(process.cwd(), 'error.log')
|
||||
|
||||
// Проверяем существование файла
|
||||
// Проверяем существование файла (если нет — возвращаем пустую строку, UI покажет «Логи пусты»)
|
||||
if (!fs.existsSync(logPath)) {
|
||||
res.status(200).json({ success: true, logs: 'Файл логов пуст или не существует.' })
|
||||
res.status(200).json({ success: true, logs: '' })
|
||||
return
|
||||
}
|
||||
|
||||
// Читаем файл
|
||||
const logs = fs.readFileSync(logPath, 'utf8')
|
||||
|
||||
// Если файл пуст
|
||||
|
||||
// Если файл пуст — возвращаем пустую строку
|
||||
if (!logs || logs.trim().length === 0) {
|
||||
res.status(200).json({ success: true, logs: 'Файл логов пуст.' })
|
||||
res.status(200).json({ success: true, logs: '' })
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ async function handler(
|
||||
const currentSettings = loadSettings(true)
|
||||
|
||||
// Обновление настроек
|
||||
const { weekNavigationEnabled, showAddGroupButton, vacationModeEnabled, vacationModeContent, debug } = req.body
|
||||
const { weekNavigationEnabled, showAddGroupButton, showTeachersButton, vacationModeEnabled, vacationModeContent, debug } = req.body
|
||||
|
||||
if (typeof weekNavigationEnabled !== 'boolean') {
|
||||
res.status(400).json({ error: 'weekNavigationEnabled must be a boolean' })
|
||||
@@ -36,6 +36,11 @@ async function handler(
|
||||
return
|
||||
}
|
||||
|
||||
if (showTeachersButton !== undefined && typeof showTeachersButton !== 'boolean') {
|
||||
res.status(400).json({ error: 'showTeachersButton must be a boolean' })
|
||||
return
|
||||
}
|
||||
|
||||
if (vacationModeEnabled !== undefined && typeof vacationModeEnabled !== 'boolean') {
|
||||
res.status(400).json({ error: 'vacationModeEnabled must be a boolean' })
|
||||
return
|
||||
@@ -77,6 +82,7 @@ async function handler(
|
||||
...currentSettings,
|
||||
weekNavigationEnabled,
|
||||
showAddGroupButton: showAddGroupButton !== undefined ? showAddGroupButton : (currentSettings.showAddGroupButton ?? true),
|
||||
showTeachersButton: showTeachersButton !== undefined ? showTeachersButton : (currentSettings.showTeachersButton ?? true),
|
||||
vacationModeEnabled: vacationModeEnabled !== undefined ? vacationModeEnabled : (currentSettings.vacationModeEnabled ?? false),
|
||||
vacationModeContent: vacationModeContent !== undefined ? vacationModeContent : (currentSettings.vacationModeContent || ''),
|
||||
...(validatedDebug !== undefined && { debug: validatedDebug })
|
||||
|
||||
@@ -32,6 +32,7 @@ type NormalModeProps = {
|
||||
groups: GroupsData
|
||||
groupsByCourse: { [course: number]: Array<{ id: string; name: string }> }
|
||||
showAddGroupButton: boolean
|
||||
showTeachersButton: boolean
|
||||
}
|
||||
|
||||
type HomePageProps = VacationModeProps | NormalModeProps
|
||||
@@ -113,7 +114,7 @@ export default function HomePage(props: HomePageProps) {
|
||||
}
|
||||
|
||||
// Обычный режим - список групп
|
||||
const { groups, groupsByCourse, showAddGroupButton } = props
|
||||
const { groups, groupsByCourse, showAddGroupButton, showTeachersButton } = props
|
||||
const [openCourses, setOpenCourses] = React.useState<Set<number>>(new Set())
|
||||
const [addGroupDialogOpen, setAddGroupDialogOpen] = React.useState(false)
|
||||
|
||||
@@ -235,16 +236,18 @@ export default function HomePage(props: HomePageProps) {
|
||||
)}
|
||||
|
||||
{/* Кнопка перехода к расписанию преподавателей */}
|
||||
<div
|
||||
className="stagger-card mt-6"
|
||||
style={{ animationDelay: `${0.15 + courseOffsets.totalGroups * 0.04 + 0.05}s` } as React.CSSProperties}
|
||||
>
|
||||
<Link href="/teachers" className="block">
|
||||
<Button variant="default" className="w-full h-auto py-4 text-base font-semibold">
|
||||
Расписание преподавателей
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
{showTeachersButton && (
|
||||
<div
|
||||
className="stagger-card mt-6"
|
||||
style={{ animationDelay: `${0.15 + courseOffsets.totalGroups * 0.04 + 0.05}s` } as React.CSSProperties}
|
||||
>
|
||||
<Link href="/teachers" className="block">
|
||||
<Button variant="default" className="w-full h-auto py-4 text-base font-semibold">
|
||||
Расписание преподавателей
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex flex-col sm:flex-row items-center justify-center gap-3 mt-8">
|
||||
{showAddGroupButton && (
|
||||
@@ -349,7 +352,8 @@ export const getServerSideProps: GetServerSideProps<HomePageProps> = async () =>
|
||||
vacationModeEnabled: false,
|
||||
groups,
|
||||
groupsByCourse,
|
||||
showAddGroupButton: settings.showAddGroupButton ?? true
|
||||
showAddGroupButton: settings.showAddGroupButton ?? true,
|
||||
showTeachersButton: settings.showTeachersButton ?? true
|
||||
} as NormalModeProps
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user