@iobroker/json-config 6.17.6 → 6.17.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/LICENSE +21 -21
  2. package/build/JsonConfig.d.ts +1 -1
  3. package/build/JsonConfig.js +18 -19
  4. package/build/JsonConfig.js.map +1 -1
  5. package/build/JsonConfigComponent/ChipInput.d.ts +89 -11
  6. package/build/JsonConfigComponent/ChipInput.js +48 -137
  7. package/build/JsonConfigComponent/ChipInput.js.map +1 -1
  8. package/build/JsonConfigComponent/ConfigAccordion.d.ts +7 -14
  9. package/build/JsonConfigComponent/ConfigAccordion.js +10 -21
  10. package/build/JsonConfigComponent/ConfigAccordion.js.map +1 -1
  11. package/build/JsonConfigComponent/ConfigAlive.d.ts +5 -1
  12. package/build/JsonConfigComponent/ConfigAlive.js +0 -1
  13. package/build/JsonConfigComponent/ConfigAlive.js.map +1 -1
  14. package/build/JsonConfigComponent/ConfigAutocomplete.d.ts +5 -29
  15. package/build/JsonConfigComponent/ConfigAutocomplete.js +7 -5
  16. package/build/JsonConfigComponent/ConfigAutocomplete.js.map +1 -1
  17. package/build/JsonConfigComponent/ConfigAutocompleteSendTo.d.ts +5 -14
  18. package/build/JsonConfigComponent/ConfigAutocompleteSendTo.js +3 -3
  19. package/build/JsonConfigComponent/ConfigAutocompleteSendTo.js.map +1 -1
  20. package/build/JsonConfigComponent/ConfigCRON.d.ts +1 -1
  21. package/build/JsonConfigComponent/ConfigCertCollection.d.ts +7 -13
  22. package/build/JsonConfigComponent/ConfigCertCollection.js +8 -18
  23. package/build/JsonConfigComponent/ConfigCertCollection.js.map +1 -1
  24. package/build/JsonConfigComponent/ConfigCertificateSelect.d.ts +7 -13
  25. package/build/JsonConfigComponent/ConfigCertificateSelect.js +5 -18
  26. package/build/JsonConfigComponent/ConfigCertificateSelect.js.map +1 -1
  27. package/build/JsonConfigComponent/ConfigCertificates.d.ts +7 -13
  28. package/build/JsonConfigComponent/ConfigCertificates.js +7 -18
  29. package/build/JsonConfigComponent/ConfigCertificates.js.map +1 -1
  30. package/build/JsonConfigComponent/ConfigCheckbox.d.ts +3 -11
  31. package/build/JsonConfigComponent/ConfigCheckbox.js +2 -2
  32. package/build/JsonConfigComponent/ConfigCheckbox.js.map +1 -1
  33. package/build/JsonConfigComponent/ConfigChip.d.ts +1 -1
  34. package/build/JsonConfigComponent/ConfigColor.d.ts +13 -20
  35. package/build/JsonConfigComponent/ConfigColor.js +9 -23
  36. package/build/JsonConfigComponent/ConfigColor.js.map +1 -1
  37. package/build/JsonConfigComponent/ConfigCoordinates.d.ts +8 -13
  38. package/build/JsonConfigComponent/ConfigCoordinates.js +29 -39
  39. package/build/JsonConfigComponent/ConfigCoordinates.js.map +1 -1
  40. package/build/JsonConfigComponent/ConfigCustom.d.ts +4 -50
  41. package/build/JsonConfigComponent/ConfigCustom.js +0 -1
  42. package/build/JsonConfigComponent/ConfigCustom.js.map +1 -1
  43. package/build/JsonConfigComponent/ConfigDatePicker.d.ts +8 -3
  44. package/build/JsonConfigComponent/ConfigDatePicker.js +21 -13
  45. package/build/JsonConfigComponent/ConfigDatePicker.js.map +1 -1
  46. package/build/JsonConfigComponent/ConfigDeviceManager.d.ts +5 -1
  47. package/build/JsonConfigComponent/ConfigDeviceManager.js +1 -1
  48. package/build/JsonConfigComponent/ConfigDeviceManager.js.map +1 -1
  49. package/build/JsonConfigComponent/ConfigFile.d.ts +1 -1
  50. package/build/JsonConfigComponent/ConfigFunc.d.ts +1 -1
  51. package/build/JsonConfigComponent/ConfigGeneric.d.ts +46 -32
  52. package/build/JsonConfigComponent/ConfigGeneric.js +23 -12
  53. package/build/JsonConfigComponent/ConfigGeneric.js.map +1 -1
  54. package/build/JsonConfigComponent/ConfigIP.d.ts +1 -1
  55. package/build/JsonConfigComponent/ConfigImageSendTo.d.ts +1 -1
  56. package/build/JsonConfigComponent/ConfigInstanceSelect.d.ts +1 -1
  57. package/build/JsonConfigComponent/ConfigInterface.d.ts +1 -1
  58. package/build/JsonConfigComponent/ConfigJsonEditor.d.ts +1 -1
  59. package/build/JsonConfigComponent/ConfigLanguage.d.ts +3 -2
  60. package/build/JsonConfigComponent/ConfigLanguage.js +2 -2
  61. package/build/JsonConfigComponent/ConfigLanguage.js.map +1 -1
  62. package/build/JsonConfigComponent/ConfigNumber.d.ts +3 -13
  63. package/build/JsonConfigComponent/ConfigNumber.js +2 -2
  64. package/build/JsonConfigComponent/ConfigNumber.js.map +1 -1
  65. package/build/JsonConfigComponent/ConfigObjectId.d.ts +1 -1
  66. package/build/JsonConfigComponent/ConfigPanel.d.ts +7 -2
  67. package/build/JsonConfigComponent/ConfigPanel.js +5 -40
  68. package/build/JsonConfigComponent/ConfigPanel.js.map +1 -1
  69. package/build/JsonConfigComponent/ConfigPassword.d.ts +1 -1
  70. package/build/JsonConfigComponent/ConfigPort.d.ts +6 -1
  71. package/build/JsonConfigComponent/ConfigPort.js +2 -3
  72. package/build/JsonConfigComponent/ConfigPort.js.map +1 -1
  73. package/build/JsonConfigComponent/ConfigRoom.d.ts +1 -1
  74. package/build/JsonConfigComponent/ConfigSelect.d.ts +1 -1
  75. package/build/JsonConfigComponent/ConfigSelectSendTo.d.ts +7 -16
  76. package/build/JsonConfigComponent/ConfigSelectSendTo.js +15 -61
  77. package/build/JsonConfigComponent/ConfigSelectSendTo.js.map +1 -1
  78. package/build/JsonConfigComponent/ConfigSendto.d.ts +3 -20
  79. package/build/JsonConfigComponent/ConfigSendto.js +8 -8
  80. package/build/JsonConfigComponent/ConfigSendto.js.map +1 -1
  81. package/build/JsonConfigComponent/ConfigSetState.d.ts +1 -1
  82. package/build/JsonConfigComponent/ConfigSlider.d.ts +1 -1
  83. package/build/JsonConfigComponent/ConfigStaticDivider.d.ts +1 -1
  84. package/build/JsonConfigComponent/ConfigStaticHeader.d.ts +1 -1
  85. package/build/JsonConfigComponent/ConfigStaticImage.d.ts +1 -1
  86. package/build/JsonConfigComponent/ConfigStaticText.d.ts +1 -1
  87. package/build/JsonConfigComponent/ConfigTable.d.ts +4 -25
  88. package/build/JsonConfigComponent/ConfigTable.js +5 -4
  89. package/build/JsonConfigComponent/ConfigTable.js.map +1 -1
  90. package/build/JsonConfigComponent/ConfigTabs.d.ts +8 -33
  91. package/build/JsonConfigComponent/ConfigTabs.js +10 -43
  92. package/build/JsonConfigComponent/ConfigTabs.js.map +1 -1
  93. package/build/JsonConfigComponent/ConfigText.d.ts +7 -13
  94. package/build/JsonConfigComponent/ConfigText.js +13 -18
  95. package/build/JsonConfigComponent/ConfigText.js.map +1 -1
  96. package/build/JsonConfigComponent/ConfigTextSendTo.d.ts +7 -9
  97. package/build/JsonConfigComponent/ConfigTextSendTo.js +11 -21
  98. package/build/JsonConfigComponent/ConfigTextSendTo.js.map +1 -1
  99. package/build/JsonConfigComponent/ConfigTimePicker.d.ts +9 -3
  100. package/build/JsonConfigComponent/ConfigTimePicker.js +28 -18
  101. package/build/JsonConfigComponent/ConfigTimePicker.js.map +1 -1
  102. package/build/JsonConfigComponent/ConfigTopic.d.ts +1 -1
  103. package/build/JsonConfigComponent/ConfigUUID.d.ts +12 -13
  104. package/build/JsonConfigComponent/ConfigUUID.js +1 -6
  105. package/build/JsonConfigComponent/ConfigUUID.js.map +1 -1
  106. package/build/JsonConfigComponent/ConfigUser.d.ts +1 -1
  107. package/build/JsonConfigComponent/index.d.ts +66 -25
  108. package/build/JsonConfigComponent/index.js +48 -61
  109. package/build/JsonConfigComponent/index.js.map +1 -1
  110. package/build/index.d.ts +2 -2
  111. package/build/index.js +2 -2
  112. package/build/index.js.map +1 -1
  113. package/package.json +27 -26
  114. package/src/JsonConfig.tsx +710 -0
  115. package/src/JsonConfigComponent/ChipInput.tsx +752 -0
  116. package/src/JsonConfigComponent/ConfigAccordion.tsx +278 -0
  117. package/src/JsonConfigComponent/ConfigAlive.tsx +74 -0
  118. package/src/JsonConfigComponent/ConfigAutocomplete.tsx +108 -0
  119. package/src/JsonConfigComponent/ConfigAutocompleteSendTo.tsx +183 -0
  120. package/src/JsonConfigComponent/ConfigCRON.jsx +101 -0
  121. package/src/JsonConfigComponent/ConfigCertCollection.tsx +102 -0
  122. package/src/JsonConfigComponent/ConfigCertificateSelect.tsx +92 -0
  123. package/src/JsonConfigComponent/ConfigCertificates.tsx +202 -0
  124. package/src/JsonConfigComponent/ConfigCheckLicense.jsx +662 -0
  125. package/src/JsonConfigComponent/ConfigCheckbox.tsx +67 -0
  126. package/src/JsonConfigComponent/ConfigChip.jsx +81 -0
  127. package/src/JsonConfigComponent/ConfigColor.tsx +86 -0
  128. package/src/JsonConfigComponent/ConfigCoordinates.tsx +234 -0
  129. package/src/JsonConfigComponent/ConfigCustom.tsx +246 -0
  130. package/src/JsonConfigComponent/ConfigDatePicker.tsx +48 -0
  131. package/src/JsonConfigComponent/ConfigDeviceManager.tsx +33 -0
  132. package/src/JsonConfigComponent/ConfigFile.jsx +181 -0
  133. package/src/JsonConfigComponent/ConfigFileSelector.jsx +520 -0
  134. package/src/JsonConfigComponent/ConfigFunc.jsx +90 -0
  135. package/src/JsonConfigComponent/ConfigGeneric.tsx +1027 -0
  136. package/src/JsonConfigComponent/ConfigIP.jsx +96 -0
  137. package/src/JsonConfigComponent/ConfigImageSendTo.jsx +79 -0
  138. package/src/JsonConfigComponent/ConfigImageUpload.jsx +114 -0
  139. package/src/JsonConfigComponent/ConfigInstanceSelect.jsx +172 -0
  140. package/src/JsonConfigComponent/ConfigInterface.jsx +112 -0
  141. package/src/JsonConfigComponent/ConfigJsonEditor.jsx +103 -0
  142. package/src/JsonConfigComponent/ConfigLanguage.tsx +153 -0
  143. package/src/JsonConfigComponent/ConfigLicense.jsx +148 -0
  144. package/src/JsonConfigComponent/ConfigNumber.tsx +207 -0
  145. package/src/JsonConfigComponent/ConfigObjectId.jsx +113 -0
  146. package/src/JsonConfigComponent/ConfigPanel.tsx +360 -0
  147. package/src/JsonConfigComponent/ConfigPassword.jsx +160 -0
  148. package/src/JsonConfigComponent/ConfigPattern.jsx +50 -0
  149. package/src/JsonConfigComponent/ConfigPort.tsx +232 -0
  150. package/src/JsonConfigComponent/ConfigRoom.jsx +90 -0
  151. package/src/JsonConfigComponent/ConfigSelect.jsx +124 -0
  152. package/src/JsonConfigComponent/ConfigSelectSendTo.tsx +251 -0
  153. package/src/JsonConfigComponent/ConfigSendto.tsx +340 -0
  154. package/src/JsonConfigComponent/ConfigSetState.jsx +116 -0
  155. package/src/JsonConfigComponent/ConfigSlider.jsx +97 -0
  156. package/src/JsonConfigComponent/ConfigStaticDivider.jsx +51 -0
  157. package/src/JsonConfigComponent/ConfigStaticHeader.jsx +63 -0
  158. package/src/JsonConfigComponent/ConfigStaticImage.jsx +48 -0
  159. package/src/JsonConfigComponent/ConfigStaticText.jsx +72 -0
  160. package/src/JsonConfigComponent/ConfigTable.tsx +1040 -0
  161. package/src/JsonConfigComponent/ConfigTabs.tsx +150 -0
  162. package/src/JsonConfigComponent/ConfigText.tsx +188 -0
  163. package/src/JsonConfigComponent/ConfigTextSendTo.tsx +102 -0
  164. package/src/JsonConfigComponent/ConfigTimePicker.tsx +63 -0
  165. package/src/JsonConfigComponent/ConfigTopic.jsx +78 -0
  166. package/src/JsonConfigComponent/ConfigUUID.tsx +55 -0
  167. package/src/JsonConfigComponent/ConfigUser.jsx +104 -0
  168. package/src/JsonConfigComponent/index.tsx +435 -0
  169. package/src/JsonConfigComponent/wrapper/Components/CustomModal.jsx +145 -0
  170. package/src/JsonConfigComponent/wrapper/Components/Editor.jsx +65 -0
  171. package/src/Utils.jsx +1683 -0
  172. package/src/index.tsx +14 -0
  173. package/src/types.d.ts +372 -0
