1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-14 15:23:33 +00:00

[PM 2164] api-key component migration (#8562)

* api-key component migration

* api-key component migration

* api-key component migration

* api-key component migration
This commit is contained in:
vinith-kovan
2024-06-05 22:44:33 +05:30
committed by GitHub
parent 24fb3f71f1
commit 1cec69e377
4 changed files with 126 additions and 138 deletions

View File

@@ -216,31 +216,33 @@ export class AccountComponent {
}; };
async viewApiKey() { async viewApiKey() {
await this.modalService.openViewRef(ApiKeyComponent, this.apiKeyModalRef, (comp) => { await ApiKeyComponent.open(this.dialogService, {
comp.keyType = "organization"; data: {
comp.entityId = this.organizationId; keyType: "organization",
comp.postKey = this.organizationApiService.getOrCreateApiKey.bind( entityId: this.organizationId,
this.organizationApiService, postKey: this.organizationApiService.getOrCreateApiKey.bind(this.organizationApiService),
); scope: "api.organization",
comp.scope = "api.organization"; grantType: "client_credentials",
comp.grantType = "client_credentials"; apiKeyTitle: "apiKey",
comp.apiKeyTitle = "apiKey"; apiKeyWarning: "apiKeyWarning",
comp.apiKeyWarning = "apiKeyWarning"; apiKeyDescription: "apiKeyDesc",
comp.apiKeyDescription = "apiKeyDesc"; },
}); });
} }
async rotateApiKey() { async rotateApiKey() {
await this.modalService.openViewRef(ApiKeyComponent, this.rotateApiKeyModalRef, (comp) => { await ApiKeyComponent.open(this.dialogService, {
comp.keyType = "organization"; data: {
comp.isRotation = true; keyType: "organization",
comp.entityId = this.organizationId; isRotation: true,
comp.postKey = this.organizationApiService.rotateApiKey.bind(this.organizationApiService); entityId: this.organizationId,
comp.scope = "api.organization"; postKey: this.organizationApiService.rotateApiKey.bind(this.organizationApiService),
comp.grantType = "client_credentials"; scope: "api.organization",
comp.apiKeyTitle = "apiKey"; grantType: "client_credentials",
comp.apiKeyWarning = "apiKeyWarning"; apiKeyTitle: "apiKey",
comp.apiKeyDescription = "apiKeyRotateDesc"; apiKeyWarning: "apiKeyWarning",
apiKeyDescription: "apiKeyRotateDesc",
},
}); });
} }
} }

View File

