mirror of
https://github.com/bitwarden/browser
synced 2026-02-18 02:19:18 +00:00
Merge branch 'main' into ps/extension-refresh
This commit is contained in:
@@ -128,10 +128,10 @@
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "test-storybook:build:production"
|
||||
"buildTarget": "test-storybook:build:production"
|
||||
},
|
||||
"development": {
|
||||
"browserTarget": "test-storybook:build:development"
|
||||
"buildTarget": "test-storybook:build:development"
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "development"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bitwarden/browser",
|
||||
"version": "2024.10.999",
|
||||
"version": "2024.11.0",
|
||||
"scripts": {
|
||||
"build": "cross-env MANIFEST_VERSION=3 webpack",
|
||||
"build:mv2": "webpack",
|
||||
|
||||
@@ -32,6 +32,7 @@ import {
|
||||
} from "@bitwarden/common/spec";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { TotpService } from "@bitwarden/common/vault/abstractions/totp.service";
|
||||
import { VaultSettingsService } from "@bitwarden/common/vault/abstractions/vault-settings/vault-settings.service";
|
||||
import { CipherRepromptType, CipherType } from "@bitwarden/common/vault/enums";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
@@ -106,6 +107,7 @@ describe("OverlayBackground", () => {
|
||||
let selectedThemeMock$: BehaviorSubject<ThemeType>;
|
||||
let inlineMenuFieldQualificationService: InlineMenuFieldQualificationService;
|
||||
let themeStateService: MockProxy<ThemeStateService>;
|
||||
let totpService: MockProxy<TotpService>;
|
||||
let overlayBackground: OverlayBackground;
|
||||
let portKeyForTabSpy: Record<number, string>;
|
||||
let pageDetailsForTabSpy: PageDetailsForTab;
|
||||
@@ -184,6 +186,7 @@ describe("OverlayBackground", () => {
|
||||
inlineMenuFieldQualificationService = new InlineMenuFieldQualificationService();
|
||||
themeStateService = mock<ThemeStateService>();
|
||||
themeStateService.selectedTheme$ = selectedThemeMock$;
|
||||
totpService = mock<TotpService>();
|
||||
overlayBackground = new OverlayBackground(
|
||||
logService,
|
||||
cipherService,
|
||||
@@ -198,6 +201,7 @@ describe("OverlayBackground", () => {
|
||||
fido2ActiveRequestManager,
|
||||
inlineMenuFieldQualificationService,
|
||||
themeStateService,
|
||||
totpService,
|
||||
generatedPasswordCallbackMock,
|
||||
addPasswordCallbackMock,
|
||||
);
|
||||
|
||||
@@ -33,6 +33,7 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { ThemeStateService } from "@bitwarden/common/platform/theming/theme-state.service";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { TotpService } from "@bitwarden/common/vault/abstractions/totp.service";
|
||||
import { VaultSettingsService } from "@bitwarden/common/vault/abstractions/vault-settings/vault-settings.service";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||
import { buildCipherIcon } from "@bitwarden/common/vault/icon/build-cipher-icon";
|
||||
@@ -217,6 +218,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
||||
private fido2ActiveRequestManager: Fido2ActiveRequestManager,
|
||||
private inlineMenuFieldQualificationService: InlineMenuFieldQualificationService,
|
||||
private themeStateService: ThemeStateService,
|
||||
private totpService: TotpService,
|
||||
private generatePasswordCallback: () => Promise<string>,
|
||||
private addPasswordCallback: (password: string) => Promise<void>,
|
||||
) {
|
||||
@@ -1058,7 +1060,6 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
||||
}
|
||||
|
||||
const cipher = this.inlineMenuCiphers.get(inlineMenuCipherId);
|
||||
|
||||
if (usePasskey && cipher.login?.hasFido2Credentials) {
|
||||
await this.authenticatePasskeyCredential(
|
||||
sender,
|
||||
@@ -1066,6 +1067,11 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
||||
);
|
||||
this.updateLastUsedInlineMenuCipher(inlineMenuCipherId, cipher);
|
||||
|
||||
if (cipher.login?.totp) {
|
||||
this.platformUtilsService.copyToClipboard(
|
||||
await this.totpService.getCode(cipher.login.totp),
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1678,6 +1678,7 @@ export default class MainBackground {
|
||||
this.fido2ActiveRequestManager,
|
||||
inlineMenuFieldQualificationService,
|
||||
this.themeStateService,
|
||||
this.totpService,
|
||||
() => this.generatePassword(),
|
||||
(password) => this.addPasswordToHistory(password),
|
||||
);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"manifest_version": 2,
|
||||
"name": "__MSG_extName__",
|
||||
"short_name": "__MSG_appName__",
|
||||
"version": "2024.10.999",
|
||||
"version": "2024.11.0",
|
||||
"description": "__MSG_extDesc__",
|
||||
"default_locale": "en",
|
||||
"author": "Bitwarden Inc.",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"minimum_chrome_version": "102.0",
|
||||
"name": "__MSG_extName__",
|
||||
"short_name": "__MSG_appName__",
|
||||
"version": "2024.10.999",
|
||||
"version": "2024.11.0",
|
||||
"description": "__MSG_extDesc__",
|
||||
"default_locale": "en",
|
||||
"author": "Bitwarden Inc.",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@bitwarden/cli",
|
||||
"description": "A secure and free password manager for all of your devices.",
|
||||
"version": "2024.10.0",
|
||||
"version": "2024.11.0",
|
||||
"keywords": [
|
||||
"bitwarden",
|
||||
"password",
|
||||
@@ -80,7 +80,7 @@
|
||||
"papaparse": "5.4.1",
|
||||
"proper-lockfile": "4.1.2",
|
||||
"rxjs": "7.8.1",
|
||||
"tldts": "6.1.56",
|
||||
"tldts": "6.1.58",
|
||||
"zxcvbn": "4.4.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@bitwarden/desktop",
|
||||
"description": "A secure and free password manager for all of your devices.",
|
||||
"version": "2024.10.3",
|
||||
"version": "2024.11.0",
|
||||
"keywords": [
|
||||
"bitwarden",
|
||||
"password",
|
||||
|
||||
4
apps/desktop/src/package-lock.json
generated
4
apps/desktop/src/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@bitwarden/desktop",
|
||||
"version": "2024.10.3",
|
||||
"version": "2024.11.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@bitwarden/desktop",
|
||||
"version": "2024.10.3",
|
||||
"version": "2024.11.0",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@bitwarden/desktop-napi": "file:../desktop_native/napi",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@bitwarden/desktop",
|
||||
"productName": "Bitwarden",
|
||||
"description": "A secure and free password manager for all of your devices.",
|
||||
"version": "2024.10.3",
|
||||
"version": "2024.11.0",
|
||||
"author": "Bitwarden Inc. <hello@bitwarden.com> (https://bitwarden.com)",
|
||||
"homepage": "https://bitwarden.com",
|
||||
"license": "GPL-3.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bitwarden/web-vault",
|
||||
"version": "2024.10.5",
|
||||
"version": "2024.11.0",
|
||||
"scripts": {
|
||||
"build:oss": "webpack",
|
||||
"build:bit": "webpack -c ../../bitwarden_license/bit-web/webpack.config.js",
|
||||
|
||||
@@ -23,15 +23,14 @@
|
||||
<bit-tab [label]="'role' | i18n">
|
||||
<ng-container *ngIf="!editMode">
|
||||
<p bitTypography="body1">{{ "inviteUserDesc" | i18n }}</p>
|
||||
<bit-form-field *ngIf="remainingSeats$ | async as remainingSeats">
|
||||
<bit-form-field>
|
||||
<bit-label>{{ "email" | i18n }}</bit-label>
|
||||
<input id="emails" type="text" appAutoFocus bitInput formControlName="emails" />
|
||||
<bit-hint *ngIf="remainingSeats > 1; else singleSeat">{{
|
||||
"inviteMultipleEmailDesc" | i18n: remainingSeats
|
||||
<bit-hint>{{
|
||||
"inviteMultipleEmailDesc"
|
||||
| i18n
|
||||
: (organization.productTierType === ProductTierType.TeamsStarter ? "10" : "20")
|
||||
}}</bit-hint>
|
||||
<ng-template #singleSeat>
|
||||
<bit-hint>{{ "inviteSingleEmailDesc" | i18n: remainingSeats }}</bit-hint>
|
||||
</ng-template>
|
||||
</bit-form-field>
|
||||
</ng-container>
|
||||
<bit-radio-group formControlName="type">
|
||||
@@ -265,6 +264,16 @@
|
||||
<button
|
||||
*ngIf="editMode"
|
||||
type="button"
|
||||
bitIconButton="bwi-close"
|
||||
buttonType="danger"
|
||||
bitFormButton
|
||||
[appA11yTitle]="'remove' | i18n"
|
||||
[bitAction]="remove"
|
||||
[disabled]="loading"
|
||||
></button>
|
||||
<button
|
||||
*ngIf="editMode && params.managedByOrganization === true"
|
||||
type="button"
|
||||
bitIconButton="bwi-trash"
|
||||
buttonType="danger"
|
||||
bitFormButton
|
||||
|
||||
@@ -65,6 +65,7 @@ export interface MemberDialogParams {
|
||||
isOnSecretsManagerStandalone: boolean;
|
||||
initialTab?: MemberDialogTab;
|
||||
numConfirmedMembers: number;
|
||||
managedByOrganization?: boolean;
|
||||
}
|
||||
|
||||
export enum MemberDialogResult {
|
||||
@@ -89,7 +90,6 @@ export class MemberDialogComponent implements OnDestroy {
|
||||
PermissionMode = PermissionMode;
|
||||
showNoMasterPasswordWarning = false;
|
||||
isOnSecretsManagerStandalone: boolean;
|
||||
remainingSeats$: Observable<number>;
|
||||
|
||||
protected organization$: Observable<Organization>;
|
||||
protected collectionAccessItems: AccessItemView[] = [];
|
||||
@@ -251,10 +251,6 @@ export class MemberDialogComponent implements OnDestroy {
|
||||
|
||||
this.loading = false;
|
||||
});
|
||||
|
||||
this.remainingSeats$ = this.organization$.pipe(
|
||||
map((organization) => organization.seats - this.params.numConfirmedMembers),
|
||||
);
|
||||
}
|
||||
|
||||
private setFormValidators(organization: Organization) {
|
||||
@@ -469,7 +465,7 @@ export class MemberDialogComponent implements OnDestroy {
|
||||
this.close(MemberDialogResult.Saved);
|
||||
};
|
||||
|
||||
delete = async () => {
|
||||
remove = async () => {
|
||||
if (!this.editMode) {
|
||||
return;
|
||||
}
|
||||
@@ -566,6 +562,39 @@ export class MemberDialogComponent implements OnDestroy {
|
||||
this.close(MemberDialogResult.Restored);
|
||||
};
|
||||
|
||||
delete = async () => {
|
||||
if (!this.editMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: {
|
||||
key: "deleteOrganizationUser",
|
||||
placeholders: [this.params.name],
|
||||
},
|
||||
content: { key: "deleteOrganizationUserWarning" },
|
||||
type: "warning",
|
||||
acceptButtonText: { key: "delete" },
|
||||
cancelButtonText: { key: "cancel" },
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await this.organizationUserApiService.deleteOrganizationUser(
|
||||
this.params.organizationId,
|
||||
this.params.organizationUserId,
|
||||
);
|
||||
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("organizationUserDeleted", this.params.name),
|
||||
});
|
||||
this.close(MemberDialogResult.Deleted);
|
||||
};
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
|
||||
@@ -320,6 +320,17 @@
|
||||
<i aria-hidden="true" class="bwi bwi-close"></i> {{ "remove" | i18n }}
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
*ngIf="u.managedByOrganization === true"
|
||||
type="button"
|
||||
bitMenuItem
|
||||
(click)="deleteUser(u)"
|
||||
>
|
||||
<span class="tw-text-danger">
|
||||
<i class="bwi bwi-fw bwi-trash" aria-hidden="true"></i>
|
||||
{{ "delete" | i18n }}
|
||||
</span>
|
||||
</button>
|
||||
</bit-menu>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -486,7 +486,7 @@ export class MembersComponent extends BaseMembersComponent<OrganizationUserView>
|
||||
const enableUpgradePasswordManagerSub = await firstValueFrom(
|
||||
this.enableUpgradePasswordManagerSub$,
|
||||
);
|
||||
if (enableUpgradePasswordManagerSub) {
|
||||
if (enableUpgradePasswordManagerSub && this.organization.canEditSubscription) {
|
||||
const reference = openChangePlanDialog(this.dialogService, {
|
||||
data: {
|
||||
organizationId: this.organization.id,
|
||||
@@ -518,6 +518,7 @@ export class MembersComponent extends BaseMembersComponent<OrganizationUserView>
|
||||
isOnSecretsManagerStandalone: this.orgIsOnSecretsManagerStandalone,
|
||||
initialTab: initialTab,
|
||||
numConfirmedMembers: this.dataSource.confirmedUserCount,
|
||||
managedByOrganization: user?.managedByOrganization,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -725,6 +726,40 @@ export class MembersComponent extends BaseMembersComponent<OrganizationUserView>
|
||||
return true;
|
||||
}
|
||||
|
||||
async deleteUser(user: OrganizationUserView) {
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: {
|
||||
key: "deleteOrganizationUser",
|
||||
placeholders: [this.userNamePipe.transform(user)],
|
||||
},
|
||||
content: { key: "deleteOrganizationUserWarning" },
|
||||
type: "warning",
|
||||
acceptButtonText: { key: "delete" },
|
||||
cancelButtonText: { key: "cancel" },
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.actionPromise = this.organizationUserApiService.deleteOrganizationUser(
|
||||
this.organization.id,
|
||||
user.id,
|
||||
);
|
||||
try {
|
||||
await this.actionPromise;
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("organizationUserDeleted", this.userNamePipe.transform(user)),
|
||||
});
|
||||
this.dataSource.removeUser(user);
|
||||
} catch (e) {
|
||||
this.validationService.showError(e);
|
||||
}
|
||||
this.actionPromise = null;
|
||||
}
|
||||
|
||||
private async noMasterPasswordConfirmationDialog(user: OrganizationUserView) {
|
||||
return this.dialogService.openSimpleDialog({
|
||||
title: {
|
||||
|
||||
@@ -21,7 +21,13 @@
|
||||
>
|
||||
{{ "purgeVault" | i18n }}
|
||||
</button>
|
||||
<button type="button" bitButton buttonType="danger" [bitAction]="deleteAccount">
|
||||
<button
|
||||
*ngIf="showDeleteAccount$ | async"
|
||||
type="button"
|
||||
bitButton
|
||||
buttonType="danger"
|
||||
[bitAction]="deleteAccount"
|
||||
>
|
||||
{{ "deleteAccount" | i18n }}
|
||||
</button>
|
||||
</app-danger-zone>
|
||||
|
||||
@@ -23,6 +23,7 @@ export class AccountComponent implements OnInit {
|
||||
|
||||
showChangeEmail$: Observable<boolean>;
|
||||
showPurgeVault$: Observable<boolean>;
|
||||
showDeleteAccount$: Observable<boolean>;
|
||||
|
||||
constructor(
|
||||
private modalService: ModalService,
|
||||
@@ -63,6 +64,16 @@ export class AccountComponent implements OnInit {
|
||||
!isAccountDeprovisioningEnabled || !userIsManagedByOrganization,
|
||||
),
|
||||
);
|
||||
|
||||
this.showDeleteAccount$ = combineLatest([
|
||||
isAccountDeprovisioningEnabled$,
|
||||
userIsManagedByOrganization$,
|
||||
]).pipe(
|
||||
map(
|
||||
([isAccountDeprovisioningEnabled, userIsManagedByOrganization]) =>
|
||||
!isAccountDeprovisioningEnabled || !userIsManagedByOrganization,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
async deauthorizeSessions() {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
{{ "refresh" | i18n }}
|
||||
</a>
|
||||
</div>
|
||||
<bit-tab-group [(selectedIndex)]="tabIndex">
|
||||
<bit-tab-group [(selectedIndex)]="tabIndex" (selectedIndexChange)="onTabChange($event)">
|
||||
<bit-tab label="{{ 'allApplicationsWithCount' | i18n: apps.length }}">
|
||||
<tools-all-applications></tools-all-applications>
|
||||
</bit-tab>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { Component } from "@angular/core";
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { first } from "rxjs";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { AsyncActionsModule, ButtonModule, TabsModule } from "@bitwarden/components";
|
||||
@@ -18,7 +17,7 @@ import { PasswordHealthComponent } from "./password-health.component";
|
||||
|
||||
export enum AccessIntelligenceTabType {
|
||||
AllApps = 0,
|
||||
PriorityApps = 1,
|
||||
CriticalApps = 1,
|
||||
NotifiedMembers = 2,
|
||||
}
|
||||
|
||||
@@ -58,8 +57,19 @@ export class AccessIntelligenceComponent {
|
||||
);
|
||||
}
|
||||
|
||||
constructor(route: ActivatedRoute) {
|
||||
route.queryParams.pipe(takeUntilDestroyed(), first()).subscribe(({ tabIndex }) => {
|
||||
onTabChange = async (newIndex: number) => {
|
||||
await this.router.navigate([], {
|
||||
relativeTo: this.route,
|
||||
queryParams: { tabIndex: newIndex },
|
||||
queryParamsHandling: "merge",
|
||||
});
|
||||
};
|
||||
|
||||
constructor(
|
||||
protected route: ActivatedRoute,
|
||||
private router: Router,
|
||||
) {
|
||||
route.queryParams.pipe(takeUntilDestroyed()).subscribe(({ tabIndex }) => {
|
||||
this.tabIndex = !isNaN(tabIndex) ? tabIndex : AccessIntelligenceTabType.AllApps;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -14,13 +14,15 @@
|
||||
</h2>
|
||||
</ng-container>
|
||||
<ng-container slot="description">
|
||||
<p class="tw-text-muted">
|
||||
{{ "noAppsInOrgDescription" | i18n }}
|
||||
<div class="tw-flex tw-flex-col tw-mb-2">
|
||||
<span class="tw-text-muted">
|
||||
{{ "noAppsInOrgDescription" | i18n }}
|
||||
</span>
|
||||
<a class="text-primary" routerLink="/login">{{ "learnMore" | i18n }}</a>
|
||||
</p>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container slot="button">
|
||||
<button bitButton buttonType="primary" type="button">
|
||||
<button (click)="goToCreateNewLoginItem()" bitButton buttonType="primary" type="button">
|
||||
{{ "createNewLoginItem" | i18n }}
|
||||
</button>
|
||||
</ng-container>
|
||||
@@ -50,7 +52,15 @@
|
||||
class="tw-grow"
|
||||
[formControl]="searchControl"
|
||||
></bit-search>
|
||||
<button class="tw-rounded-lg" type="button" buttonType="secondary" bitButton>
|
||||
<button
|
||||
class="tw-rounded-lg"
|
||||
type="button"
|
||||
buttonType="secondary"
|
||||
bitButton
|
||||
[disabled]="!selectedIds.size"
|
||||
[loading]="markingAsCritical"
|
||||
(click)="markAppsAsCritical()"
|
||||
>
|
||||
<i class="bwi bwi-star-f tw-mr-2"></i>
|
||||
{{ "markAppAsCritical" | i18n }}
|
||||
</button>
|
||||
|
||||
@@ -40,6 +40,7 @@ export class AllApplicationsComponent implements OnInit {
|
||||
protected loading = false;
|
||||
protected organization: Organization;
|
||||
noItemsIcon = Icons.Security;
|
||||
protected markingAsCritical = false;
|
||||
|
||||
// MOCK DATA
|
||||
protected mockData = applicationTableMockData;
|
||||
@@ -76,8 +77,18 @@ export class AllApplicationsComponent implements OnInit {
|
||||
.subscribe((v) => (this.dataSource.filter = v));
|
||||
}
|
||||
|
||||
goToCreateNewLoginItem = async () => {
|
||||
// TODO: implement
|
||||
this.toastService.showToast({
|
||||
variant: "warning",
|
||||
title: null,
|
||||
message: "Not yet implemented",
|
||||
});
|
||||
};
|
||||
|
||||
markAppsAsCritical = async () => {
|
||||
// TODO: Send to API once implemented
|
||||
this.markingAsCritical = true;
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
this.selectedIds.clear();
|
||||
@@ -87,6 +98,7 @@ export class AllApplicationsComponent implements OnInit {
|
||||
message: this.i18nService.t("appsMarkedAsCritical"),
|
||||
});
|
||||
resolve(true);
|
||||
this.markingAsCritical = false;
|
||||
}, 1000);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -19,7 +19,9 @@
|
||||
</p>
|
||||
</ng-container>
|
||||
<ng-container slot="button">
|
||||
<button bitButton buttonType="primary" type="button">{{ "markCriticalApps" | i18n }}</button>
|
||||
<button (click)="goToAllAppsTab()" bitButton buttonType="primary" type="button">
|
||||
{{ "markCriticalApps" | i18n }}
|
||||
</button>
|
||||
</ng-container>
|
||||
</bit-no-items>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Component, DestroyRef, inject, OnInit } from "@angular/core";
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { FormControl } from "@angular/forms";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { debounceTime, map } from "rxjs";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
@@ -12,6 +12,7 @@ import { HeaderModule } from "../../layouts/header/header.module";
|
||||
import { SharedModule } from "../../shared";
|
||||
import { PipesModule } from "../../vault/individual-vault/pipes/pipes.module";
|
||||
|
||||
import { AccessIntelligenceTabType } from "./access-intelligence.component";
|
||||
import { applicationTableMockData } from "./application-table.mock";
|
||||
|
||||
@Component({
|
||||
@@ -26,8 +27,10 @@ export class CriticalApplicationsComponent implements OnInit {
|
||||
protected searchControl = new FormControl("", { nonNullable: true });
|
||||
private destroyRef = inject(DestroyRef);
|
||||
protected loading = false;
|
||||
protected organizationId: string;
|
||||
noItemsIcon = Icons.Security;
|
||||
// MOCK DATA
|
||||
protected mockData = applicationTableMockData;
|
||||
protected mockAtRiskMembersCount = 0;
|
||||
protected mockAtRiskAppsCount = 0;
|
||||
protected mockTotalMembersCount = 0;
|
||||
@@ -38,18 +41,26 @@ export class CriticalApplicationsComponent implements OnInit {
|
||||
.pipe(
|
||||
takeUntilDestroyed(this.destroyRef),
|
||||
map(async (params) => {
|
||||
// const organizationId = params.get("organizationId");
|
||||
this.organizationId = params.get("organizationId");
|
||||
// TODO: use organizationId to fetch data
|
||||
}),
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
goToAllAppsTab = async () => {
|
||||
await this.router.navigate([`organizations/${this.organizationId}/access-intelligence`], {
|
||||
queryParams: { tabIndex: AccessIntelligenceTabType.AllApps },
|
||||
queryParamsHandling: "merge",
|
||||
});
|
||||
};
|
||||
|
||||
constructor(
|
||||
protected i18nService: I18nService,
|
||||
protected activatedRoute: ActivatedRoute,
|
||||
protected router: Router,
|
||||
) {
|
||||
this.dataSource.data = applicationTableMockData;
|
||||
this.dataSource.data = []; //applicationTableMockData;
|
||||
this.searchControl.valueChanges
|
||||
.pipe(debounceTime(200), takeUntilDestroyed())
|
||||
.subscribe((v) => (this.dataSource.filter = v));
|
||||
|
||||
@@ -3218,9 +3218,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"inviteSingleEmailDesc": {
|
||||
"message": "You have 1 invite remaining."
|
||||
},
|
||||
"userUsingTwoStep": {
|
||||
"message": "This user is using two-step login to protect their account."
|
||||
},
|
||||
@@ -9557,5 +9554,31 @@
|
||||
},
|
||||
"single-org-revoked-user-warning": {
|
||||
"message": "Non-compliant members will be revoked. Administrators can restore members once they leave all other organizations."
|
||||
},
|
||||
"deleteOrganizationUser": {
|
||||
"message": "Delete $NAME$",
|
||||
"placeholders": {
|
||||
"name": {
|
||||
"content": "$1",
|
||||
"example": "John Doe"
|
||||
},
|
||||
"description": "Title for the delete organization user dialog"
|
||||
}
|
||||
},
|
||||
"deleteOrganizationUserWarning": {
|
||||
"message": "When a member is deleted, their Bitwarden account and individual vault data will be permanently deleted. Collection data will remain in the organization. To reinstate them they must create an account and be onboarded again.",
|
||||
"description": "Warning for the delete organization user dialog"
|
||||
},
|
||||
"organizationUserDeleted": {
|
||||
"message": "Deleted $NAME$",
|
||||
"placeholders": {
|
||||
"name": {
|
||||
"content": "$1",
|
||||
"example": "John Doe"
|
||||
}
|
||||
}
|
||||
},
|
||||
"organizationUserDeletedDesc": {
|
||||
"message": "The user was removed from the organization and all associated user data has been deleted."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import "core-js/stable";
|
||||
require("zone.js/dist/zone");
|
||||
import "zone.js";
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
// Production
|
||||
} else {
|
||||
// Development and test
|
||||
Error["stackTraceLimit"] = Infinity;
|
||||
require("zone.js/dist/long-stack-trace-zone");
|
||||
}
|
||||
|
||||
@@ -275,4 +275,11 @@ export abstract class OrganizationUserApiService {
|
||||
organizationId: string,
|
||||
ids: string[],
|
||||
): Promise<ListResponse<OrganizationUserBulkResponse>>;
|
||||
|
||||
/**
|
||||
* Remove an organization user's access to the organization and delete their account data
|
||||
* @param organizationId - Identifier for the organization the user belongs to
|
||||
* @param id - Organization user identifier
|
||||
*/
|
||||
abstract deleteOrganizationUser(organizationId: string, id: string): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -359,4 +359,14 @@ export class DefaultOrganizationUserApiService implements OrganizationUserApiSer
|
||||
);
|
||||
return new ListResponse(r, OrganizationUserBulkResponse);
|
||||
}
|
||||
|
||||
deleteOrganizationUser(organizationId: string, id: string): Promise<void> {
|
||||
return this.apiService.send(
|
||||
"DELETE",
|
||||
"/organizations/" + organizationId + "/users/" + id + "/delete-account",
|
||||
null,
|
||||
true,
|
||||
false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +220,8 @@ describe("DefaultActiveUserState", () => {
|
||||
it("should not emit a previous users value if that user is no longer active", async () => {
|
||||
const user1Data: Jsonify<TestState> = {
|
||||
date: "2020-09-21T13:14:17.648Z",
|
||||
array: ["value"],
|
||||
// NOTE: `as any` is here until we migrate to Nx: https://bitwarden.atlassian.net/browse/PM-6493
|
||||
array: ["value"] as any,
|
||||
};
|
||||
const user2Data: Jsonify<TestState> = {
|
||||
date: "2020-09-21T13:14:17.648Z",
|
||||
|
||||
@@ -192,7 +192,8 @@ describe("KeyDefinition", () => {
|
||||
expect(arrayDefinition).toBeTruthy();
|
||||
expect(arrayDefinition.deserializer).toBeTruthy();
|
||||
|
||||
const deserializedValue = arrayDefinition.deserializer([false, true]);
|
||||
// NOTE: `as any` is here until we migrate to Nx: https://bitwarden.atlassian.net/browse/PM-6493
|
||||
const deserializedValue = arrayDefinition.deserializer([false, true] as any);
|
||||
|
||||
expect(deserializedValue).toBeTruthy();
|
||||
expect(deserializedValue).toHaveLength(2);
|
||||
|
||||
@@ -151,6 +151,7 @@ describe("Login DTO", () => {
|
||||
password: "myPassword" as EncryptedString,
|
||||
passwordRevisionDate: passwordRevisionDate.toISOString(),
|
||||
totp: "myTotp" as EncryptedString,
|
||||
// NOTE: `as any` is here until we migrate to Nx: https://bitwarden.atlassian.net/browse/PM-6493
|
||||
fido2Credentials: [
|
||||
{
|
||||
credentialId: "keyId" as EncryptedString,
|
||||
@@ -167,7 +168,7 @@ describe("Login DTO", () => {
|
||||
discoverable: "discoverable" as EncryptedString,
|
||||
creationDate: fido2CreationDate.toISOString(),
|
||||
},
|
||||
],
|
||||
] as any,
|
||||
});
|
||||
|
||||
expect(actual).toEqual({
|
||||
|
||||
@@ -71,7 +71,7 @@ The content can be a button, anchor, or static container.
|
||||
<bit-item>
|
||||
<button bit-item-content type="button">
|
||||
<bit-avatar slot="start" text="Foo"></bit-avatar>
|
||||
foo@bitwarden.com
|
||||
foo@bitwarden.com
|
||||
<span bitBadge variant="primary" slot="default-trailing">Auto-fill</span>
|
||||
<ng-container slot="secondary">
|
||||
<div>Bitwarden.com</div>
|
||||
|
||||
@@ -94,7 +94,7 @@ export const ContentSlots: Story = {
|
||||
slot="start"
|
||||
[text]="'Foo'"
|
||||
></bit-avatar>
|
||||
foo@bitwarden.com
|
||||
foo@bitwarden.com
|
||||
<ng-container slot="secondary">
|
||||
<div>Bitwarden.com</div>
|
||||
<div><em>locked</em></div>
|
||||
@@ -285,37 +285,37 @@ export const SingleActionList: Story = {
|
||||
<a bit-item-content href="#">
|
||||
Foobar
|
||||
<i slot="end" class="bwi bwi-angle-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
</a>
|
||||
</bit-item>
|
||||
<bit-item>
|
||||
<a bit-item-content href="#">
|
||||
Foobar
|
||||
<i slot="end" class="bwi bwi-angle-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
</a>
|
||||
</bit-item>
|
||||
<bit-item>
|
||||
<a bit-item-content href="#">
|
||||
Foobar
|
||||
<i slot="end" class="bwi bwi-angle-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
</a>
|
||||
</bit-item>
|
||||
<bit-item>
|
||||
<a bit-item-content href="#">
|
||||
Foobar
|
||||
<i slot="end" class="bwi bwi-angle-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
</a>
|
||||
</bit-item>
|
||||
<bit-item>
|
||||
<a bit-item-content href="#">
|
||||
Foobar
|
||||
<i slot="end" class="bwi bwi-angle-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
</a>
|
||||
</bit-item>
|
||||
<bit-item>
|
||||
<a bit-item-content href="#">
|
||||
Foobar
|
||||
<i slot="end" class="bwi bwi-angle-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
</a>
|
||||
</bit-item>
|
||||
</bit-item-group>
|
||||
`,
|
||||
@@ -332,14 +332,14 @@ export const SingleActionWithBadge: Story = {
|
||||
Foobar
|
||||
<span bitBadge variant="primary" slot="default-trailing">Auto-fill</span>
|
||||
<i slot="end" class="bwi bwi-angle-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
</a>
|
||||
</bit-item>
|
||||
<bit-item>
|
||||
<a bit-item-content href="#">
|
||||
Helloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo!
|
||||
<span bitBadge variant="primary" slot="default-trailing">Auto-fill</span>
|
||||
<i slot="end" class="bwi bwi-angle-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
</a>
|
||||
</bit-item>
|
||||
</bit-item-group>
|
||||
`,
|
||||
|
||||
11445
package-lock.json
generated
11445
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
49
package.json
49
package.json
@@ -35,19 +35,20 @@
|
||||
"libs/*"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "16.2.14",
|
||||
"@angular-eslint/eslint-plugin": "16.3.1",
|
||||
"@angular-eslint/eslint-plugin-template": "16.3.1",
|
||||
"@angular-eslint/template-parser": "16.3.1",
|
||||
"@angular/cli": "16.2.14",
|
||||
"@angular/compiler-cli": "16.2.12",
|
||||
"@angular/elements": "16.2.12",
|
||||
"@angular-devkit/build-angular": "17.3.9",
|
||||
"@angular-eslint/eslint-plugin": "17.5.3",
|
||||
"@angular-eslint/eslint-plugin-template": "17.5.3",
|
||||
"@angular-eslint/schematics": "17.5.3",
|
||||
"@angular-eslint/template-parser": "17.5.3",
|
||||
"@angular/cli": "17.3.9",
|
||||
"@angular/compiler-cli": "17.3.12",
|
||||
"@angular/elements": "17.3.12",
|
||||
"@babel/core": "7.24.9",
|
||||
"@babel/preset-env": "7.24.8",
|
||||
"@compodoc/compodoc": "1.1.25",
|
||||
"@electron/notarize": "2.5.0",
|
||||
"@electron/rebuild": "3.7.0",
|
||||
"@ngtools/webpack": "16.2.14",
|
||||
"@ngtools/webpack": "17.3.9",
|
||||
"@storybook/addon-a11y": "8.2.9",
|
||||
"@storybook/addon-actions": "8.2.9",
|
||||
"@storybook/addon-designs": "8.0.3",
|
||||
@@ -58,7 +59,7 @@
|
||||
"@storybook/manager-api": "8.2.9",
|
||||
"@storybook/theming": "8.2.9",
|
||||
"@types/argon2-browser": "1.18.4",
|
||||
"@types/chrome": "0.0.272",
|
||||
"@types/chrome": "0.0.280",
|
||||
"@types/firefox-webext-browser": "120.0.4",
|
||||
"@types/inquirer": "8.2.10",
|
||||
"@types/jest": "29.5.12",
|
||||
@@ -138,7 +139,7 @@
|
||||
"ts-loader": "9.5.1",
|
||||
"tsconfig-paths-webpack-plugin": "4.1.0",
|
||||
"type-fest": "2.19.0",
|
||||
"typescript": "5.1.6",
|
||||
"typescript": "5.4.2",
|
||||
"url": "0.11.4",
|
||||
"util": "0.12.5",
|
||||
"wait-on": "8.0.1",
|
||||
@@ -148,22 +149,22 @@
|
||||
"webpack-node-externals": "3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/animations": "16.2.12",
|
||||
"@angular/cdk": "16.2.14",
|
||||
"@angular/common": "16.2.12",
|
||||
"@angular/compiler": "16.2.12",
|
||||
"@angular/core": "16.2.12",
|
||||
"@angular/forms": "16.2.12",
|
||||
"@angular/platform-browser": "16.2.12",
|
||||
"@angular/platform-browser-dynamic": "16.2.12",
|
||||
"@angular/router": "16.2.12",
|
||||
"@angular/animations": "17.3.12",
|
||||
"@angular/cdk": "17.3.10",
|
||||
"@angular/common": "17.3.12",
|
||||
"@angular/compiler": "17.3.12",
|
||||
"@angular/core": "17.3.12",
|
||||
"@angular/forms": "17.3.12",
|
||||
"@angular/platform-browser": "17.3.12",
|
||||
"@angular/platform-browser-dynamic": "17.3.12",
|
||||
"@angular/router": "17.3.12",
|
||||
"@bitwarden/sdk-internal": "0.1.7",
|
||||
"@electron/fuses": "1.8.0",
|
||||
"@koa/multer": "3.0.2",
|
||||
"@koa/router": "13.1.0",
|
||||
"@microsoft/signalr": "8.0.7",
|
||||
"@microsoft/signalr-protocol-msgpack": "8.0.7",
|
||||
"@ng-select/ng-select": "11.2.0",
|
||||
"@ng-select/ng-select": "12.0.7",
|
||||
"argon2": "0.41.1",
|
||||
"argon2-browser": "1.18.0",
|
||||
"big-integer": "1.6.52",
|
||||
@@ -186,8 +187,8 @@
|
||||
"lowdb": "1.0.0",
|
||||
"lunr": "2.3.9",
|
||||
"multer": "1.4.5-lts.1",
|
||||
"ngx-infinite-scroll": "16.0.0",
|
||||
"ngx-toastr": "17.0.2",
|
||||
"ngx-infinite-scroll": "17.0.1",
|
||||
"ngx-toastr": "18.0.0",
|
||||
"node-fetch": "2.6.12",
|
||||
"node-forge": "1.3.1",
|
||||
"nord": "0.2.1",
|
||||
@@ -201,9 +202,9 @@
|
||||
"qrious": "4.0.2",
|
||||
"rxjs": "7.8.1",
|
||||
"tabbable": "6.2.0",
|
||||
"tldts": "6.1.56",
|
||||
"tldts": "6.1.58",
|
||||
"utf-8-validate": "6.0.4",
|
||||
"zone.js": "0.13.3",
|
||||
"zone.js": "0.14.10",
|
||||
"zxcvbn": "4.4.2"
|
||||
},
|
||||
"overrides": {
|
||||
|
||||
Reference in New Issue
Block a user