[SM-810] remove token permission UI (#5681)

* Remove permission field from access token dialog; remove unused i18n key

* remove permissions column from access token table

* fix SA name placehold in access token dialog

* remove comment

* pass SA view into dialog upon opening
This commit is contained in:
Will Martin 2023-06-28 14:57:42 -04:00 committed by GitHub
parent 300fade281
commit 6530680b8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 53 additions and 64 deletions

View File

@ -6195,10 +6195,6 @@
"message": "Access token created and copied to clipboard",
"description": "Notification to inform the user that the access token has been created and copied to the clipboard."
},
"accessTokenPermissionsBetaNotification": {
"message": "Permissions management is unavailable for beta.",
"description": "Notification to inform the user that the feature for managing access token permissions is not available in the beta version."
},
"revokeAccessToken": {
"message": "Revoke access token",
"description": "Invalidates / cancels an access token and as such removes access to secrets for the client application."

View File

@ -32,7 +32,6 @@
</label>
</th>
<th bitCell>{{ "name" | i18n }}</th>
<th bitCell>{{ "permissions" | i18n }}</th>
<th bitCell>{{ "expires" | i18n }}</th>
<th bitCell>{{ "lastEdited" | i18n }}</th>
<th bitCell class="tw-w-0">
@ -57,7 +56,6 @@
/>
</td>
<td bitCell>{{ token.name }}</td>
<td bitCell>{{ permission(token) | i18n }}</td>
<td bitCell>
{{ token.expireAt === null ? ("never" | i18n) : (token.expireAt | date : "medium") }}
</td>

View File

@ -39,8 +39,4 @@ export class AccessListComponent {
const selected = this.tokens.filter((s) => this.selection.selected.includes(s.id));
this.revokeAccessTokensEvent.emit(selected);
}
protected permission(token: AccessTokenView) {
return "canRead";
}
}

View File

