mirror of
https://github.com/bitwarden/browser
synced 2025-12-21 02:33:46 +00:00
Merge branch 'master' into PM-2135-beeep-refactor-and-refresh-web-user-verification-components
This commit is contained in:
11
apps/web/config/euprd.json
Normal file
11
apps/web/config/euprd.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"urls": {
|
||||
"icons": "https://icons.bitwarden.net",
|
||||
"notifications": "https://notifications.bitwarden.net",
|
||||
"scim": "https://scim.bitwarden.net"
|
||||
},
|
||||
"flags": {
|
||||
"secretsManager": true,
|
||||
"showPasswordless": true
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"urls": {
|
||||
"icons": "https://icons.poc2.bitwarden.pw",
|
||||
"notifications": "https://notifications.poc2.bitwarden.pw",
|
||||
"scim": "https://scim.poc2.bitwarden.pw"
|
||||
},
|
||||
"flags": {
|
||||
"secretsManager": true,
|
||||
"showPasswordless": true
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
"build:bit:dev:analyze": "cross-env LOGGING=false webpack -c ../../bitwarden_license/bit-web/webpack.config.js --profile --json > stats.json && npx webpack-bundle-analyzer stats.json build/",
|
||||
"build:bit:dev:watch": "cross-env ENV=development npm run build:bit:watch",
|
||||
"build:bit:qa": "cross-env NODE_ENV=production ENV=qa npm run build:bit",
|
||||
"build:bit:poc": "cross-env NODE_ENV=production ENV=poc npm run build:bit",
|
||||
"build:bit:euprd": "cross-env NODE_ENV=production ENV=euprd npm run build:bit",
|
||||
"build:bit:eudevtest": "cross-env NODE_ENV=production ENV=eudevtest npm run build:bit",
|
||||
"build:bit:cloud": "cross-env NODE_ENV=production ENV=cloud npm run build:bit",
|
||||
"build:oss:selfhost:watch": "cross-env ENV=selfhosted npm run build:oss:watch",
|
||||
|
||||
17
apps/web/src/app/admin-console/icons/devices.ts
Normal file
17
apps/web/src/app/admin-console/icons/devices.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { svgIcon } from "@bitwarden/components";
|
||||
|
||||
export const Devices = svgIcon`
|
||||
<svg width="201" height="201" viewBox="0 0 201 201" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g opacity=".49">
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd" clip-rule="evenodd" d="M34.3628 82.0889H10.3628C7.04908 82.0889 4.36279 84.7752 4.36279 88.0889V148.089C4.36279 151.403 7.04909 154.089 10.3628 154.089H34.3628C37.6765 154.089 40.3628 151.403 40.3628 148.089V88.0889C40.3628 84.7752 37.6765 82.0889 34.3628 82.0889ZM10.3628 78.0889C4.83995 78.0889 0.362793 82.566 0.362793 88.0889V148.089C0.362793 153.612 4.83995 158.089 10.3628 158.089H34.3628C39.8856 158.089 44.3628 153.612 44.3628 148.089V88.0889C44.3628 82.566 39.8856 78.0889 34.3628 78.0889H10.3628Z" />
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd" clip-rule="evenodd" d="M20.7329 86.8979C20.7329 86.3457 21.1806 85.8979 21.7329 85.8979H22.975C23.5273 85.8979 23.975 86.3457 23.975 86.8979C23.975 87.4502 23.5273 87.8979 22.975 87.8979H21.7329C21.1806 87.8979 20.7329 87.4502 20.7329 86.8979Z" />
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd" clip-rule="evenodd" d="M68.3628 159.089C68.3628 158.537 68.8105 158.089 69.3628 158.089H127.363C127.915 158.089 128.363 158.537 128.363 159.089C128.363 159.641 127.915 160.089 127.363 160.089H69.3628C68.8105 160.089 68.3628 159.641 68.3628 159.089Z" />
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd" clip-rule="evenodd" d="M88.103 159.089V141.325H90.103V159.089H88.103Z" />
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd" clip-rule="evenodd" d="M108.073 159.089V141.325H110.073V159.089H108.073Z" />
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd" clip-rule="evenodd" d="M27.3628 64.0889C27.3628 56.3569 33.6308 50.0889 41.3628 50.0889H157.363C165.095 50.0889 171.363 56.3569 171.363 64.0889V70.0889H167.363V64.0889C167.363 58.566 162.886 54.0889 157.363 54.0889H41.3628C35.8399 54.0889 31.3628 58.566 31.3628 64.0889V80.0889H27.3628V64.0889ZM42.3628 138.089H127.363V142.089H42.3628V138.089Z" />
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd" clip-rule="evenodd" d="M35.3628 65.0889C35.3628 61.2229 38.4968 58.0889 42.3628 58.0889H156.363C160.229 58.0889 163.363 61.2229 163.363 65.0889V70.0889H161.363V65.0889C161.363 62.3274 159.124 60.0889 156.363 60.0889H42.3628C39.6014 60.0889 37.3628 62.3274 37.3628 65.0889V80.0889H35.3628V65.0889ZM42.3628 132.089H127.363V134.089H42.3628V132.089Z" />
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd" clip-rule="evenodd" d="M125.363 78.0889C125.363 72.566 129.84 68.0889 135.363 68.0889H188.363C193.886 68.0889 198.363 72.566 198.363 78.0889V158.089C198.363 163.612 193.886 168.089 188.363 168.089H135.363C129.84 168.089 125.363 163.612 125.363 158.089V78.0889ZM135.363 72.0889C132.049 72.0889 129.363 74.7752 129.363 78.0889V158.089C129.363 161.403 132.049 164.089 135.363 164.089H188.363C191.676 164.089 194.363 161.403 194.363 158.089V78.0889C194.363 74.7752 191.677 72.0889 188.363 72.0889H135.363Z" />
|
||||
<path class="tw-fill-secondary-500" d="M164.363 159.089C164.363 160.193 163.467 161.089 162.363 161.089C161.258 161.089 160.363 160.193 160.363 159.089C160.363 157.984 161.258 157.089 162.363 157.089C163.467 157.089 164.363 157.984 164.363 159.089Z" />
|
||||
</g>
|
||||
</svg>
|
||||
`;
|
||||
1
apps/web/src/app/admin-console/icons/index.ts
Normal file
1
apps/web/src/app/admin-console/icons/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./devices";
|
||||
@@ -11,29 +11,11 @@ import { GroupRequest } from "./requests/group.request";
|
||||
import { OrganizationGroupBulkRequest } from "./requests/organization-group-bulk.request";
|
||||
import { GroupDetailsResponse, GroupResponse } from "./responses/group.response";
|
||||
|
||||
@Injectable({ providedIn: CoreOrganizationModule })
|
||||
@Injectable({
|
||||
providedIn: "root",
|
||||
})
|
||||
export class GroupService {
|
||||
constructor(private apiService: ApiService) {}
|
||||
|
||||
async delete(orgId: string, groupId: string): Promise<void> {
|
||||
await this.apiService.send(
|
||||
"DELETE",
|
||||
"/organizations/" + orgId + "/groups/" + groupId,
|
||||
null,
|
||||
true,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
async deleteMany(orgId: string, groupIds: string[]): Promise<void> {
|
||||
await this.apiService.send(
|
||||
"DELETE",
|
||||
"/organizations/" + orgId + "/groups",
|
||||
new OrganizationGroupBulkRequest(groupIds),
|
||||
true,
|
||||
true
|
||||
);
|
||||
}
|
||||
constructor(protected apiService: ApiService) {}
|
||||
|
||||
async get(orgId: string, groupId: string): Promise<GroupView> {
|
||||
const r = await this.apiService.send(
|
||||
@@ -60,6 +42,33 @@ export class GroupService {
|
||||
|
||||
return listResponse.data?.map((gr) => GroupView.fromResponse(gr)) ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable({ providedIn: CoreOrganizationModule })
|
||||
export class InternalGroupService extends GroupService {
|
||||
constructor(protected apiService: ApiService) {
|
||||
super(apiService);
|
||||
}
|
||||
|
||||
async delete(orgId: string, groupId: string): Promise<void> {
|
||||
await this.apiService.send(
|
||||
"DELETE",
|
||||
"/organizations/" + orgId + "/groups/" + groupId,
|
||||
null,
|
||||
true,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
async deleteMany(orgId: string, groupIds: string[]): Promise<void> {
|
||||
await this.apiService.send(
|
||||
"DELETE",
|
||||
"/organizations/" + orgId + "/groups",
|
||||
new OrganizationGroupBulkRequest(groupIds),
|
||||
true,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
async save(group: GroupView): Promise<GroupView> {
|
||||
const request = new GroupRequest();
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
export * from "./group/group.service";
|
||||
export * from "./collection-admin.service";
|
||||
export * from "./user-admin.service";
|
||||
|
||||
@@ -83,6 +83,7 @@ export class UserAdminService {
|
||||
}));
|
||||
view.groups = u.groups;
|
||||
view.accessSecretsManager = u.accessSecretsManager;
|
||||
view.hasMasterPassword = u.hasMasterPassword;
|
||||
|
||||
return view;
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
export * from "./collection-access-selection.view";
|
||||
export * from "./collection-admin.view";
|
||||
export * from "./group.view";
|
||||
export * from "./organization-user.view";
|
||||
export * from "./organization-user-admin-view";
|
||||
|
||||
@@ -16,6 +16,7 @@ export class OrganizationUserAdminView {
|
||||
accessAll: boolean;
|
||||
permissions: PermissionsApi;
|
||||
resetPasswordEnrolled: boolean;
|
||||
hasMasterPassword: boolean;
|
||||
|
||||
collections: CollectionAccessSelectionView[] = [];
|
||||
groups: string[] = [];
|
||||
|
||||
@@ -20,6 +20,7 @@ export class OrganizationUserView {
|
||||
avatarColor: string;
|
||||
twoFactorEnabled: boolean;
|
||||
usesKeyConnector: boolean;
|
||||
hasMasterPassword: boolean;
|
||||
|
||||
collections: CollectionAccessSelectionView[] = [];
|
||||
groups: string[] = [];
|
||||
|
||||
@@ -1,118 +1,89 @@
|
||||
<div class="modal fade" role="dialog" aria-modal="true" aria-labelledby="eventLogsTitle">
|
||||
<div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title" id="eventLogsTitle">
|
||||
{{ "eventLogs" | i18n }}
|
||||
<small class="text-muted" *ngIf="name">{{ name }}</small>
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
appA11yTitle="{{ 'close' | i18n }}"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body" *ngIf="!loaded">
|
||||
<i
|
||||
class="bwi bwi-spinner bwi-spin text-muted"
|
||||
title="{{ 'loading' | i18n }}"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
<span class="sr-only">{{ "loading" | i18n }}</span>
|
||||
</div>
|
||||
<div class="modal-body" *ngIf="loaded">
|
||||
<div class="d-flex">
|
||||
<div class="form-inline">
|
||||
<label class="sr-only" for="start">{{ "startDate" | i18n }}</label>
|
||||
<bit-dialog dialogSize="large" [loading]="loading">
|
||||
<span bitDialogTitle>
|
||||
{{ "eventLogs" | i18n }}
|
||||
<small class="tw-text-muted" *ngIf="name">{{ name }}</small>
|
||||
</span>
|
||||
<div bitDialogContent>
|
||||
<form [formGroup]="filterFormGroup" [bitSubmit]="refreshEvents">
|
||||
<div class="tw-flex tw-items-center tw-space-x-2">
|
||||
<div>
|
||||
<label class="tw-sr-only" for="start">{{ "startDate" | i18n }}</label>
|
||||
<span>
|
||||
<input
|
||||
bitInput
|
||||
type="datetime-local"
|
||||
class="form-control form-control-sm"
|
||||
id="start"
|
||||
placeholder="{{ 'startDate' | i18n }}"
|
||||
[(ngModel)]="start"
|
||||
placeholder="YYYY-MM-DDTHH:MM"
|
||||
formControlName="start"
|
||||
/>
|
||||
<span class="mx-2">-</span>
|
||||
<label class="sr-only" for="end">{{ "endDate" | i18n }}</label>
|
||||
</span>
|
||||
</div>
|
||||
<span class="tw-mx-2">-</span>
|
||||
<div>
|
||||
<label class="tw-sr-only" for="end">{{ "endDate" | i18n }}</label>
|
||||
<span>
|
||||
<input
|
||||
bitInput
|
||||
type="datetime-local"
|
||||
class="form-control form-control-sm"
|
||||
id="end"
|
||||
placeholder="{{ 'endDate' | i18n }}"
|
||||
[(ngModel)]="end"
|
||||
placeholder="YYYY-MM-DDTHH:MM"
|
||||
formControlName="end"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
#refreshBtn
|
||||
[appApiAction]="refreshPromise"
|
||||
type="button"
|
||||
class="btn btn-sm btn-outline-primary ml-3"
|
||||
(click)="loadEvents(true)"
|
||||
[disabled]="loaded && $any(refreshBtn).loading"
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
<button type="submit" bitButton buttonType="primary" bitFormButton>
|
||||
<i class="bwi bwi-refresh bwi-fw" aria-hidden="true"></i>
|
||||
{{ "refresh" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<hr />
|
||||
<div *ngIf="!dataSource.data || !dataSource.data.length">
|
||||
{{ "noEventsInList" | i18n }}
|
||||
</div>
|
||||
<bit-table [dataSource]="dataSource" *ngIf="dataSource?.data?.length">
|
||||
<ng-container header>
|
||||
<tr>
|
||||
<th bitCell>{{ "timestamp" | i18n }}</th>
|
||||
<th bitCell>
|
||||
<span class="tw-sr-only">{{ "client" | i18n }}</span>
|
||||
</th>
|
||||
<th bitCell *ngIf="showUser">{{ "member" | i18n }}</th>
|
||||
<th bitCell>{{ "event" | i18n }}</th>
|
||||
</tr>
|
||||
</ng-container>
|
||||
<ng-template body let-rows$>
|
||||
<tr bitRow *ngFor="let r of rows$ | async">
|
||||
<td bitCell>{{ r.date | date : "medium" }}</td>
|
||||
<td bitCell>
|
||||
<i
|
||||
class="bwi bwi-refresh bwi-fw"
|
||||
[ngClass]="{ 'bwi-spin': loaded && $any(refreshBtn).loading }"
|
||||
class="tw-text-muted bwi bwi-lg {{ r.appIcon }}"
|
||||
title="{{ r.appName }}, {{ r.ip }}"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
{{ "refresh" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
<hr />
|
||||
<div *ngIf="!events || !events.length">
|
||||
{{ "noEventsInList" | i18n }}
|
||||
</div>
|
||||
<table class="table table-hover mb-0" *ngIf="events && events.length">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="border-top-0" width="210">{{ "timestamp" | i18n }}</th>
|
||||
<th class="border-top-0" width="40">
|
||||
<span class="sr-only">{{ "device" | i18n }}</span>
|
||||
</th>
|
||||
<th class="border-top-0" width="150" *ngIf="showUser">{{ "user" | i18n }}</th>
|
||||
<th class="border-top-0">{{ "event" | i18n }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let e of events">
|
||||
<td>{{ e.date | date : "medium" }}</td>
|
||||
<td>
|
||||
<i
|
||||
class="text-muted bwi bwi-lg {{ e.appIcon }}"
|
||||
title="{{ e.appName }}, {{ e.ip }}"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
<span class="sr-only">{{ e.appName }}, {{ e.ip }}</span>
|
||||
</td>
|
||||
<td *ngIf="showUser">
|
||||
<span appA11yTitle="{{ e.userEmail }}">{{ e.userName }}</span>
|
||||
</td>
|
||||
<td [innerHTML]="e.message"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<button
|
||||
#moreBtn
|
||||
[appApiAction]="morePromise"
|
||||
type="button"
|
||||
class="btn btn-block btn-link btn-submit"
|
||||
(click)="loadEvents(false)"
|
||||
[disabled]="loaded && $any(moreBtn).loading"
|
||||
*ngIf="continuationToken"
|
||||
>
|
||||
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
|
||||
<span>{{ "loadMore" | i18n }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">
|
||||
{{ "close" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<span class="tw-sr-only">{{ r.appName }}, {{ r.ip }}</span>
|
||||
</td>
|
||||
<td bitCell *ngIf="showUser">
|
||||
<span appA11yTitle="{{ r.userEmail }}">{{ r.userName }}</span>
|
||||
</td>
|
||||
<td bitCell [innerHTML]="r.message"></td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</bit-table>
|
||||
<button
|
||||
bitButton
|
||||
buttonType="secondary"
|
||||
block
|
||||
[bitAction]="loadMoreEvents"
|
||||
type="button"
|
||||
*ngIf="continuationToken"
|
||||
>
|
||||
{{ "loadMore" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container bitDialogFooter>
|
||||
<button bitButton buttonType="secondary" type="button" bitDialogClose>
|
||||
{{ "close" | i18n }}
|
||||
</button>
|
||||
</ng-container>
|
||||
</bit-dialog>
|
||||
|
||||
@@ -1,78 +1,114 @@
|
||||
import { Component, Input, OnInit } from "@angular/core";
|
||||
import { DIALOG_DATA, DialogConfig } from "@angular/cdk/dialog";
|
||||
import { Component, Inject, OnInit } from "@angular/core";
|
||||
import { FormBuilder } from "@angular/forms";
|
||||
|
||||
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service";
|
||||
import { EventResponse } from "@bitwarden/common/models/response/event.response";
|
||||
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||
import { EventView } from "@bitwarden/common/models/view/event.view";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
|
||||
import { TableDataSource } from "@bitwarden/components";
|
||||
|
||||
import { EventService } from "../../../core";
|
||||
import { SharedModule } from "../../../shared";
|
||||
|
||||
export interface EntityEventsDialogParams {
|
||||
entity: "user" | "cipher";
|
||||
entityId: string;
|
||||
|
||||
organizationId?: string;
|
||||
providerId?: string;
|
||||
showUser?: boolean;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: "app-entity-events",
|
||||
imports: [SharedModule],
|
||||
templateUrl: "entity-events.component.html",
|
||||
standalone: true,
|
||||
})
|
||||
export class EntityEventsComponent implements OnInit {
|
||||
@Input() name: string;
|
||||
@Input() entity: "user" | "cipher";
|
||||
@Input() entityId: string;
|
||||
@Input() organizationId: string;
|
||||
@Input() providerId: string;
|
||||
@Input() showUser = false;
|
||||
|
||||
loading = true;
|
||||
loaded = false;
|
||||
events: any[];
|
||||
start: string;
|
||||
end: string;
|
||||
continuationToken: string;
|
||||
refreshPromise: Promise<any>;
|
||||
morePromise: Promise<any>;
|
||||
protected dataSource = new TableDataSource<EventView>();
|
||||
protected filterFormGroup = this.formBuilder.group({
|
||||
start: [""],
|
||||
end: [""],
|
||||
});
|
||||
|
||||
private orgUsersUserIdMap = new Map<string, any>();
|
||||
private orgUsersIdMap = new Map<string, any>();
|
||||
|
||||
get name() {
|
||||
return this.params.name;
|
||||
}
|
||||
|
||||
get showUser() {
|
||||
return this.params.showUser ?? false;
|
||||
}
|
||||
|
||||
constructor(
|
||||
@Inject(DIALOG_DATA) private params: EntityEventsDialogParams,
|
||||
private apiService: ApiService,
|
||||
private i18nService: I18nService,
|
||||
private eventService: EventService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private userNamePipe: UserNamePipe,
|
||||
private logService: LogService,
|
||||
private organizationUserService: OrganizationUserService
|
||||
private organizationUserService: OrganizationUserService,
|
||||
private formBuilder: FormBuilder,
|
||||
private validationService: ValidationService
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
const defaultDates = this.eventService.getDefaultDateFilters();
|
||||
this.start = defaultDates[0];
|
||||
this.end = defaultDates[1];
|
||||
this.filterFormGroup.setValue({
|
||||
start: defaultDates[0],
|
||||
end: defaultDates[1],
|
||||
});
|
||||
await this.load();
|
||||
}
|
||||
|
||||
async load() {
|
||||
if (this.showUser) {
|
||||
const response = await this.organizationUserService.getAllUsers(this.organizationId);
|
||||
response.data.forEach((u) => {
|
||||
const name = this.userNamePipe.transform(u);
|
||||
this.orgUsersIdMap.set(u.id, { name: name, email: u.email });
|
||||
this.orgUsersUserIdMap.set(u.userId, { name: name, email: u.email });
|
||||
});
|
||||
try {
|
||||
if (this.showUser) {
|
||||
const response = await this.organizationUserService.getAllUsers(this.params.organizationId);
|
||||
response.data.forEach((u) => {
|
||||
const name = this.userNamePipe.transform(u);
|
||||
this.orgUsersIdMap.set(u.id, { name: name, email: u.email });
|
||||
this.orgUsersUserIdMap.set(u.userId, { name: name, email: u.email });
|
||||
});
|
||||
}
|
||||
await this.loadEvents(true);
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
this.validationService.showError(e);
|
||||
}
|
||||
await this.loadEvents(true);
|
||||
this.loaded = true;
|
||||
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
async loadEvents(clearExisting: boolean) {
|
||||
if (this.refreshPromise != null || this.morePromise != null) {
|
||||
return;
|
||||
}
|
||||
loadMoreEvents = async () => {
|
||||
await this.loadEvents(false);
|
||||
};
|
||||
|
||||
refreshEvents = async () => {
|
||||
await this.loadEvents(true);
|
||||
};
|
||||
|
||||
private async loadEvents(clearExisting: boolean) {
|
||||
let dates: string[] = null;
|
||||
try {
|
||||
dates = this.eventService.formatDateFilters(this.start, this.end);
|
||||
dates = this.eventService.formatDateFilters(
|
||||
this.filterFormGroup.value.start,
|
||||
this.filterFormGroup.value.end
|
||||
);
|
||||
} catch (e) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
@@ -82,46 +118,34 @@ export class EntityEventsComponent implements OnInit {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
let response: ListResponse<EventResponse>;
|
||||
try {
|
||||
let promise: Promise<any>;
|
||||
if (this.entity === "user" && this.providerId) {
|
||||
promise = this.apiService.getEventsProviderUser(
|
||||
this.providerId,
|
||||
this.entityId,
|
||||
dates[0],
|
||||
dates[1],
|
||||
clearExisting ? null : this.continuationToken
|
||||
);
|
||||
} else if (this.entity === "user") {
|
||||
promise = this.apiService.getEventsOrganizationUser(
|
||||
this.organizationId,
|
||||
this.entityId,
|
||||
dates[0],
|
||||
dates[1],
|
||||
clearExisting ? null : this.continuationToken
|
||||
);
|
||||
} else {
|
||||
promise = this.apiService.getEventsCipher(
|
||||
this.entityId,
|
||||
dates[0],
|
||||
dates[1],
|
||||
clearExisting ? null : this.continuationToken
|
||||
);
|
||||
}
|
||||
if (clearExisting) {
|
||||
this.refreshPromise = promise;
|
||||
} else {
|
||||
this.morePromise = promise;
|
||||
}
|
||||
response = await promise;
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
if (this.params.entity === "user" && this.params.providerId) {
|
||||
response = await this.apiService.getEventsProviderUser(
|
||||
this.params.providerId,
|
||||
this.params.entityId,
|
||||
dates[0],
|
||||
dates[1],
|
||||
clearExisting ? null : this.continuationToken
|
||||
);
|
||||
} else if (this.params.entity === "user") {
|
||||
response = await this.apiService.getEventsOrganizationUser(
|
||||
this.params.organizationId,
|
||||
this.params.entityId,
|
||||
dates[0],
|
||||
dates[1],
|
||||
clearExisting ? null : this.continuationToken
|
||||
);
|
||||
} else {
|
||||
response = await this.apiService.getEventsCipher(
|
||||
this.params.entityId,
|
||||
dates[0],
|
||||
dates[1],
|
||||
clearExisting ? null : this.continuationToken
|
||||
);
|
||||
}
|
||||
|
||||
this.continuationToken = response.continuationToken;
|
||||
const events = await Promise.all(
|
||||
const events: EventView[] = await Promise.all(
|
||||
response.data.map(async (r) => {
|
||||
const userId = r.actingUserId == null ? r.userId : r.actingUserId;
|
||||
const eventInfo = await this.eventService.getEventInfo(r);
|
||||
@@ -129,8 +153,10 @@ export class EntityEventsComponent implements OnInit {
|
||||
this.showUser && userId != null && this.orgUsersUserIdMap.has(userId)
|
||||
? this.orgUsersUserIdMap.get(userId)
|
||||
: null;
|
||||
return {
|
||||
|
||||
return new EventView({
|
||||
message: eventInfo.message,
|
||||
humanReadableMessage: eventInfo.humanReadableMessage,
|
||||
appIcon: eventInfo.appIcon,
|
||||
appName: eventInfo.appName,
|
||||
userId: userId,
|
||||
@@ -139,18 +165,29 @@ export class EntityEventsComponent implements OnInit {
|
||||
date: r.date,
|
||||
ip: r.ipAddress,
|
||||
type: r.type,
|
||||
};
|
||||
installationId: r.installationId,
|
||||
systemUser: r.systemUser,
|
||||
serviceAccountId: r.serviceAccountId,
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
if (!clearExisting && this.events != null && this.events.length > 0) {
|
||||
this.events = this.events.concat(events);
|
||||
if (!clearExisting && this.dataSource.data != null && this.dataSource.data.length > 0) {
|
||||
this.dataSource.data = this.dataSource.data.concat(events);
|
||||
} else {
|
||||
this.events = events;
|
||||
this.dataSource.data = events;
|
||||
}
|
||||
|
||||
this.loading = false;
|
||||
this.morePromise = null;
|
||||
this.refreshPromise = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Strongly typed helper to open a EntityEventsComponent as a dialog
|
||||
* @param dialogService Instance of the dialog service that will be used to open the dialog
|
||||
* @param config Configuration for the dialog
|
||||
*/
|
||||
export const openEntityEventsDialog = (
|
||||
dialogService: DialogServiceAbstraction,
|
||||
config: DialogConfig<EntityEventsDialogParams>
|
||||
) => {
|
||||
return dialogService.open<void, EntityEventsDialogParams>(EntityEventsComponent, config);
|
||||
};
|
||||
|
||||
@@ -6,16 +6,16 @@ import { catchError, combineLatest, from, map, of, Subject, switchMap, takeUntil
|
||||
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service";
|
||||
import { CollectionService } from "@bitwarden/common/admin-console/abstractions/collection.service";
|
||||
import { CollectionData } from "@bitwarden/common/admin-console/models/data/collection.data";
|
||||
import { Collection } from "@bitwarden/common/admin-console/models/domain/collection";
|
||||
import { CollectionDetailsResponse } from "@bitwarden/common/admin-console/models/response/collection.response";
|
||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { CollectionData } from "@bitwarden/common/vault/models/data/collection.data";
|
||||
import { Collection } from "@bitwarden/common/vault/models/domain/collection";
|
||||
import { CollectionDetailsResponse } from "@bitwarden/common/vault/models/response/collection.response";
|
||||
|
||||
import { GroupService, GroupView } from "../core";
|
||||
import { InternalGroupService as GroupService, GroupView } from "../core";
|
||||
import {
|
||||
AccessItemType,
|
||||
AccessItemValue,
|
||||
|
||||
@@ -19,21 +19,21 @@ import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/s
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||
import { CollectionService } from "@bitwarden/common/admin-console/abstractions/collection.service";
|
||||
import { CollectionData } from "@bitwarden/common/admin-console/models/data/collection.data";
|
||||
import { Collection } from "@bitwarden/common/admin-console/models/domain/collection";
|
||||
import {
|
||||
CollectionDetailsResponse,
|
||||
CollectionResponse,
|
||||
} from "@bitwarden/common/admin-console/models/response/collection.response";
|
||||
import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { CollectionData } from "@bitwarden/common/vault/models/data/collection.data";
|
||||
import { Collection } from "@bitwarden/common/vault/models/domain/collection";
|
||||
import {
|
||||
CollectionDetailsResponse,
|
||||
CollectionResponse,
|
||||
} from "@bitwarden/common/vault/models/response/collection.response";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
|
||||
import { GroupService, GroupView } from "../core";
|
||||
import { InternalGroupService as GroupService, GroupView } from "../core";
|
||||
|
||||
import {
|
||||
GroupAddEditDialogResultType,
|
||||
|
||||
@@ -23,12 +23,16 @@
|
||||
</app-callout>
|
||||
<ng-container *ngIf="!done">
|
||||
<app-callout type="warning" *ngIf="users.length > 0 && !error">
|
||||
{{ removeUsersWarning }}
|
||||
<p>{{ removeUsersWarning }}</p>
|
||||
<p *ngIf="this.showNoMasterPasswordWarning">
|
||||
{{ "removeMembersWithoutMasterPasswordWarning" | i18n }}
|
||||
</p>
|
||||
</app-callout>
|
||||
<table class="table table-hover table-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="2">{{ "user" | i18n }}</th>
|
||||
<th *ngIf="this.showNoMasterPasswordWarning">{{ "details" | i18n }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr *ngFor="let user of users">
|
||||
@@ -39,6 +43,15 @@
|
||||
{{ user.email }}
|
||||
<small class="text-muted d-block" *ngIf="user.name">{{ user.name }}</small>
|
||||
</td>
|
||||
<td *ngIf="this.showNoMasterPasswordWarning">
|
||||
<span class="text-muted d-block tw-lowercase">
|
||||
<ng-container *ngIf="user.hasMasterPassword === true"> - </ng-container>
|
||||
<ng-container *ngIf="user.hasMasterPassword === false">
|
||||
<i class="bwi bwi-exclamation-triangle" aria-hidden="true"></i>
|
||||
{{ "noMasterPassword" | i18n }}
|
||||
</ng-container>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</ng-container>
|
||||
|
||||
@@ -12,13 +12,23 @@ import { BulkUserDetails } from "./bulk-status.component";
|
||||
})
|
||||
export class BulkRemoveComponent {
|
||||
@Input() organizationId: string;
|
||||
@Input() users: BulkUserDetails[];
|
||||
@Input() set users(value: BulkUserDetails[]) {
|
||||
this._users = value;
|
||||
this.showNoMasterPasswordWarning = this._users.some((u) => u.hasMasterPassword === false);
|
||||
}
|
||||
|
||||
get users(): BulkUserDetails[] {
|
||||
return this._users;
|
||||
}
|
||||
|
||||
private _users: BulkUserDetails[];
|
||||
|
||||
statuses: Map<string, string> = new Map();
|
||||
|
||||
loading = false;
|
||||
done = false;
|
||||
error: string;
|
||||
showNoMasterPasswordWarning = false;
|
||||
|
||||
constructor(
|
||||
protected apiService: ApiService,
|
||||
|
||||
@@ -23,12 +23,16 @@
|
||||
</app-callout>
|
||||
<ng-container *ngIf="!done">
|
||||
<app-callout type="warning" *ngIf="users.length > 0 && !error && isRevoking">
|
||||
{{ "revokeUsersWarning" | i18n }}
|
||||
<p>{{ "revokeUsersWarning" | i18n }}</p>
|
||||
<p *ngIf="this.showNoMasterPasswordWarning">
|
||||
{{ "removeMembersWithoutMasterPasswordWarning" | i18n }}
|
||||
</p>
|
||||
</app-callout>
|
||||
<table class="table table-hover table-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="2">{{ "user" | i18n }}</th>
|
||||
<th *ngIf="this.showNoMasterPasswordWarning">{{ "details" | i18n }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr *ngFor="let user of users">
|
||||
@@ -39,6 +43,15 @@
|
||||
{{ user.email }}
|
||||
<small class="text-muted d-block" *ngIf="user.name">{{ user.name }}</small>
|
||||
</td>
|
||||
<td *ngIf="this.showNoMasterPasswordWarning">
|
||||
<span class="text-muted d-block tw-lowercase">
|
||||
<ng-container *ngIf="user.hasMasterPassword === true"> - </ng-container>
|
||||
<ng-container *ngIf="user.hasMasterPassword === false">
|
||||
<i class="bwi bwi-exclamation-triangle" aria-hidden="true"></i>
|
||||
{{ "noMasterPassword" | i18n }}
|
||||
</ng-container>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</ng-container>
|
||||
|
||||
@@ -20,6 +20,7 @@ export class BulkRestoreRevokeComponent {
|
||||
loading = false;
|
||||
done = false;
|
||||
error: string;
|
||||
showNoMasterPasswordWarning = false;
|
||||
|
||||
constructor(
|
||||
protected i18nService: I18nService,
|
||||
@@ -29,6 +30,7 @@ export class BulkRestoreRevokeComponent {
|
||||
this.isRevoking = config.data.isRevoking;
|
||||
this.organizationId = config.data.organizationId;
|
||||
this.users = config.data.users;
|
||||
this.showNoMasterPasswordWarning = this.users.some((u) => u.hasMasterPassword === false);
|
||||
}
|
||||
|
||||
get bulkTitle() {
|
||||
|
||||
@@ -10,6 +10,7 @@ export interface BulkUserDetails {
|
||||
name: string;
|
||||
email: string;
|
||||
status: OrganizationUserStatusType | ProviderUserStatusType;
|
||||
hasMasterPassword?: boolean;
|
||||
}
|
||||
|
||||
type BulkStatusEntry = {
|
||||
|
||||
@@ -12,14 +12,14 @@ import {
|
||||
} from "@bitwarden/common/admin-console/enums";
|
||||
import { PermissionsApi } from "@bitwarden/common/admin-console/models/api/permissions.api";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
|
||||
import { flagEnabled } from "../../../../../../utils/flags";
|
||||
import { CollectionAdminService } from "../../../../../vault/core/collection-admin.service";
|
||||
import {
|
||||
CollectionAccessSelectionView,
|
||||
CollectionAdminService,
|
||||
GroupService,
|
||||
GroupView,
|
||||
OrganizationUserAdminView,
|
||||
@@ -72,6 +72,7 @@ export class MemberDialogComponent implements OnInit, OnDestroy {
|
||||
canUseCustomPermissions: boolean;
|
||||
PermissionMode = PermissionMode;
|
||||
canUseSecretsManager: boolean;
|
||||
showNoMasterPasswordWarning = false;
|
||||
|
||||
protected organization: Organization;
|
||||
protected collectionAccessItems: AccessItemView[] = [];
|
||||
@@ -179,6 +180,9 @@ export class MemberDialogComponent implements OnInit, OnDestroy {
|
||||
throw new Error("Could not find user to edit.");
|
||||
}
|
||||
this.isRevoked = userDetails.status === OrganizationUserStatusType.Revoked;
|
||||
this.showNoMasterPasswordWarning =
|
||||
userDetails.status > OrganizationUserStatusType.Invited &&
|
||||
userDetails.hasMasterPassword === false;
|
||||
const assignedCollectionsPermissions = {
|
||||
editAssignedCollections: userDetails.permissions.editAssignedCollections,
|
||||
deleteAssignedCollections: userDetails.permissions.deleteAssignedCollections,
|
||||
@@ -366,7 +370,7 @@ export class MemberDialogComponent implements OnInit, OnDestroy {
|
||||
? "removeUserConfirmationKeyConnector"
|
||||
: "removeOrgUserConfirmation";
|
||||
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
let confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: { key: "removeUserIdAccess", placeholders: [this.params.name] },
|
||||
content: { key: message },
|
||||
type: SimpleDialogType.WARNING,
|
||||
@@ -376,6 +380,14 @@ export class MemberDialogComponent implements OnInit, OnDestroy {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.showNoMasterPasswordWarning) {
|
||||
confirmed = await this.noMasterPasswordConfirmationDialog();
|
||||
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
await this.organizationUserService.deleteOrganizationUser(
|
||||
this.params.organizationId,
|
||||
this.params.organizationUserId
|
||||
@@ -394,7 +406,7 @@ export class MemberDialogComponent implements OnInit, OnDestroy {
|
||||
return;
|
||||
}
|
||||
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
let confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: { key: "revokeUserId", placeholders: [this.params.name] },
|
||||
content: { key: "revokeUserConfirmation" },
|
||||
acceptButtonText: { key: "revokeAccess" },
|
||||
@@ -405,6 +417,14 @@ export class MemberDialogComponent implements OnInit, OnDestroy {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.showNoMasterPasswordWarning) {
|
||||
confirmed = await this.noMasterPasswordConfirmationDialog();
|
||||
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
await this.organizationUserService.revokeOrganizationUser(
|
||||
this.params.organizationId,
|
||||
this.params.organizationUserId
|
||||
@@ -450,6 +470,19 @@ export class MemberDialogComponent implements OnInit, OnDestroy {
|
||||
private close(result: MemberDialogResult) {
|
||||
this.dialogRef.close(result);
|
||||
}
|
||||
|
||||
private noMasterPasswordConfirmationDialog() {
|
||||
return this.dialogService.openSimpleDialog({
|
||||
title: {
|
||||
key: "removeOrgUserNoMasterPasswordTitle",
|
||||
},
|
||||
content: {
|
||||
key: "removeOrgUserNoMasterPasswordDesc",
|
||||
placeholders: [this.params.name],
|
||||
},
|
||||
type: SimpleDialogType.WARNING,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function mapCollectionToAccessItemView(
|
||||
|
||||
@@ -317,7 +317,6 @@
|
||||
</ng-container>
|
||||
<ng-template #addEdit></ng-template>
|
||||
<ng-template #groupsTemplate></ng-template>
|
||||
<ng-template #eventsTemplate></ng-template>
|
||||
<ng-template #confirmTemplate></ng-template>
|
||||
<ng-template #resetPasswordTemplate></ng-template>
|
||||
<ng-template #bulkStatusTemplate></ng-template>
|
||||
|
||||
@@ -16,10 +16,10 @@ import {
|
||||
import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe";
|
||||
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
|
||||
import {
|
||||
SimpleDialogType,
|
||||
DialogServiceAbstraction,
|
||||
SimpleDialogCloseType,
|
||||
SimpleDialogOptions,
|
||||
SimpleDialogType,
|
||||
} from "@bitwarden/angular/services/dialog";
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
@@ -30,7 +30,6 @@ import {
|
||||
OrganizationUserUserDetailsResponse,
|
||||
} from "@bitwarden/common/abstractions/organization-user/responses";
|
||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||
import { CollectionService } from "@bitwarden/common/admin-console/abstractions/collection.service";
|
||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { PolicyApiServiceAbstraction as PolicyApiService } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
||||
@@ -40,11 +39,8 @@ import {
|
||||
OrganizationUserType,
|
||||
PolicyType,
|
||||
} from "@bitwarden/common/admin-console/enums";
|
||||
import { CollectionData } from "@bitwarden/common/admin-console/models/data/collection.data";
|
||||
import { Collection } from "@bitwarden/common/admin-console/models/domain/collection";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { OrganizationKeysRequest } from "@bitwarden/common/admin-console/models/request/organization-keys.request";
|
||||
import { CollectionDetailsResponse } from "@bitwarden/common/admin-console/models/response/collection.response";
|
||||
import { ProductType } from "@bitwarden/common/enums";
|
||||
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
@@ -53,9 +49,13 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
import { CollectionData } from "@bitwarden/common/vault/models/data/collection.data";
|
||||
import { Collection } from "@bitwarden/common/vault/models/domain/collection";
|
||||
import { CollectionDetailsResponse } from "@bitwarden/common/vault/models/response/collection.response";
|
||||
|
||||
import { EntityEventsComponent } from "../../../admin-console/organizations/manage/entity-events.component";
|
||||
import { openEntityEventsDialog } from "../../../admin-console/organizations/manage/entity-events.component";
|
||||
import { BasePeopleComponent } from "../../../common/base.people.component";
|
||||
import { GroupService } from "../core";
|
||||
import { OrganizationUserView } from "../core/views/organization-user.view";
|
||||
@@ -81,8 +81,6 @@ export class PeopleComponent
|
||||
{
|
||||
@ViewChild("groupsTemplate", { read: ViewContainerRef, static: true })
|
||||
groupsModalRef: ViewContainerRef;
|
||||
@ViewChild("eventsTemplate", { read: ViewContainerRef, static: true })
|
||||
eventsModalRef: ViewContainerRef;
|
||||
@ViewChild("confirmTemplate", { read: ViewContainerRef, static: true })
|
||||
confirmModalRef: ViewContainerRef;
|
||||
@ViewChild("resetPasswordTemplate", { read: ViewContainerRef, static: true })
|
||||
@@ -513,12 +511,14 @@ export class PeopleComponent
|
||||
}
|
||||
|
||||
async events(user: OrganizationUserView) {
|
||||
await this.modalService.openViewRef(EntityEventsComponent, this.eventsModalRef, (comp) => {
|
||||
comp.name = this.userNamePipe.transform(user);
|
||||
comp.organizationId = this.organization.id;
|
||||
comp.entityId = user.id;
|
||||
comp.showUser = false;
|
||||
comp.entity = "user";
|
||||
await openEntityEventsDialog(this.dialogService, {
|
||||
data: {
|
||||
name: this.userNamePipe.transform(user),
|
||||
organizationId: this.organization.id,
|
||||
entityId: user.id,
|
||||
showUser: false,
|
||||
entity: "user",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -546,7 +546,7 @@ export class PeopleComponent
|
||||
? "removeUserConfirmationKeyConnector"
|
||||
: "removeOrgUserConfirmation";
|
||||
|
||||
return await this.dialogService.openSimpleDialog({
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: {
|
||||
key: "removeUserIdAccess",
|
||||
placeholders: [this.userNamePipe.transform(user)],
|
||||
@@ -554,6 +554,35 @@ export class PeopleComponent
|
||||
content: { key: content },
|
||||
type: SimpleDialogType.WARNING,
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (user.status > OrganizationUserStatusType.Invited && user.hasMasterPassword === false) {
|
||||
return await this.noMasterPasswordConfirmationDialog(user);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected async revokeUserConfirmationDialog(user: OrganizationUserView) {
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: { key: "revokeAccess", placeholders: [this.userNamePipe.transform(user)] },
|
||||
content: this.revokeWarningMessage(),
|
||||
acceptButtonText: { key: "revokeAccess" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (user.status > OrganizationUserStatusType.Invited && user.hasMasterPassword === false) {
|
||||
return await this.noMasterPasswordConfirmationDialog(user);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async showBulkStatus(
|
||||
@@ -608,4 +637,17 @@ export class PeopleComponent
|
||||
modal.close();
|
||||
}
|
||||
}
|
||||
|
||||
private async noMasterPasswordConfirmationDialog(user: OrganizationUserView) {
|
||||
return this.dialogService.openSimpleDialog({
|
||||
title: {
|
||||
key: "removeOrgUserNoMasterPasswordTitle",
|
||||
},
|
||||
content: {
|
||||
key: "removeOrgUserNoMasterPasswordDesc",
|
||||
placeholders: [this.userNamePipe.transform(user)],
|
||||
},
|
||||
type: SimpleDialogType.WARNING,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,95 +1,66 @@
|
||||
<div class="page-header">
|
||||
<h1>{{ "organizationInfo" | i18n }}</h1>
|
||||
</div>
|
||||
<h1 bitTypography="h1" class="tw-pb-2.5">{{ "organizationInfo" | i18n }}</h1>
|
||||
<div *ngIf="loading">
|
||||
<i
|
||||
class="bwi bwi-spinner bwi-spin text-muted"
|
||||
title="{{ 'loading' | i18n }}"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
<span class="sr-only">{{ "loading" | i18n }}</span>
|
||||
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
|
||||
</div>
|
||||
<form
|
||||
*ngIf="org && !loading"
|
||||
#form
|
||||
(ngSubmit)="submit()"
|
||||
[appApiAction]="formPromise"
|
||||
ngNativeValidate
|
||||
>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label for="name">{{ "organizationName" | i18n }}</label>
|
||||
<input
|
||||
id="name"
|
||||
class="form-control"
|
||||
type="text"
|
||||
name="Name"
|
||||
[(ngModel)]="org.name"
|
||||
[disabled]="selfHosted"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="billingEmail">{{ "billingEmail" | i18n }}</label>
|
||||
<input
|
||||
id="billingEmail"
|
||||
class="form-control"
|
||||
type="text"
|
||||
name="BillingEmail"
|
||||
[(ngModel)]="org.billingEmail"
|
||||
[disabled]="selfHosted || !canEditSubscription"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="businessName">{{ "businessName" | i18n }}</label>
|
||||
<input
|
||||
id="businessName"
|
||||
class="form-control"
|
||||
type="text"
|
||||
name="BusinessName"
|
||||
[(ngModel)]="org.businessName"
|
||||
[disabled]="selfHosted || !canEditSubscription"
|
||||
/>
|
||||
</div>
|
||||
<form *ngIf="org && !loading" #form [bitSubmit]="submit" [formGroup]="formGroup">
|
||||
<div class="tw-grid tw-grid-cols-2 tw-gap-5">
|
||||
<div>
|
||||
<bit-form-field>
|
||||
<bit-label>{{ "organizationName" | i18n }}</bit-label>
|
||||
<input bitInput id="orgName" type="text" formControlName="orgName" />
|
||||
</bit-form-field>
|
||||
<bit-form-field>
|
||||
<bit-label>{{ "billingEmail" | i18n }}</bit-label>
|
||||
<input bitInput id="billingEmail" formControlName="billingEmail" type="email" />
|
||||
</bit-form-field>
|
||||
<bit-form-field>
|
||||
<bit-label>{{ "businessName" | i18n }}</bit-label>
|
||||
<input bitInput id="businessName" formControlName="businessName" type="text" />
|
||||
</bit-form-field>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div>
|
||||
<bit-avatar [text]="org.name" [id]="org.id" size="large"></bit-avatar>
|
||||
<app-account-fingerprint
|
||||
[fingerprintMaterial]="organizationId"
|
||||
[publicKeyBuffer]="publicKeyBuffer"
|
||||
fingerprintLabel="{{ 'yourOrganizationsFingerprint' | i18n }}"
|
||||
>
|
||||
</app-account-fingerprint>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
|
||||
<button type="submit" bitButton bitFormButton buttonType="primary">
|
||||
{{ "save" | i18n }}
|
||||
</button>
|
||||
</form>
|
||||
<ng-container *ngIf="canUseApi">
|
||||
<div class="secondary-header border-0 mb-0">
|
||||
<h1>{{ "apiKey" | i18n }}</h1>
|
||||
</div>
|
||||
<h1 bitTypography="h1" class="tw-mt-16 tw-pb-2.5">{{ "apiKey" | i18n }}</h1>
|
||||
<p>
|
||||
{{ "apiKeyDesc" | i18n }}
|
||||
<a href="https://docs.bitwarden.com" target="_blank" rel="noopener">
|
||||
{{ "learnMore" | i18n }}
|
||||
</a>
|
||||
</p>
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="viewApiKey()">
|
||||
<button type="button" bitButton buttonType="secondary" (click)="viewApiKey()">
|
||||
{{ "viewApiKey" | i18n }}
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="rotateApiKey()">
|
||||
<button type="button" bitButton buttonType="secondary" (click)="rotateApiKey()">
|
||||
{{ "rotateApiKey" | i18n }}
|
||||
</button>
|
||||
</ng-container>
|
||||
<div class="secondary-header text-danger border-0 mb-0">
|
||||
<h1>{{ "dangerZone" | i18n }}</h1>
|
||||
</div>
|
||||
<div class="card border-danger">
|
||||
<div class="card-body">
|
||||
<p>{{ "dangerZoneDesc" | i18n }}</p>
|
||||
<button type="button" class="btn btn-outline-danger" (click)="deleteOrganization()">
|
||||
{{ "deleteOrganization" | i18n }}
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-danger" (click)="purgeVault()">
|
||||
{{ "purgeVault" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
<h1 bitTypography="h1" class="tw-mt-16 tw-pb-2.5 !tw-text-danger">{{ "dangerZone" | i18n }}</h1>
|
||||
<div class="tw-rounded tw-border tw-border-solid tw-border-danger-500 tw-bg-background tw-p-5">
|
||||
<p>{{ "dangerZoneDesc" | i18n }}</p>
|
||||
<button type="button" bitButton buttonType="danger" (click)="deleteOrganization()">
|
||||
{{ "deleteOrganization" | i18n }}
|
||||
</button>
|
||||
<button type="button" bitButton buttonType="danger" (click)="purgeVault()">
|
||||
{{ "purgeVault" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
<ng-template #purgeOrganizationTemplate></ng-template>
|
||||
<ng-template #apiKeyTemplate></ng-template>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Component, ViewChild, ViewContainerRef } from "@angular/core";
|
||||
import { FormBuilder, Validators } from "@angular/forms";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { lastValueFrom } from "rxjs";
|
||||
import { combineLatest, lastValueFrom, Subject, switchMap, takeUntil, from } from "rxjs";
|
||||
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
@@ -13,6 +14,7 @@ import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.se
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
|
||||
import { ApiKeyComponent } from "../../../settings/api-key.component";
|
||||
import { PurgeVaultComponent } from "../../../settings/purge-vault.component";
|
||||
@@ -23,7 +25,6 @@ import { DeleteOrganizationDialogResult, openDeleteOrganizationDialog } from "./
|
||||
selector: "app-org-account",
|
||||
templateUrl: "account.component.html",
|
||||
})
|
||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
||||
export class AccountComponent {
|
||||
@ViewChild("purgeOrganizationTemplate", { read: ViewContainerRef, static: true })
|
||||
purgeModalRef: ViewContainerRef;
|
||||
@@ -40,7 +41,29 @@ export class AccountComponent {
|
||||
formPromise: Promise<OrganizationResponse>;
|
||||
taxFormPromise: Promise<unknown>;
|
||||
|
||||
private organizationId: string;
|
||||
// FormGroup validators taken from server Organization domain object
|
||||
protected formGroup = this.formBuilder.group({
|
||||
orgName: this.formBuilder.control(
|
||||
{ value: "", disabled: true },
|
||||
{
|
||||
validators: [Validators.required, Validators.maxLength(50)],
|
||||
updateOn: "change",
|
||||
}
|
||||
),
|
||||
billingEmail: this.formBuilder.control(
|
||||
{ value: "", disabled: true },
|
||||
{ validators: [Validators.required, Validators.email, Validators.maxLength(256)] }
|
||||
),
|
||||
businessName: this.formBuilder.control(
|
||||
{ value: "", disabled: true },
|
||||
{ validators: [Validators.maxLength(50)] }
|
||||
),
|
||||
});
|
||||
|
||||
protected organizationId: string;
|
||||
protected publicKeyBuffer: ArrayBuffer;
|
||||
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
constructor(
|
||||
private modalService: ModalService,
|
||||
@@ -52,53 +75,88 @@ export class AccountComponent {
|
||||
private router: Router,
|
||||
private organizationService: OrganizationService,
|
||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||
private dialogService: DialogServiceAbstraction
|
||||
private dialogService: DialogServiceAbstraction,
|
||||
private formBuilder: FormBuilder
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
this.selfHosted = this.platformUtilsService.isSelfHost();
|
||||
|
||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
||||
this.route.parent.parent.params.subscribe(async (params) => {
|
||||
this.organizationId = params.organizationId;
|
||||
this.canEditSubscription = this.organizationService.get(
|
||||
this.organizationId
|
||||
).canEditSubscription;
|
||||
try {
|
||||
this.org = await this.organizationApiService.get(this.organizationId);
|
||||
this.canUseApi = this.org.useApi;
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
}
|
||||
});
|
||||
this.loading = false;
|
||||
this.route.parent.parent.params
|
||||
.pipe(
|
||||
switchMap((params) => {
|
||||
return combineLatest([
|
||||
// Organization domain
|
||||
this.organizationService.get$(params.organizationId),
|
||||
// OrganizationResponse for form population
|
||||
from(this.organizationApiService.get(params.organizationId)),
|
||||
// Organization Public Key
|
||||
from(this.organizationApiService.getKeys(params.organizationId)),
|
||||
]);
|
||||
}),
|
||||
takeUntil(this.destroy$)
|
||||
)
|
||||
.subscribe(([organization, orgResponse, orgKeys]) => {
|
||||
// Set domain level organization variables
|
||||
this.organizationId = organization.id;
|
||||
this.canEditSubscription = organization.canEditSubscription;
|
||||
this.canUseApi = organization.useApi;
|
||||
|
||||
// Org Response
|
||||
this.org = orgResponse;
|
||||
|
||||
// Public Key Buffer for Org Fingerprint Generation
|
||||
this.publicKeyBuffer = Utils.fromB64ToArray(orgKeys?.publicKey)?.buffer;
|
||||
|
||||
// Patch existing values
|
||||
this.formGroup.patchValue({
|
||||
orgName: this.org.name,
|
||||
billingEmail: this.org.billingEmail,
|
||||
businessName: this.org.businessName,
|
||||
});
|
||||
|
||||
// Update disabled states - reactive forms prefers not using disabled attribute
|
||||
if (!this.selfHosted) {
|
||||
this.formGroup.get("orgName").enable();
|
||||
}
|
||||
|
||||
if (!this.selfHosted || this.canEditSubscription) {
|
||||
this.formGroup.get("billingEmail").enable();
|
||||
this.formGroup.get("businessName").enable();
|
||||
}
|
||||
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
async submit() {
|
||||
try {
|
||||
const request = new OrganizationUpdateRequest();
|
||||
request.name = this.org.name;
|
||||
request.businessName = this.org.businessName;
|
||||
request.billingEmail = this.org.billingEmail;
|
||||
ngOnDestroy(): void {
|
||||
// You must first call .next() in order for the notifier to properly close subscriptions using takeUntil
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
// Backfill pub/priv key if necessary
|
||||
if (!this.org.hasPublicAndPrivateKeys) {
|
||||
const orgShareKey = await this.cryptoService.getOrgKey(this.organizationId);
|
||||
const orgKeys = await this.cryptoService.makeKeyPair(orgShareKey);
|
||||
request.keys = new OrganizationKeysRequest(orgKeys[0], orgKeys[1].encryptedString);
|
||||
}
|
||||
|
||||
this.formPromise = this.organizationApiService.save(this.organizationId, request);
|
||||
await this.formPromise;
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("organizationUpdated")
|
||||
);
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
submit = async () => {
|
||||
this.formGroup.markAllAsTouched();
|
||||
if (this.formGroup.invalid) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const request = new OrganizationUpdateRequest();
|
||||
request.name = this.formGroup.value.orgName;
|
||||
request.businessName = this.formGroup.value.businessName;
|
||||
request.billingEmail = this.formGroup.value.billingEmail;
|
||||
|
||||
// Backfill pub/priv key if necessary
|
||||
if (!this.org.hasPublicAndPrivateKeys) {
|
||||
const orgShareKey = await this.cryptoService.getOrgKey(this.organizationId);
|
||||
const orgKeys = await this.cryptoService.makeKeyPair(orgShareKey);
|
||||
request.keys = new OrganizationKeysRequest(orgKeys[0], orgKeys[1].encryptedString);
|
||||
}
|
||||
|
||||
this.formPromise = this.organizationApiService.save(this.organizationId, request);
|
||||
await this.formPromise;
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("organizationUpdated"));
|
||||
};
|
||||
|
||||
async deleteOrganization() {
|
||||
const dialog = openDeleteOrganizationDialog(this.dialogService, {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
|
||||
import { LooseComponentsModule, SharedModule } from "../../../shared";
|
||||
import { AccountFingerprintComponent } from "../../../shared/components/account-fingerprint/account-fingerprint.component";
|
||||
import { PoliciesModule } from "../../organizations/policies";
|
||||
|
||||
import { AccountComponent } from "./account.component";
|
||||
@@ -9,7 +10,13 @@ import { SettingsComponent } from "./settings.component";
|
||||
import { TwoFactorSetupComponent } from "./two-factor-setup.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [SharedModule, LooseComponentsModule, PoliciesModule, OrganizationSettingsRoutingModule],
|
||||
imports: [
|
||||
SharedModule,
|
||||
LooseComponentsModule,
|
||||
PoliciesModule,
|
||||
OrganizationSettingsRoutingModule,
|
||||
AccountFingerprintComponent,
|
||||
],
|
||||
declarations: [SettingsComponent, AccountComponent, TwoFactorSetupComponent],
|
||||
})
|
||||
export class OrganizationSettingsModule {}
|
||||
|
||||
@@ -60,6 +60,16 @@
|
||||
>
|
||||
{{ "singleSignOn" | i18n }}
|
||||
</a>
|
||||
<ng-container *appIfFeature="FeatureFlag.TrustedDeviceEncryption">
|
||||
<a
|
||||
routerLink="device-approvals"
|
||||
class="list-group-item"
|
||||
routerLinkActive="active"
|
||||
*ngIf="org.canManageUsersPassword"
|
||||
>
|
||||
{{ "deviceApprovals" | i18n }}
|
||||
</a>
|
||||
</ng-container>
|
||||
<a
|
||||
routerLink="scim"
|
||||
class="list-group-item"
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Observable, switchMap } from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
|
||||
@Component({
|
||||
selector: "app-org-settings",
|
||||
@@ -11,6 +12,7 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga
|
||||
})
|
||||
export class SettingsComponent implements OnInit {
|
||||
organization$: Observable<Organization>;
|
||||
FeatureFlag = FeatureFlag;
|
||||
|
||||
constructor(private route: ActivatedRoute, private organizationService: OrganizationService) {}
|
||||
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
export * from "./shared-organization.module";
|
||||
export * from "./components/collection-dialog";
|
||||
|
||||
@@ -5,11 +5,10 @@ import { SearchModule } from "@bitwarden/components";
|
||||
import { SharedModule } from "../../../shared/shared.module";
|
||||
|
||||
import { AccessSelectorModule } from "./components/access-selector/access-selector.module";
|
||||
import { CollectionDialogModule } from "./components/collection-dialog";
|
||||
|
||||
@NgModule({
|
||||
imports: [SharedModule, CollectionDialogModule, AccessSelectorModule, SearchModule],
|
||||
imports: [SharedModule, AccessSelectorModule, SearchModule],
|
||||
declarations: [],
|
||||
exports: [SharedModule, CollectionDialogModule, AccessSelectorModule, SearchModule],
|
||||
exports: [SharedModule, AccessSelectorModule, SearchModule],
|
||||
})
|
||||
export class SharedOrganizationModule {}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { CollectionService } from "@bitwarden/common/admin-console/abstractions/collection.service";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
import {
|
||||
ImportService,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { ActivatedRoute } from "@angular/router";
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service";
|
||||
import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
|
||||
@@ -23,7 +23,7 @@ export class WeakPasswordsReportComponent extends BaseWeakPasswordsReportCompone
|
||||
|
||||
constructor(
|
||||
cipherService: CipherService,
|
||||
passwordGenerationService: PasswordGenerationServiceAbstraction,
|
||||
passwordStrengthService: PasswordStrengthServiceAbstraction,
|
||||
modalService: ModalService,
|
||||
messagingService: MessagingService,
|
||||
private route: ActivatedRoute,
|
||||
@@ -32,7 +32,7 @@ export class WeakPasswordsReportComponent extends BaseWeakPasswordsReportCompone
|
||||
) {
|
||||
super(
|
||||
cipherService,
|
||||
passwordGenerationService,
|
||||
passwordStrengthService,
|
||||
modalService,
|
||||
messagingService,
|
||||
passwordRepromptService
|
||||
|
||||
@@ -13,7 +13,6 @@ import { NotificationsService } from "@bitwarden/common/abstractions/notificatio
|
||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
|
||||
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeout.service";
|
||||
import { CollectionService } from "@bitwarden/common/admin-console/abstractions/collection.service";
|
||||
import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||
@@ -25,6 +24,7 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { InternalFolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
||||
|
||||
import { RouterService } from "../core";
|
||||
|
||||
@@ -42,7 +42,7 @@ export class LockComponent extends BaseLockComponent {
|
||||
ngZone: NgZone,
|
||||
policyApiService: PolicyApiServiceAbstraction,
|
||||
policyService: InternalPolicyService,
|
||||
passwordGenerationService: PasswordGenerationServiceAbstraction,
|
||||
passwordStrengthService: PasswordStrengthServiceAbstraction,
|
||||
dialogService: DialogServiceAbstraction
|
||||
) {
|
||||
super(
|
||||
@@ -61,7 +61,7 @@ export class LockComponent extends BaseLockComponent {
|
||||
ngZone,
|
||||
policyApiService,
|
||||
policyService,
|
||||
passwordGenerationService,
|
||||
passwordStrengthService,
|
||||
dialogService
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Subject, takeUntil } from "rxjs";
|
||||
import { first } from "rxjs/operators";
|
||||
|
||||
import { LoginComponent as BaseLoginComponent } from "@bitwarden/angular/auth/components/login.component";
|
||||
import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service";
|
||||
import { DevicesApiServiceAbstraction } from "@bitwarden/common/abstractions/devices/devices-api.service.abstraction";
|
||||
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
||||
import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
@@ -18,12 +19,12 @@ import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||
import { FormValidationErrorsService } from "@bitwarden/common/platform/abstractions/form-validation-errors.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
||||
|
||||
import { flagEnabled } from "../../../utils/flags";
|
||||
import { RouterService, StateService } from "../../core";
|
||||
@@ -50,6 +51,7 @@ export class LoginComponent extends BaseLoginComponent implements OnInit, OnDest
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
environmentService: EnvironmentService,
|
||||
passwordGenerationService: PasswordGenerationServiceAbstraction,
|
||||
private passwordStrengthService: PasswordStrengthServiceAbstraction,
|
||||
cryptoFunctionService: CryptoFunctionService,
|
||||
private policyApiService: PolicyApiServiceAbstraction,
|
||||
private policyService: InternalPolicyService,
|
||||
@@ -153,7 +155,7 @@ export class LoginComponent extends BaseLoginComponent implements OnInit, OnDest
|
||||
|
||||
// Check master password against policy
|
||||
if (this.enforcedPasswordPolicyOptions != null) {
|
||||
const strengthResult = this.passwordGenerationService.passwordStrength(
|
||||
const strengthResult = this.passwordStrengthService.getPasswordStrength(
|
||||
masterPassword,
|
||||
this.formGroup.value.email
|
||||
);
|
||||
|
||||
@@ -3,6 +3,7 @@ import { UntypedFormBuilder } from "@angular/forms";
|
||||
import { Router } from "@angular/router";
|
||||
|
||||
import { RegisterComponent as BaseRegisterComponent } from "@bitwarden/angular/components/register.component";
|
||||
import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service";
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||
@@ -12,7 +13,6 @@ import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { ReferenceEventRequest } from "@bitwarden/common/models/request/reference-event.request";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||
import { FormValidationErrorsService } from "@bitwarden/common/platform/abstractions/form-validation-errors.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
|
||||
@@ -4,7 +4,6 @@ import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||
import { TotpService } from "@bitwarden/common/abstractions/totp.service";
|
||||
import { CollectionService } from "@bitwarden/common/admin-console/abstractions/collection.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
@@ -15,6 +14,7 @@ import { StateService } from "@bitwarden/common/platform/abstractions/state.serv
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password/";
|
||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service";
|
||||
import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
|
||||
|
||||
@@ -247,13 +247,17 @@ export abstract class BasePeopleComponent<
|
||||
this.actionPromise = null;
|
||||
}
|
||||
|
||||
async revoke(user: UserType) {
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
protected async revokeUserConfirmationDialog(user: UserType) {
|
||||
return this.dialogService.openSimpleDialog({
|
||||
title: { key: "revokeAccess", placeholders: [this.userNamePipe.transform(user)] },
|
||||
content: this.revokeWarningMessage(),
|
||||
acceptButtonText: { key: "revokeAccess" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
});
|
||||
}
|
||||
|
||||
async revoke(user: UserType) {
|
||||
const confirmed = await this.revokeUserConfirmationDialog(user);
|
||||
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
|
||||
@@ -28,6 +28,7 @@ import { PolicyListService } from "../admin-console/core/policy-list.service";
|
||||
import { HtmlStorageService } from "../core/html-storage.service";
|
||||
import { I18nService } from "../core/i18n.service";
|
||||
import { StateMigrationService } from "../core/state-migration.service";
|
||||
import { CollectionAdminService } from "../vault/core/collection-admin.service";
|
||||
import { PasswordRepromptService } from "../vault/core/password-reprompt.service";
|
||||
|
||||
import { BroadcasterMessagingService } from "./broadcaster-messaging.service";
|
||||
@@ -106,6 +107,7 @@ import { WebPlatformUtilsService } from "./web-platform-utils.service";
|
||||
useClass: LoginService,
|
||||
deps: [StateService],
|
||||
},
|
||||
CollectionAdminService,
|
||||
],
|
||||
})
|
||||
export class CoreModule {
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
STATE_FACTORY,
|
||||
STATE_SERVICE_USE_CACHE,
|
||||
} from "@bitwarden/angular/services/injection-tokens";
|
||||
import { CollectionData } from "@bitwarden/common/admin-console/models/data/collection.data";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { StateMigrationService } from "@bitwarden/common/platform/abstractions/state-migration.service";
|
||||
import {
|
||||
@@ -18,6 +17,7 @@ import { StorageOptions } from "@bitwarden/common/platform/models/domain/storage
|
||||
import { StateService as BaseStateService } from "@bitwarden/common/platform/services/state.service";
|
||||
import { SendData } from "@bitwarden/common/tools/send/models/data/send.data";
|
||||
import { CipherData } from "@bitwarden/common/vault/models/data/cipher.data";
|
||||
import { CollectionData } from "@bitwarden/common/vault/models/data/collection.data";
|
||||
import { FolderData } from "@bitwarden/common/vault/models/data/folder.data";
|
||||
|
||||
import { Account } from "./account";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<router-outlet></router-outlet>
|
||||
<div class="container my-5 text-muted text-center">
|
||||
<div class="tw-mb-1">
|
||||
<div class="tw-mb-1" *ngIf="!isSelfHosted">
|
||||
<bit-menu #environmentOptions>
|
||||
<a bitMenuItem href="https://vault.bitwarden.com" class="pr-4">
|
||||
<i
|
||||
|
||||
@@ -11,9 +11,10 @@ import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
})
|
||||
export class FrontendLayoutComponent implements OnInit, OnDestroy {
|
||||
version: string;
|
||||
isSelfHosted: boolean;
|
||||
euServerFlagEnabled: boolean;
|
||||
year = "2015";
|
||||
isEuServer = true;
|
||||
euServerFlagEnabled: boolean;
|
||||
|
||||
constructor(
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
@@ -23,6 +24,7 @@ export class FrontendLayoutComponent implements OnInit, OnDestroy {
|
||||
async ngOnInit() {
|
||||
this.year = new Date().getFullYear().toString();
|
||||
this.version = await this.platformUtilsService.getApplicationVersion();
|
||||
this.isSelfHosted = this.platformUtilsService.isSelfHost();
|
||||
this.euServerFlagEnabled = await this.configService.getFeatureFlagBool(
|
||||
FeatureFlag.DisplayEuEnvironmentFlag
|
||||
);
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Component, OnInit } from "@angular/core";
|
||||
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
|
||||
@@ -22,7 +22,7 @@ export class WeakPasswordsReportComponent extends CipherReportComponent implemen
|
||||
|
||||
constructor(
|
||||
protected cipherService: CipherService,
|
||||
protected passwordGenerationService: PasswordGenerationServiceAbstraction,
|
||||
protected passwordStrengthService: PasswordStrengthServiceAbstraction,
|
||||
modalService: ModalService,
|
||||
messagingService: MessagingService,
|
||||
passwordRepromptService: PasswordRepromptService
|
||||
@@ -77,7 +77,7 @@ export class WeakPasswordsReportComponent extends CipherReportComponent implemen
|
||||
.filter((i) => i.length >= 3);
|
||||
}
|
||||
}
|
||||
const result = this.passwordGenerationService.passwordStrength(
|
||||
const result = this.passwordStrengthService.getPasswordStrength(
|
||||
c.login.password,
|
||||
null,
|
||||
userInput.length > 0 ? userInput : null
|
||||
|
||||
@@ -46,19 +46,11 @@
|
||||
Customize
|
||||
</button>
|
||||
</div>
|
||||
<hr />
|
||||
<p *ngIf="fingerprint">
|
||||
{{ "yourAccountsFingerprint" | i18n }}:
|
||||
<a
|
||||
href="https://bitwarden.com/help/fingerprint-phrase/"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
appA11yTitle="{{ 'learnMore' | i18n }}"
|
||||
>
|
||||
<i class="bwi bwi-question-circle" aria-hidden="true"></i></a
|
||||
><br />
|
||||
<code>{{ fingerprint }}</code>
|
||||
</p>
|
||||
<app-account-fingerprint
|
||||
[fingerprintMaterial]="fingerprintMaterial"
|
||||
fingerprintLabel="{{ 'yourAccountsFingerprint' | i18n }}"
|
||||
>
|
||||
</app-account-fingerprint>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading">
|
||||
|
||||
@@ -3,10 +3,8 @@ import { Subject, takeUntil } from "rxjs";
|
||||
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||
import { UpdateProfileRequest } from "@bitwarden/common/auth/models/request/update-profile.request";
|
||||
import { ProfileResponse } from "@bitwarden/common/models/response/profile.response";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
@@ -21,7 +19,7 @@ import { ChangeAvatarComponent } from "./change-avatar.component";
|
||||
export class ProfileComponent implements OnInit, OnDestroy {
|
||||
loading = true;
|
||||
profile: ProfileResponse;
|
||||
fingerprint: string;
|
||||
fingerprintMaterial: string;
|
||||
|
||||
formPromise: Promise<any>;
|
||||
@ViewChild("avatarModalTemplate", { read: ViewContainerRef, static: true })
|
||||
@@ -32,9 +30,7 @@ export class ProfileComponent implements OnInit, OnDestroy {
|
||||
private apiService: ApiService,
|
||||
private i18nService: I18nService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private cryptoService: CryptoService,
|
||||
private logService: LogService,
|
||||
private keyConnectorService: KeyConnectorService,
|
||||
private stateService: StateService,
|
||||
private modalService: ModalService
|
||||
) {}
|
||||
@@ -42,12 +38,7 @@ export class ProfileComponent implements OnInit, OnDestroy {
|
||||
async ngOnInit() {
|
||||
this.profile = await this.apiService.getProfile();
|
||||
this.loading = false;
|
||||
const fingerprint = await this.cryptoService.getFingerprint(
|
||||
await this.stateService.getUserId()
|
||||
);
|
||||
if (fingerprint != null) {
|
||||
this.fingerprint = fingerprint.join("-");
|
||||
}
|
||||
this.fingerprintMaterial = await this.stateService.getUserId();
|
||||
}
|
||||
|
||||
async ngOnDestroy() {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<ng-container>
|
||||
<hr />
|
||||
<p *ngIf="fingerprint">
|
||||
{{ fingerprintLabel }}:
|
||||
<a
|
||||
href="https://bitwarden.com/help/fingerprint-phrase/"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
appA11yTitle="{{ 'learnMore' | i18n }}"
|
||||
>
|
||||
<i class="bwi bwi-question-circle" aria-hidden="true"></i
|
||||
></a>
|
||||
<br />
|
||||
<code class="tw-text-code">{{ fingerprint }}</code>
|
||||
</p>
|
||||
</ng-container>
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Component, Input, OnInit } from "@angular/core";
|
||||
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
|
||||
import { SharedModule } from "../../shared.module";
|
||||
|
||||
@Component({
|
||||
selector: "app-account-fingerprint",
|
||||
templateUrl: "account-fingerprint.component.html",
|
||||
standalone: true,
|
||||
imports: [SharedModule],
|
||||
})
|
||||
export class AccountFingerprintComponent implements OnInit {
|
||||
@Input() fingerprintMaterial: string;
|
||||
@Input() publicKeyBuffer: ArrayBuffer;
|
||||
@Input() fingerprintLabel: string;
|
||||
|
||||
protected fingerprint: string;
|
||||
|
||||
constructor(private cryptoService: CryptoService) {}
|
||||
|
||||
async ngOnInit() {
|
||||
// TODO - In the future, remove this code and use the fingerprint pipe once merged
|
||||
const generatedFingerprint = await this.cryptoService.getFingerprint(
|
||||
this.fingerprintMaterial,
|
||||
this.publicKeyBuffer
|
||||
);
|
||||
this.fingerprint = generatedFingerprint?.join("-") ?? null;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ import { NgModule } from "@angular/core";
|
||||
import { OrganizationSwitcherComponent } from "../admin-console/components/organization-switcher.component";
|
||||
import { OrganizationCreateModule } from "../admin-console/organizations/create/organization-create.module";
|
||||
import { OrganizationLayoutComponent } from "../admin-console/organizations/layouts/organization-layout.component";
|
||||
import { EntityEventsComponent as OrgEntityEventsComponent } from "../admin-console/organizations/manage/entity-events.component";
|
||||
import { EventsComponent as OrgEventsComponent } from "../admin-console/organizations/manage/events.component";
|
||||
import { UserConfirmComponent as OrgUserConfirmComponent } from "../admin-console/organizations/manage/user-confirm.component";
|
||||
import { AcceptFamilySponsorshipComponent } from "../admin-console/organizations/sponsorships/accept-family-sponsorship.component";
|
||||
@@ -109,6 +108,7 @@ import { AddEditComponent as OrgAddEditComponent } from "../vault/org-vault/add-
|
||||
import { AttachmentsComponent as OrgAttachmentsComponent } from "../vault/org-vault/attachments.component";
|
||||
import { CollectionsComponent as OrgCollectionsComponent } from "../vault/org-vault/collections.component";
|
||||
|
||||
import { AccountFingerprintComponent } from "./components/account-fingerprint/account-fingerprint.component";
|
||||
import { SharedModule } from "./shared.module";
|
||||
|
||||
// Please do not add to this list of declarations - we should refactor these into modules when doing so makes sense until there are none left.
|
||||
@@ -122,6 +122,7 @@ import { SharedModule } from "./shared.module";
|
||||
UserVerificationModule,
|
||||
ChangeKdfModule,
|
||||
DynamicAvatarComponent,
|
||||
AccountFingerprintComponent,
|
||||
],
|
||||
declarations: [
|
||||
PremiumBadgeComponent,
|
||||
@@ -166,7 +167,6 @@ import { SharedModule } from "./shared.module";
|
||||
OrganizationPlansComponent,
|
||||
OrgAttachmentsComponent,
|
||||
OrgCollectionsComponent,
|
||||
OrgEntityEventsComponent,
|
||||
OrgEventsComponent,
|
||||
OrgExposedPasswordsReportComponent,
|
||||
OrgInactiveTwoFactorReportComponent,
|
||||
@@ -272,7 +272,6 @@ import { SharedModule } from "./shared.module";
|
||||
OrganizationPlansComponent,
|
||||
OrgAttachmentsComponent,
|
||||
OrgCollectionsComponent,
|
||||
OrgEntityEventsComponent,
|
||||
OrgEventsComponent,
|
||||
OrgExposedPasswordsReportComponent,
|
||||
OrgInactiveTwoFactorReportComponent,
|
||||
|
||||
@@ -343,6 +343,28 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" *ngIf="usernameOptions.forwardedService === 'forwardemail'">
|
||||
<div class="form-group col-4">
|
||||
<label for="forwardemail-apikey">{{ "apiAccessToken" | i18n }}</label>
|
||||
<input
|
||||
id="forwardemail-apikey"
|
||||
class="form-control"
|
||||
type="password"
|
||||
[(ngModel)]="usernameOptions.forwardedForwardEmailApiToken"
|
||||
(blur)="saveUsernameOptions()"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-group col-4">
|
||||
<label for="forwardemail-domain">{{ "domainName" | i18n }}</label>
|
||||
<input
|
||||
id="forwardemail-domain"
|
||||
class="form-control"
|
||||
type="text"
|
||||
[(ngModel)]="usernameOptions.forwardedForwardEmailDomain"
|
||||
(blur)="saveUsernameOptions()"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div class="row" *ngIf="usernameOptions.type === 'subaddress'">
|
||||
<div class="form-group col-4">
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { CollectionService } from "@bitwarden/common/admin-console/abstractions/collection.service";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
import {
|
||||
ImportService,
|
||||
|
||||
@@ -5,27 +5,23 @@
|
||||
{{ "personalOwnershipPolicyInEffectImports" | i18n }}
|
||||
</app-callout>
|
||||
<form #form (ngSubmit)="submit()" ngNativeValidate>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label for="type">1. {{ "selectFormat" | i18n }}</label>
|
||||
<select
|
||||
id="type"
|
||||
name="Format"
|
||||
[(ngModel)]="format"
|
||||
class="form-control"
|
||||
[disabled]="importBlockedByPolicy"
|
||||
required
|
||||
>
|
||||
<option *ngFor="let o of featuredImportOptions" [ngValue]="o.id">{{ o.name }}</option>
|
||||
<ng-container *ngIf="importOptions && importOptions.length">
|
||||
<option value="-" disabled></option>
|
||||
<option *ngFor="let o of importOptions" [ngValue]="o.id">{{ o.name }}</option>
|
||||
</ng-container>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<bit-form-field class="tw-w-1/2">
|
||||
<bit-label for="type">1. {{ "selectFormat" | i18n }}</bit-label>
|
||||
<bit-select
|
||||
id="type"
|
||||
name="Format"
|
||||
bitInput
|
||||
[(ngModel)]="format"
|
||||
[disabled]="importBlockedByPolicy"
|
||||
required
|
||||
>
|
||||
<bit-option *ngFor="let o of featuredImportOptions" [value]="o.id" [label]="o.name" />
|
||||
<ng-container *ngIf="importOptions && importOptions.length">
|
||||
<bit-option value="-" disabled />
|
||||
<bit-option *ngFor="let o of importOptions" [value]="o.id" [label]="o.name" />
|
||||
</ng-container>
|
||||
</bit-select>
|
||||
</bit-form-field>
|
||||
<app-callout type="info" title="{{ getFormatInstructionTitle() }}" *ngIf="format">
|
||||
<ng-container *ngIf="format === 'bitwardencsv' || format === 'bitwardenjson'">
|
||||
See detailed instructions on our help site at
|
||||
|
||||
@@ -8,25 +8,22 @@ import { OrganizationUserService } from "@bitwarden/common/abstractions/organiza
|
||||
import { OrganizationUserUserDetailsResponse } from "@bitwarden/common/abstractions/organization-user/responses";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
import { BitValidators } from "@bitwarden/components";
|
||||
|
||||
import { GroupService, GroupView } from "../../../admin-console/organizations/core";
|
||||
import { PermissionMode } from "../../../admin-console/organizations/shared/components/access-selector/access-selector.component";
|
||||
import {
|
||||
CollectionAdminService,
|
||||
CollectionAdminView,
|
||||
GroupService,
|
||||
GroupView,
|
||||
} from "../../../core";
|
||||
import {
|
||||
AccessItemType,
|
||||
AccessItemValue,
|
||||
AccessItemView,
|
||||
convertToPermission,
|
||||
AccessItemValue,
|
||||
AccessItemType,
|
||||
convertToSelectionView,
|
||||
PermissionMode,
|
||||
} from "../access-selector";
|
||||
convertToPermission,
|
||||
} from "../../../admin-console/organizations/shared/components/access-selector/access-selector.models";
|
||||
import { CollectionAdminService } from "../../core/collection-admin.service";
|
||||
import { CollectionAdminView } from "../../core/views/collection-admin.view";
|
||||
|
||||
export enum CollectionDialogTabType {
|
||||
Info = 0,
|
||||
@@ -2,11 +2,10 @@ import { NgModule } from "@angular/core";
|
||||
|
||||
import { SelectModule } from "@bitwarden/components";
|
||||
|
||||
import { AccessSelectorModule } from "../../../../../admin-console/organizations/shared/components/access-selector/access-selector.module";
|
||||
import { SharedModule } from "../../../../../shared";
|
||||
import { AccessSelectorModule } from "../../../admin-console/organizations/shared/components/access-selector/access-selector.module";
|
||||
import { SharedModule } from "../../../shared";
|
||||
|
||||
import { CollectionDialogComponent } from "./collection-dialog.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [SharedModule, AccessSelectorModule, SelectModule],
|
||||
declarations: [CollectionDialogComponent],
|
||||
@@ -2,9 +2,9 @@ import { Component, EventEmitter, HostBinding, HostListener, Input, Output } fro
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
|
||||
import { VaultItemEvent } from "./vault-item-event";
|
||||
import { RowHeightClass } from "./vault-items.component";
|
||||
|
||||
@@ -2,9 +2,10 @@ import { Component, EventEmitter, HostBinding, HostListener, Input, Output } fro
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
|
||||
import { CollectionAdminView, GroupView } from "../../../admin-console/organizations/core";
|
||||
import { GroupView } from "../../../admin-console/organizations/core";
|
||||
import { CollectionAdminView } from "../../core/views/collection-admin.view";
|
||||
|
||||
import { VaultItemEvent } from "./vault-item-event";
|
||||
import { RowHeightClass } from "./vault-items.component";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CollectionView } from "@bitwarden/common/src/admin-console/models/view/collection.view";
|
||||
import { CollectionView } from "@bitwarden/common/src/vault/models/view/collection.view";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
|
||||
import { VaultItem } from "./vault-item";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
|
||||
export interface VaultItem {
|
||||
collection?: CollectionView;
|
||||
|
||||
@@ -2,11 +2,12 @@ import { SelectionModel } from "@angular/cdk/collections";
|
||||
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
import { TableDataSource } from "@bitwarden/components";
|
||||
|
||||
import { CollectionAdminView, GroupView } from "../../../admin-console/organizations/core";
|
||||
import { GroupView } from "../../../admin-console/organizations/core";
|
||||
import { CollectionAdminView } from "../../core/views/collection-admin.view";
|
||||
import { Unassigned } from "../../individual-vault/vault-filter/shared/models/routed-vault-filter.model";
|
||||
|
||||
import { VaultItem } from "./vault-item";
|
||||
|
||||
@@ -19,10 +19,10 @@ import { LoginView } from "@bitwarden/common/vault/models/view/login.view";
|
||||
|
||||
import {
|
||||
CollectionAccessSelectionView,
|
||||
CollectionAdminView,
|
||||
GroupView,
|
||||
} from "../../../admin-console/organizations/core";
|
||||
import { PreloadedEnglishI18nModule } from "../../../core/tests";
|
||||
import { CollectionAdminView } from "../../core/views/collection-admin.view";
|
||||
import { Unassigned } from "../../individual-vault/vault-filter/shared/models/routed-vault-filter.model";
|
||||
|
||||
import { VaultItemsComponent } from "./vault-items.component";
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { CollectionRequest } from "@bitwarden/common/admin-console/models/request/collection.request";
|
||||
import { SelectionReadOnlyRequest } from "@bitwarden/common/admin-console/models/request/selection-read-only.request";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
||||
import { CollectionRequest } from "@bitwarden/common/vault/models/request/collection.request";
|
||||
import {
|
||||
CollectionAccessDetailsResponse,
|
||||
CollectionResponse,
|
||||
} from "@bitwarden/common/admin-console/models/response/collection.response";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
||||
} from "@bitwarden/common/vault/models/response/collection.response";
|
||||
|
||||
import { CoreOrganizationModule } from "../core-organization.module";
|
||||
import { CollectionAdminView } from "../views/collection-admin.view";
|
||||
import { CollectionAdminView } from "./views/collection-admin.view";
|
||||
|
||||
@Injectable({ providedIn: CoreOrganizationModule })
|
||||
@Injectable()
|
||||
export class CollectionAdminService {
|
||||
constructor(private apiService: ApiService, private cryptoService: CryptoService) {}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { CollectionAccessDetailsResponse } from "@bitwarden/common/src/admin-console/models/response/collection.response";
|
||||
import { CollectionAccessDetailsResponse } from "@bitwarden/common/src/vault/models/response/collection.response";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
|
||||
import { CollectionAccessSelectionView } from "./collection-access-selection.view";
|
||||
import { CollectionAccessSelectionView } from "../../../admin-console/organizations/core/views/collection-access-selection.view";
|
||||
|
||||
export class CollectionAdminView extends CollectionView {
|
||||
groups: CollectionAccessSelectionView[] = [];
|
||||
@@ -440,6 +440,7 @@
|
||||
class="form-control text-monospace"
|
||||
type="{{ showCardNumber ? 'text' : 'password' }}"
|
||||
name="Card.Number"
|
||||
(input)="onCardNumberChange()"
|
||||
[(ngModel)]="cipher.card.number"
|
||||
appInputVerbatim
|
||||
autocomplete="new-password"
|
||||
|
||||
@@ -5,7 +5,6 @@ import { AddEditComponent as BaseAddEditComponent } from "@bitwarden/angular/vau
|
||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||
import { TotpService } from "@bitwarden/common/abstractions/totp.service";
|
||||
import { CollectionService } from "@bitwarden/common/admin-console/abstractions/collection.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { EventType, ProductType } from "@bitwarden/common/enums";
|
||||
@@ -17,6 +16,7 @@ import { StateService } from "@bitwarden/common/platform/abstractions/state.serv
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
|
||||
|
||||
@@ -2,16 +2,16 @@ import { DialogConfig, DialogRef, DIALOG_DATA } from "@angular/cdk/dialog";
|
||||
import { Component, Inject, OnInit } from "@angular/core";
|
||||
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { CollectionService } from "@bitwarden/common/admin-console/abstractions/collection.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { Checkable, isChecked } from "@bitwarden/common/types/checkable";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
|
||||
export interface BulkShareDialogParams {
|
||||
ciphers: CipherView[];
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Component, OnDestroy } from "@angular/core";
|
||||
|
||||
import { CollectionsComponent as BaseCollectionsComponent } from "@bitwarden/angular/admin-console/components/collections.component";
|
||||
import { CollectionService } from "@bitwarden/common/admin-console/abstractions/collection.service";
|
||||
import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
|
||||
@Component({
|
||||
selector: "app-vault-collections",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Pipe, PipeTransform } from "@angular/core";
|
||||
|
||||
import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
|
||||
@Pipe({
|
||||
name: "collectionNameFromId",
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { Component, OnDestroy } from "@angular/core";
|
||||
|
||||
import { ShareComponent as BaseShareComponent } from "@bitwarden/angular/components/share.component";
|
||||
import { CollectionService } from "@bitwarden/common/admin-console/abstractions/collection.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
|
||||
@Component({
|
||||
selector: "app-vault-share",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { CollectionView } from "@bitwarden/common/src/admin-console/models/view/collection.view";
|
||||
import { TreeNode } from "@bitwarden/common/src/models/domain/tree-node";
|
||||
import { CollectionView } from "@bitwarden/common/src/vault/models/view/collection.view";
|
||||
import { FolderView } from "@bitwarden/common/src/vault/models/view/folder.view";
|
||||
|
||||
import {
|
||||
|
||||
@@ -5,12 +5,12 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
import { FolderView } from "@bitwarden/common/vault/models/view/folder.view";
|
||||
|
||||
import { VaultFilterService } from "./vault-filter.service";
|
||||
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { ServiceUtils } from "@bitwarden/common/misc/serviceUtils";
|
||||
import { TreeNode } from "@bitwarden/common/models/domain/tree-node";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
@@ -26,9 +25,10 @@ import { StateService } from "@bitwarden/common/platform/abstractions/state.serv
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
import { FolderView } from "@bitwarden/common/vault/models/view/folder.view";
|
||||
|
||||
import { CollectionAdminView } from "../../../../admin-console/organizations/core";
|
||||
import { CollectionAdminView } from "../../../core/views/collection-admin.view";
|
||||
import {
|
||||
CipherTypeFilter,
|
||||
CollectionFilter,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { TreeNode } from "@bitwarden/common/models/domain/tree-node";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
import { FolderView } from "@bitwarden/common/vault/models/view/folder.view";
|
||||
|
||||
import { VaultFilter } from "./vault-filter.model";
|
||||
|
||||
@@ -3,7 +3,7 @@ import { ITreeNodeObject } from "@bitwarden/common/src/models/domain/tree-node";
|
||||
import { FolderView } from "@bitwarden/common/src/vault/models/view/folder.view";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
|
||||
|
||||
import { CollectionAdminView } from "../../../../../admin-console/organizations/core";
|
||||
import { CollectionAdminView } from "../../../../core/views/collection-admin.view";
|
||||
|
||||
export type CipherStatus = "all" | "favorites" | "trash" | CipherType;
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from "@angular/core";
|
||||
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { TreeNode } from "@bitwarden/common/models/domain/tree-node";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
|
||||
import {
|
||||
All,
|
||||
|
||||
@@ -34,10 +34,8 @@ import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||
import { TotpService } from "@bitwarden/common/abstractions/totp.service";
|
||||
import { CollectionService } from "@bitwarden/common/admin-console/abstractions/collection.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||
import { DEFAULT_PBKDF2_ITERATIONS, EventType, KdfType } from "@bitwarden/common/enums";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
@@ -53,10 +51,12 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service";
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
import { Icons } from "@bitwarden/components";
|
||||
|
||||
import { UpdateKeyComponent } from "../../settings/update-key.component";
|
||||
|
||||
@@ -3,6 +3,7 @@ import { NgModule } from "@angular/core";
|
||||
import { BreadcrumbsModule } from "@bitwarden/components";
|
||||
|
||||
import { LooseComponentsModule, SharedModule } from "../../shared";
|
||||
import { CollectionDialogModule } from "../components/collection-dialog";
|
||||
import { VaultItemsModule } from "../components/vault-items/vault-items.module";
|
||||
import { CollectionBadgeModule } from "../org-vault/collection-badge/collection-badge.module";
|
||||
import { GroupBadgeModule } from "../org-vault/group-badge/group-badge.module";
|
||||
@@ -28,6 +29,7 @@ import { VaultComponent } from "./vault.component";
|
||||
BulkDialogsModule,
|
||||
BreadcrumbsModule,
|
||||
VaultItemsModule,
|
||||
CollectionDialogModule,
|
||||
],
|
||||
declarations: [VaultComponent, VaultHeaderComponent],
|
||||
exports: [VaultComponent],
|
||||
|
||||
@@ -5,7 +5,6 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||
import { TotpService } from "@bitwarden/common/abstractions/totp.service";
|
||||
import { CollectionService } from "@bitwarden/common/admin-console/abstractions/collection.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
@@ -16,6 +15,7 @@ import { StateService } from "@bitwarden/common/platform/abstractions/state.serv
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service";
|
||||
import { CipherData } from "@bitwarden/common/vault/models/data/cipher.data";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, Input } from "@angular/core";
|
||||
|
||||
import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
|
||||
@Component({
|
||||
selector: "app-collection-badge",
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { CollectionService } from "@bitwarden/common/admin-console/abstractions/collection.service";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { CipherData } from "@bitwarden/common/vault/models/data/cipher.data";
|
||||
import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
|
||||
import { CipherCollectionsRequest } from "@bitwarden/common/vault/models/request/cipher-collections.request";
|
||||
|
||||
@@ -8,11 +8,9 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
|
||||
import {
|
||||
CollectionAdminService,
|
||||
CollectionAdminView,
|
||||
} from "../../../admin-console/organizations/core";
|
||||
import { StateService } from "../../../core";
|
||||
import { CollectionAdminView } from "../../../vault/core/views/collection-admin.view";
|
||||
import { CollectionAdminService } from "../../core/collection-admin.service";
|
||||
import { VaultFilterService as BaseVaultFilterService } from "../../individual-vault/vault-filter/services/vault-filter.service";
|
||||
import { CollectionFilter } from "../../individual-vault/vault-filter/shared/models/vault-filter.type";
|
||||
|
||||
|
||||
@@ -14,11 +14,9 @@ import { ProductType } from "@bitwarden/common/enums";
|
||||
import { TreeNode } from "@bitwarden/common/models/domain/tree-node";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
|
||||
import {
|
||||
CollectionAdminService,
|
||||
CollectionAdminView,
|
||||
} from "../../../admin-console/organizations/core";
|
||||
import { CollectionDialogTabType } from "../../../admin-console/organizations/shared";
|
||||
import { CollectionAdminView } from "../../../vault/core/views/collection-admin.view";
|
||||
import { CollectionDialogTabType } from "../../components/collection-dialog";
|
||||
import { CollectionAdminService } from "../../core/collection-admin.service";
|
||||
import {
|
||||
All,
|
||||
RoutedVaultFilterModel,
|
||||
|
||||
@@ -96,5 +96,4 @@
|
||||
<ng-template #attachments></ng-template>
|
||||
<ng-template #cipherAddEdit></ng-template>
|
||||
<ng-template #collectionsModal></ng-template>
|
||||
<ng-template #eventsTemplate></ng-template>
|
||||
</div>
|
||||
|
||||
@@ -38,7 +38,6 @@ import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||
import { TotpService } from "@bitwarden/common/abstractions/totp.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { EventType } from "@bitwarden/common/enums";
|
||||
import { ServiceUtils } from "@bitwarden/common/misc/serviceUtils";
|
||||
import { TreeNode } from "@bitwarden/common/models/domain/tree-node";
|
||||
@@ -53,23 +52,21 @@ import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/pa
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
import { Icons } from "@bitwarden/components";
|
||||
|
||||
import {
|
||||
CollectionAdminService,
|
||||
CollectionAdminView,
|
||||
GroupService,
|
||||
GroupView,
|
||||
} from "../../admin-console/organizations/core";
|
||||
import { EntityEventsComponent } from "../../admin-console/organizations/manage/entity-events.component";
|
||||
import { GroupService, GroupView } from "../../admin-console/organizations/core";
|
||||
import { openEntityEventsDialog } from "../../admin-console/organizations/manage/entity-events.component";
|
||||
import { VaultFilterService } from "../../vault/individual-vault/vault-filter/services/abstractions/vault-filter.service";
|
||||
import { VaultFilter } from "../../vault/individual-vault/vault-filter/shared/models/vault-filter.model";
|
||||
import {
|
||||
CollectionDialogResult,
|
||||
CollectionDialogTabType,
|
||||
openCollectionDialog,
|
||||
} from "../../admin-console/organizations/shared";
|
||||
import { VaultFilterService } from "../../vault/individual-vault/vault-filter/services/abstractions/vault-filter.service";
|
||||
import { VaultFilter } from "../../vault/individual-vault/vault-filter/shared/models/vault-filter.model";
|
||||
} from "../components/collection-dialog";
|
||||
import { VaultItemEvent } from "../components/vault-items/vault-item-event";
|
||||
import { CollectionAdminService } from "../core/collection-admin.service";
|
||||
import { CollectionAdminView } from "../core/views/collection-admin.view";
|
||||
import {
|
||||
BulkDeleteDialogResult,
|
||||
openBulkDeleteDialog,
|
||||
@@ -112,8 +109,6 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
cipherAddEditModalRef: ViewContainerRef;
|
||||
@ViewChild("collectionsModal", { read: ViewContainerRef, static: true })
|
||||
collectionsModalRef: ViewContainerRef;
|
||||
@ViewChild("eventsTemplate", { read: ViewContainerRef, static: true })
|
||||
eventsModalRef: ViewContainerRef;
|
||||
|
||||
trashCleanupWarning: string = null;
|
||||
activeFilter: VaultFilter = new VaultFilter();
|
||||
@@ -888,12 +883,14 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
async viewEvents(cipher: CipherView) {
|
||||
await this.modalService.openViewRef(EntityEventsComponent, this.eventsModalRef, (comp) => {
|
||||
comp.name = cipher.name;
|
||||
comp.organizationId = this.organization.id;
|
||||
comp.entityId = cipher.id;
|
||||
comp.showUser = true;
|
||||
comp.entity = "cipher";
|
||||
await openEntityEventsDialog(this.dialogService, {
|
||||
data: {
|
||||
name: cipher.name,
|
||||
organizationId: this.organization.id,
|
||||
entityId: cipher.id,
|
||||
showUser: true,
|
||||
entity: "cipher",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import { LooseComponentsModule } from "../../shared/loose-components.module";
|
||||
import { SharedModule } from "../../shared/shared.module";
|
||||
import { OrganizationBadgeModule } from "../../vault/individual-vault/organization-badge/organization-badge.module";
|
||||
import { PipesModule } from "../../vault/individual-vault/pipes/pipes.module";
|
||||
import { CollectionDialogModule } from "../components/collection-dialog";
|
||||
import { VaultItemsModule } from "../components/vault-items/vault-items.module";
|
||||
|
||||
import { CollectionBadgeModule } from "./collection-badge/collection-badge.module";
|
||||
@@ -27,6 +28,7 @@ import { VaultComponent } from "./vault.component";
|
||||
PipesModule,
|
||||
BreadcrumbsModule,
|
||||
VaultItemsModule,
|
||||
CollectionDialogModule,
|
||||
],
|
||||
declarations: [VaultComponent, VaultHeaderComponent],
|
||||
exports: [VaultComponent],
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
|
||||
import { getNestedCollectionTree } from "./collection-utils";
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { ServiceUtils } from "@bitwarden/common/misc/serviceUtils";
|
||||
import { TreeNode } from "@bitwarden/common/models/domain/tree-node";
|
||||
import {
|
||||
CollectionView,
|
||||
NestingDelimiter,
|
||||
} from "@bitwarden/common/admin-console/models/view/collection.view";
|
||||
import { ServiceUtils } from "@bitwarden/common/misc/serviceUtils";
|
||||
import { TreeNode } from "@bitwarden/common/models/domain/tree-node";
|
||||
} from "@bitwarden/common/vault/models/view/collection.view";
|
||||
|
||||
import { CollectionAdminView } from "../../admin-console/organizations/core";
|
||||
import { CollectionAdminView } from "../../vault/core/views/collection-admin.view";
|
||||
|
||||
export function getNestedCollectionTree(
|
||||
collections: CollectionAdminView[]
|
||||
|
||||
@@ -6827,12 +6827,79 @@
|
||||
},
|
||||
"memberDecryptionTdeDescriptionEnd": {
|
||||
"message": "with automatic enrollment will turn on when this option is used.",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The account recovery administration policy with automatic enrollment will turn on when this option is used.'"
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The master password reset policy with automatic enrollment will turn on when this option is used.'"
|
||||
},
|
||||
"notFound": {
|
||||
"message": "$RESOURCE$ not found",
|
||||
"placeholders": {
|
||||
"resource": {
|
||||
"content": "$1",
|
||||
"example": "Service Account"
|
||||
}
|
||||
}
|
||||
},
|
||||
"recoverAccount": {
|
||||
"message": "Recover account"
|
||||
},
|
||||
"updatedTempPassword": {
|
||||
"message": "User updated a password issued through account recovery."
|
||||
},
|
||||
"yourOrganizationsFingerprint": {
|
||||
"message": "Your organization's fingerprint phrase",
|
||||
"description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their organization's public key with another user, for the purposes of sharing."
|
||||
},
|
||||
"deviceApprovals": {
|
||||
"message": "Device approvals"
|
||||
},
|
||||
"deviceApprovalsDesc": {
|
||||
"message": "Approve login requests below to allow the requesting member to finish logging in. Unapproved requests expire after 1 week. Verify the member’s information before approving."
|
||||
},
|
||||
"deviceInfo": {
|
||||
"message": "Device info"
|
||||
},
|
||||
"time": {
|
||||
"message": "Time"
|
||||
},
|
||||
"denyAllRequests": {
|
||||
"message": "Deny all requests"
|
||||
},
|
||||
"denyRequest": {
|
||||
"message": "Deny request"
|
||||
},
|
||||
"approveRequest": {
|
||||
"message": "Approve request"
|
||||
},
|
||||
"noDeviceRequests": {
|
||||
"message": "No device requests"
|
||||
},
|
||||
"noDeviceRequestsDesc": {
|
||||
"message": "Member device approval requests will appear here"
|
||||
},
|
||||
"loginRequestDenied": {
|
||||
"message": "Login request denied"
|
||||
},
|
||||
"allLoginRequestsDenied": {
|
||||
"message": "All login requests denied"
|
||||
},
|
||||
"loginRequestApproved": {
|
||||
"message": "Login request approved"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordTitle": {
|
||||
"message": "Account does not have master password"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordDesc": {
|
||||
"message": "Removing $USER$ without setting a master password for them may restrict access to their full account. Are you sure you want to continue?",
|
||||
"placeholders": {
|
||||
"user": {
|
||||
"content": "$1",
|
||||
"example": "John Smith"
|
||||
}
|
||||
}
|
||||
},
|
||||
"noMasterPassword": {
|
||||
"message": "No master password"
|
||||
},
|
||||
"removeMembersWithoutMasterPasswordWarning": {
|
||||
"message": "Removing members who do not have master passwords without setting one for them may restrict access to their full account."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6827,12 +6827,79 @@
|
||||
},
|
||||
"memberDecryptionTdeDescriptionEnd": {
|
||||
"message": "with automatic enrollment will turn on when this option is used.",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The account recovery administration policy with automatic enrollment will turn on when this option is used.'"
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The master password reset policy with automatic enrollment will turn on when this option is used.'"
|
||||
},
|
||||
"notFound": {
|
||||
"message": "$RESOURCE$ not found",
|
||||
"placeholders": {
|
||||
"resource": {
|
||||
"content": "$1",
|
||||
"example": "Service Account"
|
||||
}
|
||||
}
|
||||
},
|
||||
"recoverAccount": {
|
||||
"message": "Recover account"
|
||||
},
|
||||
"updatedTempPassword": {
|
||||
"message": "User updated a password issued through account recovery."
|
||||
},
|
||||
"yourOrganizationsFingerprint": {
|
||||
"message": "Your organization's fingerprint phrase",
|
||||
"description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their organization's public key with another user, for the purposes of sharing."
|
||||
},
|
||||
"deviceApprovals": {
|
||||
"message": "Device approvals"
|
||||
},
|
||||
"deviceApprovalsDesc": {
|
||||
"message": "Approve login requests below to allow the requesting member to finish logging in. Unapproved requests expire after 1 week. Verify the member’s information before approving."
|
||||
},
|
||||
"deviceInfo": {
|
||||
"message": "Device info"
|
||||
},
|
||||
"time": {
|
||||
"message": "Time"
|
||||
},
|
||||
"denyAllRequests": {
|
||||
"message": "Deny all requests"
|
||||
},
|
||||
"denyRequest": {
|
||||
"message": "Deny request"
|
||||
},
|
||||
"approveRequest": {
|
||||
"message": "Approve request"
|
||||
},
|
||||
"noDeviceRequests": {
|
||||
"message": "No device requests"
|
||||
},
|
||||
"noDeviceRequestsDesc": {
|
||||
"message": "Member device approval requests will appear here"
|
||||
},
|
||||
"loginRequestDenied": {
|
||||
"message": "Login request denied"
|
||||
},
|
||||
"allLoginRequestsDenied": {
|
||||
"message": "All login requests denied"
|
||||
},
|
||||
"loginRequestApproved": {
|
||||
"message": "Login request approved"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordTitle": {
|
||||
"message": "Account does not have master password"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordDesc": {
|
||||
"message": "Removing $USER$ without setting a master password for them may restrict access to their full account. Are you sure you want to continue?",
|
||||
"placeholders": {
|
||||
"user": {
|
||||
"content": "$1",
|
||||
"example": "John Smith"
|
||||
}
|
||||
}
|
||||
},
|
||||
"noMasterPassword": {
|
||||
"message": "No master password"
|
||||
},
|
||||
"removeMembersWithoutMasterPasswordWarning": {
|
||||
"message": "Removing members who do not have master passwords without setting one for them may restrict access to their full account."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6827,12 +6827,79 @@
|
||||
},
|
||||
"memberDecryptionTdeDescriptionEnd": {
|
||||
"message": "Bu seçim istifadə edildikdə avto-qeydiyyat ilə işə salınacaq.",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The account recovery administration policy with automatic enrollment will turn on when this option is used.'"
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The master password reset policy with automatic enrollment will turn on when this option is used.'"
|
||||
},
|
||||
"notFound": {
|
||||
"message": "$RESOURCE$ tapılmadı",
|
||||
"placeholders": {
|
||||
"resource": {
|
||||
"content": "$1",
|
||||
"example": "Service Account"
|
||||
}
|
||||
}
|
||||
},
|
||||
"recoverAccount": {
|
||||
"message": "Hesabı bərpa et"
|
||||
},
|
||||
"updatedTempPassword": {
|
||||
"message": "İstifadəçi, hesab bərpası vasitəsilə verilən bir parolu güncəllədi."
|
||||
},
|
||||
"yourOrganizationsFingerprint": {
|
||||
"message": "Təşkilatınızın barmaq izi ifadəsi",
|
||||
"description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their organization's public key with another user, for the purposes of sharing."
|
||||
},
|
||||
"deviceApprovals": {
|
||||
"message": "Device approvals"
|
||||
},
|
||||
"deviceApprovalsDesc": {
|
||||
"message": "Approve login requests below to allow the requesting member to finish logging in. Unapproved requests expire after 1 week. Verify the member’s information before approving."
|
||||
},
|
||||
"deviceInfo": {
|
||||
"message": "Device info"
|
||||
},
|
||||
"time": {
|
||||
"message": "Time"
|
||||
},
|
||||
"denyAllRequests": {
|
||||
"message": "Deny all requests"
|
||||
},
|
||||
"denyRequest": {
|
||||
"message": "Deny request"
|
||||
},
|
||||
"approveRequest": {
|
||||
"message": "Approve request"
|
||||
},
|
||||
"noDeviceRequests": {
|
||||
"message": "No device requests"
|
||||
},
|
||||
"noDeviceRequestsDesc": {
|
||||
"message": "Member device approval requests will appear here"
|
||||
},
|
||||
"loginRequestDenied": {
|
||||
"message": "Login request denied"
|
||||
},
|
||||
"allLoginRequestsDenied": {
|
||||
"message": "All login requests denied"
|
||||
},
|
||||
"loginRequestApproved": {
|
||||
"message": "Login request approved"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordTitle": {
|
||||
"message": "Hesabın ana parolu yoxdur"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordDesc": {
|
||||
"message": "Onlar üçün ana parol tənzimləmədən $USER$ silinməsi, tam hesablarına müraciəti məhdudlaşdıra bilər. Davam etmək istədiyinizə əminsiniz?",
|
||||
"placeholders": {
|
||||
"user": {
|
||||
"content": "$1",
|
||||
"example": "John Smith"
|
||||
}
|
||||
}
|
||||
},
|
||||
"noMasterPassword": {
|
||||
"message": "Ana parol yoxdur"
|
||||
},
|
||||
"removeMembersWithoutMasterPasswordWarning": {
|
||||
"message": "Ana parolu olmayan üzvləri onlar üçün parol tənzimləmədən silmək, tam hesablarına müraciəti məhdudlaşdıra bilər."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4493,13 +4493,13 @@
|
||||
"message": "Падказка для пароля не можа супадаць з паролем."
|
||||
},
|
||||
"enrollAccountRecovery": {
|
||||
"message": "Enroll in account recovery"
|
||||
"message": "Зарэгістравацца на аднаўленне ўліковага запісу"
|
||||
},
|
||||
"enrolledAccountRecovery": {
|
||||
"message": "Enrolled in account recovery"
|
||||
"message": "Зарэгістравацца на аднаўленне ўліковага запісу"
|
||||
},
|
||||
"withdrawAccountRecovery": {
|
||||
"message": "Withdraw from account recovery"
|
||||
"message": "Адклікаць аднаўленне ўліковага запісу"
|
||||
},
|
||||
"enrollPasswordResetSuccess": {
|
||||
"message": "Паспяховая рэгістрацыя!"
|
||||
@@ -4508,7 +4508,7 @@
|
||||
"message": "Адмова паспяхова ўжыта!"
|
||||
},
|
||||
"eventEnrollAccountRecovery": {
|
||||
"message": "User $ID$ enrolled in account recovery.",
|
||||
"message": "Карыстальнік $ID$ зарэгістраваўся на аднаўленне ўліковага запісу.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
@@ -4517,7 +4517,7 @@
|
||||
}
|
||||
},
|
||||
"eventWithdrawAccountRecovery": {
|
||||
"message": "User $ID$ withdrew from account recovery.",
|
||||
"message": "Карыстальнік $ID$ адклікаў аднаўленне ўліковага запісу.",
|
||||
"placeholders": {
|
||||
"id": {
|
||||
"content": "$1",
|
||||
@@ -4577,10 +4577,10 @@
|
||||
"message": "Рэгістрацыя дазволіць адміністратарам арганізацыі змяняць ваш асноўны пароль"
|
||||
},
|
||||
"accountRecoveryPolicy": {
|
||||
"message": "Account recovery administration"
|
||||
"message": "Адміністраванне аднаўлення ўліковага запісу"
|
||||
},
|
||||
"accountRecoveryPolicyDescription": {
|
||||
"message": "Recover member accounts when master password or trusted devices are forgotten or lost. The recovery processes is based on the account encryption method."
|
||||
"message": "Аднаўленне ўліковага запісу ўдзельніка, калі асноўны пароль забыты або давераная прылада страчана. Працэс аднаўлення заснаваны на метадзе шыфравання ўліковага запісу."
|
||||
},
|
||||
"resetPasswordPolicyWarning": {
|
||||
"message": "Карыстальнікі арганізацыі павінны зарэгістравацца самастойна або быць зарэгістраванымі аўтаматычна, каб адміністратары маглі скінуць іх асноўны пароль."
|
||||
@@ -5231,11 +5231,11 @@
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Connect login with SSO to your self-hosted decryption key server. Using this option, members won’t need to use their master passwords to decrypt vault data. The require SSO authentication and single organization policies are required to set up Key Connector decryption. Contact Bitwarden Support for set up assistance.'"
|
||||
},
|
||||
"memberDecryptionKeyConnectorDescLink": {
|
||||
"message": "Для наладжвання расшыфроўкі Key Connector патрабуецца аўтэнтыфікацыя SSO",
|
||||
"message": "Патрабуецца аўтэнтыфікацыя SSO і палітыкі адзінай арганізацыі",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Connect login with SSO to your self-hosted decryption key server. Using this option, members won’t need to use their master passwords to decrypt vault data. The require SSO authentication and single organization policies are required to set up Key Connector decryption. Contact Bitwarden Support for set up assistance.'"
|
||||
},
|
||||
"memberDecryptionKeyConnectorDescEnd": {
|
||||
"message": "are required to set up Key Connector decryption. Contact Bitwarden Support for set up assistance.",
|
||||
"message": "для наладжвання шыфравання з дапамогай Key Connector. Звярніцеся ў службу падтрымкі Bitwarden, каб атрымаць дапамогу пры наладжванні.",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Connect login with SSO to your self-hosted decryption key server. Using this option, members won’t need to use their master passwords to decrypt vault data. The require SSO authentication and single organization policies are required to set up Key Connector decryption. Contact Bitwarden Support for set up assistance.'"
|
||||
},
|
||||
"keyConnectorPolicyRestriction": {
|
||||
@@ -6776,7 +6776,7 @@
|
||||
}
|
||||
},
|
||||
"inputTrimValidator": {
|
||||
"message": "Input must not contain only whitespace.",
|
||||
"message": "Уведзенае значэнне не павінна змяшчаць толькі прабелы.",
|
||||
"description": "Notification to inform the user that a form's input can't contain only whitespace."
|
||||
},
|
||||
"dismiss": {
|
||||
@@ -6793,7 +6793,7 @@
|
||||
"message": "Патрабаваць ад існуючых удзельнікаў змены пароляў"
|
||||
},
|
||||
"region": {
|
||||
"message": "Region"
|
||||
"message": "Рэгіён"
|
||||
},
|
||||
"eu": {
|
||||
"message": "ЕС",
|
||||
@@ -6822,17 +6822,84 @@
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The account recovery administration policy with automatic enrollment will turn on when this option is used.'"
|
||||
},
|
||||
"memberDecryptionTdeDescriptionLink": {
|
||||
"message": "account recovery administration policy",
|
||||
"message": "Палітыка адміністравання аднаўлення ўліковых запісаў",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The account recovery administration policy with automatic enrollment will turn on when this option is used.'"
|
||||
},
|
||||
"memberDecryptionTdeDescriptionEnd": {
|
||||
"message": "with automatic enrollment will turn on when this option is used.",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The account recovery administration policy with automatic enrollment will turn on when this option is used.'"
|
||||
"message": "з аўтаматычнай рэгістрацыяй уключаецца пры выкарыстанні гэтага параметра.",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The master password reset policy with automatic enrollment will turn on when this option is used.'"
|
||||
},
|
||||
"notFound": {
|
||||
"message": "$RESOURCE$ не знойдзены",
|
||||
"placeholders": {
|
||||
"resource": {
|
||||
"content": "$1",
|
||||
"example": "Service Account"
|
||||
}
|
||||
}
|
||||
},
|
||||
"recoverAccount": {
|
||||
"message": "Recover account"
|
||||
"message": "Аднавіць уліковы запіс"
|
||||
},
|
||||
"updatedTempPassword": {
|
||||
"message": "User updated a password issued through account recovery."
|
||||
"message": "Карыстальнік абнавіў пароль пры аднаўленні ўліковага запісу."
|
||||
},
|
||||
"yourOrganizationsFingerprint": {
|
||||
"message": "Фраза адбітку пальца вашай арганізацыі",
|
||||
"description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their organization's public key with another user, for the purposes of sharing."
|
||||
},
|
||||
"deviceApprovals": {
|
||||
"message": "Зацвярджэнне прылады"
|
||||
},
|
||||
"deviceApprovalsDesc": {
|
||||
"message": "Зацвердзіце запыт уваходу ніжэй, каб дазволіць удзельнікам завяршыць уваход. Тэрмін дзеяння не зацверджаных уваходаў міне праз 1 тыдзень. Праверце звесткі ўдзельнікаў перад тым, як зацвярджаць іх."
|
||||
},
|
||||
"deviceInfo": {
|
||||
"message": "Звесткі аб прыладзе"
|
||||
},
|
||||
"time": {
|
||||
"message": "Час"
|
||||
},
|
||||
"denyAllRequests": {
|
||||
"message": "Адхіліць усе запыты"
|
||||
},
|
||||
"denyRequest": {
|
||||
"message": "Адхіліць запыты"
|
||||
},
|
||||
"approveRequest": {
|
||||
"message": "Ухваліць запыт"
|
||||
},
|
||||
"noDeviceRequests": {
|
||||
"message": "Няма запытаў ад прылады"
|
||||
},
|
||||
"noDeviceRequestsDesc": {
|
||||
"message": "Тут будуць адлюстроўвацца запыты на ўхваленне прылады ўдзельніка"
|
||||
},
|
||||
"loginRequestDenied": {
|
||||
"message": "Запыт на ўваход адхілены"
|
||||
},
|
||||
"allLoginRequestsDenied": {
|
||||
"message": "Усе запыты на ўваход адхілены"
|
||||
},
|
||||
"loginRequestApproved": {
|
||||
"message": "Запыт на ўваход ухвалены"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordTitle": {
|
||||
"message": "Уліковы запіс не мае асноўнага пароля"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordDesc": {
|
||||
"message": "Выдаленне $USER$ без прызначэння галоўнага пароля можа стаць прычынай абмежавання доступу да яго ўліковага запісу. Вы ўпэўнены, што хочаце працягнуць?",
|
||||
"placeholders": {
|
||||
"user": {
|
||||
"content": "$1",
|
||||
"example": "John Smith"
|
||||
}
|
||||
}
|
||||
},
|
||||
"noMasterPassword": {
|
||||
"message": "Без асноўнага пароля"
|
||||
},
|
||||
"removeMembersWithoutMasterPasswordWarning": {
|
||||
"message": "Выдаленне ўдзельнікаў у якіх адсутнічае асноўны пароль і для якіх ён не быў прызначаны папярэдне можа стаць прычынай абмежавання доступу да іх уліковага запісу."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6827,12 +6827,79 @@
|
||||
},
|
||||
"memberDecryptionTdeDescriptionEnd": {
|
||||
"message": "с автоматично включване ще бъде активирана при използването на тази настройка.",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The account recovery administration policy with automatic enrollment will turn on when this option is used.'"
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The master password reset policy with automatic enrollment will turn on when this option is used.'"
|
||||
},
|
||||
"notFound": {
|
||||
"message": "Няма намерен $RESOURCE$",
|
||||
"placeholders": {
|
||||
"resource": {
|
||||
"content": "$1",
|
||||
"example": "Service Account"
|
||||
}
|
||||
}
|
||||
},
|
||||
"recoverAccount": {
|
||||
"message": "Възстановяване на профила"
|
||||
},
|
||||
"updatedTempPassword": {
|
||||
"message": "Потребителят промени парола издадена чрез възстановяването на профили."
|
||||
},
|
||||
"yourOrganizationsFingerprint": {
|
||||
"message": "Уникална фраза, идентифицираща организацията ви",
|
||||
"description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their organization's public key with another user, for the purposes of sharing."
|
||||
},
|
||||
"deviceApprovals": {
|
||||
"message": "Одобрение на устройства"
|
||||
},
|
||||
"deviceApprovalsDesc": {
|
||||
"message": "Одобрете заявките за вписване по-долу, за да разрешите на съответния член да завърши вписването си. Неодобрените заявки се премахват след 1 седмица. Потвърдете информацията за члена, преди да одобрите заявката му."
|
||||
},
|
||||
"deviceInfo": {
|
||||
"message": "Информация за устройството"
|
||||
},
|
||||
"time": {
|
||||
"message": "Време"
|
||||
},
|
||||
"denyAllRequests": {
|
||||
"message": "Отхвърляне на всички заявки"
|
||||
},
|
||||
"denyRequest": {
|
||||
"message": "Отхвърляне на заявката"
|
||||
},
|
||||
"approveRequest": {
|
||||
"message": "Одобряване на заявката"
|
||||
},
|
||||
"noDeviceRequests": {
|
||||
"message": "Няма заявки от устройства"
|
||||
},
|
||||
"noDeviceRequestsDesc": {
|
||||
"message": "Тук се показват заявките за одобрение на устройства от членовете"
|
||||
},
|
||||
"loginRequestDenied": {
|
||||
"message": "Заявката за вписване е отказана"
|
||||
},
|
||||
"allLoginRequestsDenied": {
|
||||
"message": "Всички заявки за вписване са отказани"
|
||||
},
|
||||
"loginRequestApproved": {
|
||||
"message": "Заявката за вписване е одобрена"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordTitle": {
|
||||
"message": "Потребителят няма главна парола"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordDesc": {
|
||||
"message": "Ако премахнете $USER$ без да настроите главна парола, този потребител може да загуби пълния достъп до регистрацията си. Наистина ли искате да продължите?",
|
||||
"placeholders": {
|
||||
"user": {
|
||||
"content": "$1",
|
||||
"example": "John Smith"
|
||||
}
|
||||
}
|
||||
},
|
||||
"noMasterPassword": {
|
||||
"message": "Няма главна парола"
|
||||
},
|
||||
"removeMembersWithoutMasterPasswordWarning": {
|
||||
"message": "Ако премахвате членове без да настроите главни пароли за тях, те може да загубят пълния достъп до регистрациите си."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6827,12 +6827,79 @@
|
||||
},
|
||||
"memberDecryptionTdeDescriptionEnd": {
|
||||
"message": "with automatic enrollment will turn on when this option is used.",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The account recovery administration policy with automatic enrollment will turn on when this option is used.'"
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The master password reset policy with automatic enrollment will turn on when this option is used.'"
|
||||
},
|
||||
"notFound": {
|
||||
"message": "$RESOURCE$ not found",
|
||||
"placeholders": {
|
||||
"resource": {
|
||||
"content": "$1",
|
||||
"example": "Service Account"
|
||||
}
|
||||
}
|
||||
},
|
||||
"recoverAccount": {
|
||||
"message": "Recover account"
|
||||
},
|
||||
"updatedTempPassword": {
|
||||
"message": "User updated a password issued through account recovery."
|
||||
},
|
||||
"yourOrganizationsFingerprint": {
|
||||
"message": "Your organization's fingerprint phrase",
|
||||
"description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their organization's public key with another user, for the purposes of sharing."
|
||||
},
|
||||
"deviceApprovals": {
|
||||
"message": "Device approvals"
|
||||
},
|
||||
"deviceApprovalsDesc": {
|
||||
"message": "Approve login requests below to allow the requesting member to finish logging in. Unapproved requests expire after 1 week. Verify the member’s information before approving."
|
||||
},
|
||||
"deviceInfo": {
|
||||
"message": "Device info"
|
||||
},
|
||||
"time": {
|
||||
"message": "Time"
|
||||
},
|
||||
"denyAllRequests": {
|
||||
"message": "Deny all requests"
|
||||
},
|
||||
"denyRequest": {
|
||||
"message": "Deny request"
|
||||
},
|
||||
"approveRequest": {
|
||||
"message": "Approve request"
|
||||
},
|
||||
"noDeviceRequests": {
|
||||
"message": "No device requests"
|
||||
},
|
||||
"noDeviceRequestsDesc": {
|
||||
"message": "Member device approval requests will appear here"
|
||||
},
|
||||
"loginRequestDenied": {
|
||||
"message": "Login request denied"
|
||||
},
|
||||
"allLoginRequestsDenied": {
|
||||
"message": "All login requests denied"
|
||||
},
|
||||
"loginRequestApproved": {
|
||||
"message": "Login request approved"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordTitle": {
|
||||
"message": "Account does not have master password"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordDesc": {
|
||||
"message": "Removing $USER$ without setting a master password for them may restrict access to their full account. Are you sure you want to continue?",
|
||||
"placeholders": {
|
||||
"user": {
|
||||
"content": "$1",
|
||||
"example": "John Smith"
|
||||
}
|
||||
}
|
||||
},
|
||||
"noMasterPassword": {
|
||||
"message": "No master password"
|
||||
},
|
||||
"removeMembersWithoutMasterPasswordWarning": {
|
||||
"message": "Removing members who do not have master passwords without setting one for them may restrict access to their full account."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6827,12 +6827,79 @@
|
||||
},
|
||||
"memberDecryptionTdeDescriptionEnd": {
|
||||
"message": "with automatic enrollment will turn on when this option is used.",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The account recovery administration policy with automatic enrollment will turn on when this option is used.'"
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The master password reset policy with automatic enrollment will turn on when this option is used.'"
|
||||
},
|
||||
"notFound": {
|
||||
"message": "$RESOURCE$ not found",
|
||||
"placeholders": {
|
||||
"resource": {
|
||||
"content": "$1",
|
||||
"example": "Service Account"
|
||||
}
|
||||
}
|
||||
},
|
||||
"recoverAccount": {
|
||||
"message": "Recover account"
|
||||
},
|
||||
"updatedTempPassword": {
|
||||
"message": "User updated a password issued through account recovery."
|
||||
},
|
||||
"yourOrganizationsFingerprint": {
|
||||
"message": "Your organization's fingerprint phrase",
|
||||
"description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their organization's public key with another user, for the purposes of sharing."
|
||||
},
|
||||
"deviceApprovals": {
|
||||
"message": "Device approvals"
|
||||
},
|
||||
"deviceApprovalsDesc": {
|
||||
"message": "Approve login requests below to allow the requesting member to finish logging in. Unapproved requests expire after 1 week. Verify the member’s information before approving."
|
||||
},
|
||||
"deviceInfo": {
|
||||
"message": "Device info"
|
||||
},
|
||||
"time": {
|
||||
"message": "Time"
|
||||
},
|
||||
"denyAllRequests": {
|
||||
"message": "Deny all requests"
|
||||
},
|
||||
"denyRequest": {
|
||||
"message": "Deny request"
|
||||
},
|
||||
"approveRequest": {
|
||||
"message": "Approve request"
|
||||
},
|
||||
"noDeviceRequests": {
|
||||
"message": "No device requests"
|
||||
},
|
||||
"noDeviceRequestsDesc": {
|
||||
"message": "Member device approval requests will appear here"
|
||||
},
|
||||
"loginRequestDenied": {
|
||||
"message": "Login request denied"
|
||||
},
|
||||
"allLoginRequestsDenied": {
|
||||
"message": "All login requests denied"
|
||||
},
|
||||
"loginRequestApproved": {
|
||||
"message": "Login request approved"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordTitle": {
|
||||
"message": "Account does not have master password"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordDesc": {
|
||||
"message": "Removing $USER$ without setting a master password for them may restrict access to their full account. Are you sure you want to continue?",
|
||||
"placeholders": {
|
||||
"user": {
|
||||
"content": "$1",
|
||||
"example": "John Smith"
|
||||
}
|
||||
}
|
||||
},
|
||||
"noMasterPassword": {
|
||||
"message": "No master password"
|
||||
},
|
||||
"removeMembersWithoutMasterPasswordWarning": {
|
||||
"message": "Removing members who do not have master passwords without setting one for them may restrict access to their full account."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6827,12 +6827,79 @@
|
||||
},
|
||||
"memberDecryptionTdeDescriptionEnd": {
|
||||
"message": "amb inscripció automàtica s'activarà quan s'utilitze aquesta opció.",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The account recovery administration policy with automatic enrollment will turn on when this option is used.'"
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The master password reset policy with automatic enrollment will turn on when this option is used.'"
|
||||
},
|
||||
"notFound": {
|
||||
"message": "No s'ha trobat $RESOURCE$",
|
||||
"placeholders": {
|
||||
"resource": {
|
||||
"content": "$1",
|
||||
"example": "Service Account"
|
||||
}
|
||||
}
|
||||
},
|
||||
"recoverAccount": {
|
||||
"message": "Recupera el compte"
|
||||
},
|
||||
"updatedTempPassword": {
|
||||
"message": "L'usuari ha actualitzat una contrasenya emesa mitjançant la recuperació del compte."
|
||||
},
|
||||
"yourOrganizationsFingerprint": {
|
||||
"message": "Frase d'empremta digital de l'organització",
|
||||
"description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their organization's public key with another user, for the purposes of sharing."
|
||||
},
|
||||
"deviceApprovals": {
|
||||
"message": "Aprovacions de dispositius"
|
||||
},
|
||||
"deviceApprovalsDesc": {
|
||||
"message": "Aprova les sol·licituds d'inici de sessió a continuació per permetre que el membre sol·licitant acabe d'iniciar la sessió. Les sol·licituds no aprovades caduquen al cap d'una setmana. Verifiqueu la informació del membre abans d'aprovar-les."
|
||||
},
|
||||
"deviceInfo": {
|
||||
"message": "Informació del dispositiu"
|
||||
},
|
||||
"time": {
|
||||
"message": "Hora"
|
||||
},
|
||||
"denyAllRequests": {
|
||||
"message": "Denega totes les sol·licituds"
|
||||
},
|
||||
"denyRequest": {
|
||||
"message": "Denega la sol·licitud"
|
||||
},
|
||||
"approveRequest": {
|
||||
"message": "Aprova la sol·licitud"
|
||||
},
|
||||
"noDeviceRequests": {
|
||||
"message": "No hi ha sol·licituds de dispositiu"
|
||||
},
|
||||
"noDeviceRequestsDesc": {
|
||||
"message": "Les sol·licituds d'aprovació del dispositiu dels membres es mostraran ací"
|
||||
},
|
||||
"loginRequestDenied": {
|
||||
"message": "S'ha denegat la sol·licitud d'inici de sessió"
|
||||
},
|
||||
"allLoginRequestsDenied": {
|
||||
"message": "S'han denegat totes les sol·licituds d'inici de sessió"
|
||||
},
|
||||
"loginRequestApproved": {
|
||||
"message": "S'ha aprovat la sol·licitud d'inici de sessió"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordTitle": {
|
||||
"message": "El compte no té contrasenya mestra"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordDesc": {
|
||||
"message": "La supressió de l'usuari/a $USER$ sense establir-li una contrasenya mestra pot restringir l'accés al seu compte complet. Esteu segur que voleu continuar?",
|
||||
"placeholders": {
|
||||
"user": {
|
||||
"content": "$1",
|
||||
"example": "John Smith"
|
||||
}
|
||||
}
|
||||
},
|
||||
"noMasterPassword": {
|
||||
"message": "Sense contrasenya mestra"
|
||||
},
|
||||
"removeMembersWithoutMasterPasswordWarning": {
|
||||
"message": "La supressió de membres que no tenen contrasenyes mestres sense establir-ne una pot restringir l'accés al seu compte complet."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6827,12 +6827,79 @@
|
||||
},
|
||||
"memberDecryptionTdeDescriptionEnd": {
|
||||
"message": "budou použity zásady obnovení účtu s automatickým zápisem.",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The account recovery administration policy with automatic enrollment will turn on when this option is used.'"
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The master password reset policy with automatic enrollment will turn on when this option is used.'"
|
||||
},
|
||||
"notFound": {
|
||||
"message": "$RESOURCE$ nebyl nalezen",
|
||||
"placeholders": {
|
||||
"resource": {
|
||||
"content": "$1",
|
||||
"example": "Service Account"
|
||||
}
|
||||
}
|
||||
},
|
||||
"recoverAccount": {
|
||||
"message": "Obnovit účet"
|
||||
},
|
||||
"updatedTempPassword": {
|
||||
"message": "Uživatel aktualizoval heslo vydané prostřednictvím obnovení účtu."
|
||||
},
|
||||
"yourOrganizationsFingerprint": {
|
||||
"message": "Fráze otisku prstu Vaší organizace",
|
||||
"description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their organization's public key with another user, for the purposes of sharing."
|
||||
},
|
||||
"deviceApprovals": {
|
||||
"message": "Schválení zařízení"
|
||||
},
|
||||
"deviceApprovalsDesc": {
|
||||
"message": "Abyste umožnili žádajícímu členovi dokončit přihlášení, schvalte níže uvedené žádosti o přihlášení. Platnost neschválených žádostí vyprší po 1 týdnu. Před schválením ověřte údaje člena."
|
||||
},
|
||||
"deviceInfo": {
|
||||
"message": "Informace o zařízení"
|
||||
},
|
||||
"time": {
|
||||
"message": "Čas"
|
||||
},
|
||||
"denyAllRequests": {
|
||||
"message": "Odmítnout všechny žádosti"
|
||||
},
|
||||
"denyRequest": {
|
||||
"message": "Odmítnout žádost"
|
||||
},
|
||||
"approveRequest": {
|
||||
"message": "Schválit žádost"
|
||||
},
|
||||
"noDeviceRequests": {
|
||||
"message": "Žádné žádosti ze zařízení"
|
||||
},
|
||||
"noDeviceRequestsDesc": {
|
||||
"message": "Zde se zobrazí žádosti o schválení zařízení člena"
|
||||
},
|
||||
"loginRequestDenied": {
|
||||
"message": "Žádost o přihlášení zamítnuta"
|
||||
},
|
||||
"allLoginRequestsDenied": {
|
||||
"message": "Všechny žádosti o přihlášení zamítnuty"
|
||||
},
|
||||
"loginRequestApproved": {
|
||||
"message": "Žádost o přihlášení schválena"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordTitle": {
|
||||
"message": "Účet nemá hlavní heslo"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordDesc": {
|
||||
"message": "Odebrání $USER$ bez nastavení hlavního hesla může uživateli omezit přístup k jeho celému účtu. Opravdu chcete pokračovat?",
|
||||
"placeholders": {
|
||||
"user": {
|
||||
"content": "$1",
|
||||
"example": "John Smith"
|
||||
}
|
||||
}
|
||||
},
|
||||
"noMasterPassword": {
|
||||
"message": "Žádné hlavní heslo"
|
||||
},
|
||||
"removeMembersWithoutMasterPasswordWarning": {
|
||||
"message": "Odebrání členů bez nastavení jejich hlavních hesel jim může omezit přístup k jejich celým účtům."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6827,12 +6827,79 @@
|
||||
},
|
||||
"memberDecryptionTdeDescriptionEnd": {
|
||||
"message": "with automatic enrollment will turn on when this option is used.",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The account recovery administration policy with automatic enrollment will turn on when this option is used.'"
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The master password reset policy with automatic enrollment will turn on when this option is used.'"
|
||||
},
|
||||
"notFound": {
|
||||
"message": "$RESOURCE$ not found",
|
||||
"placeholders": {
|
||||
"resource": {
|
||||
"content": "$1",
|
||||
"example": "Service Account"
|
||||
}
|
||||
}
|
||||
},
|
||||
"recoverAccount": {
|
||||
"message": "Recover account"
|
||||
},
|
||||
"updatedTempPassword": {
|
||||
"message": "User updated a password issued through account recovery."
|
||||
},
|
||||
"yourOrganizationsFingerprint": {
|
||||
"message": "Your organization's fingerprint phrase",
|
||||
"description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their organization's public key with another user, for the purposes of sharing."
|
||||
},
|
||||
"deviceApprovals": {
|
||||
"message": "Device approvals"
|
||||
},
|
||||
"deviceApprovalsDesc": {
|
||||
"message": "Approve login requests below to allow the requesting member to finish logging in. Unapproved requests expire after 1 week. Verify the member’s information before approving."
|
||||
},
|
||||
"deviceInfo": {
|
||||
"message": "Device info"
|
||||
},
|
||||
"time": {
|
||||
"message": "Time"
|
||||
},
|
||||
"denyAllRequests": {
|
||||
"message": "Deny all requests"
|
||||
},
|
||||
"denyRequest": {
|
||||
"message": "Deny request"
|
||||
},
|
||||
"approveRequest": {
|
||||
"message": "Approve request"
|
||||
},
|
||||
"noDeviceRequests": {
|
||||
"message": "No device requests"
|
||||
},
|
||||
"noDeviceRequestsDesc": {
|
||||
"message": "Member device approval requests will appear here"
|
||||
},
|
||||
"loginRequestDenied": {
|
||||
"message": "Login request denied"
|
||||
},
|
||||
"allLoginRequestsDenied": {
|
||||
"message": "All login requests denied"
|
||||
},
|
||||
"loginRequestApproved": {
|
||||
"message": "Login request approved"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordTitle": {
|
||||
"message": "Account does not have master password"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordDesc": {
|
||||
"message": "Removing $USER$ without setting a master password for them may restrict access to their full account. Are you sure you want to continue?",
|
||||
"placeholders": {
|
||||
"user": {
|
||||
"content": "$1",
|
||||
"example": "John Smith"
|
||||
}
|
||||
}
|
||||
},
|
||||
"noMasterPassword": {
|
||||
"message": "No master password"
|
||||
},
|
||||
"removeMembersWithoutMasterPasswordWarning": {
|
||||
"message": "Removing members who do not have master passwords without setting one for them may restrict access to their full account."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6827,12 +6827,79 @@
|
||||
},
|
||||
"memberDecryptionTdeDescriptionEnd": {
|
||||
"message": "med automatisk indrullering aktiveres ved brug af denne indstilling.",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The account recovery administration policy with automatic enrollment will turn on when this option is used.'"
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The master password reset policy with automatic enrollment will turn on when this option is used.'"
|
||||
},
|
||||
"notFound": {
|
||||
"message": "$RESOURCE$ ikke fundet",
|
||||
"placeholders": {
|
||||
"resource": {
|
||||
"content": "$1",
|
||||
"example": "Service Account"
|
||||
}
|
||||
}
|
||||
},
|
||||
"recoverAccount": {
|
||||
"message": "Gendan konto"
|
||||
},
|
||||
"updatedTempPassword": {
|
||||
"message": "Bruger har opdateret en adgangskode udstedt via kontogendannelse."
|
||||
},
|
||||
"yourOrganizationsFingerprint": {
|
||||
"message": "Din organisations fingeraftrykssætning",
|
||||
"description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their organization's public key with another user, for the purposes of sharing."
|
||||
},
|
||||
"deviceApprovals": {
|
||||
"message": "Enhedsgodkendelser"
|
||||
},
|
||||
"deviceApprovalsDesc": {
|
||||
"message": "Godkend login-anmodninger nedenfor, så anmodende medlemmer kan fuldføre login-processen. Ikke-godkendte anmodninger udløber efter 1 uge. Bekræft medlemmets oplysninger før godkendelse."
|
||||
},
|
||||
"deviceInfo": {
|
||||
"message": "Enhedsinfo"
|
||||
},
|
||||
"time": {
|
||||
"message": "Tid"
|
||||
},
|
||||
"denyAllRequests": {
|
||||
"message": "Afvis alle anmodninger"
|
||||
},
|
||||
"denyRequest": {
|
||||
"message": "Afvis anmodning"
|
||||
},
|
||||
"approveRequest": {
|
||||
"message": "Godkend anmodning"
|
||||
},
|
||||
"noDeviceRequests": {
|
||||
"message": "Ingen enhedsanmodninger"
|
||||
},
|
||||
"noDeviceRequestsDesc": {
|
||||
"message": "Medlemmers enhedsgodkendelsesanmodninger vil fremgå her"
|
||||
},
|
||||
"loginRequestDenied": {
|
||||
"message": "Login-anmodning afvist"
|
||||
},
|
||||
"allLoginRequestsDenied": {
|
||||
"message": "Alle login-anmodninger afvist"
|
||||
},
|
||||
"loginRequestApproved": {
|
||||
"message": "Login-anmodning godkendt"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordTitle": {
|
||||
"message": "Konto har ikke hovedadgangskode"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordDesc": {
|
||||
"message": "Fjernelse af $USER$ uden opsætning af en hovedadgangskode for brugeren kan begrænse den fulde kontoadgang. Fortsæt alligevel?",
|
||||
"placeholders": {
|
||||
"user": {
|
||||
"content": "$1",
|
||||
"example": "John Smith"
|
||||
}
|
||||
}
|
||||
},
|
||||
"noMasterPassword": {
|
||||
"message": "Ingen hovedadgangskode"
|
||||
},
|
||||
"removeMembersWithoutMasterPasswordWarning": {
|
||||
"message": "Fjernelse af medlemmer uden hovedadgangskoder uden at opsætte én for dem, kan begrænse den fulde kontoadgang."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6827,12 +6827,79 @@
|
||||
},
|
||||
"memberDecryptionTdeDescriptionEnd": {
|
||||
"message": "mit automatischer Registrierung wird aktiviert, wenn diese Option verwendet wird.",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The account recovery administration policy with automatic enrollment will turn on when this option is used.'"
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The master password reset policy with automatic enrollment will turn on when this option is used.'"
|
||||
},
|
||||
"notFound": {
|
||||
"message": "$RESOURCE$ nicht gefunden",
|
||||
"placeholders": {
|
||||
"resource": {
|
||||
"content": "$1",
|
||||
"example": "Service Account"
|
||||
}
|
||||
}
|
||||
},
|
||||
"recoverAccount": {
|
||||
"message": "Konto wiederherstellen"
|
||||
},
|
||||
"updatedTempPassword": {
|
||||
"message": "Der Benutzer hat ein Passwort aktualisiert, das durch die Kontowiederherstellung ausgestellt wurde."
|
||||
},
|
||||
"yourOrganizationsFingerprint": {
|
||||
"message": "Fingerabdruck-Phrase deiner Organisation",
|
||||
"description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their organization's public key with another user, for the purposes of sharing."
|
||||
},
|
||||
"deviceApprovals": {
|
||||
"message": "Geräte-Genehmigungen"
|
||||
},
|
||||
"deviceApprovalsDesc": {
|
||||
"message": "Bestätige die Anmeldeanfragen unten, damit das anfragende Mitglied die Anmeldung abschließen kann. Nicht genehmigte Anfragen laufen nach einer Woche ab. Überprüfe die Informationen des Mitglieds vor der Genehmigung."
|
||||
},
|
||||
"deviceInfo": {
|
||||
"message": "Geräteinformation"
|
||||
},
|
||||
"time": {
|
||||
"message": "Zeit"
|
||||
},
|
||||
"denyAllRequests": {
|
||||
"message": "Alle Anfragen ablehnen"
|
||||
},
|
||||
"denyRequest": {
|
||||
"message": "Anfrage ablehnen"
|
||||
},
|
||||
"approveRequest": {
|
||||
"message": "Anfrage genehmigen"
|
||||
},
|
||||
"noDeviceRequests": {
|
||||
"message": "Keine Geräteanfragen"
|
||||
},
|
||||
"noDeviceRequestsDesc": {
|
||||
"message": "Geräte-Genehmigungsanfragen von Mitgliedern werden hier erscheinen"
|
||||
},
|
||||
"loginRequestDenied": {
|
||||
"message": "Anmeldeanfrage abgelehnt"
|
||||
},
|
||||
"allLoginRequestsDenied": {
|
||||
"message": "Alle Anmeldeanfragen abgelehnt"
|
||||
},
|
||||
"loginRequestApproved": {
|
||||
"message": "Anmeldeanfrage genehmigt"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordTitle": {
|
||||
"message": "Konto hat kein Master-Passwort"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordDesc": {
|
||||
"message": "$USER$ zu entfernen, ohne ein Master-Passwort zu setzen, könnte den Zugang zum vollen Konto einschränken. Bist du sicher, dass du fortfahren möchtest?",
|
||||
"placeholders": {
|
||||
"user": {
|
||||
"content": "$1",
|
||||
"example": "John Smith"
|
||||
}
|
||||
}
|
||||
},
|
||||
"noMasterPassword": {
|
||||
"message": "Kein Master-Passwort"
|
||||
},
|
||||
"removeMembersWithoutMasterPasswordWarning": {
|
||||
"message": "Mitglieder ohne Master-Passwort zu entfernen, ohne ein solches zu setzen, kann den Zugang zu deren vollem Konto einschränken."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6827,12 +6827,79 @@
|
||||
},
|
||||
"memberDecryptionTdeDescriptionEnd": {
|
||||
"message": "with automatic enrollment will turn on when this option is used.",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The account recovery administration policy with automatic enrollment will turn on when this option is used.'"
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The master password reset policy with automatic enrollment will turn on when this option is used.'"
|
||||
},
|
||||
"notFound": {
|
||||
"message": "$RESOURCE$ not found",
|
||||
"placeholders": {
|
||||
"resource": {
|
||||
"content": "$1",
|
||||
"example": "Service Account"
|
||||
}
|
||||
}
|
||||
},
|
||||
"recoverAccount": {
|
||||
"message": "Recover account"
|
||||
},
|
||||
"updatedTempPassword": {
|
||||
"message": "User updated a password issued through account recovery."
|
||||
},
|
||||
"yourOrganizationsFingerprint": {
|
||||
"message": "Your organization's fingerprint phrase",
|
||||
"description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their organization's public key with another user, for the purposes of sharing."
|
||||
},
|
||||
"deviceApprovals": {
|
||||
"message": "Device approvals"
|
||||
},
|
||||
"deviceApprovalsDesc": {
|
||||
"message": "Approve login requests below to allow the requesting member to finish logging in. Unapproved requests expire after 1 week. Verify the member’s information before approving."
|
||||
},
|
||||
"deviceInfo": {
|
||||
"message": "Device info"
|
||||
},
|
||||
"time": {
|
||||
"message": "Time"
|
||||
},
|
||||
"denyAllRequests": {
|
||||
"message": "Deny all requests"
|
||||
},
|
||||
"denyRequest": {
|
||||
"message": "Deny request"
|
||||
},
|
||||
"approveRequest": {
|
||||
"message": "Approve request"
|
||||
},
|
||||
"noDeviceRequests": {
|
||||
"message": "No device requests"
|
||||
},
|
||||
"noDeviceRequestsDesc": {
|
||||
"message": "Member device approval requests will appear here"
|
||||
},
|
||||
"loginRequestDenied": {
|
||||
"message": "Login request denied"
|
||||
},
|
||||
"allLoginRequestsDenied": {
|
||||
"message": "All login requests denied"
|
||||
},
|
||||
"loginRequestApproved": {
|
||||
"message": "Login request approved"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordTitle": {
|
||||
"message": "Account does not have master password"
|
||||
},
|
||||
"removeOrgUserNoMasterPasswordDesc": {
|
||||
"message": "Removing $USER$ without setting a master password for them may restrict access to their full account. Are you sure you want to continue?",
|
||||
"placeholders": {
|
||||
"user": {
|
||||
"content": "$1",
|
||||
"example": "John Smith"
|
||||
}
|
||||
}
|
||||
},
|
||||
"noMasterPassword": {
|
||||
"message": "No master password"
|
||||
},
|
||||
"removeMembersWithoutMasterPasswordWarning": {
|
||||
"message": "Removing members who do not have master passwords without setting one for them may restrict access to their full account."
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user