1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-21 02:33:46 +00:00
Files
browser/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.ts
renovate[bot] 28de9439be [deps] Autofill: Update prettier to v3 (#7014)
* [deps] Autofill: Update prettier to v3

* prettier formatting updates

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Prusik <jprusik@classynemesis.com>
2023-11-29 16:15:20 -05:00

315 lines
9.1 KiB
TypeScript

import { Component, OnDestroy, OnInit } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
import {
map,
Observable,
switchMap,
Subject,
takeUntil,
combineLatest,
startWith,
distinctUntilChanged,
take,
share,
} from "rxjs";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { DialogService } from "@bitwarden/components";
import { ProjectListView } from "../models/view/project-list.view";
import { SecretListView } from "../models/view/secret-list.view";
import {
ProjectDeleteDialogComponent,
ProjectDeleteOperation,
} from "../projects/dialog/project-delete-dialog.component";
import {
ProjectDialogComponent,
ProjectOperation,
} from "../projects/dialog/project-dialog.component";
import { ProjectService } from "../projects/project.service";
import {
SecretDeleteDialogComponent,
SecretDeleteOperation,
} from "../secrets/dialog/secret-delete.component";
import {
OperationType,
SecretDialogComponent,
SecretOperation,
} from "../secrets/dialog/secret-dialog.component";
import { SecretService } from "../secrets/secret.service";
import {
ServiceAccountDialogComponent,
ServiceAccountOperation,
} from "../service-accounts/dialog/service-account-dialog.component";
import { ServiceAccountService } from "../service-accounts/service-account.service";
import { SecretsListComponent } from "../shared/secrets-list.component";
type Tasks = {
[organizationId: string]: OrganizationTasks;
};
type OrganizationTasks = {
importSecrets: boolean;
createSecret: boolean;
createProject: boolean;
createServiceAccount: boolean;
};
@Component({
selector: "sm-overview",
templateUrl: "./overview.component.html",
})
export class OverviewComponent implements OnInit, OnDestroy {
private destroy$: Subject<void> = new Subject<void>();
private tableSize = 10;
private organizationId: string;
protected organizationName: string;
protected userIsAdmin: boolean;
protected showOnboarding = false;
protected loading = true;
protected organizationEnabled = false;
protected view$: Observable<{
allProjects: ProjectListView[];
allSecrets: SecretListView[];
latestProjects: ProjectListView[];
latestSecrets: SecretListView[];
tasks: OrganizationTasks;
}>;
constructor(
private route: ActivatedRoute,
private projectService: ProjectService,
private secretService: SecretService,
private serviceAccountService: ServiceAccountService,
private dialogService: DialogService,
private organizationService: OrganizationService,
private stateService: StateService,
private platformUtilsService: PlatformUtilsService,
private i18nService: I18nService,
) {}
ngOnInit() {
const orgId$ = this.route.params.pipe(
map((p) => p.organizationId),
distinctUntilChanged(),
);
orgId$
.pipe(
map((orgId) => this.organizationService.get(orgId)),
takeUntil(this.destroy$),
)
.subscribe((org) => {
this.organizationId = org.id;
this.organizationName = org.name;
this.userIsAdmin = org.isAdmin;
this.loading = true;
this.organizationEnabled = org.enabled;
});
const projects$ = combineLatest([
orgId$,
this.projectService.project$.pipe(startWith(null)),
]).pipe(
switchMap(([orgId]) => this.projectService.getProjects(orgId)),
share(),
);
const secrets$ = combineLatest([
orgId$,
this.secretService.secret$.pipe(startWith(null)),
this.projectService.project$.pipe(startWith(null)),
]).pipe(
switchMap(([orgId]) => this.secretService.getSecrets(orgId)),
share(),
);
const serviceAccounts$ = combineLatest([
orgId$,
this.serviceAccountService.serviceAccount$.pipe(startWith(null)),
]).pipe(
switchMap(([orgId]) => this.serviceAccountService.getServiceAccounts(orgId, false)),
share(),
);
this.view$ = orgId$.pipe(
switchMap((orgId) =>
combineLatest([projects$, secrets$, serviceAccounts$]).pipe(
switchMap(async ([projects, secrets, serviceAccounts]) => ({
latestProjects: this.getRecentItems(projects, this.tableSize),
latestSecrets: this.getRecentItems(secrets, this.tableSize),
allProjects: projects,
allSecrets: secrets,
tasks: await this.saveCompletedTasks(orgId, {
importSecrets: secrets.length > 0,
createSecret: secrets.length > 0,
createProject: projects.length > 0,
createServiceAccount: serviceAccounts.length > 0,
}),
})),
),
),
);
// Refresh onboarding status when orgId changes by fetching the first value from view$.
orgId$
.pipe(
switchMap(() => this.view$.pipe(take(1))),
takeUntil(this.destroy$),
)
.subscribe((view) => {
this.showOnboarding = Object.values(view.tasks).includes(false);
this.loading = false;
});
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
private getRecentItems<T extends { revisionDate: string }[]>(items: T, length: number): T {
return items
.sort((a, b) => {
return new Date(b.revisionDate).getTime() - new Date(a.revisionDate).getTime();
})
.slice(0, length) as T;
}
private async saveCompletedTasks(
organizationId: string,
orgTasks: OrganizationTasks,
): Promise<OrganizationTasks> {
const prevTasks = ((await this.stateService.getSMOnboardingTasks()) || {}) as Tasks;
const newlyCompletedOrgTasks = Object.fromEntries(
Object.entries(orgTasks).filter(([_k, v]) => v === true),
);
const nextOrgTasks = {
importSecrets: false,
createSecret: false,
createProject: false,
createServiceAccount: false,
...prevTasks[organizationId],
...newlyCompletedOrgTasks,
};
this.stateService.setSMOnboardingTasks({
...prevTasks,
[organizationId]: nextOrgTasks,
});
return nextOrgTasks as OrganizationTasks;
}
// Projects ---
openEditProject(projectId: string) {
this.dialogService.open<unknown, ProjectOperation>(ProjectDialogComponent, {
data: {
organizationId: this.organizationId,
operation: OperationType.Edit,
organizationEnabled: this.organizationEnabled,
projectId: projectId,
},
});
}
openNewProjectDialog() {
this.dialogService.open<unknown, ProjectOperation>(ProjectDialogComponent, {
data: {
organizationId: this.organizationId,
operation: OperationType.Add,
organizationEnabled: this.organizationEnabled,
},
});
}
openServiceAccountDialog() {
this.dialogService.open<unknown, ServiceAccountOperation>(ServiceAccountDialogComponent, {
data: {
organizationId: this.organizationId,
operation: OperationType.Add,
organizationEnabled: this.organizationEnabled,
},
});
}
openDeleteProjectDialog(event: ProjectListView[]) {
this.dialogService.open<unknown, ProjectDeleteOperation>(ProjectDeleteDialogComponent, {
data: {
projects: event,
},
});
}
// Secrets ---
openSecretDialog() {
this.dialogService.open<unknown, SecretOperation>(SecretDialogComponent, {
data: {
organizationId: this.organizationId,
operation: OperationType.Add,
organizationEnabled: this.organizationEnabled,
},
});
}
openEditSecret(secretId: string) {
this.dialogService.open<unknown, SecretOperation>(SecretDialogComponent, {
data: {
organizationId: this.organizationId,
operation: OperationType.Edit,
secretId: secretId,
organizationEnabled: this.organizationEnabled,
},
});
}
openDeleteSecret(event: SecretListView[]) {
this.dialogService.open<unknown, SecretDeleteOperation>(SecretDeleteDialogComponent, {
data: {
secrets: event,
},
});
}
openNewSecretDialog() {
this.dialogService.open<unknown, SecretOperation>(SecretDialogComponent, {
data: {
organizationId: this.organizationId,
operation: OperationType.Add,
organizationEnabled: this.organizationEnabled,
},
});
}
copySecretName(name: string) {
SecretsListComponent.copySecretName(name, this.platformUtilsService, this.i18nService);
}
copySecretValue(id: string) {
SecretsListComponent.copySecretValue(
id,
this.platformUtilsService,
this.i18nService,
this.secretService,
);
}
copySecretUuid(id: string) {
SecretsListComponent.copySecretUuid(id, this.platformUtilsService, this.i18nService);
}
protected hideOnboarding() {
this.showOnboarding = false;
this.saveCompletedTasks(this.organizationId, {
importSecrets: true,
createSecret: true,
createProject: true,
createServiceAccount: true,
});
}
}