@ -1,6 +1,14 @@
import { Component, OnInit } from "@angular/core";
import { Component, OnDestroy, OnInit } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
import { combineLatestWith, firstValueFrom, Observable, startWith, switchMap } from "rxjs";
import {
combineLatestWith,
firstValueFrom,
Observable,
startWith,
Subject,
switchMap,
takeUntil,
} from "rxjs";
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
import { ModalService } from "@bitwarden/angular/services/modal.service";
@ -8,7 +16,9 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { openUserVerificationPrompt } from "@bitwarden/web-vault/app/auth/shared/components/user-verification";
import { ServiceAccountView } from "../../models/view/service-account.view";
import { AccessTokenView } from "../models/view/access-token.view";
import { ServiceAccountService } from "../service-account.service";
import { AccessService } from "./access.service";
import { AccessTokenCreateDialogComponent } from "./dialogs/access-token-create-dialog.component";
@ -17,11 +27,11 @@ import { AccessTokenCreateDialogComponent } from "./dialogs/access-token-create-
selector: "sm-access-tokens",
templateUrl: "./access-tokens.component.html",
})
export class AccessTokenComponent implements OnInit {
export class AccessTokenComponent implements OnInit, OnDestroy {
accessTokens$: Observable<AccessTokenView[]>;
private serviceAccountId: string;
private organizationId: string;
private destroy$ = new Subject<void>();
private serviceAccountView: ServiceAccountView;
constructor(
private route: ActivatedRoute,
@ -29,19 +39,39 @@ export class AccessTokenComponent implements OnInit {
private dialogService: DialogServiceAbstraction,
private modalService: ModalService,
private platformUtilsService: PlatformUtilsService,
private i18nService: I18nService
private i18nService: I18nService,
private serviceAccountService: ServiceAccountService
) {}
ngOnInit() {
this.accessTokens$ = this.accessService.accessToken$.pipe(
startWith(null),
combineLatestWith(this.route.params),
switchMap(async ([_, params]) => {
this.organizationId = params.organizationId;
this.serviceAccountId = params.serviceAccountId;
return await this.getAccessTokens();
})
switchMap(async ([_, params]) =>
this.accessService.getAccessTokens(params.organizationId, params.serviceAccountId)
)
);
this.serviceAccountService.serviceAccount$
.pipe(
startWith(null),
combineLatestWith(this.route.params),
switchMap(([_, params]) =>
this.serviceAccountService.getByServiceAccountId(
params.serviceAccountId,
params.organizationId
)
),
takeUntil(this.destroy$)
)
.subscribe((serviceAccountView) => {
this.serviceAccountView = serviceAccountView;
});
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
protected async revoke(tokens: AccessTokenView[]) {
@ -59,7 +89,7 @@ export class AccessTokenComponent implements OnInit {
}
await this.accessService.revokeAccessTokens(
this.serviceAccountId,
this.serviceAccountView.id,
tokens.map((t) => t.id)
);
@ -69,8 +99,7 @@ export class AccessTokenComponent implements OnInit {
protected openNewAccessTokenDialog() {
AccessTokenCreateDialogComponent.openNewAccessTokenDialog(
this.dialogService,
this.serviceAccountId,
this.organizationId
this.serviceAccountView
);
}
@ -89,8 +118,4 @@ export class AccessTokenComponent implements OnInit {
return firstValueFrom(ref.closed);
}
private async getAccessTokens(): Promise<AccessTokenView[]> {
return await this.accessService.getAccessTokens(this.organizationId, this.serviceAccountId);
}
}

View File

@ -12,19 +12,6 @@
<bit-label>{{ "name" | i18n }}</bit-label>
<input bitInput formControlName="name" />
</bit-form-field>
<div class="tw-mb-6">
<bit-form-field class="tw-mb-0">
<bit-label>{{ "permissions" | i18n }}</bit-label>
<select bitInput disabled>
<option selected value="canRead">
{{ "canRead" | i18n }}
</option>
</select>
</bit-form-field>
<span class="tw-text-sm tw-text-muted">
{{ "accessTokenPermissionsBetaNotification" | i18n }}
</span>
</div>
<sm-expiration-options
formControlName="expirationDateControl"
[expirationDayOptions]="expirationDayOptions"

View File

@ -3,7 +3,6 @@ import { Component, Inject, OnInit } from "@angular/core";
import { FormControl, FormGroup, Validators } from "@angular/forms";
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { BitValidators } from "@bitwarden/components";
import { ServiceAccountView } from "../../../models/view/service-account.view";
@ -13,7 +12,6 @@ import { AccessService } from "../access.service";
import { AccessTokenDetails, AccessTokenDialogComponent } from "./access-token-dialog.component";
export interface AccessTokenOperation {
organizationId: string;
serviceAccountView: ServiceAccountView;
}
@ -35,17 +33,12 @@ export class AccessTokenCreateDialogComponent implements OnInit {
constructor(
public dialogRef: DialogRef,
@Inject(DIALOG_DATA) public data: AccessTokenOperation,
private i18nService: I18nService,
private dialogService: DialogServiceAbstraction,
private accessService: AccessService
) {}
async ngOnInit() {
if (
!this.data.organizationId ||
!this.data.serviceAccountView?.id ||
!this.data.serviceAccountView?.name
) {
if (!this.data.serviceAccountView) {
this.dialogRef.close();
throw new Error(
`The access token create dialog was not called with the appropriate operation values.`
@ -62,7 +55,7 @@ export class AccessTokenCreateDialogComponent implements OnInit {
accessTokenView.name = this.formGroup.value.name;
accessTokenView.expireAt = this.formGroup.value.expirationDateControl;
const accessToken = await this.accessService.createAccessToken(
this.data.organizationId,
this.data.serviceAccountView.organizationId,
this.data.serviceAccountView.id,
accessTokenView
);
@ -90,18 +83,11 @@ export class AccessTokenCreateDialogComponent implements OnInit {
static openNewAccessTokenDialog(
dialogService: DialogServiceAbstraction,
serviceAccountId: string,
organizationId: string
serviceAccountView: ServiceAccountView
) {
// TODO once service account names are implemented in service account contents page pass in here.
const serviceAccountView = new ServiceAccountView();
serviceAccountView.id = serviceAccountId;
serviceAccountView.name = "placeholder";
return dialogService.open<unknown, AccessTokenOperation>(AccessTokenCreateDialogComponent, {
data: {
organizationId: organizationId,
serviceAccountView: serviceAccountView,
serviceAccountView,
},
});
}

View File

@ -15,6 +15,8 @@ import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { ServiceAccountView } from "../models/view/service-account.view";
import { AccessTokenCreateDialogComponent } from "./access/dialogs/access-token-create-dialog.component";
import { ServiceAccountService } from "./service-account.service";
@ -32,6 +34,7 @@ export class ServiceAccountComponent implements OnInit, OnDestroy {
startWith(null)
);
private serviceAccountView: ServiceAccountView;
protected serviceAccount$ = combineLatest([this.route.params, this.onChange$]).pipe(
switchMap(([params, _]) =>
this.serviceAccountService.getByServiceAccountId(
@ -61,9 +64,8 @@ export class ServiceAccountComponent implements OnInit, OnDestroy {
) {}
ngOnInit(): void {
this.route.params.pipe(takeUntil(this.destroy$)).subscribe((params) => {
this.serviceAccountId = params.serviceAccountId;
this.organizationId = params.organizationId;
this.serviceAccount$.pipe(takeUntil(this.destroy$)).subscribe((serviceAccountView) => {
this.serviceAccountView = serviceAccountView;
});
}
@ -75,8 +77,7 @@ export class ServiceAccountComponent implements OnInit, OnDestroy {
protected openNewAccessTokenDialog() {
AccessTokenCreateDialogComponent.openNewAccessTokenDialog(
this.dialogService,
this.serviceAccountId,
this.organizationId
this.serviceAccountView
);
}
}