penguins-eggs 25.11.21 → 25.12.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/.oclif.manifest.json +53 -41
  2. package/README.md +80 -36
  3. package/README.pdf +21575 -3241
  4. package/addons/eggs/theme/livecd/full.grub.main.cfg +39 -4
  5. package/addons/eggs/theme/livecd/full.isolinux.main.cfg +47 -4
  6. package/bin/run.js +11 -0
  7. package/conf/derivatives.yaml +4 -2
  8. package/conf/exclude.list.d/var.list +11 -6
  9. package/dist/appimage/dependency-manager.d.ts +31 -0
  10. package/dist/appimage/dependency-manager.js +292 -0
  11. package/dist/appimage/first-run-check.js +3 -3
  12. package/dist/bin/run.js +11 -0
  13. package/dist/classes/cli-autologin.js +78 -53
  14. package/dist/classes/compressors.d.ts +7 -10
  15. package/dist/classes/compressors.js +44 -31
  16. package/dist/classes/daddy.js +11 -11
  17. package/dist/classes/distro.js +2 -2
  18. package/dist/classes/diversions.js +2 -3
  19. package/dist/classes/incubation/fisherman-helper/initcpio.d.ts +4 -0
  20. package/dist/classes/incubation/fisherman-helper/initcpio.js +14 -4
  21. package/dist/classes/incubation/fisherman-helper/settings.js +1 -1
  22. package/dist/classes/incubation/fisherman.js +1 -3
  23. package/dist/classes/incubation/incubator.js +1 -1
  24. package/dist/classes/network.d.ts +1 -1
  25. package/dist/classes/ovary.d/create-xdg-autostart.js +1 -1
  26. package/dist/classes/ovary.d/edit-live-fs.d.ts +1 -12
  27. package/dist/classes/ovary.d/edit-live-fs.js +216 -186
  28. package/dist/classes/ovary.d/fertilization.js +1 -1
  29. package/dist/classes/ovary.d/make-dot-disk.js +1 -1
  30. package/dist/classes/ovary.d/produce.js +1 -1
  31. package/dist/classes/ovary.d/user-create-live.d.ts +4 -10
  32. package/dist/classes/ovary.d/user-create-live.js +82 -84
  33. package/dist/classes/ovary.d/users-remove.d.ts +5 -6
  34. package/dist/classes/ovary.d/users-remove.js +61 -31
  35. package/dist/classes/ovary.d/xorriso-command.js +1 -5
  36. package/dist/classes/ovary.d.ts +2 -2
  37. package/dist/classes/ovary.js +2 -2
  38. package/dist/classes/pacman.d/alpine.js +2 -2
  39. package/dist/classes/pacman.d/archlinux.js +2 -2
  40. package/dist/classes/pacman.d/debian.js +2 -3
  41. package/dist/classes/pacman.d/fedora.js +2 -3
  42. package/dist/classes/pacman.d/openmamba.js +2 -3
  43. package/dist/classes/pacman.d/opensuse.js +2 -3
  44. package/dist/classes/pacman.d.ts +21 -12
  45. package/dist/classes/pacman.js +55 -47
  46. package/dist/classes/pve-live.js +1 -1
  47. package/dist/classes/settings.js +1 -1
  48. package/dist/classes/sys-users.d.ts +76 -0
  49. package/dist/classes/sys-users.js +206 -0
  50. package/dist/classes/utils.d/kernel.js +3 -3
  51. package/dist/classes/utils.d.ts +16 -11
  52. package/dist/classes/utils.js +92 -56
  53. package/dist/classes/xdg.js +1 -1
  54. package/dist/classes/yolk.js +2 -4
  55. package/dist/commands/config.js +3 -14
  56. package/dist/commands/cuckoo.js +1 -1
  57. package/dist/commands/export/appimage.js +3 -3
  58. package/dist/commands/export/pkg.js +3 -3
  59. package/dist/commands/export/tarballs.js +3 -3
  60. package/dist/commands/krill.js +1 -1
  61. package/dist/commands/produce.js +9 -4
  62. package/dist/commands/{setup.d.ts → setup/install.d.ts} +1 -5
  63. package/dist/commands/setup/install.js +71 -0
  64. package/dist/commands/setup/purge.d.ts +17 -0
  65. package/dist/commands/setup/purge.js +71 -0
  66. package/dist/commands/tools/yolk.js +1 -1
  67. package/dist/commands/update.d.ts +15 -0
  68. package/dist/commands/update.js +74 -7
  69. package/dist/interfaces/i-exec.d.ts +1 -0
  70. package/dist/krill/classes/prepare.d/location.js +1 -1
  71. package/dist/krill/classes/prepare.d/partitions.js +1 -1
  72. package/dist/krill/classes/prepare.d/users.js +2 -2
  73. package/dist/krill/classes/prepare.js +5 -5
  74. package/dist/krill/classes/sequence.d/add_user.d.ts +3 -15
  75. package/dist/krill/classes/sequence.d/add_user.js +87 -57
  76. package/dist/krill/classes/sequence.d/change_password.d.ts +5 -7
  77. package/dist/krill/classes/sequence.d/change_password.js +25 -10
  78. package/dist/krill/classes/sequence.d/del_live_user.d.ts +5 -7
  79. package/dist/krill/classes/sequence.d/del_live_user.js +39 -25
  80. package/dist/krill/classes/sequence.d/fstab.js +1 -1
  81. package/dist/krill/classes/sequence.d/grubcfg.d.ts +3 -7
  82. package/dist/krill/classes/sequence.d/grubcfg.js +33 -13
  83. package/dist/krill/classes/sequence.d/mkfs.js +1 -2
  84. package/dist/krill/classes/sequence.d/unpackfs.d.ts +2 -4
  85. package/dist/krill/classes/sequence.d/unpackfs.js +8 -5
  86. package/dist/krill/classes/sequence.js +2 -3
  87. package/dist/krill/components/title.js +4 -4
  88. package/dist/krill/lib/select_installation_device.js +1 -1
  89. package/dist/krill/lib/select_replaced_partition.js +1 -1
  90. package/dist/lib/utils.d.ts +51 -19
  91. package/dist/lib/utils.js +225 -39
  92. package/manpages/doc/man/eggs.1.gz +0 -0
  93. package/manpages/doc/man/eggs.html +29 -17
  94. package/package.json +13 -14
  95. package/perrisbrewery/template/dependencies.yaml +1 -0
  96. package/scripts/_eggs +35 -7
  97. package/scripts/boot-encrypted-root.sh +220 -0
  98. package/scripts/eggs.bash +2 -1
  99. package/scripts/mount-encrypted-home.sh +324 -0
  100. package/dist/appimage/prerequisites.d.ts +0 -34
  101. package/dist/appimage/prerequisites.js +0 -350
  102. package/dist/commands/setup.js +0 -90
  103. package/dracut/create-symlink +0 -71
  104. package/dracut/dracut-log.txt +0 -3
  105. package/dracut/export +0 -4
  106. package/dracut/export-dracut-analysis +0 -51
  107. package/dracut/export-dracut-log +0 -2
  108. package/dracut/mkisofs +0 -10
  109. package/dracut/renew-initramfs +0 -17
  110. package/dracut/sbin2bin +0 -10
  111. package/dracut/update-dracut-conf-d +0 -2
  112. package/dracut/update-dracut-modules +0 -62
  113. package/scripts/appimage-build.sh +0 -152
  114. package/scripts/appimage-install.sh +0 -43
