diff --git a/angular/src/components/password-generator.component.ts b/angular/src/components/password-generator.component.ts index 06e24422..1ad6fd63 100644 --- a/angular/src/components/password-generator.component.ts +++ b/angular/src/components/password-generator.component.ts @@ -29,6 +29,7 @@ export class PasswordGeneratorComponent implements OnInit { avoidAmbiguous = false; showWebsiteOption = false; enforcedPasswordPolicyOptions: PasswordGeneratorPolicyOptions; + usernameWebsite: string = null; constructor( protected passwordGenerationService: PasswordGenerationService, @@ -95,6 +96,9 @@ export class PasswordGeneratorComponent implements OnInit { if (!this.showWebsiteOption) { this.usernameOptions.subaddressType = this.usernameOptions.catchallType = "random"; } + if (this.usernameWebsite != null) { + this.usernameOptions.website = this.usernameWebsite; + } if (qParams.type === "username" || qParams.type === "password") { this.type = qParams.type; diff --git a/angular/src/jslib.module.ts b/angular/src/jslib.module.ts index 215e83e4..d00842d4 100644 --- a/angular/src/jslib.module.ts +++ b/angular/src/jslib.module.ts @@ -1,5 +1,6 @@ -import { CommonModule } from "@angular/common"; +import { CommonModule, DatePipe } from "@angular/common"; import { NgModule } from "@angular/core"; +import { FormsModule, ReactiveFormsModule } from "@angular/forms"; import { AvatarComponent } from "./components/avatar.component"; import { CalloutComponent } from "./components/callout.component"; @@ -35,6 +36,8 @@ import { UserNamePipe } from "./pipes/user-name.pipe"; closeButton: true, }), CommonModule, + FormsModule, + ReactiveFormsModule, ], declarations: [ A11yInvalidDirective, @@ -89,6 +92,6 @@ import { UserNamePipe } from "./pipes/user-name.pipe"; VerifyMasterPasswordComponent, ExportScopeCalloutComponent, ], - providers: [UserNamePipe, SearchPipe], + providers: [UserNamePipe, SearchPipe, I18nPipe, DatePipe], }) export class JslibModule {} diff --git a/angular/src/services/jslib-services.module.ts b/angular/src/services/jslib-services.module.ts index 068b0ee3..d35deeb1 100644 --- a/angular/src/services/jslib-services.module.ts +++ b/angular/src/services/jslib-services.module.ts @@ -36,6 +36,7 @@ import { TokenService as TokenServiceAbstraction } from "jslib-common/abstractio import { TotpService as TotpServiceAbstraction } from "jslib-common/abstractions/totp.service"; import { TwoFactorService as TwoFactorServiceAbstraction } from "jslib-common/abstractions/twoFactor.service"; import { UserVerificationService as UserVerificationServiceAbstraction } from "jslib-common/abstractions/userVerification.service"; +import { UsernameGenerationService as UsernameGenerationServiceAbstraction } from "jslib-common/abstractions/usernameGeneration.service"; import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "jslib-common/abstractions/vaultTimeout.service"; import { StateFactory } from "jslib-common/factories/stateFactory"; import { Account } from "jslib-common/models/domain/account"; @@ -69,6 +70,7 @@ import { TokenService } from "jslib-common/services/token.service"; import { TotpService } from "jslib-common/services/totp.service"; import { TwoFactorService } from "jslib-common/services/twoFactor.service"; import { UserVerificationService } from "jslib-common/services/userVerification.service"; +import { UsernameGenerationService } from "jslib-common/services/usernameGeneration.service"; import { VaultTimeoutService } from "jslib-common/services/vaultTimeout.service"; import { WebCryptoFunctionService } from "jslib-common/services/webCryptoFunction.service"; @@ -198,6 +200,11 @@ import { ValidationService } from "./validation.service"; useClass: PasswordGenerationService, deps: [CryptoServiceAbstraction, PolicyServiceAbstraction, StateServiceAbstraction], }, + { + provide: UsernameGenerationServiceAbstraction, + useClass: UsernameGenerationService, + deps: [CryptoServiceAbstraction, StateServiceAbstraction], + }, { provide: ApiServiceAbstraction, useFactory: ( diff --git a/common/src/importers/safariCsvImporter.ts b/common/src/importers/safariCsvImporter.ts index 156c2767..786b2827 100644 --- a/common/src/importers/safariCsvImporter.ts +++ b/common/src/importers/safariCsvImporter.ts @@ -17,8 +17,9 @@ export class SafariCsvImporter extends BaseImporter implements Importer { cipher.name = this.getValueOrDefault(value.Title, "--"); cipher.login.username = this.getValueOrDefault(value.Username); cipher.login.password = this.getValueOrDefault(value.Password); - cipher.login.uris = this.makeUriArray(value.Url); + cipher.login.uris = this.makeUriArray(value.Url ?? value.URL); cipher.login.totp = this.getValueOrDefault(value.OTPAuth); + cipher.notes = this.getValueOrDefault(value.Notes); this.cleanupCipher(cipher); result.ciphers.push(cipher); }); diff --git a/electron/src/updater.main.ts b/electron/src/updater.main.ts index c6105494..881208f8 100644 --- a/electron/src/updater.main.ts +++ b/electron/src/updater.main.ts @@ -109,7 +109,7 @@ export class UpdaterMain { if (result.response === 0) { // Quit and install have a different window logic, setting `isQuitting` just to be safe. this.windowMain.isQuitting = true; - autoUpdater.quitAndInstall(false, true); + autoUpdater.quitAndInstall(true, true); } }); diff --git a/spec/common/importers/safariCsvImporter.spec.ts b/spec/common/importers/safariCsvImporter.spec.ts new file mode 100644 index 00000000..f1e1186f --- /dev/null +++ b/spec/common/importers/safariCsvImporter.spec.ts @@ -0,0 +1,74 @@ +import { SafariCsvImporter as Importer } from "jslib-common/importers/safariCsvImporter"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { LoginUriView } from "jslib-common/models/view/loginUriView"; +import { LoginView } from "jslib-common/models/view/loginView"; + +import { data as oldSimplePasswordData } from "./testData/safariCsv/oldSimplePasswordData.csv"; +import { data as simplePasswordData } from "./testData/safariCsv/simplePasswordData.csv"; + +const CipherData = [ + { + title: "should parse URLs in new CSV format", + csv: simplePasswordData, + expected: Object.assign(new CipherView(), { + id: null, + organizationId: null, + folderId: null, + name: "example.com (example_user)", + login: Object.assign(new LoginView(), { + username: "example_user", + password: "example_p@ssword", + uris: [ + Object.assign(new LoginUriView(), { + uri: "https://example.com", + }), + ], + totp: "otpauth://totp/test?secret=examplesecret", + }), + notes: "Example note\nMore notes on new line", + type: 1, + }), + }, + { + title: "should parse URLs in old CSV format", + csv: oldSimplePasswordData, + expected: Object.assign(new CipherView(), { + id: null, + organizationId: null, + folderId: null, + name: "example.com (example_user)", + login: Object.assign(new LoginView(), { + username: "example_user", + password: "example_p@ssword", + uris: [ + Object.assign(new LoginUriView(), { + uri: "https://example.com", + }), + ], + }), + type: 1, + }), + }, +]; + +describe("Safari CSV Importer", () => { + CipherData.forEach((data) => { + it(data.title, async () => { + const importer = new Importer(); + const result = await importer.parse(data.csv); + expect(result != null).toBe(true); + expect(result.ciphers.length).toBeGreaterThan(0); + + const cipher = result.ciphers.shift(); + let property: keyof typeof data.expected; + for (property in data.expected) { + // eslint-disable-next-line + if (data.expected.hasOwnProperty(property)) { + // eslint-disable-next-line + expect(cipher.hasOwnProperty(property)).toBe(true); + expect(cipher[property]).toEqual(data.expected[property]); + } + } + }); + }); +}); diff --git a/spec/common/importers/testData/safariCsv/oldSimplePasswordData.csv.ts b/spec/common/importers/testData/safariCsv/oldSimplePasswordData.csv.ts new file mode 100644 index 00000000..f4dce0e7 --- /dev/null +++ b/spec/common/importers/testData/safariCsv/oldSimplePasswordData.csv.ts @@ -0,0 +1,2 @@ +export const data = `Title,Url,Username,Password +example.com (example_user),https://example.com,example_user,example_p@ssword`; diff --git a/spec/common/importers/testData/safariCsv/simplePasswordData.csv.ts b/spec/common/importers/testData/safariCsv/simplePasswordData.csv.ts new file mode 100644 index 00000000..52c7de8e --- /dev/null +++ b/spec/common/importers/testData/safariCsv/simplePasswordData.csv.ts @@ -0,0 +1,3 @@ +export const data = `Title,URL,Username,Password,Notes,OTPAuth +example.com (example_user),https://example.com,example_user,example_p@ssword,"Example note +More notes on new line",otpauth://totp/test?secret=examplesecret`;