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: unknown)
Parameters :
Name Type Optional
certificate unknown 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: unknown, trustedCertificate: TrustedCertificate)
Parameters :
Name Type Optional
event unknown 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
Type : unknown
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
Type : unknown
Default value : false
certificateAuthorityFeatureEnabled
Type : unknown
Default value : false
hasAdminRole$
Type : unknown
Default value : from(this.guard.hasAdminRole()).pipe(shareReplay(1))
hasReadRole$
Type : unknown
Default value : from(this.guard.hasReadRole()).pipe(shareReplay(1))
PRODUCT_EXPERIENCE
Type : unknown
Default value : PRODUCT_EXPERIENCE_TRUSTED_CERTIFICATES
PROOF_OF_POSSESSION_POPOVER
Type : unknown
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
Type : unknown
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) )
@if ((hasReadRole$ | async) || (hasAdminRole$ | async)) {
  <div>
    <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>

    @if (certificateAuthorityFeatureEnabled) {
      <c8y-action-bar-item
        [placement]="'right'"
        [priority]="1000"
      >
        <button
          class="btn btn-link"
          title="{{ 'Generate CA certificate' | translate }}"
          type="button"
          data-cy="trusted-certificate-list--generate-ca-certificate"
          [disabled]="!(hasAdminRole$ | async) || certificateAuthorityExists"
          (click)="addCACertificate()"
        >
          <i c8yIcon="contract"></i>
          {{ 'Generate CA certificate' | translate }}
        </button>
        <button
          class="btn-help btn-help--sm"
          [attr.aria-label]="'Help' | translate"
          popover="{{
            'The Certificate Authority (CA) certificate is used to sign device certificates for secure authentication. Only one CA certificate can be generated for the tenant.'
              | translate
          }}"
          placement="bottom"
          triggers="focus"
          type="button"
        ></button>
      </c8y-action-bar-item>
    }

    <c8y-action-bar-item
      [placement]="'right'"
      [priority]="900"
    >
      <button
        class="btn btn-link"
        title="{{ 'Add trusted certificate' | translate }}"
        type="button"
        data-cy="trusted-certificate-list--add-trusted-certificate"
        (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'"
      [priority]="800"
    >
      <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>

    @if ((trustedCertificates | async)?.data.length === 0) {
      <c8y-ui-empty-state
        [icon]="'certificate'"
        [title]="'No trusted certificates to display.' | translate"
        [subtitle]="'Add your first certificate by clicking below.' | translate"
      >
        <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">
      @if ((trustedCertificates | async)?.data.length > 0) {
        <div class="page-sticky-header hidden-xs c8y-list__item c8y-list__item--empty-actions">
          <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>
          @if (!trustedCertificate.tenantCertificateAuthority) {
            <button
              class="btn-clean"
              attr.aria-label="{{ 'Certificate' | translate }}"
              tooltip="{{ 'Certificate' | translate }}"
              type="button"
              [delay]="500"
            >
              <i c8yIcon="certificate"></i>
            </button>
          }
          @if (trustedCertificate.tenantCertificateAuthority) {
            <button
              class="btn-clean"
              attr.aria-label="{{ 'CA certificate' | translate }}"
              tooltip="{{ 'CA certificate' | translate }}"
              type="button"
              [delay]="500"
            >
              <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"
                >
                  @if (expirationHighlight?.expired) {
                    <del>
                      <ng-container *ngTemplateOutlet="expirationDateTpl"></ng-container>
                    </del>
                  } @else {
                    <ng-container *ngTemplateOutlet="expirationDateTpl"></ng-container>
                  }
                  <ng-template #expirationDateTpl>
                    @if (expirationHighlight?.icon) {
                      <i
                        class="m-r-4"
                        c8yIcon="{{ expirationHighlight?.icon }}"
                      ></i>
                    }
                    <span>{{ trustedCertificate.notAfter | c8yDate }}</span>
                  </ng-template>
                </small>
                @if (expirationHighlight?.renewable) {
                  <button
                    class="btn btn-link btn-icon"
                    title="{{ 'Renew certificate' | translate }}"
                    type="button"
                    (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>
              @if (trustedCertificate.autoRegistrationEnabled) {
                <span
                  title="{{ 'Auto registration' | translate }}:  {{
                    'Enabled`auto registration`' | translate
                  }}"
                >
                  {{ 'Enabled`auto registration`' | translate }}
                </span>
              }
              @if (!trustedCertificate.autoRegistrationEnabled) {
                <span
                  title="{{ 'Auto registration' | translate }}:  {{
                    'Disabled`auto registration`' | translate
                  }}"
                >
                  {{ '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"
              ></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>
              @if (trustedCertificate.tenantCertificateAuthority) {
                <span title="{{ 'Proof of possession' | translate }}: {{ 'N/A' | translate }}">
                  {{ 'N/A' | translate }}
                </span>
              }
              @if (!trustedCertificate.tenantCertificateAuthority) {
                <span>
                  @if (trustedCertificate.proofOfPossessionValid) {
                    <span
                      title="{{ 'Proof of possession' | translate }}:  {{
                        'Complete`proof of possession`' | translate
                      }}"
                    >
                      <div class="icon-flex">
                        <i
                          class="text-success"
                          c8yIcon="success"
                        ></i>
                        {{ 'Complete`proof of possession`' | translate }}
                      </div>
                    </span>
                  }
                  @if (!trustedCertificate.proofOfPossessionValid) {
                    <span
                      title="{{ 'Proof of possession' | translate }}:  {{
                        'Incomplete`proof of possession`' | translate
                      }}"
                    >
                      <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>
              @if (!trustedCertificate.tenantCertificateAuthority) {
                <div class="col-md-7">
                  <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>
                  @if (trustedCertificate.proofOfPossessionValid) {
                    <div>
                      <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>
                  }
                  @if (!trustedCertificate.proofOfPossessionValid) {
                    <div>
                      <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 ""