@@ -11,7 +11,7 @@ import Distro from '../classes/distro.js';
11
11
  import Tools from '../classes/tools.js';
12
12
  import Utils from '../classes/utils.js';
13
13
  import Diversions from '../classes/diversions.js';
14
- import { exec } from '../lib/utils.js';
14
+ import { exec, spawn } from '../lib/utils.js';
15
15
  import axios from 'axios';
16
16
  import https from 'node:https';
17
17
  const agent = new https.Agent({
@@ -57,8 +57,13 @@ export default class Update extends Command {
57
57
  await this.getPkgFromLan();
58
58
  break;
59
59
  }
60
- case 'Package_Manager': {
61
- await this.getPkgFromPackageManager();
60
+ case 'Internet': {
61
+ if (Utils.isAppImage()) {
62
+ await this.getLatestAppImage();
63
+ }
64
+ else {
65
+ await this.getPkgFromPackageManager();
66
+ }
62
67
  break;
63
68
  }
64
69
  case 'Source': {
@@ -73,7 +78,7 @@ export default class Update extends Command {
73
78
  */
74
79
  async choosePkg() {
75
80
  const choices = ['Abort'];
76
- choices.push('LAN', 'Package_Manager', 'Source');
81
+ choices.push('LAN', 'Internet', 'Source');
77
82
  const questions = [
78
83
  {
79
84
  choices,
@@ -92,6 +97,7 @@ export default class Update extends Command {
92
97
  *
93
98
  */
94
99
  async getPkgFromPackageManager() {
100
+ Utils.titles(`update from package Manager`);
95
101
  let cmd = "";
96
102
  if (this.distro.familyId === 'alpine') {
97
103
  cmd = `doas apk add penguins-egga`;
@@ -111,7 +117,6 @@ export default class Update extends Command {
111
117
  else if (this.distro.familyId === "opensuse") {
112
118
  cmd = 'sudo zypper install penguins-eggs\\zypper install --force penguins-eggs';
113
119
  }
114
- Utils.titles(`update`);
115
120
  Utils.warning(`To install/update penguins-eggs cut and copy one of the follow commands`);
116
121
  console.log();
117
122
  console.log(cmd);
@@ -129,10 +134,10 @@ export default class Update extends Command {
129
134
  let install = '';
130
135
  let repo = '';
131
136
  if (Utils.isAppImage()) {
132
- console.log("AppImage: penguins-eggs-*-x86_64.AppImage will be installed as /usr/local/bin/eggs");
137
+ console.log("AppImage: penguins-eggs-*-x86_64.AppImage will be installed as /usr/bin/eggs");
133
138
  filter = `penguins-eggs-*-x86_64.AppImage`;
134
139
  copy = `scp ${Tu.config.remoteUser}@${Tu.config.remoteHost}:${Tu.config.remotePathPackages}/${filter} /tmp`;
135
- install = `mkdir -p /usr/local/bin |mv /tmp/${filter} /usr/local/bin/eggs`;
140
+ install = `mv /tmp/${filter} /usr/bin/eggs`;
136
141
  }
137
142
  else {
138
143
  /**
@@ -244,4 +249,66 @@ export default class Update extends Command {
244
249
  console.log('- ' + country[0] + ': ' + country[1]);
245
250
  }
246
251
  }
252
+ /**
253
+ *
254
+ */
255
+ async getLatestAppImage() {
256
+ let url = await this.getLatestAppImageUrl();
257
+ console.log(`Downloading AppImage from ${url}`);
258
+ let AppFile = '/tmp/eggs.AppImage';
259
+ if (url !== null) {
260
+ await this.downloadWithCurl(url, AppFile);
261
+ }
262
+ await exec(`mv ${AppFile} /usr/bin/eggs`);
263
+ await exec(`chmod +x /usr/bin/eggs`);
264
+ }
265
+ /**
266
+ *
267
+ */
268
+ async getLatestAppImageUrl() {
269
+ const repo = 'pieroproietti/penguins-eggs';
270
+ const apiUrl = `https://api.github.com/repos/${repo}/releases/latest`;
271
+ try {
272
+ const response = await fetch(apiUrl);
273
+ if (!response.ok)
274
+ throw new Error(`Errore API GitHub: ${response.statusText}`);
275
+ const data = await response.json();
276
+ // Cerchiamo l'asset che finisce per .AppImage
277
+ const asset = data.assets.find((a) => a.name.endsWith('.AppImage'));
278
+ return asset ? asset.browser_download_url : null;
279
+ }
280
+ catch (error) {
281
+ console.error(" :", error);
282
+ return null;
283
+ }
284
+ }
285
+ /**
286
+ *
287
+ * @param url
288
+ * @param outputFilename
289
+ * @returns
290
+ */
291
+ async downloadWithCurl(url, outputFilename) {
292
+ return new Promise((resolve, reject) => {
293
+ console.log(`Avvio download di: ${outputFilename}...`);
294
+ // Spawniamo il processo curl
295
+ // -L: segue i redirect (fondamentale per GitHub)
296
+ // -o: specifica il file di output
297
+ const curl = spawn('curl', ['-L', '-o', outputFilename, url], {
298
+ stdio: 'inherit' // Questo mostra la progress bar di curl direttamente nel tuo terminale!
299
+ });
300
+ curl.on('close', (code) => {
301
+ if (code === 0) {
302
+ console.log('\nDownload completato con successo!');
303
+ resolve();
304
+ }
305
+ else {
306
+ reject(new Error(`Curl è uscito con codice errore: ${code}`));
307
+ }
308
+ });
309
+ curl.on('error', (err) => {
310
+ reject(new Error(`Impossibile avviare curl. È installato? ${err.message}`));
311
+ });
312
+ });
313
+ }
247
314
  }
@@ -8,4 +8,5 @@
8
8
  export interface IExec {
9
9
  code: number;
10
10
  data: string;
11
+ error?: string;
11
12
  }
@@ -12,7 +12,7 @@ import Location from '../../components/location.js';
12
12
  import selectRegions from '../../lib/select_regions.js';
13
13
  import selectZones from '../../lib/select_zones.js';
14
14
  import axios from 'axios';
15
- import shx from 'shelljs';
15
+ import { shx } from '../../../lib/utils.js';
16
16
  /**
17
17
  *
18
18
  * @param this
@@ -14,7 +14,7 @@ import selectFileSystemType from '../../lib/select_filesystem_type.js';
14
14
  import selectInstallationDevice from '../../lib/select_installation_device.js';
15
15
  import selectReplacedPartition from '../../lib/select_replaced_partition.js';
16
16
  import selectUserSwapChoice from '../../lib/select_user_swap_choice.js';
17
- import shx from 'shelljs';
17
+ import { shx } from '../../../lib/utils.js';
18
18
  import selectInstallationMode from '../../lib/select_installation_mode.js';
19
19
  /**
20
20
  * PARTITIONS
@@ -13,7 +13,7 @@ import getUsername from '../../lib/get_username.js';
13
13
  import getUserfullname from '../../lib/get_userfullname.js';
14
14
  import getPassword from '../../lib/get_password.js';
15
15
  import getHostname from '../../lib/get_hostname.js';
16
- import shx from 'shelljs';
16
+ import { shx } from '../../../lib/utils.js';
17
17
  /**
18
18
  * USERS
19
19
  */
@@ -36,7 +36,7 @@ export async function users() {
36
36
  }
37
37
  let hostname = this.krillConfig.hostname;
38
38
  if (hostname === '' || hostname === undefined) {
39
- hostname = shx.exec('cat /etc/hostname').trim();
39
+ hostname = shx.exec('cat /etc/hostname').stdout.trim();
40
40
  }
41
41
  let autologin = true;
42
42
  let sameUserPassword = true;
@@ -8,7 +8,7 @@
8
8
  */
9
9
  import os from 'os';
10
10
  import fs from 'fs';
11
- import shx from 'shelljs';
11
+ import { shx } from '../../lib/utils.js';
12
12
  import axios from 'axios';
13
13
  import { SwapChoice, InstallationMode, FsType } from './krill_enums.js';
14
14
  import Keyboards from '../../classes/keyboards.js';
@@ -199,15 +199,15 @@ export default class Krill {
199
199
  generateHostname(ip, random) {
200
200
  let hostname = this.krillConfig.hostname;
201
201
  if (hostname === '') {
202
- hostname = shx.exec('cat /etc/hostname', { silent: true }).trim();
202
+ hostname = shx.exec('cat /etc/hostname', { silent: true }).stdout.trim();
203
203
  }
204
204
  if (ip) {
205
205
  hostname = 'ip-' + Utils.address().replaceAll('.', '-');
206
206
  }
207
207
  if (random) {
208
- const fl = shx.exec(`tr -dc a-z </dev/urandom | head -c 2 ; echo ''`, { silent: true }).trim();
209
- const n = shx.exec(`tr -dc 0-9 </dev/urandom | head -c 3 ; echo ''`, { silent: true }).trim();
210
- const sl = shx.exec(`tr -dc a-z </dev/urandom | head -c 2 ; echo ''`, { silent: true }).trim();
208
+ const fl = shx.exec(`tr -dc a-z </dev/urandom | head -c 2 ; echo ''`, { silent: true }).stdout.trim();
209
+ const n = shx.exec(`tr -dc 0-9 </dev/urandom | head -c 3 ; echo ''`, { silent: true }).stdout.trim();
210
+ const sl = shx.exec(`tr -dc a-z </dev/urandom | head -c 2 ; echo ''`, { silent: true }).stdout.trim();
211
211
  hostname = `${os.hostname()}-${fl}${n}${sl}`;
212
212
  }
213
213
  return hostname;
@@ -1,20 +1,8 @@
1
1
  /**
2
- * ./src/krill/modules/add-user.ts
2
+ * ./src/krill/classes/secquence.d/add-user.ts
3
3
  * penguins-eggs v.25.7.x / ecmascript 2020
4
- * author: Piero Proietti
5
- * email: piero.proietti@gmail.com
6
- * license: MIT
7
- * https://stackoverflow.com/questions/23876782/how-do-i-split-a-typescript-class-into-multiple-files
4
+ * * REFACTORED: Uses "The SysUser Master" class.
5
+ * Replaces chroot/binary dependencies with pure Node.js manipulation.
8
6
  */
9
7
  import Sequence from '../sequence.js';
10
- /**
11
- *
12
- * @param this
13
- * @param username
14
- * @param password
15
- * @param fullusername
16
- * @param roomNumber
17
- * @param workPhone
18
- * @param homePhone
19
- */
20
8
  export default function addUser(this: Sequence, username?: string, password?: string, fullusername?: string, roomNumber?: string, workPhone?: string, homePhone?: string): Promise<void>;
@@ -1,77 +1,107 @@
1
1
  /**
2
- * ./src/krill/modules/add-user.ts
2
+ * ./src/krill/classes/secquence.d/add-user.ts
3
3
  * penguins-eggs v.25.7.x / ecmascript 2020
4
- * author: Piero Proietti
5
- * email: piero.proietti@gmail.com
6
- * license: MIT
7
- * https://stackoverflow.com/questions/23876782/how-do-i-split-a-typescript-class-into-multiple-files
4
+ * * REFACTORED: Uses "The SysUser Master" class.
5
+ * Replaces chroot/binary dependencies with pure Node.js manipulation.
8
6
  */
9
- import Utils from '../../../classes/utils.js';
7
+ import SysUsers from '../../../classes/sys-users.js';
8
+ import { exec } from '../../../lib/utils.js';
10
9
  import fs from 'fs';
10
+ import path from 'path';
11
11
  import yaml from 'js-yaml';
12
- import { exec } from '../../../lib/utils.js';
13
- /**
14
- *
15
- * @param this
16
- * @param username
17
- * @param password
18
- * @param fullusername
19
- * @param roomNumber
20
- * @param workPhone
21
- * @param homePhone
22
- */
23
12
  export default async function addUser(username = 'live', password = 'evolution', fullusername = '', roomNumber = '', workPhone = '', homePhone = '') {
24
- // adduser user
25
- let cmd = `chroot ${this.installTarget} adduser ${username} --home /home/${username} --shell /bin/bash --disabled-password --gecos "${fullusername},${roomNumber},${workPhone},${homePhone}" ${this.toNull}`;
26
- if (this.distro.familyId === 'archlinux') {
27
- cmd = `chroot ${this.installTarget} useradd --create-home --shell /bin/bash ${username} ${this.toNull}`;
28
- }
29
- else if (this.distro.familyId === 'fedora') {
30
- cmd = `chroot ${this.installTarget} adduser ${username} --create-home --shell /bin/bash --comment "${fullusername},${roomNumber},${workPhone},${homePhone}" ${this.toNull}`;
31
- }
32
- else if (this.distro.familyId === 'openmamba') {
33
- cmd = `chroot ${this.installTarget} useradd ${username} --create-home --shell /bin/bash --comment "${fullusername},${roomNumber},${workPhone},${homePhone}" ${this.toNull}`;
34
- }
35
- else if (this.distro.familyId === 'opensuse') {
36
- cmd = `chroot ${this.installTarget} useradd ${username} --create-home --shell /bin/bash --comment "${fullusername},${roomNumber},${workPhone},${homePhone}" ${this.toNull}`;
13
+ const target = this.installTarget;
14
+ const familyId = this.distro.familyId;
15
+ // --- 1. INIZIALIZZAZIONE SYSUSERS ---
16
+ const sysUsers = new SysUsers(target, familyId);
17
+ sysUsers.load(); // Carica passwd, shadow, group in memoria
18
+ console.log(`Creating user ${username} via SysUsers (Safe Mode)...`);
19
+ // --- 2. PREPARAZIONE DATI ---
20
+ // Shell detection (Fallback per Alpine/Minimal)
21
+ let shell = '/bin/bash';
22
+ if (!fs.existsSync(path.join(target, 'bin/bash')) && fs.existsSync(path.join(target, 'bin/ash'))) {
23
+ shell = '/bin/ash';
37
24
  }
38
- await exec(cmd, this.echo);
39
- cmd = `echo ${username}:${password} | chroot ${this.installTarget} /usr/sbin/chpasswd ${this.toNull}`;
40
- await exec(cmd, this.echo);
41
- let group = 'wheel';
42
- if (this.distro.familyId === 'debian') {
43
- group = 'sudo';
25
+ // Definizione oggetto utente
26
+ const newUser = {
27
+ username: username,
28
+ password: 'x',
29
+ uid: '1000', // Hardcoded per il primo utente (standard installer)
30
+ gid: '1000',
31
+ gecos: `${fullusername},${roomNumber},${workPhone},${homePhone}`,
32
+ home: `/home/${username}`,
33
+ shell: shell
34
+ };
35
+ // --- 3. MODIFICHE LOGICHE (IN MEMORIA) ---
36
+ // Aggiunge l'utente (gestisce passwd, shadow, group primario, subuid)
37
+ sysUsers.addUser(newUser, password);
38
+ // Aggiungi ai gruppi amministrativi (logica distro)
39
+ let adminGroup = 'wheel';
40
+ if (['debian', 'ubuntu', 'linuxmint', 'pop', 'neon'].includes(familyId)) {
41
+ adminGroup = 'sudo';
44
42
  }
45
- else if (this.distro.familyId === 'openmamba') {
46
- group = 'sysadmin';
43
+ else if (familyId === 'openmamba') {
44
+ adminGroup = 'sysadmin';
47
45
  }
48
- cmd = `chroot ${this.installTarget} usermod -aG ${group} ${username} ${this.toNull}`;
49
- await exec(cmd, this.echo);
50
- // add autologin group in archlinux
51
- await exec(cmd, this.echo);
52
- if (this.distro.familyId === 'archlinux') {
53
- await exec(`chroot ${this.installTarget} getent group autologin || groupadd autologin`);
54
- await exec(`chroot ${this.installTarget} usermod -aG autologin ${username}`);
55
- }
56
- /**
57
- * look to calamares/modules/users.conf for groups
58
- */
46
+ sysUsers.addUserToGroup(username, adminGroup);
47
+ // Aggiungi ai gruppi definiti in Calamares/Eggs config
59
48
  let usersConf = '/etc/calamares/modules/users.conf';
60
49
  if (!fs.existsSync(usersConf)) {
61
50
  usersConf = '/etc/penguins-eggs.d/krill/modules/users.conf';
62
51
  }
63
52
  if (fs.existsSync(usersConf)) {
64
- const o = yaml.load(fs.readFileSync(usersConf, 'utf8'));
65
- for (const group of o.defaultGroups) {
66
- const groupExists = await exec(`getent group ${group}`);
67
- if (groupExists.code == 0) {
68
- let addGroup = `chroot ${this.installTarget} usermod -aG ${group} ${username}`;
69
- await exec(addGroup);
53
+ try {
54
+ const content = fs.readFileSync(usersConf, 'utf8');
55
+ const o = yaml.load(content);
56
+ if (o && o.defaultGroups) {
57
+ for (const grp of o.defaultGroups) {
58
+ sysUsers.addUserToGroup(username, grp);
59
+ }
70
60
  }
71
61
  }
62
+ catch (e) {
63
+ console.error('Warning: Error parsing users.conf, skipping extra groups.', e);
64
+ }
65
+ }
66
+ // Fix specifico Archlinux (Autologin)
67
+ if (familyId === 'archlinux') {
68
+ sysUsers.addUserToGroup(username, 'autologin');
69
+ }
70
+ // --- 4. SALVATAGGIO ATOMICO SU DISCO ---
71
+ // Scrive tutti i file di config e applica chcon (SELinux) se necessario
72
+ await sysUsers.save();
73
+ // --- 5. CREAZIONE FISICA HOME DIRECTORY ---
74
+ // Queste operazioni toccano il filesystem reale, quindi usiamo exec/fs
75
+ const homeDir = path.join(target, newUser.home);
76
+ // Cleanup preventivo
77
+ await exec(`rm -rf ${homeDir}`, this.echo);
78
+ // Creazione da /etc/skel
79
+ const skelPath = path.join(target, 'etc', 'skel');
80
+ if (fs.existsSync(skelPath)) {
81
+ await exec(`mkdir -p ${homeDir}`, this.echo);
82
+ await exec(`cp -rT ${skelPath} ${homeDir}`, this.echo);
72
83
  }
73
84
  else {
74
- console.log(`cannot find: ${usersConf}!`);
75
- await Utils.pressKeyToExit();
85
+ await exec(`mkdir -p ${homeDir}`, this.echo);
86
+ }
87
+ // Permessi e Proprietario
88
+ await exec(`chown -R ${newUser.uid}:${newUser.gid} ${homeDir}`, this.echo);
89
+ // Privacy: 700 è meglio di 755 per la home utente
90
+ await exec(`chmod 700 ${homeDir}`, this.echo);
91
+ // --- 6. FIX SELINUX FINALE (HOME & RELABEL) ---
92
+ // SysUsers ha sistemato /etc/*, ma la home directory è appena stata creata
93
+ // e potrebbe avere contesti errati.
94
+ if (['fedora', 'rhel', 'centos', 'almalinux', 'rocky'].includes(familyId)) {
95
+ try {
96
+ console.log('Applying SELinux contexts to home directory...');
97
+ // Fix contesto home
98
+ await exec(`chcon -R -t user_home_t ${homeDir}`, { echo: false }).catch(() => { });
99
+ // Fix "Nuclear Option": forza relabel al boot se qualcosa fosse sfuggito
100
+ await exec(`touch ${target}/.autorelabel`, { echo: false });
101
+ }
102
+ catch (e) {
103
+ console.error('SELinux home fix warning:', e);
104
+ }
76
105
  }
106
+ console.log(`User ${username} successfully configured via SysUser Master.`);
77
107
  }
@@ -1,15 +1,13 @@
1
1
  /**
2
- * ./src/krill/modules/change-password.ts
2
+ * src/krill/modules/change-password.ts
3
3
  * penguins-eggs v.25.7.x / ecmascript 2020
4
- * author: Piero Proietti
5
- * email: piero.proietti@gmail.com
6
- * license: MIT
7
- * https://stackoverflow.com/questions/23876782/how-do-i-split-a-typescript-class-into-multiple-files
4
+ * * REFACTORED: Uses "The SysUser Master" class.
5
+ * Changes user password directly in /etc/shadow safely (No binaries, SELinux safe).
8
6
  */
9
7
  import Sequence from '../sequence.js';
10
8
  /**
11
9
  * changePassword
12
- * @param name
13
- * @param newPassword
10
+ * @param name - Username to update
11
+ * @param newPassword - New plain text password
14
12
  */
15
13
  export default function changePassword(this: Sequence, name?: string, newPassword?: string): Promise<void>;
@@ -1,18 +1,33 @@
1
1
  /**
2
- * ./src/krill/modules/change-password.ts
2
+ * src/krill/modules/change-password.ts
3
3
  * penguins-eggs v.25.7.x / ecmascript 2020
4
- * author: Piero Proietti
5
- * email: piero.proietti@gmail.com
6
- * license: MIT
7
- * https://stackoverflow.com/questions/23876782/how-do-i-split-a-typescript-class-into-multiple-files
4
+ * * REFACTORED: Uses "The SysUser Master" class.
5
+ * Changes user password directly in /etc/shadow safely (No binaries, SELinux safe).
8
6
  */
9
- import { exec } from '../../../lib/utils.js';
7
+ import SysUsers from '../../../classes/sys-users.js';
8
+ import fs from 'fs';
10
9
  /**
11
10
  * changePassword
12
- * @param name
13
- * @param newPassword
11
+ * @param name - Username to update
12
+ * @param newPassword - New plain text password
14
13
  */
15
14
  export default async function changePassword(name = 'live', newPassword = 'evolution') {
16
- const cmd = `echo ${name}:${newPassword} | chroot ${this.installTarget} /usr/sbin/chpasswd ${this.toNull}`;
17
- await exec(cmd, this.echo);
15
+ const target = this.installTarget;
16
+ const familyId = this.distro.familyId;
17
+ console.log(`Changing password for user '${name}' via SysUsers...`);
18
+ // 1. CARICAMENTO
19
+ // Se non esiste il target (caso strano), usciamo
20
+ if (!fs.existsSync(target)) {
21
+ console.error(`Error: Target ${target} not found for password change.`);
22
+ return;
23
+ }
24
+ const sysUsers = new SysUsers(target, familyId);
25
+ sysUsers.load();
26
+ // 2. MODIFICA (In Memoria)
27
+ // La classe SysUsers ha già il metodo setPassword che usa bcryptjs
28
+ // e aggiorna il timestamp di lastChange.
29
+ sysUsers.setPassword(name, newPassword);
30
+ // 3. SALVATAGGIO (Atomico + SELinux Fix)
31
+ await sysUsers.save();
32
+ console.log(`Password updated for '${name}'.`);
18
33
  }
@@ -1,14 +1,12 @@
1
1
  /**
2
- * ./src/krill/modules/del-live-user.ts
2
+ * src/krill/classes/sequence.d/del_live_user.ts
3
3
  * penguins-eggs v.25.7.x / ecmascript 2020
4
- * author: Piero Proietti
5
- * email: piero.proietti@gmail.com
6
- * license: MIT
7
- * https://stackoverflow.com/questions/23876782/how-do-i-split-a-typescript-class-into-multiple-files
4
+ * * REFACTORED: Uses "The SysUser Master" class.
5
+ * Removes the live user from the installed target safely (SELinux friendly).
8
6
  */
9
7
  import Sequence from '../sequence.js';
10
8
  /**
11
- * delUser
12
- * va corretto con users.conf di calamares
9
+ * delLiveUser
10
+ * Rimuove l'utente live dal sistema installato (target)
13
11
  */
14
12
  export default function delLiveUser(this: Sequence): Promise<void>;
@@ -1,39 +1,53 @@
1
1
  /**
2
- * ./src/krill/modules/del-live-user.ts
2
+ * src/krill/classes/sequence.d/del_live_user.ts
3
3
  * penguins-eggs v.25.7.x / ecmascript 2020
4
- * author: Piero Proietti
5
- * email: piero.proietti@gmail.com
6
- * license: MIT
7
- * https://stackoverflow.com/questions/23876782/how-do-i-split-a-typescript-class-into-multiple-files
4
+ * * REFACTORED: Uses "The SysUser Master" class.
5
+ * Removes the live user from the installed target safely (SELinux friendly).
8
6
  */
7
+ import SysUsers from '../../../classes/sys-users.js';
9
8
  import Utils from '../../../classes/utils.js';
10
9
  import { exec } from '../../../lib/utils.js';
10
+ import fs from 'fs';
11
+ import path from 'path';
11
12
  /**
12
- * delUser
13
- * va corretto con users.conf di calamares
13
+ * delLiveUser
14
+ * Rimuove l'utente live dal sistema installato (target)
14
15
  */
15
16
  export default async function delLiveUser() {
17
+ // Eseguiamo solo se siamo in modalità live (ovvero stiamo installando da una ISO)
16
18
  if (Utils.isLive()) {
17
- const user = this.settings.config.user_opt;
18
- let userExists = false;
19
- try {
20
- const cmd = `#!/bin/sh\ngetent passwd "${user}" > /dev/null`;
21
- await exec(cmd, Utils.setEcho(this.verbose));
22
- userExists = true;
19
+ // Recuperiamo il nome utente live (default: 'live' o quello impostato in build)
20
+ const liveUsername = this.settings.config.user_opt || 'live';
21
+ const target = this.installTarget;
22
+ const familyId = this.distro.familyId;
23
+ console.log(`Removing live user '${liveUsername}' from target via SysUsers...`);
24
+ // --- 1. CARICAMENTO CONFIGURAZIONE ---
25
+ // Istanziamo il nostro "Master" puntando alla root del sistema installato
26
+ const sysUsers = new SysUsers(target, familyId);
27
+ sysUsers.load();
28
+ // --- 2. RIMOZIONE LOGICA (IN MEMORIA) ---
29
+ // Rimuove l'utente da passwd, shadow, group e dai membri dei gruppi extra
30
+ sysUsers.removeUser(liveUsername);
31
+ // --- 3. SALVATAGGIO ATOMICO ---
32
+ // Scrive i file fisici e ripristina i contesti SELinux in un colpo solo
33
+ await sysUsers.save();
34
+ // --- 4. PULIZIA FILESYSTEM (File non gestiti da SysUsers) ---
35
+ // a) Home Directory
36
+ const homeDir = path.join(target, 'home', liveUsername);
37
+ if (fs.existsSync(homeDir)) {
38
+ await exec(`rm -rf ${homeDir}`, this.echo);
23
39
  }
24
- catch (error) {
25
- console.log(error);
40
+ // b) File Sudoers (spesso creato in /etc/sudoers.d/)
41
+ const sudoersFile = path.join(target, 'etc', 'sudoers.d', liveUsername);
42
+ if (fs.existsSync(sudoersFile)) {
43
+ fs.unlinkSync(sudoersFile);
44
+ console.log(`Removed sudoers file: ${sudoersFile}`);
26
45
  }
27
- finally {
28
- if (userExists) {
29
- let cmd = `chroot ${this.installTarget} deluser --remove-home ${user} ${this.toNull}`;
30
- if (this.distro.familyId === 'archlinux' ||
31
- this.distro.familyId === 'fedora' ||
32
- this.distro.familyId === 'opensuse') {
33
- cmd = `chroot ${this.installTarget} sudo userdel -r ${user} ${this.toNull}`;
34
- }
35
- await exec(cmd, this.echo);
36
- }
46
+ // c) Mail spool
47
+ const mailFile = path.join(target, 'var', 'mail', liveUsername);
48
+ if (fs.existsSync(mailFile)) {
49
+ fs.unlinkSync(mailFile);
37
50
  }
51
+ console.log(`Live user '${liveUsername}' removed successfully via SysUser Master.`);
38
52
  }
39
53
  }
@@ -6,7 +6,7 @@
6
6
  * license: MIT
7
7
  * https://stackoverflow.com/questions/23876782/how-do-i-split-a-typescript-class-into-multiple-files
8
8
  */
9
- import shx from 'shelljs';
9
+ import { shx } from '../../../lib/utils.js';
10
10
  import { InstallationMode } from '../krill_enums.js';
11
11
  import Utils from '../../../classes/utils.js';
12
12
  import { SwapChoice } from '../krill_enums.js';
@@ -1,17 +1,13 @@
1
1
  /**
2
2
  * ./src/krill/modules/grubcfg.ts
3
3
  * penguins-eggs v.25.7.x / ecmascript 2020
4
- * author: Piero Proietti
5
- * email: piero.proietti@gmail.com
6
- * license: MIT
7
- * https://stackoverflow.com/questions/23876782/how-do-i-split-a-typescript-class-into-multiple-files
4
+ * * REFACTORED: Adds SELinux permissive mode for RHEL family
8
5
  */
9
6
  import Sequence from '../../classes/sequence.js';
10
7
  /**
11
8
  * grubcfg
12
9
  * - open /etc/default/grub
13
- * - find GRUB_CMDLINE_LINUX_DEFAULT=
14
- * - replace with GRUB_CMDLINE_LINUX_DEFAULT=
15
- * 's/GRUB_CMDLINE_LINUX_DEFAULT=.*$/GRUB_CMDLINE_LINUX_DEFAULT=/g'
10
+ * - handle BTRFS/LUKS settings
11
+ * - inject enforcing=0 for Fedora/RHEL to allow autorelabel on first boot
16
12
  */
17
13
  export default function grubcfg(this: Sequence): Promise<void>;