src/app/features/api-client/api-client-credentials-dialog/api-client-credentials-dialog.component.ts
Shows the credentials of an API client right after it was created (or its secret was regenerated), which is the only time its secret is available, so that they can be passed on to the external system.
| changeDetection | ChangeDetectionStrategy.OnPush |
| selector | app-api-client-credentials-dialog |
| standalone | true |
| imports |
MatDialogModule
MatButtonModule
MatTooltipModule
|
| styleUrls | ./api-client-credentials-dialog.component.scss |
| templateUrl | ./api-client-credentials-dialog.component.html |
| styleUrl | ./api-client-credentials-dialog.component.scss |
No results matching.
MatDialogModule
MatButtonModule
MatTooltipModule
FaIconComponent
DialogCloseComponent
HintBoxComponent
Properties |
|
Methods |
constructor()
|
| copy | ||||||
copy(value: string)
|
||||||
|
Parameters :
Returns :
void
|
| copyAll |
copyAll()
|
|
Returns :
void
|
| Readonly fields |
Type : { label: string; value: string; copyLabel: string }[]
|
| Readonly scopeLabels |
Type : unknown
|
Default value : this.data.scopes.map((s) => getScopeLabel(s))
|
import { ChangeDetectionStrategy, Component, inject } from "@angular/core";
import { Clipboard } from "@angular/cdk/clipboard";
import { MAT_DIALOG_DATA, MatDialogModule } from "@angular/material/dialog";
import { MatButtonModule } from "@angular/material/button";
import { MatTooltipModule } from "@angular/material/tooltip";
import { FaIconComponent } from "@fortawesome/angular-fontawesome";
import { DialogCloseComponent } from "#src/app/core/common-components/dialog-close/dialog-close.component";
import { HintBoxComponent } from "#src/app/core/common-components/hint-box/hint-box.component";
import { AlertService } from "#src/app/core/alerts/alert.service";
import { ApiClientCredentials, ApiClientService } from "../api-client.service";
import { getScopeLabel } from "../api-client-scopes";
export interface ApiClientCredentialsDialogData {
credentials: ApiClientCredentials;
/** the client scopes of the API client */
scopes: string[];
}
/**
* Shows the credentials of an API client right after it was created (or its secret was regenerated),
* which is the only time its secret is available, so that they can be passed on to the external system.
*/
@Component({
selector: "app-api-client-credentials-dialog",
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [
MatDialogModule,
MatButtonModule,
MatTooltipModule,
FaIconComponent,
DialogCloseComponent,
HintBoxComponent,
],
templateUrl: "./api-client-credentials-dialog.component.html",
styleUrl: "./api-client-credentials-dialog.component.scss",
})
export class ApiClientCredentialsDialogComponent {
private readonly apiClientService = inject(ApiClientService);
private readonly alertService = inject(AlertService);
private readonly clipboard = inject(Clipboard);
private readonly data =
inject<ApiClientCredentialsDialogData>(MAT_DIALOG_DATA);
readonly fields: { label: string; value: string; copyLabel: string }[];
readonly scopeLabels = this.data.scopes.map((s) => getScopeLabel(s));
constructor() {
const connection = this.apiClientService.getConnectionDetails();
this.fields = [
{ label: $localize`API base URL`, value: connection.apiBaseUrl },
{ label: $localize`Token URL`, value: connection.tokenUrl },
{ label: $localize`Client ID`, value: this.data.credentials.clientId },
{
label: $localize`Client secret`,
value: this.data.credentials.clientSecret,
},
].map((field) => ({
...field,
copyLabel: $localize`:aria label of a copy button:Copy ${field.label}:fieldName:`,
}));
}
copy(value: string) {
if (this.clipboard.copy(value)) {
this.alertService.addInfo($localize`Copied to clipboard`);
} else {
this.alertService.addWarning(
$localize`Could not copy to the clipboard. Please select and copy the text instead.`,
);
}
}
copyAll() {
return this.copy(
this.apiClientService.formatForSharing(
this.data.credentials,
this.data.scopes,
),
);
}
}
<h2 mat-dialog-title i18n>API credentials</h2>
<app-dialog-close mat-dialog-close></app-dialog-close>
<mat-dialog-content>
<app-hint-box>
<span i18n>
Copy the client secret now and pass it on securely, e.g. through a
password manager. It is not shown again. If it gets lost, you can generate
a new secret, which stops the previous one from working.
</span>
</app-hint-box>
<dl class="credentials">
@for (field of fields; track field.label) {
<dt>{{ field.label }}</dt>
<dd class="flex-row align-center">
<code class="credential-value flex-grow">{{ field.value }}</code>
<button
mat-icon-button
type="button"
(click)="copy(field.value)"
matTooltip="Copy"
i18n-matTooltip
[attr.aria-label]="field.copyLabel"
>
<fa-icon [icon]="['far', 'copy']"></fa-icon>
</button>
</dd>
}
<dt i18n>Access</dt>
<dd>
<ul class="scopes">
@for (label of scopeLabels; track label) {
<li>{{ label }}</li>
}
</ul>
</dd>
</dl>
</mat-dialog-content>
<mat-dialog-actions>
<button
mat-raised-button
color="accent"
type="button"
(click)="copyAll()"
cdkFocusInitial
>
<fa-icon [icon]="['far', 'copy']" class="standard-icon-with-text"></fa-icon>
<span i18n>Copy all</span>
</button>
<button mat-button mat-dialog-close i18n="Button label">Done</button>
</mat-dialog-actions>
./api-client-credentials-dialog.component.scss
.credentials {
margin: 0;
dt {
font-weight: bold;
margin-top: 12px;
}
dd {
margin: 0;
}
}
.credential-value {
overflow-wrap: anywhere;
}
.scopes {
margin: 4px 0 0;
padding-left: 20px;
}