File

trusted-certificates/list/trusted-certificate-list.component.ts

Implements

OnInit

Metadata

Index

Properties
Methods

Constructor

constructor(bsModal: BsModalService, alertService: AlertService, trustedCertificateService: TrustedCertificateService, modalService: ModalService, translateService: TranslateService, clipboardService: ClipboardService, gainsightService: GainsightService, systemOptionsService: SystemOptionsService, featureCacheService: FeatureCacheService, guard: TrustedCertificatesGuard)
Parameters :
Name Type Optional
bsModal BsModalService No
alertService AlertService No
trustedCertificateService TrustedCertificateService No
modalService ModalService No
translateService TranslateService No
clipboardService ClipboardService No
gainsightService GainsightService No
systemOptionsService SystemOptionsService No
featureCacheService FeatureCacheService No
guard TrustedCertificatesGuard No

Methods

Async addCACertificate
addCACertificate()
Returns : any
Async addTrustedCertificate
addTrustedCertificate()
Returns : any
copyUnsignedVerificationCodeToClipboard
copyUnsignedVerificationCodeToClipboard(trustedCertificate: ITrustedCertificate)
Parameters :
Name Type Optional
trustedCertificate ITrustedCertificate No
Returns : void
Async deleteTrustedCertificate
deleteTrustedCertificate(certificate)
Parameters :
Name Optional
certificate No
Returns : any
downloadUnsignedVerificationCode
downloadUnsignedVerificationCode(trustedCertificate: ITrustedCertificate)
Parameters :
Name Type Optional
trustedCertificate ITrustedCertificate No
Returns : void
getExpirationHighlight
getExpirationHighlight(item: ITrustedCertificate)
Parameters :
Name Type Optional
item ITrustedCertificate No
Returns : { expired: boolean; icon: string; textClass: string; tooltipText: string; renewable: boolean; }
getTrustedCertificates
getTrustedCertificates()
Returns : any
Async loadTrustedCertificates
loadTrustedCertificates()
Returns : any
Async ngOnInit
ngOnInit()
Returns : any
onFileInput
onFileInput(event, trustedCertificate: TrustedCertificate)
Parameters :
Name Type Optional
event No
trustedCertificate TrustedCertificate No
Returns : void
regenerateUnsignedVerificationCode
regenerateUnsignedVerificationCode(trustedCertificate: ITrustedCertificate)
Parameters :
Name Type Optional
trustedCertificate ITrustedCertificate No
Returns : void
Async renewCertificate
renewCertificate()
Returns : any
Async updateCertificate
updateCertificate(trustedCertificate: ITrustedCertificate, updatingPart: Partial)
Parameters :
Name Type Optional
trustedCertificate ITrustedCertificate No
updatingPart Partial<ITrustedCertificate> No
Returns : any
verifySignedVerificationCode
verifySignedVerificationCode(trustedCertificate: TrustedCertificate)
Parameters :
Name Type Optional
trustedCertificate TrustedCertificate No
Returns : void

Properties

