Skip to content

Commit e2e9596

Browse files
authored
Merge pull request #43 from Navino16/feature/extra-groups-ids
Very happy with these changes, thank you for the help!
2 parents 65ac81d + a4ae5ec commit e2e9596

5 files changed

Lines changed: 48 additions & 31 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ node_modules
1111
.vscode
1212
.DS_Store
1313
.cursorignore
14+
.idea
1415
tsconfig.tsbuildinfo
1516
docker-compose.test.yml

README.md

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,6 @@
22
<img src="public/heading.png" width="400px">
33
</p>
44

5-
# ATTENTION BREAKING UPDATE!!
6-
7-
> The latest `main` branch has completely changed the way this app used to run.
8-
> The main reason being trying to address some security concerns and make the whole application work
9-
> across multiple platform without too much trouble.
10-
>
11-
> If you came here due to this change trying to figure out why your app stopped working you have two options:
12-
>
13-
> 1 - Update your `docker-compose.yml` with the new one provided within this readme (or just copy [docker-compose.yml](docker-compose.yml))
14-
>
15-
> 2 - Keep your `docker-compose.yml` file as it is and use the legacy tag in the image `image: ghcr.io/fccview/cronmaster:legacy`. However bear in mind this will not be supported going forward, any issue regarding the legacy tag will be ignored and I will only support the main branch. Feel free to fork that specific branch in case you want to work on it yourself :)
16-
175
## Features
186

197
- **Modern UI**: Beautiful, responsive interface with dark/light mode.
@@ -23,6 +11,23 @@
2311
- **Docker Support**: Runs entirely from a Docker container.
2412
- **Easy Setup**: Quick presets for common cron schedules.
2513

14+
<br />
15+
16+
---
17+
18+
<p align="center">
19+
<a href="http://discord.gg/invite/mMuk2WzVZu">
20+
<img width="40" src="public/repo-images/discord_icon.webp">
21+
</a>
22+
<br />
23+
<i>Join the discord server for more info</i>
24+
<br />
25+
</p>
26+
27+
---
28+
29+
<br />
30+
2631
## Before we start
2732

2833
Hey there! 👋 Just a friendly heads-up: I'm a big believer in open source and love sharing my work with the community. Everything you find in my GitHub repos is and always will be 100% free. If someone tries to sell you a "premium" version of any of my projects while claiming to be me, please know that this is not legitimate. 🚫
@@ -166,6 +171,8 @@ HOST_PROJECT_DIR=/home/<your_user_here>/homelab/cronmaster
166171
- `HOST_PROJECT_DIR` is required in order for the scripts created within the app to run properly
167172
- The `DOCKER=true` environment variable enables direct file access mode for crontab operations. This is REQUIRED when running the application in docker mode.
168173

174+
**Important Note on Root Commands**: When running commands as `root` within Cronmaster, ensure that these commands also function correctly as `root` on your host machine. If a command works as `root` on your host but fails within Cronmaster, please open an issue with detailed information.
175+
169176
## Usage
170177

171178
### Viewing System Information
@@ -257,6 +264,9 @@ I would like to thank the following members for raising issues and help test/deb
257264
<td align="center" valign="top" width="20%">
258265
<a href="https://github.com/cerede2000"><img width="100" height="100" src="https://avatars.githubusercontent.com/u/38144752?v=4&size=100"><br />cerede2000</a>
259266
</td>
267+
<td align="center" valign="top" width="20%">
268+
<a href="https://github.com/Navino16"><img width="100" height="100" src="https://avatars.githubusercontent.com/u/22234867?v=4&size=100"><br />Navino16</a>
269+
</td>
260270
</tr>
261271
</tbody>
262272
</table>

