From a2fae600c478352ceeee68ae9ad75aca7fa02b0c Mon Sep 17 00:00:00 2001
From: Nathan Schulte <nmschulte@desmas.net>
Date: Tue, 11 Jul 2023 01:29:32 -0500
Subject: [PATCH] add usermod command about default username

cmdUsermod supports changing the default username

in case any extra initial state needs updated, cmdUsermod can be amended to run additional commands
---
 modules/mobile/Config.cpp   | 11 +++++++++++
 modules/mobile/Config.h     |  8 ++++++--
 modules/mobile/UsersJob.cpp |  4 ++++
 modules/mobile/UsersJob.h   |  2 ++
 modules/mobile/mobile.conf  |  5 +++++
 modules/mobile/mobile.qrc   |  2 +-
 6 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/modules/mobile/Config.cpp b/modules/mobile/Config.cpp
index e5ea478..414b2d4 100644
--- a/modules/mobile/Config.cpp
+++ b/modules/mobile/Config.cpp
@@ -36,6 +36,7 @@ Config::setConfigurationMap( const QVariantMap& cfgMap )
             "messagebus", "news", "nobody", "ntp", "operator", "polkitd", "postmaster", "pulse", "root", "shutdown",
             "smmsp", "squid", "sshd", "sync", "uucp", "vpopmail", "xfs" } );
 
+    // ensure m_cmdUsermod matches m_username
     m_username = getString( cfgMap, "username", "user" );
     m_userPasswordNumeric = getBool( cfgMap, "userPasswordNumeric", true );
 
@@ -60,6 +61,8 @@ Config::setConfigurationMap( const QVariantMap& cfgMap )
 
     m_cmdInternalStoragePrepare = getString( cfgMap, "cmdInternalStoragePrepare", "ondev-internal-storage-prepare" );
     m_cmdPasswd = getString( cfgMap, "cmdPasswd", "passwd" );
+    m_cmdUsermod = getString( cfgMap, "cmdUsermod", "xargs -I{} -n1 usermod -m -d /home/{} -l {} user");
+
     m_cmdSshdEnable = getString( cfgMap, "cmdSshdEnable", "systemctl enable sshd.service" );
     m_cmdSshdDisable = getString( cfgMap, "cmdSshdDisable", "systemctl disable sshd.service" );
     m_cmdSshdUseradd = getString( cfgMap, "cmdSshdUseradd", "useradd -G wheel -m" );
@@ -74,6 +77,7 @@ Config::createJobs()
     /* Put users job in queue (should run after unpackfs) */
     Calamares::Job* j = new UsersJob( m_featureSshd,
                                       m_cmdPasswd,
+                                      m_cmdUsermod,
                                       cmdSshd,
                                       m_cmdSshdUseradd,
                                       m_isSshEnabled,
@@ -138,6 +142,13 @@ Config::runPartitionJobThenLeave( bool b )
     }
 }
 
