@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
177 lines (170 loc) • 20.3 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, Component, NgModule } from '@angular/core';
import * as i1$1 from '@c8y/ngx-components';
import { PX_ACTIONS, gettext, Status, CoreModule, hookRoute, ViewContext } from '@c8y/ngx-components';
import { PopoverModule } from 'ngx-bootstrap/popover';
import { TooltipModule } from 'ngx-bootstrap/tooltip';
import { ButtonsModule } from 'ngx-bootstrap/buttons';
import { ReactiveFormsModule } from '@angular/forms';
import * as i1 from '@c8y/client';
import * as i4 from '@angular/router';
import { BehaviorSubject } from 'rxjs';
import { tap, map, switchMap, shareReplay, finalize } from 'rxjs/operators';
import * as i5 from '@ngx-translate/core';
import * as i6 from '@angular/common';
class DeviceProvisionedCertificatesService {
constructor(userService, client) {
this.userService = userService;
this.client = client;
}
async getDeviceProvisionedCertificates(device) {
const deviceId = await this.getDeviceUserName(device);
const { data } = await this.userService.detail(deviceId, { withCertificates: true });
return data.provisionedCertificates;
}
async getDeviceUserName(device) {
const method = 'GET';
const url = `/inventory/managedObjects/${device.id}/user`;
const res = await this.client.fetch(url, { method });
const data = await res.json();
if (res.status > 400) {
throw new Error(data.message);
}
return data.userName;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceProvisionedCertificatesService, deps: [{ token: i1.UserService }, { token: i1.FetchClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceProvisionedCertificatesService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceProvisionedCertificatesService, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.UserService }, { type: i1.FetchClient }] });
class DeviceProvisionedCertificatesGuard {
constructor(deviceProvisionedCertificatesService) {
this.deviceProvisionedCertificatesService = deviceProvisionedCertificatesService;
}
async canActivate(route) {
const contextData = route.data.contextData || route.parent.data.contextData;
if (!contextData) {
return false;
}
try {
const provisionedCertificates = await this.deviceProvisionedCertificatesService.getDeviceProvisionedCertificates(contextData);
return provisionedCertificates && provisionedCertificates.length > 0;
}
catch (error) {
return false;
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceProvisionedCertificatesGuard, deps: [{ token: DeviceProvisionedCertificatesService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceProvisionedCertificatesGuard }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceProvisionedCertificatesGuard, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: DeviceProvisionedCertificatesService }] });
class DeviceTabProvisionedCertificatesComponent {
constructor(alertService, modalService, deviceSerialsService, crlService, route, translateService) {
this.alertService = alertService;
this.modalService = modalService;
this.deviceSerialsService = deviceSerialsService;
this.crlService = crlService;
this.route = route;
this.translateService = translateService;
this.reloading = false;
this.reload = new BehaviorSubject(null);
this.provisionedCertificates = this.reload.pipe(tap(() => {
this.reloading = true;
}), map(() => this.route.snapshot.parent.data.contextData), switchMap(device => this.deviceSerialsService.getDeviceProvisionedCertificates(device)), tap(() => {
this.reloading = false;
}), shareReplay(1), finalize(() => {
this.reloading = false;
}));
this.PX_ACTIONS = PX_ACTIONS;
}
ngOnInit() {
this.reload.next();
}
highlightDependingOnExpirationStatus(item) {
const warningOffset = 24 * 60 * 60 * 1000 * 90; // 90 days
const todayTimestamp = new Date().getTime();
const warningTimestamp = new Date().getTime() + warningOffset;
const notAfterTimestamp = new Date(item.validTill).getTime();
const expired = notAfterTimestamp < todayTimestamp;
const expiresInLessThan90Days = notAfterTimestamp < warningTimestamp;
if (expired) {
return 'text-danger';
}
if (expiresInLessThan90Days) {
return 'text-warning';
}
return '';
}
async revokeProvisionedCertificate(provisionedCertificate) {
if (provisionedCertificate) {
try {
const serialNumberInHex = provisionedCertificate.serialNumber;
await this.confirmRevocation(serialNumberInHex);
await this.crlService.uploadCrls([{ serialNumberInHex }]);
}
catch (error) {
this.alertService.addServerFailure(error);
}
finally {
this.reload.next();
}
}
}
async confirmRevocation(serialNumber) {
return await this.modalService.confirm(gettext('Revoke provisioned certificate'), this.translateService.instant(gettext(`You are about to revoke provisioned certificate {{ serialNumber }}. Do you want to proceed?`), { serialNumber }), Status.DANGER, { ok: gettext('Revoke'), cancel: gettext('Cancel') });
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceTabProvisionedCertificatesComponent, deps: [{ token: i1$1.AlertService }, { token: i1$1.ModalService }, { token: DeviceProvisionedCertificatesService }, { token: i1.CrlService }, { token: i4.ActivatedRoute }, { token: i5.TranslateService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DeviceTabProvisionedCertificatesComponent, selector: "device-tab-serials-component", ngImport: i0, template: "<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Reload' | translate }}\"\n type=\"button\"\n (click)=\"reload.next()\"\n >\n <i\n c8yIcon=\"refresh\"\n [ngClass]=\"{ 'icon-spin': reloading }\"\n ></i>\n {{ 'Reload' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<!-- TODO: Add link to the mentioned documentation when it's available -->\n<c8y-ui-empty-state\n [icon]=\"'certificate'\"\n [title]=\"'No provisioned certificates to display.' | translate\"\n *ngIf=\"(provisionedCertificates | async)?.length === 0\"\n></c8y-ui-empty-state>\n\n<div\n [ngStyle]=\"{ width: '50%' }\"\n *ngIf=\"(provisionedCertificates | async)?.length > 0\"\n>\n <div class=\"bg-level-0\">\n <div class=\"card-header separator\">\n <div\n class=\"card-title\"\n translate\n >\n Provisioned certificates\n </div>\n </div>\n <div class=\"p-16\">\n <c8y-list-group class=\"m-b-24\">\n <div\n class=\"page-sticky-header hidden-xs c8y-list__item\"\n style=\"display: block !important\"\n >\n <div class=\"c8y-list__item__block\">\n <div class=\"c8y-list__item__body\">\n <div class=\"content-flex-60\">\n <div class=\"col-5\">\n <span\n class=\"text-truncate\"\n title=\" {{ 'Serial No.' | translate }} \"\n >\n {{ 'Serial No.' | translate }}\n </span>\n </div>\n <div class=\"col-6\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Expiration date' | translate }}\"\n >\n {{ 'Expiration date' | translate }}\n </span>\n </div>\n <div class=\"col-1\"></div>\n </div>\n </div>\n </div>\n </div>\n\n <c8y-li\n *ngFor=\"let provisionedCertificate of provisionedCertificates | async; let i = index\"\n >\n <c8y-li-body class=\"content-flex-60\">\n <div class=\"col-5\">\n <div\n class=\"text-truncate\"\n title=\"{{ 'Serial No.' | translate }}: {{ provisionedCertificate.serialNumber }}\"\n >\n <span\n class=\"text-label-small m-t-8 m-r-8 visible-xs-inline\"\n translate\n >\n Serial No.\n </span>\n {{ provisionedCertificate.serialNumber }}\n </div>\n </div>\n\n <div class=\"col-6\">\n <div\n class=\"text-truncate\"\n title=\"{{ 'Expiration date' | translate }}: {{\n provisionedCertificate.validTill | c8yDate\n }}\"\n >\n <span\n class=\"text-label-small m-t-8 m-r-8 visible-xs-inline\"\n translate\n >\n Expiration date\n </span>\n <small\n *ngIf=\"provisionedCertificate.validTill\"\n [ngClass]=\"highlightDependingOnExpirationStatus(provisionedCertificate)\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"calendar\"\n *ngIf=\"!highlightDependingOnExpirationStatus(provisionedCertificate)\"\n ></i>\n <i\n class=\"m-r-4\"\n c8yIcon=\"warning\"\n *ngIf=\"highlightDependingOnExpirationStatus(provisionedCertificate)\"\n ></i>\n <span>{{ provisionedCertificate.validTill | c8yDate }}</span>\n </small>\n </div>\n </div>\n <div class=\"col-1\">\n <button\n class=\"btn btn-dot btn-dot--danger\"\n title=\"{{ 'Revoke' | translate }}\"\n type=\"button\"\n (click)=\"revokeProvisionedCertificate(provisionedCertificate)\"\n >\n <i c8yIcon=\"delete\"></i>\n </button>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "component", type: i1$1.ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "component", type: i1$1.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i1$1.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i1$1.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i6.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i1$1.ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: i1$1.ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: i1$1.ListItemBodyComponent, selector: "c8y-list-item-body, c8y-li-body", inputs: ["body"] }, { kind: "pipe", type: i1$1.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.DatePipe, name: "c8yDate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceTabProvisionedCertificatesComponent, decorators: [{
type: Component,
args: [{ selector: 'device-tab-serials-component', template: "<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Reload' | translate }}\"\n type=\"button\"\n (click)=\"reload.next()\"\n >\n <i\n c8yIcon=\"refresh\"\n [ngClass]=\"{ 'icon-spin': reloading }\"\n ></i>\n {{ 'Reload' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<!-- TODO: Add link to the mentioned documentation when it's available -->\n<c8y-ui-empty-state\n [icon]=\"'certificate'\"\n [title]=\"'No provisioned certificates to display.' | translate\"\n *ngIf=\"(provisionedCertificates | async)?.length === 0\"\n></c8y-ui-empty-state>\n\n<div\n [ngStyle]=\"{ width: '50%' }\"\n *ngIf=\"(provisionedCertificates | async)?.length > 0\"\n>\n <div class=\"bg-level-0\">\n <div class=\"card-header separator\">\n <div\n class=\"card-title\"\n translate\n >\n Provisioned certificates\n </div>\n </div>\n <div class=\"p-16\">\n <c8y-list-group class=\"m-b-24\">\n <div\n class=\"page-sticky-header hidden-xs c8y-list__item\"\n style=\"display: block !important\"\n >\n <div class=\"c8y-list__item__block\">\n <div class=\"c8y-list__item__body\">\n <div class=\"content-flex-60\">\n <div class=\"col-5\">\n <span\n class=\"text-truncate\"\n title=\" {{ 'Serial No.' | translate }} \"\n >\n {{ 'Serial No.' | translate }}\n </span>\n </div>\n <div class=\"col-6\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Expiration date' | translate }}\"\n >\n {{ 'Expiration date' | translate }}\n </span>\n </div>\n <div class=\"col-1\"></div>\n </div>\n </div>\n </div>\n </div>\n\n <c8y-li\n *ngFor=\"let provisionedCertificate of provisionedCertificates | async; let i = index\"\n >\n <c8y-li-body class=\"content-flex-60\">\n <div class=\"col-5\">\n <div\n class=\"text-truncate\"\n title=\"{{ 'Serial No.' | translate }}: {{ provisionedCertificate.serialNumber }}\"\n >\n <span\n class=\"text-label-small m-t-8 m-r-8 visible-xs-inline\"\n translate\n >\n Serial No.\n </span>\n {{ provisionedCertificate.serialNumber }}\n </div>\n </div>\n\n <div class=\"col-6\">\n <div\n class=\"text-truncate\"\n title=\"{{ 'Expiration date' | translate }}: {{\n provisionedCertificate.validTill | c8yDate\n }}\"\n >\n <span\n class=\"text-label-small m-t-8 m-r-8 visible-xs-inline\"\n translate\n >\n Expiration date\n </span>\n <small\n *ngIf=\"provisionedCertificate.validTill\"\n [ngClass]=\"highlightDependingOnExpirationStatus(provisionedCertificate)\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"calendar\"\n *ngIf=\"!highlightDependingOnExpirationStatus(provisionedCertificate)\"\n ></i>\n <i\n class=\"m-r-4\"\n c8yIcon=\"warning\"\n *ngIf=\"highlightDependingOnExpirationStatus(provisionedCertificate)\"\n ></i>\n <span>{{ provisionedCertificate.validTill | c8yDate }}</span>\n </small>\n </div>\n </div>\n <div class=\"col-1\">\n <button\n class=\"btn btn-dot btn-dot--danger\"\n title=\"{{ 'Revoke' | translate }}\"\n type=\"button\"\n (click)=\"revokeProvisionedCertificate(provisionedCertificate)\"\n >\n <i c8yIcon=\"delete\"></i>\n </button>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n </div>\n </div>\n</div>\n" }]
}], ctorParameters: () => [{ type: i1$1.AlertService }, { type: i1$1.ModalService }, { type: DeviceProvisionedCertificatesService }, { type: i1.CrlService }, { type: i4.ActivatedRoute }, { type: i5.TranslateService }] });
class DeviceProvisionedCertificatesModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceProvisionedCertificatesModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: DeviceProvisionedCertificatesModule, declarations: [DeviceTabProvisionedCertificatesComponent], imports: [CoreModule, TooltipModule, ReactiveFormsModule, ButtonsModule, PopoverModule] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceProvisionedCertificatesModule, providers: [
hookRoute([
{
context: ViewContext.Device,
path: 'device-provisioned-certificates',
component: DeviceTabProvisionedCertificatesComponent,
label: gettext('x509'),
icon: 'c8y-device-profile',
canActivate: [DeviceProvisionedCertificatesGuard]
}
]),
DeviceProvisionedCertificatesService,
DeviceProvisionedCertificatesGuard
], imports: [CoreModule, TooltipModule, ReactiveFormsModule, ButtonsModule, PopoverModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceProvisionedCertificatesModule, decorators: [{
type: NgModule,
args: [{
declarations: [DeviceTabProvisionedCertificatesComponent],
exports: [],
imports: [CoreModule, TooltipModule, ReactiveFormsModule, ButtonsModule, PopoverModule],
providers: [
hookRoute([
{
context: ViewContext.Device,
path: 'device-provisioned-certificates',
component: DeviceTabProvisionedCertificatesComponent,
label: gettext('x509'),
icon: 'c8y-device-profile',
canActivate: [DeviceProvisionedCertificatesGuard]
}
]),
DeviceProvisionedCertificatesService,
DeviceProvisionedCertificatesGuard
]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { DeviceProvisionedCertificatesModule };
//# sourceMappingURL=c8y-ngx-components-device-provisioned-certificates.mjs.map