127.0.0.1:8000 smart-home-server / master init_hue_auth.js
master

Tree @master (Download .tar.gz)

init_hue_auth.js @masterraw · history · blame

require('dotenv').config();
const {
    v4: uuid
} = require('uuid');
const mysql = require('mysql');
const v3 = require('node-hue-api').v3;
const axios = require('axios');
const utils = require('./server/utils');
const hue_auth = require('./server/utils/hue/auth');

// Values for the ClientId, ClientSecret and AppId from the Hue Remote Application you create in your developer account.
const APP_ID = 'smart-home-server';
const remoteBootstrap = v3.api.createRemote(
    process.env.HUE_CLIENT_ID,
    process.env.HUE_CLIENT_SECRET
);

global.MYSQL_POOL = mysql.createPool({
    connectionLimit: 10,
    host: 'localhost',
    user: process.env.SQL_USER,
    password: process.env.SQL_PASS,
    database: 'smart_home'
});

console.log("Start Philips Hue authentication...");
// A state value you can use to validate the Callback URL results with, it should not really be hardcoded, but should
// be dynamically generated.

let state;

utils.query("SELECT state from hue_auth").then(function(rows) {
    if (rows.length) {
        state = rows[0].state;
        if (!state) {
            state = uuid();
            console.log("New transaction state:", state);
        } else {
            console.log("Transaction state restored:", state);
        }
        return "UPDATE";
    } else {
        state = uuid();
        return "INSERT INTO";
    }
}).then(function(command) {
    return utils.query(`${command} hue_auth SET ?`, {
        state: state
    });
}).then(function() {
    return utils.query("SELECT auth_code FROM hue_auth");
}).then(function(rows) {
    return new Promise(function(resolve, reject) {
        let authorizationCode;
        if (rows.length) {
            authorizationCode = rows[0].auth_code;
        }
        if (authorizationCode) {
            resolve(authorizationCode);
        } else {
            reject(
                "Generate an authorization code for your application using this URL:\n\n" +
                remoteBootstrap.getAuthCodeUrl('node-hue-api-remote', APP_ID, state) + "\n"
            );
        }
    });
}).then(function(authorizationCode) {
    // Exchange the code for tokens and connect to the Remote Hue API
    return remoteBootstrap.connectWithCode(authorizationCode);
}).then(function(api) {
    console.log('Successfully validated authorization code and exchanged for tokens');
    const remoteCredentials = api.remote.getRemoteAccessCredentials();
    return hue_auth.store_auth({
        access_token: remoteCredentials.tokens.access.value,
        access_token_expires: remoteCredentials.tokens.access.expiresAt,
        refresh_token: remoteCredentials.tokens.refresh.value,
        refresh_token_expires: remoteCredentials.tokens.refresh.expiresAt,
        username: remoteCredentials.username,
        auth_code: null
    });
}).then(function() {
    console.log("Philips Hue authentication obtained");
    return axios.post(`http://localhost:${process.env.PORT || 4669}/hue/reauthenticate`, {
        state: state
    });
}).then(function(response) {
    if (response.data.status === "ok") {
        console.log("Smarthome Server successfully reauthenticated with Philips Hue");
    } else {
        console.log("Smarthome Server could not automatically reauthenticate with Philips Hue\n", response.data.message);
    }

    return utils.query("UPDATE hue_auth SET ?", {
        state: null
    });
}).then(function() {
    console.log("Philips Hue authentication successful");
}).catch(function(err) {
    console.log('Philips Hue authentication unsuccessful. Reason:\n', err);
    return utils.query("DELETE FROM hue_auth");
}).finally(function() {
    process.exit(0);
});