Skip to content

Commit

Permalink
runfix: e2ei basic device enrollment [WPB-9816] (#17444) (#17448)
Browse files Browse the repository at this point in the history
* Revert "fix: show enrollment modal for existing clients after e2ei activation [WPB-9816] (#17422)"

This reverts commit 72c8c63.

* runfix: show modal for a basic device

* runfix: old client can snooze the enrollment

* test: enrollment for basic credential type

Co-authored-by: Patryk Górka <patrykbunix@gmail.com>
  • Loading branch information
otto-the-bot and PatrykBuniX committed May 23, 2024
1 parent aeb8d5c commit 175986b
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 51 deletions.
62 changes: 45 additions & 17 deletions src/script/E2EIdentity/E2EIdentityEnrollment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,28 @@ function wait(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}

const generateWireIdentity = (
selfClientId: string,
credentialType: CredentialType = CredentialType.X509,
status: e2EIdentityVerification.MLSStatuses = e2EIdentityVerification.MLSStatuses.NOT_ACTIVATED,
) => ({
x509Identity: {
certificate: '',
displayName: 'John Doe',
domain: 'domain',
handle: 'johndoe',
notAfter: BigInt(0),
notBefore: BigInt(0),
serialNumber: '',
},
thumbprint: '',
credentialType,
status,
clientId: selfClientId,
deviceId: selfClientId,
qualifiedUserId: {id: 'userId', domain: 'domain'},
});

const modalMock = jest.spyOn(PrimaryModal, 'show');

describe('E2EIHandler', () => {
Expand Down Expand Up @@ -325,6 +347,26 @@ describe('E2EIHandler', () => {

describe('startTimers()', () => {
describe('should start enrollment for existing devices', () => {
it('with a basic credential type', async () => {
jest.spyOn(coreMock.service!.e2eIdentity!, 'isEnrollmentInProgress').mockResolvedValue(false);
jest.spyOn(coreMock.service!.e2eIdentity!, 'isFreshMLSSelfClient').mockResolvedValue(false);
jest
.spyOn(e2EIdentityVerification, 'getActiveWireIdentity')
.mockResolvedValue(
generateWireIdentity(selfClientId, CredentialType.Basic, e2EIdentityVerification.MLSStatuses.VALID),
);

const instance = await E2EIHandler.getInstance().initialize(params);

const taskSchedulerMock = jest.spyOn(LowPrecisionTaskScheduler, 'addTask');
const primaryModalMock = jest.spyOn(PrimaryModal, 'show');

await instance.startTimers();

expect(taskSchedulerMock).not.toHaveBeenCalled();
expect(primaryModalMock).toHaveBeenCalled();
});

it('without existing WireIdentity', async () => {
jest.spyOn(coreMock.service!.e2eIdentity!, 'isEnrollmentInProgress').mockResolvedValue(false);
jest.spyOn(coreMock.service!.e2eIdentity!, 'isFreshMLSSelfClient').mockResolvedValue(false);
Expand All @@ -344,23 +386,9 @@ describe('E2EIHandler', () => {
it('with pristine WireIdentity', async () => {
jest.spyOn(coreMock.service!.e2eIdentity!, 'isEnrollmentInProgress').mockResolvedValue(false);
jest.spyOn(coreMock.service!.e2eIdentity!, 'isFreshMLSSelfClient').mockResolvedValue(false);
jest.spyOn(e2EIdentityVerification, 'getActiveWireIdentity').mockResolvedValue({
x509Identity: {
certificate: '',
displayName: 'John Doe',
domain: 'domain',
handle: 'johndoe',
notAfter: BigInt(0),
notBefore: BigInt(0),
serialNumber: '',
},
thumbprint: '',
credentialType: CredentialType.X509,
status: e2EIdentityVerification.MLSStatuses.NOT_ACTIVATED,
clientId: selfClientId,
deviceId: selfClientId,
qualifiedUserId: {id: 'userId', domain: 'domain'},
});
jest
.spyOn(e2EIdentityVerification, 'getActiveWireIdentity')
.mockResolvedValue(generateWireIdentity(selfClientId, CredentialType.X509));

const instance = await E2EIHandler.getInstance().initialize(params);

Expand Down
22 changes: 10 additions & 12 deletions src/script/E2EIdentity/E2EIdentityEnrollment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*
*/

import {CredentialType} from '@wireapp/core/lib/messagingProtocols/mls';
import {LowPrecisionTaskScheduler} from '@wireapp/core/lib/util/LowPrecisionTaskScheduler';
import {amplify} from 'amplify';
import {SigninResponse} from 'oidc-client-ts';
Expand Down Expand Up @@ -174,24 +175,18 @@ export class E2EIHandler extends TypedEventEmitter<Events> {
* @returns the delay under which the next enrollment/renewal modal will be prompted
*/
public async startTimers() {
// Get the time when the user was first prompted with the enrollment modal
let storedE2eActivatedAt = this.enrollmentStore.get.e2eiActivatedAt();
// Check if the user has never been prompted with the enrollment modal, default store value is 0
const isFirstActivation = storedE2eActivatedAt === 0;
// If the user has never been prompted with the enrollment modal, we store the current time as the first activation time
if (isFirstActivation) {
storedE2eActivatedAt = Date.now();
this.enrollmentStore.store.e2eiActivatedAt(storedE2eActivatedAt);
}
// We store the first time the user was prompted with the enrollment modal
const storedE2eActivatedAt = this.enrollmentStore.get.e2eiActivatedAt();
const e2eActivatedAt = storedE2eActivatedAt || Date.now();
this.enrollmentStore.store.e2eiActivatedAt(e2eActivatedAt);

const timerKey = 'enrollmentTimer';
const identity = await getActiveWireIdentity();

const {firingDate: computedFiringDate, isSnoozable} = getEnrollmentTimer(
identity,
storedE2eActivatedAt,
e2eActivatedAt,
this.config.gracePeriodInMs,
isFirstActivation,
);

const task = async () => {
Expand All @@ -202,7 +197,10 @@ export class E2EIHandler extends TypedEventEmitter<Events> {
const firingDate = this.enrollmentStore.get.timer() || computedFiringDate;
this.enrollmentStore.store.timer(firingDate);

const isFirstE2EIActivation = !storedE2eActivatedAt && (!identity || identity.status === MLSStatuses.NOT_ACTIVATED);
const isNotActivated = identity?.status === MLSStatuses.NOT_ACTIVATED;
const isBasicDevice = identity?.credentialType === CredentialType.Basic;

const isFirstE2EIActivation = !storedE2eActivatedAt && (!identity || isNotActivated || isBasicDevice);
if (isFirstE2EIActivation || firingDate <= Date.now()) {
// We want to automatically trigger the enrollment modal if it's a devices in team that just activated e2eidentity
// Or if the timer is supposed to fire now
Expand Down
16 changes: 0 additions & 16 deletions src/script/E2EIdentity/EnrollmentTimer/EnrollmentTimer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,6 @@ describe('e2ei delays', () => {
jest.setSystemTime(1709050878009);
});

it('should return an immediate delay at feature activation', () => {
const delay = getEnrollmentTimer(
{
x509Identity: {
certificate: ' ',
notAfter: (Date.now() + TimeInMillis.MINUTE * 10) / 1000,
},
} as any,
Date.now(),
TimeInMillis.DAY * 30,
true,
);

expect(delay).toEqual({firingDate: Date.now(), isSnoozable: true});
});

it('should return an immediate delay if the identity is expired', () => {
const delay = getEnrollmentTimer({status: MLSStatuses.EXPIRED} as any, Date.now(), gracePeriod);

Expand Down
6 changes: 0 additions & 6 deletions src/script/E2EIdentity/EnrollmentTimer/EnrollmentTimer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ export function getEnrollmentTimer(
identity: WireIdentity | undefined,
e2eiActivatedAt: number,
teamGracePeriodDuration: number,
isFirstActivation: boolean = false,
) {
if (identity?.status === MLSStatuses.EXPIRED) {
return {isSnoozable: false, firingDate: Date.now()};
Expand All @@ -100,11 +99,6 @@ export function getEnrollmentTimer(
const deadline = getGracePeriod(identity, e2eiActivatedAt, teamGracePeriodDuration);
const nextTick = getNextTick(deadline);

// For the first activation, we want to trigger the timer immediately
if (isFirstActivation) {
return {isSnoozable: nextTick > 0, firingDate: Date.now()};
}

// When logging in to a old device that doesn't have an identity yet, we trigger an enrollment timer
return {isSnoozable: nextTick > 0, firingDate: Date.now() + nextTick};
}

0 comments on commit 175986b

Please sign in to comment.