Commit 016bbefaba26b71e8d75a5c8e3dea19efa7c8d08

Authored by Igor Kulikov
2 parents 3b5a4941 1d117297

Merge with master

Showing 100 changed files with 940 additions and 152 deletions

Too many changes to show.

To preserve performance only 100 of 1613 files are displayed.

1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
@@ -13,7 +13,6 @@ @@ -13,7 +13,6 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -  
17 import org.apache.tools.ant.filters.ReplaceTokens 16 import org.apache.tools.ant.filters.ReplaceTokens
18 17
19 buildscript { 18 buildscript {
1 <!-- 1 <!--
2 2
3 - Copyright © 2016-2017 The Thingsboard Authors 3 + Copyright © 2016-2018 The Thingsboard Authors
4 4
5 Licensed under the Apache License, Version 2.0 (the "License"); 5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License. 6 you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
23 - <version>1.4.0-SNAPSHOT</version> 23 + <version>1.4.1-SNAPSHOT</version>
24 <artifactId>thingsboard</artifactId> 24 <artifactId>thingsboard</artifactId>
25 </parent> 25 </parent>
26 <groupId>org.thingsboard</groupId> 26 <groupId>org.thingsboard</groupId>
1 <!-- 1 <!--
2 2
3 - Copyright © 2016-2017 The Thingsboard Authors 3 + Copyright © 2016-2018 The Thingsboard Authors
4 4
5 Licensed under the Apache License, Version 2.0 (the "License"); 5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License. 6 you may not use this file except in compliance with the License.
1 <?xml version="1.0" encoding="UTF-8" ?> 1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!-- 2 <!--
3 3
4 - Copyright © 2016-2017 The Thingsboard Authors 4 + Copyright © 2016-2018 The Thingsboard Authors
5 5
6 Licensed under the Apache License, Version 2.0 (the "License"); 6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License. 7 you may not use this file except in compliance with the License.
1 # 1 #
2 -# Copyright © 2016-2017 The Thingsboard Authors 2 +# Copyright © 2016-2018 The Thingsboard Authors
3 # 3 #
4 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License. 5 # you may not use this file except in compliance with the License.
@@ -66,7 +66,7 @@ @@ -66,7 +66,7 @@
66 "controllerScript": "self.onInit = function() {\n self.ctx.varsRegex = /\\$\\{([^\\}]*)\\}/g;\n self.ctx.htmlSet = false;\n \n var cssParser = new cssjs();\n cssParser.testMode = false;\n var namespace = 'html-value-card-' + hashCode(self.ctx.settings.cardCss);\n cssParser.cssPreviewNamespace = namespace;\n cssParser.createStyleElement(namespace, self.ctx.settings.cardCss);\n self.ctx.$container.addClass(namespace);\n self.ctx.html = self.ctx.settings.cardHtml;\n self.ctx.replaceInfo = processHtmlPattern(self.ctx.html, self.ctx.data);\n \n updateHtml();\n \n function hashCode(str) {\n var hash = 0;\n var i, char;\n if (str.length === 0) return hash;\n for (i = 0; i < str.length; i++) {\n char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash;\n }\n return hash;\n }\n \n function processHtmlPattern(pattern, data) {\n var match = self.ctx.varsRegex.exec(pattern);\n var replaceInfo = {};\n replaceInfo.variables = [];\n while (match !== null) {\n var variableInfo = {};\n variableInfo.dataKeyIndex = -1;\n var variable = match[0];\n var label = match[1];\n var valDec = 2;\n var splitVals = label.split(':');\n if (splitVals.length > 1) {\n label = splitVals[0];\n valDec = parseFloat(splitVals[1]);\n }\n variableInfo.variable = variable;\n variableInfo.valDec = valDec;\n if (label == 'entityName') {\n variableInfo.isEntityName = true;\n } else if (label.startsWith('#')) {\n var keyIndexStr = label.substring(1);\n var n = Math.floor(Number(keyIndexStr));\n if (String(n) === keyIndexStr && n >= 0) {\n variableInfo.dataKeyIndex = n;\n }\n }\n if (!variableInfo.isEntityName && variableInfo.dataKeyIndex === -1) {\n for (var i = 0; i < data.length; i++) {\n var datasourceData = data[i];\n var dataKey = datasourceData.dataKey;\n if (dataKey.label === label) {\n variableInfo.dataKeyIndex = i;\n break;\n }\n }\n }\n replaceInfo.variables.push(variableInfo);\n match = self.ctx.varsRegex.exec(pattern);\n }\n return replaceInfo;\n } \n}\n\nself.onDataUpdated = function() {\n updateHtml();\n}\n\nself.onDestroy = function() {\n}\n\nfunction isNumber(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n}\n\nfunction padValue(val, dec, int) {\n var i = 0;\n var s, strVal, n;\n\n val = parseFloat(val);\n n = (val < 0);\n val = Math.abs(val);\n\n if (dec > 0) {\n strVal = val.toFixed(dec).toString().split('.');\n s = int - strVal[0].length;\n\n for (; i < s; ++i) {\n strVal[0] = '0' + strVal[0];\n }\n\n strVal = (n ? '-' : '') + strVal[0] + '.' + strVal[1];\n }\n\n else {\n strVal = Math.round(val).toString();\n s = int - strVal.length;\n\n for (; i < s; ++i) {\n strVal = '0' + strVal;\n }\n\n strVal = (n ? '-' : '') + strVal;\n }\n\n return strVal;\n}\n\nfunction updateHtml() {\n var text = self.ctx.html;\n var updated = false;\n for (var v in self.ctx.replaceInfo.variables) {\n var variableInfo = self.ctx.replaceInfo.variables[v];\n var txtVal = '';\n if (variableInfo.dataKeyIndex > -1) {\n var varData = self.ctx.data[variableInfo.dataKeyIndex].data;\n if (varData.length > 0) {\n var val = varData[varData.length-1][1];\n if (isNumber(val)) {\n txtVal = padValue(val, variableInfo.valDec, 0);\n } else {\n txtVal = val;\n }\n }\n } else if (variableInfo.isEntityName) {\n if (self.ctx.defaultSubscription.datasources.length) {\n txtVal = self.ctx.defaultSubscription.datasources[0].entityName;\n } else {\n txtVal = 'Unknown';\n }\n }\n if (typeof variableInfo.lastVal === undefined ||\n variableInfo.lastVal !== txtVal) {\n updated = true;\n variableInfo.lastVal = txtVal;\n }\n text = text.split(variableInfo.variable).join(txtVal);\n }\n if (updated || !self.ctx.htmlSet) {\n self.ctx.$container.html(text);\n if (!self.ctx.htmlSet) {\n self.ctx.htmlSet = true;\n }\n }\n}\n\n", 66 "controllerScript": "self.onInit = function() {\n self.ctx.varsRegex = /\\$\\{([^\\}]*)\\}/g;\n self.ctx.htmlSet = false;\n \n var cssParser = new cssjs();\n cssParser.testMode = false;\n var namespace = 'html-value-card-' + hashCode(self.ctx.settings.cardCss);\n cssParser.cssPreviewNamespace = namespace;\n cssParser.createStyleElement(namespace, self.ctx.settings.cardCss);\n self.ctx.$container.addClass(namespace);\n self.ctx.html = self.ctx.settings.cardHtml;\n self.ctx.replaceInfo = processHtmlPattern(self.ctx.html, self.ctx.data);\n \n updateHtml();\n \n function hashCode(str) {\n var hash = 0;\n var i, char;\n if (str.length === 0) return hash;\n for (i = 0; i < str.length; i++) {\n char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash;\n }\n return hash;\n }\n \n function processHtmlPattern(pattern, data) {\n var match = self.ctx.varsRegex.exec(pattern);\n var replaceInfo = {};\n replaceInfo.variables = [];\n while (match !== null) {\n var variableInfo = {};\n variableInfo.dataKeyIndex = -1;\n var variable = match[0];\n var label = match[1];\n var valDec = 2;\n var splitVals = label.split(':');\n if (splitVals.length > 1) {\n label = splitVals[0];\n valDec = parseFloat(splitVals[1]);\n }\n variableInfo.variable = variable;\n variableInfo.valDec = valDec;\n if (label == 'entityName') {\n variableInfo.isEntityName = true;\n } else if (label.startsWith('#')) {\n var keyIndexStr = label.substring(1);\n var n = Math.floor(Number(keyIndexStr));\n if (String(n) === keyIndexStr && n >= 0) {\n variableInfo.dataKeyIndex = n;\n }\n }\n if (!variableInfo.isEntityName && variableInfo.dataKeyIndex === -1) {\n for (var i = 0; i < data.length; i++) {\n var datasourceData = data[i];\n var dataKey = datasourceData.dataKey;\n if (dataKey.label === label) {\n variableInfo.dataKeyIndex = i;\n break;\n }\n }\n }\n replaceInfo.variables.push(variableInfo);\n match = self.ctx.varsRegex.exec(pattern);\n }\n return replaceInfo;\n } \n}\n\nself.onDataUpdated = function() {\n updateHtml();\n}\n\nself.onDestroy = function() {\n}\n\nfunction isNumber(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n}\n\nfunction padValue(val, dec, int) {\n var i = 0;\n var s, strVal, n;\n\n val = parseFloat(val);\n n = (val < 0);\n val = Math.abs(val);\n\n if (dec > 0) {\n strVal = val.toFixed(dec).toString().split('.');\n s = int - strVal[0].length;\n\n for (; i < s; ++i) {\n strVal[0] = '0' + strVal[0];\n }\n\n strVal = (n ? '-' : '') + strVal[0] + '.' + strVal[1];\n }\n\n else {\n strVal = Math.round(val).toString();\n s = int - strVal.length;\n\n for (; i < s; ++i) {\n strVal = '0' + strVal;\n }\n\n strVal = (n ? '-' : '') + strVal;\n }\n\n return strVal;\n}\n\nfunction updateHtml() {\n var text = self.ctx.html;\n var updated = false;\n for (var v in self.ctx.replaceInfo.variables) {\n var variableInfo = self.ctx.replaceInfo.variables[v];\n var txtVal = '';\n if (variableInfo.dataKeyIndex > -1) {\n var varData = self.ctx.data[variableInfo.dataKeyIndex].data;\n if (varData.length > 0) {\n var val = varData[varData.length-1][1];\n if (isNumber(val)) {\n txtVal = padValue(val, variableInfo.valDec, 0);\n } else {\n txtVal = val;\n }\n }\n } else if (variableInfo.isEntityName) {\n if (self.ctx.defaultSubscription.datasources.length) {\n txtVal = self.ctx.defaultSubscription.datasources[0].entityName;\n } else {\n txtVal = 'Unknown';\n }\n }\n if (typeof variableInfo.lastVal === undefined ||\n variableInfo.lastVal !== txtVal) {\n updated = true;\n variableInfo.lastVal = txtVal;\n }\n text = text.split(variableInfo.variable).join(txtVal);\n }\n if (updated || !self.ctx.htmlSet) {\n self.ctx.$container.html(text);\n if (!self.ctx.htmlSet) {\n self.ctx.htmlSet = true;\n }\n }\n}\n\n",
67 "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"required\": [\"cardHtml\"],\n \"properties\": {\n \"cardCss\": {\n \"title\": \"CSS\",\n \"type\": \"string\",\n \"default\": \".card {\\n font-weight: bold; \\n}\"\n },\n \"cardHtml\": {\n \"title\": \"HTML\",\n \"type\": \"string\",\n \"default\": \"<div class='card'>HTML code here</div>\"\n }\n }\n },\n \"form\": [\n {\n \"key\": \"cardCss\",\n \"type\": \"css\"\n }, \n {\n \"key\": \"cardHtml\",\n \"type\": \"html\"\n } \n ]\n}", 67 "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"required\": [\"cardHtml\"],\n \"properties\": {\n \"cardCss\": {\n \"title\": \"CSS\",\n \"type\": \"string\",\n \"default\": \".card {\\n font-weight: bold; \\n}\"\n },\n \"cardHtml\": {\n \"title\": \"HTML\",\n \"type\": \"string\",\n \"default\": \"<div class='card'>HTML code here</div>\"\n }\n }\n },\n \"form\": [\n {\n \"key\": \"cardCss\",\n \"type\": \"css\"\n }, \n {\n \"key\": \"cardHtml\",\n \"type\": \"html\"\n } \n ]\n}",
68 "dataKeySettingsSchema": "{}\n", 68 "dataKeySettingsSchema": "{}\n",
69 - "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"My value\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"return Math.random() * 5.45;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"cardCss\":\".card {\\n width: 100%;\\n height: 100%;\\n border: 2px solid #ccc;\\n box-sizing: border-box;\\n}\\n\\n.card .content {\\n padding: 20px;\\n display: flex;\\n flex-direction: row;\\n align-items: center;\\n justify-content: space-around;\\n height: 100%;\\n box-sizing: border-box;\\n}\\n\\n.card .content .column {\\n display: flex;\\n flex-direction: column; \\n justify-content: space-around;\\n height: 100%;\\n}\\n\\n.card h1 {\\n text-transform: uppercase;\\n color: #999;\\n font-size: 20px;\\n font-weight: bold;\\n margin: 0;\\n padding-bottom: 10px;\\n line-height: 32px;\\n}\\n\\n.card .value {\\n font-size: 38px;\\n font-weight: 200;\\n}\\n\\n.card .description {\\n font-size: 20px;\\n color: #999;\\n}\\n\",\"cardHtml\":\"<div class='card'>\\n <div class='content'>\\n <div class='column'>\\n <h1>Value title</h1>\\n <div class='value'>\\n ${My value:2} units.\\n </div> \\n <div class='description'>\\n Value description text\\n </div>\\n </div>\\n <img height=\\\"80px\\\" src=\\\"https://thingsboard.io/images/logo_small.png\\\" />\\n </div>\\n</div>\"},\"title\":\"HTML Value Card\",\"dropShadow\":false,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" 69 + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"My value\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"return Math.random() * 5.45;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"cardCss\":\".card {\\n width: 100%;\\n height: 100%;\\n border: 2px solid #ccc;\\n box-sizing: border-box;\\n}\\n\\n.card .content {\\n padding: 20px;\\n display: flex;\\n flex-direction: row;\\n align-items: center;\\n justify-content: space-around;\\n height: 100%;\\n box-sizing: border-box;\\n}\\n\\n.card .content .column {\\n display: flex;\\n flex-direction: column; \\n justify-content: space-around;\\n height: 100%;\\n}\\n\\n.card h1 {\\n text-transform: uppercase;\\n color: #999;\\n font-size: 20px;\\n font-weight: bold;\\n margin: 0;\\n padding-bottom: 10px;\\n line-height: 32px;\\n}\\n\\n.card .value {\\n font-size: 38px;\\n font-weight: 200;\\n}\\n\\n.card .description {\\n font-size: 20px;\\n color: #999;\\n}\\n\",\"cardHtml\":\"<div class='card'>\\n <div class='content'>\\n <div class='column'>\\n <h1>Value title</h1>\\n <div class='value'>\\n ${My value:2} units.\\n </div> \\n <div class='description'>\\n Value description text\\n </div>\\n </div>\\n <img height=\\\"80px\\\" src=\\\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMzIwIiB3aWR0aD0iMzIwIj48ZyBzdHJva2Utd2lkdGg9IjI4Ij48ZyBmaWxsPSIjMzA1NjgwIiBjb2xvcj0iIzAwMCIgd2hpdGUtc3BhY2U9Im5vcm1hbCI+PHBhdGggc3R5bGU9InRleHQtZGVjb3JhdGlvbi1jb2xvcjojMDAwO2lzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbDtibG9jay1wcm9ncmVzc2lvbjp0Yjt0ZXh0LWRlY29yYXRpb24tbGluZTpub25lO3RleHQtZGVjb3JhdGlvbi1zdHlsZTpzb2xpZDt0ZXh0LWluZGVudDowO3RleHQtdHJhbnNmb3JtOm5vbmUiIGQ9Ik0xNTEuMTMgMGMtMjguMzYzIDAtNTQuOTE1IDcuOTE1LTc3LjYxMyAyMS41MzdhMzYuNTc4IDM2LjU3OCAwIDAgMC0yMy4wNjctOC4xOTQgOC43NjYgOC43NjYgMCAwIDAtLjAwNCAwYy0yMC4xNTQuMDAxLTM2LjY3OSAxNi41MjgtMzYuNjc4IDM2LjY4MmE4Ljc2NiA4Ljc2NiAwIDAgMCAwIC4wMSAzNi42OSAzNi42OSAwIDAgMCA4LjEwNCAyMi45MjhjLTEzLjgzIDIyLjgzLTIxLjg3IDQ5LjU4LTIxLjg3IDc4LjE3YTguNzY2IDguNzY2IDAgMSAwIDE3LjUzIDBjMC0yNC43MDIgNi43Mi00Ny43NDggMTguMzc5LTY3LjU3NCA0LjU2NiAxLjk4NSA5LjQ3MiAzLjE1IDE0LjUxOSAzLjE1N2E4Ljc2NiA4Ljc2NiAwIDAgMCAuMDEyIDBjMjAuMTU1IDAgMzYuNjgzLTE2LjUyNyAzNi42ODItMzYuNjgyYTguNzY2IDguNzY2IDAgMCAwIDAtLjAwNGMtLjAwMS01LTEuMTM4LTkuODYzLTMuMDgzLTE0LjM5NyAxOS43MTctMTEuNDg0IDQyLjU4NS0xOC4wOTUgNjcuMDg1LTE4LjA5NWE4Ljc2NiA4Ljc2NiAwIDEgMCAwLTE3LjUzek01MC40NCAzMC44OGM1LjkxMy4wMDIgMTEuMTkxIDIuNTEyIDE0LjgzNiA3LjA3N2E4Ljc2NiA4Ljc2NiAwIDAgMCAuMTgzLjIxNCAxOS4xMzcgMTkuMTM3IDAgMCAxIDQuMTM0IDExLjg2M2MtLjAwMiAxMC42NzctOC40NjggMTkuMTQ0LTE5LjE0NCAxOS4xNDhhMTkuMTQ1IDE5LjE0NSAwIDAgMS0xMi00LjI1NCA4Ljc2NiA4Ljc2NiAwIDAgMC0uMDEzLS4wMSAxOS4xMzYgMTkuMTM2IDAgMCAxLTcuMTQ0LTE0Ljg5MmMuMDAzLTEwLjY3NyA4LjQ3LTE5LjE0NCAxOS4xNDgtMTkuMTQ2eiIvPjxwYXRoIHN0eWxlPSJ0ZXh0LWRlY29yYXRpb24tY29sb3I6IzAwMDtpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWw7YmxvY2stcHJvZ3Jlc3Npb246dGI7dGV4dC1kZWNvcmF0aW9uLWxpbmU6bm9uZTt0ZXh0LWRlY29yYXRpb24tc3R5bGU6c29saWQ7dGV4dC1pbmRlbnQ6MDt0ZXh0LXRyYW5zZm9ybTpub25lIiBkPSJNNjYuOTkyIDEwMi44M2E4LjE4NyA4LjE4NyAwIDAgMC0yLjI1OCA2LjA3MSA4LjYwNCA4LjYwNCAwIDAgMCAyLjMzOCA1LjUxOGM2LjgwNSA2Ljg1NiAyMC4yMjMgMjAuMjIzIDIwLjIyMyAyMC4yMjNsMTEuODQ0LTExLjgzcy0xMi45NzMtMTIuOTYxLTIwLjE3Ni0yMC4xNzFjLTEuNjA0LTEuNjMyLTMuNzUtMi4zMTQtNi4wMTItMi4zMjRhOC4xNSA4LjE1IDAgMCAwLTUuOTYgMi41MTJ6bTMyLjE0NyAxOS45ODNMNjIuNSAxNTkuNDUyYy0zLjk3NSAzLjk3Ni0zLjk3NSAxMC40MjEgMCAxNC4zOTdsMTguMTU2IDE4LjE1NiAzMS43NTMgMzEuNzUzIDMwLjQ3OCAzMC40NzhjMy45NzYgMy45NzYgMTAuNDIyIDMuOTc2IDE0LjM5OCAwbDI0Ljc5MS0yNC43OTEgMzcuOTE0LTM3LjkxNCAzNi42MzktMzYuNjM5YzMuOTc1LTMuOTc2IDMuOTc1LTEwLjQyMiAwLTE0LjM5OGwtMTguNjMtMTguNjMtMzEuNzUtMzEuNzYtMzAuMDEtMzBjLTMuOTc3LTMuOTc1LTEwLjQyMi0zLjk3NS0xNC4zOTggMGwtMjQuNzkgMjQuNzktMzcuOTEgMzcuOTF6bTM3LjkxMS0zNy45MXMtMTIuOTczLTEyLjk2MS0yMC4xNzYtMjAuMTcxYy0xLjYwNC0xLjYzMi0zLjc1LTIuMzE0LTYuMDEyLTIuMzI0LTQuNzE3LS4wMjMtOC40MzQgMy44NjEtOC4yMTcgOC41ODNhOC42MDQgOC42MDQgMCAwIDAgMi4zMzcgNS41MThjNi44MDUgNi44NTYgMjAuMjIzIDIwLjIyMyAyMC4yMjMgMjAuMjIzbDExLjg0NC0xMS44M3ptNjkuMTkzIDUuMjEzczEyLjk2MS0xMi45NzMgMjAuMTcxLTIwLjE3NmMxLjYzMy0xLjYwNCAyLjMxNC0zLjc1IDIuMzI0LTYuMDEyLjAyMy00LjcxNi0zLjg2MS04LjQzNC04LjU4My04LjIxN2E4LjYwNCA4LjYwNCAwIDAgMC01LjUxOCAyLjMzOGMtNi44NTYgNi44MDUtMjAuMjIzIDIwLjIyMy0yMC4yMjMgMjAuMjIzbDExLjgzIDExLjg0NHptMzEuNzUzIDMxLjc1M3MxMi45NjEtMTIuOTczIDIwLjE3MS0yMC4xNzZjMS42MzMtMS42MDQgMi4zMTQtMy43NSAyLjMyNC02LjAxMi4wMjMtNC43MTYtMy44NjEtOC40MzQtOC41ODMtOC4yMTdhOC42MDQgOC42MDQgMCAwIDAtNS41MTggMi4zMzhjLTYuODU2IDYuODA1LTIwLjIyMyAyMC4yMjMtMjAuMjIzIDIwLjIyM2wxMS44MyAxMS44NDR6bS0xOC4wMDkgNjkuNjY3czEyLjk3MyAxMi45NjEgMjAuMTc4IDIwLjE3YzEuNjA0IDEuNjMyIDMuNzUgMi4zMTMgNi4wMTIgMi4zMjQgNC43MTcuMDIyIDguNDM0LTMuODYyIDguMjE3LTguNTg0bC0uMDAyLjAwMmE4LjYwNiA4LjYwNiAwIDAgMC0yLjMzOC01LjUxOGMtNi44MDUtNi44NTYtMjAuMjIyLTIwLjIyMi0yMC4yMjItMjAuMjIybC0xMS44NDQgMTEuODN6bS0zNy45MTQgMzcuOTE0czEyLjk3MyAxMi45NjEgMjAuMTc4IDIwLjE3YzEuNjA0IDEuNjMyIDMuNzUgMi4zMTMgNi4wMTIgMi4zMjMgNC43MTcuMDIzIDguNDM0LTMuODYxIDguMjE3LTguNTgzaC0uMDAyYTguNjAzIDguNjAzIDAgMCAwLTIuMzM3LTUuNTE4Yy02LjgwNS02Ljg1Ni0yMC4yMjMtMjAuMjIzLTIwLjIyMy0yMC4yMjNsLTExLjg0NCAxMS44M3ptLTY5LjY2Ny01LjY4N3MtMTIuOTYxIDEyLjk3My0yMC4xNjkgMjAuMTc4Yy0xLjYzMiAxLjYwNC0yLjMxNCAzLjc1LTIuMzI0IDYuMDEyLS4wMjMgNC43MTcgMy44NjEgOC40MzQgOC41ODMgOC4yMTdoLS4wMDJhOC42MDIgOC42MDIgMCAwIDAgNS41MTgtMi4zMzdjNi44NTYtNi44MDUgMjAuMjIzLTIwLjIyMyAyMC4yMjMtMjAuMjIzbC0xMS44Mi0xMS44NHptLTMxLjc0My0zMS43NHMtMTIuOTYxIDEyLjk3My0yMC4xNjkgMjAuMTc4Yy0xLjYzMiAxLjYwNC0yLjMxNCAzLjc1LTIuMzI0IDYuMDEyLS4wMjMgNC43MTcgMy44NjEgOC40MzQgOC41ODMgOC4yMTdoLS4wMDJhOC42MDQgOC42MDQgMCAwIDAgNS41MTgtMi4zMzdjNi44NTYtNi44MDUgMjAuMjIzLTIwLjIyMyAyMC4yMjMtMjAuMjIzbC0xMS44My0xMS44NXpNMTY3LjkgMTAxLjQ3YzEuNjgtMS43MDYgMy45NjctMi42NiA2LjI5Ny0yLjYyNmE3Ljg5IDcuODkgMCAwIDEgNC41NjMgMS41MWwxNi40OTkgMTIuMWMzLjIgMi4yOTcgNC4xNDQgNi42NTkgMi4yMyAxMC4zMTItMS45MTMgMy42NTMtNi4xMjMgNS41MjQtOS45NSA0LjQyM2w2LjEyNCAyMy45NDhjMS4xMTMgNC4zNTEtMS41NjQgOC45NjctNS45ODQgMTAuMzE3bC00NC42NDIgMTMuNjMgOC4yNDYgMzEuODg0YzEuMTczIDQuMzctMS41MDIgOS4wNDQtNS45NTUgMTAuNDA3cy04Ljk3NS0xLjExMS0xMC4wNjgtNS41MDVsLTEwLjI4Mi0zOS43N2MtMS4xMjYtNC4zNTUgMS41NS04Ljk4NCA1Ljk3Ni0xMC4zMzdsNDQuNjYxLTEzLjYzNy00LjEyMi0xNi4xMThjLTIuNzYzIDMuMDY0LTcuMjMzIDMuODA4LTEwLjU4NiAxLjc2MS0zLjM1My0yLjA0Ny00LjYxNC02LjI5LTIuOTg2LTEwLjA0N2w4LjExNy0xOS40NTRhOC44NzIgOC44NzIgMCAwIDEgMS44NjMtMi43OTd6IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiLz48cGF0aCBzdHlsZT0idGV4dC1kZWNvcmF0aW9uLWNvbG9yOiMwMDA7aXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsO2Jsb2NrLXByb2dyZXNzaW9uOnRiO3RleHQtZGVjb3JhdGlvbi1saW5lOm5vbmU7dGV4dC1kZWNvcmF0aW9uLXN0eWxlOnNvbGlkO3RleHQtaW5kZW50OjA7dGV4dC10cmFuc2Zvcm06bm9uZSIgZD0iTTE2OC44NyAzMjAuMDRjMjguMzYzIDAgNTQuOTE1LTcuOTE1IDc3LjYxNC0yMS41MzhhMzYuNTc4IDM2LjU3OCAwIDAgMCAyMy4wNjcgOC4xOTQgOC43NjYgOC43NjYgMCAwIDAgLjAwNCAwYzIwLjE1NSAwIDM2LjY4LTE2LjUyOCAzNi42NzktMzYuNjgyYTguNzY2IDguNzY2IDAgMCAwIDAtLjAxMSAzNi42ODggMzYuNjg4IDAgMCAwLTguMTAzLTIyLjkyN2MxMy44MjUtMjIuODIgMjEuODY2LTQ5LjU3MiAyMS44NjYtNzguMTYyYTguNzY2IDguNzY2IDAgMSAwLTE3LjUzMSAwYzAgMjQuNzAzLTYuNzIgNDcuNzQ5LTE4LjM3OCA2Ny41NzUtNC41NjctMS45ODUtOS40NzMtMy4xNS0xNC41Mi0zLjE1N2E4Ljc2NiA4Ljc2NiAwIDAgMC0uMDEyIDBjLTIwLjE1NS0uMDAxLTM2LjY4MyAxNi41MjctMzYuNjgyIDM2LjY4Mi4wMDIgNC45OTkgMS4xMzkgOS44NjIgMy4wODMgMTQuMzk3LTE5LjcxNyAxMS40ODQtNDIuNTg2IDE4LjA5NS02Ny4wODYgMTguMDk1YTguNzY2IDguNzY2IDAgMSAwIDAgMTcuNTN6bTEwMC42OS0zMC44NzVjLTUuOTEzIDAtMTEuMTkxLTIuNTEyLTE0LjgzNi03LjA3N2E4Ljc2NiA4Ljc2NiAwIDAgMC0uMTgzLS4yMTQgMTkuMTM2IDE5LjEzNiAwIDAgMS00LjEzNC0xMS44NjNjLjAwMi0xMC42NzcgOC40NjgtMTkuMTQ0IDE5LjE0NC0xOS4xNDhhMTkuMTQ1IDE5LjE0NSAwIDAgMSAxMiA0LjI1NCA4Ljc2NiA4Ljc2NiAwIDAgMCAuMDEzLjAxIDE5LjEzNiAxOS4xMzYgMCAwIDEgNy4xNDQgMTQuODkyYy0uMDAzIDEwLjY3Ny04LjQ3IDE5LjE0NS0xOS4xNDggMTkuMTQ2eiIvPjwvZz48L2c+PC9zdmc+\\\" />\\n </div>\\n</div>\"},\"title\":\"HTML Value Card\",\"dropShadow\":false,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
70 } 70 }
71 }, 71 },
72 { 72 {
1 -- 1 --
2 --- Copyright © 2016-2017 The Thingsboard Authors 2 +-- Copyright © 2016-2018 The Thingsboard Authors
3 -- 3 --
4 -- Licensed under the Apache License, Version 2.0 (the "License"); 4 -- Licensed under the Apache License, Version 2.0 (the "License");
5 -- you may not use this file except in compliance with the License. 5 -- you may not use this file except in compliance with the License.
1 -- 1 --
2 --- Copyright © 2016-2017 The Thingsboard Authors 2 +-- Copyright © 2016-2018 The Thingsboard Authors
3 -- 3 --
4 -- Licensed under the Apache License, Version 2.0 (the "License"); 4 -- Licensed under the Apache License, Version 2.0 (the "License");
5 -- you may not use this file except in compliance with the License. 5 -- you may not use this file except in compliance with the License.
  1 +--
  2 +-- Copyright © 2016-2018 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 +CREATE TABLE IF NOT EXISTS thingsboard.audit_log_by_entity_id (
  18 + tenant_id timeuuid,
  19 + id timeuuid,
  20 + customer_id timeuuid,
  21 + entity_id timeuuid,
  22 + entity_type text,
  23 + entity_name text,
  24 + user_id timeuuid,
  25 + user_name text,
  26 + action_type text,
  27 + action_data text,
  28 + action_status text,
  29 + action_failure_details text,
  30 + PRIMARY KEY ((tenant_id, entity_id, entity_type), id)
  31 +);
  32 +
  33 +CREATE TABLE IF NOT EXISTS thingsboard.audit_log_by_customer_id (
  34 + tenant_id timeuuid,
  35 + id timeuuid,
  36 + customer_id timeuuid,
  37 + entity_id timeuuid,
  38 + entity_type text,
  39 + entity_name text,
  40 + user_id timeuuid,
  41 + user_name text,
  42 + action_type text,
  43 + action_data text,
  44 + action_status text,
  45 + action_failure_details text,
  46 + PRIMARY KEY ((tenant_id, customer_id), id)
  47 +);
  48 +
  49 +CREATE TABLE IF NOT EXISTS thingsboard.audit_log_by_user_id (
  50 + tenant_id timeuuid,
  51 + id timeuuid,
  52 + customer_id timeuuid,
  53 + entity_id timeuuid,
  54 + entity_type text,
  55 + entity_name text,
  56 + user_id timeuuid,
  57 + user_name text,
  58 + action_type text,
  59 + action_data text,
  60 + action_status text,
  61 + action_failure_details text,
  62 + PRIMARY KEY ((tenant_id, user_id), id)
  63 +);
  64 +
  65 +
  66 +
  67 +CREATE TABLE IF NOT EXISTS thingsboard.audit_log_by_tenant_id (
  68 + tenant_id timeuuid,
  69 + id timeuuid,
  70 + partition bigint,
  71 + customer_id timeuuid,
  72 + entity_id timeuuid,
  73 + entity_type text,
  74 + entity_name text,
  75 + user_id timeuuid,
  76 + user_name text,
  77 + action_type text,
  78 + action_data text,
  79 + action_status text,
  80 + action_failure_details text,
  81 + PRIMARY KEY ((tenant_id, partition), id)
  82 +);
  83 +
  84 +CREATE TABLE IF NOT EXISTS thingsboard.audit_log_by_tenant_id_partitions (
  85 + tenant_id timeuuid,
  86 + partition bigint,
  87 + PRIMARY KEY (( tenant_id ), partition)
  88 +) WITH CLUSTERING ORDER BY ( partition ASC )
  89 +AND compaction = { 'class' : 'LeveledCompactionStrategy' };
  90 +
  91 +DROP MATERIALIZED VIEW IF EXISTS thingsboard.dashboard_by_tenant_and_search_text;
  92 +DROP MATERIALIZED VIEW IF EXISTS thingsboard.dashboard_by_customer_and_search_text;
  93 +
  94 +DROP TABLE IF EXISTS thingsboard.dashboard;
  95 +
  96 +CREATE TABLE IF NOT EXISTS thingsboard.dashboard (
  97 + id timeuuid,
  98 + tenant_id timeuuid,
  99 + title text,
  100 + search_text text,
  101 + assigned_customers text,
  102 + configuration text,
  103 + PRIMARY KEY (id, tenant_id)
  104 +);
  105 +
  106 +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.dashboard_by_tenant_and_search_text AS
  107 + SELECT *
  108 + from thingsboard.dashboard
  109 + WHERE tenant_id IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL
  110 + PRIMARY KEY ( tenant_id, search_text, id )
  111 + WITH CLUSTERING ORDER BY ( search_text ASC, id DESC );
  112 +
  1 +--
  2 +-- Copyright © 2016-2018 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 +CREATE TABLE IF NOT EXISTS audit_log (
  18 + id varchar(31) NOT NULL CONSTRAINT audit_log_pkey PRIMARY KEY,
  19 + tenant_id varchar(31),
  20 + customer_id varchar(31),
  21 + entity_id varchar(31),
  22 + entity_type varchar(255),
  23 + entity_name varchar(255),
  24 + user_id varchar(31),
  25 + user_name varchar(255),
  26 + action_type varchar(255),
  27 + action_data varchar(1000000),
  28 + action_status varchar(255),
  29 + action_failure_details varchar(1000000)
  30 +);
  31 +
  32 +DROP TABLE IF EXISTS dashboard;
  33 +
  34 +CREATE TABLE IF NOT EXISTS dashboard (
  35 + id varchar(31) NOT NULL CONSTRAINT dashboard_pkey PRIMARY KEY,
  36 + configuration varchar(10000000),
  37 + assigned_customers varchar(1000000),
  38 + search_text varchar(255),
  39 + tenant_id varchar(31),
  40 + title varchar(255)
  41 +);
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
@@ -13,7 +13,6 @@ @@ -13,7 +13,6 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -  
17 package org.thingsboard.server; 16 package org.thingsboard.server;
18 17
19 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
@@ -40,6 +40,7 @@ import org.thingsboard.server.controller.plugin.PluginWebSocketMsgEndpoint; @@ -40,6 +40,7 @@ import org.thingsboard.server.controller.plugin.PluginWebSocketMsgEndpoint;
40 import org.thingsboard.server.dao.alarm.AlarmService; 40 import org.thingsboard.server.dao.alarm.AlarmService;
41 import org.thingsboard.server.dao.asset.AssetService; 41 import org.thingsboard.server.dao.asset.AssetService;
42 import org.thingsboard.server.dao.attributes.AttributesService; 42 import org.thingsboard.server.dao.attributes.AttributesService;
  43 +import org.thingsboard.server.dao.audit.AuditLogService;
43 import org.thingsboard.server.dao.customer.CustomerService; 44 import org.thingsboard.server.dao.customer.CustomerService;
44 import org.thingsboard.server.dao.device.DeviceService; 45 import org.thingsboard.server.dao.device.DeviceService;
45 import org.thingsboard.server.dao.event.EventService; 46 import org.thingsboard.server.dao.event.EventService;
@@ -114,6 +115,9 @@ public class ActorSystemContext { @@ -114,6 +115,9 @@ public class ActorSystemContext {
114 @Getter private RelationService relationService; 115 @Getter private RelationService relationService;
115 116
116 @Autowired 117 @Autowired
  118 + @Getter private AuditLogService auditLogService;
  119 +
  120 + @Autowired
117 @Getter @Setter private PluginWebSocketMsgEndpoint wsMsgEndpoint; 121 @Getter @Setter private PluginWebSocketMsgEndpoint wsMsgEndpoint;
118 122
119 @Value("${actors.session.sync.timeout}") 123 @Value("${actors.session.sync.timeout}")
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.Device; @@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.Device;
26 import org.thingsboard.server.common.data.EntityType; 26 import org.thingsboard.server.common.data.EntityType;
27 import org.thingsboard.server.common.data.Tenant; 27 import org.thingsboard.server.common.data.Tenant;
28 import org.thingsboard.server.common.data.asset.Asset; 28 import org.thingsboard.server.common.data.asset.Asset;
  29 +import org.thingsboard.server.common.data.audit.ActionType;
29 import org.thingsboard.server.common.data.id.*; 30 import org.thingsboard.server.common.data.id.*;
30 import org.thingsboard.server.common.data.kv.AttributeKey; 31 import org.thingsboard.server.common.data.kv.AttributeKey;
31 import org.thingsboard.server.common.data.kv.AttributeKvEntry; 32 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
@@ -41,9 +42,7 @@ import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotific @@ -41,9 +42,7 @@ import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotific
41 import org.thingsboard.server.extensions.api.plugins.PluginApiCallSecurityContext; 42 import org.thingsboard.server.extensions.api.plugins.PluginApiCallSecurityContext;
42 import org.thingsboard.server.extensions.api.plugins.PluginCallback; 43 import org.thingsboard.server.extensions.api.plugins.PluginCallback;
43 import org.thingsboard.server.extensions.api.plugins.PluginContext; 44 import org.thingsboard.server.extensions.api.plugins.PluginContext;
44 -import org.thingsboard.server.extensions.api.plugins.msg.PluginToRuleMsg;  
45 -import org.thingsboard.server.extensions.api.plugins.msg.TimeoutMsg;  
46 -import org.thingsboard.server.extensions.api.plugins.msg.ToDeviceRpcRequest; 45 +import org.thingsboard.server.extensions.api.plugins.msg.*;
47 import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg; 46 import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg;
48 import org.thingsboard.server.extensions.api.plugins.rpc.RpcMsg; 47 import org.thingsboard.server.extensions.api.plugins.rpc.RpcMsg;
49 import org.thingsboard.server.extensions.api.plugins.ws.PluginWebsocketSessionRef; 48 import org.thingsboard.server.extensions.api.plugins.ws.PluginWebsocketSessionRef;
@@ -197,6 +196,52 @@ public final class PluginProcessingContext implements PluginContext { @@ -197,6 +196,52 @@ public final class PluginProcessingContext implements PluginContext {
197 } 196 }
198 197
199 @Override 198 @Override
  199 + public void logAttributesUpdated(PluginApiCallSecurityContext ctx, EntityId entityId, String attributeType,
  200 + List<AttributeKvEntry> attributes, Exception e) {
  201 + pluginCtx.auditLogService.logEntityAction(
  202 + ctx.getTenantId(),
  203 + ctx.getCustomerId(),
  204 + ctx.getUserId(),
  205 + ctx.getUserName(),
  206 + (UUIDBased & EntityId)entityId,
  207 + null,
  208 + ActionType.ATTRIBUTES_UPDATED,
  209 + e,
  210 + attributeType,
  211 + attributes);
  212 + }
  213 +
  214 + @Override
  215 + public void logAttributesDeleted(PluginApiCallSecurityContext ctx, EntityId entityId, String attributeType, List<String> keys, Exception e) {
  216 + pluginCtx.auditLogService.logEntityAction(
  217 + ctx.getTenantId(),
  218 + ctx.getCustomerId(),
  219 + ctx.getUserId(),
  220 + ctx.getUserName(),
  221 + (UUIDBased & EntityId)entityId,
  222 + null,
  223 + ActionType.ATTRIBUTES_DELETED,
  224 + e,
  225 + attributeType,
  226 + keys);
  227 + }
  228 +
  229 + @Override
  230 + public void logAttributesRead(PluginApiCallSecurityContext ctx, EntityId entityId, String attributeType, List<String> keys, Exception e) {
  231 + pluginCtx.auditLogService.logEntityAction(
  232 + ctx.getTenantId(),
  233 + ctx.getCustomerId(),
  234 + ctx.getUserId(),
  235 + ctx.getUserName(),
  236 + (UUIDBased & EntityId)entityId,
  237 + null,
  238 + ActionType.ATTRIBUTES_READ,
  239 + e,
  240 + attributeType,
  241 + keys);
  242 + }
  243 +
  244 + @Override
200 public void loadLatestTimeseries(final EntityId entityId, final Collection<String> keys, final PluginCallback<List<TsKvEntry>> callback) { 245 public void loadLatestTimeseries(final EntityId entityId, final Collection<String> keys, final PluginCallback<List<TsKvEntry>> callback) {
201 validate(entityId, new ValidationCallback(callback, ctx -> { 246 validate(entityId, new ValidationCallback(callback, ctx -> {
202 ListenableFuture<List<TsKvEntry>> rsListFuture = pluginCtx.tsService.findLatest(entityId, keys); 247 ListenableFuture<List<TsKvEntry>> rsListFuture = pluginCtx.tsService.findLatest(entityId, keys);
@@ -429,12 +474,12 @@ public final class PluginProcessingContext implements PluginContext { @@ -429,12 +474,12 @@ public final class PluginProcessingContext implements PluginContext {
429 474
430 @Override 475 @Override
431 public ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType) { 476 public ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType) {
432 - return this.pluginCtx.relationService.findByFromAndType(from, relationType, RelationTypeGroup.COMMON); 477 + return this.pluginCtx.relationService.findByFromAndTypeAsync(from, relationType, RelationTypeGroup.COMMON);
433 } 478 }
434 479
435 @Override 480 @Override
436 public ListenableFuture<List<EntityRelation>> findByToAndType(EntityId from, String relationType) { 481 public ListenableFuture<List<EntityRelation>> findByToAndType(EntityId from, String relationType) {
437 - return this.pluginCtx.relationService.findByToAndType(from, relationType, RelationTypeGroup.COMMON); 482 + return this.pluginCtx.relationService.findByToAndTypeAsync(from, relationType, RelationTypeGroup.COMMON);
438 } 483 }
439 484
440 @Override 485 @Override
@@ -461,6 +506,29 @@ public final class PluginProcessingContext implements PluginContext { @@ -461,6 +506,29 @@ public final class PluginProcessingContext implements PluginContext {
461 } 506 }
462 507
463 @Override 508 @Override
  509 + public void logRpcRequest(PluginApiCallSecurityContext ctx, DeviceId deviceId, ToDeviceRpcRequestBody body, boolean oneWay, Optional<RpcError> rpcError, Exception e) {
  510 + String rpcErrorStr = "";
  511 + if (rpcError.isPresent()) {
  512 + rpcErrorStr = "RPC Error: " + rpcError.get().name();
  513 + }
  514 + String method = body.getMethod();
  515 + String params = body.getParams();
  516 + pluginCtx.auditLogService.logEntityAction(
  517 + ctx.getTenantId(),
  518 + ctx.getCustomerId(),
  519 + ctx.getUserId(),
  520 + ctx.getUserName(),
  521 + deviceId,
  522 + null,
  523 + ActionType.RPC_CALL,
  524 + e,
  525 + rpcErrorStr,
  526 + new Boolean(oneWay),
  527 + method,
  528 + params);
  529 + }
  530 +
  531 + @Override
464 public void scheduleTimeoutMsg(TimeoutMsg msg) { 532 public void scheduleTimeoutMsg(TimeoutMsg msg) {
465 pluginCtx.scheduleTimeoutMsg(msg); 533 pluginCtx.scheduleTimeoutMsg(msg);
466 } 534 }
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@ import org.thingsboard.server.controller.plugin.PluginWebSocketMsgEndpoint; @@ -27,6 +27,7 @@ import org.thingsboard.server.controller.plugin.PluginWebSocketMsgEndpoint;
27 import org.thingsboard.server.common.data.id.PluginId; 27 import org.thingsboard.server.common.data.id.PluginId;
28 import org.thingsboard.server.dao.asset.AssetService; 28 import org.thingsboard.server.dao.asset.AssetService;
29 import org.thingsboard.server.dao.attributes.AttributesService; 29 import org.thingsboard.server.dao.attributes.AttributesService;
  30 +import org.thingsboard.server.dao.audit.AuditLogService;
30 import org.thingsboard.server.dao.customer.CustomerService; 31 import org.thingsboard.server.dao.customer.CustomerService;
31 import org.thingsboard.server.dao.device.DeviceService; 32 import org.thingsboard.server.dao.device.DeviceService;
32 import org.thingsboard.server.dao.plugin.PluginService; 33 import org.thingsboard.server.dao.plugin.PluginService;
@@ -63,6 +64,7 @@ public final class SharedPluginProcessingContext { @@ -63,6 +64,7 @@ public final class SharedPluginProcessingContext {
63 final ClusterRpcService rpcService; 64 final ClusterRpcService rpcService;
64 final ClusterRoutingService routingService; 65 final ClusterRoutingService routingService;
65 final RelationService relationService; 66 final RelationService relationService;
  67 + final AuditLogService auditLogService;
66 final PluginId pluginId; 68 final PluginId pluginId;
67 final TenantId tenantId; 69 final TenantId tenantId;
68 70
@@ -86,6 +88,7 @@ public final class SharedPluginProcessingContext { @@ -86,6 +88,7 @@ public final class SharedPluginProcessingContext {
86 this.customerService = sysContext.getCustomerService(); 88 this.customerService = sysContext.getCustomerService();
87 this.tenantService = sysContext.getTenantService(); 89 this.tenantService = sysContext.getTenantService();
88 this.relationService = sysContext.getRelationService(); 90 this.relationService = sysContext.getRelationService();
  91 + this.auditLogService = sysContext.getAuditLogService();
89 } 92 }
90 93
91 public PluginId getPluginId() { 94 public PluginId getPluginId() {
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
@@ -148,7 +148,7 @@ public class BasicRpcSessionListener implements GrpcSessionListener { @@ -148,7 +148,7 @@ public class BasicRpcSessionListener implements GrpcSessionListener {
148 DeviceId deviceId = new DeviceId(toUUID(msg.getDeviceId())); 148 DeviceId deviceId = new DeviceId(toUUID(msg.getDeviceId()));
149 149
150 ToDeviceRpcRequestBody requestBody = new ToDeviceRpcRequestBody(msg.getMethod(), msg.getParams()); 150 ToDeviceRpcRequestBody requestBody = new ToDeviceRpcRequestBody(msg.getMethod(), msg.getParams());
151 - ToDeviceRpcRequest request = new ToDeviceRpcRequest(toUUID(msg.getMsgId()), deviceTenantId, deviceId, msg.getOneway(), msg.getExpTime(), requestBody); 151 + ToDeviceRpcRequest request = new ToDeviceRpcRequest(toUUID(msg.getMsgId()), null, deviceTenantId, deviceId, msg.getOneway(), msg.getExpTime(), requestBody);
152 152
153 return new ToDeviceRpcRequestPluginMsg(serverAddress, pluginId, pluginTenantId, request); 153 return new ToDeviceRpcRequestPluginMsg(serverAddress, pluginId, pluginTenantId, request);
154 } 154 }
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
  1 +/**
  2 + * Copyright © 2016-2018 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 +package org.thingsboard.server.config;
  17 +
  18 +import org.springframework.boot.context.properties.ConfigurationProperties;
  19 +import org.springframework.context.annotation.Configuration;
  20 +import org.thingsboard.server.common.data.EntityType;
  21 +import org.thingsboard.server.common.data.audit.ActionType;
  22 +
  23 +import java.util.HashMap;
  24 +import java.util.Map;
  25 +
  26 +@Configuration
  27 +@ConfigurationProperties(prefix = "audit_log.logging_level")
  28 +public class AuditLogLevelProperties {
  29 +
  30 + private Map<String, String> mask = new HashMap<>();
  31 +
  32 + public AuditLogLevelProperties() {
  33 + super();
  34 + }
  35 +
  36 + public void setMask(Map<String, String> mask) {
  37 + this.mask = mask;
  38 + }
  39 +
  40 + public Map<String, String> getMask() {
  41 + return this.mask;
  42 + }
  43 +}
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
@@ -40,6 +40,7 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher; @@ -40,6 +40,7 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
40 import org.springframework.web.cors.CorsUtils; 40 import org.springframework.web.cors.CorsUtils;
41 import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 41 import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
42 import org.springframework.web.filter.CorsFilter; 42 import org.springframework.web.filter.CorsFilter;
  43 +import org.thingsboard.server.dao.audit.AuditLogLevelFilter;
43 import org.thingsboard.server.exception.ThingsboardErrorResponseHandler; 44 import org.thingsboard.server.exception.ThingsboardErrorResponseHandler;
44 import org.thingsboard.server.service.security.auth.rest.RestAuthenticationProvider; 45 import org.thingsboard.server.service.security.auth.rest.RestAuthenticationProvider;
45 import org.thingsboard.server.service.security.auth.rest.RestLoginProcessingFilter; 46 import org.thingsboard.server.service.security.auth.rest.RestLoginProcessingFilter;
@@ -198,4 +199,9 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt @@ -198,4 +199,9 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt
198 return new CorsFilter(source); 199 return new CorsFilter(source);
199 } 200 }
200 } 201 }
  202 +
  203 + @Bean
  204 + public AuditLogLevelFilter auditLogLevelFilter(@Autowired AuditLogLevelProperties auditLogLevelProperties) {
  205 + return new AuditLogLevelFilter(auditLogLevelProperties.getMask());
  206 + }
201 } 207 }
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
@@ -21,7 +21,9 @@ import org.springframework.security.access.prepost.PreAuthorize; @@ -21,7 +21,9 @@ import org.springframework.security.access.prepost.PreAuthorize;
21 import org.springframework.web.bind.annotation.*; 21 import org.springframework.web.bind.annotation.*;
22 import org.thingsboard.server.common.data.Customer; 22 import org.thingsboard.server.common.data.Customer;
23 import org.thingsboard.server.common.data.EntitySubtype; 23 import org.thingsboard.server.common.data.EntitySubtype;
  24 +import org.thingsboard.server.common.data.EntityType;
24 import org.thingsboard.server.common.data.asset.Asset; 25 import org.thingsboard.server.common.data.asset.Asset;
  26 +import org.thingsboard.server.common.data.audit.ActionType;
25 import org.thingsboard.server.common.data.id.AssetId; 27 import org.thingsboard.server.common.data.id.AssetId;
26 import org.thingsboard.server.common.data.id.CustomerId; 28 import org.thingsboard.server.common.data.id.CustomerId;
27 import org.thingsboard.server.common.data.id.TenantId; 29 import org.thingsboard.server.common.data.id.TenantId;
@@ -73,8 +75,16 @@ public class AssetController extends BaseController { @@ -73,8 +75,16 @@ public class AssetController extends BaseController {
73 checkCustomerId(asset.getCustomerId()); 75 checkCustomerId(asset.getCustomerId());
74 } 76 }
75 } 77 }
76 - return checkNotNull(assetService.saveAsset(asset)); 78 + Asset savedAsset = checkNotNull(assetService.saveAsset(asset));
  79 +
  80 + logEntityAction(savedAsset.getId(), savedAsset,
  81 + savedAsset.getCustomerId(),
  82 + asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
  83 +
  84 + return savedAsset;
77 } catch (Exception e) { 85 } catch (Exception e) {
  86 + logEntityAction(emptyId(EntityType.ASSET), asset,
  87 + null, asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e);
78 throw handleException(e); 88 throw handleException(e);
79 } 89 }
80 } 90 }
@@ -86,9 +96,18 @@ public class AssetController extends BaseController { @@ -86,9 +96,18 @@ public class AssetController extends BaseController {
86 checkParameter(ASSET_ID, strAssetId); 96 checkParameter(ASSET_ID, strAssetId);
87 try { 97 try {
88 AssetId assetId = new AssetId(toUUID(strAssetId)); 98 AssetId assetId = new AssetId(toUUID(strAssetId));
89 - checkAssetId(assetId); 99 + Asset asset = checkAssetId(assetId);
90 assetService.deleteAsset(assetId); 100 assetService.deleteAsset(assetId);
  101 +
  102 + logEntityAction(assetId, asset,
  103 + asset.getCustomerId(),
  104 + ActionType.DELETED, null, strAssetId);
  105 +
91 } catch (Exception e) { 106 } catch (Exception e) {
  107 + logEntityAction(emptyId(EntityType.ASSET),
  108 + null,
  109 + null,
  110 + ActionType.DELETED, e, strAssetId);
92 throw handleException(e); 111 throw handleException(e);
93 } 112 }
94 } 113 }
@@ -102,13 +121,24 @@ public class AssetController extends BaseController { @@ -102,13 +121,24 @@ public class AssetController extends BaseController {
102 checkParameter(ASSET_ID, strAssetId); 121 checkParameter(ASSET_ID, strAssetId);
103 try { 122 try {
104 CustomerId customerId = new CustomerId(toUUID(strCustomerId)); 123 CustomerId customerId = new CustomerId(toUUID(strCustomerId));
105 - checkCustomerId(customerId); 124 + Customer customer = checkCustomerId(customerId);
106 125
107 AssetId assetId = new AssetId(toUUID(strAssetId)); 126 AssetId assetId = new AssetId(toUUID(strAssetId));
108 checkAssetId(assetId); 127 checkAssetId(assetId);
109 128
110 - return checkNotNull(assetService.assignAssetToCustomer(assetId, customerId)); 129 + Asset savedAsset = checkNotNull(assetService.assignAssetToCustomer(assetId, customerId));
  130 +
  131 + logEntityAction(assetId, savedAsset,
  132 + savedAsset.getCustomerId(),
  133 + ActionType.ASSIGNED_TO_CUSTOMER, null, strAssetId, strCustomerId, customer.getName());
  134 +
  135 + return savedAsset;
111 } catch (Exception e) { 136 } catch (Exception e) {
  137 +
  138 + logEntityAction(emptyId(EntityType.ASSET), null,
  139 + null,
  140 + ActionType.ASSIGNED_TO_CUSTOMER, e, strAssetId, strCustomerId);
  141 +
112 throw handleException(e); 142 throw handleException(e);
113 } 143 }
114 } 144 }
@@ -124,8 +154,22 @@ public class AssetController extends BaseController { @@ -124,8 +154,22 @@ public class AssetController extends BaseController {
124 if (asset.getCustomerId() == null || asset.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { 154 if (asset.getCustomerId() == null || asset.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) {
125 throw new IncorrectParameterException("Asset isn't assigned to any customer!"); 155 throw new IncorrectParameterException("Asset isn't assigned to any customer!");
126 } 156 }
127 - return checkNotNull(assetService.unassignAssetFromCustomer(assetId)); 157 +
  158 + Customer customer = checkCustomerId(asset.getCustomerId());
  159 +
  160 + Asset savedAsset = checkNotNull(assetService.unassignAssetFromCustomer(assetId));
  161 +
  162 + logEntityAction(assetId, asset,
  163 + asset.getCustomerId(),
  164 + ActionType.UNASSIGNED_FROM_CUSTOMER, null, strAssetId, customer.getId().toString(), customer.getName());
  165 +
  166 + return savedAsset;
128 } catch (Exception e) { 167 } catch (Exception e) {
  168 +
  169 + logEntityAction(emptyId(EntityType.ASSET), null,
  170 + null,
  171 + ActionType.UNASSIGNED_FROM_CUSTOMER, e, strAssetId);
  172 +
129 throw handleException(e); 173 throw handleException(e);
130 } 174 }
131 } 175 }
@@ -139,8 +183,19 @@ public class AssetController extends BaseController { @@ -139,8 +183,19 @@ public class AssetController extends BaseController {
139 AssetId assetId = new AssetId(toUUID(strAssetId)); 183 AssetId assetId = new AssetId(toUUID(strAssetId));
140 Asset asset = checkAssetId(assetId); 184 Asset asset = checkAssetId(assetId);
141 Customer publicCustomer = customerService.findOrCreatePublicCustomer(asset.getTenantId()); 185 Customer publicCustomer = customerService.findOrCreatePublicCustomer(asset.getTenantId());
142 - return checkNotNull(assetService.assignAssetToCustomer(assetId, publicCustomer.getId())); 186 + Asset savedAsset = checkNotNull(assetService.assignAssetToCustomer(assetId, publicCustomer.getId()));
  187 +
  188 + logEntityAction(assetId, savedAsset,
  189 + savedAsset.getCustomerId(),
  190 + ActionType.ASSIGNED_TO_CUSTOMER, null, strAssetId, publicCustomer.getId().toString(), publicCustomer.getName());
  191 +
  192 + return savedAsset;
143 } catch (Exception e) { 193 } catch (Exception e) {
  194 +
  195 + logEntityAction(emptyId(EntityType.ASSET), null,
  196 + null,
  197 + ActionType.ASSIGNED_TO_CUSTOMER, e, strAssetId);
  198 +
144 throw handleException(e); 199 throw handleException(e);
145 } 200 }
146 } 201 }
  1 +/**
  2 + * Copyright © 2016-2018 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 +package org.thingsboard.server.controller;
  17 +
  18 +import org.springframework.security.access.prepost.PreAuthorize;
  19 +import org.springframework.web.bind.annotation.*;
  20 +import org.thingsboard.server.common.data.audit.AuditLog;
  21 +import org.thingsboard.server.common.data.id.CustomerId;
  22 +import org.thingsboard.server.common.data.id.EntityIdFactory;
  23 +import org.thingsboard.server.common.data.id.TenantId;
  24 +import org.thingsboard.server.common.data.id.UserId;
  25 +import org.thingsboard.server.common.data.page.TimePageData;
  26 +import org.thingsboard.server.common.data.page.TimePageLink;
  27 +import org.thingsboard.server.exception.ThingsboardException;
  28 +
  29 +import java.util.UUID;
  30 +
  31 +@RestController
  32 +@RequestMapping("/api")
  33 +public class AuditLogController extends BaseController {
  34 +
  35 + @PreAuthorize("hasAuthority('TENANT_ADMIN')")
  36 + @RequestMapping(value = "/audit/logs/customer/{customerId}", params = {"limit"}, method = RequestMethod.GET)
  37 + @ResponseBody
  38 + public TimePageData<AuditLog> getAuditLogsByCustomerId(
  39 + @PathVariable("customerId") String strCustomerId,
  40 + @RequestParam int limit,
  41 + @RequestParam(required = false) Long startTime,
  42 + @RequestParam(required = false) Long endTime,
  43 + @RequestParam(required = false, defaultValue = "false") boolean ascOrder,
  44 + @RequestParam(required = false) String offset) throws ThingsboardException {
  45 + try {
  46 + checkParameter("CustomerId", strCustomerId);
  47 + TenantId tenantId = getCurrentUser().getTenantId();
  48 + TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset);
  49 + return checkNotNull(auditLogService.findAuditLogsByTenantIdAndCustomerId(tenantId, new CustomerId(UUID.fromString(strCustomerId)), pageLink));
  50 + } catch (Exception e) {
  51 + throw handleException(e);
  52 + }
  53 + }
  54 +
  55 + @PreAuthorize("hasAuthority('TENANT_ADMIN')")
  56 + @RequestMapping(value = "/audit/logs/user/{userId}", params = {"limit"}, method = RequestMethod.GET)
  57 + @ResponseBody
  58 + public TimePageData<AuditLog> getAuditLogsByUserId(
  59 + @PathVariable("userId") String strUserId,
  60 + @RequestParam int limit,
  61 + @RequestParam(required = false) Long startTime,
  62 + @RequestParam(required = false) Long endTime,
  63 + @RequestParam(required = false, defaultValue = "false") boolean ascOrder,
  64 + @RequestParam(required = false) String offset) throws ThingsboardException {
  65 + try {
  66 + checkParameter("UserId", strUserId);
  67 + TenantId tenantId = getCurrentUser().getTenantId();
  68 + TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset);
  69 + return checkNotNull(auditLogService.findAuditLogsByTenantIdAndUserId(tenantId, new UserId(UUID.fromString(strUserId)), pageLink));
  70 + } catch (Exception e) {
  71 + throw handleException(e);
  72 + }
  73 + }
  74 +
  75 + @PreAuthorize("hasAuthority('TENANT_ADMIN')")
  76 + @RequestMapping(value = "/audit/logs/entity/{entityType}/{entityId}", params = {"limit"}, method = RequestMethod.GET)
  77 + @ResponseBody
  78 + public TimePageData<AuditLog> getAuditLogsByEntityId(
  79 + @PathVariable("entityType") String strEntityType,
  80 + @PathVariable("entityId") String strEntityId,
  81 + @RequestParam int limit,
  82 + @RequestParam(required = false) Long startTime,
  83 + @RequestParam(required = false) Long endTime,
  84 + @RequestParam(required = false, defaultValue = "false") boolean ascOrder,
  85 + @RequestParam(required = false) String offset) throws ThingsboardException {
  86 + try {
  87 + checkParameter("EntityId", strEntityId);
  88 + checkParameter("EntityType", strEntityType);
  89 + TenantId tenantId = getCurrentUser().getTenantId();
  90 + TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset);
  91 + return checkNotNull(auditLogService.findAuditLogsByTenantIdAndEntityId(tenantId, EntityIdFactory.getByTypeAndId(strEntityType, strEntityId), pageLink));
  92 + } catch (Exception e) {
  93 + throw handleException(e);
  94 + }
  95 + }
  96 +
  97 + @PreAuthorize("hasAuthority('TENANT_ADMIN')")
  98 + @RequestMapping(value = "/audit/logs", params = {"limit"}, method = RequestMethod.GET)
  99 + @ResponseBody
  100 + public TimePageData<AuditLog> getAuditLogs(
  101 + @RequestParam int limit,
  102 + @RequestParam(required = false) Long startTime,
  103 + @RequestParam(required = false) Long endTime,
  104 + @RequestParam(required = false, defaultValue = "false") boolean ascOrder,
  105 + @RequestParam(required = false) String offset) throws ThingsboardException {
  106 + try {
  107 + TenantId tenantId = getCurrentUser().getTenantId();
  108 + TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset);
  109 + return checkNotNull(auditLogService.findAuditLogsByTenantId(tenantId, pageLink));
  110 + } catch (Exception e) {
  111 + throw handleException(e);
  112 + }
  113 + }
  114 +}
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
@@ -15,9 +15,12 @@ @@ -15,9 +15,12 @@
15 */ 15 */
16 package org.thingsboard.server.controller; 16 package org.thingsboard.server.controller;
17 17
  18 +import com.fasterxml.jackson.databind.JsonNode;
  19 +import com.fasterxml.jackson.databind.ObjectMapper;
18 import lombok.extern.slf4j.Slf4j; 20 import lombok.extern.slf4j.Slf4j;
19 import org.apache.commons.lang3.StringUtils; 21 import org.apache.commons.lang3.StringUtils;
20 import org.springframework.beans.factory.annotation.Autowired; 22 import org.springframework.beans.factory.annotation.Autowired;
  23 +import org.springframework.beans.factory.annotation.Value;
21 import org.springframework.security.core.Authentication; 24 import org.springframework.security.core.Authentication;
22 import org.springframework.security.core.context.SecurityContextHolder; 25 import org.springframework.security.core.context.SecurityContextHolder;
23 import org.springframework.web.bind.annotation.ExceptionHandler; 26 import org.springframework.web.bind.annotation.ExceptionHandler;
@@ -27,6 +30,8 @@ import org.thingsboard.server.common.data.alarm.Alarm; @@ -27,6 +30,8 @@ import org.thingsboard.server.common.data.alarm.Alarm;
27 import org.thingsboard.server.common.data.alarm.AlarmId; 30 import org.thingsboard.server.common.data.alarm.AlarmId;
28 import org.thingsboard.server.common.data.alarm.AlarmInfo; 31 import org.thingsboard.server.common.data.alarm.AlarmInfo;
29 import org.thingsboard.server.common.data.asset.Asset; 32 import org.thingsboard.server.common.data.asset.Asset;
  33 +import org.thingsboard.server.common.data.audit.ActionStatus;
  34 +import org.thingsboard.server.common.data.audit.ActionType;
30 import org.thingsboard.server.common.data.id.*; 35 import org.thingsboard.server.common.data.id.*;
31 import org.thingsboard.server.common.data.page.TextPageLink; 36 import org.thingsboard.server.common.data.page.TextPageLink;
32 import org.thingsboard.server.common.data.page.TimePageLink; 37 import org.thingsboard.server.common.data.page.TimePageLink;
@@ -39,6 +44,7 @@ import org.thingsboard.server.common.data.widget.WidgetType; @@ -39,6 +44,7 @@ import org.thingsboard.server.common.data.widget.WidgetType;
39 import org.thingsboard.server.common.data.widget.WidgetsBundle; 44 import org.thingsboard.server.common.data.widget.WidgetsBundle;
40 import org.thingsboard.server.dao.alarm.AlarmService; 45 import org.thingsboard.server.dao.alarm.AlarmService;
41 import org.thingsboard.server.dao.asset.AssetService; 46 import org.thingsboard.server.dao.asset.AssetService;
  47 +import org.thingsboard.server.dao.audit.AuditLogService;
42 import org.thingsboard.server.dao.customer.CustomerService; 48 import org.thingsboard.server.dao.customer.CustomerService;
43 import org.thingsboard.server.dao.dashboard.DashboardService; 49 import org.thingsboard.server.dao.dashboard.DashboardService;
44 import org.thingsboard.server.dao.device.DeviceCredentialsService; 50 import org.thingsboard.server.dao.device.DeviceCredentialsService;
@@ -72,6 +78,7 @@ public abstract class BaseController { @@ -72,6 +78,7 @@ public abstract class BaseController {
72 78
73 public static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; 79 public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
74 public static final String YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION = "You don't have permission to perform this operation!"; 80 public static final String YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION = "You don't have permission to perform this operation!";
  81 +
75 @Autowired 82 @Autowired
76 private ThingsboardErrorResponseHandler errorResponseHandler; 83 private ThingsboardErrorResponseHandler errorResponseHandler;
77 84
@@ -117,6 +124,8 @@ public abstract class BaseController { @@ -117,6 +124,8 @@ public abstract class BaseController {
117 @Autowired 124 @Autowired
118 protected RelationService relationService; 125 protected RelationService relationService;
119 126
  127 + @Autowired
  128 + protected AuditLogService auditLogService;
120 129
121 @ExceptionHandler(ThingsboardException.class) 130 @ExceptionHandler(ThingsboardException.class)
122 public void handleThingsboardException(ThingsboardException ex, HttpServletResponse response) { 131 public void handleThingsboardException(ThingsboardException ex, HttpServletResponse response) {
@@ -129,7 +138,7 @@ public abstract class BaseController { @@ -129,7 +138,7 @@ public abstract class BaseController {
129 138
130 private ThingsboardException handleException(Exception exception, boolean logException) { 139 private ThingsboardException handleException(Exception exception, boolean logException) {
131 if (logException) { 140 if (logException) {
132 - log.error("Error [{}]", exception.getMessage()); 141 + log.error("Error [{}]", exception.getMessage(), exception);
133 } 142 }
134 143
135 String cause = ""; 144 String cause = "";
@@ -414,7 +423,7 @@ public abstract class BaseController { @@ -414,7 +423,7 @@ public abstract class BaseController {
414 try { 423 try {
415 validateId(dashboardId, "Incorrect dashboardId " + dashboardId); 424 validateId(dashboardId, "Incorrect dashboardId " + dashboardId);
416 Dashboard dashboard = dashboardService.findDashboardById(dashboardId); 425 Dashboard dashboard = dashboardService.findDashboardById(dashboardId);
417 - checkDashboard(dashboard, true); 426 + checkDashboard(dashboard);
418 return dashboard; 427 return dashboard;
419 } catch (Exception e) { 428 } catch (Exception e) {
420 throw handleException(e, false); 429 throw handleException(e, false);
@@ -425,28 +434,23 @@ public abstract class BaseController { @@ -425,28 +434,23 @@ public abstract class BaseController {
425 try { 434 try {
426 validateId(dashboardId, "Incorrect dashboardId " + dashboardId); 435 validateId(dashboardId, "Incorrect dashboardId " + dashboardId);
427 DashboardInfo dashboardInfo = dashboardService.findDashboardInfoById(dashboardId); 436 DashboardInfo dashboardInfo = dashboardService.findDashboardInfoById(dashboardId);
428 - SecurityUser authUser = getCurrentUser();  
429 - checkDashboard(dashboardInfo, authUser.getAuthority() != Authority.SYS_ADMIN); 437 + checkDashboard(dashboardInfo);
430 return dashboardInfo; 438 return dashboardInfo;
431 } catch (Exception e) { 439 } catch (Exception e) {
432 throw handleException(e, false); 440 throw handleException(e, false);
433 } 441 }
434 } 442 }
435 443
436 - private void checkDashboard(DashboardInfo dashboard, boolean checkCustomerId) throws ThingsboardException { 444 + private void checkDashboard(DashboardInfo dashboard) throws ThingsboardException {
437 checkNotNull(dashboard); 445 checkNotNull(dashboard);
438 checkTenantId(dashboard.getTenantId()); 446 checkTenantId(dashboard.getTenantId());
439 SecurityUser authUser = getCurrentUser(); 447 SecurityUser authUser = getCurrentUser();
440 if (authUser.getAuthority() == Authority.CUSTOMER_USER) { 448 if (authUser.getAuthority() == Authority.CUSTOMER_USER) {
441 - if (dashboard.getCustomerId() == null || dashboard.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { 449 + if (!dashboard.isAssignedToCustomer(authUser.getCustomerId())) {
442 throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION, 450 throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION,
443 ThingsboardErrorCode.PERMISSION_DENIED); 451 ThingsboardErrorCode.PERMISSION_DENIED);
444 } 452 }
445 } 453 }
446 - if (checkCustomerId &&  
447 - dashboard.getCustomerId() != null && !dashboard.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) {  
448 - checkCustomerId(dashboard.getCustomerId());  
449 - }  
450 } 454 }
451 455
452 ComponentDescriptor checkComponentDescriptorByClazz(String clazz) throws ThingsboardException { 456 ComponentDescriptor checkComponentDescriptorByClazz(String clazz) throws ThingsboardException {
@@ -541,4 +545,20 @@ public abstract class BaseController { @@ -541,4 +545,20 @@ public abstract class BaseController {
541 serverPort); 545 serverPort);
542 return baseUrl; 546 return baseUrl;
543 } 547 }
  548 +
  549 + protected <I extends UUIDBased & EntityId> I emptyId(EntityType entityType) {
  550 + return (I)EntityIdFactory.getByTypeAndUuid(entityType, ModelConstants.NULL_UUID);
  551 + }
  552 +
  553 + protected <E extends BaseData<I> & HasName,
  554 + I extends UUIDBased & EntityId> void logEntityAction(I entityId, E entity, CustomerId customerId,
  555 + ActionType actionType, Exception e, Object... additionalInfo) throws ThingsboardException {
  556 + User user = getCurrentUser();
  557 + if (customerId == null || customerId.isNullUid()) {
  558 + customerId = user.getCustomerId();
  559 + }
  560 + auditLogService.logEntityAction(user.getTenantId(), customerId, user.getId(), user.getName(), entityId, entity, actionType, e, additionalInfo);
  561 + }
  562 +
  563 +
544 } 564 }
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
@@ -22,6 +22,8 @@ import org.springframework.http.HttpStatus; @@ -22,6 +22,8 @@ import org.springframework.http.HttpStatus;
22 import org.springframework.security.access.prepost.PreAuthorize; 22 import org.springframework.security.access.prepost.PreAuthorize;
23 import org.springframework.web.bind.annotation.*; 23 import org.springframework.web.bind.annotation.*;
24 import org.thingsboard.server.common.data.Customer; 24 import org.thingsboard.server.common.data.Customer;
  25 +import org.thingsboard.server.common.data.EntityType;
  26 +import org.thingsboard.server.common.data.audit.ActionType;
25 import org.thingsboard.server.common.data.id.CustomerId; 27 import org.thingsboard.server.common.data.id.CustomerId;
26 import org.thingsboard.server.common.data.id.TenantId; 28 import org.thingsboard.server.common.data.id.TenantId;
27 import org.thingsboard.server.common.data.page.TextPageData; 29 import org.thingsboard.server.common.data.page.TextPageData;
@@ -86,8 +88,18 @@ public class CustomerController extends BaseController { @@ -86,8 +88,18 @@ public class CustomerController extends BaseController {
86 public Customer saveCustomer(@RequestBody Customer customer) throws ThingsboardException { 88 public Customer saveCustomer(@RequestBody Customer customer) throws ThingsboardException {
87 try { 89 try {
88 customer.setTenantId(getCurrentUser().getTenantId()); 90 customer.setTenantId(getCurrentUser().getTenantId());
89 - return checkNotNull(customerService.saveCustomer(customer)); 91 + Customer savedCustomer = checkNotNull(customerService.saveCustomer(customer));
  92 +
  93 + logEntityAction(savedCustomer.getId(), savedCustomer,
  94 + savedCustomer.getId(),
  95 + customer.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
  96 +
  97 + return savedCustomer;
90 } catch (Exception e) { 98 } catch (Exception e) {
  99 +
  100 + logEntityAction(emptyId(EntityType.CUSTOMER), customer,
  101 + null, customer.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e);
  102 +
91 throw handleException(e); 103 throw handleException(e);
92 } 104 }
93 } 105 }
@@ -99,9 +111,20 @@ public class CustomerController extends BaseController { @@ -99,9 +111,20 @@ public class CustomerController extends BaseController {
99 checkParameter(CUSTOMER_ID, strCustomerId); 111 checkParameter(CUSTOMER_ID, strCustomerId);
100 try { 112 try {
101 CustomerId customerId = new CustomerId(toUUID(strCustomerId)); 113 CustomerId customerId = new CustomerId(toUUID(strCustomerId));
102 - checkCustomerId(customerId); 114 + Customer customer = checkCustomerId(customerId);
103 customerService.deleteCustomer(customerId); 115 customerService.deleteCustomer(customerId);
  116 +
  117 + logEntityAction(customerId, customer,
  118 + customer.getId(),
  119 + ActionType.DELETED, null, strCustomerId);
  120 +
104 } catch (Exception e) { 121 } catch (Exception e) {
  122 +
  123 + logEntityAction(emptyId(EntityType.CUSTOMER),
  124 + null,
  125 + null,
  126 + ActionType.DELETED, e, strCustomerId);
  127 +
105 throw handleException(e); 128 throw handleException(e);
106 } 129 }
107 } 130 }
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
@@ -18,18 +18,22 @@ package org.thingsboard.server.controller; @@ -18,18 +18,22 @@ package org.thingsboard.server.controller;
18 import org.springframework.http.HttpStatus; 18 import org.springframework.http.HttpStatus;
19 import org.springframework.security.access.prepost.PreAuthorize; 19 import org.springframework.security.access.prepost.PreAuthorize;
20 import org.springframework.web.bind.annotation.*; 20 import org.springframework.web.bind.annotation.*;
21 -import org.thingsboard.server.common.data.Customer;  
22 -import org.thingsboard.server.common.data.Dashboard;  
23 -import org.thingsboard.server.common.data.DashboardInfo; 21 +import org.thingsboard.server.common.data.*;
  22 +import org.thingsboard.server.common.data.audit.ActionType;
24 import org.thingsboard.server.common.data.id.CustomerId; 23 import org.thingsboard.server.common.data.id.CustomerId;
25 import org.thingsboard.server.common.data.id.DashboardId; 24 import org.thingsboard.server.common.data.id.DashboardId;
26 import org.thingsboard.server.common.data.id.TenantId; 25 import org.thingsboard.server.common.data.id.TenantId;
27 import org.thingsboard.server.common.data.page.TextPageData; 26 import org.thingsboard.server.common.data.page.TextPageData;
28 import org.thingsboard.server.common.data.page.TextPageLink; 27 import org.thingsboard.server.common.data.page.TextPageLink;
  28 +import org.thingsboard.server.common.data.page.TimePageData;
  29 +import org.thingsboard.server.common.data.page.TimePageLink;
29 import org.thingsboard.server.dao.exception.IncorrectParameterException; 30 import org.thingsboard.server.dao.exception.IncorrectParameterException;
30 import org.thingsboard.server.dao.model.ModelConstants; 31 import org.thingsboard.server.dao.model.ModelConstants;
31 import org.thingsboard.server.exception.ThingsboardException; 32 import org.thingsboard.server.exception.ThingsboardException;
32 33
  34 +import java.util.HashSet;
  35 +import java.util.Set;
  36 +
33 @RestController 37 @RestController
34 @RequestMapping("/api") 38 @RequestMapping("/api")
35 public class DashboardController extends BaseController { 39 public class DashboardController extends BaseController {
@@ -75,8 +79,17 @@ public class DashboardController extends BaseController { @@ -75,8 +79,17 @@ public class DashboardController extends BaseController {
75 public Dashboard saveDashboard(@RequestBody Dashboard dashboard) throws ThingsboardException { 79 public Dashboard saveDashboard(@RequestBody Dashboard dashboard) throws ThingsboardException {
76 try { 80 try {
77 dashboard.setTenantId(getCurrentUser().getTenantId()); 81 dashboard.setTenantId(getCurrentUser().getTenantId());
78 - return checkNotNull(dashboardService.saveDashboard(dashboard)); 82 + Dashboard savedDashboard = checkNotNull(dashboardService.saveDashboard(dashboard));
  83 +
  84 + logEntityAction(savedDashboard.getId(), savedDashboard,
  85 + null,
  86 + dashboard.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
  87 +
  88 + return savedDashboard;
79 } catch (Exception e) { 89 } catch (Exception e) {
  90 + logEntityAction(emptyId(EntityType.DASHBOARD), dashboard,
  91 + null, dashboard.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e);
  92 +
80 throw handleException(e); 93 throw handleException(e);
81 } 94 }
82 } 95 }
@@ -88,9 +101,20 @@ public class DashboardController extends BaseController { @@ -88,9 +101,20 @@ public class DashboardController extends BaseController {
88 checkParameter(DASHBOARD_ID, strDashboardId); 101 checkParameter(DASHBOARD_ID, strDashboardId);
89 try { 102 try {
90 DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); 103 DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
91 - checkDashboardId(dashboardId); 104 + Dashboard dashboard = checkDashboardId(dashboardId);
92 dashboardService.deleteDashboard(dashboardId); 105 dashboardService.deleteDashboard(dashboardId);
  106 +
  107 + logEntityAction(dashboardId, dashboard,
  108 + null,
  109 + ActionType.DELETED, null, strDashboardId);
  110 +
93 } catch (Exception e) { 111 } catch (Exception e) {
  112 +
  113 + logEntityAction(emptyId(EntityType.DASHBOARD),
  114 + null,
  115 + null,
  116 + ActionType.DELETED, e, strDashboardId);
  117 +
94 throw handleException(e); 118 throw handleException(e);
95 } 119 }
96 } 120 }
@@ -104,30 +128,207 @@ public class DashboardController extends BaseController { @@ -104,30 +128,207 @@ public class DashboardController extends BaseController {
104 checkParameter(DASHBOARD_ID, strDashboardId); 128 checkParameter(DASHBOARD_ID, strDashboardId);
105 try { 129 try {
106 CustomerId customerId = new CustomerId(toUUID(strCustomerId)); 130 CustomerId customerId = new CustomerId(toUUID(strCustomerId));
107 - checkCustomerId(customerId); 131 + Customer customer = checkCustomerId(customerId);
108 132
109 DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); 133 DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
110 checkDashboardId(dashboardId); 134 checkDashboardId(dashboardId);
111 135
112 - return checkNotNull(dashboardService.assignDashboardToCustomer(dashboardId, customerId)); 136 + Dashboard savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(dashboardId, customerId));
  137 +
  138 + logEntityAction(dashboardId, savedDashboard,
  139 + customerId,
  140 + ActionType.ASSIGNED_TO_CUSTOMER, null, strDashboardId, strCustomerId, customer.getName());
  141 +
  142 +
  143 + return savedDashboard;
113 } catch (Exception e) { 144 } catch (Exception e) {
  145 +
  146 + logEntityAction(emptyId(EntityType.DASHBOARD), null,
  147 + null,
  148 + ActionType.ASSIGNED_TO_CUSTOMER, e, strDashboardId, strCustomerId);
  149 +
114 throw handleException(e); 150 throw handleException(e);
115 } 151 }
116 } 152 }
117 153
118 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 154 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
119 - @RequestMapping(value = "/customer/dashboard/{dashboardId}", method = RequestMethod.DELETE) 155 + @RequestMapping(value = "/customer/{customerId}/dashboard/{dashboardId}", method = RequestMethod.DELETE)
120 @ResponseBody 156 @ResponseBody
121 - public Dashboard unassignDashboardFromCustomer(@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException { 157 + public Dashboard unassignDashboardFromCustomer(@PathVariable("customerId") String strCustomerId,
  158 + @PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
  159 + checkParameter("customerId", strCustomerId);
  160 + checkParameter(DASHBOARD_ID, strDashboardId);
  161 + try {
  162 + CustomerId customerId = new CustomerId(toUUID(strCustomerId));
  163 + Customer customer = checkCustomerId(customerId);
  164 + DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
  165 + Dashboard dashboard = checkDashboardId(dashboardId);
  166 +
  167 + Dashboard savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(dashboardId, customerId));
  168 +
  169 + logEntityAction(dashboardId, dashboard,
  170 + customerId,
  171 + ActionType.UNASSIGNED_FROM_CUSTOMER, null, strDashboardId, customer.getId().toString(), customer.getName());
  172 +
  173 + return savedDashboard;
  174 + } catch (Exception e) {
  175 +
  176 + logEntityAction(emptyId(EntityType.DASHBOARD), null,
  177 + null,
  178 + ActionType.UNASSIGNED_FROM_CUSTOMER, e, strDashboardId);
  179 +
  180 + throw handleException(e);
  181 + }
  182 + }
  183 +
  184 + @PreAuthorize("hasAuthority('TENANT_ADMIN')")
  185 + @RequestMapping(value = "/dashboard/{dashboardId}/customers", method = RequestMethod.POST)
  186 + @ResponseBody
  187 + public Dashboard updateDashboardCustomers(@PathVariable(DASHBOARD_ID) String strDashboardId,
  188 + @RequestBody String[] strCustomerIds) throws ThingsboardException {
  189 + checkParameter(DASHBOARD_ID, strDashboardId);
  190 + try {
  191 + DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
  192 + Dashboard dashboard = checkDashboardId(dashboardId);
  193 +
  194 + Set<CustomerId> customerIds = new HashSet<>();
  195 + if (strCustomerIds != null) {
  196 + for (String strCustomerId : strCustomerIds) {
  197 + customerIds.add(new CustomerId(toUUID(strCustomerId)));
  198 + }
  199 + }
  200 +
  201 + Set<CustomerId> addedCustomerIds = new HashSet<>();
  202 + Set<CustomerId> removedCustomerIds = new HashSet<>();
  203 + for (CustomerId customerId : customerIds) {
  204 + if (!dashboard.isAssignedToCustomer(customerId)) {
  205 + addedCustomerIds.add(customerId);
  206 + }
  207 + }
  208 +
  209 + Set<ShortCustomerInfo> assignedCustomers = dashboard.getAssignedCustomers();
  210 + if (assignedCustomers != null) {
  211 + for (ShortCustomerInfo customerInfo : assignedCustomers) {
  212 + if (!customerIds.contains(customerInfo.getCustomerId())) {
  213 + removedCustomerIds.add(customerInfo.getCustomerId());
  214 + }
  215 + }
  216 + }
  217 +
  218 + if (addedCustomerIds.isEmpty() && removedCustomerIds.isEmpty()) {
  219 + return dashboard;
  220 + } else {
  221 + Dashboard savedDashboard = null;
  222 + for (CustomerId customerId : addedCustomerIds) {
  223 + savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(dashboardId, customerId));
  224 + ShortCustomerInfo customerInfo = savedDashboard.getAssignedCustomerInfo(customerId);
  225 + logEntityAction(dashboardId, savedDashboard,
  226 + customerId,
  227 + ActionType.ASSIGNED_TO_CUSTOMER, null, strDashboardId, customerId.toString(), customerInfo.getTitle());
  228 + }
  229 + for (CustomerId customerId : removedCustomerIds) {
  230 + ShortCustomerInfo customerInfo = dashboard.getAssignedCustomerInfo(customerId);
  231 + savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(dashboardId, customerId));
  232 + logEntityAction(dashboardId, dashboard,
  233 + customerId,
  234 + ActionType.UNASSIGNED_FROM_CUSTOMER, null, strDashboardId, customerId.toString(), customerInfo.getTitle());
  235 +
  236 + }
  237 + return savedDashboard;
  238 + }
  239 + } catch (Exception e) {
  240 +
  241 + logEntityAction(emptyId(EntityType.DASHBOARD), null,
  242 + null,
  243 + ActionType.ASSIGNED_TO_CUSTOMER, e, strDashboardId);
  244 +
  245 + throw handleException(e);
  246 + }
  247 + }
  248 +
  249 + @PreAuthorize("hasAuthority('TENANT_ADMIN')")
  250 + @RequestMapping(value = "/dashboard/{dashboardId}/customers/add", method = RequestMethod.POST)
  251 + @ResponseBody
  252 + public Dashboard addDashboardCustomers(@PathVariable(DASHBOARD_ID) String strDashboardId,
  253 + @RequestBody String[] strCustomerIds) throws ThingsboardException {
  254 + checkParameter(DASHBOARD_ID, strDashboardId);
  255 + try {
  256 + DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
  257 + Dashboard dashboard = checkDashboardId(dashboardId);
  258 +
  259 + Set<CustomerId> customerIds = new HashSet<>();
  260 + if (strCustomerIds != null) {
  261 + for (String strCustomerId : strCustomerIds) {
  262 + CustomerId customerId = new CustomerId(toUUID(strCustomerId));
  263 + if (!dashboard.isAssignedToCustomer(customerId)) {
  264 + customerIds.add(customerId);
  265 + }
  266 + }
  267 + }
  268 +
  269 + if (customerIds.isEmpty()) {
  270 + return dashboard;
  271 + } else {
  272 + Dashboard savedDashboard = null;
  273 + for (CustomerId customerId : customerIds) {
  274 + savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(dashboardId, customerId));
  275 + ShortCustomerInfo customerInfo = savedDashboard.getAssignedCustomerInfo(customerId);
  276 + logEntityAction(dashboardId, savedDashboard,
  277 + customerId,
  278 + ActionType.ASSIGNED_TO_CUSTOMER, null, strDashboardId, customerId.toString(), customerInfo.getTitle());
  279 + }
  280 + return savedDashboard;
  281 + }
  282 + } catch (Exception e) {
  283 +
  284 + logEntityAction(emptyId(EntityType.DASHBOARD), null,
  285 + null,
  286 + ActionType.ASSIGNED_TO_CUSTOMER, e, strDashboardId);
  287 +
  288 + throw handleException(e);
  289 + }
  290 + }
  291 +
  292 + @PreAuthorize("hasAuthority('TENANT_ADMIN')")
  293 + @RequestMapping(value = "/dashboard/{dashboardId}/customers/remove", method = RequestMethod.POST)
  294 + @ResponseBody
  295 + public Dashboard removeDashboardCustomers(@PathVariable(DASHBOARD_ID) String strDashboardId,
  296 + @RequestBody String[] strCustomerIds) throws ThingsboardException {
122 checkParameter(DASHBOARD_ID, strDashboardId); 297 checkParameter(DASHBOARD_ID, strDashboardId);
123 try { 298 try {
124 DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); 299 DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
125 Dashboard dashboard = checkDashboardId(dashboardId); 300 Dashboard dashboard = checkDashboardId(dashboardId);
126 - if (dashboard.getCustomerId() == null || dashboard.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) {  
127 - throw new IncorrectParameterException("Dashboard isn't assigned to any customer!"); 301 +
  302 + Set<CustomerId> customerIds = new HashSet<>();
  303 + if (strCustomerIds != null) {
  304 + for (String strCustomerId : strCustomerIds) {
  305 + CustomerId customerId = new CustomerId(toUUID(strCustomerId));
  306 + if (dashboard.isAssignedToCustomer(customerId)) {
  307 + customerIds.add(customerId);
  308 + }
  309 + }
  310 + }
  311 +
  312 + if (customerIds.isEmpty()) {
  313 + return dashboard;
  314 + } else {
  315 + Dashboard savedDashboard = null;
  316 + for (CustomerId customerId : customerIds) {
  317 + ShortCustomerInfo customerInfo = dashboard.getAssignedCustomerInfo(customerId);
  318 + savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(dashboardId, customerId));
  319 + logEntityAction(dashboardId, dashboard,
  320 + customerId,
  321 + ActionType.UNASSIGNED_FROM_CUSTOMER, null, strDashboardId, customerId.toString(), customerInfo.getTitle());
  322 +
  323 + }
  324 + return savedDashboard;
128 } 325 }
129 - return checkNotNull(dashboardService.unassignDashboardFromCustomer(dashboardId));  
130 } catch (Exception e) { 326 } catch (Exception e) {
  327 +
  328 + logEntityAction(emptyId(EntityType.DASHBOARD), null,
  329 + null,
  330 + ActionType.UNASSIGNED_FROM_CUSTOMER, e, strDashboardId);
  331 +
131 throw handleException(e); 332 throw handleException(e);
132 } 333 }
133 } 334 }
@@ -141,8 +342,46 @@ public class DashboardController extends BaseController { @@ -141,8 +342,46 @@ public class DashboardController extends BaseController {
141 DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); 342 DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
142 Dashboard dashboard = checkDashboardId(dashboardId); 343 Dashboard dashboard = checkDashboardId(dashboardId);
143 Customer publicCustomer = customerService.findOrCreatePublicCustomer(dashboard.getTenantId()); 344 Customer publicCustomer = customerService.findOrCreatePublicCustomer(dashboard.getTenantId());
144 - return checkNotNull(dashboardService.assignDashboardToCustomer(dashboardId, publicCustomer.getId())); 345 + Dashboard savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(dashboardId, publicCustomer.getId()));
  346 +
  347 + logEntityAction(dashboardId, savedDashboard,
  348 + publicCustomer.getId(),
  349 + ActionType.ASSIGNED_TO_CUSTOMER, null, strDashboardId, publicCustomer.getId().toString(), publicCustomer.getName());
  350 +
  351 + return savedDashboard;
  352 + } catch (Exception e) {
  353 +
  354 + logEntityAction(emptyId(EntityType.DASHBOARD), null,
  355 + null,
  356 + ActionType.ASSIGNED_TO_CUSTOMER, e, strDashboardId);
  357 +
  358 + throw handleException(e);
  359 + }
  360 + }
  361 +
  362 + @PreAuthorize("hasAuthority('TENANT_ADMIN')")
  363 + @RequestMapping(value = "/customer/public/dashboard/{dashboardId}", method = RequestMethod.DELETE)
  364 + @ResponseBody
  365 + public Dashboard unassignDashboardFromPublicCustomer(@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
  366 + checkParameter(DASHBOARD_ID, strDashboardId);
  367 + try {
  368 + DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
  369 + Dashboard dashboard = checkDashboardId(dashboardId);
  370 + Customer publicCustomer = customerService.findOrCreatePublicCustomer(dashboard.getTenantId());
  371 +
  372 + Dashboard savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(dashboardId, publicCustomer.getId()));
  373 +
  374 + logEntityAction(dashboardId, dashboard,
  375 + publicCustomer.getId(),
  376 + ActionType.UNASSIGNED_FROM_CUSTOMER, null, strDashboardId, publicCustomer.getId().toString(), publicCustomer.getName());
  377 +
  378 + return savedDashboard;
145 } catch (Exception e) { 379 } catch (Exception e) {
  380 +
  381 + logEntityAction(emptyId(EntityType.DASHBOARD), null,
  382 + null,
  383 + ActionType.UNASSIGNED_FROM_CUSTOMER, e, strDashboardId);
  384 +
146 throw handleException(e); 385 throw handleException(e);
147 } 386 }
148 } 387 }
@@ -186,19 +425,20 @@ public class DashboardController extends BaseController { @@ -186,19 +425,20 @@ public class DashboardController extends BaseController {
186 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 425 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
187 @RequestMapping(value = "/customer/{customerId}/dashboards", params = { "limit" }, method = RequestMethod.GET) 426 @RequestMapping(value = "/customer/{customerId}/dashboards", params = { "limit" }, method = RequestMethod.GET)
188 @ResponseBody 427 @ResponseBody
189 - public TextPageData<DashboardInfo> getCustomerDashboards( 428 + public TimePageData<DashboardInfo> getCustomerDashboards(
190 @PathVariable("customerId") String strCustomerId, 429 @PathVariable("customerId") String strCustomerId,
191 @RequestParam int limit, 430 @RequestParam int limit,
192 - @RequestParam(required = false) String textSearch,  
193 - @RequestParam(required = false) String idOffset,  
194 - @RequestParam(required = false) String textOffset) throws ThingsboardException { 431 + @RequestParam(required = false) Long startTime,
  432 + @RequestParam(required = false) Long endTime,
  433 + @RequestParam(required = false, defaultValue = "false") boolean ascOrder,
  434 + @RequestParam(required = false) String offset) throws ThingsboardException {
195 checkParameter("customerId", strCustomerId); 435 checkParameter("customerId", strCustomerId);
196 try { 436 try {
197 TenantId tenantId = getCurrentUser().getTenantId(); 437 TenantId tenantId = getCurrentUser().getTenantId();
198 CustomerId customerId = new CustomerId(toUUID(strCustomerId)); 438 CustomerId customerId = new CustomerId(toUUID(strCustomerId));
199 checkCustomerId(customerId); 439 checkCustomerId(customerId);
200 - TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset);  
201 - return checkNotNull(dashboardService.findDashboardsByTenantIdAndCustomerId(tenantId, customerId, pageLink)); 440 + TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset);
  441 + return checkNotNull(dashboardService.findDashboardsByTenantIdAndCustomerId(tenantId, customerId, pageLink).get());
202 } catch (Exception e) { 442 } catch (Exception e) {
203 throw handleException(e); 443 throw handleException(e);
204 } 444 }
1 /** 1 /**
2 - * Copyright © 2016-2017 The Thingsboard Authors 2 + * Copyright © 2016-2018 The Thingsboard Authors
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
@@ -22,6 +22,10 @@ import org.springframework.web.bind.annotation.*; @@ -22,6 +22,10 @@ import org.springframework.web.bind.annotation.*;
22 import org.thingsboard.server.common.data.Customer; 22 import org.thingsboard.server.common.data.Customer;
23 import org.thingsboard.server.common.data.Device; 23 import org.thingsboard.server.common.data.Device;
24 import org.thingsboard.server.common.data.EntitySubtype; 24 import org.thingsboard.server.common.data.EntitySubtype;
  25 +import org.thingsboard.server.common.data.EntityType;
  26 +import org.thingsboard.server.common.data.audit.ActionStatus;
  27 +import org.thingsboard.server.common.data.audit.ActionType;
  28 +import org.thingsboard.server.common.data.device.DeviceSearchQuery;
25 import org.thingsboard.server.common.data.id.CustomerId; 29 import org.thingsboard.server.common.data.id.CustomerId;
26 import org.thingsboard.server.common.data.id.DeviceId; 30 import org.thingsboard.server.common.data.id.DeviceId;
27 import org.thingsboard.server.common.data.id.TenantId; 31 import org.thingsboard.server.common.data.id.TenantId;
@@ -29,7 +33,6 @@ import org.thingsboard.server.common.data.page.TextPageData; @@ -29,7 +33,6 @@ import org.thingsboard.server.common.data.page.TextPageData;
29 import org.thingsboard.server.common.data.page.TextPageLink; 33 import org.thingsboard.server.common.data.page.TextPageLink;
30 import org.thingsboard.server.common.data.security.Authority; 34 import org.thingsboard.server.common.data.security.Authority;
31 import org.thingsboard.server.common.data.security.DeviceCredentials; 35 import org.thingsboard.server.common.data.security.DeviceCredentials;
32 -import org.thingsboard.server.common.data.device.DeviceSearchQuery;  
33 import org.thingsboard.server.dao.exception.IncorrectParameterException; 36 import org.thingsboard.server.dao.exception.IncorrectParameterException;
34 import org.thingsboard.server.dao.model.ModelConstants; 37 import org.thingsboard.server.dao.model.ModelConstants;
35 import org.thingsboard.server.exception.ThingsboardErrorCode; 38 import org.thingsboard.server.exception.ThingsboardErrorCode;
@@ -75,14 +78,22 @@ public class DeviceController extends BaseController { @@ -75,14 +78,22 @@ public class DeviceController extends BaseController {
75 } 78 }
76 } 79 }
77 Device savedDevice = checkNotNull(deviceService.saveDevice(device)); 80 Device savedDevice = checkNotNull(deviceService.saveDevice(device));
  81 +
78 actorService 82 actorService
79 .onDeviceNameOrTypeUpdate( 83 .onDeviceNameOrTypeUpdate(
80 savedDevice.getTenantId(), 84 savedDevice.getTenantId(),
81 savedDevice.getId(), 85 savedDevice.getId(),
82 savedDevice.getName(), 86 savedDevice.getName(),
83 savedDevice.getType()); 87 savedDevice.getType());
  88 +
  89 + logEntityAction(savedDevice.getId(), savedDevice,
  90 + savedDevice.getCustomerId(),
  91 + device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
  92 +
84 return savedDevice; 93 return savedDevice;
85 } catch (Exception e) { 94 } catch (Exception e) {
  95 + logEntityAction(emptyId(EntityType.DEVICE), device,
  96 + null, device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e);
86 throw handleException(e); 97 throw handleException(e);
87 } 98 }
88 } 99 }
@@ -94,9 +105,18 @@ public class DeviceController extends BaseController { @@ -94,9 +105,18 @@ public class DeviceController extends BaseController {
94 checkParameter(DEVICE_ID, strDeviceId); 105 checkParameter(DEVICE_ID, strDeviceId);
95 try { 106 try {
96 DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); 107 DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
97 - checkDeviceId(deviceId); 108 + Device device = checkDeviceId(deviceId);
98 deviceService.deleteDevice(deviceId); 109 deviceService.deleteDevice(deviceId);
  110 +
  111 + logEntityAction(deviceId, device,
  112 + device.getCustomerId(),
  113 + ActionType.DELETED, null, strDeviceId);
  114 +
99 } catch (Exception e) { 115 } catch (Exception e) {
  116 + logEntityAction(emptyId(EntityType.DEVICE),
  117 + null,
  118 + null,
  119 + ActionType.DELETED, e, strDeviceId);
100 throw handleException(e); 120 throw handleException(e);
101 } 121 }
102 } 122 }
@@ -110,13 +130,22 @@ public class DeviceController extends BaseController { @@ -110,13 +130,22 @@ public class DeviceController extends BaseController {
110 checkParameter(DEVICE_ID, strDeviceId); 130 checkParameter(DEVICE_ID, strDeviceId);
111 try { 131 try {
112 CustomerId customerId = new CustomerId(toUUID(strCustomerId)); 132 CustomerId customerId = new CustomerId(toUUID(strCustomerId));
113 - checkCustomerId(customerId); 133 + Customer customer = checkCustomerId(customerId);
114 134
115 DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); 135 DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
116 checkDeviceId(deviceId); 136 checkDeviceId(deviceId);
117 137
118 - return checkNotNull(deviceService.assignDeviceToCustomer(deviceId, customerId)); 138 + Device savedDevice = checkNotNull(deviceService.assignDeviceToCustomer(deviceId, customerId));
  139 +
  140 + logEntityAction(deviceId, savedDevice,
  141 + savedDevice.getCustomerId(),
  142 + ActionType.ASSIGNED_TO_CUSTOMER, null, strDeviceId, strCustomerId, customer.getName());
  143 +
  144 + return savedDevice;
119 } catch (Exception e) { 145 } catch (Exception e) {
  146 + logEntityAction(emptyId(EntityType.DEVICE), null,
  147 + null,
  148 + ActionType.ASSIGNED_TO_CUSTOMER, e, strDeviceId, strCustomerId);
120 throw handleException(e); 149 throw handleException(e);
121 } 150 }
122 } 151 }
@@ -132,8 +161,19 @@ public class DeviceController extends BaseController { @@ -132,8 +161,19 @@ public class DeviceController extends BaseController {
132 if (device.getCustomerId() == null || device.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { 161 if (device.getCustomerId() == null || device.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) {
133 throw new IncorrectParameterException("Device isn't assigned to any customer!"); 162 throw new IncorrectParameterException("Device isn't assigned to any customer!");
134 } 163 }
135 - return checkNotNull(deviceService.unassignDeviceFromCustomer(deviceId)); 164 + Customer customer = checkCustomerId(device.getCustomerId());
  165 +
  166 + Device savedDevice = checkNotNull(deviceService.unassignDeviceFromCustomer(deviceId));
  167 +
  168 + logEntityAction(deviceId, device,
  169 + device.getCustomerId(),
  170 + ActionType.UNASSIGNED_FROM_CUSTOMER, null, strDeviceId, customer.getId().toString(), customer.getName());
  171 +
  172 + return savedDevice;
136 } catch (Exception e) { 173 } catch (Exception e) {
  174 + logEntityAction(emptyId(EntityType.DEVICE), null,
  175 + null,
  176 + ActionType.UNASSIGNED_FROM_CUSTOMER, e, strDeviceId);
137 throw handleException(e); 177 throw handleException(e);
138 } 178 }
139 } 179 }
@@ -147,8 +187,17 @@ public class DeviceController extends BaseController { @@ -147,8 +187,17 @@ public class DeviceController extends BaseController {
147 DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); 187 DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
148 Device device = checkDeviceId(deviceId); 188 Device device = checkDeviceId(deviceId);
149 Customer publicCustomer = customerService.findOrCreatePublicCustomer(device.getTenantId()); 189 Customer publicCustomer = customerService.findOrCreatePublicCustomer(device.getTenantId());
150 - return checkNotNull(deviceService.assignDeviceToCustomer(deviceId, publicCustomer.getId())); 190 + Device savedDevice = checkNotNull(deviceService.assignDeviceToCustomer(deviceId, publicCustomer.getId()));
  191 +
  192 + logEntityAction(deviceId, savedDevice,
  193 + savedDevice.getCustomerId(),
  194 + ActionType.ASSIGNED_TO_CUSTOMER, null, strDeviceId, publicCustomer.getId().toString(), publicCustomer.getName());
  195 +
  196 + return savedDevice;
151 } catch (Exception e) { 197 } catch (Exception e) {
  198 + logEntityAction(emptyId(EntityType.DEVICE), null,
  199 + null,
  200 + ActionType.ASSIGNED_TO_CUSTOMER, e, strDeviceId);
152 throw handleException(e); 201 throw handleException(e);
153 } 202 }
154 } 203 }
@@ -160,9 +209,16 @@ public class DeviceController extends BaseController { @@ -160,9 +209,16 @@ public class DeviceController extends BaseController {
160 checkParameter(DEVICE_ID, strDeviceId); 209 checkParameter(DEVICE_ID, strDeviceId);
161 try { 210 try {
162 DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); 211 DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
163 - checkDeviceId(deviceId);  
164 - return checkNotNull(deviceCredentialsService.findDeviceCredentialsByDeviceId(deviceId)); 212 + Device device = checkDeviceId(deviceId);
  213 + DeviceCredentials deviceCredentials = checkNotNull(deviceCredentialsService.findDeviceCredentialsByDeviceId(deviceId));
  214 + logEntityAction(deviceId, device,
  215 + device.getCustomerId(),
  216 + ActionType.CREDENTIALS_READ, null, strDeviceId);
  217 + return deviceCredentials;
165 } catch (Exception e) { 218 } catch (Exception e) {
  219 + logEntityAction(emptyId(EntityType.DEVICE), null,
  220 + null,
  221 + ActionType.CREDENTIALS_READ, e, strDeviceId);
166 throw handleException(e); 222 throw handleException(e);
167 } 223 }
168 } 224 }
@@ -173,11 +229,17 @@ public class DeviceController extends BaseController { @@ -173,11 +229,17 @@ public class DeviceController extends BaseController {
173 public DeviceCredentials saveDeviceCredentials(@RequestBody DeviceCredentials deviceCredentials) throws ThingsboardException { 229 public DeviceCredentials saveDeviceCredentials(@RequestBody DeviceCredentials deviceCredentials) throws ThingsboardException {
174 checkNotNull(deviceCredentials); 230 checkNotNull(deviceCredentials);
175 try { 231 try {
176 - checkDeviceId(deviceCredentials.getDeviceId()); 232 + Device device = checkDeviceId(deviceCredentials.getDeviceId());
177 DeviceCredentials result = checkNotNull(deviceCredentialsService.updateDeviceCredentials(deviceCredentials)); 233 DeviceCredentials result = checkNotNull(deviceCredentialsService.updateDeviceCredentials(deviceCredentials));
178 actorService.onCredentialsUpdate(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId()); 234 actorService.onCredentialsUpdate(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId());
  235 + logEntityAction(device.getId(), device,
  236 + device.getCustomerId(),
  237 + ActionType.CREDENTIALS_UPDATED, null, deviceCredentials);
179 return result; 238 return result;
180 } catch (Exception e) { 239 } catch (Exception e) {
  240 + logEntityAction(emptyId(EntityType.DEVICE), null,
  241 + null,
  242 + ActionType.CREDENTIALS_UPDATED, e, deviceCredentials);
181 throw handleException(e); 243 throw handleException(e);
182 } 244 }
183 } 245 }
@@ -306,5 +368,4 @@ public class DeviceController extends BaseController { @@ -306,5 +368,4 @@ public class DeviceController extends BaseController {
306 throw handleException(e); 368 throw handleException(e);
307 } 369 }
308 } 370 }
309 -  
310 } 371 }