[SM-749] Redirect to SA list if SA isn't found (#5511)

* redirect if SA isn't found

* refactor to use getByServiceAccountId

* add error toasts
This commit is contained in:
Will Martin 2023-06-05 10:40:41 -04:00 committed by GitHub
parent a3110f89fc
commit f913d8b6be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 79 additions and 27 deletions

View File

@ -6828,7 +6828,16 @@
}, },
"memberDecryptionTdeDescriptionEnd": { "memberDecryptionTdeDescriptionEnd": {
"message": "with automatic enrollment will turn on when this option is used.", "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": { "recoverAccount": {
"message": "Recover account" "message": "Recover account"

View File

@ -3,6 +3,7 @@ import { ActivatedRoute, Router } from "@angular/router";
import { import {
catchError, catchError,
combineLatest, combineLatest,
EMPTY,
filter, filter,
Observable, Observable,
startWith, startWith,
@ -12,6 +13,8 @@ import {
} from "rxjs"; } from "rxjs";
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { ProjectView } from "../../models/view/project.view"; import { ProjectView } from "../../models/view/project.view";
import { import {
@ -37,7 +40,9 @@ export class ProjectComponent implements OnInit, OnDestroy {
private route: ActivatedRoute, private route: ActivatedRoute,
private projectService: ProjectService, private projectService: ProjectService,
private router: Router, private router: Router,
private dialogService: DialogServiceAbstraction private dialogService: DialogServiceAbstraction,
private platformUtilsService: PlatformUtilsService,
private i18nService: I18nService
) {} ) {}
ngOnInit(): void { ngOnInit(): void {
@ -48,10 +53,17 @@ export class ProjectComponent implements OnInit, OnDestroy {
); );
this.project$ = combineLatest([this.route.params, currentProjectEdited]).pipe( this.project$ = combineLatest([this.route.params, currentProjectEdited]).pipe(
switchMap(([params, _]) => { switchMap(([params, _]) => this.projectService.getByProjectId(params.projectId)),
return this.projectService.getByProjectId(params.projectId); catchError(() => {
}), this.router.navigate(["/sm", this.organizationId, "projects"]).then(() => {
catchError(async () => this.handleError()) this.platformUtilsService.showToast(
"error",
null,
this.i18nService.t("notFound", this.i18nService.t("project"))
);
});
return EMPTY;
})
); );
this.route.params.pipe(takeUntil(this.destroy$)).subscribe((params) => { this.route.params.pipe(takeUntil(this.destroy$)).subscribe((params) => {
@ -60,12 +72,6 @@ export class ProjectComponent implements OnInit, OnDestroy {
}); });
} }
handleError = () => {
const projectsListUrl = `/sm/${this.organizationId}/projects/`;
this.router.navigate([projectsListUrl]);
return new ProjectView();
};
ngOnDestroy(): void { ngOnDestroy(): void {
this.destroy$.next(); this.destroy$.next();
this.destroy$.complete(); this.destroy$.complete();

View File

@ -1,8 +1,19 @@
import { Component } from "@angular/core"; import { Component, OnDestroy, OnInit } from "@angular/core";
import { ActivatedRoute } from "@angular/router"; import { ActivatedRoute, Router } from "@angular/router";
import { switchMap } from "rxjs"; import {
EMPTY,
Subject,
catchError,
combineLatest,
filter,
startWith,
switchMap,
takeUntil,
} from "rxjs";
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { AccessTokenCreateDialogComponent } from "./access/dialogs/access-token-create-dialog.component"; import { AccessTokenCreateDialogComponent } from "./access/dialogs/access-token-create-dialog.component";
import { ServiceAccountService } from "./service-account.service"; import { ServiceAccountService } from "./service-account.service";
@ -11,30 +22,56 @@ import { ServiceAccountService } from "./service-account.service";
selector: "sm-service-account", selector: "sm-service-account",
templateUrl: "./service-account.component.html", templateUrl: "./service-account.component.html",
}) })
export class ServiceAccountComponent { export class ServiceAccountComponent implements OnInit, OnDestroy {
private destroy$ = new Subject<void>();
private organizationId: string; private organizationId: string;
private serviceAccountId: string; private serviceAccountId: string;
/** private onChange$ = this.serviceAccountService.serviceAccount$.pipe(
* TODO: remove when a server method is available that fetches a service account by ID filter((sa) => sa?.id === this.serviceAccountId),
*/ startWith(null)
protected serviceAccount$ = this.route.params.pipe( );
switchMap((params) => {
this.serviceAccountId = params.serviceAccountId;
this.organizationId = params.organizationId;
return this.serviceAccountService protected serviceAccount$ = combineLatest([this.route.params, this.onChange$]).pipe(
.getServiceAccounts(params.organizationId) switchMap(([params, _]) =>
.then((saList) => saList.find((sa) => sa.id === params.serviceAccountId)); this.serviceAccountService.getByServiceAccountId(
params.serviceAccountId,
params.organizationId
)
),
catchError(() => {
this.router.navigate(["/sm", this.organizationId, "service-accounts"]).then(() => {
this.platformUtilsService.showToast(
"error",
null,
this.i18nService.t("notFound", this.i18nService.t("serviceAccount"))
);
});
return EMPTY;
}) })
); );
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private serviceAccountService: ServiceAccountService, private serviceAccountService: ServiceAccountService,
private dialogService: DialogServiceAbstraction private dialogService: DialogServiceAbstraction,
private router: Router,
private platformUtilsService: PlatformUtilsService,
private i18nService: I18nService
) {} ) {}
ngOnInit(): void {
this.route.params.pipe(takeUntil(this.destroy$)).subscribe((params) => {
this.serviceAccountId = params.serviceAccountId;
this.organizationId = params.organizationId;
});
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
protected openNewAccessTokenDialog() { protected openNewAccessTokenDialog() {
AccessTokenCreateDialogComponent.openNewAccessTokenDialog( AccessTokenCreateDialogComponent.openNewAccessTokenDialog(
this.dialogService, this.dialogService,