Merge branch 'better-hostname'
This commit is contained in:
commit
371fe267b1
@ -293,19 +293,19 @@ System::targetPath( const QString& path ) const
|
||||
}
|
||||
}
|
||||
|
||||
QString
|
||||
CreationResult
|
||||
System::createTargetFile( const QString& path, const QByteArray& contents ) const
|
||||
{
|
||||
QString completePath = targetPath( path );
|
||||
if ( completePath.isEmpty() )
|
||||
{
|
||||
return QString();
|
||||
return CreationResult( CreationResult::Code::Invalid );
|
||||
}
|
||||
|
||||
QFile f( completePath );
|
||||
if ( f.exists() )
|
||||
{
|
||||
return QString();
|
||||
return CreationResult( CreationResult::Code::AlreadyExists );
|
||||
}
|
||||
|
||||
QIODevice::OpenMode m =
|
||||
@ -317,18 +317,18 @@ System::createTargetFile( const QString& path, const QByteArray& contents ) cons
|
||||
|
||||
if ( !f.open( m ) )
|
||||
{
|
||||
return QString();
|
||||
return CreationResult( CreationResult::Code::Failed );
|
||||
}
|
||||
|
||||
if ( f.write( contents ) != contents.size() )
|
||||
{
|
||||
f.close();
|
||||
f.remove();
|
||||
return QString();
|
||||
return CreationResult( CreationResult::Code::Failed );
|
||||
}
|
||||
|
||||
f.close();
|
||||
return QFileInfo( f ).canonicalFilePath();
|
||||
return CreationResult( QFileInfo( f ).canonicalFilePath() );
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -84,6 +84,41 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief The result of a create*() action, for status
|
||||
*
|
||||
* A CreationResult has a status field, can be converted to bool
|
||||
* (true only on success) and can report the full pathname of
|
||||
* the thing created if it was successful.
|
||||
*/
|
||||
class CreationResult : public QPair< int, QString >
|
||||
{
|
||||
public:
|
||||
enum class Code : int
|
||||
{
|
||||
// These are "not failed", but only OK is a success
|
||||
OK = 0,
|
||||
AlreadyExists = 1,
|
||||
// These are "failed"
|
||||
Invalid = -1,
|
||||
Failed = -2
|
||||
};
|
||||
|
||||
CreationResult( Code r )
|
||||
: QPair< int, QString >( static_cast< int >( r ), QString() )
|
||||
{
|
||||
}
|
||||
explicit CreationResult( const QString& path )
|
||||
: QPair< int, QString >( 0, path )
|
||||
{
|
||||
}
|
||||
|
||||
Code code() const { return static_cast< Code >( first ); }
|
||||
QString path() const { return second; }
|
||||
|
||||
bool failed() const { return first < 0; }
|
||||
operator bool() const { return first == 0; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The System class is a singleton with utility functions that perform
|
||||
* system-specific operations.
|
||||
@ -244,7 +279,7 @@ public:
|
||||
* root of the host system, or empty on failure. (Here, it is
|
||||
* possible to be canonical because the file exists).
|
||||
*/
|
||||
DLLEXPORT QString createTargetFile( const QString& path, const QByteArray& contents ) const;
|
||||
DLLEXPORT CreationResult createTargetFile( const QString& path, const QByteArray& contents ) const;
|
||||
|
||||
/** @brief Remove a file from the target system.
|
||||
*
|
||||
|
@ -46,6 +46,7 @@ private Q_SLOTS:
|
||||
void init();
|
||||
void cleanupTestCase();
|
||||
|
||||
void testCreationResult();
|
||||
void testTargetPath();
|
||||
void testCreateTarget();
|
||||
void testCreateTargetBasedirs();
|
||||
@ -95,6 +96,42 @@ TestPaths::init()
|
||||
m_gs->insert( "rootMountPoint", "/tmp" );
|
||||
}
|
||||
|
||||
void TestPaths::testCreationResult()
|
||||
{
|
||||
using Code = CalamaresUtils::CreationResult::Code;
|
||||
|
||||
for( auto c : { Code::OK, Code::AlreadyExists, Code::Failed, Code::Invalid } )
|
||||
{
|
||||
auto r = CalamaresUtils::CreationResult( c );
|
||||
QVERIFY( r.path().isEmpty() );
|
||||
QCOMPARE( r.path(), QString() );
|
||||
// Get a warning from Clang if we're not covering everything
|
||||
switch( r.code() )
|
||||
{
|
||||
case Code::OK:
|
||||
QVERIFY( !r.failed() );
|
||||
QVERIFY( r );
|
||||
break;
|
||||
case Code::AlreadyExists:
|
||||
QVERIFY( !r.failed() );
|
||||
QVERIFY( !r );
|
||||
break;
|
||||
case Code::Failed:
|
||||
case Code::Invalid:
|
||||
QVERIFY( r.failed() );
|
||||
QVERIFY( !r );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QString path( "/etc/os-release" );
|
||||
auto r = CalamaresUtils::CreationResult( path );
|
||||
QVERIFY( !r.failed() );
|
||||
QVERIFY( r );
|
||||
QCOMPARE( r.code(), Code::OK );
|
||||
QCOMPARE( r.path(), path );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TestPaths::testTargetPath()
|
||||
@ -117,7 +154,10 @@ TestPaths::testTargetPath()
|
||||
void
|
||||
TestPaths::testCreateTarget()
|
||||
{
|
||||
QCOMPARE( m_system->createTargetFile( testFile, "Hello" ), QString( absFile ) ); // Success
|
||||
auto r = m_system->createTargetFile( testFile, "Hello" );
|
||||
QVERIFY( !r.failed() );
|
||||
QVERIFY( r );
|
||||
QCOMPARE( r.path(), QString( absFile ) ); // Success
|
||||
|
||||
QFileInfo fi( absFile );
|
||||
QVERIFY( fi.exists() );
|
||||
|
@ -54,7 +54,7 @@ InitramfsJob::exec()
|
||||
// First make sure we generate a safe initramfs with suitable permissions.
|
||||
static const char confFile[] = "/etc/initramfs-tools/conf.d/calamares-safe-initramfs.conf";
|
||||
static const char contents[] = "UMASK=0077\n";
|
||||
if ( CalamaresUtils::System::instance()->createTargetFile( confFile, QByteArray( contents ) ).isEmpty() )
|
||||
if ( CalamaresUtils::System::instance()->createTargetFile( confFile, QByteArray( contents ) ).failed() )
|
||||
{
|
||||
cWarning() << Logger::SubEntry << "Could not configure safe UMASK for initramfs.";
|
||||
// But continue anyway.
|
||||
|
@ -59,7 +59,10 @@ void InitramfsTests::testCreateHostFile()
|
||||
{
|
||||
|
||||
CalamaresUtils::System s( false ); // don't chroot
|
||||
QString path = s.createTargetFile( confFile, QByteArray( contents ) );
|
||||
auto r = s.createTargetFile( confFile, QByteArray( contents ) );
|
||||
QVERIFY( !r.failed() );
|
||||
QVERIFY( r );
|
||||
QString path = r.path();
|
||||
QVERIFY( !path.isEmpty() );
|
||||
QCOMPARE( path, confFile ); // don't chroot, so path create relative to /
|
||||
QVERIFY( QFile::exists( confFile ) );
|
||||
@ -76,7 +79,10 @@ void InitramfsTests::testCreateTargetFile()
|
||||
static const char short_confFile[] = "/calamares-safe-umask";
|
||||
|
||||
CalamaresUtils::System s( true );
|
||||
QString path = s.createTargetFile( short_confFile, QByteArray( contents ) );
|
||||
auto r = s.createTargetFile( short_confFile, QByteArray( contents ) );
|
||||
QVERIFY( r.failed() );
|
||||
QVERIFY( !r );
|
||||
QString path = r.path();
|
||||
QVERIFY( path.isEmpty() ); // because no rootmountpoint is set
|
||||
|
||||
Calamares::JobQueue j;
|
||||
|
@ -125,8 +125,13 @@ MachineIdTests::testJob()
|
||||
gs->insert( "rootMountPoint", "/tmp" );
|
||||
|
||||
// Prepare part of the target filesystem
|
||||
{
|
||||
QVERIFY( system->createTargetDirs("/etc") );
|
||||
QVERIFY( !(system->createTargetFile( "/etc/machine-id", "Hello" ).isEmpty() ) );
|
||||
auto r = system->createTargetFile( "/etc/machine-id", "Hello" );
|
||||
QVERIFY( !r.failed() );
|
||||
QVERIFY( r );
|
||||
QVERIFY( !r.path().isEmpty() );
|
||||
}
|
||||
|
||||
MachineIdJob job( nullptr );
|
||||
QVERIFY( !job.prettyName().isEmpty() );
|
||||
|
@ -1,4 +1,4 @@
|
||||
find_package( Qt5 COMPONENTS Core REQUIRED )
|
||||
find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Core DBus Network )
|
||||
find_package( Crypt REQUIRED )
|
||||
|
||||
# Add optional libraries here
|
||||
@ -36,6 +36,7 @@ calamares_add_plugin( users
|
||||
calamaresui
|
||||
${CRYPT_LIBRARIES}
|
||||
${USER_EXTRA_LIB}
|
||||
Qt5::DBus
|
||||
SHARED_LIB
|
||||
)
|
||||
|
||||
|
@ -22,14 +22,19 @@
|
||||
|
||||
#include "GlobalStorage.h"
|
||||
#include "JobQueue.h"
|
||||
#include "utils/CalamaresUtilsSystem.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QtDBus/QDBusConnection>
|
||||
#include <QtDBus/QDBusInterface>
|
||||
#include <QtDBus/QDBusReply>
|
||||
|
||||
SetHostNameJob::SetHostNameJob( const QString& hostname )
|
||||
SetHostNameJob::SetHostNameJob( const QString& hostname, Actions a )
|
||||
: Calamares::Job()
|
||||
, m_hostname( hostname )
|
||||
, m_actions( a )
|
||||
{
|
||||
}
|
||||
|
||||
@ -53,6 +58,58 @@ SetHostNameJob::prettyStatusMessage() const
|
||||
return tr( "Setting hostname %1." ).arg( m_hostname );
|
||||
}
|
||||
|
||||
static bool
|
||||
setFileHostname( const QString& hostname )
|
||||
{
|
||||
return !( CalamaresUtils::System::instance()
|
||||
->createTargetFile( QStringLiteral( "/etc/hostname" ), ( hostname + '\n' ).toUtf8() )
|
||||
.failed() );
|
||||
}
|
||||
|
||||
static bool
|
||||
writeFileEtcHosts( const QString& hostname )
|
||||
{
|
||||
// The actual hostname gets substituted in at %1
|
||||
static const char etc_hosts[] = R"(# Host addresses
|
||||
127.0.0.1 localhost
|
||||
127.0.1.1 %1
|
||||
::1 localhost ip6-localhost ip6-loopback
|
||||
ff02::1 ip6-allnodes
|
||||
ff02::2 ip6-allrouters
|
||||
)";
|
||||
|
||||
return !( CalamaresUtils::System::instance()
|
||||
->createTargetFile( QStringLiteral( "/etc/hosts" ), QString( etc_hosts ).arg( hostname ).toUtf8() )
|
||||
.failed() );
|
||||
}
|
||||
|
||||
static void
|
||||
setSystemdHostname( const QString& hostname )
|
||||
{
|
||||
QDBusInterface hostnamed( "org.freedesktop.hostname1",
|
||||
"/org/freedesktop/hostname1",
|
||||
"org.freedesktop.hostname1",
|
||||
QDBusConnection::systemBus() );
|
||||
|
||||
// Static, writes /etc/hostname
|
||||
{
|
||||
QDBusReply< uint > r = hostnamed.call( "SetStaticHostname", hostname, false );
|
||||
if ( !r.isValid() )
|
||||
{
|
||||
cWarning() << "Could not set hostname through org.freedesktop.hostname1.SetStaticHostname." << r.error();
|
||||
}
|
||||
}
|
||||
// Dynamic, updates kernel
|
||||
{
|
||||
QDBusReply< uint > r = hostnamed.call( "SetHostname", hostname, false );
|
||||
if ( !r.isValid() )
|
||||
{
|
||||
cWarning() << "Could not set hostname through org.freedesktop.hostname1.SetHostname." << r.error();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Calamares::JobResult
|
||||
SetHostNameJob::exec()
|
||||
{
|
||||
@ -71,43 +128,29 @@ SetHostNameJob::exec()
|
||||
return Calamares::JobResult::error( tr( "Internal Error" ) );
|
||||
}
|
||||
|
||||
QFile hostfile( destDir + "/etc/hostname" );
|
||||
if ( !hostfile.open( QFile::WriteOnly ) )
|
||||
if ( m_actions & Action::EtcHostname )
|
||||
{
|
||||
if ( !setFileHostname( m_hostname ) )
|
||||
{
|
||||
cError() << "Can't write to hostname file";
|
||||
return Calamares::JobResult::error( tr( "Cannot write hostname to target system" ) );
|
||||
}
|
||||
}
|
||||
|
||||
QTextStream hostfileout( &hostfile );
|
||||
hostfileout << m_hostname << "\n";
|
||||
hostfile.close();
|
||||
|
||||
QFile hostsfile( destDir + "/etc/hosts" );
|
||||
if ( !hostsfile.open( QFile::WriteOnly ) )
|
||||
if ( m_actions & Action::WriteEtcHosts )
|
||||
{
|
||||
if ( !writeFileEtcHosts( m_hostname ) )
|
||||
{
|
||||
cError() << "Can't write to hosts file";
|
||||
return Calamares::JobResult::error( tr( "Cannot write hostname to target system" ) );
|
||||
}
|
||||
}
|
||||
|
||||
// We also need to write the appropriate entries for /etc/hosts
|
||||
QTextStream hostsfileout( &hostsfile );
|
||||
// ipv4 support
|
||||
hostsfileout << "127.0.0.1"
|
||||
<< "\t"
|
||||
<< "localhost"
|
||||
<< "\n";
|
||||
hostsfileout << "127.0.1.1"
|
||||
<< "\t" << m_hostname << "\n";
|
||||
// ipv6 support
|
||||
hostsfileout << "::1"
|
||||
<< "\t"
|
||||
<< "localhost ip6-localhost ip6-loopback"
|
||||
<< "\n";
|
||||
hostsfileout << "ff02::1 ip6-allnodes"
|
||||
<< "\n"
|
||||
<< "ff02::2 ip6-allrouters"
|
||||
<< "\n";
|
||||
hostsfile.close();
|
||||
if ( m_actions & Action::SystemdHostname )
|
||||
{
|
||||
// Does its own logging
|
||||
setSystemdHostname( m_hostname );
|
||||
}
|
||||
|
||||
return Calamares::JobResult::ok();
|
||||
}
|
||||
|
@ -26,7 +26,17 @@ class SetHostNameJob : public Calamares::Job
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SetHostNameJob( const QString& hostname );
|
||||
enum Action
|
||||
{
|
||||
None = 0x0,
|
||||
EtcHostname = 0x1, // Write to /etc/hostname directly
|
||||
SystemdHostname = 0x2, // Set via hostnamed(1)
|
||||
WriteEtcHosts = 0x4 // Write /etc/hosts (127.0.1.1 is this host)
|
||||
};
|
||||
Q_DECLARE_FLAGS( Actions, Action )
|
||||
|
||||
|
||||
SetHostNameJob( const QString& hostname, Actions a );
|
||||
QString prettyName() const override;
|
||||
QString prettyDescription() const override;
|
||||
QString prettyStatusMessage() const override;
|
||||
@ -34,7 +44,9 @@ public:
|
||||
|
||||
private:
|
||||
const QString m_hostname;
|
||||
const Actions m_actions;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS( SetHostNameJob::Actions )
|
||||
|
||||
#endif // SETHOSTNAMEJOB_CPP_H
|
||||
|
@ -3,6 +3,7 @@
|
||||
* Copyright 2014-2017, Teo Mrnjavac <teo@kde.org>
|
||||
* Copyright 2017-2018, Adriaan de Groot <groot@kde.org>
|
||||
* Copyright 2019, Collabora Ltd <arnaud.ferraris@collabora.com>
|
||||
* Copyright 2020, Gabriel Craciunescu <crazy@frugalware.org>
|
||||
*
|
||||
* Portions from the Manjaro Installation Framework
|
||||
* by Roland Singer <roland@manjaro.org>
|
||||
@ -40,6 +41,7 @@
|
||||
#include "utils/String.h"
|
||||
|
||||
#include <QBoxLayout>
|
||||
#include <QFile>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QRegExp>
|
||||
@ -97,14 +99,12 @@ UsersPage::UsersPage( QWidget* parent )
|
||||
connect( ui->textBoxUserVerifiedPassword, &QLineEdit::textChanged, this, &UsersPage::onPasswordTextChanged );
|
||||
connect( ui->textBoxRootPassword, &QLineEdit::textChanged, this, &UsersPage::onRootPasswordTextChanged );
|
||||
connect( ui->textBoxVerifiedRootPassword, &QLineEdit::textChanged, this, &UsersPage::onRootPasswordTextChanged );
|
||||
connect( ui->checkBoxValidatePassword, &QCheckBox::stateChanged, this, [this]( int )
|
||||
{
|
||||
connect( ui->checkBoxValidatePassword, &QCheckBox::stateChanged, this, [this]( int ) {
|
||||
onPasswordTextChanged( ui->textBoxUserPassword->text() );
|
||||
onRootPasswordTextChanged( ui->textBoxRootPassword->text() );
|
||||
checkReady( isReady() );
|
||||
} );
|
||||
connect( ui->checkBoxReusePassword, &QCheckBox::stateChanged, this, [this]( int checked )
|
||||
{
|
||||
connect( ui->checkBoxReusePassword, &QCheckBox::stateChanged, this, [this]( int checked ) {
|
||||
ui->labelChooseRootPassword->setVisible( !checked );
|
||||
ui->labelRootPassword->setVisible( !checked );
|
||||
ui->labelRootPasswordError->setVisible( !checked );
|
||||
@ -166,6 +166,37 @@ UsersPage::isReady()
|
||||
return readyFields && m_readyRootPassword;
|
||||
}
|
||||
|
||||
QString
|
||||
UsersPage::getHostname() const
|
||||
{
|
||||
return ui->textBoxHostname->text();
|
||||
}
|
||||
|
||||
QString
|
||||
UsersPage::getRootPassword() const
|
||||
{
|
||||
if ( m_writeRootPassword )
|
||||
{
|
||||
if ( ui->checkBoxReusePassword->isChecked() )
|
||||
{
|
||||
return ui->textBoxUserPassword->text();
|
||||
}
|
||||
else
|
||||
{
|
||||
return ui->textBoxRootPassword->text();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
QPair< QString, QString >
|
||||
UsersPage::getUserPassword() const
|
||||
{
|
||||
return QPair< QString, QString >( ui->textBoxUsername->text(), ui->textBoxUserPassword->text() );
|
||||
}
|
||||
|
||||
QList< Calamares::job_ptr >
|
||||
UsersPage::createJobs( const QStringList& defaultGroupsList )
|
||||
@ -186,32 +217,10 @@ UsersPage::createJobs( const QStringList& defaultGroupsList )
|
||||
defaultGroupsList );
|
||||
list.append( Calamares::job_ptr( j ) );
|
||||
|
||||
j = new SetPasswordJob( ui->textBoxUsername->text(), ui->textBoxUserPassword->text() );
|
||||
list.append( Calamares::job_ptr( j ) );
|
||||
|
||||
if ( m_writeRootPassword )
|
||||
{
|
||||
gs->insert( "reuseRootPassword", ui->checkBoxReusePassword->isChecked() );
|
||||
if ( ui->checkBoxReusePassword->isChecked() )
|
||||
{
|
||||
j = new SetPasswordJob( "root", ui->textBoxUserPassword->text() );
|
||||
}
|
||||
else
|
||||
{
|
||||
j = new SetPasswordJob( "root", ui->textBoxRootPassword->text() );
|
||||
}
|
||||
list.append( Calamares::job_ptr( j ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
j = new SetPasswordJob( "root",
|
||||
"" ); //explicitly disable root password
|
||||
list.append( Calamares::job_ptr( j ) );
|
||||
}
|
||||
|
||||
j = new SetHostNameJob( ui->textBoxHostname->text() );
|
||||
list.append( Calamares::job_ptr( j ) );
|
||||
|
||||
gs->insert( "hostname", ui->textBoxHostname->text() );
|
||||
if ( ui->checkBoxAutoLogin->isChecked() )
|
||||
{
|
||||
@ -269,6 +278,38 @@ UsersPage::onFullNameTextEdited( const QString& textRef )
|
||||
checkReady( isReady() );
|
||||
}
|
||||
|
||||
/** @brief Guess the machine's name
|
||||
*
|
||||
* If there is DMI data, use that; otherwise, just call the machine "-pc".
|
||||
* Reads the DMI data just once.
|
||||
*/
|
||||
static QString
|
||||
guessProductName()
|
||||
{
|
||||
static bool tried = false;
|
||||
static QString dmiProduct;
|
||||
|
||||
if ( !tried )
|
||||
{
|
||||
// yes validateHostnameText() but these files can be a mess
|
||||
QRegExp dmirx( "[^a-zA-Z0-9]", Qt::CaseInsensitive );
|
||||
QFile dmiFile( QStringLiteral( "/sys/devices/virtual/dmi/id/product_name" ) );
|
||||
|
||||
if ( dmiFile.exists() && dmiFile.open( QIODevice::ReadOnly ) )
|
||||
{
|
||||
dmiProduct = QString::fromLocal8Bit( dmiFile.readAll().simplified().data() )
|
||||
.toLower()
|
||||
.replace( dmirx, " " )
|
||||
.remove( ' ' );
|
||||
}
|
||||
if ( dmiProduct.isEmpty() )
|
||||
{
|
||||
dmiProduct = QStringLiteral( "-pc" );
|
||||
}
|
||||
tried = true;
|
||||
}
|
||||
return dmiProduct;
|
||||
}
|
||||
|
||||
void
|
||||
UsersPage::fillSuggestions()
|
||||
@ -303,7 +344,9 @@ UsersPage::fillSuggestions()
|
||||
{
|
||||
if ( !cleanParts.isEmpty() && !cleanParts.first().isEmpty() )
|
||||
{
|
||||
QString hostnameSuggestion = QString( "%1-pc" ).arg( cleanParts.first() );
|
||||
QString hostnameSuggestion;
|
||||
QString productName = guessProductName();
|
||||
hostnameSuggestion = QString( "%1-%2" ).arg( cleanParts.first() ).arg( productName );
|
||||
if ( HOSTNAME_RX.indexIn( hostnameSuggestion ) != -1 )
|
||||
{
|
||||
ui->textBoxHostname->setText( hostnameSuggestion );
|
||||
@ -524,8 +567,8 @@ UsersPage::addPasswordCheck( const QString& key, const QVariant& value )
|
||||
{
|
||||
if ( value.toBool() )
|
||||
{
|
||||
m_passwordChecks.push_back( PasswordCheck(
|
||||
[]() { return QCoreApplication::translate( "PWQ", "Password is empty" ); },
|
||||
m_passwordChecks.push_back(
|
||||
PasswordCheck( []() { return QCoreApplication::translate( "PWQ", "Password is empty" ); },
|
||||
[]( const QString& s ) { return !s.isEmpty(); },
|
||||
PasswordCheck::Weight( 1 ) ) );
|
||||
}
|
||||
|
@ -63,6 +63,13 @@ public:
|
||||
*/
|
||||
void addPasswordCheck( const QString& key, const QVariant& value );
|
||||
|
||||
///@brief Hostname as entered / auto-filled
|
||||
QString getHostname() const;
|
||||
///@brief Root password, depends on settings, may be empty
|
||||
QString getRootPassword() const;
|
||||
///@brief User name and password
|
||||
QPair< QString, QString > getUserPassword() const;
|
||||
|
||||
protected slots:
|
||||
void onFullNameTextEdited( const QString& );
|
||||
void fillSuggestions();
|
||||
|
@ -20,10 +20,12 @@
|
||||
|
||||
#include "UsersViewStep.h"
|
||||
|
||||
#include "SetHostNameJob.h"
|
||||
#include "SetPasswordJob.h"
|
||||
#include "UsersPage.h"
|
||||
|
||||
// #include "utils/CalamaresUtils.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/NamedEnum.h"
|
||||
#include "utils/Variant.h"
|
||||
|
||||
#include "GlobalStorage.h"
|
||||
@ -31,9 +33,28 @@
|
||||
|
||||
CALAMARES_PLUGIN_FACTORY_DEFINITION( UsersViewStepFactory, registerPlugin< UsersViewStep >(); )
|
||||
|
||||
static const NamedEnumTable< SetHostNameJob::Action >&
|
||||
hostnameActions()
|
||||
{
|
||||
using Action = SetHostNameJob::Action;
|
||||
|
||||
// *INDENT-OFF*
|
||||
// clang-format off
|
||||
static const NamedEnumTable< Action > names {
|
||||
{ QStringLiteral( "none" ), Action::None },
|
||||
{ QStringLiteral( "etcfile" ), Action::EtcHostname },
|
||||
{ QStringLiteral( "hostnamed" ), Action::SystemdHostname }
|
||||
};
|
||||
// clang-format on
|
||||
// *INDENT-ON*
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
UsersViewStep::UsersViewStep( QObject* parent )
|
||||
: Calamares::ViewStep( parent )
|
||||
, m_widget( new UsersPage() )
|
||||
, m_actions( SetHostNameJob::Action::None )
|
||||
{
|
||||
emit nextStatusChanged( true );
|
||||
connect( m_widget, &UsersPage::checkReady, this, &UsersViewStep::nextStatusChanged );
|
||||
@ -109,14 +130,27 @@ void
|
||||
UsersViewStep::onLeave()
|
||||
{
|
||||
m_jobs.clear();
|
||||
|
||||
m_jobs.append( m_widget->createJobs( m_defaultGroups ) );
|
||||
|
||||
Calamares::Job* j;
|
||||
|
||||
auto userPW = m_widget->getUserPassword();
|
||||
j = new SetPasswordJob( userPW.first, userPW.second );
|
||||
m_jobs.append( Calamares::job_ptr( j ) );
|
||||
|
||||
j = new SetPasswordJob( "root", m_widget->getRootPassword() );
|
||||
m_jobs.append( Calamares::job_ptr( j ) );
|
||||
|
||||
j = new SetHostNameJob( m_widget->getHostname(), m_actions );
|
||||
m_jobs.append( Calamares::job_ptr( j ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UsersViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
{
|
||||
using CalamaresUtils::getBool;
|
||||
|
||||
if ( configurationMap.contains( "defaultGroups" )
|
||||
&& configurationMap.value( "defaultGroups" ).type() == QVariant::List )
|
||||
{
|
||||
@ -142,25 +176,12 @@ UsersViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
configurationMap.value( "sudoersGroup" ).toString() );
|
||||
}
|
||||
|
||||
if ( configurationMap.contains( "setRootPassword" )
|
||||
&& configurationMap.value( "setRootPassword" ).type() == QVariant::Bool )
|
||||
{
|
||||
Calamares::JobQueue::instance()->globalStorage()->insert(
|
||||
"setRootPassword", configurationMap.value( "setRootPassword" ).toBool() );
|
||||
m_widget->setWriteRootPassword( configurationMap.value( "setRootPassword" ).toBool() );
|
||||
}
|
||||
bool setRootPassword = getBool( configurationMap, "setRootPassword", true );
|
||||
Calamares::JobQueue::instance()->globalStorage()->insert( "setRootPassword", setRootPassword );
|
||||
|
||||
if ( configurationMap.contains( "doAutologin" )
|
||||
&& configurationMap.value( "doAutologin" ).type() == QVariant::Bool )
|
||||
{
|
||||
m_widget->setAutologinDefault( configurationMap.value( "doAutologin" ).toBool() );
|
||||
}
|
||||
|
||||
if ( configurationMap.contains( "doReusePassword" )
|
||||
&& configurationMap.value( "doReusePassword" ).type() == QVariant::Bool )
|
||||
{
|
||||
m_widget->setReusePasswordDefault( configurationMap.value( "doReusePassword" ).toBool() );
|
||||
}
|
||||
m_widget->setWriteRootPassword( setRootPassword );
|
||||
m_widget->setAutologinDefault( getBool( configurationMap, "doAutologin", false ) );
|
||||
m_widget->setReusePasswordDefault( getBool( configurationMap, "doReusePassword", false ) );
|
||||
|
||||
if ( configurationMap.contains( "passwordRequirements" )
|
||||
&& configurationMap.value( "passwordRequirements" ).type() == QVariant::Map )
|
||||
@ -173,8 +194,8 @@ UsersViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
}
|
||||
}
|
||||
|
||||
m_widget->setPasswordCheckboxVisible( CalamaresUtils::getBool( configurationMap, "allowWeakPasswords", false ) );
|
||||
m_widget->setValidatePasswordDefault( !CalamaresUtils::getBool( configurationMap, "allowWeakPasswordsDefault", false) );
|
||||
m_widget->setPasswordCheckboxVisible( getBool( configurationMap, "allowWeakPasswords", false ) );
|
||||
m_widget->setValidatePasswordDefault( !getBool( configurationMap, "allowWeakPasswordsDefault", false ) );
|
||||
|
||||
QString shell( QLatin1String( "/bin/bash" ) ); // as if it's not set at all
|
||||
if ( configurationMap.contains( "userShell" ) )
|
||||
@ -184,4 +205,21 @@ UsersViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
// Now it might be explicitly set to empty, which is ok
|
||||
|
||||
Calamares::JobQueue::instance()->globalStorage()->insert( "userShell", shell );
|
||||
|
||||
using Action = SetHostNameJob::Action;
|
||||
|
||||
QString hostnameActionString = CalamaresUtils::getString( configurationMap, "setHostname" );
|
||||
if ( hostnameActionString.isEmpty() )
|
||||
{
|
||||
hostnameActionString = QStringLiteral( "EtcFile" );
|
||||
}
|
||||
bool ok = false;
|
||||
auto hostnameAction = hostnameActions().find( hostnameActionString, ok );
|
||||
if ( !ok )
|
||||
{
|
||||
hostnameAction = Action::EtcHostname;
|
||||
}
|
||||
|
||||
Action hostsfileAction = getBool( configurationMap, "writeHostsFile", true ) ? Action::WriteEtcHosts : Action::None;
|
||||
m_actions = hostsfileAction | hostnameAction;
|
||||
}
|
||||
|
@ -20,13 +20,13 @@
|
||||
#ifndef USERSPAGEPLUGIN_H
|
||||
#define USERSPAGEPLUGIN_H
|
||||
|
||||
#include "SetHostNameJob.h"
|
||||
|
||||
#include "DllMacro.h"
|
||||
#include "utils/PluginFactory.h"
|
||||
#include "viewpages/ViewStep.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <utils/PluginFactory.h>
|
||||
#include <viewpages/ViewStep.h>
|
||||
|
||||
#include <DllMacro.h>
|
||||
|
||||
#include <QVariant>
|
||||
|
||||
class UsersPage;
|
||||
@ -61,6 +61,7 @@ private:
|
||||
QList< Calamares::job_ptr > m_jobs;
|
||||
|
||||
QStringList m_defaultGroups;
|
||||
SetHostNameJob::Actions m_actions;
|
||||
};
|
||||
|
||||
CALAMARES_PLUGIN_FACTORY_DECLARATION( UsersViewStepFactory )
|
||||
|
@ -122,3 +122,17 @@ allowWeakPasswordsDefault: false
|
||||
# - set, non-empty, use that path as shell. No validation is done
|
||||
# that the shell actually exists or is executable.
|
||||
# userShell: /bin/bash
|
||||
|
||||
# Hostname setting
|
||||
#
|
||||
# The user can enter a hostname; this is configured into the system
|
||||
# in some way; pick one of:
|
||||
# - *None*, to not set the hostname at all
|
||||
# - *EtcFile*, to write to `/etc/hostname` directly
|
||||
# - *Hostnamed*, to use systemd hostnamed(1) over DBus
|
||||
# The default is *EtcFile*.
|
||||
setHostname: EtcFile
|
||||
|
||||
# Should /etc/hosts be written with a hostname for this machine
|
||||
# (also adds localhost and some ipv6 standard entries).
|
||||
writeHostsFile: true
|
||||
|
Loading…
Reference in New Issue
Block a user