Commit 9d4b79c91cec7273b82cf4b537c7a4172c6e2601

Authored by Igor Kulikov
1 parent c8ec87f4

UI: Audit logs.

Showing 42 changed files with 1125 additions and 35 deletions
... ... @@ -3,7 +3,7 @@
3 3 "version": "3.0.0",
4 4 "scripts": {
5 5 "ng": "ng",
6   - "start": "ng serve --host 0.0.0.0 --open",
  6 + "start": "ng serve --open",
7 7 "build": "ng build",
8 8 "build:prod": "ng build --prod --vendor-chunk",
9 9 "test": "ng test",
... ...
... ... @@ -165,7 +165,14 @@ export class AuthService {
165 165 if (captureLastUrl) {
166 166 this.redirectUrl = this.router.url;
167 167 }
168   - this.clearJwtToken();
  168 + this.http.post('/api/auth/logout', null, defaultHttpOptions(true, true))
  169 + .subscribe(() => {
  170 + this.clearJwtToken();
  171 + },
  172 + () => {
  173 + this.clearJwtToken();
  174 + }
  175 + );
169 176 }
170 177
171 178 private notifyUserLoaded(isUserLoaded: boolean) {
... ...
  1 +///
  2 +/// Copyright © 2016-2019 The Thingsboard Authors
  3 +///
  4 +/// Licensed under the Apache License, Version 2.0 (the "License");
  5 +/// you may not use this file except in compliance with the License.
  6 +/// You may obtain a copy of the License at
  7 +///
  8 +/// http://www.apache.org/licenses/LICENSE-2.0
  9 +///
  10 +/// Unless required by applicable law or agreed to in writing, software
  11 +/// distributed under the License is distributed on an "AS IS" BASIS,
  12 +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +/// See the License for the specific language governing permissions and
  14 +/// limitations under the License.
  15 +///
  16 +
  17 +import { Injectable } from '@angular/core';
  18 +import { defaultHttpOptions } from './http-utils';
  19 +import { Observable } from 'rxjs/index';
  20 +import { HttpClient } from '@angular/common/http';
  21 +import { PageLink, TimePageLink } from '@shared/models/page/page-link';
  22 +import { PageData } from '@shared/models/page/page-data';
  23 +import { AuditLog } from '@shared/models/audit-log.models';
  24 +import { EntityId } from '@shared/models/id/entity-id';
  25 +
  26 +@Injectable({
  27 + providedIn: 'root'
  28 +})
  29 +export class AuditLogService {
  30 +
  31 + constructor(
  32 + private http: HttpClient
  33 + ) { }
  34 +
  35 + public getAuditLogs(pageLink: TimePageLink,
  36 + ignoreErrors: boolean = false, ignoreLoading: boolean = false): Observable<PageData<AuditLog>> {
  37 + return this.http.get<PageData<AuditLog>>(`/api/audit/logs${pageLink.toQuery()}`,
  38 + defaultHttpOptions(ignoreLoading, ignoreErrors));
  39 + }
  40 +
  41 + public getAuditLogsByCustomerId(customerId: string, pageLink: TimePageLink,
  42 + ignoreErrors: boolean = false, ignoreLoading: boolean = false): Observable<PageData<AuditLog>> {
  43 + return this.http.get<PageData<AuditLog>>(`/api/audit/logs/customer/${customerId}${pageLink.toQuery()}`,
  44 + defaultHttpOptions(ignoreLoading, ignoreErrors));
  45 + }
  46 +
  47 + public getAuditLogsByUserId(userId: string, pageLink: TimePageLink,
  48 + ignoreErrors: boolean = false, ignoreLoading: boolean = false): Observable<PageData<AuditLog>> {
  49 + return this.http.get<PageData<AuditLog>>(`/api/audit/logs/user/${userId}${pageLink.toQuery()}`,
  50 + defaultHttpOptions(ignoreLoading, ignoreErrors));
  51 + }
  52 +
  53 + public getAuditLogsByEntityId(entityId: EntityId, pageLink: TimePageLink,
  54 + ignoreErrors: boolean = false, ignoreLoading: boolean = false): Observable<PageData<AuditLog>> {
  55 + return this.http.get<PageData<AuditLog>>(`/api/audit/logs/entity/${entityId.entityType}/${entityId.id}${pageLink.toQuery()}`,
  56 + defaultHttpOptions(ignoreLoading, ignoreErrors));
  57 + }
  58 +
  59 +}
... ...
  1 +<!--
  2 +
  3 + Copyright © 2016-2019 The Thingsboard Authors
  4 +
  5 + Licensed under the Apache License, Version 2.0 (the "License");
  6 + you may not use this file except in compliance with the License.
  7 + You may obtain a copy of the License at
  8 +
  9 + http://www.apache.org/licenses/LICENSE-2.0
  10 +
  11 + Unless required by applicable law or agreed to in writing, software
  12 + distributed under the License is distributed on an "AS IS" BASIS,
  13 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14 + See the License for the specific language governing permissions and
  15 + limitations under the License.
  16 +
  17 +-->
  18 +<mat-toolbar fxLayout="row" color="primary">
  19 + <h2 translate>audit-log.audit-log-details</h2>
  20 + <span fxFlex></span>
  21 + <button mat-button mat-icon-button
  22 + [mat-dialog-close]="false"
  23 + type="button">
  24 + <mat-icon class="material-icons">close</mat-icon>
  25 + </button>
  26 +</mat-toolbar>
  27 +<div mat-dialog-content fxLayout="column">
  28 + <label translate class="tb-title no-padding">audit-log.action-data</label>
  29 + <div #actionDataEditor class="tb-audit-log-action-data">
  30 + </div>
  31 + <span style="min-height: 30px;"></span>
  32 + <label [fxShow]="displayFailureDetails" translate class="tb-title no-padding">audit-log.failure-details</label>
  33 + <div #failureDetailsEditor [fxShow]="displayFailureDetails" class="tb-audit-log-failure-details">
  34 + </div>
  35 +</div>
  36 +<div mat-dialog-actions fxLayout="row">
  37 + <span fxFlex></span>
  38 + <button mat-button color="primary"
  39 + style="margin-right: 20px;"
  40 + type="button"
  41 + [disabled]="(isLoading$ | async)"
  42 + [mat-dialog-close]="false" cdkFocusInitial>
  43 + {{ 'action.close' | translate }}
  44 + </button>
  45 +</div>
... ...
  1 +/**
  2 + * Copyright © 2016-2019 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +:host {
  17 + .tb-audit-log-action-data,
  18 + .tb-audit-log-failure-details {
  19 + width: 100%;
  20 + min-width: 400px;
  21 + height: 100%;
  22 + min-height: 50px;
  23 + border: 1px solid #c0c0c0;
  24 + }
  25 +}
... ...
  1 +///
  2 +/// Copyright © 2016-2019 The Thingsboard Authors
  3 +///
  4 +/// Licensed under the Apache License, Version 2.0 (the "License");
  5 +/// you may not use this file except in compliance with the License.
  6 +/// You may obtain a copy of the License at
  7 +///
  8 +/// http://www.apache.org/licenses/LICENSE-2.0
  9 +///
  10 +/// Unless required by applicable law or agreed to in writing, software
  11 +/// distributed under the License is distributed on an "AS IS" BASIS,
  12 +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +/// See the License for the specific language governing permissions and
  14 +/// limitations under the License.
  15 +///
  16 +
  17 +import {
  18 + Component,
  19 + ElementRef,
  20 + Inject,
  21 + OnInit,
  22 + Renderer2,
  23 + ViewChild
  24 +} from '@angular/core';
  25 +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
  26 +import { PageComponent } from '@shared/components/page.component';
  27 +import { Store } from '@ngrx/store';
  28 +import { AppState } from '@core/core.state';
  29 +import { TbAnchorComponent } from '@shared/components/tb-anchor.component';
  30 +import { ActionStatus, AuditLog } from '@shared/models/audit-log.models';
  31 +
  32 +import * as ace from 'ace-builds';
  33 +
  34 +export interface AuditLogDetailsDialogData {
  35 + auditLog: AuditLog;
  36 +}
  37 +
  38 +@Component({
  39 + selector: 'tb-audit-log-details-dialog',
  40 + templateUrl: './audit-log-details-dialog.component.html',
  41 + styleUrls: ['./audit-log-details-dialog.component.scss']
  42 +})
  43 +export class AuditLogDetailsDialogComponent extends PageComponent implements OnInit {
  44 +
  45 + @ViewChild('actionDataEditor', {static: true})
  46 + actionDataEditorElmRef: ElementRef;
  47 + private actionDataEditor: ace.Ace.Editor;
  48 +
  49 + @ViewChild('failureDetailsEditor', {static: true})
  50 + failureDetailsEditorElmRef: ElementRef;
  51 + private failureDetailsEditor: ace.Ace.Editor;
  52 +
  53 + auditLog: AuditLog;
  54 + displayFailureDetails: boolean;
  55 + actionData: string;
  56 + actionFailureDetails: string;
  57 +
  58 + @ViewChild('entityDetailsForm', {static: true}) entityDetailsFormAnchor: TbAnchorComponent;
  59 +
  60 + constructor(protected store: Store<AppState>,
  61 + @Inject(MAT_DIALOG_DATA) public data: AuditLogDetailsDialogData,
  62 + public dialogRef: MatDialogRef<AuditLogDetailsDialogComponent>,
  63 + private renderer: Renderer2) {
  64 + super(store);
  65 + }
  66 +
  67 + ngOnInit(): void {
  68 + this.auditLog = this.data.auditLog;
  69 + this.displayFailureDetails = this.auditLog.actionStatus === ActionStatus.FAILURE;
  70 + this.actionData = this.auditLog.actionData ? JSON.stringify(this.auditLog.actionData, null, 2) : '';
  71 + this.actionFailureDetails = this.auditLog.actionFailureDetails;
  72 +
  73 + this.actionDataEditor = this.createEditor(this.actionDataEditorElmRef, this.actionData);
  74 + if (this.displayFailureDetails) {
  75 + this.failureDetailsEditor = this.createEditor(this.failureDetailsEditorElmRef, this.actionFailureDetails);
  76 + }
  77 + }
  78 +
  79 + createEditor(editorElementRef: ElementRef, content: string): ace.Ace.Editor {
  80 + const editorElement = editorElementRef.nativeElement;
  81 + let editorOptions: Partial<ace.Ace.EditorOptions> = {
  82 + mode: 'ace/mode/java',
  83 + theme: 'ace/theme/github',
  84 + showGutter: false,
  85 + showPrintMargin: false,
  86 + readOnly: true
  87 + };
  88 +
  89 + const advancedOptions = {
  90 + enableSnippets: false,
  91 + enableBasicAutocompletion: false,
  92 + enableLiveAutocompletion: false
  93 + };
  94 +
  95 + editorOptions = {...editorOptions, ...advancedOptions};
  96 + const editor = ace.edit(editorElement, editorOptions);
  97 + editor.session.setUseWrapMode(false);
  98 + editor.setValue(content, -1);
  99 + this.updateEditorSize(editorElement, content, editor);
  100 + return editor;
  101 + }
  102 +
  103 + updateEditorSize(editorElement: any, content: string, editor: ace.Ace.Editor) {
  104 + let newHeight = 200;
  105 + let newWidth = 600;
  106 + if (content && content.length > 0) {
  107 + const lines = content.split('\n');
  108 + newHeight = 16 * lines.length + 16;
  109 + let maxLineLength = 0;
  110 + lines.forEach((row) => {
  111 + const line = row.replace(/\t/g, ' ').replace(/\n/g, '');
  112 + const lineLength = line.length;
  113 + maxLineLength = Math.max(maxLineLength, lineLength);
  114 + });
  115 + newWidth = 8 * maxLineLength + 16;
  116 + }
  117 + newHeight = Math.min(400, newHeight);
  118 + this.renderer.setStyle(editorElement, 'minHeight', newHeight.toString() + 'px');
  119 + this.renderer.setStyle(editorElement, 'height', newHeight.toString() + 'px');
  120 + this.renderer.setStyle(editorElement, 'width', newWidth.toString() + 'px');
  121 + editor.resize();
  122 + }
  123 +
  124 +}
... ...
  1 +///
  2 +/// Copyright © 2016-2019 The Thingsboard Authors
  3 +///
  4 +/// Licensed under the Apache License, Version 2.0 (the "License");
  5 +/// you may not use this file except in compliance with the License.
  6 +/// You may obtain a copy of the License at
  7 +///
  8 +/// http://www.apache.org/licenses/LICENSE-2.0
  9 +///
  10 +/// Unless required by applicable law or agreed to in writing, software
  11 +/// distributed under the License is distributed on an "AS IS" BASIS,
  12 +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +/// See the License for the specific language governing permissions and
  14 +/// limitations under the License.
  15 +///
  16 +
  17 +import {
  18 + DateEntityTableColumn,
  19 + EntityTableColumn,
  20 + EntityTableConfig
  21 +} from '@home/models/entity/entities-table-config.models';
  22 +import {
  23 + actionStatusTranslations,
  24 + actionTypeTranslations,
  25 + AuditLog,
  26 + AuditLogMode
  27 +} from '@shared/models/audit-log.models';
  28 +import {
  29 + EntityTypeResource,
  30 + EntityTypeTranslation,
  31 + entityTypeTranslations
  32 +} from '@shared/models/entity-type.models';
  33 +import { AuditLogService } from '@core/http/audit-log.service';
  34 +import { TranslateService } from '@ngx-translate/core';
  35 +import { DatePipe } from '@angular/common';
  36 +import { Direction } from '@shared/models/page/sort-order';
  37 +import { MatDialog } from '@angular/material';
  38 +import { PageLink, TimePageLink } from '@shared/models/page/page-link';
  39 +import { Observable } from 'rxjs';
  40 +import { PageData } from '@shared/models/page/page-data';
  41 +import { EntityId } from '@shared/models/id/entity-id';
  42 +import { UserId } from '@shared/models/id/user-id';
  43 +import { CustomerId } from '@shared/models/id/customer-id';
  44 +import {
  45 + AuditLogDetailsDialogComponent,
  46 + AuditLogDetailsDialogData
  47 +} from '@home/components/audit-log/audit-log-details-dialog.component';
  48 +
  49 +export class AuditLogTableConfig extends EntityTableConfig<AuditLog, TimePageLink> {
  50 +
  51 + constructor(private auditLogService: AuditLogService,
  52 + private translate: TranslateService,
  53 + private datePipe: DatePipe,
  54 + private dialog: MatDialog,
  55 + private auditLogMode: AuditLogMode = AuditLogMode.TENANT,
  56 + public entityId: EntityId = null,
  57 + public userId: UserId = null,
  58 + public customerId: CustomerId = null,
  59 + updateOnInit = true) {
  60 + super();
  61 + this.loadDataOnInit = updateOnInit;
  62 + this.tableTitle = '';
  63 + this.useTimePageLink = true;
  64 + this.detailsPanelEnabled = false;
  65 + this.selectionEnabled = false;
  66 + this.searchEnabled = true;
  67 + this.addEnabled = false;
  68 + this.entitiesDeleteEnabled = false;
  69 + this.actionsColumnTitle = 'audit-log.details';
  70 + this.entityTranslations = {
  71 + noEntities: 'audit-log.no-audit-logs-prompt',
  72 + search: 'audit-log.search'
  73 + };
  74 + this.entityResources = {
  75 + } as EntityTypeResource;
  76 +
  77 + this.entitiesFetchFunction = pageLink => this.fetchAuditLogs(pageLink);
  78 +
  79 + this.defaultSortOrder = {property: 'createdTime', direction: Direction.DESC};
  80 +
  81 + this.columns.push(
  82 + new DateEntityTableColumn<AuditLog>('createdTime', 'audit-log.timestamp', this.datePipe, '150px'));
  83 +
  84 + if (this.auditLogMode !== AuditLogMode.ENTITY) {
  85 + this.columns.push(
  86 + new EntityTableColumn<AuditLog>('entityType', 'audit-log.entity-type', '100%',
  87 + (entity) => translate.instant(entityTypeTranslations.get(entity.entityId.entityType).type)),
  88 + new EntityTableColumn<AuditLog>('entityName', 'audit-log.entity-name'),
  89 + );
  90 + }
  91 +
  92 + if (this.auditLogMode !== AuditLogMode.USER) {
  93 + this.columns.push(
  94 + new EntityTableColumn<AuditLog>('userName', 'audit-log.user')
  95 + );
  96 + }
  97 +
  98 + this.columns.push(
  99 + new EntityTableColumn<AuditLog>('actionType', 'audit-log.type', '100%',
  100 + (entity) => translate.instant(actionTypeTranslations.get(entity.actionType))),
  101 + new EntityTableColumn<AuditLog>('actionStatus', 'audit-log.status', '100%',
  102 + (entity) => translate.instant(actionStatusTranslations.get(entity.actionStatus)))
  103 + );
  104 +
  105 + this.cellActionDescriptors.push(
  106 + {
  107 + name: this.translate.instant('audit-log.details'),
  108 + icon: 'more_horiz',
  109 + isEnabled: () => true,
  110 + onAction: ($event, entity) => this.showAuditLogDetails(entity)
  111 + }
  112 + );
  113 + }
  114 +
  115 + fetchAuditLogs(pageLink: TimePageLink): Observable<PageData<AuditLog>> {
  116 + switch (this.auditLogMode) {
  117 + case AuditLogMode.TENANT:
  118 + return this.auditLogService.getAuditLogs(pageLink);
  119 + case AuditLogMode.ENTITY:
  120 + return this.auditLogService.getAuditLogsByEntityId(this.entityId, pageLink);
  121 + case AuditLogMode.USER:
  122 + return this.auditLogService.getAuditLogsByUserId(this.userId.id, pageLink);
  123 + case AuditLogMode.CUSTOMER:
  124 + return this.auditLogService.getAuditLogsByCustomerId(this.customerId.id, pageLink);
  125 + }
  126 + }
  127 +
  128 + showAuditLogDetails(entity: AuditLog) {
  129 + this.dialog.open<AuditLogDetailsDialogComponent, AuditLogDetailsDialogData>(AuditLogDetailsDialogComponent, {
  130 + disableClose: true,
  131 + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
  132 + data: {
  133 + auditLog: entity
  134 + }
  135 + });
  136 + }
  137 +
  138 +}
... ...
  1 +<!--
  2 +
  3 + Copyright © 2016-2019 The Thingsboard Authors
  4 +
  5 + Licensed under the Apache License, Version 2.0 (the "License");
  6 + you may not use this file except in compliance with the License.
  7 + You may obtain a copy of the License at
  8 +
  9 + http://www.apache.org/licenses/LICENSE-2.0
  10 +
  11 + Unless required by applicable law or agreed to in writing, software
  12 + distributed under the License is distributed on an "AS IS" BASIS,
  13 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14 + See the License for the specific language governing permissions and
  15 + limitations under the License.
  16 +
  17 +-->
  18 +<tb-entities-table [entitiesTableConfig]="auditLogTableConfig" [ngClass]="{'tb-details-mode': detailsMode}"></tb-entities-table>
... ...
  1 +/**
  2 + * Copyright © 2016-2019 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +:host ::ng-deep {
  17 + tb-entities-table.tb-details-mode {
  18 + .mat-drawer-container {
  19 + background-color: white;
  20 + }
  21 + }
  22 +}
... ...
  1 +///
  2 +/// Copyright © 2016-2019 The Thingsboard Authors
  3 +///
  4 +/// Licensed under the Apache License, Version 2.0 (the "License");
  5 +/// you may not use this file except in compliance with the License.
  6 +/// You may obtain a copy of the License at
  7 +///
  8 +/// http://www.apache.org/licenses/LICENSE-2.0
  9 +///
  10 +/// Unless required by applicable law or agreed to in writing, software
  11 +/// distributed under the License is distributed on an "AS IS" BASIS,
  12 +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +/// See the License for the specific language governing permissions and
  14 +/// limitations under the License.
  15 +///
  16 +
  17 +import { Component, Input, OnInit, ViewChild } from '@angular/core';
  18 +import { AuditLogService } from '@core/http/audit-log.service';
  19 +import { TranslateService } from '@ngx-translate/core';
  20 +import { DatePipe } from '@angular/common';
  21 +import { MatDialog } from '@angular/material';
  22 +import { AuditLogMode } from '@shared/models/audit-log.models';
  23 +import { EntityId } from '@shared/models/id/entity-id';
  24 +import { UserId } from '@shared/models/id/user-id';
  25 +import { CustomerId } from '@shared/models/id/customer-id';
  26 +import { AuditLogTableConfig } from '@home/components/audit-log/audit-log-table-config';
  27 +import { EntitiesTableComponent } from '@home/components/entity/entities-table.component';
  28 +import { Store } from '@ngrx/store';
  29 +import { AppState } from '@core/core.state';
  30 +import { Authority } from '@shared/models/authority.enum';
  31 +import { getCurrentAuthUser } from '@core/auth/auth.selectors';
  32 +
  33 +@Component({
  34 + selector: 'tb-audit-log-table',
  35 + templateUrl: './audit-log-table.component.html',
  36 + styleUrls: ['./audit-log-table.component.scss']
  37 +})
  38 +export class AuditLogTableComponent implements OnInit {
  39 +
  40 + @Input()
  41 + auditLogMode: AuditLogMode;
  42 +
  43 + @Input()
  44 + detailsMode: boolean;
  45 +
  46 + activeValue = false;
  47 + dirtyValue = false;
  48 + entityIdValue: EntityId;
  49 + userIdValue: UserId;
  50 + customerIdValue: CustomerId;
  51 +
  52 + @Input()
  53 + set active(active: boolean) {
  54 + if (this.activeValue !== active) {
  55 + this.activeValue = active;
  56 + if (this.activeValue && this.dirtyValue) {
  57 + this.dirtyValue = false;
  58 + this.entitiesTable.updateData();
  59 + }
  60 + }
  61 + }
  62 +
  63 + @Input()
  64 + set entityId(entityId: EntityId) {
  65 + this.entityIdValue = entityId;
  66 + if (this.auditLogTableConfig && this.auditLogTableConfig.entityId !== entityId) {
  67 + this.auditLogTableConfig.entityId = entityId;
  68 + this.entitiesTable.resetSortAndFilter(this.activeValue);
  69 + if (!this.activeValue) {
  70 + this.dirtyValue = true;
  71 + }
  72 + }
  73 + }
  74 +
  75 + @Input()
  76 + set userId(userId: UserId) {
  77 + this.userIdValue = userId;
  78 + if (this.auditLogTableConfig && this.auditLogTableConfig.userId !== userId) {
  79 + this.auditLogTableConfig.userId = userId;
  80 + this.entitiesTable.resetSortAndFilter(this.activeValue);
  81 + if (!this.activeValue) {
  82 + this.dirtyValue = true;
  83 + }
  84 + }
  85 + }
  86 +
  87 + @Input()
  88 + set customerId(customerId: CustomerId) {
  89 + this.customerIdValue = customerId;
  90 + if (this.auditLogTableConfig && this.auditLogTableConfig.customerId !== customerId) {
  91 + this.auditLogTableConfig.customerId = customerId;
  92 + this.entitiesTable.resetSortAndFilter(this.activeValue);
  93 + if (!this.activeValue) {
  94 + this.dirtyValue = true;
  95 + }
  96 + }
  97 + }
  98 +
  99 + @ViewChild(EntitiesTableComponent, {static: true}) entitiesTable: EntitiesTableComponent;
  100 +
  101 + auditLogTableConfig: AuditLogTableConfig;
  102 +
  103 + constructor(private auditLogService: AuditLogService,
  104 + private translate: TranslateService,
  105 + private datePipe: DatePipe,
  106 + private dialog: MatDialog,
  107 + private store: Store<AppState>) {
  108 + }
  109 +
  110 + ngOnInit() {
  111 + let updateOnInit = this.activeValue;
  112 + this.dirtyValue = !this.activeValue;
  113 + if (!this.auditLogMode) {
  114 + const authUser = getCurrentAuthUser(this.store);
  115 + if (authUser.authority === Authority.TENANT_ADMIN) {
  116 + this.auditLogMode = AuditLogMode.TENANT;
  117 + }
  118 + updateOnInit = true;
  119 + }
  120 + this.auditLogTableConfig = new AuditLogTableConfig(
  121 + this.auditLogService,
  122 + this.translate,
  123 + this.datePipe,
  124 + this.dialog,
  125 + this.auditLogMode,
  126 + this.entityIdValue,
  127 + this.userIdValue,
  128 + this.customerIdValue,
  129 + updateOnInit
  130 + );
  131 + }
  132 +
  133 +}
... ...
... ... @@ -158,10 +158,10 @@
158 158 [ngStyle]="cellStyle(entity, column, row, col)"></mat-cell>
159 159 </ng-container>
160 160 <ng-container matColumnDef="actions" stickyEnd>
161   - <mat-header-cell *matHeaderCellDef [ngStyle.gt-md]="{ minWidth: (cellActionDescriptors.length * 40) + 'px' }">
  161 + <mat-header-cell *matHeaderCellDef [ngStyle.gt-md]="{ minWidth: (cellActionDescriptors.length * 40) + 'px', maxWidth: (cellActionDescriptors.length * 40) + 'px' }">
162 162 {{ entitiesTableConfig.actionsColumnTitle ? (entitiesTableConfig.actionsColumnTitle | translate) : '' }}
163 163 </mat-header-cell>
164   - <mat-cell *matCellDef="let entity" [ngStyle.gt-md]="{ minWidth: (cellActionDescriptors.length * 40) + 'px' }">
  164 + <mat-cell *matCellDef="let entity" [ngStyle.gt-md]="{ minWidth: (cellActionDescriptors.length * 40) + 'px', maxWidth: (cellActionDescriptors.length * 40) + 'px' }">
165 165 <div fxHide fxShow.gt-md fxFlex fxLayout="row" fxLayoutAlign="end">
166 166 <button mat-button mat-icon-button [disabled]="isLoading$ | async"
167 167 [fxShow]="actionDescriptor.isEnabled(entity)" *ngFor="let actionDescriptor of cellActionDescriptors"
... ...
... ... @@ -32,9 +32,22 @@ import { EntityTableConfig } from '@home/models/entity/entities-table-config.mod
32 32 import { MatTab } from '@angular/material';
33 33 import { EntityAction } from '@home/models/entity/entity-component.models';
34 34 import { BehaviorSubject } from 'rxjs';
  35 +import { Authority } from '@app/shared/models/authority.enum';
  36 +import { selectAuthUser, getCurrentAuthUser } from '@core/auth/auth.selectors';
  37 +import { AuthUser } from '@shared/models/user.model';
  38 +import { EntityType } from '@shared/models/entity-type.models';
  39 +import { AuditLogMode } from '@shared/models/audit-log.models';
35 40
36 41 export abstract class EntityTabsComponent<T extends BaseData<HasId>> extends PageComponent implements OnInit, AfterViewInit {
37 42
  43 + authorities = Authority;
  44 +
  45 + entityTypes = EntityType;
  46 +
  47 + auditLogModes = AuditLogMode;
  48 +
  49 + authUser: AuthUser;
  50 +
38 51 entityValue: T;
39 52
40 53 @ViewChildren(MatTab) entityTabs: QueryList<MatTab>;
... ... @@ -68,6 +81,7 @@ export abstract class EntityTabsComponent<T extends BaseData<HasId>> extends Pag
68 81
69 82 protected constructor(protected store: Store<AppState>) {
70 83 super(store);
  84 + this.authUser = getCurrentAuthUser(store);
71 85 }
72 86
73 87 ngOnInit() {
... ...
... ... @@ -22,10 +22,13 @@ import {EntitiesTableComponent} from './entity/entities-table.component';
22 22 import {DetailsPanelComponent} from './details-panel.component';
23 23 import {EntityDetailsPanelComponent} from './entity/entity-details-panel.component';
24 24 import {ContactComponent} from './contact.component';
  25 +import { AuditLogDetailsDialogComponent } from './audit-log/audit-log-details-dialog.component';
  26 +import { AuditLogTableComponent } from './audit-log/audit-log-table.component';
25 27
26 28 @NgModule({
27 29 entryComponents: [
28   - AddEntityDialogComponent
  30 + AddEntityDialogComponent,
  31 + AuditLogDetailsDialogComponent
29 32 ],
30 33 declarations:
31 34 [
... ... @@ -34,6 +37,8 @@ import {ContactComponent} from './contact.component';
34 37 DetailsPanelComponent,
35 38 EntityDetailsPanelComponent,
36 39 ContactComponent,
  40 + AuditLogTableComponent,
  41 + AuditLogDetailsDialogComponent
37 42 ],
38 43 imports: [
39 44 CommonModule,
... ... @@ -44,7 +49,8 @@ import {ContactComponent} from './contact.component';
44 49 AddEntityDialogComponent,
45 50 DetailsPanelComponent,
46 51 EntityDetailsPanelComponent,
47   - ContactComponent
  52 + ContactComponent,
  53 + AuditLogTableComponent
48 54 ]
49 55 })
50 56 export class HomeComponentsModule { }
... ...
  1 +<!--
  2 +
  3 + Copyright © 2016-2019 The Thingsboard Authors
  4 +
  5 + Licensed under the Apache License, Version 2.0 (the "License");
  6 + you may not use this file except in compliance with the License.
  7 + You may obtain a copy of the License at
  8 +
  9 + http://www.apache.org/licenses/LICENSE-2.0
  10 +
  11 + Unless required by applicable law or agreed to in writing, software
  12 + distributed under the License is distributed on an "AS IS" BASIS,
  13 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14 + See the License for the specific language governing permissions and
  15 + limitations under the License.
  16 +
  17 +-->
  18 +<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
  19 + label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab">
  20 + <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id" detailsMode="true"></tb-audit-log-table>
  21 +</mat-tab>
... ...
  1 +///
  2 +/// Copyright © 2016-2019 The Thingsboard Authors
  3 +///
  4 +/// Licensed under the Apache License, Version 2.0 (the "License");
  5 +/// you may not use this file except in compliance with the License.
  6 +/// You may obtain a copy of the License at
  7 +///
  8 +/// http://www.apache.org/licenses/LICENSE-2.0
  9 +///
  10 +/// Unless required by applicable law or agreed to in writing, software
  11 +/// distributed under the License is distributed on an "AS IS" BASIS,
  12 +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +/// See the License for the specific language governing permissions and
  14 +/// limitations under the License.
  15 +///
  16 +
  17 +import { Component } from '@angular/core';
  18 +import { Store } from '@ngrx/store';
  19 +import { AppState } from '@core/core.state';
  20 +import { EntityTabsComponent } from '../../components/entity/entity-tabs.component';
  21 +import { AssetInfo } from '@app/shared/models/asset.models';
  22 +
  23 +@Component({
  24 + selector: 'tb-asset-tabs',
  25 + templateUrl: './asset-tabs.component.html',
  26 + styleUrls: []
  27 +})
  28 +export class AssetTabsComponent extends EntityTabsComponent<AssetInfo> {
  29 +
  30 + constructor(protected store: Store<AppState>) {
  31 + super(store);
  32 + }
  33 +
  34 + ngOnInit() {
  35 + super.ngOnInit();
  36 + }
  37 +
  38 +}
... ...
... ... @@ -22,14 +22,17 @@ import {AssetComponent} from './asset.component';
22 22 import {AssetTableHeaderComponent} from './asset-table-header.component';
23 23 import {AssetRoutingModule} from './asset-routing.module';
24 24 import {HomeComponentsModule} from '@modules/home/components/home-components.module';
  25 +import { AssetTabsComponent } from '@home/pages/asset/asset-tabs.component';
25 26
26 27 @NgModule({
27 28 entryComponents: [
28 29 AssetComponent,
  30 + AssetTabsComponent,
29 31 AssetTableHeaderComponent
30 32 ],
31 33 declarations: [
32 34 AssetComponent,
  35 + AssetTabsComponent,
33 36 AssetTableHeaderComponent
34 37 ],
35 38 imports: [
... ...
... ... @@ -55,6 +55,7 @@ import {AssetService} from '@app/core/http/asset.service';
55 55 import {AssetComponent} from '@modules/home/pages/asset/asset.component';
56 56 import {AssetTableHeaderComponent} from '@modules/home/pages/asset/asset-table-header.component';
57 57 import {AssetId} from '@app/shared/models/id/asset-id';
  58 +import { AssetTabsComponent } from '@home/pages/asset/asset-tabs.component';
58 59
59 60 @Injectable()
60 61 export class AssetsTableConfigResolver implements Resolve<EntityTableConfig<AssetInfo>> {
... ... @@ -75,6 +76,7 @@ export class AssetsTableConfigResolver implements Resolve<EntityTableConfig<Asse
75 76
76 77 this.config.entityType = EntityType.ASSET;
77 78 this.config.entityComponent = AssetComponent;
  79 + this.config.entityTabsComponent = AssetTabsComponent;
78 80 this.config.entityTranslations = entityTypeTranslations.get(EntityType.ASSET);
79 81 this.config.entityResources = entityTypeResources.get(EntityType.ASSET);
80 82
... ...
  1 +///
  2 +/// Copyright © 2016-2019 The Thingsboard Authors
  3 +///
  4 +/// Licensed under the Apache License, Version 2.0 (the "License");
  5 +/// you may not use this file except in compliance with the License.
  6 +/// You may obtain a copy of the License at
  7 +///
  8 +/// http://www.apache.org/licenses/LICENSE-2.0
  9 +///
  10 +/// Unless required by applicable law or agreed to in writing, software
  11 +/// distributed under the License is distributed on an "AS IS" BASIS,
  12 +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +/// See the License for the specific language governing permissions and
  14 +/// limitations under the License.
  15 +///
  16 +
  17 +import { NgModule } from '@angular/core';
  18 +import { RouterModule, Routes } from '@angular/router';
  19 +import { Authority } from '@shared/models/authority.enum';
  20 +import { AuditLogTableComponent } from '@home/components/audit-log/audit-log-table.component';
  21 +
  22 +const routes: Routes = [
  23 + {
  24 + path: 'auditLogs',
  25 + component: AuditLogTableComponent,
  26 + data: {
  27 + auth: [Authority.TENANT_ADMIN],
  28 + title: 'audit-log.audit-logs',
  29 + breadcrumb: {
  30 + label: 'audit-log.audit-logs',
  31 + icon: 'track_changes'
  32 + }
  33 + }
  34 + }
  35 +];
  36 +
  37 +@NgModule({
  38 + imports: [RouterModule.forChild(routes)],
  39 + exports: [RouterModule]
  40 +})
  41 +export class AuditLogRoutingModule { }
... ...
  1 +///
  2 +/// Copyright © 2016-2019 The Thingsboard Authors
  3 +///
  4 +/// Licensed under the Apache License, Version 2.0 (the "License");
  5 +/// you may not use this file except in compliance with the License.
  6 +/// You may obtain a copy of the License at
  7 +///
  8 +/// http://www.apache.org/licenses/LICENSE-2.0
  9 +///
  10 +/// Unless required by applicable law or agreed to in writing, software
  11 +/// distributed under the License is distributed on an "AS IS" BASIS,
  12 +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +/// See the License for the specific language governing permissions and
  14 +/// limitations under the License.
  15 +///
  16 +
  17 +import { NgModule } from '@angular/core';
  18 +import { CommonModule } from '@angular/common';
  19 +import { SharedModule } from '@shared/shared.module';
  20 +import { AuditLogRoutingModule } from '@modules/home/pages/audit-log/audit-log-routing.module';
  21 +
  22 +@NgModule({
  23 + declarations: [
  24 + ],
  25 + imports: [
  26 + CommonModule,
  27 + SharedModule,
  28 + AuditLogRoutingModule
  29 + ]
  30 +})
  31 +export class AuditLogModule { }
... ...
  1 +<!--
  2 +
  3 + Copyright © 2016-2019 The Thingsboard Authors
  4 +
  5 + Licensed under the Apache License, Version 2.0 (the "License");
  6 + you may not use this file except in compliance with the License.
  7 + You may obtain a copy of the License at
  8 +
  9 + http://www.apache.org/licenses/LICENSE-2.0
  10 +
  11 + Unless required by applicable law or agreed to in writing, software
  12 + distributed under the License is distributed on an "AS IS" BASIS,
  13 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14 + See the License for the specific language governing permissions and
  15 + limitations under the License.
  16 +
  17 +-->
  18 +<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
  19 + label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab">
  20 + <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.CUSTOMER" [customerId]="entity.id" detailsMode="true"></tb-audit-log-table>
  21 +</mat-tab>
... ...
  1 +///
  2 +/// Copyright © 2016-2019 The Thingsboard Authors
  3 +///
  4 +/// Licensed under the Apache License, Version 2.0 (the "License");
  5 +/// you may not use this file except in compliance with the License.
  6 +/// You may obtain a copy of the License at
  7 +///
  8 +/// http://www.apache.org/licenses/LICENSE-2.0
  9 +///
  10 +/// Unless required by applicable law or agreed to in writing, software
  11 +/// distributed under the License is distributed on an "AS IS" BASIS,
  12 +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +/// See the License for the specific language governing permissions and
  14 +/// limitations under the License.
  15 +///
  16 +
  17 +import { Component } from '@angular/core';
  18 +import { Store } from '@ngrx/store';
  19 +import { AppState } from '@core/core.state';
  20 +import { EntityTabsComponent } from '../../components/entity/entity-tabs.component';
  21 +import { Customer } from '@shared/models/customer.model';
  22 +
  23 +@Component({
  24 + selector: 'tb-customer-tabs',
  25 + templateUrl: './customer-tabs.component.html',
  26 + styleUrls: []
  27 +})
  28 +export class CustomerTabsComponent extends EntityTabsComponent<Customer> {
  29 +
  30 + constructor(protected store: Store<AppState>) {
  31 + super(store);
  32 + }
  33 +
  34 + ngOnInit() {
  35 + super.ngOnInit();
  36 + }
  37 +
  38 +}
... ...
... ... @@ -20,13 +20,16 @@ import { SharedModule } from '@shared/shared.module';
20 20 import {CustomerComponent} from '@modules/home/pages/customer/customer.component';
21 21 import {CustomerRoutingModule} from './customer-routing.module';
22 22 import {HomeComponentsModule} from '@modules/home/components/home-components.module';
  23 +import { CustomerTabsComponent } from '@home/pages/customer/customer-tabs.component';
23 24
24 25 @NgModule({
25 26 entryComponents: [
26   - CustomerComponent
  27 + CustomerComponent,
  28 + CustomerTabsComponent
27 29 ],
28 30 declarations: [
29   - CustomerComponent
  31 + CustomerComponent,
  32 + CustomerTabsComponent
30 33 ],
31 34 imports: [
32 35 CommonModule,
... ...
... ... @@ -35,6 +35,7 @@ import { EntityAction } from '@home/models/entity/entity-component.models';
35 35 import {Customer} from '@app/shared/models/customer.model';
36 36 import {CustomerService} from '@app/core/http/customer.service';
37 37 import {CustomerComponent} from '@modules/home/pages/customer/customer.component';
  38 +import { CustomerTabsComponent } from '@home/pages/customer/customer-tabs.component';
38 39
39 40 @Injectable()
40 41 export class CustomersTableConfigResolver implements Resolve<EntityTableConfig<Customer>> {
... ... @@ -48,6 +49,7 @@ export class CustomersTableConfigResolver implements Resolve<EntityTableConfig<C
48 49
49 50 this.config.entityType = EntityType.CUSTOMER;
50 51 this.config.entityComponent = CustomerComponent;
  52 + this.config.entityTabsComponent = CustomerTabsComponent;
51 53 this.config.entityTranslations = entityTypeTranslations.get(EntityType.CUSTOMER);
52 54 this.config.entityResources = entityTypeResources.get(EntityType.CUSTOMER);
53 55
... ...
  1 +<!--
  2 +
  3 + Copyright © 2016-2019 The Thingsboard Authors
  4 +
  5 + Licensed under the Apache License, Version 2.0 (the "License");
  6 + you may not use this file except in compliance with the License.
  7 + You may obtain a copy of the License at
  8 +
  9 + http://www.apache.org/licenses/LICENSE-2.0
  10 +
  11 + Unless required by applicable law or agreed to in writing, software
  12 + distributed under the License is distributed on an "AS IS" BASIS,
  13 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14 + See the License for the specific language governing permissions and
  15 + limitations under the License.
  16 +
  17 +-->
  18 +<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
  19 + label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab">
  20 + <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id" detailsMode="true"></tb-audit-log-table>
  21 +</mat-tab>
... ...
  1 +///
  2 +/// Copyright © 2016-2019 The Thingsboard Authors
  3 +///
  4 +/// Licensed under the Apache License, Version 2.0 (the "License");
  5 +/// you may not use this file except in compliance with the License.
  6 +/// You may obtain a copy of the License at
  7 +///
  8 +/// http://www.apache.org/licenses/LICENSE-2.0
  9 +///
  10 +/// Unless required by applicable law or agreed to in writing, software
  11 +/// distributed under the License is distributed on an "AS IS" BASIS,
  12 +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +/// See the License for the specific language governing permissions and
  14 +/// limitations under the License.
  15 +///
  16 +
  17 +import { Component } from '@angular/core';
  18 +import { Store } from '@ngrx/store';
  19 +import { AppState } from '@core/core.state';
  20 +import { EntityTabsComponent } from '../../components/entity/entity-tabs.component';
  21 +import { Dashboard } from '@shared/models/dashboard.models';
  22 +
  23 +@Component({
  24 + selector: 'tb-dashboard-tabs',
  25 + templateUrl: './dashboard-tabs.component.html',
  26 + styleUrls: []
  27 +})
  28 +export class DashboardTabsComponent extends EntityTabsComponent<Dashboard> {
  29 +
  30 + constructor(protected store: Store<AppState>) {
  31 + super(store);
  32 + }
  33 +
  34 + ngOnInit() {
  35 + super.ngOnInit();
  36 + }
  37 +
  38 +}
... ...
... ... @@ -23,15 +23,18 @@ import {ManageDashboardCustomersDialogComponent} from '@modules/home/pages/dashb
23 23 import {DashboardRoutingModule} from './dashboard-routing.module';
24 24 import {MakeDashboardPublicDialogComponent} from '@modules/home/pages/dashboard/make-dashboard-public-dialog.component';
25 25 import {HomeComponentsModule} from '@modules/home/components/home-components.module';
  26 +import { DashboardTabsComponent } from '@home/pages/dashboard/dashboard-tabs.component';
26 27
27 28 @NgModule({
28 29 entryComponents: [
29 30 DashboardFormComponent,
  31 + DashboardTabsComponent,
30 32 ManageDashboardCustomersDialogComponent,
31 33 MakeDashboardPublicDialogComponent
32 34 ],
33 35 declarations: [
34 36 DashboardFormComponent,
  37 + DashboardTabsComponent,
35 38 ManageDashboardCustomersDialogComponent,
36 39 MakeDashboardPublicDialogComponent
37 40 ],
... ...
... ... @@ -62,6 +62,7 @@ import {
62 62 MakeDashboardPublicDialogComponent,
63 63 MakeDashboardPublicDialogData
64 64 } from '@modules/home/pages/dashboard/make-dashboard-public-dialog.component';
  65 +import { DashboardTabsComponent } from '@home/pages/dashboard/dashboard-tabs.component';
65 66
66 67 @Injectable()
67 68 export class DashboardsTableConfigResolver implements Resolve<EntityTableConfig<DashboardInfo | Dashboard>> {
... ... @@ -79,6 +80,7 @@ export class DashboardsTableConfigResolver implements Resolve<EntityTableConfig<
79 80
80 81 this.config.entityType = EntityType.DASHBOARD;
81 82 this.config.entityComponent = DashboardFormComponent;
  83 + this.config.entityTabsComponent = DashboardTabsComponent;
82 84 this.config.entityTranslations = entityTypeTranslations.get(EntityType.DASHBOARD);
83 85 this.config.entityResources = entityTypeResources.get(EntityType.DASHBOARD);
84 86
... ...
... ... @@ -15,15 +15,7 @@
15 15 limitations under the License.
16 16
17 17 -->
18   -<mat-tab label="{{entity?.name}}">
19   - Hobotok<br/>
20   - {{ entity | json }}
21   -</mat-tab>
22   -<mat-tab *ngIf="entity?.additionalInfo?.gateway" label="Gateway">
23   - Hobotok 2<br/>
24   - {{ entity | json }}
25   -</mat-tab>
26   -<mat-tab label="{{ 'extension.extensions' | translate }}">
27   - Hobotok 2<br/>
28   - {{ entity | json }}
  18 +<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
  19 + label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab">
  20 + <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id" detailsMode="true"></tb-audit-log-table>
29 21 </mat-tab>
... ...
... ... @@ -28,8 +28,6 @@ import { EntityTabsComponent } from '../../components/entity/entity-tabs.compone
28 28 })
29 29 export class DeviceTabsComponent extends EntityTabsComponent<DeviceInfo> {
30 30
31   - entityType = EntityType;
32   -
33 31 constructor(protected store: Store<AppState>) {
34 32 super(store);
35 33 }
... ...
  1 +<!--
  2 +
  3 + Copyright © 2016-2019 The Thingsboard Authors
  4 +
  5 + Licensed under the Apache License, Version 2.0 (the "License");
  6 + you may not use this file except in compliance with the License.
  7 + You may obtain a copy of the License at
  8 +
  9 + http://www.apache.org/licenses/LICENSE-2.0
  10 +
  11 + Unless required by applicable law or agreed to in writing, software
  12 + distributed under the License is distributed on an "AS IS" BASIS,
  13 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14 + See the License for the specific language governing permissions and
  15 + limitations under the License.
  16 +
  17 +-->
  18 +<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
  19 + label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab">
  20 + <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id" detailsMode="true"></tb-audit-log-table>
  21 +</mat-tab>
... ...
  1 +///
  2 +/// Copyright © 2016-2019 The Thingsboard Authors
  3 +///
  4 +/// Licensed under the Apache License, Version 2.0 (the "License");
  5 +/// you may not use this file except in compliance with the License.
  6 +/// You may obtain a copy of the License at
  7 +///
  8 +/// http://www.apache.org/licenses/LICENSE-2.0
  9 +///
  10 +/// Unless required by applicable law or agreed to in writing, software
  11 +/// distributed under the License is distributed on an "AS IS" BASIS,
  12 +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +/// See the License for the specific language governing permissions and
  14 +/// limitations under the License.
  15 +///
  16 +
  17 +import { Component } from '@angular/core';
  18 +import { Store } from '@ngrx/store';
  19 +import { AppState } from '@core/core.state';
  20 +import { EntityTabsComponent } from '../../components/entity/entity-tabs.component';
  21 +import { EntityViewInfo } from '@app/shared/models/entity-view.models';
  22 +
  23 +@Component({
  24 + selector: 'tb-entity-view-tabs',
  25 + templateUrl: './entity-view-tabs.component.html',
  26 + styleUrls: []
  27 +})
  28 +export class EntityViewTabsComponent extends EntityTabsComponent<EntityViewInfo> {
  29 +
  30 + constructor(protected store: Store<AppState>) {
  31 + super(store);
  32 + }
  33 +
  34 + ngOnInit() {
  35 + super.ngOnInit();
  36 + }
  37 +
  38 +}
... ...
... ... @@ -22,14 +22,17 @@ import {EntityViewComponent} from '@modules/home/pages/entity-view/entity-view.c
22 22 import {EntityViewTableHeaderComponent} from './entity-view-table-header.component';
23 23 import {EntityViewRoutingModule} from './entity-view-routing.module';
24 24 import {HomeComponentsModule} from '@modules/home/components/home-components.module';
  25 +import { EntityViewTabsComponent } from '@home/pages/entity-view/entity-view-tabs.component';
25 26
26 27 @NgModule({
27 28 entryComponents: [
28 29 EntityViewComponent,
  30 + EntityViewTabsComponent,
29 31 EntityViewTableHeaderComponent
30 32 ],
31 33 declarations: [
32 34 EntityViewComponent,
  35 + EntityViewTabsComponent,
33 36 EntityViewTableHeaderComponent
34 37 ],
35 38 imports: [
... ...
... ... @@ -55,6 +55,7 @@ import {EntityViewService} from '@core/http/entity-view.service';
55 55 import {EntityViewComponent} from '@modules/home/pages/entity-view/entity-view.component';
56 56 import {EntityViewTableHeaderComponent} from '@modules/home/pages/entity-view/entity-view-table-header.component';
57 57 import {EntityViewId} from '@shared/models/id/entity-view-id';
  58 +import { EntityViewTabsComponent } from '@home/pages/entity-view/entity-view-tabs.component';
58 59
59 60 @Injectable()
60 61 export class EntityViewsTableConfigResolver implements Resolve<EntityTableConfig<EntityViewInfo>> {
... ... @@ -75,6 +76,7 @@ export class EntityViewsTableConfigResolver implements Resolve<EntityTableConfig
75 76
76 77 this.config.entityType = EntityType.ENTITY_VIEW;
77 78 this.config.entityComponent = EntityViewComponent;
  79 + this.config.entityTabsComponent = EntityViewTabsComponent;
78 80 this.config.entityTranslations = entityTypeTranslations.get(EntityType.ENTITY_VIEW);
79 81 this.config.entityResources = entityTypeResources.get(EntityType.ENTITY_VIEW);
80 82
... ...
... ... @@ -21,7 +21,7 @@ import { HomeLinksModule } from './home-links/home-links.module';
21 21 import { ProfileModule } from './profile/profile.module';
22 22 import { TenantModule } from '@modules/home/pages/tenant/tenant.module';
23 23 import { CustomerModule } from '@modules/home/pages/customer/customer.module';
24   -// import { AuditLogModule } from '@modules/home/pages/audit-log/audit-log.module';
  24 +import { AuditLogModule } from '@modules/home/pages/audit-log/audit-log.module';
25 25 import { UserModule } from '@modules/home/pages/user/user.module';
26 26 import {DeviceModule} from '@modules/home/pages/device/device.module';
27 27 import {AssetModule} from '@modules/home/pages/asset/asset.module';
... ... @@ -43,7 +43,7 @@ import {DashboardModule} from '@modules/home/pages/dashboard/dashboard.module';
43 43 RuleChainModule,
44 44 WidgetLibraryModule,
45 45 DashboardModule,
46   -// AuditLogModule,
  46 + AuditLogModule,
47 47 UserModule
48 48 ]
49 49 })
... ...
  1 +<!--
  2 +
  3 + Copyright © 2016-2019 The Thingsboard Authors
  4 +
  5 + Licensed under the Apache License, Version 2.0 (the "License");
  6 + you may not use this file except in compliance with the License.
  7 + You may obtain a copy of the License at
  8 +
  9 + http://www.apache.org/licenses/LICENSE-2.0
  10 +
  11 + Unless required by applicable law or agreed to in writing, software
  12 + distributed under the License is distributed on an "AS IS" BASIS,
  13 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14 + See the License for the specific language governing permissions and
  15 + limitations under the License.
  16 +
  17 +-->
  18 +<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
  19 + label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab">
  20 + <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id" detailsMode="true"></tb-audit-log-table>
  21 +</mat-tab>
... ...
  1 +///
  2 +/// Copyright © 2016-2019 The Thingsboard Authors
  3 +///
  4 +/// Licensed under the Apache License, Version 2.0 (the "License");
  5 +/// you may not use this file except in compliance with the License.
  6 +/// You may obtain a copy of the License at
  7 +///
  8 +/// http://www.apache.org/licenses/LICENSE-2.0
  9 +///
  10 +/// Unless required by applicable law or agreed to in writing, software
  11 +/// distributed under the License is distributed on an "AS IS" BASIS,
  12 +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +/// See the License for the specific language governing permissions and
  14 +/// limitations under the License.
  15 +///
  16 +
  17 +import { Component } from '@angular/core';
  18 +import { Store } from '@ngrx/store';
  19 +import { AppState } from '@core/core.state';
  20 +import { EntityTabsComponent } from '../../components/entity/entity-tabs.component';
  21 +import { AssetInfo } from '@app/shared/models/asset.models';
  22 +import { RuleChain } from '@shared/models/rule-chain.models';
  23 +
  24 +@Component({
  25 + selector: 'tb-rulechain-tabs',
  26 + templateUrl: './rulechain-tabs.component.html',
  27 + styleUrls: []
  28 +})
  29 +export class RuleChainTabsComponent extends EntityTabsComponent<RuleChain> {
  30 +
  31 + constructor(protected store: Store<AppState>) {
  32 + super(store);
  33 + }
  34 +
  35 + ngOnInit() {
  36 + super.ngOnInit();
  37 + }
  38 +
  39 +}
... ...
... ... @@ -20,13 +20,16 @@ import {SharedModule} from '@shared/shared.module';
20 20 import {RuleChainComponent} from '@modules/home/pages/rulechain/rulechain.component';
21 21 import {RuleChainRoutingModule} from '@modules/home/pages/rulechain/rulechain-routing.module';
22 22 import {HomeComponentsModule} from '@modules/home/components/home-components.module';
  23 +import { RuleChainTabsComponent } from '@home/pages/rulechain/rulechain-tabs.component';
23 24
24 25 @NgModule({
25 26 entryComponents: [
26   - RuleChainComponent
  27 + RuleChainComponent,
  28 + RuleChainTabsComponent
27 29 ],
28 30 declarations: [
29   - RuleChainComponent
  31 + RuleChainComponent,
  32 + RuleChainTabsComponent
30 33 ],
31 34 imports: [
32 35 CommonModule,
... ...
... ... @@ -31,6 +31,7 @@ import {RuleChain} from '@shared/models/rule-chain.models';
31 31 import {RuleChainService} from '@core/http/rule-chain.service';
32 32 import {RuleChainComponent} from '@modules/home/pages/rulechain/rulechain.component';
33 33 import {DialogService} from '@core/services/dialog.service';
  34 +import { RuleChainTabsComponent } from '@home/pages/rulechain/rulechain-tabs.component';
34 35
35 36 @Injectable()
36 37 export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<RuleChain>> {
... ... @@ -45,6 +46,7 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
45 46
46 47 this.config.entityType = EntityType.RULE_CHAIN;
47 48 this.config.entityComponent = RuleChainComponent;
  49 + this.config.entityTabsComponent = RuleChainTabsComponent;
48 50 this.config.entityTranslations = entityTypeTranslations.get(EntityType.RULE_CHAIN);
49 51 this.config.entityResources = entityTypeResources.get(EntityType.RULE_CHAIN);
50 52
... ...
... ... @@ -105,10 +105,6 @@ export class UserMenuComponent implements OnInit, OnDestroy {
105 105 this.router.navigate(['profile']);
106 106 }
107 107
108   - openCustomerProfile(): void {
109   - this.router.navigate(['customerProfile']);
110   - }
111   -
112 108 logout(): void {
113 109 this.authService.logout();
114 110 }
... ...
  1 +///
  2 +/// Copyright © 2016-2019 The Thingsboard Authors
  3 +///
  4 +/// Licensed under the Apache License, Version 2.0 (the "License");
  5 +/// you may not use this file except in compliance with the License.
  6 +/// You may obtain a copy of the License at
  7 +///
  8 +/// http://www.apache.org/licenses/LICENSE-2.0
  9 +///
  10 +/// Unless required by applicable law or agreed to in writing, software
  11 +/// distributed under the License is distributed on an "AS IS" BASIS,
  12 +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +/// See the License for the specific language governing permissions and
  14 +/// limitations under the License.
  15 +///
  16 +
  17 +import { BaseData } from './base-data';
  18 +import { AuditLogId } from './id/audit-log-id';
  19 +import { CustomerId } from './id/customer-id';
  20 +import { EntityId } from './id/entity-id';
  21 +import { UserId } from './id/user-id';
  22 +import { TenantId } from './id/tenant-id';
  23 +
  24 +export enum AuditLogMode {
  25 + TENANT,
  26 + ENTITY,
  27 + USER,
  28 + CUSTOMER
  29 +}
  30 +
  31 +export enum ActionType {
  32 + ADDED = 'ADDED',
  33 + DELETED = 'DELETED',
  34 + UPDATED = 'UPDATED',
  35 + ATTRIBUTES_UPDATED = 'ATTRIBUTES_UPDATED',
  36 + ATTRIBUTES_DELETED = 'ATTRIBUTES_DELETED',
  37 + RPC_CALL = 'RPC_CALL',
  38 + CREDENTIALS_UPDATED = 'CREDENTIALS_UPDATED',
  39 + ASSIGNED_TO_CUSTOMER = 'ASSIGNED_TO_CUSTOMER',
  40 + UNASSIGNED_FROM_CUSTOMER = 'UNASSIGNED_FROM_CUSTOMER',
  41 + ACTIVATED = 'ACTIVATED',
  42 + SUSPENDED = 'SUSPENDED',
  43 + CREDENTIALS_READ = 'CREDENTIALS_READ',
  44 + ATTRIBUTES_READ = 'ATTRIBUTES_READ',
  45 + RELATION_ADD_OR_UPDATE = 'RELATION_ADD_OR_UPDATE',
  46 + RELATION_DELETED = 'RELATION_DELETED',
  47 + RELATIONS_DELETED = 'RELATIONS_DELETED',
  48 + ALARM_ACK = 'ALARM_ACK',
  49 + ALARM_CLEAR = 'ALARM_CLEAR',
  50 + LOGIN = 'LOGIN',
  51 + LOGOUT = 'LOGOUT'
  52 +}
  53 +
  54 +export enum ActionStatus {
  55 + SUCCESS = 'SUCCESS',
  56 + FAILURE = 'FAILURE'
  57 +}
  58 +
  59 +export const actionTypeTranslations = new Map<ActionType, string>(
  60 + [
  61 + [ActionType.ADDED, 'audit-log.type-added'],
  62 + [ActionType.DELETED, 'audit-log.type-deleted'],
  63 + [ActionType.UPDATED, 'audit-log.type-updated'],
  64 + [ActionType.ATTRIBUTES_UPDATED, 'audit-log.type-attributes-updated'],
  65 + [ActionType.ATTRIBUTES_DELETED, 'audit-log.type-attributes-deleted'],
  66 + [ActionType.RPC_CALL, 'audit-log.type-rpc-call'],
  67 + [ActionType.CREDENTIALS_UPDATED, 'audit-log.type-credentials-updated'],
  68 + [ActionType.ASSIGNED_TO_CUSTOMER, 'audit-log.type-assigned-to-customer'],
  69 + [ActionType.UNASSIGNED_FROM_CUSTOMER, 'audit-log.type-unassigned-from-customer'],
  70 + [ActionType.ACTIVATED, 'audit-log.type-activated'],
  71 + [ActionType.SUSPENDED, 'audit-log.type-suspended'],
  72 + [ActionType.CREDENTIALS_READ, 'audit-log.type-credentials-read'],
  73 + [ActionType.ATTRIBUTES_READ, 'audit-log.type-attributes-read'],
  74 + [ActionType.RELATION_ADD_OR_UPDATE, 'audit-log.type-relation-add-or-update'],
  75 + [ActionType.RELATION_DELETED, 'audit-log.type-relation-delete'],
  76 + [ActionType.RELATIONS_DELETED, 'audit-log.type-relations-delete'],
  77 + [ActionType.ALARM_ACK, 'audit-log.type-alarm-ack'],
  78 + [ActionType.ALARM_CLEAR, 'audit-log.type-alarm-clear'],
  79 + [ActionType.LOGIN, 'audit-log.type-login'],
  80 + [ActionType.LOGOUT, 'audit-log.type-logout']
  81 + ]
  82 +);
  83 +
  84 +export const actionStatusTranslations = new Map<ActionStatus, string>(
  85 + [
  86 + [ActionStatus.SUCCESS, 'audit-log.status-success'],
  87 + [ActionStatus.FAILURE, 'audit-log.status-failure'],
  88 + ]
  89 +);
  90 +
  91 +export interface AuditLog extends BaseData<AuditLogId> {
  92 + tenantId: TenantId;
  93 + customerId: CustomerId;
  94 + entityId: EntityId;
  95 + entityName: string;
  96 + userId: UserId;
  97 + userName: string;
  98 + actionType: ActionType;
  99 + actionData: any;
  100 + actionStatus: ActionStatus;
  101 + actionFailureDetails: string;
  102 +}
... ...
  1 +///
  2 +/// Copyright © 2016-2019 The Thingsboard Authors
  3 +///
  4 +/// Licensed under the Apache License, Version 2.0 (the "License");
  5 +/// you may not use this file except in compliance with the License.
  6 +/// You may obtain a copy of the License at
  7 +///
  8 +/// http://www.apache.org/licenses/LICENSE-2.0
  9 +///
  10 +/// Unless required by applicable law or agreed to in writing, software
  11 +/// distributed under the License is distributed on an "AS IS" BASIS,
  12 +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +/// See the License for the specific language governing permissions and
  14 +/// limitations under the License.
  15 +///
  16 +
  17 +import { HasUUID } from '@shared/models/id/has-uuid';
  18 +
  19 +export class AuditLogId implements HasUUID {
  20 + id: string;
  21 + constructor(id: string) {
  22 + this.id = id;
  23 + }
  24 +}
... ...
... ... @@ -62,8 +62,6 @@ import {TranslateModule} from '@ngx-translate/core';
62 62 import {TbCheckboxComponent} from '@shared/components/tb-checkbox.component';
63 63 import {HelpComponent} from '@shared/components/help.component';
64 64 import {TbAnchorComponent} from '@shared/components/tb-anchor.component';
65   -// import { AuditLogDetailsDialogComponent } from '@shared/components/audit-log/audit-log-details-dialog.component';
66   -// import { AuditLogTableComponent } from '@shared/components/audit-log/audit-log-table.component';
67 65 import {MillisecondsToTimeStringPipe} from '@shared/pipe/milliseconds-to-time-string.pipe';
68 66 import {TimewindowComponent} from '@shared/components/time/timewindow.component';
69 67 import {OverlayModule} from '@angular/cdk/overlay';
... ... @@ -97,7 +95,6 @@ import {SocialSharePanelComponent} from './components/socialshare-panel.componen
97 95 entryComponents: [
98 96 TbSnackBarComponent,
99 97 TbAnchorComponent,
100   -// AuditLogDetailsDialogComponent,
101 98 TimewindowPanelComponent,
102 99 ],
103 100 declarations: [
... ... @@ -111,8 +108,6 @@ import {SocialSharePanelComponent} from './components/socialshare-panel.componen
111 108 TbSnackBarComponent,
112 109 BreadcrumbComponent,
113 110 UserMenuComponent,
114   -// AuditLogTableComponent,
115   -// AuditLogDetailsDialogComponent,
116 111 TimewindowComponent,
117 112 TimewindowPanelComponent,
118 113 TimeintervalComponent,
... ... @@ -184,7 +179,6 @@ import {SocialSharePanelComponent} from './components/socialshare-panel.componen
184 179 TbCheckboxComponent,
185 180 BreadcrumbComponent,
186 181 UserMenuComponent,
187   -// AuditLogTableComponent,
188 182 TimewindowComponent,
189 183 TimewindowPanelComponent,
190 184 TimeintervalComponent,
... ...