+void
+Config::setUsername( const QString& username )
+{
+    m_username = username;
+    emit usernameChanged( m_username );
+}
+
 void
 Config::setUserPassword( const QString& userPassword )
 {
diff --git a/modules/mobile/Config.h b/modules/mobile/Config.h
index eaf7cb8..3d77561 100644
--- a/modules/mobile/Config.h
+++ b/modules/mobile/Config.h
@@ -24,7 +24,7 @@ class Config : public QObject
     Q_PROPERTY( QStringList reservedUsernames READ reservedUsernames CONSTANT FINAL )
 
     /* default user */
-    Q_PROPERTY( QString username READ username CONSTANT FINAL )
+    Q_PROPERTY( QString username READ username WRITE setUsername NOTIFY usernameChanged )
     Q_PROPERTY( QString userPassword READ userPassword WRITE setUserPassword NOTIFY userPasswordChanged )
     Q_PROPERTY( bool userPasswordNumeric READ userPasswordNumeric CONSTANT FINAL )
 
@@ -78,9 +78,10 @@ public:
     /* reserved usernames (user_pass, ssh_credentials) */
     QStringList reservedUsernames() const { return m_reservedUsernames; };
 
-    /* default user */
+    /* user */
     QString username() const { return m_username; }
     QString userPassword() const { return m_userPassword; }
+    void setUsername( const QString& username );
     void setUserPassword( const QString& userPassword );
     bool userPasswordNumeric() const { return m_userPasswordNumeric; }
 
@@ -126,6 +127,7 @@ public:
 
     /* users job */
     QString cmdPasswd() const { return m_cmdPasswd; }
+    QString cmdUsermod() const { return m_cmdUsermod; }
     QString cmdSshdEnable() const { return m_cmdSshdEnable; }
     QString cmdSshdDisable() const { return m_cmdSshdDisable; }
     QString cmdSshdUseradd() const { return m_cmdSshdUseradd; }
@@ -181,6 +183,7 @@ private:
 
     /* users job */
     QString m_cmdPasswd;
+    QString m_cmdUsermod;
     QString m_cmdSshdEnable;
     QString m_cmdSshdDisable;
     QString m_cmdSshdUseradd;
@@ -190,6 +193,7 @@ signals:
 
     /* default user */
     void userPasswordChanged( QString userPassword );
+    void usernameChanged( QString username );
 
     /* ssh server + credentials */
     void sshdUsernameChanged( QString sshdUsername );
diff --git a/modules/mobile/UsersJob.cpp b/modules/mobile/UsersJob.cpp
index 9dc382d..333f208 100644
--- a/modules/mobile/UsersJob.cpp
+++ b/modules/mobile/UsersJob.cpp
@@ -14,6 +14,7 @@
 
 UsersJob::UsersJob( bool featureSshd,
                     const QString& cmdPasswd,
+                    const QString& cmdUsermod,
                     const QString& cmdSshd,
                     const QString& cmdSshdUseradd,
                     bool isSshEnabled,
@@ -24,6 +25,7 @@ UsersJob::UsersJob( bool featureSshd,
     : Calamares::Job()
     , m_featureSshd( featureSshd )
     , m_cmdPasswd( cmdPasswd )
+    , m_cmdUsermod( cmdUsermod )
     , m_cmdSshd( cmdSshd )
     , m_cmdSshdUseradd( cmdSshdUseradd )
     , m_isSshEnabled( isSshEnabled )
@@ -52,6 +54,8 @@ UsersJob::exec()
         { { "sh", "-c", m_cmdPasswd + " " + m_username }, m_password + "\n" + m_password + "\n" },
     };
 
+    commands.append( { { "sh", "-c", m_cmdUsermod }, m_username + "\n" } );
+
     if ( m_featureSshd )
     {
         commands.append( { { "sh", "-c", m_cmdSshd }, QString() } );
diff --git a/modules/mobile/UsersJob.h b/modules/mobile/UsersJob.h
index c101669..8c4b285 100644
--- a/modules/mobile/UsersJob.h
+++ b/modules/mobile/UsersJob.h
@@ -10,6 +10,7 @@ class UsersJob : public Calamares::Job
 public:
     UsersJob( bool featureSshd,
               const QString& cmdPasswd,
+              const QString& cmdUsermod,
               const QString& cmdSshd,
               const QString& cmdSshdUseradd,
               bool isSshEnabled,
@@ -26,6 +27,7 @@ public:
 private:
     bool m_featureSshd;
     QString m_cmdPasswd;
+    QString m_cmdUsermod;
     QString m_cmdSshd;
     QString m_cmdSshdUseradd;
     bool m_isSshEnabled;
diff --git a/modules/mobile/mobile.conf b/modules/mobile/mobile.conf
index b0860af..0b773df 100644
--- a/modules/mobile/mobile.conf
+++ b/modules/mobile/mobile.conf
@@ -26,6 +26,7 @@ bogus: true
 # version: "(unknown)"
 
 ## Default username (for which the password will be set)
+## Ensure also cmdUsermod command matches the default user, so it can be changed if desired.
 # username: "user"
 
 ## reserved usernames (for user_pass username prompt and ssh_credentials)
@@ -154,6 +155,10 @@ bogus: true
 ### Commands running in the target OS (chroot)
 #######
 
+## Change the username for the default user
+## Stdin: username with \n
+# cmdUsermod: "xargs -I{} -n1 usermod -m -d /home/{} -l {} user"
+
 ## Set the password for default user and sshd user
 ## Arguments: <username>
 ## Stdin: password twice, each time with \n
diff --git a/modules/mobile/mobile.qrc b/modules/mobile/mobile.qrc
index 27e592a..d8ef887 100644
--- a/modules/mobile/mobile.qrc
+++ b/modules/mobile/mobile.qrc
@@ -7,7 +7,7 @@
   <file>install_target.qml</file> <!-- install from external to internal? -->
   <file>install_target_confirm.qml</file> <!-- overwrite internal storage? -->
 
-  <file>user_pass.qml</file> <!-- default user: password -->
+  <file>user_pass.qml</file> <!-- default user: username, password -->
   <file>ssh_confirm.qml</file> <!-- sshd: enable or not? -->
   <file>ssh_credentials.qml</file> <!-- sshd user: username, password -->
   <file>fs_selection.qml</file> <!-- filesystem selection -->
-- 
2.34.1

