add/edit/view fixes for ciphers

This commit is contained in:
Kyle Spearrin 2017-10-16 10:09:17 -04:00
parent af973cbce3
commit 176b9a8ed0
7 changed files with 347 additions and 143 deletions

View File

@ -46,7 +46,7 @@
$scope.savePromise = null;
$scope.save = function () {
if (!cipher.name || cipher.name === '') {
if (!$scope.cipher.name || $scope.cipher.name === '') {
toastr.error(i18nService.nameRequired, i18nService.errorsOccurred);
return;
}

View File

@ -7,6 +7,7 @@ angular
$scope.constants = constantsService;
$scope.showAttachments = !utilsService.isEdge();
$scope.addFieldType = constantsService.fieldType.text.toString();
$scope.selectedType = constantsService.cipherType.login.toString();
var cipherId = $stateParams.cipherId;
var fromView = $stateParams.fromView;
var from = $stateParams.from;
@ -34,14 +35,18 @@ angular
utilsService.initListSectionItemListeners($(document), angular);
$scope.typeChanged = function () {
$scope.cipher.type = parseInt($scope.selectedType);
};
$scope.savePromise = null;
$scope.save = function (model) {
if (!model.name) {
$scope.save = function () {
if (!$scope.cipher.name || $scope.cipher.name === '') {
toastr.error(i18nService.nameRequired, i18nService.errorsOccurred);
return;
}
$scope.savePromise = loginService.encrypt(model).then(function (cipherModel) {
$scope.savePromise = loginService.encrypt($scope.cipher).then(function (cipherModel) {
var cipher = new Cipher(cipherModel, true);
return loginService.saveWithServer(cipher).then(function (c) {
$analytics.eventTrack('Edited Cipher');

View File

@ -12,34 +12,38 @@ angular
$scope.isPremium = tokenService.getPremium();
$scope.cipher = null;
var cipherObj = null;
loginService.get($stateParams.cipherId).then(function (cipher) {
if (!cipher) {
return;
}
cipherObj = cipher;
return cipher.decrypt();
}).then(function (model) {
$scope.cipher = model;
if (model.password) {
$scope.cipher.maskedPassword = $scope.maskValue(model.password);
}
if (model.type == constantsService.cipherType.login && model.login) {
if (model.login.password) {
$scope.cipher.maskedPassword = $scope.maskValue(model.login.password);
}
if (model.uri) {
$scope.cipher.showLaunch = model.uri.startsWith('http://') || model.uri.startsWith('https://');
var domain = utilsService.getDomain(model.uri);
if (domain) {
$scope.cipher.website = domain;
if (model.login.uri) {
$scope.cipher.showLaunch = model.login.uri.startsWith('http://') || model.login.uri.startsWith('https://');
var domain = utilsService.getDomain(model.login.uri);
if (domain) {
$scope.cipher.login.website = domain;
}
else {
$scope.cipher.login.website = model.login.uri;
}
}
else {
$scope.cipher.website = model.uri;
$scope.cipher.showLaunch = false;
}
}
else {
$scope.cipher.showLaunch = false;
}
if (model.totp && (cipher.organizationUseTotp || tokenService.getPremium())) {
if (model.login.totp && (cipherObj.organizationUseTotp || tokenService.getPremium())) {
totpUpdateCode();
totpTick();
@ -87,7 +91,7 @@ angular
$scope.launchWebsite = function (cipher) {
if (cipher.showLaunch) {
$analytics.eventTrack('Launched Website');
chrome.tabs.create({ url: cipher.uri });
chrome.tabs.create({ url: cipher.login.uri });
}
};
@ -192,11 +196,11 @@ angular
});
function totpUpdateCode() {
if (!$scope.cipher.totp) {
if ($scope.cipher.type !== constantsService.cipherType.login || !$scope.cipher.login.totp) {
return;
}
totpService.getCode($scope.cipher.totp).then(function (code) {
totpService.getCode($scope.cipher.login.totp).then(function (code) {
$timeout(function () {
if (code) {
$scope.totpCodeFormatted = code.substring(0, 3) + ' ' + code.substring(3);

View File

@ -188,7 +188,7 @@
</div>
</div>
<div ng-if="cipher.type === constants.cipherType.secureNote">
<!-- Nothing for now -->
</div>
</div>
</div>

View File

@ -1,4 +1,4 @@
<form name="theForm" ng-submit="save(cipher)" bit-form="savePromise" autocomplete="off">
<form name="theForm" ng-submit="save()" bit-form="savePromise" autocomplete="off">
<div class="header">
<div class="left">
<a ng-click="close()" href="">{{i18n.cancel}}</a>
@ -21,29 +21,177 @@
<label for="name" class="item-label">{{i18n.name}}</label>
<input id="name" type="text" name="Name" ng-model="cipher.name">
</div>
<div class="list-section-item">
<label for="uri" class="item-label">{{i18n.uri}}</label>
<input id="uri" type="text" name="Uri" ng-model="cipher.uri">
<div ng-if="cipher.type === constants.cipherType.login">
<div class="list-section-item">
<label for="loginUri" class="item-label">{{i18n.uri}}</label>
<input id="loginUri" type="text" name="Login.Uri" ng-model="cipher.login.uri">
</div>
<div class="list-section-item">
<label for="loginUsername" class="item-label">{{i18n.username}}</label>
<input id="loginUsername" type="text" name="Login.Username" ng-model="cipher.login.username">
</div>
<div class="list-section-item">
<label for="loginPassword" class="item-label">{{i18n.password}}</label>
<input id="loginPassword" type="password" name="Login.Password" ng-model="cipher.login.password">
</div>
<a class="list-section-item" href="" ng-click="generatePassword()">
{{i18n.generatePassword}}
<i class="fa fa-chevron-right"></i>
</a>
</div>
<div class="list-section-item">
<label for="username" class="item-label">{{i18n.username}}</label>
<input id="username" type="text" name="Username" ng-model="cipher.username">
<div ng-if="cipher.type === constants.cipherType.card">
<div class="list-section-item">
<label for="cardCardholderName" class="item-label">{{i18n.cardholderName}}</label>
<input id="cardCardholderName" type="text" name="Card.CardholderName"
ng-model="cipher.card.cardholderName">
</div>
<div class="list-section-item">
<label for="cardNumber" class="item-label">{{i18n.number}}</label>
<input id="cardNumber" type="text" name="Card.Number" ng-model="cipher.card.number">
</div>
<div class="list-section-item">
<label for="cardBrand" class="item-label">{{i18n.brand}}</label>
<select id="cardBrand" name="Card.Brand" ng-model="cipher.card.brand">
<option value="">-- {{i18n.select}} --</option>
<option value="Visa">Visa</option>
<option value="Mastercard">Mastercard</option>
<option value="Amex">American Express</option>
<option value="Discover">Discover</option>
<option value="Diners Club">Diners Club</option>
<option value="JCB">JCB</option>
<option value="Maestro">Maestro</option>
<option value="UnionPay">UnionPay</option>
<option value="Other">{{i18n.other}}</option>
</select>
</div>
<div class="list-section-item">
<label for="cardExpMonth" class="item-label">{{i18n.expirationMonth}}</label>
<select id="cardExpMonth" name="Card.ExpMonth" ng-model="cipher.card.expMonth">
<option value="">-- {{i18n.select}} --</option>
<option value="1">01 - {{i18n.january}}</option>
<option value="2">02 - {{i18n.february}}</option>
<option value="3">03 - {{i18n.march}}</option>
<option value="4">04 - {{i18n.april}}</option>
<option value="5">05 - {{i18n.may}}</option>
<option value="6">06 - {{i18n.june}}</option>
<option value="7">07 - {{i18n.july}}</option>
<option value="8">08 - {{i18n.august}}</option>
<option value="9">09 - {{i18n.september}}</option>
<option value="10">10 - {{i18n.october}}</option>
<option value="11">11 - {{i18n.november}}</option>
<option value="12">12 - {{i18n.december}}</option>
</select>
</div>
<div class="list-section-item">
<label for="cardExpYear" class="item-label">{{i18n.expirationYear}}</label>
<input id="cardExpYear" type="text" name="Card.ExpYear" ng-model="cipher.card.expYear"
placeholder="{{i18n.ex}} 2019">
</div>
<div class="list-section-item">
<label for="cardCode" class="item-label">{{i18n.securityCode}}</label>
<input id="cardCode" type="text" name="Card.Code" ng-model="cipher.card.code">
</div>
</div>
<div class="list-section-item">
<label for="password" class="item-label">{{i18n.password}}</label>
<input id="password" type="password" name="Password" ng-model="cipher.password">
<div ng-if="cipher.type === constants.cipherType.identity">
<div class="list-section-item">
<label for="identityTitle" class="item-label">{{i18n.title}}</label>
<select id="identityTitle" name="Identity.Title" ng-model="cipher.identity.title">
<option value="">-- {{i18n.select}} --</option>
<option value="{{i18n.mr}}">{{i18n.mr}}</option>
<option value="{{i18n.mrs}}">{{i18n.mrs}}</option>
<option value="{{i18n.ms}}">{{i18n.ms}}</option>
<option value="{{i18n.dr}}">{{i18n.dr}}</option>
</select>
</div>
<div class="list-section-item">
<label for="identityFirstName" class="item-label">{{i18n.firstName}}</label>
<input id="identityFirstName" type="text" name="Identity.FirstName"
ng-model="cipher.identity.firstName">
</div>
<div class="list-section-item">
<label for="identityMiddleName" class="item-label">{{i18n.middleName}}</label>
<input id="identityMiddleName" type="text" name="Identity.MiddleName"
ng-model="cipher.identity.middleName">
</div>
<div class="list-section-item">
<label for="identityLastName" class="item-label">{{i18n.lastName}}</label>
<input id="identityLastName" type="text" name="Identity.LastName"
ng-model="cipher.identity.lastName">
</div>
<div class="list-section-item">
<label for="identityUsername" class="item-label">{{i18n.username}}</label>
<input id="identityUsername" type="text" name="Identity.Username"
ng-model="cipher.identity.username">
</div>
<div class="list-section-item">
<label for="identityCompany" class="item-label">{{i18n.company}}</label>
<input id="identityCompany" type="text" name="Identity.Company" ng-model="cipher.identity.company">
</div>
<div class="list-section-item">
<label for="identitySsn" class="item-label">{{i18n.ssn}}</label>
<input id="identitySsn" type="text" name="Identity.SSN" ng-model="cipher.identity.ssn">
</div>
<div class="list-section-item">
<label for="identityPassportNumber" class="item-label">{{i18n.passportNumber}}</label>
<input id="identityPassportNumber" type="text" name="Identity.PassportNumber"
ng-model="cipher.identity.passportNumber">
</div>
<div class="list-section-item">
<label for="identityLicenseNumber" class="item-label">{{i18n.licenseNumber}}</label>
<input id="identityLicenseNumber" type="text" name="Identity.LicenseNumber"
ng-model="cipher.identity.licenseNumber">
</div>
<div class="list-section-item">
<label for="identityEmail" class="item-label">{{i18n.email}}</label>
<input id="identityEmail" type="text" name="Identity.Email" ng-model="cipher.identity.email">
</div>
<div class="list-section-item">
<label for="identityPhone" class="item-label">{{i18n.phone}}</label>
<input id="identityPhone" type="text" name="Identity.Phone" ng-model="cipher.identity.phone">
</div>
<div class="list-section-item">
<label for="identityAddress1" class="item-label">{{i18n.address1}}</label>
<input id="identityAddress1" type="text" name="Identity.Address1" ng-model="cipher.identity.address1">
</div>
<div class="list-section-item">
<label for="identityAddress2" class="item-label">{{i18n.address2}}</label>
<input id="identityAddress2" type="text" name="Identity.Address2" ng-model="cipher.identity.address2">
</div>
<div class="list-section-item">
<label for="identityAddress3" class="item-label">{{i18n.address3}}</label>
<input id="identityAddress3" type="text" name="Identity.Address3" ng-model="cipher.identity.address3">
</div>
<div class="list-section-item">
<label for="identityCity" class="item-label">{{i18n.cityTown}}</label>
<input id="identityCity" type="text" name="Identity.City" ng-model="cipher.identity.city">
</div>
<div class="list-section-item">
<label for="identityState" class="item-label">{{i18n.stateProvince}}</label>
<input id="identityState" type="text" name="Identity.State" ng-model="cipher.identity.state">
</div>
<div class="list-section-item">
<label for="identityPostalCode" class="item-label">{{i18n.zipPostalCode}}</label>
<input id="identityPostalCode" type="text" name="Identity.PostalCode"
ng-model="cipher.identity.postalCode">
</div>
<div class="list-section-item">
<label for="identityCountry" class="item-label">{{i18n.country}}</label>
<input id="identityCountry" type="text" name="Identity.Country" ng-model="cipher.identity.country">
</div>
</div>
<div ng-if="cipher.type === constants.cipherType.secureNote">
<!-- Nothing for now -->
</div>
<a class="list-section-item" href="" ng-click="generatePassword()">
{{i18n.generatePassword}}
<i class="fa fa-chevron-right"></i>
</a>
</div>
</div>
<div class="list-section">
<div class="list-section-items">
<div class="list-section-item">
<label for="totp" class="item-label">{{i18n.authenticatorKeyTotp}}</label>
<input id="totp" type="text" name="Totp" ng-model="cipher.totp">
<div ng-if="cipher.type === constants.cipherType.login">
<div class="list-section-item">
<label for="loginTotp" class="item-label">{{i18n.authenticatorKeyTotp}}</label>
<input id="loginTotp" type="text" name="Login.Totp" ng-model="cipher.login.totp">
</div>
</div>
<div class="list-section-item">
<label for="folder" class="item-label">{{i18n.folder}}</label>

View File

@ -19,52 +19,97 @@
<span class="item-label">{{i18n.name}}</span>
{{cipher.name}}
</div>
<div class="list-section-item" ng-if="cipher.uri" title="{{cipher.uri}}">
<a class="btn-list" href="" title="{{i18n.launchWebsite}}" ng-click="launchWebsite(cipher)"
ng-show="cipher.showLaunch">
<i class="fa fa-lg fa-share-square-o"></i>
</a>
<span class="item-label">{{i18n.website}}</span>
{{cipher.website}}
<div ng-if="cipher.type === constants.cipherType.login">
<div class="list-section-item" ng-if="cipher.login.uri" title="{{cipher.login.uri}}">
<a class="btn-list" href="" title="{{i18n.launchWebsite}}" ng-click="launchWebsite(cipher)"
ng-show="cipher.showLaunch">
<i class="fa fa-lg fa-share-square-o"></i>
</a>
<span class="item-label">{{i18n.website}}</span>
{{cipher.login.website}}
</div>
<div class="list-section-item" ng-if="cipher.login.username">
<a class="btn-list" href="" title="{{i18n.copyUsername}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.username)"
data-clipboard-text="{{cipher.login.username}}">
<i class="fa fa-lg fa-clipboard"></i>
</a>
<span class="item-label">{{i18n.username}}</span>
<span id="username">{{cipher.login.username}}</span>
</div>
<div class="list-section-item" ng-if="cipher.login.password">
<a class="btn-list" href="" title="{{i18n.copyPassword}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.password)"
data-clipboard-text="{{cipher.login.password}}">
<i class="fa fa-lg fa-clipboard"></i>
</a>
<a class="btn-list" href="" title="{{i18n.togglePassword}}" ng-click="togglePassword()">
<i class="fa fa-lg" ng-class="[{'fa-eye': !showPassword}, {'fa-eye-slash': showPassword}]"></i>
</a>
<span class="item-label">{{i18n.password}}</span>
<span ng-show="!showPassword" class="monospaced">{{cipher.maskedPassword}}</span>
<span id="password" ng-show="showPassword" class="monospaced">{{cipher.login.password}}</span>
</div>
<div class="list-section-item totp" ng-class="{'low': totpLow}" ng-if="cipher.login.totp && totpCode">
<a class="btn-list" href="" title="{{i18n.copyVerificationCode}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.verificationCodeTotp)" data-clipboard-text="{{totpCode}}">
<i class="fa fa-lg fa-clipboard"></i>
</a>
<span class="totp-countdown">
<span class="totp-sec">{{totpSec}}</span>
<svg>
<g>
<circle class="totp-circle inner" r="12.6" cy="16" cx="16"
style="stroke-dashoffset: {{totpDash}}px;"></circle>
<circle class="totp-circle outer" r="14" cy="16" cx="16"></circle>
</g>
</svg>
</span>
<span class="item-label">{{i18n.verificationCodeTotp}}</span>
<span id="totp" class="totp-code">{{totpCodeFormatted}}</span>
</div>
</div>
<div class="list-section-item" ng-if="cipher.username">
<a class="btn-list" href="" title="{{i18n.copyUsername}}" ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.username)" data-clipboard-text="{{cipher.username}}">
<i class="fa fa-lg fa-clipboard"></i>
</a>
<span class="item-label">{{i18n.username}}</span>
<span id="username">{{cipher.username}}</span>
<div ng-if="cipher.type === constants.cipherType.card">
<div class="list-section-item" ng-if="cipher.card.cardholderName">
<a class="btn-list" href="" title="{{i18n.copy}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.cardholderName)"
data-clipboard-text="{{cipher.card.cardholderName}}">
<i class="fa fa-lg fa-clipboard"></i>
</a>
<span class="item-label">{{i18n.cardholderName}}</span>
<span id="username">{{cipher.card.cardholderName}}</span>
</div>
<div class="list-section-item" ng-if="cipher.card.number">
<a class="btn-list" href="" title="{{i18n.copy}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.number)"
data-clipboard-text="{{cipher.card.number}}">
<i class="fa fa-lg fa-clipboard"></i>
</a>
<span class="item-label">{{i18n.number}}</span>
<span id="username">{{cipher.card.number}}</span>
</div>
</div>
<div class="list-section-item" ng-if="cipher.password">
<a class="btn-list" href="" title="{{i18n.copyPassword}}" ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.password)" data-clipboard-text="{{cipher.password}}">
<i class="fa fa-lg fa-clipboard"></i>
</a>
<a class="btn-list" href="" title="{{i18n.togglePassword}}" ng-click="togglePassword()">
<i class="fa fa-lg" ng-class="[{'fa-eye': !showPassword}, {'fa-eye-slash': showPassword}]"></i>
</a>
<span class="item-label">{{i18n.password}}</span>
<span ng-show="!showPassword" class="monospaced">{{cipher.maskedPassword}}</span>
<span id="password" ng-show="showPassword" class="monospaced">{{cipher.password}}</span>
<div ng-if="cipher.type === constants.cipherType.identity">
<div class="list-section-item" ng-if="cipher.identity.firstName">
<span class="item-label">{{i18n.firstName}}</span>
{{cipher.identity.firstName}}
</div>
<div class="list-section-item" ng-if="cipher.identity.middleName">
<span class="item-label">{{i18n.middleName}}</span>
{{cipher.identity.middleName}}
</div>
<div class="list-section-item" ng-if="cipher.identity.lastName">
<span class="item-label">{{i18n.lastName}}</span>
{{cipher.identity.lastName}}
</div>
</div>
<div class="list-section-item totp" ng-class="{'low': totpLow}" ng-if="cipher.totp && totpCode">
<a class="btn-list" href="" title="{{i18n.copyVerificationCode}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.verificationCodeTotp)" data-clipboard-text="{{totpCode}}">
<i class="fa fa-lg fa-clipboard"></i>
</a>
<span class="totp-countdown">
<span class="totp-sec">{{totpSec}}</span>
<svg>
<g>
<circle class="totp-circle inner" r="12.6" cy="16" cx="16"
style="stroke-dashoffset: {{totpDash}}px;"></circle>
<circle class="totp-circle outer" r="14" cy="16" cx="16"></circle>
</g>
</svg>
</span>
<span class="item-label">{{i18n.verificationCodeTotp}}</span>
<span id="totp" class="totp-code">{{totpCodeFormatted}}</span>
<div ng-if="cipher.type === constants.cipherType.secureNote">
<!-- Nothing for now -->
</div>
</div>
</div>

View File

@ -28,62 +28,13 @@ function initLoginService() {
type: login.type
};
function encryptCipherData(cipher, model, key, self) {
switch (cipher.type) {
case constantsService.cipherType.login:
return encryptObjProperty(cipher.login, model.login, {
uri: null,
username: null,
password: null,
totp: null
}, key, self);
case constantsService.cipherType.secureNote:
model.secureNote = {
type: cipher.secureNote.type
};
return Q();
case constantsService.cipherType.card:
return encryptObjProperty(cipher.card, model.card, {
cardholderName: null,
brand: null,
number: null,
expMonth: null,
expYear: null,
code: null
}, key, self);
case constantsService.cipherType.identity:
return encryptObjProperty(cipher.identity, model.identity, {
title: null,
firstName: null,
middleName: null,
lastName: null,
address1: null,
address2: null,
address3: null,
city: null,
state: null,
postalCode: null,
country: null,
company: null,
email: null,
phone: null,
ssn: null,
username: null,
passportNumber: null,
licenseNumber: null
}, key, self);
default:
throw 'Unknown type.';
}
}
return self.cryptoService.getOrgKey(login.organizationId).then(function (key) {
return Q.all([
encryptObjProperty(login, model, {
name: null,
notes: null
}, key, self),
encryptCipherData(login, model, key),
encryptCipherData(login, model, key, self),
self.encryptFields(login.fields, key).then(function (fields) {
model.fields = fields;
})
@ -93,10 +44,62 @@ function initLoginService() {
});
};
function encryptCipherData(cipher, model, key, self) {
switch (cipher.type) {
case self.constantsService.cipherType.login:
model.login = {};
return encryptObjProperty(cipher.login, model.login, {
uri: null,
username: null,
password: null,
totp: null
}, key, self);
case self.constantsService.cipherType.secureNote:
model.secureNote = {
type: cipher.secureNote.type
};
return Q();
case self.constantsService.cipherType.card:
model.card = {};
return encryptObjProperty(cipher.card, model.card, {
cardholderName: null,
brand: null,
number: null,
expMonth: null,
expYear: null,
code: null
}, key, self);
case self.constantsService.cipherType.identity:
model.identity = {};
return encryptObjProperty(cipher.identity, model.identity, {
title: null,
firstName: null,
middleName: null,
lastName: null,
address1: null,
address2: null,
address3: null,
city: null,
state: null,
postalCode: null,
country: null,
company: null,
email: null,
phone: null,
ssn: null,
username: null,
passportNumber: null,
licenseNumber: null
}, key, self);
default:
throw 'Unknown type.';
}
}
LoginService.prototype.encryptFields = function (fields, key) {
var self = this;
if (!fields || !fields.length) {
return null;
return Q(null);
}
var encFields = [];
@ -132,20 +135,19 @@ function initLoginService() {
for (var prop in map) {
if (map.hasOwnProperty(prop)) {
/* jshint ignore:start */
(function (theProp) {
(function (theProp, theModel) {
var promise = Q().then(function () {
var objProb = obj[(map[theProp] || theProp)];
if (objProb && objProb !== '') {
return self.cryptoService.encrypt(objProb, key);
var objProp = obj[(map[theProp] || theProp)];
if (objProp && objProp !== '') {
return self.cryptoService.encrypt(objProp, key);
}
return null;
}).then(function (val) {
model[theProp] = val;
return;
theModel[theProp] = val;
});
promises.push(promise);
})(prop);
})(prop, model);
/* jshint ignore:end */
}
}
@ -169,7 +171,7 @@ function initLoginService() {
return self.utilsService.getObjFromStorage(key);
}).then(function (ciphers) {
if (ciphers && id in ciphers) {
return new Login(ciphers[id], false, localData[id]);
return new Cipher(ciphers[id], false, localData[id]);
}
return null;
@ -329,7 +331,7 @@ function initLoginService() {
function apiSuccess(response) {
cipher.id = response.id;
self.userService.getUserIdPromise().then(function (userId) {
var data = new LoginData(response, userId);
var data = new CipherData(response, userId);
return self.upsert(data);
}).then(function () {
deferred.resolve(cipher);
@ -514,11 +516,11 @@ function initLoginService() {
return;
}
data = new LoginData(response, userId);
data = new CipherData(response, userId);
return self.upsert(data);
}).then(function () {
if (data) {
deferred.resolve(new Login(data));
deferred.resolve(new CipherData(data));
}
});
};