diff --git a/plugins/alexa/.vscode/settings.json b/plugins/alexa/.vscode/settings.json index 3a74f5bd0b..964a62559e 100644 --- a/plugins/alexa/.vscode/settings.json +++ b/plugins/alexa/.vscode/settings.json @@ -1,4 +1,4 @@ { - "scrypted.debugHost": "10.10.0.51", + "scrypted.debugHost": "scrypted-server", } \ No newline at end of file diff --git a/plugins/alexa/CHANGELOG.md b/plugins/alexa/CHANGELOG.md new file mode 100644 index 0000000000..db7ff27632 --- /dev/null +++ b/plugins/alexa/CHANGELOG.md @@ -0,0 +1,148 @@ +
+Changelog + +### 0.3.0 + +alexa/google-home: additional auth token checks to harden endpoints for cloud sharing +alexa: removed unneeded packages (#1319) +alexa: added support for `light`, `outlet`, and `fan` device types (#1318) + + +### 0.2.10 + +alexa: fix potential response race + + +### 0.2.9 + +alexa: fix race condition in sendResponse + + +### 0.2.8 + +alexa: display camera on doorbell press (#1066) + + +### 0.2.7 + +alexa: added helpful error messages regarding token expiration (#1007) + + +### 0.2.6 + +alexa: fix doorbells + + +### 0.2.5 + +alexa: publish w/ storage fix + + +### 0.2.4 + +alexa: add setting to publish debug events to console (#685) + + +### 0.2.3 + +webrtc/alexa: add option to disable TURN on peers that already have externally reachable addresses + + +### 0.2.1 + +alexa: set screen ratio to 720p (#625) + + +### 0.2.0 + +alexa: refactor code structure (#606) + + +### 0.1.0 + +alexa: ensure we are talking to the correct API endpoint (#580) + + +### 0.0.20 + +alexa: provide hint that medium resolution is always used. + + +### 0.0.19 + +various: minor cleanups +alexa: added logging around `tokenInfo` resets (#488) +sdk: rename sdk.version to sdk.serverVersion +plugins: update tsconfig.json +alexa: publish beta + + +### 0.0.18 + +alexa: rethrow login failure error +added support for type `Garage` and refactored the controller for future support (#479) +updated install instructions (#478) +webrtc/alexa: fix race condition with intercoms and track not received yet. + + +### 0.0.17 + +alexa: close potential security hole if scrypted is exposed to the internet directly (ie, user is not using the cloud plugin against recommendations) + + +### 0.0.16 + +plugins: remove postinstall +plugins: add tsconfig.json +alexa: doorbell motion sensor support + + +### 0.0.15 + +alexa: fix harmless crash in log + + +### 0.0.14 + +alexa: fix empty endpoint list + + +### 0.0.13 + +all: prune package.json +alexa: fix doorbell syncing + + +### 0.0.12 + +alexa: publish + + +### 0.0.10 + +alexa: 2 way audio + + +### 0.0.4 + +alexa: 2 way audio +alexa: motion events + + +### 0.0.3 + +webrtc: refactor +alexa: use rtc signaling channel +alexa: publish + + +### 0.0.1 + +alexa: doorbells +alexa: sync devices properly +alexa: add camera/doorbell, fix webrtc to work with amazon reqs +alexa: initial pass with working cameras +cloud: stub out alexa + + +
diff --git a/plugins/alexa/package-lock.json b/plugins/alexa/package-lock.json index 73897acf1c..75b5681305 100644 --- a/plugins/alexa/package-lock.json +++ b/plugins/alexa/package-lock.json @@ -1,12 +1,12 @@ { "name": "@scrypted/alexa", - "version": "0.3.0", + "version": "0.3.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@scrypted/alexa", - "version": "0.3.0", + "version": "0.3.1", "dependencies": { "axios": "^1.3.4", "uuid": "^9.0.0" diff --git a/plugins/alexa/package.json b/plugins/alexa/package.json index 0cab56cbee..69882940b5 100644 --- a/plugins/alexa/package.json +++ b/plugins/alexa/package.json @@ -1,6 +1,6 @@ { "name": "@scrypted/alexa", - "version": "0.3.0", + "version": "0.3.1", "scripts": { "scrypted-setup-project": "scrypted-setup-project", "prescrypted-setup-project": "scrypted-package-json", diff --git a/plugins/alexa/src/main.ts b/plugins/alexa/src/main.ts index 3b905ad56f..7c72913fc8 100644 --- a/plugins/alexa/src/main.ts +++ b/plugins/alexa/src/main.ts @@ -47,7 +47,11 @@ class AlexaPlugin extends ScryptedDeviceBase implements HttpRequestHandler, Mixi onPut(oldValue: boolean, newValue: boolean) { DEBUG = newValue; } - } + }, + pairedUserId: { + title: "Pairing Key", + description: "The pairing key used to validate requests from Alexa. Clear this key or delete the plugin to allow pairing with a different Alexa login.", + }, }); accessToken: Promise; @@ -608,6 +612,13 @@ class AlexaPlugin extends ScryptedDeviceBase implements HttpRequestHandler, Mixi // validate this. old tokens will be grandfathered in. if (getcookieResponse.data.expiry && getcookieResponse.data.clientId !== 'amazon') throw new Error('client id mismatch'); + if (!this.storageSettings.values.pairedUserId) { + this.storageSettings.values.pairedUserId = getcookieResponse.data.id; + } + else if (this.storageSettings.values.pairedUserId !== getcookieResponse.data.id) { + this.log.a('This plugin is already paired with a different account. Clear the existing key in the plugin settings to pair this plugin with a different account.'); + throw new Error('user id mismatch'); + } this.validAuths.add(authorization); } catch (e) { diff --git a/plugins/google-home/.vscode/settings.json b/plugins/google-home/.vscode/settings.json index 44d4d203fc..964a62559e 100644 --- a/plugins/google-home/.vscode/settings.json +++ b/plugins/google-home/.vscode/settings.json @@ -1,4 +1,4 @@ { - "scrypted.debugHost": "koushik-ubuntu", + "scrypted.debugHost": "scrypted-server", } \ No newline at end of file diff --git a/plugins/google-home/package-lock.json b/plugins/google-home/package-lock.json index a51ab1fec6..51894042b5 100644 --- a/plugins/google-home/package-lock.json +++ b/plugins/google-home/package-lock.json @@ -1,12 +1,12 @@ { "name": "@scrypted/google-home", - "version": "0.0.56", + "version": "0.0.57", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@scrypted/google-home", - "version": "0.0.56", + "version": "0.0.57", "dependencies": { "@googleapis/homegraph": "^2.0.0", "@homebridge/ciao": "^1.1.5", diff --git a/plugins/google-home/package.json b/plugins/google-home/package.json index 6e3acb4aa9..da8b10a318 100644 --- a/plugins/google-home/package.json +++ b/plugins/google-home/package.json @@ -25,7 +25,8 @@ "interfaces": [ "HttpRequestHandler", "EngineIOHandler", - "MixinProvider" + "MixinProvider", + "Settings" ], "pluginDependencies": [ "@scrypted/cloud", @@ -48,5 +49,5 @@ "@types/lodash": "^4.14.168", "@types/url-parse": "^1.4.3" }, - "version": "0.0.56" + "version": "0.0.57" } diff --git a/plugins/google-home/src/main.ts b/plugins/google-home/src/main.ts index a1c553033a..0e2f69ae2b 100644 --- a/plugins/google-home/src/main.ts +++ b/plugins/google-home/src/main.ts @@ -1,5 +1,5 @@ import type { homegraph_v1 } from "@googleapis/homegraph/v1"; -import sdk, { EngineIOHandler, HttpRequest, HttpRequestHandler, HttpResponse, MixinProvider, Refresh, ScryptedDevice, ScryptedDeviceBase, ScryptedDeviceType, ScryptedInterface, ScryptedInterfaceProperty } from '@scrypted/sdk'; +import sdk, { EngineIOHandler, HttpRequest, HttpRequestHandler, HttpResponse, MixinProvider, Refresh, ScryptedDevice, ScryptedDeviceBase, ScryptedDeviceType, ScryptedInterface, ScryptedInterfaceProperty, Setting, SettingValue, Settings } from '@scrypted/sdk'; import type { SmartHomeV1DisconnectRequest, SmartHomeV1DisconnectResponse, SmartHomeV1ExecuteRequest, SmartHomeV1ExecuteResponse, SmartHomeV1ExecuteResponseCommands } from 'actions-on-google/dist/service/smarthome/api/v1'; import axios from 'axios'; import { GoogleAuth } from "google-auth-library"; @@ -8,6 +8,7 @@ import throttle from 'lodash/throttle'; import './commands'; import { supportedTypes } from './common'; import './types'; +import { StorageSettings } from '@scrypted/sdk/storage-settings'; import { canAccess } from './commands/camerastream'; import { commandHandlers } from './handlers'; @@ -44,10 +45,36 @@ const googleAuth = new GoogleAuth({ const includeToken = 3; -class GoogleHome extends ScryptedDeviceBase implements HttpRequestHandler, EngineIOHandler, MixinProvider { - linkTracker = localStorage.getItem('linkTracker'); - agentUserId = localStorage.getItem('agentUserId'); - localAuthorization = localStorage.getItem('localAuthorization'); +class GoogleHome extends ScryptedDeviceBase implements HttpRequestHandler, EngineIOHandler, MixinProvider, Settings { + storageSettings = new StorageSettings(this, { + // the tracker tracks whether this device has been reported in a sync request payload. + // this is because reporting too many devices in the initial sync fails upstream at google. + linkTracker: { + hide: true, + persistedDefaultValue: Math.random().toString(), + }, + agentUserId: { + hide: true, + persistedDefaultValue: uuidv4(), + }, + localAuthorization: { + hide: true, + persistedDefaultValue: uuidv4(), + }, + pairedUserId: { + title: "Pairing Key", + description: "The pairing key used to validate requests from Google Home. Clear this key or delete the plugin to allow pairing with a different Google Home login.", + }, + }); + get linkTracker() { + return this.storageSettings.values.linkTracker; + } + get agentUserId() { + return this.storageSettings.values.agentUserId; + } + get localAuthorization() { + return this.storageSettings.values.localAuthorization; + } reportQueue = new Set(); reportStateThrottled = throttle(() => this.reportState(), 2000); throttleSync = throttle(() => this.requestSync(), 15000, { @@ -71,23 +98,6 @@ class GoogleHome extends ScryptedDeviceBase implements HttpRequestHandler, Engin this.googleAuthClient = googleAuth.fromJSON(this.jwt); } - // the tracker tracks whether this device has been reported in a sync request payload. - // this is because reporting too many devices in the initial sync fails upstream at google. - if (!this.linkTracker) { - this.linkTracker = Math.random().toString(); - localStorage.setItem('linkTracker', this.linkTracker); - } - - if (!this.agentUserId) { - this.agentUserId = uuidv4(); - localStorage.setItem('agentUserId', this.agentUserId); - } - - if (!this.localAuthorization) { - this.localAuthorization = uuidv4(); - localStorage.setItem('localAuthorization', this.localAuthorization); - } - try { this.defaultIncluded = JSON.parse(localStorage.getItem('defaultIncluded')); } @@ -150,6 +160,14 @@ class GoogleHome extends ScryptedDeviceBase implements HttpRequestHandler, Engin }); } + getSettings(): Promise { + return this.storageSettings.getSettings(); + } + + putSetting(key: string, value: SettingValue): Promise { + return this.storageSettings.putSetting(key, value); + } + async isSyncable(device: ScryptedDevice): Promise { const plugins = await this.plugins; const mixins = (device.mixins || []).slice(); @@ -528,6 +546,13 @@ class GoogleHome extends ScryptedDeviceBase implements HttpRequestHandler, Engin // validate this. old tokens will be grandfathered in. if (getcookieResponse.data.expiry && getcookieResponse.data.clientId !== 'google') throw new Error('client id mismatch'); + if (!this.storageSettings.values.pairedUserId) { + this.storageSettings.values.pairedUserId = getcookieResponse.data.id; + } + else if (this.storageSettings.values.pairedUserId !== getcookieResponse.data.id) { + this.log.a('This plugin is already paired with a different account. Clear the existing key in the plugin settings to pair this plugin with a different account.'); + throw new Error('user id mismatch'); + } this.validAuths.add(authorization); } catch (e) { diff --git a/plugins/google-home/tsconfig.json b/plugins/google-home/tsconfig.json index 34a847ad82..ba9b4d395b 100644 --- a/plugins/google-home/tsconfig.json +++ b/plugins/google-home/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "module": "commonjs", + "module": "Node16", "target": "ES2021", "resolveJsonModule": true, "moduleResolution": "Node16",