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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -13,7 +13,6 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -
17 16 import org.apache.tools.ant.filters.ReplaceTokens
18 17
19 18 buildscript {
... ...
1 1 <!--
2 2
3   - Copyright © 2016-2017 The Thingsboard Authors
  3 + Copyright © 2016-2018 The Thingsboard Authors
4 4
5 5 Licensed under the Apache License, Version 2.0 (the "License");
6 6 you may not use this file except in compliance with the License.
... ... @@ -20,7 +20,7 @@
20 20 <modelVersion>4.0.0</modelVersion>
21 21 <parent>
22 22 <groupId>org.thingsboard</groupId>
23   - <version>1.4.0-SNAPSHOT</version>
  23 + <version>1.4.1-SNAPSHOT</version>
24 24 <artifactId>thingsboard</artifactId>
25 25 </parent>
26 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 5 Licensed under the Apache License, Version 2.0 (the "License");
6 6 you may not use this file except in compliance with the License.
... ...
1 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 6 Licensed under the Apache License, Version 2.0 (the "License");
7 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 4 # Licensed under the Apache License, Version 2.0 (the "License");
5 5 # you may not use this file except in compliance with the License.
... ...
... ... @@ -66,7 +66,7 @@
66 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 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 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 4 -- Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 -- Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -13,7 +13,6 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -
17 16 package org.thingsboard.server;
18 17
19 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 40 import org.thingsboard.server.dao.alarm.AlarmService;
41 41 import org.thingsboard.server.dao.asset.AssetService;
42 42 import org.thingsboard.server.dao.attributes.AttributesService;
  43 +import org.thingsboard.server.dao.audit.AuditLogService;
43 44 import org.thingsboard.server.dao.customer.CustomerService;
44 45 import org.thingsboard.server.dao.device.DeviceService;
45 46 import org.thingsboard.server.dao.event.EventService;
... ... @@ -114,6 +115,9 @@ public class ActorSystemContext {
114 115 @Getter private RelationService relationService;
115 116
116 117 @Autowired
  118 + @Getter private AuditLogService auditLogService;
  119 +
  120 + @Autowired
117 121 @Getter @Setter private PluginWebSocketMsgEndpoint wsMsgEndpoint;
118 122
119 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 26 import org.thingsboard.server.common.data.EntityType;
27 27 import org.thingsboard.server.common.data.Tenant;
28 28 import org.thingsboard.server.common.data.asset.Asset;
  29 +import org.thingsboard.server.common.data.audit.ActionType;
29 30 import org.thingsboard.server.common.data.id.*;
30 31 import org.thingsboard.server.common.data.kv.AttributeKey;
31 32 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
... ... @@ -41,9 +42,7 @@ import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotific
41 42 import org.thingsboard.server.extensions.api.plugins.PluginApiCallSecurityContext;
42 43 import org.thingsboard.server.extensions.api.plugins.PluginCallback;
43 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 46 import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg;
48 47 import org.thingsboard.server.extensions.api.plugins.rpc.RpcMsg;
49 48 import org.thingsboard.server.extensions.api.plugins.ws.PluginWebsocketSessionRef;
... ... @@ -197,6 +196,52 @@ public final class PluginProcessingContext implements PluginContext {
197 196 }
198 197
199 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 245 public void loadLatestTimeseries(final EntityId entityId, final Collection<String> keys, final PluginCallback<List<TsKvEntry>> callback) {
201 246 validate(entityId, new ValidationCallback(callback, ctx -> {
202 247 ListenableFuture<List<TsKvEntry>> rsListFuture = pluginCtx.tsService.findLatest(entityId, keys);
... ... @@ -429,12 +474,12 @@ public final class PluginProcessingContext implements PluginContext {
429 474
430 475 @Override
431 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 480 @Override
436 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 485 @Override
... ... @@ -461,6 +506,29 @@ public final class PluginProcessingContext implements PluginContext {
461 506 }
462 507
463 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 532 public void scheduleTimeoutMsg(TimeoutMsg msg) {
465 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 27 import org.thingsboard.server.common.data.id.PluginId;
28 28 import org.thingsboard.server.dao.asset.AssetService;
29 29 import org.thingsboard.server.dao.attributes.AttributesService;
  30 +import org.thingsboard.server.dao.audit.AuditLogService;
30 31 import org.thingsboard.server.dao.customer.CustomerService;
31 32 import org.thingsboard.server.dao.device.DeviceService;
32 33 import org.thingsboard.server.dao.plugin.PluginService;
... ... @@ -63,6 +64,7 @@ public final class SharedPluginProcessingContext {
63 64 final ClusterRpcService rpcService;
64 65 final ClusterRoutingService routingService;
65 66 final RelationService relationService;
  67 + final AuditLogService auditLogService;
66 68 final PluginId pluginId;
67 69 final TenantId tenantId;
68 70
... ... @@ -86,6 +88,7 @@ public final class SharedPluginProcessingContext {
86 88 this.customerService = sysContext.getCustomerService();
87 89 this.tenantService = sysContext.getTenantService();
88 90 this.relationService = sysContext.getRelationService();
  91 + this.auditLogService = sysContext.getAuditLogService();
89 92 }
90 93
91 94 public PluginId getPluginId() {
... ...
1 1 /**
2   - * Copyright © 2016-2017 The Thingsboard Authors
  2 + * Copyright © 2016-2018 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -148,7 +148,7 @@ public class BasicRpcSessionListener implements GrpcSessionListener {
148 148 DeviceId deviceId = new DeviceId(toUUID(msg.getDeviceId()));
149 149
150 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 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 40 import org.springframework.web.cors.CorsUtils;
41 41 import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
42 42 import org.springframework.web.filter.CorsFilter;
  43 +import org.thingsboard.server.dao.audit.AuditLogLevelFilter;
43 44 import org.thingsboard.server.exception.ThingsboardErrorResponseHandler;
44 45 import org.thingsboard.server.service.security.auth.rest.RestAuthenticationProvider;
45 46 import org.thingsboard.server.service.security.auth.rest.RestLoginProcessingFilter;
... ... @@ -198,4 +199,9 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt
198 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 21 import org.springframework.web.bind.annotation.*;
22 22 import org.thingsboard.server.common.data.Customer;
23 23 import org.thingsboard.server.common.data.EntitySubtype;
  24 +import org.thingsboard.server.common.data.EntityType;
24 25 import org.thingsboard.server.common.data.asset.Asset;
  26 +import org.thingsboard.server.common.data.audit.ActionType;
25 27 import org.thingsboard.server.common.data.id.AssetId;
26 28 import org.thingsboard.server.common.data.id.CustomerId;
27 29 import org.thingsboard.server.common.data.id.TenantId;
... ... @@ -73,8 +75,16 @@ public class AssetController extends BaseController {
73 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 85 } catch (Exception e) {
  86 + logEntityAction(emptyId(EntityType.ASSET), asset,
  87 + null, asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e);
78 88 throw handleException(e);
79 89 }
80 90 }
... ... @@ -86,9 +96,18 @@ public class AssetController extends BaseController {
86 96 checkParameter(ASSET_ID, strAssetId);
87 97 try {
88 98 AssetId assetId = new AssetId(toUUID(strAssetId));
89   - checkAssetId(assetId);
  99 + Asset asset = checkAssetId(assetId);
90 100 assetService.deleteAsset(assetId);
  101 +
  102 + logEntityAction(assetId, asset,
  103 + asset.getCustomerId(),
  104 + ActionType.DELETED, null, strAssetId);
  105 +
91 106 } catch (Exception e) {
  107 + logEntityAction(emptyId(EntityType.ASSET),
  108 + null,
  109 + null,
  110 + ActionType.DELETED, e, strAssetId);
92 111 throw handleException(e);
93 112 }
94 113 }
... ... @@ -102,13 +121,24 @@ public class AssetController extends BaseController {
102 121 checkParameter(ASSET_ID, strAssetId);
103 122 try {
104 123 CustomerId customerId = new CustomerId(toUUID(strCustomerId));
105   - checkCustomerId(customerId);
  124 + Customer customer = checkCustomerId(customerId);
106 125
107 126 AssetId assetId = new AssetId(toUUID(strAssetId));
108 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 136 } catch (Exception e) {
  137 +
  138 + logEntityAction(emptyId(EntityType.ASSET), null,
  139 + null,
  140 + ActionType.ASSIGNED_TO_CUSTOMER, e, strAssetId, strCustomerId);
  141 +
112 142 throw handleException(e);
113 143 }
114 144 }
... ... @@ -124,8 +154,22 @@ public class AssetController extends BaseController {
124 154 if (asset.getCustomerId() == null || asset.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) {
125 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 167 } catch (Exception e) {
  168 +
  169 + logEntityAction(emptyId(EntityType.ASSET), null,
  170 + null,
  171 + ActionType.UNASSIGNED_FROM_CUSTOMER, e, strAssetId);
  172 +
129 173 throw handleException(e);
130 174 }
131 175 }
... ... @@ -139,8 +183,19 @@ public class AssetController extends BaseController {
139 183 AssetId assetId = new AssetId(toUUID(strAssetId));
140 184 Asset asset = checkAssetId(assetId);
141 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 193 } catch (Exception e) {
  194 +
  195 + logEntityAction(emptyId(EntityType.ASSET), null,
  196 + null,
  197 + ActionType.ASSIGNED_TO_CUSTOMER, e, strAssetId);
  198 +
144 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -15,9 +15,12 @@
15 15 */
16 16 package org.thingsboard.server.controller;
17 17
  18 +import com.fasterxml.jackson.databind.JsonNode;
  19 +import com.fasterxml.jackson.databind.ObjectMapper;
18 20 import lombok.extern.slf4j.Slf4j;
19 21 import org.apache.commons.lang3.StringUtils;
20 22 import org.springframework.beans.factory.annotation.Autowired;
  23 +import org.springframework.beans.factory.annotation.Value;
21 24 import org.springframework.security.core.Authentication;
22 25 import org.springframework.security.core.context.SecurityContextHolder;
23 26 import org.springframework.web.bind.annotation.ExceptionHandler;
... ... @@ -27,6 +30,8 @@ import org.thingsboard.server.common.data.alarm.Alarm;
27 30 import org.thingsboard.server.common.data.alarm.AlarmId;
28 31 import org.thingsboard.server.common.data.alarm.AlarmInfo;
29 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 35 import org.thingsboard.server.common.data.id.*;
31 36 import org.thingsboard.server.common.data.page.TextPageLink;
32 37 import org.thingsboard.server.common.data.page.TimePageLink;
... ... @@ -39,6 +44,7 @@ import org.thingsboard.server.common.data.widget.WidgetType;
39 44 import org.thingsboard.server.common.data.widget.WidgetsBundle;
40 45 import org.thingsboard.server.dao.alarm.AlarmService;
41 46 import org.thingsboard.server.dao.asset.AssetService;
  47 +import org.thingsboard.server.dao.audit.AuditLogService;
42 48 import org.thingsboard.server.dao.customer.CustomerService;
43 49 import org.thingsboard.server.dao.dashboard.DashboardService;
44 50 import org.thingsboard.server.dao.device.DeviceCredentialsService;
... ... @@ -72,6 +78,7 @@ public abstract class BaseController {
72 78
73 79 public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
74 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 82 @Autowired
76 83 private ThingsboardErrorResponseHandler errorResponseHandler;
77 84
... ... @@ -117,6 +124,8 @@ public abstract class BaseController {
117 124 @Autowired
118 125 protected RelationService relationService;
119 126
  127 + @Autowired
  128 + protected AuditLogService auditLogService;
120 129
121 130 @ExceptionHandler(ThingsboardException.class)
122 131 public void handleThingsboardException(ThingsboardException ex, HttpServletResponse response) {
... ... @@ -129,7 +138,7 @@ public abstract class BaseController {
129 138
130 139 private ThingsboardException handleException(Exception exception, boolean logException) {
131 140 if (logException) {
132   - log.error("Error [{}]", exception.getMessage());
  141 + log.error("Error [{}]", exception.getMessage(), exception);
133 142 }
134 143
135 144 String cause = "";
... ... @@ -414,7 +423,7 @@ public abstract class BaseController {
414 423 try {
415 424 validateId(dashboardId, "Incorrect dashboardId " + dashboardId);
416 425 Dashboard dashboard = dashboardService.findDashboardById(dashboardId);
417   - checkDashboard(dashboard, true);
  426 + checkDashboard(dashboard);
418 427 return dashboard;
419 428 } catch (Exception e) {
420 429 throw handleException(e, false);
... ... @@ -425,28 +434,23 @@ public abstract class BaseController {
425 434 try {
426 435 validateId(dashboardId, "Incorrect dashboardId " + dashboardId);
427 436 DashboardInfo dashboardInfo = dashboardService.findDashboardInfoById(dashboardId);
428   - SecurityUser authUser = getCurrentUser();
429   - checkDashboard(dashboardInfo, authUser.getAuthority() != Authority.SYS_ADMIN);
  437 + checkDashboard(dashboardInfo);
430 438 return dashboardInfo;
431 439 } catch (Exception e) {
432 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 445 checkNotNull(dashboard);
438 446 checkTenantId(dashboard.getTenantId());
439 447 SecurityUser authUser = getCurrentUser();
440 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 450 throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION,
443 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 456 ComponentDescriptor checkComponentDescriptorByClazz(String clazz) throws ThingsboardException {
... ... @@ -541,4 +545,20 @@ public abstract class BaseController {
541 545 serverPort);
542 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -22,6 +22,8 @@ import org.springframework.http.HttpStatus;
22 22 import org.springframework.security.access.prepost.PreAuthorize;
23 23 import org.springframework.web.bind.annotation.*;
24 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 27 import org.thingsboard.server.common.data.id.CustomerId;
26 28 import org.thingsboard.server.common.data.id.TenantId;
27 29 import org.thingsboard.server.common.data.page.TextPageData;
... ... @@ -86,8 +88,18 @@ public class CustomerController extends BaseController {
86 88 public Customer saveCustomer(@RequestBody Customer customer) throws ThingsboardException {
87 89 try {
88 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 98 } catch (Exception e) {
  99 +
  100 + logEntityAction(emptyId(EntityType.CUSTOMER), customer,
  101 + null, customer.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e);
  102 +
91 103 throw handleException(e);
92 104 }
93 105 }
... ... @@ -99,9 +111,20 @@ public class CustomerController extends BaseController {
99 111 checkParameter(CUSTOMER_ID, strCustomerId);
100 112 try {
101 113 CustomerId customerId = new CustomerId(toUUID(strCustomerId));
102   - checkCustomerId(customerId);
  114 + Customer customer = checkCustomerId(customerId);
103 115 customerService.deleteCustomer(customerId);
  116 +
  117 + logEntityAction(customerId, customer,
  118 + customer.getId(),
  119 + ActionType.DELETED, null, strCustomerId);
  120 +
104 121 } catch (Exception e) {
  122 +
  123 + logEntityAction(emptyId(EntityType.CUSTOMER),
  124 + null,
  125 + null,
  126 + ActionType.DELETED, e, strCustomerId);
  127 +
105 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -18,18 +18,22 @@ package org.thingsboard.server.controller;
18 18 import org.springframework.http.HttpStatus;
19 19 import org.springframework.security.access.prepost.PreAuthorize;
20 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 23 import org.thingsboard.server.common.data.id.CustomerId;
25 24 import org.thingsboard.server.common.data.id.DashboardId;
26 25 import org.thingsboard.server.common.data.id.TenantId;
27 26 import org.thingsboard.server.common.data.page.TextPageData;
28 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 30 import org.thingsboard.server.dao.exception.IncorrectParameterException;
30 31 import org.thingsboard.server.dao.model.ModelConstants;
31 32 import org.thingsboard.server.exception.ThingsboardException;
32 33
  34 +import java.util.HashSet;
  35 +import java.util.Set;
  36 +
33 37 @RestController
34 38 @RequestMapping("/api")
35 39 public class DashboardController extends BaseController {
... ... @@ -75,8 +79,17 @@ public class DashboardController extends BaseController {
75 79 public Dashboard saveDashboard(@RequestBody Dashboard dashboard) throws ThingsboardException {
76 80 try {
77 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 89 } catch (Exception e) {
  90 + logEntityAction(emptyId(EntityType.DASHBOARD), dashboard,
  91 + null, dashboard.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e);
  92 +
80 93 throw handleException(e);
81 94 }
82 95 }
... ... @@ -88,9 +101,20 @@ public class DashboardController extends BaseController {
88 101 checkParameter(DASHBOARD_ID, strDashboardId);
89 102 try {
90 103 DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
91   - checkDashboardId(dashboardId);
  104 + Dashboard dashboard = checkDashboardId(dashboardId);
92 105 dashboardService.deleteDashboard(dashboardId);
  106 +
  107 + logEntityAction(dashboardId, dashboard,
  108 + null,
  109 + ActionType.DELETED, null, strDashboardId);
  110 +
93 111 } catch (Exception e) {
  112 +
  113 + logEntityAction(emptyId(EntityType.DASHBOARD),
  114 + null,
  115 + null,
  116 + ActionType.DELETED, e, strDashboardId);
  117 +
94 118 throw handleException(e);
95 119 }
96 120 }
... ... @@ -104,30 +128,207 @@ public class DashboardController extends BaseController {
104 128 checkParameter(DASHBOARD_ID, strDashboardId);
105 129 try {
106 130 CustomerId customerId = new CustomerId(toUUID(strCustomerId));
107   - checkCustomerId(customerId);
  131 + Customer customer = checkCustomerId(customerId);
108 132
109 133 DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
110 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 144 } catch (Exception e) {
  145 +
  146 + logEntityAction(emptyId(EntityType.DASHBOARD), null,
  147 + null,
  148 + ActionType.ASSIGNED_TO_CUSTOMER, e, strDashboardId, strCustomerId);
  149 +
114 150 throw handleException(e);
115 151 }
116 152 }
117 153
118 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 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 297 checkParameter(DASHBOARD_ID, strDashboardId);
123 298 try {
124 299 DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
125 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 326 } catch (Exception e) {
  327 +
  328 + logEntityAction(emptyId(EntityType.DASHBOARD), null,
  329 + null,
  330 + ActionType.UNASSIGNED_FROM_CUSTOMER, e, strDashboardId);
  331 +
131 332 throw handleException(e);
132 333 }
133 334 }
... ... @@ -141,8 +342,46 @@ public class DashboardController extends BaseController {
141 342 DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
142 343 Dashboard dashboard = checkDashboardId(dashboardId);
143 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 379 } catch (Exception e) {
  380 +
  381 + logEntityAction(emptyId(EntityType.DASHBOARD), null,
  382 + null,
  383 + ActionType.UNASSIGNED_FROM_CUSTOMER, e, strDashboardId);
  384 +
146 385 throw handleException(e);
147 386 }
148 387 }
... ... @@ -186,19 +425,20 @@ public class DashboardController extends BaseController {
186 425 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
187 426 @RequestMapping(value = "/customer/{customerId}/dashboards", params = { "limit" }, method = RequestMethod.GET)
188 427 @ResponseBody
189   - public TextPageData<DashboardInfo> getCustomerDashboards(
  428 + public TimePageData<DashboardInfo> getCustomerDashboards(
190 429 @PathVariable("customerId") String strCustomerId,
191 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 435 checkParameter("customerId", strCustomerId);
196 436 try {
197 437 TenantId tenantId = getCurrentUser().getTenantId();
198 438 CustomerId customerId = new CustomerId(toUUID(strCustomerId));
199 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 442 } catch (Exception e) {
203 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 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 5 * you may not use this file except in compliance with the License.
... ... @@ -22,6 +22,10 @@ import org.springframework.web.bind.annotation.*;
22 22 import org.thingsboard.server.common.data.Customer;
23 23 import org.thingsboard.server.common.data.Device;
24 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 29 import org.thingsboard.server.common.data.id.CustomerId;
26 30 import org.thingsboard.server.common.data.id.DeviceId;
27 31 import org.thingsboard.server.common.data.id.TenantId;
... ... @@ -29,7 +33,6 @@ import org.thingsboard.server.common.data.page.TextPageData;
29 33 import org.thingsboard.server.common.data.page.TextPageLink;
30 34 import org.thingsboard.server.common.data.security.Authority;
31 35 import org.thingsboard.server.common.data.security.DeviceCredentials;
32   -import org.thingsboard.server.common.data.device.DeviceSearchQuery;
33 36 import org.thingsboard.server.dao.exception.IncorrectParameterException;
34 37 import org.thingsboard.server.dao.model.ModelConstants;
35 38 import org.thingsboard.server.exception.ThingsboardErrorCode;
... ... @@ -75,14 +78,22 @@ public class DeviceController extends BaseController {
75 78 }
76 79 }
77 80 Device savedDevice = checkNotNull(deviceService.saveDevice(device));
  81 +
78 82 actorService
79 83 .onDeviceNameOrTypeUpdate(
80 84 savedDevice.getTenantId(),
81 85 savedDevice.getId(),
82 86 savedDevice.getName(),
83 87 savedDevice.getType());
  88 +
  89 + logEntityAction(savedDevice.getId(), savedDevice,
  90 + savedDevice.getCustomerId(),
  91 + device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
  92 +
84 93 return savedDevice;
85 94 } catch (Exception e) {
  95 + logEntityAction(emptyId(EntityType.DEVICE), device,
  96 + null, device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e);
86 97 throw handleException(e);
87 98 }
88 99 }
... ... @@ -94,9 +105,18 @@ public class DeviceController extends BaseController {
94 105 checkParameter(DEVICE_ID, strDeviceId);
95 106 try {
96 107 DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
97   - checkDeviceId(deviceId);
  108 + Device device = checkDeviceId(deviceId);
98 109 deviceService.deleteDevice(deviceId);
  110 +
  111 + logEntityAction(deviceId, device,
  112 + device.getCustomerId(),
  113 + ActionType.DELETED, null, strDeviceId);
  114 +
99 115 } catch (Exception e) {
  116 + logEntityAction(emptyId(EntityType.DEVICE),
  117 + null,
  118 + null,
  119 + ActionType.DELETED, e, strDeviceId);
100 120 throw handleException(e);
101 121 }
102 122 }
... ... @@ -110,13 +130,22 @@ public class DeviceController extends BaseController {
110 130 checkParameter(DEVICE_ID, strDeviceId);
111 131 try {
112 132 CustomerId customerId = new CustomerId(toUUID(strCustomerId));
113   - checkCustomerId(customerId);
  133 + Customer customer = checkCustomerId(customerId);
114 134
115 135 DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
116 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 145 } catch (Exception e) {
  146 + logEntityAction(emptyId(EntityType.DEVICE), null,
  147 + null,
  148 + ActionType.ASSIGNED_TO_CUSTOMER, e, strDeviceId, strCustomerId);
120 149 throw handleException(e);
121 150 }
122 151 }
... ... @@ -132,8 +161,19 @@ public class DeviceController extends BaseController {
132 161 if (device.getCustomerId() == null || device.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) {
133 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 173 } catch (Exception e) {
  174 + logEntityAction(emptyId(EntityType.DEVICE), null,
  175 + null,
  176 + ActionType.UNASSIGNED_FROM_CUSTOMER, e, strDeviceId);
137 177 throw handleException(e);
138 178 }
139 179 }
... ... @@ -147,8 +187,17 @@ public class DeviceController extends BaseController {
147 187 DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
148 188 Device device = checkDeviceId(deviceId);
149 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 197 } catch (Exception e) {
  198 + logEntityAction(emptyId(EntityType.DEVICE), null,
  199 + null,
  200 + ActionType.ASSIGNED_TO_CUSTOMER, e, strDeviceId);
152 201 throw handleException(e);
153 202 }
154 203 }
... ... @@ -160,9 +209,16 @@ public class DeviceController extends BaseController {
160 209 checkParameter(DEVICE_ID, strDeviceId);
161 210 try {
162 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 218 } catch (Exception e) {
  219 + logEntityAction(emptyId(EntityType.DEVICE), null,
  220 + null,
  221 + ActionType.CREDENTIALS_READ, e, strDeviceId);
166 222 throw handleException(e);
167 223 }
168 224 }
... ... @@ -173,11 +229,17 @@ public class DeviceController extends BaseController {
173 229 public DeviceCredentials saveDeviceCredentials(@RequestBody DeviceCredentials deviceCredentials) throws ThingsboardException {
174 230 checkNotNull(deviceCredentials);
175 231 try {
176   - checkDeviceId(deviceCredentials.getDeviceId());
  232 + Device device = checkDeviceId(deviceCredentials.getDeviceId());
177 233 DeviceCredentials result = checkNotNull(deviceCredentialsService.updateDeviceCredentials(deviceCredentials));
178 234 actorService.onCredentialsUpdate(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId());
  235 + logEntityAction(device.getId(), device,
  236 + device.getCustomerId(),
  237 + ActionType.CREDENTIALS_UPDATED, null, deviceCredentials);
179 238 return result;
180 239 } catch (Exception e) {
  240 + logEntityAction(emptyId(EntityType.DEVICE), null,
  241 + null,
  242 + ActionType.CREDENTIALS_UPDATED, e, deviceCredentials);
181 243 throw handleException(e);
182 244 }
183 245 }
... ... @@ -306,5 +368,4 @@ public class DeviceController extends BaseController {
306 368 throw handleException(e);
307 369 }
308 370 }
309   -
310 371 }
... ...