AUTO_REGISTRATION_POPOVER
Default value : gettext( 'Devices using the MQTT protocol with credentials signed by this certificate will be able to communicate with the platform without prior registration. The option does not support devices using the LWM2M protocol.' )
certificateAuthorityExists
Default value : false
certificateAuthorityFeatureEnabled
Default value : false
hasAdminRole$
Default value : from(this.guard.hasAdminRole()).pipe(shareReplay(1))
hasReadRole$
Default value : from(this.guard.hasReadRole()).pipe(shareReplay(1))
PRODUCT_EXPERIENCE
Default value : PRODUCT_EXPERIENCE_TRUSTED_CERTIFICATES
PROOF_OF_POSSESSION_POPOVER
Default value : gettext( '"Proof of possession" is a security method used to prove that whoever sends a message is also in the possession of the particular cryptographic key.' )
reload
Type : BehaviorSubject<void>
Default value : new BehaviorSubject(null)
reloading
Type : BehaviorSubject<boolean>
Default value : new BehaviorSubject(false)
SIGNED_VERIFICATION_CODE_POPOVER
Default value : gettext( 'Use the following openssl command to create the signed verification code: openssl dgst -sha256 -sign <private.key> <verification_code.txt> | openssl base64 -A' )
signedVerificationCode
Type : string
sortByExpirationDateAsc
Type : ForOfFilterPipe<ITrustedCertificate>
Default value : pipe( tap(results => { return results.sort((n1, n2) => { if (n1.tenantCertificateAuthority !== n2.tenantCertificateAuthority) { return n1.tenantCertificateAuthority ? -1 : 1; } return n1.notAfter.localeCompare(n2.notAfter); }); }) )
trustedCertificates
Type : Observable<IResultList<ITrustedCertificate>>
Default value : this.reload.pipe( tap(() => this.reloading.next(true)), switchMap(() => this.getTrustedCertificates()), tap(response => { this.certificateAuthorityExists = response.data.some( value => value.tenantCertificateAuthority ); }), tap(() => this.reloading.next(false)), shareReplay(1) )
<div *ngIf="(hasReadRole$ | async) || (hasAdminRole$ | async)">
  <c8y-title>{{ 'Trusted certificates' | translate }}</c8y-title>

  <c8y-breadcrumb>
    <c8y-breadcrumb-item
      icon="c8y-management"
      label="{{ 'Management' | translate }}"
    ></c8y-breadcrumb-item>
    <c8y-breadcrumb-item
      icon="certificate"
      label="{{ 'Trusted certificates' | translate }}"
    ></c8y-breadcrumb-item>
  </c8y-breadcrumb>

  <c8y-action-bar-item
    [placement]="'right'"
    *ngIf="certificateAuthorityFeatureEnabled"
  >
    <button
      class="btn btn-link"
      title="{{ 'Add CA certificate' | translate }}"
      type="button"
      [disabled]="!(hasAdminRole$ | async) || certificateAuthorityExists"
      (click)="addCACertificate()"
    >
      <i c8yIcon="contract"></i>
      {{ 'Add CA certificate' | translate }}
    </button>
    <button
      class="btn-help btn-help--sm"
      [attr.aria-label]="'Help' | translate"
      popover="{{
        'Adding a CA certificate lets the app trust certificates from the specified authority, ensuring secure connections. Only one certificate is allowed, which is why the button is disabled.'
          | translate
      }}"
      placement="bottom"
      triggers="focus"
      type="button"
      *ngIf="certificateAuthorityExists"
    ></button>
    <button
      class="btn-help btn-help--sm"
      [attr.aria-label]="'Help' | translate"
      popover="{{
        'Adding a CA certificate lets the app trust certificates from the specified authority, ensuring secure connections.'
          | translate
      }}"
      placement="bottom"
      triggers="focus"
      type="button"
      *ngIf="!certificateAuthorityExists"
    ></button>
  </c8y-action-bar-item>

  <c8y-action-bar-item [placement]="'right'">
    <button
      class="btn btn-link"
      title="{{ 'Add trusted certificate' | translate }}"
      type="button"
      (click)="addTrustedCertificate()"
      [disabled]="!(hasAdminRole$ | async)"
    >
      <i c8yIcon="plus-circle"></i>
      {{ 'Add trusted certificate' | translate }}
    </button>
  </c8y-action-bar-item>

  <c8y-action-bar-item [placement]="'right'">
    <button
      class="btn btn-link"
      title="{{ 'Reload' | translate }}"
      type="button"
      (click)="loadTrustedCertificates()"
    >
      <i
        c8yIcon="refresh"
        [ngClass]="{ 'icon-spin': reloading | async }"
      ></i>
      {{ 'Reload' | translate }}
    </button>
  </c8y-action-bar-item>

  <c8y-help
    src="/docs/device-certificate-authentication/managing-trusted-certificates/#managing-trusted-certificates"
  ></c8y-help>

  <c8y-ui-empty-state
    [icon]="'certificate'"
    [title]="'No trusted certificates to display.' | translate"
    [subtitle]="'Add your first certificate by clicking below.' | translate"
    *ngIf="(trustedCertificates | async)?.data.length === 0"
  >
    <button
      class="btn btn-primary"
      title="{{ 'Add trusted certificate' | translate }}"
      type="button"
      (click)="addTrustedCertificate()"
    >
      {{ 'Add trusted certificate' | translate }}
    </button>
  </c8y-ui-empty-state>

  <c8y-list-group class="m-b-24">
    <div
      class="page-sticky-header hidden-xs c8y-list__item c8y-list__item--empty-actions"
      *ngIf="(trustedCertificates | async)?.data.length > 0"
    >
      <div class="c8y-list__item__block">
        <div class="c8y-list__item__icon">
          <i
            class="invisible"
            c8yIcon="certificate"
          ></i>
        </div>
        <div class="c8y-list__item__body">
          <div class="content-flex-60">
            <div class="col-2">
              <span
                class="text-truncate"
                title=" {{ 'Certificate' | translate }} "
              >
                {{ 'Certificate' | translate }}
              </span>
            </div>
            <div class="col-2">
              <span
                class="text-truncate"
                title="{{ 'Status' | translate }}"
              >
                {{ 'Status' | translate }}
              </span>
            </div>
            <div class="col-2">
              <span
                class="text-truncate"
                title="{{ 'Algorithm' | translate }}"
              >
                {{ 'Algorithm' | translate }}
              </span>
            </div>
            <div class="col-2">
              <span
                class="text-truncate"
                title="{{ 'Expiration date' | translate }}"
              >
                {{ 'Expiration date' | translate }}
              </span>
            </div>
            <div class="col-2">
              <span
                class="text-truncate"
                title=" {{ 'Auto registration' | translate }}"
              >
                {{ 'Auto registration' | translate }}
              </span>
            </div>
            <div class="col-2">
              <span
                class="text-truncate"
                title=" {{ 'Proof of possession' | translate }}"
              >
                {{ 'Proof of possession' | translate }}
              </span>
            </div>
          </div>
        </div>
        <div class="c8y-list__item__actions"></div>
      </div>
    </div>

    <c8y-li
      *c8yFor="
        let trustedCertificate of trustedCertificates | async;
        let i = index;
        pipe: sortByExpirationDateAsc;
        loadMore: 'none'
      "
      #listItem
      data-cy="c8y-trusted-certificates-list--item-block"
    >
      <c8y-li-icon>
        <button
          class="btn-clean"
          attr.aria-label="{{ 'Certificate' | translate }}"
          tooltip="{{ 'Certificate' | translate }}"
          type="button"
          [delay]="500"
          *ngIf="!trustedCertificate.tenantCertificateAuthority"
        >
          <i c8yIcon="certificate"></i>
        </button>
        <button
          class="btn-clean"
          attr.aria-label="{{ 'CA certificate' | translate }}"
          tooltip="{{ 'CA certificate' | translate }}"
          type="button"
          [delay]="500"
          *ngIf="trustedCertificate.tenantCertificateAuthority"
        >
          <i c8yIcon="contract"></i>
        </button>
      </c8y-li-icon>

      <c8y-li-body class="content-flex-60">
        <div class="col-2">
          <button
            class="btn-clean text-truncate"
            title="{{ trustedCertificate.name }}"
            type="button"
            (click)="listItem.toggleCollapsed()"
          >
            {{ trustedCertificate.name }}
          </button>
        </div>
        <div class="col-2">
          <div class="visible-xs p-8"></div>
          <button
            class="btn c8y-btn-checkbox--inline"
            name="certificateStatus"
            type="button"
            [(ngModel)]="trustedCertificate.status"
            btnCheckbox
            btnCheckboxTrue="ENABLED"
            btnCheckboxFalse="DISABLED"
            (ngModelChange)="updateCertificate(trustedCertificate, { status: $event })"
            [disabled]="!(hasAdminRole$ | async)"
            [ngClass]="{
              disabled: !(hasAdminRole$ | async)
            }"
          >
            <small
              title="{{ 'Disabled`trusted certificate status`' | translate }}"
              [hidden]="trustedCertificate.status !== 'DISABLED'"
            >
              {{ 'Disabled`trusted certificate status`' | translate }}
            </small>
            <small
              title="{{ 'Enabled`trusted certificate status`' | translate }}"
              [hidden]="trustedCertificate.status !== 'ENABLED'"
            >
              {{ 'Enabled`trusted certificate status`' | translate }}
            </small>
          </button>
          <div class="visible-xs p-8"></div>
        </div>
        <div class="col-2">
          <div
            class="text-truncate"
            title="{{ 'Algorithm' | translate }}: {{ trustedCertificate.algorithmName }}"
          >
            <span
              class="text-label-small m-t-8 m-r-8 visible-xs-inline"
              translate
            >
              Algorithm
            </span>
            {{ trustedCertificate.algorithmName }}
          </div>
        </div>

        <div class="col-2">
          <div
            class="text-truncate"
            title="{{ 'Expiration date' | translate }}: {{ trustedCertificate.notAfter | c8yDate }}"
          >
            <span
              class="text-label-small m-t-8 m-r-8 visible-xs-inline"
              translate
            >
              Expiration date
            </span>
            @let expirationHighlight = getExpirationHighlight(trustedCertificate);
            <span>
              <small
                [attr.title]="expirationHighlight?.tooltipText"
                [ngClass]="expirationHighlight?.textClass"
              >
                <ng-container *ngIf="expirationHighlight?.expired; else notExpiredYet">
                  <del>
                    <ng-container *ngTemplateOutlet="expirationDateTpl"></ng-container>
                  </del>
                </ng-container>
                <ng-template #notExpiredYet>
                  <ng-container *ngTemplateOutlet="expirationDateTpl"></ng-container>
                </ng-template>
                <ng-template #expirationDateTpl>
                  <i
                    class="m-r-4"
                    c8yIcon="{{ expirationHighlight?.icon }}"
                    *ngIf="expirationHighlight?.icon"
                  ></i>
                  <span>{{ trustedCertificate.notAfter | c8yDate }}</span>
                </ng-template>
              </small>
              <button
                class="btn btn-link btn-icon"
                title="{{ 'Renew certificate' | translate }}"
                type="button"
                *ngIf="expirationHighlight?.renewable"
                (click)="renewCertificate()"
              >
                <i c8yIcon="refresh"></i>
              </button>
            </span>
          </div>
        </div>
        <div class="col-2">
          <div class="text-truncate">
            <span class="text-label-small m-t-8 m-r-4 visible-xs-inline">
              {{ 'Auto registration' | translate }}
            </span>
            <span
              title="{{ 'Auto registration' | translate }}:  {{
                'Enabled`auto registration`' | translate
              }}"
              *ngIf="trustedCertificate.autoRegistrationEnabled"
            >
              {{ 'Enabled`auto registration`' | translate }}
            </span>
            <span
              title="{{ 'Auto registration' | translate }}:  {{
                'Disabled`auto registration`' | translate
              }}"
              *ngIf="!trustedCertificate.autoRegistrationEnabled"
            >
              {{ 'Disabled`auto registration`' | translate }}
            </span>
            <button
              class="btn-help btn-help--sm"
              [attr.aria-label]="'Help' | translate"
              popover="{{ AUTO_REGISTRATION_POPOVER | translate }}"
              placement="right"
              triggers="focus"
              container="body"
              type="button"
              type="button"
            ></button>
          </div>
        </div>
        <div class="col-2 d-flex">
          <div class="text-truncate">
            <span class="text-label-small m-t-8 m-r-4 visible-xs-inline">
              {{ 'Proof of possession' | translate }}
            </span>
            <span
              title="{{ 'Proof of possession' | translate }}: {{ 'N/A' | translate }}"
              *ngIf="trustedCertificate.tenantCertificateAuthority"
            >
              {{ 'N/A' | translate }}
            </span>
            <span *ngIf="!trustedCertificate.tenantCertificateAuthority">
              <span
                title="{{ 'Proof of possession' | translate }}:  {{
                  'Complete`proof of possession`' | translate
                }}"
                *ngIf="trustedCertificate.proofOfPossessionValid"
              >
                <div class="icon-flex">
                  <i
                    class="text-success"
                    c8yIcon="success"
                  ></i>
                  {{ 'Complete`proof of possession`' | translate }}
                </div>
              </span>
              <span
                title="{{ 'Proof of possession' | translate }}:  {{
                  'Incomplete`proof of possession`' | translate
                }}"
                *ngIf="!trustedCertificate.proofOfPossessionValid"
              >
                <div class="icon-flex">
                  <i
                    class="text-warning"
                    c8yIcon="warning"
                  ></i>
                  {{ 'Incomplete`proof of possession`' | translate }}
                </div>
              </span>
            </span>
          </div>
          <button
            class="m-l-auto btn-dot btn-dot--danger btn showOnHover m-r-8"
            [attr.aria-label]="'Delete' | translate"
            tooltip="{{ 'Delete' | translate }}"
            placement="right"
            type="button"
            data-cy="c8y-trusted-certificate--delete"
            [delay]="500"
            (click)="deleteTrustedCertificate(trustedCertificate)"
            [disabled]="!(hasAdminRole$ | async)"
          >
            <i c8yIcon="delete"></i>
          </button>
        </div>
      </c8y-li-body>

      <c8y-li-collapse>
        <div class="p-t-16 p-b-16">
          <div class="row">
            <div class="col-md-4">
              <c8y-form-group>
                <label class="control-label">
                  {{ 'Certificate name' | translate }}
                </label>
                <div class="input-group input-group-editable">
                  <input
                    class="form-control"
                    type="text"
                    required
                    data-cy="c8y-trusted-certificates--edit-certificate-name"
                    [(ngModel)]="trustedCertificate.name"
                    [disabled]="!(hasAdminRole$ | async)"
                  />
                  <span></span>
                  <div class="input-group-btn">
                    <button
                      class="btn btn-primary"
                      title="{{ 'Update certificate name' | translate }}"
                      type="button"
                      (click)="
                        updateCertificate(trustedCertificate, { name: trustedCertificate.name })
                      "
                      [disabled]="!trustedCertificate.name"
                    >
                      {{ 'Save' | translate }}
                    </button>
                  </div>
                </div>
              </c8y-form-group>
            </div>
            <div class="col-md-1"></div>
            <div class="col-md-7">
              <c8y-form-group>
                <label
                  class="control-label"
                  for="certInPemFormat"
                  translate
                >
                  Certificate
                </label>
                <textarea
                  class="form-control no-resize"
                  id="certInPemFormat"
                  name="certInPemFormat"
                  type="text"
                  rows="7"
                  readonly
                  [(ngModel)]="trustedCertificate.certInPemFormat"
                ></textarea>
              </c8y-form-group>
              <c8y-form-group>
                <label
                  class="c8y-checkbox"
                  title="{{ 'Auto registration' | translate }}"
                  [ngClass]="{
                    disabled: !(hasAdminRole$ | async)
                  }"
                >
                  <input
                    type="checkbox"
                    [(ngModel)]="trustedCertificate.autoRegistrationEnabled"
                    (ngModelChange)="
                      updateCertificate(trustedCertificate, { autoRegistrationEnabled: $event })
                    "
                    [disabled]="!(hasAdminRole$ | async)"
                  />
                  <span></span>
                  <span>{{ 'Auto registration' | translate }}</span>
                  <button
                    class="btn-help btn-help--sm"
                    [attr.aria-label]="'Help' | translate"
                    popover="{{ AUTO_REGISTRATION_POPOVER | translate }}"
                    placement="right"
                    triggers="focus"
                    container="body"
                    type="button"
                    type="button"
                  ></button>
                </label>
              </c8y-form-group>
            </div>
          </div>
          <div class="row">
            <div class="col-md-4">
              <div
                class="legend form-block"
                translate
              >
                Additional properties
              </div>
              <ul class="list-unstyled">
                <li class="p-t-4 p-b-4 d-flex separator-bottom flex-wrap">
                  <label class="small m-b-0 m-r-8 a-s-start flex-grow">
                    {{ 'Algorithm' | translate }}
                  </label>
                  <span class="m-l-auto text-break-word">
                    {{ trustedCertificate.algorithmName }}
                  </span>
                </li>
                <li class="p-t-4 p-b-4 d-flex separator-bottom flex-wrap">
                  <label class="small m-b-0 m-r-8 a-s-start flex-grow">
                    {{ 'Version' | translate }}
                  </label>
                  <span class="m-l-auto text-break-word">
                    {{ trustedCertificate.version }}
                  </span>
                </li>
                <li class="p-t-4 p-b-4 d-flex separator-bottom flex-wrap">
                  <label class="small m-b-0 m-r-8 a-s-start flex-grow">
                    {{ 'Valid from' | translate }}
                  </label>
                  <span class="m-l-auto text-break-word">
                    {{ trustedCertificate.notBefore | c8yDate }}
                  </span>
                </li>
                <li class="p-t-4 p-b-4 d-flex separator-bottom flex-wrap">
                  <label class="small m-b-0 m-r-8 a-s-start flex-grow">
                    {{ 'Issuer' | translate }}
                  </label>
                  <span class="m-l-auto text-break-word">
                    {{ trustedCertificate.issuer }}
                  </span>
                </li>
                <li class="p-t-4 p-b-4 d-flex separator-bottom flex-wrap">
                  <label class="small m-b-0 m-r-8 a-s-start flex-grow">
                    {{ 'Expiration date' | translate }}
                  </label>
                  <span class="m-l-auto text-break-word">
                    {{ trustedCertificate.notAfter | c8yDate }}
                  </span>
                </li>
                <li class="p-t-4 p-b-4 d-flex separator-bottom flex-wrap">
                  <label class="small m-b-0 m-r-8 a-s-start flex-grow">
                    {{ 'Serial number' | translate }}
                  </label>
                  <span class="m-l-auto text-break-word">
                    {{ trustedCertificate.serialNumber }}
                  </span>
                </li>
                <li class="p-t-4 p-b-4 d-flex separator-bottom flex-wrap">
                  <label class="small m-b-0 m-r-8 a-s-start flex-grow">
                    {{ 'Subject`of a certificate`' | translate }}
                  </label>
                  <span class="m-l-auto text-break-word">
                    {{ trustedCertificate.subject }}
                  </span>
                </li>
              </ul>
            </div>
            <div class="col-md-1"></div>
            <div
              class="col-md-7"
              *ngIf="!trustedCertificate.tenantCertificateAuthority"
            >
              <div class="legend form-block">
                {{ 'Proof of possession' | translate }}
                <button
                  class="btn-help btn-help--sm"
                  [attr.aria-label]="'Help' | translate"
                  popover="{{ PROOF_OF_POSSESSION_POPOVER | translate }}"
                  placement="right"
                  triggers="focus"
                  container="body"
                  type="button"
                  type="button"
                ></button>
              </div>
              <div *ngIf="trustedCertificate.proofOfPossessionValid">
                <span
                  class="icon-flex"
                  title="{{ 'Proof of possession' | translate }}:  {{
                    'Complete`proof of possession`' | translate
                  }}"
                >
                  <i
                    class="text-success"
                    c8yIcon="success"
                  ></i>
                  {{ 'Complete`proof of possession`' | translate }}
                </span>
              </div>
              <div *ngIf="!trustedCertificate.proofOfPossessionValid">
                <div class="row m-b-16">
                  <div class="col-md-6">
                    <span
                      class="icon-flex"
                      title="{{ 'Proof of possession' | translate }}:  {{
                        'Incomplete`proof of possession`' | translate
                      }}"
                    >
                      <i
                        class="text-warning"
                        c8yIcon="warning"
                      ></i>
                      {{ 'Incomplete`proof of possession`' | translate }}
                    </span>
                  </div>
                  <div class="col-md-6 col-lg-6 text-right-md">
                    <span class="text-label-small m-r-4">
                      {{ 'Verification code expires/expired on' | translate }}
                    </span>
                    {{
                      (trustedCertificate.proofOfPossessionVerificationCodeUsableUntil | c8yDate) ||
                        '---'
                    }}
                  </div>
                </div>
                <div class="row">
                  <div class="col-md-6 col-lg-6">
                    <c8y-form-group>
                      <label
                        class="control-label"
                        for="unsignedVerificationCode"
                        translate
                      >
                        Verification code
                      </label>
                      <textarea
                        class="form-control no-resize"
                        id="unsignedVerificationCode"
                        name="unsignedVerificationCode"
                        type="text"
                        rows="5"
                        readonly
                        [(ngModel)]="trustedCertificate.proofOfPossessionUnsignedVerificationCode"
                      ></textarea>
                    </c8y-form-group>
                    <div class="d-flex">
                      <button
                        class="btn btn-primary btn-sm"
                        title="{{ 'Regenerate verification code' | translate }}"
                        type="button"
                        (click)="regenerateUnsignedVerificationCode(trustedCertificate)"
                        [disabled]="!(hasAdminRole$ | async)"
                      >
                        {{ 'Regenerate`verification code`' | translate }}
                      </button>

                      <button
                        class="btn btn-sm btn-default m-l-auto m-r-0"
                        [attr.aria-label]="'Copy to clipboard' | translate"
                        tooltip="{{ 'Copy to clipboard' | translate }}"
                        placement="right"
                        type="button"
                        data-cy="c8y-trusted-certificates--copy-to-clipboard"
                        [delay]="500"
                        [disabled]="!trustedCertificate.proofOfPossessionUnsignedVerificationCode"
                        (click)="copyUnsignedVerificationCodeToClipboard(trustedCertificate)"
                      >
                        <i c8yIcon="clipboard"></i>
                      </button>
                      <button
                        class="btn btn-default btn-sm"
                        [attr.aria-label]="'Download as file' | translate"
                        tooltip="{{ 'Download as file' | translate }}"
                        type="button"
                        data-cy="c8y-trusted-certificates--download-as-file"
                        [delay]="500"
                        [disabled]="!trustedCertificate.proofOfPossessionUnsignedVerificationCode"
                        (click)="downloadUnsignedVerificationCode(trustedCertificate)"
                        c8yProductExperience
                        [actionName]="PRODUCT_EXPERIENCE.EVENT"
                        [actionData]="{
                          component: PRODUCT_EXPERIENCE.VERIFICATION_CODE.COMPONENTS.DOWNLOAD_CODE,
                          action: PRODUCT_EXPERIENCE.VERIFICATION_CODE.ACTIONS.DOWNLOAD
                        }"
                      >
                        <i c8yIcon="download"></i>
                      </button>
                    </div>
                  </div>

                  <div class="col-md-6 col-lg-6">
                    <c8y-form-group>
                      <label
                        class="control-label"
                        for="signedVerificationCode"
                      >
                        {{ 'Signed verification code' | translate }}
                        <button
                          class="btn-help btn-help--sm"
                          [attr.aria-label]="'Help' | translate"
                          popover="{{ SIGNED_VERIFICATION_CODE_POPOVER | translate }}"
                          placement="top"
                          container="body"
                          type="button"
                          data-cy="c8y-trusted-certificates--signed-verification-code-popup"
                          [outsideClick]="true"
                        ></button>
                      </label>
                      <textarea
                        class="form-control no-resize"
                        id="signedVerificationCode"
                        name="signedVerificationCode"
                        type="text"
                        rows="5"
                        [(ngModel)]="trustedCertificate.signedVerificationCode"
                      ></textarea>
                    </c8y-form-group>
                    <div class="d-flex">
                      <button
                        class="btn btn-primary btn-sm"
                        title="{{ 'Verify signed verification code' | translate }}"
                        type="button"
                        (click)="verifySignedVerificationCode(trustedCertificate)"
                        [disabled]="!trustedCertificate.signedVerificationCode"
                      >
                        {{ 'Verify`signed verification code`' | translate }}
                      </button>
                      <button
                        class="btn btn-sm btn-default m-l-auto"
                        [attr.aria-label]="'Upload file' | translate"
                        tooltip="{{ 'Upload file' | translate }}"
                        type="button"
                        [delay]="500"
                        (click)="fileInput.click()"
                        [disabled]="!(hasAdminRole$ | async)"
                      >
                        <i c8yIcon="upload"></i>
                      </button>
                      <input
                        class="hidden"
                        type="file"
                        #fileInput
                        (change)="onFileInput($event, trustedCertificate)"
                      />
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </c8y-li-collapse>
    </c8y-li>
  </c8y-list-group>
</div>

results matching ""

    No results matching ""