@iobroker/json-config 8.2.11 → 8.2.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.
package/README.md CHANGED
@@ -541,10 +541,12 @@ To use this, you must first provide the OAuth2 data (client ID, secret, etc.) to
541
541
 
542
542
  | Property | Description |
543
543
  |----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
544
- | `identifier` | Oauth2 identifier, like `spotify`, `google`, `dropbox`, `microsoft` |
545
- | `saveTokenIn` | Optional state name where the token will be saved. Default is `oauth2Tokens`. The path is relative to the adapter instance, like `adapterName.X.oauth2Tokens` |
546
- | `scope` | Optional scopes divided by space, e.g. `user-read-private user-read-email` |
547
- | `refreshLabel` | Optional button label for refreshing the token |
544
+ | `identifier` | Oauth2 identifier, like `spotify`, `google`, `dropbox`, `microsoft` |
545
+ | `saveTokenIn` | Optional state name where the token will be saved. Default is `oauth2Tokens`. The path is relative to the adapter instance, like `adapterName.X.oauth2Tokens` |
546
+ | `scope` | Optional scopes divided by space, e.g. `user-read-private user-read-email` |
547
+ | `refreshLabel` | Optional button label for refreshing the token |
548
+ | `ownClientId` | Optional attribute name where the user's own OAuth Client ID will be stored. If set, an input field for Client ID is shown |
549
+ | `ownClientSecret` | Optional attribute name where the user's own OAuth Client Secret will be stored. If set, an input field for Client Secret is shown |
548
550
 
549
551
  #### Example for `oauth2`
550
552
 
@@ -1747,6 +1749,9 @@ The schema is used here: https://github.com/SchemaStore/schemastore/blob/6da29cd
1747
1749
  ### **WORK IN PROGRESS**
1748
1750
  -->
1749
1751
  ## Changelog
1752
+ ### 8.2.12 (2026-03-24)
1753
+ - (@GermanBluefox) Added the possibility to use own Client ID for oauth authentication
1754
+
1750
1755
  ### 8.2.11 (2026-03-20)
1751
1756
  - (@GermanBluefox) Correcting unit in schema
1752
1757
  - (@GermanBluefox) Fill other config fields when an object ID is selected
@@ -25,6 +25,8 @@ interface ConfigOAuth2State extends ConfigGenericState {
25
25
  blocked: boolean;
26
26
  running: boolean;
27
27
  pressed: boolean;
28
+ clientId: string;
29
+ clientSecret: string;
28
30
  }
29
31
  export default class ConfigOAuth2 extends ConfigGeneric<ConfigOAuth2Props, ConfigOAuth2State> {
30
32
  private authWindow?;
@@ -37,6 +39,6 @@ export default class ConfigOAuth2 extends ConfigGeneric<ConfigOAuth2Props, Confi
37
39
  saveToken(accessTokens: string): void;
38
40
  onMessage: (event: MessageEvent) => void;
39
41
  onOpenUrl(): void;
40
- renderItem(): React.JSX.Element;
42
+ renderItem(_error?: boolean, disabled?: boolean): React.JSX.Element;
41
43
  }
42
44
  export {};
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
- import { Button, TextField } from '@mui/material';
3
- import { CloudUpload } from '@mui/icons-material';
2
+ import { Button, IconButton, TextField } from '@mui/material';
3
+ import { Close as CloseIcon, CloudUpload } from '@mui/icons-material';
4
4
  import { I18n } from '@iobroker/adapter-react-v5';
5
5
  import ConfigGeneric from './ConfigGeneric';
