mirror of
https://github.com/tsightler/ring-mqtt.git
synced 2025-09-27 05:05:54 +08:00

Hide errors immediately on submit Clear secure info immediately on submit Clear password immediately on successful auth
119 lines
3.6 KiB
JavaScript
119 lines
3.6 KiB
JavaScript
import { RingRestClient } from 'ring-client-api/rest-client'
|
|
import utils from './utils.js'
|
|
import express from 'express'
|
|
import bodyParser from 'body-parser'
|
|
import chalk from 'chalk'
|
|
import debugModule from 'debug'
|
|
import { webTemplate } from './web-template.js'
|
|
|
|
const debug = debugModule('ring-mqtt')
|
|
|
|
class WebService {
|
|
constructor() {
|
|
this.app = express()
|
|
this.listener = null
|
|
this.ringConnected = false
|
|
this.initializeEventListeners()
|
|
}
|
|
|
|
initializeEventListeners() {
|
|
utils.event.on('ring_api_state', async (state) => {
|
|
this.ringConnected = state === 'connected'
|
|
|
|
if (this.ringConnected && process.env.RUNMODE !== 'addon') {
|
|
await this.stop()
|
|
}
|
|
})
|
|
}
|
|
|
|
async handleAccountSubmission(req, res, restClient) {
|
|
try {
|
|
await restClient.getCurrentAuth()
|
|
res.json({ success: true })
|
|
} catch (error) {
|
|
if (restClient.using2fa) {
|
|
debug('Username/Password was accepted, waiting for 2FA code to be entered.')
|
|
res.json({ requires2fa: true })
|
|
} else {
|
|
const errorMessage = error.message || 'Null response, you may be temporarily throttled/blocked. Please shut down ring-mqtt and try again in a few hours.'
|
|
debug(chalk.red(errorMessage))
|
|
res.status(400).json({ error: errorMessage })
|
|
}
|
|
}
|
|
}
|
|
|
|
async handleCodeSubmission(req, res, restClient) {
|
|
try {
|
|
const generatedToken = await restClient.getAuth(req.body.code)
|
|
if (generatedToken) {
|
|
utils.event.emit('generated_token', generatedToken.refresh_token)
|
|
res.json({ success: true })
|
|
}
|
|
} catch (error) {
|
|
const errorMessage = error.message || 'The 2FA code was not accepted, please verify the code and try again.'
|
|
debug(chalk.red(errorMessage))
|
|
res.status(400).json({ error: errorMessage })
|
|
}
|
|
}
|
|
|
|
setupRoutes() {
|
|
let restClient
|
|
this.app.use(bodyParser.urlencoded({ extended: false }))
|
|
this.app.use(bodyParser.json())
|
|
|
|
const router = express.Router()
|
|
|
|
router.get('/get-state', (req, res) => {
|
|
res.json({
|
|
connected: this.ringConnected,
|
|
displayName: this.displayName
|
|
})
|
|
})
|
|
|
|
router.post('/submit-account', async (req, res) => {
|
|
restClient = new RingRestClient({
|
|
email: req.body.email,
|
|
password: req.body.password,
|
|
controlCenterDisplayName: this.displayName,
|
|
systemId: this.systemId
|
|
})
|
|
await this.handleAccountSubmission(req, res, restClient)
|
|
})
|
|
|
|
router.post('/submit-code', async (req, res) => {
|
|
await this.handleCodeSubmission(req, res, restClient)
|
|
})
|
|
|
|
// Mount router at base URL
|
|
this.app.use('/', router)
|
|
|
|
// Serve the static HTML
|
|
this.app.get('*', (req, res) => {
|
|
res.send(webTemplate)
|
|
})
|
|
}
|
|
|
|
async start(systemId) {
|
|
if (this.listener) {
|
|
return
|
|
}
|
|
|
|
this.systemId = systemId
|
|
this.displayName = `${process.env.RUNMODE === 'addon' ? 'ring-mqtt-addon' : 'ring-mqtt'}-${systemId.slice(-5)}`
|
|
|
|
this.setupRoutes()
|
|
|
|
this.listener = this.app.listen(55123, () => {
|
|
debug('Successfully started the ring-mqtt web UI')
|
|
})
|
|
}
|
|
|
|
async stop() {
|
|
if (this.listener) {
|
|
await this.listener.close()
|
|
this.listener = null
|
|
}
|
|
}
|
|
}
|
|
|
|
export default new WebService() |