Device manager - logout of other session (PSG-744) (#9280)
* add sign out of current device section in device details * lint * add sign out cta for other sessions * test other device sign out * add pending sign out loader * tidy * fix strict error * use gap instead of nbsp * use more specific assertions in tests, tweak formatting * tweak test
This commit is contained in:
parent
0c22b15bba
commit
10bb10539b
13 changed files with 371 additions and 49 deletions
|
@ -14,10 +14,12 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
|
||||
import { MatrixClient } from 'matrix-js-sdk/src/client';
|
||||
import { logger } from 'matrix-js-sdk/src/logger';
|
||||
|
||||
import { _t } from "../../../../../languageHandler";
|
||||
import { useOwnDevices } from '../../devices/useOwnDevices';
|
||||
import { DevicesState, useOwnDevices } from '../../devices/useOwnDevices';
|
||||
import SettingsSubsection from '../../shared/SettingsSubsection';
|
||||
import { FilteredDeviceList } from '../../devices/FilteredDeviceList';
|
||||
import CurrentDeviceSection from '../../devices/CurrentDeviceSection';
|
||||
|
@ -28,12 +30,64 @@ import Modal from '../../../../../Modal';
|
|||
import SetupEncryptionDialog from '../../../dialogs/security/SetupEncryptionDialog';
|
||||
import VerificationRequestDialog from '../../../dialogs/VerificationRequestDialog';
|
||||
import LogoutDialog from '../../../dialogs/LogoutDialog';
|
||||
import MatrixClientContext from '../../../../../contexts/MatrixClientContext';
|
||||
import { deleteDevicesWithInteractiveAuth } from '../../devices/deleteDevices';
|
||||
|
||||
const useSignOut = (
|
||||
matrixClient: MatrixClient,
|
||||
refreshDevices: DevicesState['refreshDevices'],
|
||||
): {
|
||||
onSignOutCurrentDevice: () => void;
|
||||
onSignOutOtherDevices: (deviceIds: DeviceWithVerification['device_id'][]) => Promise<void>;
|
||||
signingOutDeviceIds: DeviceWithVerification['device_id'][];
|
||||
} => {
|
||||
const [signingOutDeviceIds, setSigningOutDeviceIds] = useState<DeviceWithVerification['device_id'][]>([]);
|
||||
|
||||
const onSignOutCurrentDevice = () => {
|
||||
Modal.createDialog(
|
||||
LogoutDialog,
|
||||
{}, // props,
|
||||
undefined, // className
|
||||
false, // isPriority
|
||||
true, // isStatic
|
||||
);
|
||||
};
|
||||
|
||||
const onSignOutOtherDevices = async (deviceIds: DeviceWithVerification['device_id'][]) => {
|
||||
if (!deviceIds.length) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
setSigningOutDeviceIds([...signingOutDeviceIds, ...deviceIds]);
|
||||
await deleteDevicesWithInteractiveAuth(
|
||||
matrixClient,
|
||||
deviceIds,
|
||||
async (success) => {
|
||||
if (success) {
|
||||
// @TODO(kerrya) clear selection if was bulk deletion
|
||||
// when added in PSG-659
|
||||
await refreshDevices();
|
||||
}
|
||||
setSigningOutDeviceIds(signingOutDeviceIds.filter(deviceId => !deviceIds.includes(deviceId)));
|
||||
},
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error("Error deleting sessions", error);
|
||||
setSigningOutDeviceIds(signingOutDeviceIds.filter(deviceId => !deviceIds.includes(deviceId)));
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
onSignOutCurrentDevice,
|
||||
onSignOutOtherDevices,
|
||||
signingOutDeviceIds,
|
||||
};
|
||||
};
|
||||
|
||||
const SessionManagerTab: React.FC = () => {
|
||||
const {
|
||||
devices,
|
||||
currentDeviceId,
|
||||
currentUserMember,
|
||||
isLoading,
|
||||
requestDeviceVerification,
|
||||
refreshDevices,
|
||||
|
@ -43,6 +97,10 @@ const SessionManagerTab: React.FC = () => {
|
|||
const filteredDeviceListRef = useRef<HTMLDivElement>(null);
|
||||
const scrollIntoViewTimeoutRef = useRef<ReturnType<typeof setTimeout>>();
|
||||
|
||||
const matrixClient = useContext(MatrixClientContext);
|
||||
const userId = matrixClient.getUserId();
|
||||
const currentUserMember = userId && matrixClient.getUser(userId) || undefined;
|
||||
|
||||
const onDeviceExpandToggle = (deviceId: DeviceWithVerification['device_id']): void => {
|
||||
if (expandedDeviceIds.includes(deviceId)) {
|
||||
setExpandedDeviceIds(expandedDeviceIds.filter(id => id !== deviceId));
|
||||
|
@ -91,14 +149,11 @@ const SessionManagerTab: React.FC = () => {
|
|||
});
|
||||
}, [requestDeviceVerification, refreshDevices, currentUserMember]);
|
||||
|
||||
const onSignOutCurrentDevice = () => {
|
||||
if (!currentDevice) {
|
||||
return;
|
||||
}
|
||||
Modal.createDialog(LogoutDialog,
|
||||
/* props= */{}, /* className= */undefined,
|
||||
/* isPriority= */false, /* isStatic= */true);
|
||||
};
|
||||
const {
|
||||
onSignOutCurrentDevice,
|
||||
onSignOutOtherDevices,
|
||||
signingOutDeviceIds,
|
||||
} = useSignOut(matrixClient, refreshDevices);
|
||||
|
||||
useEffect(() => () => {
|
||||
clearTimeout(scrollIntoViewTimeoutRef.current);
|
||||
|
@ -113,6 +168,7 @@ const SessionManagerTab: React.FC = () => {
|
|||
<CurrentDeviceSection
|
||||
device={currentDevice}
|
||||
isLoading={isLoading}
|
||||
isSigningOut={signingOutDeviceIds.includes(currentDevice?.device_id)}
|
||||
onVerifyCurrentDevice={onVerifyCurrentDevice}
|
||||
onSignOutCurrentDevice={onSignOutCurrentDevice}
|
||||
/>
|
||||
|
@ -130,9 +186,11 @@ const SessionManagerTab: React.FC = () => {
|
|||
devices={otherDevices}
|
||||
filter={filter}
|
||||
expandedDeviceIds={expandedDeviceIds}
|
||||
signingOutDeviceIds={signingOutDeviceIds}
|
||||
onFilterChange={setFilter}
|
||||
onDeviceExpandToggle={onDeviceExpandToggle}
|
||||
onRequestDeviceVerification={requestDeviceVerification ? onTriggerDeviceVerification : undefined}
|
||||
onSignOutDevices={onSignOutOtherDevices}
|
||||
ref={filteredDeviceListRef}
|
||||
/>
|
||||
</SettingsSubsection>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue