Add accessToSecrets to service account lists (#5749)
This commit is contained in:
parent
5756aa851b
commit
6c68b46acb
|
@ -5,3 +5,7 @@ export class ServiceAccountView {
|
||||||
creationDate: string;
|
creationDate: string;
|
||||||
revisionDate: string;
|
revisionDate: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ServiceAccountSecretsDetailsView extends ServiceAccountView {
|
||||||
|
accessToSecrets: number;
|
||||||
|
}
|
||||||
|
|
|
@ -130,7 +130,7 @@ export class OverviewComponent implements OnInit, OnDestroy {
|
||||||
orgId$,
|
orgId$,
|
||||||
this.serviceAccountService.serviceAccount$.pipe(startWith(null)),
|
this.serviceAccountService.serviceAccount$.pipe(startWith(null)),
|
||||||
]).pipe(
|
]).pipe(
|
||||||
switchMap(([orgId]) => this.serviceAccountService.getServiceAccounts(orgId)),
|
switchMap(([orgId]) => this.serviceAccountService.getServiceAccounts(orgId, false)),
|
||||||
share()
|
share()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -16,3 +16,12 @@ export class ServiceAccountResponse extends BaseResponse {
|
||||||
this.revisionDate = this.getResponseProperty("RevisionDate");
|
this.revisionDate = this.getResponseProperty("RevisionDate");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ServiceAccountSecretsDetailsResponse extends ServiceAccountResponse {
|
||||||
|
accessToSecrets: number;
|
||||||
|
|
||||||
|
constructor(response: any) {
|
||||||
|
super(response);
|
||||||
|
this.accessToSecrets = this.getResponseProperty("AccessToSecrets");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -8,11 +8,17 @@ import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.
|
||||||
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
||||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||||
|
|
||||||
import { ServiceAccountView } from "../models/view/service-account.view";
|
import {
|
||||||
|
ServiceAccountSecretsDetailsView,
|
||||||
|
ServiceAccountView,
|
||||||
|
} from "../models/view/service-account.view";
|
||||||
import { BulkOperationStatus } from "../shared/dialogs/bulk-status-dialog.component";
|
import { BulkOperationStatus } from "../shared/dialogs/bulk-status-dialog.component";
|
||||||
|
|
||||||
import { ServiceAccountRequest } from "./models/requests/service-account.request";
|
import { ServiceAccountRequest } from "./models/requests/service-account.request";
|
||||||
import { ServiceAccountResponse } from "./models/responses/service-account.response";
|
import {
|
||||||
|
ServiceAccountResponse,
|
||||||
|
ServiceAccountSecretsDetailsResponse,
|
||||||
|
} from "./models/responses/service-account.response";
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: "root",
|
providedIn: "root",
|
||||||
|
@ -28,16 +34,24 @@ export class ServiceAccountService {
|
||||||
private encryptService: EncryptService
|
private encryptService: EncryptService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async getServiceAccounts(organizationId: string): Promise<ServiceAccountView[]> {
|
async getServiceAccounts(
|
||||||
|
organizationId: string,
|
||||||
|
includeAccessToSecrets?: boolean
|
||||||
|
): Promise<ServiceAccountSecretsDetailsView[]> {
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
if (includeAccessToSecrets) {
|
||||||
|
params.set("includeAccessToSecrets", "true");
|
||||||
|
}
|
||||||
|
|
||||||
const r = await this.apiService.send(
|
const r = await this.apiService.send(
|
||||||
"GET",
|
"GET",
|
||||||
"/organizations/" + organizationId + "/service-accounts",
|
"/organizations/" + organizationId + "/service-accounts?" + params.toString(),
|
||||||
null,
|
null,
|
||||||
true,
|
true,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
const results = new ListResponse(r, ServiceAccountResponse);
|
const results = new ListResponse(r, ServiceAccountSecretsDetailsResponse);
|
||||||
return await this.createServiceAccountViews(organizationId, results.data);
|
return await this.createServiceAccountSecretsDetailsViews(organizationId, results.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getByServiceAccountId(
|
async getByServiceAccountId(
|
||||||
|
@ -127,21 +141,39 @@ export class ServiceAccountService {
|
||||||
serviceAccountView.organizationId = serviceAccountResponse.organizationId;
|
serviceAccountView.organizationId = serviceAccountResponse.organizationId;
|
||||||
serviceAccountView.creationDate = serviceAccountResponse.creationDate;
|
serviceAccountView.creationDate = serviceAccountResponse.creationDate;
|
||||||
serviceAccountView.revisionDate = serviceAccountResponse.revisionDate;
|
serviceAccountView.revisionDate = serviceAccountResponse.revisionDate;
|
||||||
serviceAccountView.name = await this.encryptService.decryptToUtf8(
|
serviceAccountView.name = serviceAccountResponse.name
|
||||||
new EncString(serviceAccountResponse.name),
|
? await this.encryptService.decryptToUtf8(
|
||||||
organizationKey
|
new EncString(serviceAccountResponse.name),
|
||||||
);
|
organizationKey
|
||||||
|
)
|
||||||
|
: null;
|
||||||
return serviceAccountView;
|
return serviceAccountView;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createServiceAccountViews(
|
private async createServiceAccountSecretsDetailsView(
|
||||||
|
organizationKey: SymmetricCryptoKey,
|
||||||
|
response: ServiceAccountSecretsDetailsResponse
|
||||||
|
): Promise<ServiceAccountSecretsDetailsView> {
|
||||||
|
const view = new ServiceAccountSecretsDetailsView();
|
||||||
|
view.id = response.id;
|
||||||
|
view.organizationId = response.organizationId;
|
||||||
|
view.creationDate = response.creationDate;
|
||||||
|
view.revisionDate = response.revisionDate;
|
||||||
|
view.accessToSecrets = response.accessToSecrets;
|
||||||
|
view.name = response.name
|
||||||
|
? await this.encryptService.decryptToUtf8(new EncString(response.name), organizationKey)
|
||||||
|
: null;
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async createServiceAccountSecretsDetailsViews(
|
||||||
organizationId: string,
|
organizationId: string,
|
||||||
serviceAccountResponses: ServiceAccountResponse[]
|
serviceAccountResponses: ServiceAccountSecretsDetailsResponse[]
|
||||||
): Promise<ServiceAccountView[]> {
|
): Promise<ServiceAccountSecretsDetailsView[]> {
|
||||||
const orgKey = await this.getOrganizationKey(organizationId);
|
const orgKey = await this.getOrganizationKey(organizationId);
|
||||||
return await Promise.all(
|
return await Promise.all(
|
||||||
serviceAccountResponses.map(async (s: ServiceAccountResponse) => {
|
serviceAccountResponses.map(async (s: ServiceAccountSecretsDetailsResponse) => {
|
||||||
return await this.createServiceAccountView(orgKey, s);
|
return await this.createServiceAccountSecretsDetailsView(orgKey, s);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,8 +64,7 @@
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td bitCell>
|
<td bitCell>
|
||||||
<!-- TODO add number of secrets once mapping is implemented-->
|
<span> {{ serviceAccount.accessToSecrets }} </span>
|
||||||
<span> 0 </span>
|
|
||||||
</td>
|
</td>
|
||||||
<td bitCell>{{ serviceAccount.revisionDate | date : "medium" }}</td>
|
<td bitCell>{{ serviceAccount.revisionDate | date : "medium" }}</td>
|
||||||
<td bitCell>
|
<td bitCell>
|
||||||
|
|
|
@ -6,25 +6,28 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { TableDataSource } from "@bitwarden/components";
|
import { TableDataSource } from "@bitwarden/components";
|
||||||
|
|
||||||
import { ServiceAccountView } from "../models/view/service-account.view";
|
import {
|
||||||
|
ServiceAccountSecretsDetailsView,
|
||||||
|
ServiceAccountView,
|
||||||
|
} from "../models/view/service-account.view";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "sm-service-accounts-list",
|
selector: "sm-service-accounts-list",
|
||||||
templateUrl: "./service-accounts-list.component.html",
|
templateUrl: "./service-accounts-list.component.html",
|
||||||
})
|
})
|
||||||
export class ServiceAccountsListComponent implements OnDestroy {
|
export class ServiceAccountsListComponent implements OnDestroy {
|
||||||
protected dataSource = new TableDataSource<ServiceAccountView>();
|
protected dataSource = new TableDataSource<ServiceAccountSecretsDetailsView>();
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
get serviceAccounts(): ServiceAccountView[] {
|
get serviceAccounts(): ServiceAccountSecretsDetailsView[] {
|
||||||
return this._serviceAccounts;
|
return this._serviceAccounts;
|
||||||
}
|
}
|
||||||
set serviceAccounts(serviceAccounts: ServiceAccountView[]) {
|
set serviceAccounts(serviceAccounts: ServiceAccountSecretsDetailsView[]) {
|
||||||
this.selection.clear();
|
this.selection.clear();
|
||||||
this._serviceAccounts = serviceAccounts;
|
this._serviceAccounts = serviceAccounts;
|
||||||
this.dataSource.data = serviceAccounts;
|
this.dataSource.data = serviceAccounts;
|
||||||
}
|
}
|
||||||
private _serviceAccounts: ServiceAccountView[];
|
private _serviceAccounts: ServiceAccountSecretsDetailsView[];
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
set search(search: string) {
|
set search(search: string) {
|
||||||
|
@ -72,8 +75,8 @@ export class ServiceAccountsListComponent implements OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(serviceAccount: ServiceAccountView) {
|
delete(serviceAccount: ServiceAccountSecretsDetailsView) {
|
||||||
this.deleteServiceAccountsEvent.emit([serviceAccount]);
|
this.deleteServiceAccountsEvent.emit([serviceAccount as ServiceAccountView]);
|
||||||
}
|
}
|
||||||
|
|
||||||
bulkDeleteServiceAccounts() {
|
bulkDeleteServiceAccounts() {
|
||||||
|
|
|
@ -4,7 +4,10 @@ import { combineLatest, Observable, startWith, switchMap } from "rxjs";
|
||||||
|
|
||||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||||
|
|
||||||
import { ServiceAccountView } from "../models/view/service-account.view";
|
import {
|
||||||
|
ServiceAccountSecretsDetailsView,
|
||||||
|
ServiceAccountView,
|
||||||
|
} from "../models/view/service-account.view";
|
||||||
import { AccessPolicyService } from "../shared/access-policies/access-policy.service";
|
import { AccessPolicyService } from "../shared/access-policies/access-policy.service";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -23,7 +26,7 @@ import { ServiceAccountService } from "./service-account.service";
|
||||||
templateUrl: "./service-accounts.component.html",
|
templateUrl: "./service-accounts.component.html",
|
||||||
})
|
})
|
||||||
export class ServiceAccountsComponent implements OnInit {
|
export class ServiceAccountsComponent implements OnInit {
|
||||||
protected serviceAccounts$: Observable<ServiceAccountView[]>;
|
protected serviceAccounts$: Observable<ServiceAccountSecretsDetailsView[]>;
|
||||||
protected search: string;
|
protected search: string;
|
||||||
|
|
||||||
private organizationId: string;
|
private organizationId: string;
|
||||||
|
@ -78,7 +81,7 @@ export class ServiceAccountsComponent implements OnInit {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getServiceAccounts(): Promise<ServiceAccountView[]> {
|
private async getServiceAccounts(): Promise<ServiceAccountSecretsDetailsView[]> {
|
||||||
return await this.serviceAccountService.getServiceAccounts(this.organizationId);
|
return await this.serviceAccountService.getServiceAccounts(this.organizationId, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue