refactor: remove application mfa helper functions (#2852)
This commit is contained in:
@@ -917,28 +917,6 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
|
|||||||
return service.canAttemptDecryptionOfItem(item)
|
return service.canAttemptDecryptionOfItem(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
public async isMfaActivated(): Promise<boolean> {
|
|
||||||
return this.mfa.isMfaActivated()
|
|
||||||
}
|
|
||||||
|
|
||||||
public async generateMfaSecret(): Promise<string> {
|
|
||||||
return this.mfa.generateMfaSecret()
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getOtpToken(secret: string): Promise<string> {
|
|
||||||
return this.mfa.getOtpToken(secret)
|
|
||||||
}
|
|
||||||
|
|
||||||
public async enableMfa(secret: string, otpToken: string): Promise<void> {
|
|
||||||
return this.mfa.enableMfa(secret, otpToken)
|
|
||||||
}
|
|
||||||
|
|
||||||
public async disableMfa(): Promise<void> {
|
|
||||||
if (await this.protections.authorizeMfaDisable()) {
|
|
||||||
return this.mfa.disableMfa()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async isUsingHomeServer(): Promise<boolean> {
|
async isUsingHomeServer(): Promise<boolean> {
|
||||||
const homeServerService = this.dependencies.get<HomeServerServiceInterface>(TYPES.HomeServerService)
|
const homeServerService = this.dependencies.get<HomeServerServiceInterface>(TYPES.HomeServerService)
|
||||||
|
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ import {
|
|||||||
SyncBackoffService,
|
SyncBackoffService,
|
||||||
SyncBackoffServiceInterface,
|
SyncBackoffServiceInterface,
|
||||||
StorageServiceInterface,
|
StorageServiceInterface,
|
||||||
|
ProtectionsClientInterface,
|
||||||
} from '@standardnotes/services'
|
} from '@standardnotes/services'
|
||||||
import { ItemManager } from '../../Services/Items/ItemManager'
|
import { ItemManager } from '../../Services/Items/ItemManager'
|
||||||
import { PayloadManager } from '../../Services/Payloads/PayloadManager'
|
import { PayloadManager } from '../../Services/Payloads/PayloadManager'
|
||||||
@@ -1229,6 +1230,7 @@ export class Dependencies {
|
|||||||
this.get<SettingsService>(TYPES.SettingsService),
|
this.get<SettingsService>(TYPES.SettingsService),
|
||||||
this.get<PureCryptoInterface>(TYPES.Crypto),
|
this.get<PureCryptoInterface>(TYPES.Crypto),
|
||||||
this.get<FeaturesService>(TYPES.FeaturesService),
|
this.get<FeaturesService>(TYPES.FeaturesService),
|
||||||
|
this.get<ProtectionsClientInterface>(TYPES.ProtectionService),
|
||||||
this.get<InternalEventBus>(TYPES.InternalEventBus),
|
this.get<InternalEventBus>(TYPES.InternalEventBus),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
import { SettingsService } from '../Settings'
|
import { SettingsService } from '../Settings'
|
||||||
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
|
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
|
||||||
import { FeaturesService } from '../Features/FeaturesService'
|
import { FeaturesService } from '../Features/FeaturesService'
|
||||||
import { AbstractService, InternalEventBusInterface, MfaServiceInterface, SignInStrings } from '@standardnotes/services'
|
import {
|
||||||
|
AbstractService,
|
||||||
|
InternalEventBusInterface,
|
||||||
|
MfaServiceInterface,
|
||||||
|
ProtectionsClientInterface,
|
||||||
|
SignInStrings,
|
||||||
|
} from '@standardnotes/services'
|
||||||
import { SettingName } from '@standardnotes/domain-core'
|
import { SettingName } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
export class MfaService extends AbstractService implements MfaServiceInterface {
|
export class MfaService extends AbstractService implements MfaServiceInterface {
|
||||||
@@ -9,6 +15,7 @@ export class MfaService extends AbstractService implements MfaServiceInterface {
|
|||||||
private settingsService: SettingsService,
|
private settingsService: SettingsService,
|
||||||
private crypto: PureCryptoInterface,
|
private crypto: PureCryptoInterface,
|
||||||
private featuresService: FeaturesService,
|
private featuresService: FeaturesService,
|
||||||
|
private protections: ProtectionsClientInterface,
|
||||||
protected override internalEventBus: InternalEventBusInterface,
|
protected override internalEventBus: InternalEventBusInterface,
|
||||||
) {
|
) {
|
||||||
super(internalEventBus)
|
super(internalEventBus)
|
||||||
@@ -48,6 +55,10 @@ export class MfaService extends AbstractService implements MfaServiceInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async disableMfa(): Promise<void> {
|
async disableMfa(): Promise<void> {
|
||||||
|
if (!(await this.protections.authorizeMfaDisable())) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
return await this.settingsService.deleteSetting(SettingName.create(SettingName.NAMES.MfaSecret).getValue())
|
return await this.settingsService.deleteSetting(SettingName.create(SettingName.NAMES.MfaSecret).getValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ describe('mfa service', () => {
|
|||||||
it('generates 160 bit base32-encoded mfa secret', async () => {
|
it('generates 160 bit base32-encoded mfa secret', async () => {
|
||||||
const RFC4648 = /[ABCDEFGHIJKLMNOPQRSTUVWXYZ234567]/g
|
const RFC4648 = /[ABCDEFGHIJKLMNOPQRSTUVWXYZ234567]/g
|
||||||
|
|
||||||
const secret = await application.generateMfaSecret()
|
const secret = await application.mfa.generateMfaSecret()
|
||||||
expect(secret).to.have.lengthOf(32)
|
expect(secret).to.have.lengthOf(32)
|
||||||
expect(secret.replace(RFC4648, '')).to.have.lengthOf(0)
|
expect(secret.replace(RFC4648, '')).to.have.lengthOf(0)
|
||||||
})
|
})
|
||||||
@@ -43,30 +43,30 @@ describe('mfa service', () => {
|
|||||||
|
|
||||||
Factory.handlePasswordChallenges(application, accountPassword)
|
Factory.handlePasswordChallenges(application, accountPassword)
|
||||||
|
|
||||||
expect(await application.isMfaActivated()).to.equal(false)
|
expect(await application.mfa.isMfaActivated()).to.equal(false)
|
||||||
|
|
||||||
const secret = await application.generateMfaSecret()
|
const secret = await application.mfa.generateMfaSecret()
|
||||||
const token = await application.getOtpToken(secret)
|
const token = await application.mfa.getOtpToken(secret)
|
||||||
|
|
||||||
await application.enableMfa(secret, token)
|
await application.mfa.enableMfa(secret, token)
|
||||||
|
|
||||||
expect(await application.isMfaActivated()).to.equal(true)
|
expect(await application.mfa.isMfaActivated()).to.equal(true)
|
||||||
|
|
||||||
await application.disableMfa()
|
await application.mfa.disableMfa()
|
||||||
|
|
||||||
expect(await application.isMfaActivated()).to.equal(false)
|
expect(await application.mfa.isMfaActivated()).to.equal(false)
|
||||||
}).timeout(Factory.TenSecondTimeout)
|
}).timeout(Factory.TenSecondTimeout)
|
||||||
|
|
||||||
it('prompts for account password when disabling mfa', async () => {
|
it('prompts for account password when disabling mfa', async () => {
|
||||||
await registerApp(application)
|
await registerApp(application)
|
||||||
|
|
||||||
Factory.handlePasswordChallenges(application, accountPassword)
|
Factory.handlePasswordChallenges(application, accountPassword)
|
||||||
const secret = await application.generateMfaSecret()
|
const secret = await application.mfa.generateMfaSecret()
|
||||||
const token = await application.getOtpToken(secret)
|
const token = await application.mfa.getOtpToken(secret)
|
||||||
|
|
||||||
sinon.spy(application.challenges, 'sendChallenge')
|
sinon.spy(application.challenges, 'sendChallenge')
|
||||||
await application.enableMfa(secret, token)
|
await application.mfa.enableMfa(secret, token)
|
||||||
await application.disableMfa()
|
await application.mfa.disableMfa()
|
||||||
|
|
||||||
const spyCall = application.challenges.sendChallenge.getCall(0)
|
const spyCall = application.challenges.sendChallenge.getCall(0)
|
||||||
const challenge = spyCall.firstArg
|
const challenge = spyCall.firstArg
|
||||||
|
|||||||
@@ -71,12 +71,12 @@ describe('account recovery', function () {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should disable MFA after recovery sign in', async () => {
|
it('should disable MFA after recovery sign in', async () => {
|
||||||
const secret = await application.generateMfaSecret()
|
const secret = await application.mfa.generateMfaSecret()
|
||||||
const token = await application.getOtpToken(secret)
|
const token = await application.mfa.getOtpToken(secret)
|
||||||
|
|
||||||
await application.enableMfa(secret, token)
|
await application.mfa.enableMfa(secret, token)
|
||||||
|
|
||||||
expect(await application.isMfaActivated()).to.equal(true)
|
expect(await application.mfa.isMfaActivated()).to.equal(true)
|
||||||
|
|
||||||
const generatedRecoveryCodes = await application.getRecoveryCodes.execute()
|
const generatedRecoveryCodes = await application.getRecoveryCodes.execute()
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ describe('account recovery', function () {
|
|||||||
password: context.password,
|
password: context.password,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(await application.isMfaActivated()).to.equal(false)
|
expect(await application.mfa.isMfaActivated()).to.equal(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not allow to sign in with recovery code and invalid credentials', async () => {
|
it('should not allow to sign in with recovery code and invalid credentials', async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user