feat(systemd-manager): Support sudo password and root detection in SystemdManager; add user/group support in services and templates; add tests and expand README
This commit is contained in:
@@ -31,13 +31,29 @@ export class SmartDaemonSystemdManager {
|
||||
public smartsystem: plugins.smartsystem.Smartsystem;
|
||||
|
||||
public shouldExecute: boolean = false;
|
||||
public isRoot: boolean = false;
|
||||
public sudoPassword?: string;
|
||||
|
||||
constructor(smartdaemonRefArg: SmartDaemon) {
|
||||
constructor(smartdaemonRefArg: SmartDaemon, sudoPasswordArg?: string) {
|
||||
this.smartdaemonRef = smartdaemonRefArg;
|
||||
this.smartshellInstance = new plugins.smartshell.Smartshell({
|
||||
executor: 'bash',
|
||||
});
|
||||
this.smartsystem = new plugins.smartsystem.Smartsystem();
|
||||
this.sudoPassword = sudoPasswordArg;
|
||||
|
||||
// Check if we're running as root
|
||||
this.checkIsRoot().then(isRoot => {
|
||||
this.isRoot = isRoot;
|
||||
if (!isRoot) {
|
||||
console.log('Not running as root. Sudo will be used for privileged operations.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async checkIsRoot(): Promise<boolean> {
|
||||
const result = await this.smartshellInstance.exec('id -u');
|
||||
return result.stdout.trim() === '0';
|
||||
}
|
||||
|
||||
public async checkElegibility() {
|
||||
@@ -52,7 +68,28 @@ export class SmartDaemonSystemdManager {
|
||||
|
||||
public async execute(commandArg: string) {
|
||||
if (await this.checkElegibility()) {
|
||||
await this.smartshellInstance.exec(commandArg);
|
||||
// Only use sudo if we're not root and command doesn't already have sudo
|
||||
if (!this.isRoot && !commandArg.startsWith('sudo')) {
|
||||
commandArg = `sudo ${commandArg}`;
|
||||
|
||||
if (this.sudoPassword) {
|
||||
// Use interactive PTY mode for password input
|
||||
const interactiveExec = await this.smartshellInstance.execInteractiveControlPty(commandArg);
|
||||
await interactiveExec.sendLine(this.sudoPassword);
|
||||
const result = await interactiveExec.finalPromise;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Execute command (with or without sudo)
|
||||
try {
|
||||
await this.smartshellInstance.exec(commandArg);
|
||||
} catch (error) {
|
||||
if (!this.isRoot && error.message && error.message.includes('authentication')) {
|
||||
throw new Error('Sudo authentication failed. Please configure passwordless sudo or provide a sudo password.');
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,18 +138,31 @@ export class SmartDaemonSystemdManager {
|
||||
|
||||
public async saveService(serviceArg: SmartDaemonService) {
|
||||
if (await this.checkElegibility()) {
|
||||
await plugins.smartfile.memory.toFs(
|
||||
this.smartdaemonRef.templateManager.generateUnitFileForService(serviceArg),
|
||||
SmartDaemonSystemdManager.createFilePathFromServiceName(serviceArg.name)
|
||||
);
|
||||
const content = this.smartdaemonRef.templateManager.generateUnitFileForService(serviceArg);
|
||||
const targetPath = SmartDaemonSystemdManager.createFilePathFromServiceName(serviceArg.name);
|
||||
|
||||
if (this.isRoot) {
|
||||
// Direct write when running as root
|
||||
await plugins.smartfile.memory.toFs(content, targetPath);
|
||||
} else {
|
||||
// Use sudo to write when not root
|
||||
const tempPath = `/tmp/smartdaemon_${serviceArg.name}.service`;
|
||||
await plugins.smartfile.memory.toFs(content, tempPath);
|
||||
await this.execute(`mv ${tempPath} ${targetPath}`); // execute() will add sudo
|
||||
await this.execute(`chmod 644 ${targetPath}`); // execute() will add sudo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async deleteService(serviceArg: SmartDaemonService) {
|
||||
if (await this.checkElegibility()) {
|
||||
await plugins.smartfile.fs.remove(
|
||||
SmartDaemonSystemdManager.createServiceNameFromServiceName(serviceArg.name)
|
||||
);
|
||||
const filePath = SmartDaemonSystemdManager.createFilePathFromServiceName(serviceArg.name);
|
||||
|
||||
if (this.isRoot) {
|
||||
await plugins.smartfile.fs.remove(filePath);
|
||||
} else {
|
||||
await this.execute(`rm ${filePath}`); // execute() will add sudo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user