fix(api): logrotate modification & permissions (#1145)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Chores**
- Updated deployment and build commands to use a more efficient package
manager.
- **Refactor**
- Improved the internal file modification structure for enhanced
flexibility and maintainability.
- **New Features**
- Enhanced log management by adding functionality for proper permission
handling and cleanup after operations.
- Introduced a new log rotation configuration for managing log files
effectively.
- Updated timestamps for various components to reflect the latest
download times.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Pujit Mehrotra
2025-02-19 09:13:43 -05:00
committed by GitHub
parent 7539a3ed75
commit b970fd9e6c
10 changed files with 73 additions and 24 deletions

View File

@@ -5,12 +5,12 @@ default:
@just list-commands @just list-commands
setup: setup:
npm install pnpm install
npm run container:build pnpm run container:build
# builds js files that can run on an unraid server # builds js files that can run on an unraid server
@build: @build:
npm run build pnpm run build
# deploys to an unraid server # deploys to an unraid server
@deploy: @deploy:
@@ -18,4 +18,3 @@ setup:
# build & deploy # build & deploy
bd: build deploy bd: build deploy

View File

@@ -27,7 +27,7 @@ export abstract class FileModification {
* Get the path to the applied patch file for the target filePath, saved after applying the patch * Get the path to the applied patch file for the target filePath, saved after applying the patch
* @param targetFile - The path to the file that was patched * @param targetFile - The path to the file that was patched
*/ */
private getPathToAppliedPatch(targetFile: string): string { protected getPathToAppliedPatch(targetFile = this.filePath): string {
const dir = dirname(targetFile); const dir = dirname(targetFile);
const filename = `${basename(targetFile)}.patch`; const filename = `${basename(targetFile)}.patch`;
return join(dir, filename); return join(dir, filename);

View File

@@ -19,7 +19,9 @@ interface ModificationTestCase {
} }
const getPathToFixture = (fileName: string) => resolve(__dirname, `__fixtures__/downloaded/${fileName}`); const getPathToFixture = (fileName: string) => resolve(__dirname, `__fixtures__/downloaded/${fileName}`);
const testCases: ModificationTestCase[] = [
/** Modifications that patch the content of an existing file in one or more places. */
const patchTestCases: ModificationTestCase[] = [
{ {
ModificationClass: DefaultPageLayoutModification, ModificationClass: DefaultPageLayoutModification,
fileUrl: fileUrl:
@@ -43,6 +45,10 @@ const testCases: ModificationTestCase[] = [
fileUrl: 'https://github.com/unraid/webgui/raw/refs/heads/master/emhttp/auth-request.php', fileUrl: 'https://github.com/unraid/webgui/raw/refs/heads/master/emhttp/auth-request.php',
fileName: 'auth-request.php', fileName: 'auth-request.php',
}, },
];
/** Modifications that simply add a new file & remove it on rollback. */
const simpleTestCases: ModificationTestCase[] = [
{ {
ModificationClass: LogRotateModification, ModificationClass: LogRotateModification,
fileUrl: 'logrotate.conf', fileUrl: 'logrotate.conf',
@@ -131,16 +137,24 @@ async function testInvalidModification(testCase: ModificationTestCase, patcher:
await patcher.rollback(); await patcher.rollback();
} }
const allTestCases = [...patchTestCases, ...simpleTestCases];
describe('File modifications', () => { describe('File modifications', () => {
let patcher: FileModification; let patcher: FileModification;
test.each(testCases)(`$fileName modifier correctly applies to fresh install`, async (testCase) => { test.each(allTestCases)(
await testModification(testCase, patcher); `$fileName modifier correctly applies to fresh install`,
}); async (testCase) => {
await testModification(testCase, patcher);
}
);
test.each(testCases)(`$fileName modifier correctly handles invalid content`, async (testCase) => { test.each(patchTestCases)(
await testInvalidModification(testCase, patcher); `$fileName modifier correctly handles invalid content`,
}); async (testCase) => {
await testInvalidModification(testCase, patcher);
}
);
afterEach(async () => { afterEach(async () => {
await patcher?.rollback(); await patcher?.rollback();

View File

@@ -1,4 +1,3 @@
/var/log/unraid-api/*.log { /var/log/unraid-api/*.log {
rotate 1 rotate 1
missingok missingok
@@ -9,4 +8,13 @@
copytruncate copytruncate
create 0640 root root create 0640 root root
} }
/var/log/graphql-api.log {
rotate 1
missingok
size 1M
su root root
compress
delaycompress
copytruncate
create 0640 root root
}

View File

@@ -1,5 +1,5 @@
import { Logger } from '@nestjs/common'; import { Logger } from '@nestjs/common';
import { readFile } from 'node:fs/promises'; import { readFile, rm, writeFile } from 'node:fs/promises';
import { fileExists } from '@app/core/utils/files/file-exists'; import { fileExists } from '@app/core/utils/files/file-exists';
import { import {
@@ -21,7 +21,17 @@ export class LogRotateModification extends FileModification {
copytruncate copytruncate
create 0640 root root create 0640 root root
} }
`; /var/log/graphql-api.log {
rotate 1
missingok
size 1M
su root root
compress
delaycompress
copytruncate
create 0640 root root
}
`.trimStart();
constructor(logger: Logger) { constructor(logger: Logger) {
super(logger); super(logger);
@@ -46,4 +56,15 @@ export class LogRotateModification extends FileModification {
} }
return { shouldApply: true, reason: 'No LogRotate config for the API configured yet' }; return { shouldApply: true, reason: 'No LogRotate config for the API configured yet' };
} }
async apply(): Promise<string> {
await this.rollback();
await writeFile(this.filePath, this.logRotateConfig, { mode: 0o644 });
return this.logRotateConfig;
}
async rollback(): Promise<void> {
await rm(this.getPathToAppliedPatch(), { force: true });
await rm(this.filePath, { force: true });
}
} }

View File

@@ -2,8 +2,7 @@ Index: /etc/logrotate.d/unraid-api
=================================================================== ===================================================================
--- /etc/logrotate.d/unraid-api original --- /etc/logrotate.d/unraid-api original
+++ /etc/logrotate.d/unraid-api modified +++ /etc/logrotate.d/unraid-api modified
@@ -0,0 +1,12 @@ @@ -0,0 +1,20 @@
+
+/var/log/unraid-api/*.log { +/var/log/unraid-api/*.log {
+ rotate 1 + rotate 1
+ missingok + missingok
@@ -14,5 +13,13 @@ Index: /etc/logrotate.d/unraid-api
+ copytruncate + copytruncate
+ create 0640 root root + create 0640 root root
+} +}
+ +/var/log/graphql-api.log {
\ No newline at end of file + rotate 1
+ missingok
+ size 1M
+ su root root
+ compress
+ delaycompress
+ copytruncate
+ create 0640 root root
+}