Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Users step #5280

Merged
merged 19 commits into from
Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
95107cf
webui: use dynamic rules in password form component
rvykydal Oct 20, 2023
5f40775
webui: move also password strength logic into pw form component
rvykydal Oct 23, 2023
17901f1
webui: move pasword form component into a separate file
rvykydal Oct 23, 2023
d7b83f7
webui: add a simple Create Account screen
rvykydal Oct 16, 2023
69d9fdc
webui: use password form component for Create Account screen
rvykydal Oct 23, 2023
b01f27b
webui: share length password rule between users and disk encryption
rvykydal Oct 23, 2023
f0453c1
webui: add simplest user name check to Create Accounts
rvykydal Oct 24, 2023
a45f9d8
webui: keep the state of Create Account UI
rvykydal Oct 24, 2023
143740d
webui: make partitioning reset on going back more robust
rvykydal Oct 24, 2023
86e8edb
webui: apply the created user to the backend
rvykydal Oct 25, 2023
4021cc1
webui: make created user administarator by default
rvykydal Oct 31, 2023
d7af610
webui: hide user screen on live images
rvykydal Nov 1, 2023
1593bcd
webui: add simple test for users screen
rvykydal Nov 2, 2023
7865158
webui: add users screen to tests for sidebar navigation
rvykydal Nov 2, 2023
3d23299
webui: allow to create user more easily for reaching a step in test
rvykydal Nov 2, 2023
3bf083a
webui: create required user when reaching a test step by default
rvykydal Nov 3, 2023
415843e
webui: update end2end tests for the new users screen
rvykydal Nov 3, 2023
1588dad
webui: fix password strength indicator layout in horizontal form
rvykydal Nov 6, 2023
fb8257c
webui: update pixel test images
rvykydal Oct 31, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions ui/webui/src/apis/users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2023 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with This program; If not, see <http://www.gnu.org/licenses/>.
*/
import cockpit from "cockpit";
import { _setProperty } from "./helpers.js";

const OBJECT_PATH = "/org/fedoraproject/Anaconda/Modules/Users";
const INTERFACE_NAME = "org.fedoraproject.Anaconda.Modules.Users";

const setProperty = (...args) => {
return _setProperty(UsersClient, OBJECT_PATH, INTERFACE_NAME, ...args);
};

export class UsersClient {
constructor (address) {
if (UsersClient.instance && (!address || UsersClient.instance.address === address)) {
return UsersClient.instance;
}

UsersClient.instance?.client.close();

UsersClient.instance = this;

this.client = cockpit.dbus(
INTERFACE_NAME,
{ superuser: "try", bus: "none", address }
);
this.address = address;
}

init () {
this.client.addEventListener(
"close", () => console.error("Users client closed")
);
}
}

/**
* @param {Array.<Object>} users An array of user objects
*/
export const setUsers = (users) => {
return setProperty("Users", cockpit.variant("aa{sv}", users));
};
35 changes: 30 additions & 5 deletions ui/webui/src/components/AnacondaWizard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import { getDefaultScenario } from "./storage/InstallationScenario.jsx";
import { MountPointMapping, getPageProps as getMountPointMappingProps } from "./storage/MountPointMapping.jsx";
import { DiskEncryption, getStorageEncryptionState, getPageProps as getDiskEncryptionProps } from "./storage/DiskEncryption.jsx";
import { InstallationLanguage, getPageProps as getInstallationLanguageProps } from "./localization/InstallationLanguage.jsx";
import { Accounts, getPageProps as getAccountsProps, getAccountsState, accountsToDbusUsers } from "./users/Accounts.jsx";
import { InstallationProgress } from "./installation/InstallationProgress.jsx";
import { ReviewConfiguration, ReviewConfigurationConfirmModal, getPageProps as getReviewConfigurationProps } from "./review/ReviewConfiguration.jsx";
import { exitGui } from "../helpers/exit.js";
Expand All @@ -50,6 +51,9 @@ import {
applyStorage,
resetPartitioning,
} from "../apis/storage_partitioning.js";
import {
setUsers,
} from "../apis/users.js";
import { SystemTypeContext, OsReleaseContext } from "./Common.jsx";

