1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-20 10:13:31 +00:00

Merge branch 'main' into vault/pm-5273

# Conflicts:
#	libs/common/src/state-migrations/migrate.ts
This commit is contained in:
Carlos Gonçalves
2024-03-12 12:02:49 +00:00
183 changed files with 3499 additions and 2091 deletions

View File

@@ -264,7 +264,7 @@ export class SettingsComponent implements OnInit {
enableDuckDuckGoBrowserIntegration:
await this.stateService.getEnableDuckDuckGoBrowserIntegration(),
theme: await this.stateService.getTheme(),
locale: (await this.stateService.getLocale()) ?? null,
locale: await firstValueFrom(this.i18nService.locale$),
};
this.form.setValue(initialValues, { emitEvent: false });
@@ -553,7 +553,7 @@ export class SettingsComponent implements OnInit {
}
async saveLocale() {
await this.stateService.setLocale(this.form.value.locale);
await this.i18nService.setLocale(this.form.value.locale);
}
async saveTheme() {

View File

@@ -52,8 +52,7 @@ export class InitService {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.syncService.fullSync(true);
await this.vaultTimeoutService.init(true);
const locale = await this.stateService.getLocale();
await (this.i18nService as I18nRendererService).init(locale);
await (this.i18nService as I18nRendererService).init();
(this.eventUploadService as EventUploadService).init(true);
this.twoFactorService.init();
setTimeout(() => this.notificationsService.init(), 3000);

View File

@@ -43,7 +43,7 @@ import { GlobalState } from "@bitwarden/common/platform/models/domain/global-sta
import { MemoryStorageService } from "@bitwarden/common/platform/services/memory-storage.service";
import { MigrationRunner } from "@bitwarden/common/platform/services/migration-runner";
import { SystemService } from "@bitwarden/common/platform/services/system.service";
import { StateProvider } from "@bitwarden/common/platform/state";
import { GlobalStateProvider, StateProvider } from "@bitwarden/common/platform/state";
// eslint-disable-next-line import/no-restricted-paths -- Implementation for memory storage
import { MemoryStorageService as MemoryStorageServiceForStateProviders } from "@bitwarden/common/platform/state/storage/memory-storage.service";
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
@@ -104,7 +104,7 @@ const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK");
{
provide: I18nServiceAbstraction,
useClass: I18nRendererService,
deps: [SYSTEM_LANGUAGE, LOCALES_DIRECTORY],
deps: [SYSTEM_LANGUAGE, LOCALES_DIRECTORY, GlobalStateProvider],
},
{
provide: MessagingServiceAbstraction,
@@ -126,6 +126,7 @@ const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK");
StateServiceAbstraction,
AutofillSettingsServiceAbstraction,
VaultTimeoutSettingsService,
BiometricStateService,
],
},
{

View File

@@ -28,7 +28,7 @@
<button type="submit" class="btn primary block" [disabled]="!accessibilityForm.valid">
{{ "submit" | i18n }}
</button>
<button type="button" routerLink="/login" class="btn block">{{ "done" | i18n }}</button>
<button type="button" (click)="close()" class="btn block">{{ "done" | i18n }}</button>
</div>
</div>
</form>

View File

@@ -2,14 +2,11 @@ import { Component, NgZone } from "@angular/core";
import { UntypedFormControl, UntypedFormGroup, Validators } from "@angular/forms";
import { Router } from "@angular/router";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
const BroadcasterSubscriptionId = "AccessibilityCookieComponent";
@Component({
selector: "app-accessibility-cookie",
templateUrl: "accessibility-cookie.component.html",
@@ -27,40 +24,21 @@ export class AccessibilityCookieComponent {
protected platformUtilsService: PlatformUtilsService,
protected environmentService: EnvironmentService,
protected i18nService: I18nService,
private broadcasterService: BroadcasterService,
protected ngZone: NgZone,
) {}
async ngOnInit() {
this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => {
this.ngZone.run(() => {
switch (message.command) {
case "windowIsFocused":
if (this.listenForCookie) {
this.listenForCookie = false;
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.checkForCookie();
}
break;
default:
}
});
});
}
registerhCaptcha() {
this.platformUtilsService.launchUri("https://www.hcaptcha.com/accessibility");
}
async checkForCookie() {
this.hCaptchaWindow.close();
async close() {
const [cookie] = await ipc.auth.getHcaptchaAccessibilityCookie();
if (cookie) {
this.onCookieSavedSuccess();
} else {
this.onCookieSavedFailure();
}
await this.router.navigate(["/login"]);
}
onCookieSavedSuccess() {
@@ -89,10 +67,6 @@ export class AccessibilityCookieComponent {
return;
}
this.listenForCookie = true;
this.hCaptchaWindow = window.open(this.accessibilityForm.value.link);
}
ngOnDestroy() {
this.broadcasterService.unsubscribe(BroadcasterSubscriptionId);
window.open(this.accessibilityForm.value.link, "_blank", "noopener noreferrer");
}
}

View File

@@ -404,7 +404,7 @@
"message": "길이"
},
"passwordMinLength": {
"message": "Minimum password length"
"message": "최소 비밀번호 길이"
},
"uppercase": {
"message": "대문자 (A-Z)"
@@ -561,10 +561,10 @@
"message": "계정 생성이 완료되었습니다! 이제 로그인하실 수 있습니다."
},
"youSuccessfullyLoggedIn": {
"message": "You successfully logged in"
"message": "로그인에 성공했습니다."
},
"youMayCloseThisWindow": {
"message": "You may close this window"
"message": "이제 창을 닫으실 수 있습니다."
},
"masterPassSent": {
"message": "마스터 비밀번호 힌트가 담긴 이메일을 보냈습니다."
@@ -780,7 +780,7 @@
"message": "문의하기"
},
"helpAndFeedback": {
"message": "Help and feedback"
"message": "도움말 및 피드백"
},
"getHelp": {
"message": "도움말"
@@ -1399,7 +1399,7 @@
"message": "잘못된 PIN 코드입니다."
},
"tooManyInvalidPinEntryAttemptsLoggingOut": {
"message": "Too many invalid PIN entry attempts. Logging out."
"message": "잘못된 PIN 입력 시도가 너무 많습니다. 로그아웃 합니다."
},
"unlockWithWindowsHello": {
"message": "Windows Hello를 사용하여 잠금 해제"
@@ -1889,7 +1889,7 @@
"message": "Verification required for this action. Set a PIN to continue."
},
"setPin": {
"message": "Set PIN"
"message": "PIN 설정"
},
"verifyWithBiometrics": {
"message": "Verify with biometrics"

View File

@@ -97,7 +97,6 @@ export class Main {
}
this.logService = new ElectronLogMainService(null, app.getPath("userData"));
this.i18nService = new I18nMainService("en", "./locales/");
const storageDefaults: any = {};
// Default vault timeout to "on restart", and action to "lock"
@@ -112,6 +111,8 @@ export class Main {
);
const globalStateProvider = new DefaultGlobalStateProvider(storageServiceProvider);
this.i18nService = new I18nMainService("en", "./locales/", globalStateProvider);
const accountService = new AccountServiceImplementation(
new NoopMessagingService(),
this.logService,
@@ -218,8 +219,7 @@ export class Main {
this.migrationRunner.run().then(
async () => {
await this.windowMain.init();
const locale = await this.stateService.getLocale();
await this.i18nService.init(locale != null ? locale : app.getLocale());
await this.i18nService.init();
this.messagingMain.init();
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises

View File

@@ -30,7 +30,7 @@ export class WindowMain {
private windowStateChangeTimer: NodeJS.Timeout;
private windowStates: { [key: string]: WindowState } = {};
private enableAlwaysOnTop = false;
private session: Electron.Session;
session: Electron.Session;
readonly defaultWidth = 950;
readonly defaultHeight = 600;

View File

@@ -1,12 +1,12 @@
{
"name": "@bitwarden/desktop",
"version": "2024.2.2",
"version": "2024.3.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@bitwarden/desktop",
"version": "2024.2.2",
"version": "2024.3.0",
"license": "GPL-3.0",
"dependencies": {
"@bitwarden/desktop-native": "file:../desktop_native"

View File

@@ -2,7 +2,7 @@
"name": "@bitwarden/desktop",
"productName": "Bitwarden",
"description": "A secure and free password manager for all of your devices.",
"version": "2024.2.2",
"version": "2024.3.0",
"author": "Bitwarden Inc. <hello@bitwarden.com> (https://bitwarden.com)",
"homepage": "https://bitwarden.com",
"license": "GPL-3.0",

View File

@@ -1,14 +1,22 @@
import * as fs from "fs";
import * as path from "path";
import { ipcMain } from "electron";
import { app, ipcMain } from "electron";
import { I18nService as BaseI18nService } from "@bitwarden/common/platform/services/i18n.service";
import { GlobalStateProvider } from "@bitwarden/common/platform/state";
export class I18nMainService extends BaseI18nService {
constructor(systemLanguage: string, localesDirectory: string) {
super(systemLanguage, localesDirectory, (formattedLocale: string) =>
this.readLanguageFile(formattedLocale),
constructor(
systemLanguage: string,
localesDirectory: string,
globalStateProvider: GlobalStateProvider,
) {
super(
systemLanguage,
localesDirectory,
(formattedLocale: string) => this.readLanguageFile(formattedLocale),
globalStateProvider,
);
ipcMain.handle("getLanguageFile", async (event, formattedLocale: string) =>
@@ -76,6 +84,12 @@ export class I18nMainService extends BaseI18nService {
];
}
override async init(): Promise<void> {
// Set system language to electron language
this.systemLanguage = app.getLocale();
await super.init();
}
private readLanguageFile(formattedLocale: string): Promise<any> {
// Check that the provided locale only contains letters and dashes and underscores to avoid possible path traversal
if (!/^[a-zA-Z_-]+$/.test(formattedLocale)) {

View File

@@ -1,10 +1,20 @@
import { I18nService as BaseI18nService } from "@bitwarden/common/platform/services/i18n.service";
import { GlobalStateProvider } from "@bitwarden/common/platform/state";
export class I18nRendererService extends BaseI18nService {
constructor(systemLanguage: string, localesDirectory: string) {
super(systemLanguage, localesDirectory, (formattedLocale: string) => {
return ipc.platform.getLanguageFile(formattedLocale);
});
constructor(
systemLanguage: string,
localesDirectory: string,
globalStateProvider: GlobalStateProvider,
) {
super(
systemLanguage,
localesDirectory,
(formattedLocale: string) => {
return ipc.platform.getLanguageFile(formattedLocale);
},
globalStateProvider,
);
// Please leave 'en' where it is, as it's our fallback language in case no translation can be found
this.supportedTranslationLocales = [

View File

@@ -1,16 +1,6 @@
import * as path from "path";
import {
app,
dialog,
ipcMain,
Menu,
MenuItem,
nativeTheme,
session,
Notification,
shell,
} from "electron";
import { app, dialog, ipcMain, Menu, MenuItem, nativeTheme, Notification, shell } from "electron";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { ThemeType } from "@bitwarden/common/platform/enums";
@@ -64,7 +54,7 @@ export class ElectronMainMessagingService implements MessagingService {
});
ipcMain.handle("getCookie", async (event, options) => {
return await session.defaultSession.cookies.get(options);
return await this.windowMain.session.cookies.get(options);
});
ipcMain.handle("loginRequest", async (event, options) => {