@@ -0,0 +1,662 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { withStyles } from '@mui/styles';
4
+
5
+ import {
6
+ Button,
7
+ CircularProgress,
8
+ Dialog,
9
+ DialogContent,
10
+ DialogActions,
11
+ DialogTitle,
12
+ Table,
13
+ TableHead,
14
+ TableCell,
15
+ TableRow,
16
+ TableBody,
17
+ DialogContentText,
18
+ TableContainer,
19
+ } from '@mui/material';
20
+
21
+ import { Check as IconCheck, Send as IconSend } from '@mui/icons-material';
22
+
23
+ import { Confirm as ConfirmDialog, I18n } from '@iobroker/adapter-react-v5';
24
+
25
+ import ConfigGeneric from './ConfigGeneric';
26
+
27
+ const styles = theme => ({
28
+ fullWidth: {
29
+ width: '100%',
30
+ },
31
+ icon: {
32
+ width: 24,
33
+ height: 24,
34
+ marginRight: 4,
35
+ },
36
+ licLabel: {
37
+ fontWeight: 'bold',
38
+ minWidth: 100,
39
+ marginRight: 10,
40
+ textTransform: 'capitalize',
41
+ display: 'inline-block',
42
+ },
43
+ licValue: {
44
+ fontWeight: 'normal',
45
+ },
46
+ errorTitle: {
47
+ color: theme.palette.mode === 'dark' ? '#e39191' : '#b62020',
48
+ },
49
+ okTitle: {
50
+ color: theme.palette.mode === 'dark' ? '#6fd56f' : '#007c00',
51
+ },
52
+ errorText: {
53
+ color: theme.palette.mode === 'dark' ? '#e39191' : '#b62020',
54
+ marginBottom: 30,
55
+ },
56
+ });
57
+
58
+ class ConfigCheckLicense extends ConfigGeneric {
59
+ async componentDidMount() {
60
+ super.componentDidMount();
61
+ this.setState({
62
+ _error: '',
63
+ running: false,
64
+ showLicenseData: null,
65
+ foundSuitableLicense: false,
66
+ licenseOfflineCheck: false,
67
+ result: null,
68
+ });
69
+ }
70
+
71
+ renderErrorDialog() {
72
+ if (this.state._error && !this.state.showLicenseData) {
73
+ let content = this.state._error;
74
+ if (this.state.allLicenses) {
75
+ content = [
76
+ <div key="error">{content}</div>,
77
+ ];
78
+ content.push(<Button
79
+ key="button"
80
+ variant="contained"
81
+ onClick={() => window.open('https://iobroker.net/www/account/licenses', '_blank')}
82
+ >
83
+ {I18n.t('iobroker.net')}
84
+ </Button>);
85
+ if (!this.state.allLicenses.length) {
86
+ content.push(<div key="text1">{I18n.t('ra_No one license found in license manager')}</div>);
87
+ content.push(<div key="text2">{I18n.t('ra_Please create license')}</div>);
88
+ } else {
89
+ // license.id,
90
+ // validName,
91
+ // validUuid,
92
+ // validTill,
93
+ // validVersion,
94
+ // license,
95
+ content.push(<TableContainer key="table">
96
+ <Table size="small">
97
+ <TableHead>
98
+ <TableRow>
99
+ <TableCell>{I18n.t('ra_Product')}</TableCell>
100
+ <TableCell>{I18n.t('ra_Version')}</TableCell>
101
+ <TableCell>UUID</TableCell>
102
+ <TableCell>{I18n.t('ra_ValidTill')}</TableCell>
103
+ <TableCell>{I18n.t('ra_Commercial')}</TableCell>
104
+ <TableCell>ID</TableCell>
105
+ </TableRow>
106
+ </TableHead>
107
+ <TableBody>
108
+ {this.state.allLicenses.map(license => <TableRow key={license.id}>
109
+ <TableCell className={license.validName ? '' : this.props.classes.errorText}>{license.license.product}</TableCell>
110
+ <TableCell className={license.validVersion ? '' : this.props.classes.errorText}>{license.license.version}</TableCell>
111
+ <TableCell className={license.validUuid ? '' : this.props.classes.errorText}>{license.license.uuid || '--'}</TableCell>
112
+ <TableCell className={license.validTill ? '' : this.props.classes.errorText}>{license.license.validTill && license.license.validTill !== '0000-00-00 00:00:00' ? new Date(license.license.validTill).toLocaleDateString() : '--'}</TableCell>
113
+ <TableCell>{license.license.invoice !== 'free' ? (license.license.invoice === 'MANUALLY_CREATED' ? '✓' : license.license.invoice) : '-'}</TableCell>
114
+ <TableCell>{license.id}</TableCell>
115
+ </TableRow>)}
116
+ </TableBody>
117
+ </Table>
118
+ </TableContainer>);
119
+ }
120
+ }
121
+
122
+ return <Dialog
123
+ open={!0}
124
+ maxWidth="xl"
125
+ fullWidth={this.props.fullWidth !== undefined ? this.props.fullWidth : true}
126
+ onClose={() => this.handleOk()}
127
+ >
128
+ <DialogTitle>
129
+ {I18n.t('ra_Error')}
130
+ </DialogTitle>
131
+ <DialogContent>
132
+ <DialogContentText>
133
+ {content}
134
+ </DialogContentText>
135
+ </DialogContent>
136
+ <DialogActions>
137
+ <Button
138
+ variant="contained"
139
+ onClick={() => this.setState({ _error: '', allLicenses: null })}
140
+ color="primary"
141
+ autoFocus
142
+ startIcon={<IconCheck />}
143
+ >
144
+ {I18n.t('ra_Ok')}
145
+ </Button>
146
+ </DialogActions>
147
+ </Dialog>;
148
+ }
149
+
150
+ return null;
151
+ }
152
+
153
+ renderMessageDialog() {
154
+ if (this.state.showLicenseData) {
155
+ const pre = [];
156
+ const data = this.state.showLicenseData;
157
+ Object.keys(data).forEach(key => {
158
+ if (data[key] === null || data[key] === undefined) {
159
+ return;
160
+ }
161
+ if (typeof data[key] === 'object') {
162
+ const obj = data[key];
163
+ Object.keys(obj).forEach(key1 => {
164
+ if (obj[key1] !== null && obj[key1] !== undefined) {
165
+ if (typeof obj[key1] === 'object') {
166
+ pre.push(<div key={key1}>
167
+ <div className={this.props.classes.licLabel}>
168
+ {key1}
169
+ :
170
+ </div>
171
+ {JSON.stringify(obj[key1], null, 2)}
172
+ </div>);
173
+ } else {
174
+ pre.push(<div key={key1}>
175
+ <div className={this.props.classes.licLabel}>
176
+ {key}
177
+ {' '}
178
+ -
179
+ {key1}
180
+ :
181
+ </div>
182
+ {obj[key1].toString()}
183
+ </div>);
184
+ }
185
+ }
186
+ });
187
+ } else {
188
+ pre.push(<div key={key}>
189
+ <div className={this.props.classes.licLabel}>
190
+ {key.replace(/_/g, ' ')}
191
+ :
192
+ </div>
193
+ {data[key].toString()}
194
+ </div>);
195
+ }
196
+ });
197
+ pre.push(<div key="checked">
198
+ <div className={this.props.classes.licLabel}>
199
+ {I18n.t('ra_Checked')}
200
+ :
201
+ </div>
202
+ {this.state.licenseOfflineCheck ? I18n.t('ra_locally') : I18n.t('ra_via internet')}
203
+ </div>);
204
+
205
+ return <Dialog open={!0} onClose={() => this.setState({ showLicenseData: null })}>
206
+ <DialogTitle>
207
+ <span className={this.state.result ? this.props.classes.okTitle : this.props.classes.errorTitle}>
208
+ {I18n.t('ra_License %s', this.state.result ? 'OK' : 'INVALID')}
209
+ </span>
210
+ </DialogTitle>
211
+ <DialogContent>
212
+ {this.state.showLinkToProfile ? <Button
213
+ variant="contained"
214
+ onClick={() => window.open('https://iobroker.net/www/account/licenses', '_blank')}
215
+ >
216
+ https://iobroker.net
217
+ </Button> : null}
218
+ {this.state._error ? <div className={this.props.classes.errorText}>{this.state._error}</div> : null}
219
+ {pre}
220
+ </DialogContent>
221
+ <DialogActions>
222
+ <Button
223
+ onClick={() => this.setState({ showLicenseData: null, _error: '' })}
224
+ color="primary"
225
+ variant="contained"
226
+ >
227
+ {I18n.t('ra_Close')}
228
+ </Button>
229
+ </DialogActions>
230
+ </Dialog>;
231
+ }
232
+ return null;
233
+ }
234
+
235
+ static parseJwt(token) {
236
+ const base64Url = token.split('.')[1];
237
+ const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
238
+ const jsonPayload = decodeURIComponent(
239
+ atob(base64)
240
+ .split('')
241
+ .map(c => `%${`00${c.charCodeAt(0).toString(16)}`.slice(-2)}`)
242
+ .join(''),
243
+ );
244
+ try {
245
+ return JSON.parse(jsonPayload);
246
+ } catch (e) {
247
+ return null;
248
+ }
249
+ }
250
+
251
+ static isVersionValid(version, rule, invoice, adapterName) {
252
+ if (!rule || !version) {
253
+ return true;
254
+ }
255
+ let result = true;
256
+ const [major] = version.split('.');
257
+ if (rule.startsWith('>=')) {
258
+ result = parseInt(major, 10) >= parseInt(rule.substring(2, 10));
259
+ } else if (rule.startsWith('<=')) {
260
+ result = parseInt(major, 10) <= parseInt(rule.substring(2, 10));
261
+ } else if (rule.startsWith('>')) {
262
+ result = parseInt(major, 10) > parseInt(rule.substring(1, 10));
263
+ } else if (rule.startsWith('<')) {
264
+ result = parseInt(major, 10) < parseInt(rule.substring(1, 10));
265
+ } else if (rule.startsWith('=')) {
266
+ result = parseInt(major, 10) === parseInt(rule.substring(1, 10));
267
+ } else if (rule.startsWith('==')) {
268
+ result = parseInt(major, 10) === parseInt(rule.substring(2, 10));
269
+ } else if (rule.startsWith('===')) {
270
+ result = parseInt(major, 10) === parseInt(rule.substring(3, 10));
271
+ }
272
+
273
+ if (!result && invoice && adapterName) {
274
+ // all commercial licenses are valid for all versions
275
+ if (invoice !== 'free') {
276
+ return true;
277
+ }
278
+ }
279
+
280
+ return true;
281
+ }
282
+
283
+ async findInLicenseManager(adapterName) {
284
+ // read if the license manager is supported
285
+ const licenses = await this.props.socket.getObject('system.licenses');
286
+ const errors = [];
287
+ if (licenses?.native?.licenses?.length) {
288
+ // enable license manager
289
+ let useLicense;
290
+ const now = Date.now();
291
+
292
+ let uuid;
293
+ if (this.props.schema.uuid) {
294
+ const uuidObj = await this.props.socket.getObject('system.meta.uuid');
295
+ uuid = uuidObj?.native?.uuid;
296
+ }
297
+ let version;
298
+ if (this.props.schema.version) {
299
+ const aObj = await this.props.socket.getObject(`system.adapter.${adapterName}`);
300
+ version = aObj?.common?.version;
301
+ }
302
+
303
+ // find license for vis
304
+ licenses.native.licenses.forEach(license => {
305
+ const validTill = !license.validTill || license.validTill === '0000-00-00 00:00:00' || new Date(license.validTill).getTime() > now;
306
+ const parts = (license.product || '').split('.');
307
+ const validName = parts[1] === adapterName || (adapterName === 'vis-2' && parts[1] === 'vis');
308
+ const validUuid = !uuid || !license.uuid || license.uuid === uuid;
309
+ const validVersion = ConfigCheckLicense.isVersionValid(version, license.version, license.invoice, adapterName);
310
+ // commercial license has priority over free license
311
+ if ((!useLicense || license.invoice !== 'free') && validTill && validName && validUuid && validVersion) {
312
+ useLicense = license;
313
+ }
314
+ errors.push({
315
+ id: license.id,
316
+ validName,
317
+ validUuid,
318
+ validVersion,
319
+ validTill,
320
+ license,
321
+ });
322
+ });
323
+
324
+ if (useLicense) {
325
+ errors.find(e => e.id === useLicense.id).used = true;
326
+ }
327
+ }
328
+
329
+ return errors;
330
+ }
331
+
332
+ static updateLicenses(socket) {
333
+ return new Promise((resolve, reject) => {
334
+ socket.getRawSocket().emit('updateLicenses', null, null, (err, licenses) => {
335
+ if (err === 'permissionError') {
336
+ reject(I18n.t('ra_May not trigger "updateLicenses"'));
337
+ } else if (err && err.error) {
338
+ if (typeof err.error === 'string') {
339
+ reject(I18n.t(err.error));
340
+ } else {
341
+ reject(JSON.stringify(err.error));
342
+ }
343
+ } else if (err) {
344
+ if (typeof err === 'string') {
345
+ reject(I18n.t(err));
346
+ } else {
347
+ reject(JSON.stringify(err));
348
+ }
349
+ } else {
350
+ resolve(licenses);
351
+ }
352
+ });
353
+ });
354
+ }
355
+
356
+ async checkLicense(license, adapterName) {
357
+ let uuid;
358
+ if (this.props.schema.uuid) {
359
+ const uuidObj = await this.props.socket.getObject('system.meta.uuid');
360
+ uuid = uuidObj?.native?.uuid;
361
+ }
362
+ let version;
363
+ if (this.props.schema.version) {
364
+ const aObj = await this.props.socket.getObject(`system.adapter.${adapterName}`);
365
+ version = aObj?.common?.version;
366
+ }
367
+
368
+ const controller = new AbortController();
369
+ let timeout = setTimeout(() => {
370
+ timeout = null;
371
+ controller.abort();
372
+ }, 5000);
373
+
374
+ try {
375
+ const response = await window.fetch('https://iobroker.net/api/v1/public/cert/', {
376
+ method: 'POST',
377
+ body: JSON.stringify({ json: license, uuid }),
378
+ headers: {
379
+ 'Content-Type': 'text/plain',
380
+ },
381
+ signal: controller.signal,
382
+ });
383
+ timeout && clearTimeout(timeout);
384
+ let data = await response.text();
385
+ try {
386
+ data = JSON.parse(data);
387
+ } catch (e) {
388
+ // ignore
389
+ }
390
+
391
+ if (data?.error) {
392
+ try {
393
+ const data_ = ConfigCheckLicense.parseJwt(license);
394
+ const _error = I18n.t(`ra_${data_.error || data.error || 'Unknown error'}`).replace(/^ra_/, '');
395
+
396
+ return this.setState({
397
+ _error,
398
+ licenseOfflineCheck: false,
399
+ showLicenseData: data_,
400
+ result: false,
401
+ running: false,
402
+ });
403
+ } catch (e) {
404
+ console.log('Cannot parse license');
405
+ return this.setState({ _error: data.error, result: false, running: false });
406
+ }
407
+ } else {
408
+ let showLicenseData = null;
409
+ try {
410
+ showLicenseData = ConfigCheckLicense.parseJwt(license);
411
+ } catch (e) {
412
+ // ignore
413
+ }
414
+ if (data) {
415
+ const validTill = data.validTill || data.valid_till;
416
+ if (
417
+ validTill &&
418
+ validTill !== '0000-00-00 00:00:00' &&
419
+ new Date(validTill).getTime() < Date.now()
420
+ ) {
421
+ return this.setState({
422
+ _error: I18n.t('ra_License expired on %s', new Date(validTill).toLocaleString()),
423
+ licenseOfflineCheck: false,
424
+ showLicenseData,
425
+ result: false,
426
+ running: false,
427
+ });
428
+ }
429
+ const parts = (data.name || '').split('.');
430
+ if (parts[1] === adapterName || (parts[1] === 'vis' && adapterName === 'vis-2')) {
431
+ // check UUID
432
+ if (uuid && !data.uuid && adapterName === 'vis-2') {
433
+ return this.setState({
434
+ _error: I18n.t(
435
+ 'ra_License must be converted',
436
+ data.uuid,
437
+ ),
438
+ showLinkToProfile: true,
439
+ licenseOfflineCheck: false,
440
+ showLicenseData,
441
+ result: false,
442
+ running: false,
443
+ });
444
+ }
445
+
446
+ if (uuid && data.uuid && data.uuid !== uuid) {
447
+ return this.setState({
448
+ _error: I18n.t(
449
+ 'ra_Serial number (UUID) "%s" in license is for other device.',
450
+ data.uuid,
451
+ ),
452
+ licenseOfflineCheck: false,
453
+ showLicenseData,
454
+ result: false,
455
+ running: false,
456
+ });
457
+ }
458
+
459
+ if (!ConfigCheckLicense.isVersionValid(version, data.version, data.invoice, adapterName)) {
460
+ return this.setState({
461
+ _error: I18n.t(
462
+ 'ra_License is for version %s, but required version is %s',
463
+ data.version,
464
+ this.props.schema.version,
465
+ ),
466
+ licenseOfflineCheck: false,
467
+ showLicenseData,
468
+ result: false,
469
+ running: false,
470
+ });
471
+ }
472
+
473
+ return this.setState({
474
+ licenseOfflineCheck: false,
475
+ showLicenseData,
476
+ result: true,
477
+ running: false,
478
+ });
479
+ }
480
+ return this.setState({
481
+ _error: I18n.t('ra_License for other product "%s"', data.name),
482
+ licenseOfflineCheck: false,
483
+ showLicenseData,
484
+ result: false,
485
+ running: false,
486
+ });
487
+ }
488
+ throw new Error('ra_Invalid answer from server');
489
+ }
490
+ } catch (error) {
491
+ if (error?.response?.status === 404) {
492
+ return this.setState({ _error: I18n.t('ra_License does not exist'), result: false, running: false });
493
+ }
494
+ // check offline
495
+ try {
496
+ const data = ConfigCheckLicense.parseJwt(license);
497
+ const parts = (data.name || '').split('.');
498
+
499
+ if (
500
+ data.valid_till &&
501
+ data.valid_till !== '0000-00-00 00:00:00' &&
502
+ new Date(data.valid_till).getTime() < Date.now()
503
+ ) {
504
+ return this.setState({
505
+ _error: I18n.t('ra_License expired on %s', new Date(data.valid_till).toLocaleString()),
506
+ showLicenseData: data,
507
+ licenseOfflineCheck: true,
508
+ running: false,
509
+ result: false,
510
+ });
511
+ }
512
+ if (parts[1] === adapterName) {
513
+ // check UUID
514
+ if (uuid && data.uuid && data.uuid !== uuid) {
515
+ return this.setState({
516
+ _error: I18n.t('ra_Serial number (UUID) "%s" in license is for other device.', data.uuid),
517
+ showLicenseData: data,
518
+ licenseOfflineCheck: true,
519
+ result: false,
520
+ running: false,
521
+ });
522
+ }
523
+
524
+ if (!ConfigCheckLicense.isVersionValid(version, data.version, data.invoice, adapterName)) {
525
+ return this.setState({
526
+ _error: I18n.t(
527
+ 'ra_License is for version %s, but required version is %s',
528
+ data.version,
529
+ this.props.schema.version,
530
+ ),
531
+ licenseOfflineCheck: true,
532
+ showLicenseData: data,
533
+ result: false,
534
+ running: false,
535
+ });
536
+ }
537
+
538
+ return this.setState({
539
+ running: false,
540
+ result: true,
541
+ licenseOfflineCheck: true,
542
+ showLicenseData: data,
543
+ });
544
+ }
545
+ return this.setState({
546
+ _error: I18n.t('ra_License for other product "%s"', data.name),
547
+ licenseOfflineCheck: true,
548
+ showLicenseData: data,
549
+ result: false,
550
+ running: false,
551
+ });
552
+ } catch (e) {
553
+ return this.setState({
554
+ _error: I18n.t('ra_Cannot decode license'),
555
+ result: false,
556
+ licenseOfflineCheck: true,
557
+ running: false,
558
+ });
559
+ }
560
+ }
561
+ }
562
+
563
+ renderAskForUpdate() {
564
+ if (!this.state.askForUpdate) {
565
+ return null;
566
+ }
567
+ return <ConfirmDialog
568
+ text={I18n.t(
569
+ 'ra_License not found in license manager. Do you want to read licenses from iobroker.net?',
570
+ )}
571
+ ok={I18n.t('ra_Yes')}
572
+ onClose={async isYes => {
573
+ if (isYes) {
574
+ this.setState({ askForUpdate: false });
575
+ try {
576
+ await ConfigCheckLicense.updateLicenses(this.props.socket);
577
+ } catch (e) {
578
+ window.alert(I18n.t('ra_Cannot read licenses: %s', e));
579
+ return;
580
+ }
581
+ await this._onClick(true);
582
+ } else {
583
+ this.setState({ askForUpdate: false, running: false });
584
+ }
585
+ }}
586
+ />;
587
+ }
588
+
589
+ async _onClick(secondRun) {
590
+ const adapterName = this.props.adapterName === 'vis-2' ? 'vis' : this.props.adapterName;
591
+ this.setState({ running: true });
592
+ let license;
593
+ let licenses;
594
+ if (this.props.data.useLicenseManager) {
595
+ licenses = await this.findInLicenseManager(adapterName);
596
+ license = licenses.find(li => li.used);
597
+ if (license) {
598
+ license = license.license.json;
599
+ }
600
+ if (!license && !secondRun) {
601
+ // no suitable license found in the license manager
602
+ // should we read all licenses again?
603
+ this.setState({ askForUpdate: true });
604
+ return;
605
+ }
606
+ } else {
607
+ license = this.props.data.license;
608
+ }
609
+ if (license) {
610
+ await this.checkLicense(license, adapterName, this.props.schema.uuid);
611
+ } else if (this.props.data.useLicenseManager) {
612
+ this.setState({
613
+ _error: I18n.t('ra_Suitable license not found in license manager'),
614
+ result: false,
615
+ running: false,
616
+ allLicenses: licenses,
617
+ });
618
+ } else {
619
+ // this case could not happen
620
+ this.setState({
621
+ _error: I18n.t('ra_Please enter the license'),
622
+ result: false,
623
+ running: false,
624
+ });
625
+ }
626
+ }
627
+
628
+ renderItem(/* error, disabled, defaultValue */) {
629
+ return <div className={this.props.classes.fullWidth}>
630
+ <Button
631
+ variant={this.props.schema.variant || 'outlined'}
632
+ color={this.props.schema.color || 'primary'}
633
+ className={this.props.classes.fullWidth}
634
+ disabled={(!this.props.data.license && !this.props.data.useLicenseManager) || this.state.running}
635
+ startIcon={<IconSend />}
636
+ onClick={() => this._onClick()}
637
+ >
638
+ {this.state.running ? <CircularProgress size={20} style={{ marginRight: 8 }} /> : null}
639
+ {this.getText(this.props.schema.label || 'ra_Check license', this.props.schema.noTranslation)}
640
+ </Button>
641
+ {this.renderMessageDialog()}
642
+ {this.renderErrorDialog()}
643
+ {this.renderAskForUpdate()}
644
+ </div>;
645
+ }
646
+ }
647
+
648
+ ConfigCheckLicense.propTypes = {
649
+ socket: PropTypes.object.isRequired,
650
+ themeType: PropTypes.string,
651
+ themeName: PropTypes.string,
652
+ style: PropTypes.object,
653
+ className: PropTypes.string,
654
+ data: PropTypes.object.isRequired,
655
+ schema: PropTypes.object,
656
+ onError: PropTypes.func,
657
+ onChange: PropTypes.func,
658
+ adapterName: PropTypes.string,
659
+ instance: PropTypes.number,
660
+ };
661
+
662
+ export default withStyles(styles)(ConfigCheckLicense);