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 | <?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. | ... | ... |
... | ... | @@ -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 | +-- | |
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. |
... | ... | @@ -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. |
... | ... | @@ -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. |
... | ... | @@ -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. |
... | ... | @@ -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 | +/** | |
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. |
... | ... | @@ -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. |
... | ... | @@ -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. |
... | ... | @@ -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. |
... | ... | @@ -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 | } | ... | ... |