@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`
|
|
545
|
-
| `saveTokenIn`
|
|
546
|
-
| `scope`
|
|
547
|
-
| `refreshLabel`
|
|
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
|
-
|
|
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(
|
|
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":"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","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.
|
|
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.
|
|
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",
|