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
|
System::createTargetFile( const QString& path, const QByteArray& contents ) const
|
||||||
{
|
{
|
||||||
QString completePath = targetPath( path );
|
QString completePath = targetPath( path );
|
||||||
if ( completePath.isEmpty() )
|
if ( completePath.isEmpty() )
|
||||||
{
|
{
|
||||||
return QString();
|
return CreationResult( CreationResult::Code::Invalid );
|
||||||
}
|
}
|
||||||
|
|
||||||
QFile f( completePath );
|
QFile f( completePath );
|
||||||
if ( f.exists() )
|
if ( f.exists() )
|
||||||
{
|
{
|
||||||
return QString();
|
return CreationResult( CreationResult::Code::AlreadyExists );
|
||||||
}
|
}
|
||||||
|
|
||||||
QIODevice::OpenMode m =
|
QIODevice::OpenMode m =
|
||||||
@ -317,18 +317,18 @@ System::createTargetFile( const QString& path, const QByteArray& contents ) cons
|
|||||||
|
|
||||||
if ( !f.open( m ) )
|
if ( !f.open( m ) )
|
||||||
{
|
{
|
||||||
return QString();
|
return CreationResult( CreationResult::Code::Failed );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( f.write( contents ) != contents.size() )
|
if ( f.write( contents ) != contents.size() )
|
||||||
{
|
{
|
||||||
f.close();
|
f.close();
|
||||||
f.remove();
|
f.remove();
|
||||||
return QString();
|
return CreationResult( CreationResult::Code::Failed );
|
||||||
}
|
}
|
||||||
|
|
||||||
f.close();
|
f.close();
|
||||||
return QFileInfo( f ).canonicalFilePath();
|
return CreationResult( QFileInfo( f ).canonicalFilePath() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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
|
* @brief The System class is a singleton with utility functions that perform
|
||||||
* system-specific operations.
|
* system-specific operations.
|
||||||
@ -244,7 +279,7 @@ public:
|
|||||||
* root of the host system, or empty on failure. (Here, it is
|
* root of the host system, or empty on failure. (Here, it is
|
||||||
* possible to be canonical because the file exists).
|
* 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.
|
/** @brief Remove a file from the target system.
|
||||||
*
|
*
|
||||||
|
@ -46,6 +46,7 @@ private Q_SLOTS:
|
|||||||
void init();
|
void init();
|
||||||
void cleanupTestCase();
|
void cleanupTestCase();
|
||||||
|
|
||||||
|
void testCreationResult();
|
||||||
void testTargetPath();
|
void testTargetPath();
|
||||||
void testCreateTarget();
|
void testCreateTarget();
|
||||||
void testCreateTargetBasedirs();
|
void testCreateTargetBasedirs();
|
||||||
@ -95,6 +96,42 @@ TestPaths::init()
|
|||||||
m_gs->insert( "rootMountPoint", "/tmp" );
|
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
|
void
|
||||||
TestPaths::testTargetPath()
|
TestPaths::testTargetPath()
|
||||||
@ -117,7 +154,10 @@ TestPaths::testTargetPath()
|
|||||||
void
|
void
|
||||||
TestPaths::testCreateTarget()
|
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 );
|
QFileInfo fi( absFile );
|
||||||
QVERIFY( fi.exists() );
|
QVERIFY( fi.exists() );
|
||||||
|
@ -54,7 +54,7 @@ InitramfsJob::exec()
|
|||||||
// First make sure we generate a safe initramfs with suitable permissions.
|
// 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 confFile[] = "/etc/initramfs-tools/conf.d/calamares-safe-initramfs.conf";
|
||||||
static const char contents[] = "UMASK=0077\n";
|
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.";
|
cWarning() << Logger::SubEntry << "Could not configure safe UMASK for initramfs.";
|
||||||
// But continue anyway.
|
// But continue anyway.
|
||||||
|
@ -57,9 +57,12 @@ void InitramfsTests::cleanup()
|
|||||||
|
|
||||||
void InitramfsTests::testCreateHostFile()
|
void InitramfsTests::testCreateHostFile()
|
||||||
{
|
{
|
||||||
|
|
||||||
CalamaresUtils::System s( false ); // don't chroot
|
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() );
|
QVERIFY( !path.isEmpty() );
|
||||||
QCOMPARE( path, confFile ); // don't chroot, so path create relative to /
|
QCOMPARE( path, confFile ); // don't chroot, so path create relative to /
|
||||||
QVERIFY( QFile::exists( confFile ) );
|
QVERIFY( QFile::exists( confFile ) );
|
||||||
@ -67,30 +70,33 @@ void InitramfsTests::testCreateHostFile()
|
|||||||
QFileInfo fi( confFile );
|
QFileInfo fi( confFile );
|
||||||
QVERIFY( fi.exists() );
|
QVERIFY( fi.exists() );
|
||||||
QCOMPARE( fi.size(), sizeof( contents )-1 ); // don't count trailing NUL
|
QCOMPARE( fi.size(), sizeof( contents )-1 ); // don't count trailing NUL
|
||||||
|
|
||||||
QFile::remove( confFile );
|
QFile::remove( confFile );
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitramfsTests::testCreateTargetFile()
|
void InitramfsTests::testCreateTargetFile()
|
||||||
{
|
{
|
||||||
static const char short_confFile[] = "/calamares-safe-umask";
|
static const char short_confFile[] = "/calamares-safe-umask";
|
||||||
|
|
||||||
CalamaresUtils::System s( true );
|
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
|
QVERIFY( path.isEmpty() ); // because no rootmountpoint is set
|
||||||
|
|
||||||
Calamares::JobQueue j;
|
Calamares::JobQueue j;
|
||||||
j.globalStorage()->insert( "rootMountPoint", "/tmp" );
|
j.globalStorage()->insert( "rootMountPoint", "/tmp" );
|
||||||
|
|
||||||
path = s.createTargetFile( short_confFile, QByteArray( contents ) );
|
path = s.createTargetFile( short_confFile, QByteArray( contents ) );
|
||||||
QVERIFY( path.endsWith( short_confFile ) ); // chroot, so path create relative to
|
QVERIFY( path.endsWith( short_confFile ) ); // chroot, so path create relative to
|
||||||
QVERIFY( path.startsWith( "/tmp/" ) );
|
QVERIFY( path.startsWith( "/tmp/" ) );
|
||||||
QVERIFY( QFile::exists( path ) );
|
QVERIFY( QFile::exists( path ) );
|
||||||
|
|
||||||
QFileInfo fi( path );
|
QFileInfo fi( path );
|
||||||
QVERIFY( fi.exists() );
|
QVERIFY( fi.exists() );
|
||||||
QCOMPARE( fi.size(), sizeof( contents )-1 ); // don't count trailing NUL
|
QCOMPARE( fi.size(), sizeof( contents )-1 ); // don't count trailing NUL
|
||||||
|
|
||||||
QFile::remove( path );
|
QFile::remove( path );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -125,8 +125,13 @@ MachineIdTests::testJob()
|
|||||||
gs->insert( "rootMountPoint", "/tmp" );
|
gs->insert( "rootMountPoint", "/tmp" );
|
||||||
|
|
||||||
// Prepare part of the target filesystem
|
// Prepare part of the target filesystem
|
||||||
QVERIFY( system->createTargetDirs("/etc") );
|
{
|
||||||
QVERIFY( !(system->createTargetFile( "/etc/machine-id", "Hello" ).isEmpty() ) );
|
QVERIFY( system->createTargetDirs("/etc") );
|
||||||
|
auto r = system->createTargetFile( "/etc/machine-id", "Hello" );
|
||||||
|
QVERIFY( !r.failed() );
|
||||||
|
QVERIFY( r );
|
||||||
|
QVERIFY( !r.path().isEmpty() );
|
||||||
|
}
|
||||||
|
|
||||||
MachineIdJob job( nullptr );
|
MachineIdJob job( nullptr );
|
||||||
QVERIFY( !job.prettyName().isEmpty() );
|
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 )
|
find_package( Crypt REQUIRED )
|
||||||
|
|
||||||
# Add optional libraries here
|
# Add optional libraries here
|
||||||
@ -36,6 +36,7 @@ calamares_add_plugin( users
|
|||||||
calamaresui
|
calamaresui
|
||||||
${CRYPT_LIBRARIES}
|
${CRYPT_LIBRARIES}
|
||||||
${USER_EXTRA_LIB}
|
${USER_EXTRA_LIB}
|
||||||
|
Qt5::DBus
|
||||||
SHARED_LIB
|
SHARED_LIB
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -22,14 +22,19 @@
|
|||||||
|
|
||||||
#include "GlobalStorage.h"
|
#include "GlobalStorage.h"
|
||||||
#include "JobQueue.h"
|
#include "JobQueue.h"
|
||||||
|
#include "utils/CalamaresUtilsSystem.h"
|
||||||
#include "utils/Logger.h"
|
#include "utils/Logger.h"
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#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()
|
: Calamares::Job()
|
||||||
, m_hostname( hostname )
|
, m_hostname( hostname )
|
||||||
|
, m_actions( a )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,6 +58,58 @@ SetHostNameJob::prettyStatusMessage() const
|
|||||||
return tr( "Setting hostname %1." ).arg( m_hostname );
|
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
|
Calamares::JobResult
|
||||||
SetHostNameJob::exec()
|
SetHostNameJob::exec()
|
||||||
{
|
{
|
||||||
@ -71,43 +128,29 @@ SetHostNameJob::exec()
|
|||||||
return Calamares::JobResult::error( tr( "Internal Error" ) );
|
return Calamares::JobResult::error( tr( "Internal Error" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
QFile hostfile( destDir + "/etc/hostname" );
|
if ( m_actions & Action::EtcHostname )
|
||||||
if ( !hostfile.open( QFile::WriteOnly ) )
|
|
||||||
{
|
{
|
||||||
cError() << "Can't write to hostname file";
|
if ( !setFileHostname( m_hostname ) )
|
||||||
return Calamares::JobResult::error( tr( "Cannot write hostname to target system" ) );
|
{
|
||||||
|
cError() << "Can't write to hostname file";
|
||||||
|
return Calamares::JobResult::error( tr( "Cannot write hostname to target system" ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QTextStream hostfileout( &hostfile );
|
if ( m_actions & Action::WriteEtcHosts )
|
||||||
hostfileout << m_hostname << "\n";
|
|
||||||
hostfile.close();
|
|
||||||
|
|
||||||
QFile hostsfile( destDir + "/etc/hosts" );
|
|
||||||
if ( !hostsfile.open( QFile::WriteOnly ) )
|
|
||||||
{
|
{
|
||||||
cError() << "Can't write to hosts file";
|
if ( !writeFileEtcHosts( m_hostname ) )
|
||||||
return Calamares::JobResult::error( tr( "Cannot write hostname to target system" ) );
|
{
|
||||||
|
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
|
if ( m_actions & Action::SystemdHostname )
|
||||||
QTextStream hostsfileout( &hostsfile );
|
{
|
||||||
// ipv4 support
|
// Does its own logging
|
||||||
hostsfileout << "127.0.0.1"
|
setSystemdHostname( m_hostname );
|
||||||
<< "\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();
|
|
||||||
|
|
||||||
return Calamares::JobResult::ok();
|
return Calamares::JobResult::ok();
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,17 @@ class SetHostNameJob : public Calamares::Job
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
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 prettyName() const override;
|
||||||
QString prettyDescription() const override;
|
QString prettyDescription() const override;
|
||||||
QString prettyStatusMessage() const override;
|
QString prettyStatusMessage() const override;
|
||||||
@ -34,7 +44,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
const QString m_hostname;
|
const QString m_hostname;
|
||||||
|
const Actions m_actions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_OPERATORS_FOR_FLAGS( SetHostNameJob::Actions )
|
||||||
|
|
||||||
#endif // SETHOSTNAMEJOB_CPP_H
|
#endif // SETHOSTNAMEJOB_CPP_H
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
* Copyright 2014-2017, Teo Mrnjavac <teo@kde.org>
|
* Copyright 2014-2017, Teo Mrnjavac <teo@kde.org>
|
||||||
* Copyright 2017-2018, Adriaan de Groot <groot@kde.org>
|
* Copyright 2017-2018, Adriaan de Groot <groot@kde.org>
|
||||||
* Copyright 2019, Collabora Ltd <arnaud.ferraris@collabora.com>
|
* Copyright 2019, Collabora Ltd <arnaud.ferraris@collabora.com>
|
||||||
|
* Copyright 2020, Gabriel Craciunescu <crazy@frugalware.org>
|
||||||
*
|
*
|
||||||
* Portions from the Manjaro Installation Framework
|
* Portions from the Manjaro Installation Framework
|
||||||
* by Roland Singer <roland@manjaro.org>
|
* by Roland Singer <roland@manjaro.org>
|
||||||
@ -40,6 +41,7 @@
|
|||||||
#include "utils/String.h"
|
#include "utils/String.h"
|
||||||
|
|
||||||
#include <QBoxLayout>
|
#include <QBoxLayout>
|
||||||
|
#include <QFile>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QRegExp>
|
#include <QRegExp>
|
||||||
@ -97,14 +99,12 @@ UsersPage::UsersPage( QWidget* parent )
|
|||||||
connect( ui->textBoxUserVerifiedPassword, &QLineEdit::textChanged, this, &UsersPage::onPasswordTextChanged );
|
connect( ui->textBoxUserVerifiedPassword, &QLineEdit::textChanged, this, &UsersPage::onPasswordTextChanged );
|
||||||
connect( ui->textBoxRootPassword, &QLineEdit::textChanged, this, &UsersPage::onRootPasswordTextChanged );
|
connect( ui->textBoxRootPassword, &QLineEdit::textChanged, this, &UsersPage::onRootPasswordTextChanged );
|
||||||
connect( ui->textBoxVerifiedRootPassword, &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() );
|
onPasswordTextChanged( ui->textBoxUserPassword->text() );
|
||||||
onRootPasswordTextChanged( ui->textBoxRootPassword->text() );
|
onRootPasswordTextChanged( ui->textBoxRootPassword->text() );
|
||||||
checkReady( isReady() );
|
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->labelChooseRootPassword->setVisible( !checked );
|
||||||
ui->labelRootPassword->setVisible( !checked );
|
ui->labelRootPassword->setVisible( !checked );
|
||||||
ui->labelRootPasswordError->setVisible( !checked );
|
ui->labelRootPasswordError->setVisible( !checked );
|
||||||
@ -166,6 +166,37 @@ UsersPage::isReady()
|
|||||||
return readyFields && m_readyRootPassword;
|
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 >
|
QList< Calamares::job_ptr >
|
||||||
UsersPage::createJobs( const QStringList& defaultGroupsList )
|
UsersPage::createJobs( const QStringList& defaultGroupsList )
|
||||||
@ -186,32 +217,10 @@ UsersPage::createJobs( const QStringList& defaultGroupsList )
|
|||||||
defaultGroupsList );
|
defaultGroupsList );
|
||||||
list.append( Calamares::job_ptr( j ) );
|
list.append( Calamares::job_ptr( j ) );
|
||||||
|
|
||||||
j = new SetPasswordJob( ui->textBoxUsername->text(), ui->textBoxUserPassword->text() );
|
|
||||||
list.append( Calamares::job_ptr( j ) );
|
|
||||||
|
|
||||||
if ( m_writeRootPassword )
|
if ( m_writeRootPassword )
|
||||||
{
|
{
|
||||||
gs->insert( "reuseRootPassword", ui->checkBoxReusePassword->isChecked() );
|
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() );
|
gs->insert( "hostname", ui->textBoxHostname->text() );
|
||||||
if ( ui->checkBoxAutoLogin->isChecked() )
|
if ( ui->checkBoxAutoLogin->isChecked() )
|
||||||
{
|
{
|
||||||
@ -269,6 +278,38 @@ UsersPage::onFullNameTextEdited( const QString& textRef )
|
|||||||
checkReady( isReady() );
|
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
|
void
|
||||||
UsersPage::fillSuggestions()
|
UsersPage::fillSuggestions()
|
||||||
@ -303,7 +344,9 @@ UsersPage::fillSuggestions()
|
|||||||
{
|
{
|
||||||
if ( !cleanParts.isEmpty() && !cleanParts.first().isEmpty() )
|
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 )
|
if ( HOSTNAME_RX.indexIn( hostnameSuggestion ) != -1 )
|
||||||
{
|
{
|
||||||
ui->textBoxHostname->setText( hostnameSuggestion );
|
ui->textBoxHostname->setText( hostnameSuggestion );
|
||||||
@ -524,10 +567,10 @@ UsersPage::addPasswordCheck( const QString& key, const QVariant& value )
|
|||||||
{
|
{
|
||||||
if ( value.toBool() )
|
if ( value.toBool() )
|
||||||
{
|
{
|
||||||
m_passwordChecks.push_back( PasswordCheck(
|
m_passwordChecks.push_back(
|
||||||
[]() { return QCoreApplication::translate( "PWQ", "Password is empty" ); },
|
PasswordCheck( []() { return QCoreApplication::translate( "PWQ", "Password is empty" ); },
|
||||||
[]( const QString& s ) { return !s.isEmpty(); },
|
[]( const QString& s ) { return !s.isEmpty(); },
|
||||||
PasswordCheck::Weight( 1 ) ) );
|
PasswordCheck::Weight( 1 ) ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef CHECK_PWQUALITY
|
#ifdef CHECK_PWQUALITY
|
||||||
|
@ -63,6 +63,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
void addPasswordCheck( const QString& key, const QVariant& value );
|
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:
|
protected slots:
|
||||||
void onFullNameTextEdited( const QString& );
|
void onFullNameTextEdited( const QString& );
|
||||||
void fillSuggestions();
|
void fillSuggestions();
|
||||||
|
@ -20,10 +20,12 @@
|
|||||||
|
|
||||||
#include "UsersViewStep.h"
|
#include "UsersViewStep.h"
|
||||||
|
|
||||||
|
#include "SetHostNameJob.h"
|
||||||
|
#include "SetPasswordJob.h"
|
||||||
#include "UsersPage.h"
|
#include "UsersPage.h"
|
||||||
|
|
||||||
// #include "utils/CalamaresUtils.h"
|
|
||||||
#include "utils/Logger.h"
|
#include "utils/Logger.h"
|
||||||
|
#include "utils/NamedEnum.h"
|
||||||
#include "utils/Variant.h"
|
#include "utils/Variant.h"
|
||||||
|
|
||||||
#include "GlobalStorage.h"
|
#include "GlobalStorage.h"
|
||||||
@ -31,9 +33,28 @@
|
|||||||
|
|
||||||
CALAMARES_PLUGIN_FACTORY_DEFINITION( UsersViewStepFactory, registerPlugin< UsersViewStep >(); )
|
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 )
|
UsersViewStep::UsersViewStep( QObject* parent )
|
||||||
: Calamares::ViewStep( parent )
|
: Calamares::ViewStep( parent )
|
||||||
, m_widget( new UsersPage() )
|
, m_widget( new UsersPage() )
|
||||||
|
, m_actions( SetHostNameJob::Action::None )
|
||||||
{
|
{
|
||||||
emit nextStatusChanged( true );
|
emit nextStatusChanged( true );
|
||||||
connect( m_widget, &UsersPage::checkReady, this, &UsersViewStep::nextStatusChanged );
|
connect( m_widget, &UsersPage::checkReady, this, &UsersViewStep::nextStatusChanged );
|
||||||
@ -109,14 +130,27 @@ void
|
|||||||
UsersViewStep::onLeave()
|
UsersViewStep::onLeave()
|
||||||
{
|
{
|
||||||
m_jobs.clear();
|
m_jobs.clear();
|
||||||
|
|
||||||
m_jobs.append( m_widget->createJobs( m_defaultGroups ) );
|
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
|
void
|
||||||
UsersViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
UsersViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
||||||
{
|
{
|
||||||
|
using CalamaresUtils::getBool;
|
||||||
|
|
||||||
if ( configurationMap.contains( "defaultGroups" )
|
if ( configurationMap.contains( "defaultGroups" )
|
||||||
&& configurationMap.value( "defaultGroups" ).type() == QVariant::List )
|
&& configurationMap.value( "defaultGroups" ).type() == QVariant::List )
|
||||||
{
|
{
|
||||||
@ -142,25 +176,12 @@ UsersViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
|||||||
configurationMap.value( "sudoersGroup" ).toString() );
|
configurationMap.value( "sudoersGroup" ).toString() );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( configurationMap.contains( "setRootPassword" )
|
bool setRootPassword = getBool( configurationMap, "setRootPassword", true );
|
||||||
&& configurationMap.value( "setRootPassword" ).type() == QVariant::Bool )
|
Calamares::JobQueue::instance()->globalStorage()->insert( "setRootPassword", setRootPassword );
|
||||||
{
|
|
||||||
Calamares::JobQueue::instance()->globalStorage()->insert(
|
|
||||||
"setRootPassword", configurationMap.value( "setRootPassword" ).toBool() );
|
|
||||||
m_widget->setWriteRootPassword( configurationMap.value( "setRootPassword" ).toBool() );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( configurationMap.contains( "doAutologin" )
|
m_widget->setWriteRootPassword( setRootPassword );
|
||||||
&& configurationMap.value( "doAutologin" ).type() == QVariant::Bool )
|
m_widget->setAutologinDefault( getBool( configurationMap, "doAutologin", false ) );
|
||||||
{
|
m_widget->setReusePasswordDefault( getBool( configurationMap, "doReusePassword", false ) );
|
||||||
m_widget->setAutologinDefault( configurationMap.value( "doAutologin" ).toBool() );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( configurationMap.contains( "doReusePassword" )
|
|
||||||
&& configurationMap.value( "doReusePassword" ).type() == QVariant::Bool )
|
|
||||||
{
|
|
||||||
m_widget->setReusePasswordDefault( configurationMap.value( "doReusePassword" ).toBool() );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( configurationMap.contains( "passwordRequirements" )
|
if ( configurationMap.contains( "passwordRequirements" )
|
||||||
&& configurationMap.value( "passwordRequirements" ).type() == QVariant::Map )
|
&& 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->setPasswordCheckboxVisible( getBool( configurationMap, "allowWeakPasswords", false ) );
|
||||||
m_widget->setValidatePasswordDefault( !CalamaresUtils::getBool( configurationMap, "allowWeakPasswordsDefault", false) );
|
m_widget->setValidatePasswordDefault( !getBool( configurationMap, "allowWeakPasswordsDefault", false ) );
|
||||||
|
|
||||||
QString shell( QLatin1String( "/bin/bash" ) ); // as if it's not set at all
|
QString shell( QLatin1String( "/bin/bash" ) ); // as if it's not set at all
|
||||||
if ( configurationMap.contains( "userShell" ) )
|
if ( configurationMap.contains( "userShell" ) )
|
||||||
@ -184,4 +205,21 @@ UsersViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
|||||||
// Now it might be explicitly set to empty, which is ok
|
// Now it might be explicitly set to empty, which is ok
|
||||||
|
|
||||||
Calamares::JobQueue::instance()->globalStorage()->insert( "userShell", shell );
|
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
|
#ifndef USERSPAGEPLUGIN_H
|
||||||
#define USERSPAGEPLUGIN_H
|
#define USERSPAGEPLUGIN_H
|
||||||
|
|
||||||
|
#include "SetHostNameJob.h"
|
||||||
|
|
||||||
|
#include "DllMacro.h"
|
||||||
|
#include "utils/PluginFactory.h"
|
||||||
|
#include "viewpages/ViewStep.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include <utils/PluginFactory.h>
|
|
||||||
#include <viewpages/ViewStep.h>
|
|
||||||
|
|
||||||
#include <DllMacro.h>
|
|
||||||
|
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
class UsersPage;
|
class UsersPage;
|
||||||
@ -61,6 +61,7 @@ private:
|
|||||||
QList< Calamares::job_ptr > m_jobs;
|
QList< Calamares::job_ptr > m_jobs;
|
||||||
|
|
||||||
QStringList m_defaultGroups;
|
QStringList m_defaultGroups;
|
||||||
|
SetHostNameJob::Actions m_actions;
|
||||||
};
|
};
|
||||||
|
|
||||||
CALAMARES_PLUGIN_FACTORY_DECLARATION( UsersViewStepFactory )
|
CALAMARES_PLUGIN_FACTORY_DECLARATION( UsersViewStepFactory )
|
||||||
|
@ -28,13 +28,13 @@ defaultGroups:
|
|||||||
# Disable when your Distribution does not require such a group.
|
# Disable when your Distribution does not require such a group.
|
||||||
autologinGroup: autologin
|
autologinGroup: autologin
|
||||||
# You can control the initial state for the 'autologin checkbox' here.
|
# You can control the initial state for the 'autologin checkbox' here.
|
||||||
# Possible values are:
|
# Possible values are:
|
||||||
# - true to check or
|
# - true to check or
|
||||||
# - false to uncheck
|
# - false to uncheck
|
||||||
# These set the **initial** state of the checkbox.
|
# These set the **initial** state of the checkbox.
|
||||||
doAutologin: true
|
doAutologin: true
|
||||||
|
|
||||||
# When *sudoersGroup* is set to a non-empty string, Calamares creates a
|
# When *sudoersGroup* is set to a non-empty string, Calamares creates a
|
||||||
# sudoers file for the user. This file is located at:
|
# sudoers file for the user. This file is located at:
|
||||||
# `/etc/sudoers.d/10-installer`
|
# `/etc/sudoers.d/10-installer`
|
||||||
# Remember to add the (value of) *sudoersGroup* to *defaultGroups*.
|
# Remember to add the (value of) *sudoersGroup* to *defaultGroups*.
|
||||||
@ -48,8 +48,8 @@ sudoersGroup: wheel
|
|||||||
# Setting this to false , causes the root account to be disabled.
|
# Setting this to false , causes the root account to be disabled.
|
||||||
setRootPassword: true
|
setRootPassword: true
|
||||||
# You can control the initial state for the 'reuse password for root'
|
# You can control the initial state for the 'reuse password for root'
|
||||||
# checkbox here. Possible values are:
|
# checkbox here. Possible values are:
|
||||||
# - true to check or
|
# - true to check or
|
||||||
# - false to uncheck
|
# - false to uncheck
|
||||||
#
|
#
|
||||||
# When checked, the user password is used for the root account too.
|
# When checked, the user password is used for the root account too.
|
||||||
@ -96,18 +96,18 @@ passwordRequirements:
|
|||||||
libpwquality:
|
libpwquality:
|
||||||
- minlen=0
|
- minlen=0
|
||||||
- minclass=0
|
- minclass=0
|
||||||
|
|
||||||
# You can control the visibility of the 'strong passwords' checkbox here.
|
# You can control the visibility of the 'strong passwords' checkbox here.
|
||||||
# Possible values are:
|
# Possible values are:
|
||||||
# - true to show or
|
# - true to show or
|
||||||
# - false to hide (default)
|
# - false to hide (default)
|
||||||
# the checkbox. This checkbox allows the user to choose to disable
|
# the checkbox. This checkbox allows the user to choose to disable
|
||||||
# password-strength-checks. By default the box is **hidden**, so
|
# password-strength-checks. By default the box is **hidden**, so
|
||||||
# that you have to pick a password that satisfies the checks.
|
# that you have to pick a password that satisfies the checks.
|
||||||
allowWeakPasswords: false
|
allowWeakPasswords: false
|
||||||
# You can control the initial state for the 'strong passwords' checkbox here.
|
# You can control the initial state for the 'strong passwords' checkbox here.
|
||||||
# Possible values are:
|
# Possible values are:
|
||||||
# - true to uncheck or
|
# - true to uncheck or
|
||||||
# - false to check (default)
|
# - false to check (default)
|
||||||
# the checkbox by default. Since the box is labeled to enforce strong
|
# the checkbox by default. Since the box is labeled to enforce strong
|
||||||
# passwords, in order to **allow** weak ones by default, the box needs
|
# passwords, in order to **allow** weak ones by default, the box needs
|
||||||
@ -122,3 +122,17 @@ allowWeakPasswordsDefault: false
|
|||||||
# - set, non-empty, use that path as shell. No validation is done
|
# - set, non-empty, use that path as shell. No validation is done
|
||||||
# that the shell actually exists or is executable.
|
# that the shell actually exists or is executable.
|
||||||
# userShell: /bin/bash
|
# 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