From 6a8d2c305e9a548c9d6cdcc04569ca3f32ab8370 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Fri, 27 Jul 2018 17:48:18 -0400 Subject: [PATCH] support for password revision date on logins --- src/models/api/loginApi.ts | 2 ++ src/models/data/loginData.ts | 3 ++- src/models/domain/login.ts | 4 +++- src/models/request/cipherRequest.ts | 1 + src/models/view/loginView.ts | 9 ++++++--- src/services/cipher.service.ts | 18 +++++++++++------- 6 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/models/api/loginApi.ts b/src/models/api/loginApi.ts index ba9a9da11d8..7f5fac7b6ba 100644 --- a/src/models/api/loginApi.ts +++ b/src/models/api/loginApi.ts @@ -4,11 +4,13 @@ export class LoginApi { uris: LoginUriApi[]; username: string; password: string; + passwordRevisionDate?: Date; totp: string; constructor(data: any) { this.username = data.Username; this.password = data.Password; + this.passwordRevisionDate = data.PasswordRevisionDate; this.totp = data.Totp; if (data.Uris) { diff --git a/src/models/data/loginData.ts b/src/models/data/loginData.ts index a7d504e0525..31a4d6bcce6 100644 --- a/src/models/data/loginData.ts +++ b/src/models/data/loginData.ts @@ -1,5 +1,4 @@ import { LoginApi } from '../api/loginApi'; -import { LoginUriApi } from '../api/loginUriApi'; import { LoginUriData } from './loginUriData'; @@ -7,6 +6,7 @@ export class LoginData { uris: LoginUriData[]; username: string; password: string; + passwordRevisionDate?: Date; totp: string; constructor(data?: LoginApi) { @@ -16,6 +16,7 @@ export class LoginData { this.username = data.username; this.password = data.password; + this.passwordRevisionDate = data.passwordRevisionDate; this.totp = data.totp; if (data.uris) { diff --git a/src/models/domain/login.ts b/src/models/domain/login.ts index 3d81b0eb09c..23fc207335c 100644 --- a/src/models/domain/login.ts +++ b/src/models/domain/login.ts @@ -2,7 +2,6 @@ import { LoginUri } from './loginUri'; import { LoginData } from '../data/loginData'; -import { LoginUriView } from '../view/loginUriView'; import { LoginView } from '../view/loginView'; import { CipherString } from './cipherString'; @@ -12,6 +11,7 @@ export class Login extends Domain { uris: LoginUri[]; username: CipherString; password: CipherString; + passwordRevisionDate?: Date; totp: CipherString; constructor(obj?: LoginData, alreadyEncrypted: boolean = false) { @@ -20,6 +20,7 @@ export class Login extends Domain { return; } + this.passwordRevisionDate = obj.passwordRevisionDate; this.buildDomainModel(this, obj, { username: null, password: null, @@ -54,6 +55,7 @@ export class Login extends Domain { toLoginData(): LoginData { const l = new LoginData(); + l.passwordRevisionDate = this.passwordRevisionDate; this.buildDataModel(this, l, { username: null, password: null, diff --git a/src/models/request/cipherRequest.ts b/src/models/request/cipherRequest.ts index 01a4a9add90..fa2caa326d3 100644 --- a/src/models/request/cipherRequest.ts +++ b/src/models/request/cipherRequest.ts @@ -39,6 +39,7 @@ export class CipherRequest { uris: null, username: cipher.login.username ? cipher.login.username.encryptedString : null, password: cipher.login.password ? cipher.login.password.encryptedString : null, + passwordRevisionDate: cipher.login.passwordRevisionDate, totp: cipher.login.totp ? cipher.login.totp.encryptedString : null, }; diff --git a/src/models/view/loginView.ts b/src/models/view/loginView.ts index c36540fec6d..e0c7b06bf07 100644 --- a/src/models/view/loginView.ts +++ b/src/models/view/loginView.ts @@ -3,16 +3,19 @@ import { View } from './view'; import { Login } from '../domain/login'; -import { PlatformUtilsService } from '../../abstractions/platformUtils.service'; - export class LoginView implements View { username: string; password: string; + passwordRevisionDate?: Date; totp: string; uris: LoginUriView[]; constructor(l?: Login) { - // ctor + if (!l) { + return; + } + + this.passwordRevisionDate = l.passwordRevisionDate; } get uri(): string { diff --git a/src/services/cipher.service.ts b/src/services/cipher.service.ts index fdb1f5ceb5f..063cebf2c97 100644 --- a/src/services/cipher.service.ts +++ b/src/services/cipher.service.ts @@ -69,12 +69,15 @@ export class CipherService implements CipherServiceAbstraction { const existingCipher = await (await this.get(model.id)).decrypt(); if (existingCipher != null) { model.passwordHistory = existingCipher.passwordHistory || []; - if (model.type === CipherType.Login && existingCipher.type === CipherType.Login && - existingCipher.login.password !== model.login.password) { - const ph = new PasswordHistoryView(null); - ph.password = existingCipher.login.password; - ph.lastUsedDate = new Date(); - model.passwordHistory.splice(0, 0, ph); + if (model.type === CipherType.Login && existingCipher.type === CipherType.Login) { + if (existingCipher.login.password !== model.login.password) { + const ph = new PasswordHistoryView(); + ph.password = existingCipher.login.password; + ph.lastUsedDate = model.login.passwordRevisionDate = new Date(); + model.passwordHistory.splice(0, 0, ph); + } else { + model.login.passwordRevisionDate = existingCipher.login.passwordRevisionDate; + } } if (existingCipher.hasFields) { const existingHiddenFields = existingCipher.fields.filter((f) => f.type === FieldType.Hidden); @@ -83,7 +86,7 @@ export class CipherService implements CipherServiceAbstraction { existingHiddenFields.forEach((ef) => { const matchedField = hiddenFields.filter((f) => f.name === ef.name); if (matchedField.length === 0 || matchedField[0].value !== ef.value) { - const ph = new PasswordHistoryView(null); + const ph = new PasswordHistoryView(); ph.password = ef.name + ': ' + ef.value; ph.lastUsedDate = new Date(); model.passwordHistory.splice(0, 0, ph); @@ -767,6 +770,7 @@ export class CipherService implements CipherServiceAbstraction { switch (cipher.type) { case CipherType.Login: cipher.login = new Login(); + cipher.login.passwordRevisionDate = model.login.passwordRevisionDate; await this.encryptObjProperty(model.login, cipher.login, { username: null, password: null,