const _ = cockpit.gettext;
Expand All @@ -63,6 +67,7 @@ export const AnacondaWizard = ({ dispatch, storageData, localizationData, runtim
const [stepNotification, setStepNotification] = useState();
const [storageEncryption, setStorageEncryption] = useState(getStorageEncryptionState());
const [storageScenarioId, setStorageScenarioId] = useState(window.sessionStorage.getItem("storage-scenario-id") || getDefaultScenario().id);
const [accounts, setAccounts] = useState(getAccountsState());
const [showWizard, setShowWizard] = useState(true);
const osRelease = useContext(OsReleaseContext);
const isBootIso = useContext(SystemTypeContext) === "BOOT_ISO";
Expand Down Expand Up @@ -143,6 +148,15 @@ export const AnacondaWizard = ({ dispatch, storageData, localizationData, runtim
...getDiskEncryptionProps({ storageScenarioId })
}]
},
{
component: Accounts,
data: {
accounts,
setAccounts,
passwordPolicies: runtimeData.passwordPolicies,
},
...getAccountsProps({ isBootIso })
},
{
component: ReviewConfiguration,
data: {
Expand Down Expand Up @@ -178,10 +192,14 @@ export const AnacondaWizard = ({ dispatch, storageData, localizationData, runtim
const firstStepId = stepsOrder.filter(step => !step.isHidden)[0].id;
const currentStepId = path[0] || firstStepId;

const isStepFollowedBy = (earlierStepId, laterStepId) => {
const earlierStepIdx = flattenedStepsIds.findIndex(s => s === earlierStepId);
const laterStepIdx = flattenedStepsIds.findIndex(s => s === laterStepId);
return earlierStepIdx < laterStepIdx;
};

const canJumpToStep = (stepId, currentStepId) => {
const stepIdx = flattenedStepsIds.findIndex(s => s === stepId);
const currentStepIdx = flattenedStepsIds.findIndex(s => s === currentStepId);
return stepIdx <= currentStepIdx;
return stepId === currentStepId || isStepFollowedBy(stepId, currentStepId);
};

const createSteps = (stepsOrder) => {
Expand Down Expand Up @@ -224,8 +242,10 @@ export const AnacondaWizard = ({ dispatch, storageData, localizationData, runtim
setIsFormValid(false);
}

// Reset the applied partitioning when going back from review page
if (prevStep.prevId === "installation-review") {
// Reset the applied partitioning when going back from a step after creating partitioning to a step
// before creating partitioning.
if ((prevStep.prevId === "accounts" || isStepFollowedBy("accounts", prevStep.prevId)) &&
isStepFollowedBy(newStep.id, "accounts")) {
setIsFormDisabled(true);
resetPartitioning()
.then(
Expand Down Expand Up @@ -262,6 +282,7 @@ export const AnacondaWizard = ({ dispatch, storageData, localizationData, runtim
stepsOrder={stepsOrder}
storageEncryption={storageEncryption}
storageScenarioId={storageScenarioId}
accounts={accounts}
/>}
hideClose
mainAriaLabel={`${title} content`}
Expand All @@ -288,6 +309,7 @@ const Footer = ({
stepsOrder,
storageEncryption,
storageScenarioId,
accounts,
}) => {
const [nextWaitsConfirmation, setNextWaitsConfirmation] = useState(false);
const [quitWaitsConfirmation, setQuitWaitsConfirmation] = useState(false);
Expand Down Expand Up @@ -338,6 +360,9 @@ const Footer = ({
setStepNotification();
},
});
} else if (activeStep.id === "accounts") {
setUsers(accountsToDbusUsers(accounts));
onNext();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm does this need special condition? The else { does the same.

Copy link
Contributor Author

@rvykydal rvykydal Oct 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is setUsers ? Strange it is not visible here. IIRC I did one rebase of the PR but it was on Wed afternoon, nevermind...

} else {
onNext();
}
Expand Down
Loading