app/_server/actions/cronjobs/index.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -265,12 +265,10 @@ export const runCronJob = async (
265265

266266
if (isDocker) {
267267
const userInfo = await getUserInfo(job.user);
268+
const executionUser = userInfo ? userInfo.username : "root";
269+
const escapedCommand = job.command.replace(/'/g, "'\\''");
268270

269-
if (userInfo && userInfo.username !== "root") {
270-
command = `nsenter -t 1 -m -u -i -n -p --setuid=${userInfo.uid} --setgid=${userInfo.gid} sh -c "${job.command}"`;
271-
} else {
272-
command = `nsenter -t 1 -m -u -i -n -p sh -c "${job.command}"`;
273-
}
271+
command = `nsenter -t 1 -m -u -i -n -p su - ${executionUser} -c '${escapedCommand}'`;
274272
}
275273

276274
const { stdout, stderr } = await execAsync(command, {

app/_server/actions/scripts/index.ts

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const sanitizeScriptName = (name: string): string => {
2121
.replace(/-+/g, "-")
2222
.replace(/^-|-$/g, "")
2323
.substring(0, 50);
24-
}
24+
};
2525

2626
const generateUniqueFilename = async (baseName: string): Promise<string> => {
2727
const scripts = await loadAllScripts();
@@ -34,14 +34,14 @@ const generateUniqueFilename = async (baseName: string): Promise<string> => {
3434
}
3535

3636
return filename;
37-
}
37+
};
3838

3939
const ensureScriptsDirectory = async () => {
4040
const scriptsDir = await SCRIPTS_DIR();
4141
if (!existsSync(scriptsDir)) {
4242
await mkdir(scriptsDir, { recursive: true });
4343
}
44-
}
44+
};
4545

4646
const ensureHostScriptsDirectory = async () => {
4747
const hostProjectDir = process.env.HOST_PROJECT_DIR || process.cwd();
@@ -50,7 +50,7 @@ const ensureHostScriptsDirectory = async () => {
5050
if (!existsSync(hostScriptsDir)) {
5151
await mkdir(hostScriptsDir, { recursive: true });
5252
}
53-
}
53+
};
5454

5555
const saveScriptFile = async (filename: string, content: string) => {
5656
const isDocker = process.env.DOCKER === "true";
@@ -59,7 +59,13 @@ const saveScriptFile = async (filename: string, content: string) => {
5959

6060
const scriptPath = join(scriptsDir, filename);
6161
await writeFile(scriptPath, content, "utf8");
62-
}
62+
63+
try {
64+
await execAsync(`chmod +x "${scriptPath}"`);
65+
} catch (error) {
66+
console.error(`Failed to set execute permissions on ${scriptPath}:`, error);
67+
}
68+
};
6369

6470
const deleteScriptFile = async (filename: string) => {
6571
const isDocker = process.env.DOCKER === "true";
@@ -68,11 +74,11 @@ const deleteScriptFile = async (filename: string) => {
6874
if (existsSync(scriptPath)) {
6975
await unlink(scriptPath);
7076
}
71-
}
77+
};
7278

7379
export const fetchScripts = async (): Promise<Script[]> => {
7480
return await loadAllScripts();
75-
}
81+
};
7682

7783
export const createScript = async (
7884
formData: FormData
@@ -120,7 +126,7 @@ export const createScript = async (
120126
console.error("Error creating script:", error);
121127
return { success: false, message: "Error creating script" };
122128
}
123-
}
129+
};
124130

125131
export const updateScript = async (
126132
formData: FormData
@@ -159,7 +165,7 @@ export const updateScript = async (
159165
console.error("Error updating script:", error);
160166
return { success: false, message: "Error updating script" };
161167
}
162-
}
168+
};
163169

164170
export const deleteScript = async (
165171
id: string
@@ -180,7 +186,7 @@ export const deleteScript = async (
180186
console.error("Error deleting script:", error);
181187
return { success: false, message: "Error deleting script" };
182188
}
183-
}
189+
};
184190

185191
export const cloneScript = async (
186192
id: string,
@@ -230,7 +236,7 @@ export const cloneScript = async (
230236
console.error("Error cloning script:", error);
231237
return { success: false, message: "Error cloning script" };
232238
}
233-
}
239+
};
234240

235241
export const getScriptContent = async (filename: string): Promise<string> => {
236242
try {
@@ -263,9 +269,11 @@ export const getScriptContent = async (filename: string): Promise<string> => {
263269
console.error("Error reading script content:", error);
264270
return "";
265271
}
266-
}
272+
};
267273

268-
export const executeScript = async (filename: string): Promise<{
274+
export const executeScript = async (
275+
filename: string
276+
): Promise<{
269277
success: boolean;
270278
output: string;
271279
error: string;
@@ -301,4 +309,4 @@ export const executeScript = async (filename: string): Promise<{
301309
error: error.message || "Unknown error",
302310
};
303311
}
304-
}
312+
};
3.99 KB
Loading

0 commit comments

Comments
 (0)