6
6
  export default class ConfigOAuth2 extends ConfigGeneric {
@@ -16,6 +16,8 @@ export default class ConfigOAuth2 extends ConfigGeneric {
16
16
  blocked: false,
17
17
  running: false,
18
18
  pressed: false,
19
+ clientId: '',
20
+ clientSecret: '',
19
21
  };
20
22
  this.url = `https://oauth2.iobroker.in/${props.schema.identifier}?redirect=true`;
21
23
  if (props.schema.scope) {
@@ -32,14 +34,26 @@ export default class ConfigOAuth2 extends ConfigGeneric {
32
34
  window.attachEvent('onmessage', this.onMessage, false);
33
35
  }
34
36
  await this.props.oContext.socket.subscribeState(this.oid, this.onTokensUpdated);
37
+ let state;
38
+ if (this.props.schema.ownClientId) {
39
+ state = { clientId: ConfigGeneric.getValue(this.props.data, this.props.schema.ownClientId) };
40
+ }
41
+ if (this.props.schema.ownClientId) {
42
+ state ||= {};
43
+ state.clientSecret = ConfigGeneric.getValue(this.props.data, this.props.schema.ownClientSecret);
44
+ }
35
45
  // read tokens
36
46
  const tokens = await this.props.oContext.socket.getState(this.oid);
37
47
  if (tokens) {
38
48
  const accessTokens = JSON.parse(tokens.val);
39
49
  if (new Date(accessTokens.access_token_expires_on).getTime() > Date.now()) {
40
- this.setState({ accessTokens: tokens.val });
50
+ state ||= {};
51
+ state.accessTokens = tokens.val;
41
52
  }
42
53
  }
54
+ if (state) {
55
+ this.setState(state);
56
+ }
43
57
  }
44
58
  onTokensUpdated = (_id, state) => {
45
59
  if (state?.val) {
@@ -104,7 +118,7 @@ export default class ConfigOAuth2 extends ConfigGeneric {
104
118
  }
105
119
  };
106
120
  onOpenUrl() {
107
- this.authWindow = window.open(this.url, this.props.schema.identifier);
121
+ this.authWindow = window.open(this.url + (this.props.schema.ownClientId ? `&clientId=${encodeURIComponent(this.state.clientId)}` : ''), this.props.schema.identifier);
108
122
  if (!this.authWindow || this.authWindow.closed || typeof this.authWindow.closed === 'undefined') {
109
123
  this.setState({ blocked: true });
110
124
  }
@@ -112,7 +126,7 @@ export default class ConfigOAuth2 extends ConfigGeneric {
112
126
  this.setState({ pressed: true });
113
127
  }
114
128
  }
115
- renderItem() {
129
+ renderItem(_error, disabled) {
116
130
  let validTill = '';
117
131
  if (this.state.accessTokens) {
118
132
  try {
@@ -136,7 +150,27 @@ export default class ConfigOAuth2 extends ConfigGeneric {
136
150
  }
137
151
  const icon = this.getIcon();
138
152
  return (React.createElement("div", { style: { width: '100%', margin: '0 0 1rem 0' } },
139
- React.createElement(Button, { disabled: this.state.running, endIcon: icon || React.createElement(CloudUpload, null), variant: "contained", onClick: () => this.onOpenUrl() }, label),
153
+ this.props.schema.ownClientId ? (React.createElement(TextField, { value: this.state.clientId, onChange: e => {
154
+ const value = e.target.value;
155
+ this.setState({ clientId: value }, () => this.onChange(this.props.schema.ownClientId, value));
156
+ }, variant: "standard", fullWidth: true, error: !this.state.clientId, disabled: !!disabled, label: I18n.t('ra_OAuth Client ID'), slotProps: {
157
+ input: {
158
+ endAdornment: this.state.clientId ? (React.createElement(IconButton, { size: "small", tabIndex: -1, onClick: () => this.setState({ clientId: '' }, () => this.onChange(this.props.schema.ownClientId, '')) },
159
+ React.createElement(CloseIcon, null))) : null,
160
+ },
161
+ } })) : null,
162
+ this.props.schema.ownClientSecret ? (React.createElement(TextField, { value: this.state.clientSecret, onChange: e => {
163
+ const value = e.target.value;
164
+ this.setState({ clientSecret: value }, () => this.onChange(this.props.schema.ownClientSecret, value));
165
+ }, variant: "standard", fullWidth: true, error: !this.state.clientSecret, disabled: !!disabled, label: I18n.t('ra_OAuth Client secret'), slotProps: {
166
+ input: {
167
+ endAdornment: this.state.clientSecret ? (React.createElement(IconButton, { size: "small", tabIndex: -1, onClick: () => this.setState({ clientSecret: '' }, () => this.onChange(this.props.schema.ownClientSecret, '')) },
168
+ React.createElement(CloseIcon, null))) : null,
169
+ },
170
+ } })) : null,
171
+ React.createElement(Button, { disabled: this.state.running ||
172
+ (this.props.schema.ownClientSecret && !this.state.clientSecret) ||
173
+ (this.props.schema.ownClientId && !this.state.clientId), endIcon: icon || React.createElement(CloudUpload, null), variant: "contained", onClick: () => this.onOpenUrl() }, label),
140
174
  this.state.blocked ? (React.createElement("div", { style: { color: 'red', fontSize: 16, marginTop: 20 } }, I18n.t('ra_Please allow popups in your browser for this page!'))) : null,
141
175
  this.state.accessTokens ? (React.createElement("div", { style: { color: 'green', fontSize: 16, marginTop: 20 } }, this.props.alive
142
176
  ? I18n.t('ra_Successfully authorized. Token valid till %s and will be automatically renewed.', validTill)
@@ -1 +1 @@
1
- {"version":3,"file":"ConfigOAuth2.js","sourceRoot":"./src/","sources":["JsonConfigComponent/ConfigOAuth2.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAElD,OAAO,aAAmE,MAAM,iBAAiB,CAAC;AAgClG,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,aAAmD;IACjF,UAAU,CAAsB;IACvB,GAAG,CAAS;IACZ,GAAG,CAAS;IAE7B,YAAY,KAAwB;QAChC,KAAK,CAAC,KAAK,CAAC,CAAC;QAEb,IAAI,CAAC,KAAK,GAAG;YACT,GAAG,IAAI,CAAC,KAAK;YACb,YAAY,EAAE,EAAE;YAChB,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,KAAK;SACjB,CAAC;QAEF,IAAI,CAAC,GAAG,GAAG,8BAA8B,KAAK,CAAC,MAAM,CAAC,UAAU,gBAAgB,CAAC;QACjF,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACrB,IAAI,CAAC,GAAG,IAAI,UAAU,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QACnE,CAAC;QAED,IAAI,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,IAAI,cAAc,EAAE,CAAC;IACvI,CAAC;IAED,KAAK,CAAC,iBAAiB;QACnB,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC1B,IAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC;YAC1B,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,SAAgB,EAAE,KAAK,CAAC,CAAC;QACrE,CAAC;aAAM,CAAC;YACJ,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,SAAgB,EAAE,KAAK,CAAC,CAAC;QAClE,CAAC;QAED,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QAEhF,cAAc;QACd,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnE,IAAI,MAAM,EAAE,CAAC;YACT,MAAM,YAAY,GAAiB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAa,CAAC,CAAC;YACpE,IAAI,IAAI,IAAI,CAAC,YAAY,CAAC,uBAAuB,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBACxE,IAAI,CAAC,QAAQ,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,GAAa,EAAE,CAAC,CAAC;YAC1D,CAAC;QACL,CAAC;IACL,CAAC;IAED,eAAe,GAAG,CAAC,GAAW,EAAE,KAAwC,EAAQ,EAAE;QAC9E,IAAI,KAAK,EAAE,GAAG,EAAE,CAAC;YACb,MAAM,YAAY,GAAiB,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAa,CAAC,CAAC;YACnE,IAAI,IAAI,IAAI,CAAC,YAAY,CAAC,uBAAuB,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBACxE,IAAI,IAAI,CAAC,KAAK,CAAC,YAAY,KAAK,KAAK,CAAC,GAAG,EAAE,CAAC;oBACxC,IAAI,CAAC,QAAQ,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,GAAa,EAAE,CAAC,CAAC;gBACzD,CAAC;gBACD,OAAO;YACX,CAAC;QACL,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,CAAC;IACxC,CAAC,CAAC;IAEF,oBAAoB;QAChB,KAAK,CAAC,oBAAoB,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,mBAAmB,EAAE,CAAC;YAC7B,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,SAAgB,EAAE,KAAK,CAAC,CAAC;QACxE,CAAC;aAAM,CAAC;YACJ,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,SAAgB,EAAE,KAAK,CAAC,CAAC;QAClE,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;IAChF,CAAC;IAED,SAAS,CAAC,YAAoB;QAC1B,IAAI,CAAC;YACD,IAAI,YAAY,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBAChD,2BAA2B;gBAC3B,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC;YACtC,CAAC;YAED,MAAM,kBAAkB,GAAiB,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAClE,IAAI,kBAAkB,CAAC,YAAY,IAAI,kBAAkB,CAAC,aAAa,IAAI,kBAAkB,CAAC,UAAU,EAAE,CAAC;gBACvG,4CAA4C;gBAC5C,kBAAkB,CAAC,uBAAuB,KAAK,IAAI,IAAI,CACnD,IAAI,CAAC,GAAG,EAAE,GAAG,kBAAkB,CAAC,UAAU,GAAG,IAAI,CACpD,CAAC,WAAW,EAAE,CAAC;gBAEhB,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM;qBACrB,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,EAAE,IAAI,CAAC;qBAC5D,KAAK,CAAC,CAAC,CAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;YAC7E,CAAC;QACL,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,SAAS;YACT,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;IACL,CAAC;IAED,SAAS,GAAG,CAAC,KAAmB,EAAQ,EAAE;QACtC,IAAI,KAAK,CAAC,MAAM,KAAK,4BAA4B,EAAE,CAAC;YAChD,OAAO;QACX,CAAC;QACD,IACI,CAAC,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;YAC3B,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,kBAAkB,CAAC,CAAC;YAC7E,CAAC,OAAQ,KAAa,CAAC,OAAO,KAAK,QAAQ;gBACtC,KAAa,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,kBAAkB,CAAC,CAAC,EAC3F,CAAC;YACC,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,IAAI,IAAK,KAAa,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAChE,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;gBACzB,IAAI,CAAC,QAAQ,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,CAC1E,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAC1C,CAAC;gBAEF,0CAA0C;gBAC1C,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;gBACpD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YAC3B,CAAC;iBAAM,CAAC;gBACJ,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACnC,CAAC;QACL,CAAC;IACL,CAAC,CAAC;IAEF,SAAS;QACL,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAC9F,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACrC,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACrC,CAAC;IACL,CAAC;IAED,UAAU;QACN,IAAI,SAAS,GAAG,EAAE,CAAC;QACnB,IAAI,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;YAC1B,IAAI,CAAC;gBACD,MAAM,kBAAkB,GAAiB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;gBAC7E,SAAS,GAAG,IAAI,IAAI,CAAC,kBAAkB,CAAC,uBAAuB,CAAC,CAAC,cAAc,EAAE,CAAC;YACtF,CAAC;YAAC,MAAM,CAAC;gBACL,SAAS;YACb,CAAC;QACL,CAAC;QAED,IAAI,KAAa,CAAC;QAClB,IAAI,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;YAC1B,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY;gBAClC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC;gBAC9C,CAAC,CAAC,IAAI,CAAC,CAAC,CACF,oBAAoB,EACpB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CACxF,CAAC;QACZ,CAAC;aAAM,CAAC;YACJ,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK;gBAC3B,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC;gBACvC,CAAC,CAAC,IAAI,CAAC,CAAC,CACF,kBAAkB,EAClB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CACxF,CAAC;QACZ,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAE5B,OAAO,CACH,6BAAK,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE;YAC/C,oBAAC,MAAM,IACH,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,EAC5B,OAAO,EAAE,IAAI,IAAI,oBAAC,WAAW,OAAG,EAChC,OAAO,EAAC,WAAW,EACnB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,IAE9B,KAAK,CACD;YACR,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAClB,6BAAK,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,IACpD,IAAI,CAAC,CAAC,CAAC,uDAAuD,CAAC,CAC9D,CACT,CAAC,CAAC,CAAC,IAAI;YACP,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CACvB,6BAAK,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,IACtD,IAAI,CAAC,KAAK,CAAC,KAAK;gBACb,CAAC,CAAC,IAAI,CAAC,CAAC,CACF,oFAAoF,EACpF,SAAS,CACZ;gBACH,CAAC,CAAC,IAAI,CAAC,CAAC,CACF,mGAAmG,EACnG,SAAS,CACZ,CACL,CACT,CAAC,CAAC,CAAC,IAAI;YACP,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAClB;gBACI,6BAAK,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE;oBAClD,8BAAM,KAAK,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE;wBAC1B,GAAG,IAAI,CAAC,CAAC,CAAC,gGAAgG,CAAC,EAAE;4BAE3G;oBACP,+BAAM;oBACN,2BACI,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,EACpC,IAAI,EAAE,IAAI,CAAC,GAAG,EACd,GAAG,EAAC,YAAY,IAEf,IAAI,CAAC,GAAG,CACT,CACF;gBACN,oBAAC,SAAS,IACN,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,EAC9B,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,uCAAuC,CAAC,EACtD,OAAO,EAAC,UAAU,EAClB,QAAQ,EAAE,CAAC,CAAC,EAAE;wBACV,IAAI,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;wBAClC,IAAI,YAAY,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;4BAChD,2BAA2B;4BAC3B,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC;wBACtC,CAAC;wBACD,IAAI,CAAC;4BACD,MAAM,kBAAkB,GAAiB,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;4BAClE,IAAI,kBAAkB,CAAC,YAAY,EAAE,CAAC;gCAClC,kBAAkB,CAAC,uBAAuB,GAAG,IAAI,IAAI,CACjD,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,kBAAkB,CAAC,UAAU,GAAG,EAAE,CAAC,GAAG,IAAI,CAC3D,CAAC,WAAW,EAAE,CAAC;gCAChB,IAAI,CAAC,QAAQ,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,EAAE,EAAE,GAAG,EAAE,CACrE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAC1C,CAAC;4BACN,CAAC;wBACL,CAAC;wBAAC,MAAM,CAAC;4BACL,SAAS;wBACb,CAAC;oBACL,CAAC,EACD,SAAS,SACX,CACH,CACN,CAAC,CAAC,CAAC,IAAI,CACN,CACT,CAAC;IACN,CAAC;CACJ","sourcesContent":["import React from 'react';\n\nimport { Button, TextField } from '@mui/material';\nimport { CloudUpload } from '@mui/icons-material';\n\nimport { I18n } from '@iobroker/adapter-react-v5';\n\nimport ConfigGeneric, { type ConfigGenericProps, type ConfigGenericState } from './ConfigGeneric';\nimport type { ConfigItemOAuth2 } from '../types';\n\ndeclare global {\n interface Window {\n attachEvent: Window['addEventListener'];\n detachEvent: Window['removeEventListener'];\n }\n}\n\ninterface ConfigOAuth2Props extends ConfigGenericProps {\n schema: ConfigItemOAuth2;\n}\n\nexport interface AccessTokens {\n access_token: string;\n expires_in: number;\n access_token_expires_on: string;\n ext_expires_in: number;\n token_type: 'Bearer';\n scope: string;\n refresh_token: string;\n}\n\ninterface ConfigOAuth2State extends ConfigGenericState {\n accessTokens: string;\n success: boolean;\n blocked: boolean;\n running: boolean;\n pressed: boolean;\n}\n\nexport default class ConfigOAuth2 extends ConfigGeneric<ConfigOAuth2Props, ConfigOAuth2State> {\n private authWindow?: WindowProxy | null;\n private readonly oid: string;\n private readonly url: string;\n\n constructor(props: ConfigOAuth2Props) {\n super(props);\n\n this.state = {\n ...this.state,\n accessTokens: '',\n success: false,\n blocked: false,\n running: false,\n pressed: false,\n };\n\n this.url = `https://oauth2.iobroker.in/${props.schema.identifier}?redirect=true`;\n if (props.schema.scope) {\n this.url += `&scope=${encodeURIComponent(props.schema.scope)}`;\n }\n\n this.oid = `${this.props.oContext.adapterName}.${this.props.oContext.instance}.${this.props.schema.saveTokenIn || 'oauth2Tokens'}`;\n }\n\n async componentDidMount(): Promise<void> {\n super.componentDidMount();\n if (window.addEventListener) {\n window.addEventListener('message', this.onMessage as any, false);\n } else {\n window.attachEvent('onmessage', this.onMessage as any, false);\n }\n\n await this.props.oContext.socket.subscribeState(this.oid, this.onTokensUpdated);\n\n // read tokens\n const tokens = await this.props.oContext.socket.getState(this.oid);\n if (tokens) {\n const accessTokens: AccessTokens = JSON.parse(tokens.val as string);\n if (new Date(accessTokens.access_token_expires_on).getTime() > Date.now()) {\n this.setState({ accessTokens: tokens.val as string });\n }\n }\n }\n\n onTokensUpdated = (_id: string, state: ioBroker.State | null | undefined): void => {\n if (state?.val) {\n const accessTokens: AccessTokens = JSON.parse(state.val as string);\n if (new Date(accessTokens.access_token_expires_on).getTime() > Date.now()) {\n if (this.state.accessTokens !== state.val) {\n this.setState({ accessTokens: state.val as string });\n }\n return;\n }\n }\n this.setState({ accessTokens: '' });\n };\n\n componentWillUnmount(): void {\n super.componentWillUnmount();\n if (window.removeEventListener) {\n window.removeEventListener('message', this.onMessage as any, false);\n } else {\n window.detachEvent('onmessage', this.onMessage as any, false);\n }\n this.props.oContext.socket.unsubscribeState(this.oid, this.onTokensUpdated);\n }\n\n saveToken(accessTokens: string): void {\n try {\n if (accessTokens && !accessTokens.startsWith('{')) {\n // convert base64 to string\n accessTokens = atob(accessTokens);\n }\n\n const accessTokensParsed: AccessTokens = JSON.parse(accessTokens);\n if (accessTokensParsed.access_token && accessTokensParsed.refresh_token && accessTokensParsed.expires_in) {\n // Give 10 seconds to user to copy the token\n accessTokensParsed.access_token_expires_on ||= new Date(\n Date.now() + accessTokensParsed.expires_in * 1000,\n ).toISOString();\n\n this.props.oContext.socket\n .setState(this.oid, JSON.stringify(accessTokensParsed), true)\n .catch((e: Error) => console.log(`Error occurred: ${e.toString()}`));\n }\n } catch (e) {\n // ignore\n console.warn(e);\n }\n }\n\n onMessage = (event: MessageEvent): void => {\n if (event.origin !== 'https://oauth2.iobroker.in') {\n return;\n }\n if (\n (typeof event.data === 'string' &&\n event.data.startsWith(`${this.props.schema.identifier}-authentication:`)) ||\n (typeof (event as any).message === 'string' &&\n (event as any).message.startsWith(`${this.props.schema.identifier}-authentication:`))\n ) {\n const parts = (event.data || (event as any).message).split(':');\n if (parts[1] === 'success') {\n this.setState({ accessTokens: parts[2], success: true, pressed: false }, () =>\n this.saveToken(this.state.accessTokens),\n );\n\n // send message to auth window to close it\n this.authWindow?.postMessage('close', event.origin);\n this.authWindow = null;\n } else {\n this.props.onError?.(parts[2]);\n }\n }\n };\n\n onOpenUrl(): void {\n this.authWindow = window.open(this.url, this.props.schema.identifier);\n if (!this.authWindow || this.authWindow.closed || typeof this.authWindow.closed === 'undefined') {\n this.setState({ blocked: true });\n } else {\n this.setState({ pressed: true });\n }\n }\n\n renderItem(): React.JSX.Element {\n let validTill = '';\n if (this.state.accessTokens) {\n try {\n const accessTokensParsed: AccessTokens = JSON.parse(this.state.accessTokens);\n validTill = new Date(accessTokensParsed.access_token_expires_on).toLocaleString();\n } catch {\n // ignore\n }\n }\n\n let label: string;\n if (this.state.accessTokens) {\n label = this.props.schema.refreshLabel\n ? this.getText(this.props.schema.refreshLabel)\n : I18n.t(\n 'ra_Renew %s access',\n this.props.schema.identifier[0].toUpperCase() + this.props.schema.identifier.slice(1),\n );\n } else {\n label = this.props.schema.label\n ? this.getText(this.props.schema.label)\n : I18n.t(\n 'ra_Get %s access',\n this.props.schema.identifier[0].toUpperCase() + this.props.schema.identifier.slice(1),\n );\n }\n const icon = this.getIcon();\n\n return (\n <div style={{ width: '100%', margin: '0 0 1rem 0' }}>\n <Button\n disabled={this.state.running}\n endIcon={icon || <CloudUpload />}\n variant=\"contained\"\n onClick={() => this.onOpenUrl()}\n >\n {label}\n </Button>\n {this.state.blocked ? (\n <div style={{ color: 'red', fontSize: 16, marginTop: 20 }}>\n {I18n.t('ra_Please allow popups in your browser for this page!')}\n </div>\n ) : null}\n {this.state.accessTokens ? (\n <div style={{ color: 'green', fontSize: 16, marginTop: 20 }}>\n {this.props.alive\n ? I18n.t(\n 'ra_Successfully authorized. Token valid till %s and will be automatically renewed.',\n validTill,\n )\n : I18n.t(\n 'ra_Successfully authorized. Token valid till %s but it can expire as the instance is not running.',\n validTill,\n )}\n </div>\n ) : null}\n {this.state.pressed ? (\n <>\n <div style={{ width: '100%', margin: '1rem 0 1rem 0' }}>\n <span style={{ marginRight: 4 }}>\n {`${I18n.t('ra_If the button above does not work, you can authorize manually this app by visiting this url')}`}\n :\n </span>\n <br />\n <a\n target={this.props.schema.identifier}\n href={this.url}\n rel=\"noreferrer\"\n >\n {this.url}\n </a>\n </div>\n <TextField\n value={this.state.accessTokens}\n label={I18n.t('ra_Enter the code from that page here')}\n variant=\"standard\"\n onChange={e => {\n let accessTokens = e.target.value;\n if (accessTokens && !accessTokens.startsWith('{')) {\n // convert base64 to string\n accessTokens = atob(accessTokens);\n }\n try {\n const accessTokensParsed: AccessTokens = JSON.parse(accessTokens);\n if (accessTokensParsed.access_token) {\n accessTokensParsed.access_token_expires_on = new Date(\n Date.now() + (accessTokensParsed.expires_in - 10) * 1000,\n ).toISOString();\n this.setState({ accessTokens: JSON.stringify(accessTokensParsed) }, () =>\n this.saveToken(this.state.accessTokens),\n );\n }\n } catch {\n // ignore\n }\n }}\n fullWidth\n />\n </>\n ) : null}\n </div>\n );\n }\n}\n"]}
1
+ {"version":3,"file":"ConfigOAuth2.js","sourceRoot":"./src/","sources":["JsonConfigComponent/ConfigOAuth2.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\n\nimport { Button, IconButton, TextField } from '@mui/material';\nimport { Close as CloseIcon, CloudUpload } from '@mui/icons-material';\n\nimport { I18n } from '@iobroker/adapter-react-v5';\n\nimport ConfigGeneric, { type ConfigGenericProps, type ConfigGenericState } from './ConfigGeneric';\nimport type { ConfigItemOAuth2 } from '../types';\n\ndeclare global {\n interface Window {\n attachEvent: Window['addEventListener'];\n detachEvent: Window['removeEventListener'];\n }\n}\n\ninterface ConfigOAuth2Props extends ConfigGenericProps {\n schema: ConfigItemOAuth2;\n}\n\nexport interface AccessTokens {\n access_token: string;\n expires_in: number;\n access_token_expires_on: string;\n ext_expires_in: number;\n token_type: 'Bearer';\n scope: string;\n refresh_token: string;\n}\n\ninterface ConfigOAuth2State extends ConfigGenericState {\n accessTokens: string;\n success: boolean;\n blocked: boolean;\n running: boolean;\n pressed: boolean;\n clientId: string;\n clientSecret: string;\n}\n\nexport default class ConfigOAuth2 extends ConfigGeneric<ConfigOAuth2Props, ConfigOAuth2State> {\n private authWindow?: WindowProxy | null;\n private readonly oid: string;\n private readonly url: string;\n\n constructor(props: ConfigOAuth2Props) {\n super(props);\n\n this.state = {\n ...this.state,\n accessTokens: '',\n success: false,\n blocked: false,\n running: false,\n pressed: false,\n clientId: '',\n clientSecret: '',\n };\n\n this.url = `https://oauth2.iobroker.in/${props.schema.identifier}?redirect=true`;\n if (props.schema.scope) {\n this.url += `&scope=${encodeURIComponent(props.schema.scope)}`;\n }\n\n this.oid = `${this.props.oContext.adapterName}.${this.props.oContext.instance}.${this.props.schema.saveTokenIn || 'oauth2Tokens'}`;\n }\n\n async componentDidMount(): Promise<void> {\n super.componentDidMount();\n if (window.addEventListener) {\n window.addEventListener('message', this.onMessage as any, false);\n } else {\n window.attachEvent('onmessage', this.onMessage as any, false);\n }\n\n await this.props.oContext.socket.subscribeState(this.oid, this.onTokensUpdated);\n\n let state: Partial<ConfigOAuth2State> | undefined;\n if (this.props.schema.ownClientId) {\n state = { clientId: ConfigGeneric.getValue(this.props.data, this.props.schema.ownClientId) };\n }\n if (this.props.schema.ownClientId) {\n state ||= {};\n state.clientSecret = ConfigGeneric.getValue(this.props.data, this.props.schema.ownClientSecret);\n }\n\n // read tokens\n const tokens = await this.props.oContext.socket.getState(this.oid);\n if (tokens) {\n const accessTokens: AccessTokens = JSON.parse(tokens.val as string);\n if (new Date(accessTokens.access_token_expires_on).getTime() > Date.now()) {\n state ||= {};\n state.accessTokens = tokens.val as string;\n }\n }\n if (state) {\n this.setState(state as ConfigOAuth2State);\n }\n }\n\n onTokensUpdated = (_id: string, state: ioBroker.State | null | undefined): void => {\n if (state?.val) {\n const accessTokens: AccessTokens = JSON.parse(state.val as string);\n if (new Date(accessTokens.access_token_expires_on).getTime() > Date.now()) {\n if (this.state.accessTokens !== state.val) {\n this.setState({ accessTokens: state.val as string });\n }\n return;\n }\n }\n this.setState({ accessTokens: '' });\n };\n\n componentWillUnmount(): void {\n super.componentWillUnmount();\n if (window.removeEventListener) {\n window.removeEventListener('message', this.onMessage as any, false);\n } else {\n window.detachEvent('onmessage', this.onMessage as any, false);\n }\n this.props.oContext.socket.unsubscribeState(this.oid, this.onTokensUpdated);\n }\n\n saveToken(accessTokens: string): void {\n try {\n if (accessTokens && !accessTokens.startsWith('{')) {\n // convert base64 to string\n accessTokens = atob(accessTokens);\n }\n\n const accessTokensParsed: AccessTokens = JSON.parse(accessTokens);\n if (accessTokensParsed.access_token && accessTokensParsed.refresh_token && accessTokensParsed.expires_in) {\n // Give 10 seconds to user to copy the token\n accessTokensParsed.access_token_expires_on ||= new Date(\n Date.now() + accessTokensParsed.expires_in * 1000,\n ).toISOString();\n\n this.props.oContext.socket\n .setState(this.oid, JSON.stringify(accessTokensParsed), true)\n .catch((e: Error) => console.log(`Error occurred: ${e.toString()}`));\n }\n } catch (e) {\n // ignore\n console.warn(e);\n }\n }\n\n onMessage = (event: MessageEvent): void => {\n if (event.origin !== 'https://oauth2.iobroker.in') {\n return;\n }\n if (\n (typeof event.data === 'string' &&\n event.data.startsWith(`${this.props.schema.identifier}-authentication:`)) ||\n (typeof (event as any).message === 'string' &&\n (event as any).message.startsWith(`${this.props.schema.identifier}-authentication:`))\n ) {\n const parts = (event.data || (event as any).message).split(':');\n if (parts[1] === 'success') {\n this.setState({ accessTokens: parts[2], success: true, pressed: false }, () =>\n this.saveToken(this.state.accessTokens),\n );\n\n // send message to auth window to close it\n this.authWindow?.postMessage('close', event.origin);\n this.authWindow = null;\n } else {\n this.props.onError?.(parts[2]);\n }\n }\n };\n\n onOpenUrl(): void {\n this.authWindow = window.open(\n this.url + (this.props.schema.ownClientId ? `&clientId=${encodeURIComponent(this.state.clientId)}` : ''),\n this.props.schema.identifier,\n );\n if (!this.authWindow || this.authWindow.closed || typeof this.authWindow.closed === 'undefined') {\n this.setState({ blocked: true });\n } else {\n this.setState({ pressed: true });\n }\n }\n\n renderItem(_error?: boolean, disabled?: boolean): React.JSX.Element {\n let validTill = '';\n if (this.state.accessTokens) {\n try {\n const accessTokensParsed: AccessTokens = JSON.parse(this.state.accessTokens);\n validTill = new Date(accessTokensParsed.access_token_expires_on).toLocaleString();\n } catch {\n // ignore\n }\n }\n\n let label: string;\n if (this.state.accessTokens) {\n label = this.props.schema.refreshLabel\n ? this.getText(this.props.schema.refreshLabel)\n : I18n.t(\n 'ra_Renew %s access',\n this.props.schema.identifier[0].toUpperCase() + this.props.schema.identifier.slice(1),\n );\n } else {\n label = this.props.schema.label\n ? this.getText(this.props.schema.label)\n : I18n.t(\n 'ra_Get %s access',\n this.props.schema.identifier[0].toUpperCase() + this.props.schema.identifier.slice(1),\n );\n }\n const icon = this.getIcon();\n\n return (\n <div style={{ width: '100%', margin: '0 0 1rem 0' }}>\n {this.props.schema.ownClientId ? (\n <TextField\n value={this.state.clientId}\n onChange={e => {\n const value = e.target.value;\n\n this.setState({ clientId: value }, () =>\n this.onChange(this.props.schema.ownClientId, value),\n );\n }}\n variant=\"standard\"\n fullWidth\n error={!this.state.clientId}\n disabled={!!disabled}\n label={I18n.t('ra_OAuth Client ID')}\n slotProps={{\n input: {\n endAdornment: this.state.clientId ? (\n <IconButton\n size=\"small\"\n tabIndex={-1}\n onClick={() =>\n this.setState({ clientId: '' }, () =>\n this.onChange(this.props.schema.ownClientId, ''),\n )\n }\n >\n <CloseIcon />\n </IconButton>\n ) : null,\n },\n }}\n />\n ) : null}\n {this.props.schema.ownClientSecret ? (\n <TextField\n value={this.state.clientSecret}\n onChange={e => {\n const value = e.target.value;\n\n this.setState({ clientSecret: value }, () =>\n this.onChange(this.props.schema.ownClientSecret, value),\n );\n }}\n variant=\"standard\"\n fullWidth\n error={!this.state.clientSecret}\n disabled={!!disabled}\n label={I18n.t('ra_OAuth Client secret')}\n slotProps={{\n input: {\n endAdornment: this.state.clientSecret ? (\n <IconButton\n size=\"small\"\n tabIndex={-1}\n onClick={() =>\n this.setState({ clientSecret: '' }, () =>\n this.onChange(this.props.schema.ownClientSecret, ''),\n )\n }\n >\n <CloseIcon />\n </IconButton>\n ) : null,\n },\n }}\n />\n ) : null}\n <Button\n disabled={\n this.state.running ||\n (this.props.schema.ownClientSecret && !this.state.clientSecret) ||\n (this.props.schema.ownClientId && !this.state.clientId)\n }\n endIcon={icon || <CloudUpload />}\n variant=\"contained\"\n onClick={() => this.onOpenUrl()}\n >\n {label}\n </Button>\n {this.state.blocked ? (\n <div style={{ color: 'red', fontSize: 16, marginTop: 20 }}>\n {I18n.t('ra_Please allow popups in your browser for this page!')}\n </div>\n ) : null}\n {this.state.accessTokens ? (\n <div style={{ color: 'green', fontSize: 16, marginTop: 20 }}>\n {this.props.alive\n ? I18n.t(\n 'ra_Successfully authorized. Token valid till %s and will be automatically renewed.',\n validTill,\n )\n : I18n.t(\n 'ra_Successfully authorized. Token valid till %s but it can expire as the instance is not running.',\n validTill,\n )}\n </div>\n ) : null}\n {this.state.pressed ? (\n <>\n <div style={{ width: '100%', margin: '1rem 0 1rem 0' }}>\n <span style={{ marginRight: 4 }}>\n {`${I18n.t('ra_If the button above does not work, you can authorize manually this app by visiting this url')}`}\n :\n </span>\n <br />\n <a\n target={this.props.schema.identifier}\n href={this.url}\n rel=\"noreferrer\"\n >\n {this.url}\n </a>\n </div>\n <TextField\n value={this.state.accessTokens}\n label={I18n.t('ra_Enter the code from that page here')}\n variant=\"standard\"\n onChange={e => {\n let accessTokens = e.target.value;\n if (accessTokens && !accessTokens.startsWith('{')) {\n // convert base64 to string\n accessTokens = atob(accessTokens);\n }\n try {\n const accessTokensParsed: AccessTokens = JSON.parse(accessTokens);\n if (accessTokensParsed.access_token) {\n accessTokensParsed.access_token_expires_on = new Date(\n Date.now() + (accessTokensParsed.expires_in - 10) * 1000,\n ).toISOString();\n this.setState({ accessTokens: JSON.stringify(accessTokensParsed) }, () =>\n this.saveToken(this.state.accessTokens),\n );\n }\n } catch {\n // ignore\n }\n }}\n fullWidth\n />\n </>\n ) : null}\n </div>\n );\n }\n}\n"]}
package/build/types.d.ts CHANGED
@@ -363,6 +363,8 @@ export interface ConfigItemOAuth2 extends ConfigItem {
363
363
  // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
364
364
  identifier: 'spotify' | 'google' | 'dropbox' | 'microsoft' | string;
365
365
  scope?: string; // optional scopes divided by space, e.g. `user-read-private user-read-email`
366
+ ownClientId?: string; // Optional. User can provide own Client ID and this is a attribut name where the client ID must be stored
367
+ ownClientSecret?: string; // Optional. User can provide own Client secret and this is a attribut name where the client secret must be stored
366
368
  refreshLabel?: ioBroker.StringOrTranslated; // label for the refresh button
367
369
  }
368
370
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@iobroker/json-config",
3
3
  "description": "This package contains the ioBroker JSON config UI components",
4
- "version": "8.2.11",
4
+ "version": "8.2.12",
5
5
  "author": {
6
6
  "name": "bluefox",
7
7
  "email": "dogafox@gmail.com"
@@ -35,7 +35,7 @@
35
35
  "access": "public"
36
36
  },
37
37
  "dependencies": {
38
- "@iobroker/adapter-react-v5": "^8.1.3",
38
+ "@iobroker/adapter-react-v5": "^8.1.5",
39
39
  "@module-federation/runtime": "^2.1.0",
40
40
  "@mui/x-date-pickers": "^7.29.4",
41
41
  "crypto-js": "^4.2.0",