@@ -1,72 +1,42 @@
<div class="modal fade" role="dialog" aria-modal="true" aria-labelledby="apiKeyTitle"> <form [formGroup]="formGroup" [bitSubmit]="submit">
<div class="modal-dialog modal-dialog-scrollable" role="document"> <bit-dialog>
<form <span bitDialogTitle>{{ data.apiKeyTitle | i18n }}</span>
class="modal-content" <div bitDialogContent>
#form <p bitTypography="body1">{{ data.apiKeyDescription | i18n }}</p>
(ngSubmit)="submit()" <app-user-verification-form-input formControlName="masterPassword" *ngIf="!clientSecret">
[appApiAction]="formPromise" </app-user-verification-form-input>
ngNativeValidate <app-callout type="warning" *ngIf="clientSecret">{{ data.apiKeyWarning | i18n }}</app-callout>
>
<div class="modal-header">
<h1 class="modal-title" id="apiKeyTitle">{{ apiKeyTitle | i18n }}</h1>
<button
type="button"
class="close"
data-dismiss="modal"
appA11yTitle="{{ 'close' | i18n }}"
>
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p>{{ apiKeyDescription | i18n }}</p>
<app-user-verification
[(ngModel)]="masterPassword"
ngDefaultControl
name="secret"
*ngIf="!clientSecret"
>
</app-user-verification>
<app-callout type="warning" *ngIf="clientSecret">{{ apiKeyWarning | i18n }}</app-callout>
<app-callout <app-callout
type="info" type="info"
title="{{ 'oauth2ClientCredentials' | i18n }}" title="{{ 'oauth2ClientCredentials' | i18n }}"
icon="bwi bwi-key" icon="bwi bwi-key"
*ngIf="clientSecret" *ngIf="clientSecret"
> >
<p class="mb-1"> <p bitTypography="body1" class="tw-mb-1">
<strong>client_id:</strong><br /> <strong>client_id:</strong><br />
<code>{{ clientId }}</code> <code>{{ clientId }}</code>
</p> </p>
<p class="mb-1"> <p bitTypography="body1" class="tw-mb-1">
<strong>client_secret:</strong><br /> <strong>client_secret:</strong><br />
<code>{{ clientSecret }}</code> <code>{{ clientSecret }}</code>
</p> </p>
<p class="mb-1"> <p bitTypography="body1" class="tw-mb-1">
<strong>scope:</strong><br /> <strong>scope:</strong><br />
<code>{{ scope }}</code> <code>{{ data.scope }}</code>
</p> </p>
<p class="mb-0"> <p bitTypography="body1" class="tw-mb-0">
<strong>grant_type:</strong><br /> <strong>grant_type:</strong><br />
<code>{{ grantType }}</code> <code>{{ data.grantType }}</code>
</p> </p>
</app-callout> </app-callout>
</div> </div>
<div class="modal-footer"> <div bitDialogFooter>
<button <button type="submit" buttonType="primary" *ngIf="!clientSecret" bitButton bitFormButton>
type="submit" <span>{{ (data.isRotation ? "rotateApiKey" : "viewApiKey") | i18n }}</span>
class="btn btn-primary btn-submit"
[disabled]="form.loading"
*ngIf="!clientSecret"
>
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
<span>{{ (isRotation ? "rotateApiKey" : "viewApiKey") | i18n }}</span>
</button> </button>
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal"> <button type="button" bitButton bitFormButton bitDialogClose>
{{ "close" | i18n }} {{ "close" | i18n }}
</button> </button>
</div> </div>
</form> </bit-dialog>
</div> </form>
</div>

View File

