Téléverser les fichiers vers "workstation-setup/src"
This commit is contained in:
@@ -339,26 +339,32 @@ Kirigami.ApplicationWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
Item {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.fillHeight: true
|
||||||
spacing: 2
|
|
||||||
|
|
||||||
Controls.Label {
|
Column {
|
||||||
Layout.fillWidth: true
|
anchors.left: parent.left
|
||||||
text: modelData.title
|
anchors.right: parent.right
|
||||||
color: "white"
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
font.pixelSize: 14
|
spacing: 2
|
||||||
font.weight: index === root.currentStep ? Font.DemiBold : Font.Medium
|
|
||||||
horizontalAlignment: Text.AlignLeft
|
|
||||||
}
|
|
||||||
|
|
||||||
Controls.Label {
|
Controls.Label {
|
||||||
Layout.fillWidth: true
|
width: parent.width
|
||||||
text: modelData.subtitle
|
text: modelData.title
|
||||||
color: "#b9cee5"
|
color: "white"
|
||||||
font.pixelSize: 11
|
font.pixelSize: 14
|
||||||
horizontalAlignment: Text.AlignLeft
|
font.weight: index === root.currentStep ? Font.DemiBold : Font.Medium
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
}
|
||||||
|
|
||||||
|
Controls.Label {
|
||||||
|
width: parent.width
|
||||||
|
text: modelData.subtitle
|
||||||
|
color: "#b9cee5"
|
||||||
|
font.pixelSize: 11
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -608,34 +614,72 @@ Kirigami.ApplicationWindow {
|
|||||||
text: "Saisissez le mot de passe que vous venez de choisir et le PIN de la YubiKey. Aucune recovery key n'est demandée dans ce workflow."
|
text: "Saisissez le mot de passe que vous venez de choisir et le PIN de la YubiKey. Aucune recovery key n'est demandée dans ce workflow."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InfoBox {
|
||||||
|
visible: !provisioning.busy
|
||||||
|
iconText: "☝"
|
||||||
|
text: "Après avoir lancé l'association, l'assistant vous indiquera précisément quand toucher la YubiKey. Plusieurs touchers peuvent être nécessaires."
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
id: fidoLiveStatus
|
||||||
|
visible: provisioning.busy && root.currentStep === 3
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
implicitHeight: touchInstruction.implicitHeight + 32
|
implicitHeight: fidoLiveRow.implicitHeight + 32
|
||||||
radius: 12
|
radius: 12
|
||||||
color: "#fffbeb"
|
color: provisioning.fidoTouchRequired ? "#fff7ed" : "#eff6ff"
|
||||||
border.width: 2
|
border.width: provisioning.fidoTouchRequired ? 3 : 1
|
||||||
border.color: "#f59e0b"
|
border.color: provisioning.fidoTouchRequired ? "#f97316" : "#bfdbfe"
|
||||||
|
|
||||||
|
SequentialAnimation on opacity {
|
||||||
|
running: fidoLiveStatus.visible && provisioning.fidoTouchRequired
|
||||||
|
loops: Animation.Infinite
|
||||||
|
NumberAnimation { from: 1.0; to: 0.58; duration: 520 }
|
||||||
|
NumberAnimation { from: 0.58; to: 1.0; duration: 520 }
|
||||||
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
id: fidoLiveRow
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: 16
|
anchors.margins: 16
|
||||||
spacing: 14
|
spacing: 14
|
||||||
|
|
||||||
Controls.Label {
|
Controls.BusyIndicator {
|
||||||
text: "☝"
|
visible: !provisioning.fidoTouchRequired
|
||||||
font.pixelSize: 25
|
running: visible
|
||||||
Layout.alignment: Qt.AlignTop
|
Layout.preferredWidth: 30
|
||||||
|
Layout.preferredHeight: 30
|
||||||
}
|
}
|
||||||
|
|
||||||
Controls.Label {
|
Controls.Label {
|
||||||
id: touchInstruction
|
visible: provisioning.fidoTouchRequired
|
||||||
|
text: "☝"
|
||||||
|
font.pixelSize: 30
|
||||||
|
Layout.alignment: Qt.AlignTop
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: "IMPORTANT : après avoir cliqué sur « Associer la YubiKey », surveillez la clé. Elle peut clignoter plusieurs fois. Touchez-la à CHAQUE clignotement jusqu'à la fin de l'association."
|
spacing: 4
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
color: "#92400e"
|
Controls.Label {
|
||||||
font.pixelSize: 14
|
Layout.fillWidth: true
|
||||||
font.weight: Font.DemiBold
|
text: provisioning.fidoTouchRequired
|
||||||
lineHeight: 1.25
|
? "TOUCHEZ LA YUBIKEY MAINTENANT"
|
||||||
|
: "Association FIDO2 en cours"
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
color: provisioning.fidoTouchRequired ? "#9a3412" : "#1d4ed8"
|
||||||
|
font.pixelSize: provisioning.fidoTouchRequired ? 18 : 15
|
||||||
|
font.weight: Font.Bold
|
||||||
|
}
|
||||||
|
|
||||||
|
Controls.Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: provisioning.fidoStatus
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
color: provisioning.fidoTouchRequired ? "#9a3412" : "#334155"
|
||||||
|
font.pixelSize: 13
|
||||||
|
lineHeight: 1.2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -213,6 +213,70 @@ void ProvisioningBackend::setBusy(bool busy)
|
|||||||
emit busyChanged();
|
emit busyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ProvisioningBackend::resetFidoInteraction()
|
||||||
|
{
|
||||||
|
const bool changed = m_fidoTouchRequired
|
||||||
|
|| m_fidoTouchRequestCount != 0
|
||||||
|
|| !m_fidoStatus.isEmpty();
|
||||||
|
|
||||||
|
m_fidoTouchRequired = false;
|
||||||
|
m_fidoTouchRequestCount = 0;
|
||||||
|
m_fidoStatus.clear();
|
||||||
|
m_helperStdoutBuffer.clear();
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
emit fidoInteractionChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProvisioningBackend::handleHelperStdout(Operation operation, const QByteArray &data)
|
||||||
|
{
|
||||||
|
if (operation != Operation::Fido || data.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_helperStdoutBuffer += data;
|
||||||
|
|
||||||
|
qsizetype newlineIndex = -1;
|
||||||
|
while ((newlineIndex = m_helperStdoutBuffer.indexOf('\n')) >= 0) {
|
||||||
|
QByteArray line = m_helperStdoutBuffer.left(newlineIndex);
|
||||||
|
m_helperStdoutBuffer.remove(0, newlineIndex + 1);
|
||||||
|
if (!line.isEmpty() && line.endsWith('\r')) {
|
||||||
|
line.chop(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
if (line == QByteArrayLiteral("EVENT_FIDO_INITIALIZING")) {
|
||||||
|
m_fidoTouchRequired = false;
|
||||||
|
m_fidoStatus = QStringLiteral("Initialisation de l'association FIDO2…");
|
||||||
|
changed = true;
|
||||||
|
} else if (line == QByteArrayLiteral("EVENT_FIDO_GENERATING")) {
|
||||||
|
m_fidoTouchRequired = false;
|
||||||
|
m_fidoStatus = QStringLiteral("Génération du secret FIDO2…");
|
||||||
|
changed = true;
|
||||||
|
} else if (line == QByteArrayLiteral("EVENT_FIDO_UPDATING_HOME")) {
|
||||||
|
m_fidoTouchRequired = false;
|
||||||
|
m_fidoStatus = QStringLiteral("Mise à jour du home chiffré…");
|
||||||
|
changed = true;
|
||||||
|
} else if (line == QByteArrayLiteral("EVENT_FIDO_SYNCHRONIZING")) {
|
||||||
|
m_fidoTouchRequired = false;
|
||||||
|
m_fidoStatus = QStringLiteral("Synchronisation des clés de chiffrement…");
|
||||||
|
changed = true;
|
||||||
|
} else if (line == QByteArrayLiteral("EVENT_FIDO_TOUCH_REQUIRED")) {
|
||||||
|
m_fidoTouchRequired = true;
|
||||||
|
++m_fidoTouchRequestCount;
|
||||||
|
m_fidoStatus = QStringLiteral("Touchez la YubiKey maintenant — demande %1. Il peut y avoir plusieurs touchers pendant cette étape.")
|
||||||
|
.arg(m_fidoTouchRequestCount);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
emit fidoInteractionChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ProvisioningBackend::secureClear(QByteArray &data)
|
void ProvisioningBackend::secureClear(QByteArray &data)
|
||||||
{
|
{
|
||||||
if (!data.isEmpty()) {
|
if (!data.isEmpty()) {
|
||||||
@@ -359,6 +423,10 @@ void ProvisioningBackend::enrollFido(const QString ¤tPassword,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resetFidoInteraction();
|
||||||
|
m_fidoStatus = QStringLiteral("Préparation de l'association FIDO2…");
|
||||||
|
emit fidoInteractionChanged();
|
||||||
|
|
||||||
startHelper(Operation::Fido,
|
startHelper(Operation::Fido,
|
||||||
QString::fromUtf8(NIXOS_WORKSTATIONS_FIDO_HELPER_PATH),
|
QString::fromUtf8(NIXOS_WORKSTATIONS_FIDO_HELPER_PATH),
|
||||||
currentPassword,
|
currentPassword,
|
||||||
@@ -396,6 +464,7 @@ void ProvisioningBackend::startHelper(Operation operation,
|
|||||||
secureClear(third);
|
secureClear(third);
|
||||||
|
|
||||||
m_helperTimedOut = false;
|
m_helperTimedOut = false;
|
||||||
|
m_helperStdoutBuffer.clear();
|
||||||
setBusy(true);
|
setBusy(true);
|
||||||
|
|
||||||
auto *process = new QProcess(this);
|
auto *process = new QProcess(this);
|
||||||
@@ -432,6 +501,14 @@ void ProvisioningBackend::startHelper(Operation operation,
|
|||||||
timer->start();
|
timer->start();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(process, &QProcess::readyReadStandardOutput, this,
|
||||||
|
[this, process, operation]() {
|
||||||
|
if (m_process != process) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handleHelperStdout(operation, process->readAllStandardOutput());
|
||||||
|
});
|
||||||
|
|
||||||
connect(process, &QProcess::errorOccurred, this,
|
connect(process, &QProcess::errorOccurred, this,
|
||||||
[this, process, timer, operation](QProcess::ProcessError error) {
|
[this, process, timer, operation](QProcess::ProcessError error) {
|
||||||
if (m_process != process || error != QProcess::FailedToStart) {
|
if (m_process != process || error != QProcess::FailedToStart) {
|
||||||
@@ -443,6 +520,9 @@ void ProvisioningBackend::startHelper(Operation operation,
|
|||||||
process->deleteLater();
|
process->deleteLater();
|
||||||
setBusy(false);
|
setBusy(false);
|
||||||
appendLog(operationName(operation) + QStringLiteral(" failed to start"));
|
appendLog(operationName(operation) + QStringLiteral(" failed to start"));
|
||||||
|
if (operation == Operation::Fido) {
|
||||||
|
resetFidoInteraction();
|
||||||
|
}
|
||||||
emitResult(operation, false, QStringLiteral("Impossible de démarrer le composant de configuration."));
|
emitResult(operation, false, QStringLiteral("Impossible de démarrer le composant de configuration."));
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -459,6 +539,10 @@ void ProvisioningBackend::startHelper(Operation operation,
|
|||||||
|
|
||||||
QByteArray stderrData = process->readAllStandardError();
|
QByteArray stderrData = process->readAllStandardError();
|
||||||
QByteArray stdoutData = process->readAllStandardOutput();
|
QByteArray stdoutData = process->readAllStandardOutput();
|
||||||
|
if (operation == Operation::Fido && !stdoutData.isEmpty()) {
|
||||||
|
handleHelperStdout(operation, stdoutData);
|
||||||
|
stdoutData.clear();
|
||||||
|
}
|
||||||
QByteArray combined = stderrData + '\n' + stdoutData;
|
QByteArray combined = stderrData + '\n' + stdoutData;
|
||||||
|
|
||||||
const bool timedOut = m_helperTimedOut;
|
const bool timedOut = m_helperTimedOut;
|
||||||
@@ -515,6 +599,14 @@ void ProvisioningBackend::startHelper(Operation operation,
|
|||||||
setBusy(false);
|
setBusy(false);
|
||||||
refreshState();
|
refreshState();
|
||||||
|
|
||||||
|
if (operation == Operation::Fido) {
|
||||||
|
m_fidoTouchRequired = false;
|
||||||
|
m_fidoStatus = helperSucceeded && markerCreated
|
||||||
|
? QStringLiteral("Association FIDO2 terminée.")
|
||||||
|
: QStringLiteral("Association FIDO2 interrompue.");
|
||||||
|
emit fidoInteractionChanged();
|
||||||
|
}
|
||||||
|
|
||||||
emitResult(operation, helperSucceeded && markerCreated, message);
|
emitResult(operation, helperSucceeded && markerCreated, message);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ class ProvisioningBackend final : public QObject
|
|||||||
Q_PROPERTY(QString currentUser READ currentUser CONSTANT)
|
Q_PROPERTY(QString currentUser READ currentUser CONSTANT)
|
||||||
Q_PROPERTY(QString targetUser READ targetUser CONSTANT)
|
Q_PROPERTY(QString targetUser READ targetUser CONSTANT)
|
||||||
Q_PROPERTY(bool authorizedUser READ authorizedUser CONSTANT)
|
Q_PROPERTY(bool authorizedUser READ authorizedUser CONSTANT)
|
||||||
|
Q_PROPERTY(bool fidoTouchRequired READ fidoTouchRequired NOTIFY fidoInteractionChanged)
|
||||||
|
Q_PROPERTY(int fidoTouchRequestCount READ fidoTouchRequestCount NOTIFY fidoInteractionChanged)
|
||||||
|
Q_PROPERTY(QString fidoStatus READ fidoStatus NOTIFY fidoInteractionChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ProvisioningBackend(QString targetUser, QObject *parent = nullptr);
|
explicit ProvisioningBackend(QString targetUser, QObject *parent = nullptr);
|
||||||
@@ -30,6 +33,9 @@ public:
|
|||||||
QString currentUser() const { return m_currentUser; }
|
QString currentUser() const { return m_currentUser; }
|
||||||
QString targetUser() const { return m_targetUser; }
|
QString targetUser() const { return m_targetUser; }
|
||||||
bool authorizedUser() const;
|
bool authorizedUser() const;
|
||||||
|
bool fidoTouchRequired() const { return m_fidoTouchRequired; }
|
||||||
|
int fidoTouchRequestCount() const { return m_fidoTouchRequestCount; }
|
||||||
|
QString fidoStatus() const { return m_fidoStatus; }
|
||||||
|
|
||||||
// Getters de diagnostic utilisés par main.cpp (--diagnose).
|
// Getters de diagnostic utilisés par main.cpp (--diagnose).
|
||||||
QString stateDirectory() const;
|
QString stateDirectory() const;
|
||||||
@@ -52,6 +58,7 @@ signals:
|
|||||||
void passwordChangeFinished(bool success, const QString &message);
|
void passwordChangeFinished(bool success, const QString &message);
|
||||||
void pinChangeFinished(bool success, const QString &message);
|
void pinChangeFinished(bool success, const QString &message);
|
||||||
void fidoEnrollmentFinished(bool success, const QString &message);
|
void fidoEnrollmentFinished(bool success, const QString &message);
|
||||||
|
void fidoInteractionChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class Operation {
|
enum class Operation {
|
||||||
@@ -69,6 +76,8 @@ private:
|
|||||||
bool createMarker(const QString &path);
|
bool createMarker(const QString &path);
|
||||||
void appendLog(const QString &message) const;
|
void appendLog(const QString &message) const;
|
||||||
void setBusy(bool busy);
|
void setBusy(bool busy);
|
||||||
|
void resetFidoInteraction();
|
||||||
|
void handleHelperStdout(Operation operation, const QByteArray &data);
|
||||||
|
|
||||||
void startHelper(Operation operation,
|
void startHelper(Operation operation,
|
||||||
const QString &helperPath,
|
const QString &helperPath,
|
||||||
@@ -91,4 +100,8 @@ private:
|
|||||||
QString m_targetUser;
|
QString m_targetUser;
|
||||||
QProcess *m_process = nullptr;
|
QProcess *m_process = nullptr;
|
||||||
QByteArray m_pendingPayload;
|
QByteArray m_pendingPayload;
|
||||||
|
QByteArray m_helperStdoutBuffer;
|
||||||
|
bool m_fidoTouchRequired = false;
|
||||||
|
int m_fidoTouchRequestCount = 0;
|
||||||
|
QString m_fidoStatus;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ int main(int argc, char *argv[])
|
|||||||
QGuiApplication::setOrganizationName(QStringLiteral("Raspot"));
|
QGuiApplication::setOrganizationName(QStringLiteral("Raspot"));
|
||||||
QGuiApplication::setOrganizationDomain(QStringLiteral("raspot.in"));
|
QGuiApplication::setOrganizationDomain(QStringLiteral("raspot.in"));
|
||||||
QGuiApplication::setApplicationName(QStringLiteral("NixOS Workstations Setup"));
|
QGuiApplication::setApplicationName(QStringLiteral("NixOS Workstations Setup"));
|
||||||
QGuiApplication::setApplicationVersion(QStringLiteral("1.8.4"));
|
QGuiApplication::setApplicationVersion(QStringLiteral("1.8.5"));
|
||||||
QGuiApplication::setDesktopFileName(QStringLiteral("org.raspot.nixosworkstations.setup"));
|
QGuiApplication::setDesktopFileName(QStringLiteral("org.raspot.nixosworkstations.setup"));
|
||||||
|
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
|
|||||||
Reference in New Issue
Block a user