diff --git a/new-ui/src/pages/full/EnrollmentPage/hooks/activateUser.ts b/new-ui/src/pages/full/EnrollmentPage/hooks/activateUser.ts new file mode 100644 index 00000000..78b6f06a --- /dev/null +++ b/new-ui/src/pages/full/EnrollmentPage/hooks/activateUser.ts @@ -0,0 +1,20 @@ +import { edgeApi } from '../../../../shared/edge-api/api'; +import { useEnrollmentStore } from './useEnrollmentStore'; + +/** + * Activate the enrolling user by calling the proxy activation API. + * + * Reads proxy URL, cookie, skipPassword, and userPassword from the store via + * {@linkcode useEnrollmentStore.getState} so every invocation uses the latest + * values (no stale-closure risk after in-flight {@linkcode setState} updates). + * + * When `skipPassword` is true the `password` key is omitted from the request + * body instead of sending `null` or an empty string. + */ +export const activateUser = async () => { + const { proxyUrl, sessionCookie, skipPassword, userPassword } = + useEnrollmentStore.getState(); + const body = skipPassword ? {} : { password: userPassword ?? '' }; + // biome-ignore lint/style/noNonNullAssertion: proxy and cookie are set in start() + return edgeApi.activateUser(proxyUrl!, sessionCookie!, body); +}; diff --git a/new-ui/src/pages/full/EnrollmentPage/hooks/useEnrollmentStore.tsx b/new-ui/src/pages/full/EnrollmentPage/hooks/useEnrollmentStore.tsx index 67b1e6c4..5d8ce4f8 100644 --- a/new-ui/src/pages/full/EnrollmentPage/hooks/useEnrollmentStore.tsx +++ b/new-ui/src/pages/full/EnrollmentPage/hooks/useEnrollmentStore.tsx @@ -61,6 +61,7 @@ export const useEnrollmentStore = create()( skipMfaChoice: !response.settings.smtp_configured || !response.settings.mfa_required, skipMfa: !response.settings.mfa_required, + skipPassword: response.user.password_management_disabled, deadline: dayjs.unix(response.deadline_timestamp).toISOString(), userTotpSecret: secret ?? null, }); diff --git a/new-ui/src/pages/full/EnrollmentPage/steps/MfaConfigurationStep/MfaConfigurationStep.tsx b/new-ui/src/pages/full/EnrollmentPage/steps/MfaConfigurationStep/MfaConfigurationStep.tsx index 88799349..e349378a 100644 --- a/new-ui/src/pages/full/EnrollmentPage/steps/MfaConfigurationStep/MfaConfigurationStep.tsx +++ b/new-ui/src/pages/full/EnrollmentPage/steps/MfaConfigurationStep/MfaConfigurationStep.tsx @@ -12,15 +12,16 @@ import { MfaMethod } from '../../../../../shared/rust-api/types'; import { ThemeSpacing } from '../../../../../shared/types'; import { isPresent } from '../../../../../shared/utils/isPresent'; import { EnrollmentControls } from '../../components/EnrollmentControls/EnrollmentControls'; +import { activateUser } from '../../hooks/activateUser'; import { useEnrollmentStore } from '../../hooks/useEnrollmentStore'; export const MfaConfigurationStep = () => { const method = useEnrollmentStore((s) => s.userMfaChoice); const [code, setCode] = useState(null); const [error, setError] = useState(null); - const [proxyUrl, cookie, password] = useEnrollmentStore( + const [proxyUrl, cookie] = useEnrollmentStore( // biome-ignore lint/style/noNonNullAssertion: safe - useShallow((s) => [s.proxyUrl!, s.sessionCookie!, s.userPassword!]), + useShallow((s) => [s.proxyUrl!, s.sessionCookie!]), ); const { mutate, isPending } = useMutation({ @@ -30,9 +31,7 @@ export const MfaConfigurationStep = () => { code: code!, method, }); - await edgeApi.activateUser(proxyUrl, cookie, { - password, - }); + await activateUser(); return resp; }, onError: () => {}, diff --git a/new-ui/src/pages/full/EnrollmentPage/steps/PasswordStep/PasswordStep.tsx b/new-ui/src/pages/full/EnrollmentPage/steps/PasswordStep/PasswordStep.tsx index ed08c7ba..f1af01e3 100644 --- a/new-ui/src/pages/full/EnrollmentPage/steps/PasswordStep/PasswordStep.tsx +++ b/new-ui/src/pages/full/EnrollmentPage/steps/PasswordStep/PasswordStep.tsx @@ -14,6 +14,7 @@ import { formChangeLogic } from '../../../../../shared/formLogic'; import { MfaMethod } from '../../../../../shared/rust-api/types'; import { ThemeSpacing } from '../../../../../shared/types'; import { EnrollmentControls } from '../../components/EnrollmentControls/EnrollmentControls'; +import { activateUser } from '../../hooks/activateUser'; import { useEnrollmentStore } from '../../hooks/useEnrollmentStore'; import { type PasswordErrorCodeValue, @@ -85,14 +86,11 @@ export const PasswordStep = () => { return; } } + useEnrollmentStore.setState({ + userPassword: value.password.trim(), + }); if (skipMfa) { - await edgeApi.activateUser(proxyUrl, cookie, { - password: value.password, - }); - } else { - useEnrollmentStore.setState({ - userPassword: value.password.trim(), - }); + await activateUser(); } useEnrollmentStore.getState().next(); }, diff --git a/new-ui/src/pages/full/EnrollmentPage/steps/WelcomeStep/WelcomeStep.tsx b/new-ui/src/pages/full/EnrollmentPage/steps/WelcomeStep/WelcomeStep.tsx index 5036be5c..858f9017 100644 --- a/new-ui/src/pages/full/EnrollmentPage/steps/WelcomeStep/WelcomeStep.tsx +++ b/new-ui/src/pages/full/EnrollmentPage/steps/WelcomeStep/WelcomeStep.tsx @@ -1,15 +1,19 @@ import './style.scss'; import dayjs from 'dayjs'; -import { useMemo } from 'react'; +import { useMemo, useState } from 'react'; import { InfoBanner } from '../../../../../shared/components/InfoBanner/InfoBanner'; import { SizedBox } from '../../../../../shared/components/SizedBox/SizedBox'; import { ThemeSpacing } from '../../../../../shared/types'; import { formatDuration } from '../../../../../shared/utils/formatDuration'; import { EnrollmentControls } from '../../components/EnrollmentControls/EnrollmentControls'; +import { activateUser } from '../../hooks/activateUser'; import { useEnrollmentStore } from '../../hooks/useEnrollmentStore'; export const WelcomeStep = () => { const enrollData = useEnrollmentStore((s) => s.startResponse); + const [activating, setActivating] = useState(false); + const skipPassword = useEnrollmentStore((s) => s.skipPassword); + const skipMfa = useEnrollmentStore((s) => s.skipMfa); const timeLeft = useMemo(() => { const deadline = enrollData?.deadline_timestamp; @@ -32,8 +36,8 @@ export const WelcomeStep = () => {
    -
  • {`Create your password`}
  • -
  • {`Configure MFA`}
  • + {!skipPassword &&
  • {`Create your password`}
  • } + {!skipMfa &&
  • {`Configure MFA`}
  • }
{ {enrollData.admin.email} { + onNext={async () => { + if (skipPassword && skipMfa) { + setActivating(true); + await activateUser(); + } useEnrollmentStore.getState().next(); }} disableBack + loading={activating} /> ); diff --git a/new-ui/src/shared/edge-api/types.ts b/new-ui/src/shared/edge-api/types.ts index 26eb60df..a4e05094 100644 --- a/new-ui/src/shared/edge-api/types.ts +++ b/new-ui/src/shared/edge-api/types.ts @@ -24,6 +24,7 @@ export type UserInfo = { phone_number: string; device_names: string[]; enrolled: boolean; + password_management_disabled: boolean; }; export type EnrollmentSettings = { @@ -76,7 +77,7 @@ export type MfaSetupFinishRequest = { code: string; method: MfaMethodValue }; export type MfaSetupFinishResponse = { recovery_codes: string[] }; export type ActivateUserRequest = { - password: string; + password?: string; phone_number: string; }; diff --git a/nix/package.nix b/nix/package.nix index 67916379..0417b987 100644 --- a/nix/package.nix +++ b/nix/package.nix @@ -200,8 +200,8 @@ in cp ${desktopItem}/share/applications/* $out/share/applications/ mkdir -p $out/share/icons/hicolor/{32x32,128x128}/apps - install -Dm644 src-tauri/icons/32x32.png $out/share/icons/hicolor/32x32/apps/${pname}.png - install -Dm644 src-tauri/icons/128x128.png $out/share/icons/hicolor/128x128/apps/${pname}.png + install -Dm644 src-tauri/icons/windows/32x32.png $out/share/icons/hicolor/32x32/apps/${pname}.png + install -Dm644 src-tauri/icons/windows/128x128.png $out/share/icons/hicolor/128x128/apps/${pname}.png runHook postInstall ''; diff --git a/nix/shell.nix b/nix/shell.nix index 836d01ec..428c640c 100644 --- a/nix/shell.nix +++ b/nix/shell.nix @@ -54,6 +54,7 @@ in trivy desktop-file-utils xdg-utils + just ]; shellHook = with pkgs; '' diff --git a/src-tauri/enterprise/posture/src/inspector/mod.rs b/src-tauri/enterprise/posture/src/inspector/mod.rs index d168d68c..b60209b7 100644 --- a/src-tauri/enterprise/posture/src/inspector/mod.rs +++ b/src-tauri/enterprise/posture/src/inspector/mod.rs @@ -130,5 +130,6 @@ pub fn device_posture_data() -> DevicePostureData { windows_security_update_age_days: Some(Int32Check::from(security_update_age_days())), linux_kernel_version: Some(StringCheck::from(linux_kernel_version())), device_integrity: Some(BoolCheck::from(device_integrity())), + android_security_patch_date: None, } } diff --git a/src-tauri/proto b/src-tauri/proto index e84d7c0c..053e83dc 160000 --- a/src-tauri/proto +++ b/src-tauri/proto @@ -1 +1 @@ -Subproject commit e84d7c0c7d4270e05ec6d1e536353a5e0449d458 +Subproject commit 053e83dc45f0effe19e4f7faad6ccba2c458c241