@@ -1,46 +1,58 @@
import { Component } from "@angular/core"; import { DIALOG_DATA, DialogConfig } from "@angular/cdk/dialog";
import { Component, Inject } from "@angular/core";
import { FormBuilder, Validators } from "@angular/forms";
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction"; import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { SecretVerificationRequest } from "@bitwarden/common/auth/models/request/secret-verification.request"; import { SecretVerificationRequest } from "@bitwarden/common/auth/models/request/secret-verification.request";
import { ApiKeyResponse } from "@bitwarden/common/auth/models/response/api-key.response"; import { ApiKeyResponse } from "@bitwarden/common/auth/models/response/api-key.response";
import { Verification } from "@bitwarden/common/auth/types/verification"; import { Verification } from "@bitwarden/common/auth/types/verification";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { DialogService } from "@bitwarden/components";
@Component({ export type ApiKeyDialogData = {
selector: "app-api-key",
templateUrl: "api-key.component.html",
})
export class ApiKeyComponent {
keyType: string; keyType: string;
isRotation: boolean; isRotation?: boolean;
postKey: (entityId: string, request: SecretVerificationRequest) => Promise<ApiKeyResponse>;
entityId: string; entityId: string;
postKey: (entityId: string, request: SecretVerificationRequest) => Promise<ApiKeyResponse>;
scope: string; scope: string;
grantType: string; grantType: string;
apiKeyTitle: string; apiKeyTitle: string;
apiKeyWarning: string; apiKeyWarning: string;
apiKeyDescription: string; apiKeyDescription: string;
};
masterPassword: Verification; @Component({
formPromise: Promise<ApiKeyResponse>; selector: "app-api-key",
templateUrl: "api-key.component.html",
})
export class ApiKeyComponent {
clientId: string; clientId: string;
clientSecret: string; clientSecret: string;
formGroup = this.formBuilder.group({
masterPassword: [null as Verification, [Validators.required]],
});
constructor( constructor(
@Inject(DIALOG_DATA) protected data: ApiKeyDialogData,
private formBuilder: FormBuilder,
private userVerificationService: UserVerificationService, private userVerificationService: UserVerificationService,
private logService: LogService,
) {} ) {}
async submit() { submit = async () => {
try { if (this.formGroup.invalid) {
this.formPromise = this.userVerificationService this.formGroup.markAllAsTouched();
.buildRequest(this.masterPassword) return;
.then((request) => this.postKey(this.entityId, request)); }
const response = await this.formPromise; const response = await this.userVerificationService
.buildRequest(this.formGroup.value.masterPassword)
.then((request) => this.data.postKey(this.data.entityId, request));
this.clientSecret = response.apiKey; this.clientSecret = response.apiKey;
this.clientId = `${this.keyType}.${this.entityId}`; this.clientId = `${this.data.keyType}.${this.data.entityId}`;
} catch (e) { };
this.logService.error(e); /**
} * Strongly typed helper to open a ApiKeyComponent
} * @param dialogService Instance of the dialog service that will be used to open the dialog
* @param config Configuration for the dialog
*/
static open = (dialogService: DialogService, config: DialogConfig<ApiKeyDialogData>) => {
return dialogService.open(ApiKeyComponent, config);
};
} }

View File

@@ -1,9 +1,9 @@
import { Component, OnInit, ViewChild, ViewContainerRef } from "@angular/core"; import { Component, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
import { ModalService } from "@bitwarden/angular/services/modal.service";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction"; import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { DialogService } from "@bitwarden/components";
import { ApiKeyComponent } from "./api-key.component"; import { ApiKeyComponent } from "./api-key.component";
@@ -22,8 +22,8 @@ export class SecurityKeysComponent implements OnInit {
constructor( constructor(
private userVerificationService: UserVerificationService, private userVerificationService: UserVerificationService,
private stateService: StateService, private stateService: StateService,
private modalService: ModalService,
private apiService: ApiService, private apiService: ApiService,
private dialogService: DialogService,
) {} ) {}
async ngOnInit() { async ngOnInit() {
@@ -32,30 +32,34 @@ export class SecurityKeysComponent implements OnInit {
async viewUserApiKey() { async viewUserApiKey() {
const entityId = await this.stateService.getUserId(); const entityId = await this.stateService.getUserId();
await this.modalService.openViewRef(ApiKeyComponent, this.viewUserApiKeyModalRef, (comp) => { await ApiKeyComponent.open(this.dialogService, {
comp.keyType = "user"; data: {
comp.entityId = entityId; keyType: "user",
comp.postKey = this.apiService.postUserApiKey.bind(this.apiService); entityId: entityId,
comp.scope = "api"; postKey: this.apiService.postUserApiKey.bind(this.apiService),
comp.grantType = "client_credentials"; scope: "api",
comp.apiKeyTitle = "apiKey"; grantType: "client_credentials",
comp.apiKeyWarning = "userApiKeyWarning"; apiKeyTitle: "apiKey",
comp.apiKeyDescription = "userApiKeyDesc"; apiKeyWarning: "userApiKeyWarning",
apiKeyDescription: "userApiKeyDesc",
},
}); });
} }
async rotateUserApiKey() { async rotateUserApiKey() {
const entityId = await this.stateService.getUserId(); const entityId = await this.stateService.getUserId();
await this.modalService.openViewRef(ApiKeyComponent, this.rotateUserApiKeyModalRef, (comp) => { await ApiKeyComponent.open(this.dialogService, {
comp.keyType = "user"; data: {
comp.isRotation = true; keyType: "user",
comp.entityId = entityId; isRotation: true,
comp.postKey = this.apiService.postUserRotateApiKey.bind(this.apiService); entityId: entityId,
comp.scope = "api"; postKey: this.apiService.postUserRotateApiKey.bind(this.apiService),
comp.grantType = "client_credentials"; scope: "api",
comp.apiKeyTitle = "apiKey"; grantType: "client_credentials",
comp.apiKeyWarning = "userApiKeyWarning"; apiKeyTitle: "apiKey",
comp.apiKeyDescription = "apiKeyRotateDesc"; apiKeyWarning: "userApiKeyWarning",
apiKeyDescription: "apiKeyRotateDesc",
},
}); });
} }
} }