/** * Import vendor modules */ const unifi = require('node-unifi'); /** * Import own modules */ const variables = require('./variables'); const log = require('./log'); /** * UniFi Settings */ const settings = { ip: variables.unifiIp, port: variables.unifiPort, username: variables.unifiUsername, password: variables.unifiPassword, siteID: variables.unifiSiteId }; /** * Controller session */ let controller = null; /** * Start a UniFi controller reusable session * * @return {Promise} */ const startSession = () => { return new Promise((resolve, reject) => { // Check if we have a current session already if(controller !== null) { resolve(); return; } if(settings.username.includes('@')) { reject('[UniFi] Incorrect username detected! UniFi Cloud credentials are not supported!'); return; } // Create new UniFi controller object controller = new unifi.Controller({ host: settings.ip, port: settings.port, site: settings.siteID, sslverify: false }); // Login to UniFi Controller controller.login(settings.username, settings.password).then(() => { log.debug('[UniFi] Login successful!'); resolve(); }).catch((e) => { // Something went wrong so clear the current controller so a user can retry controller = null; log.error('[UniFi] Error while logging in!'); log.debug(e); reject('[UniFi] Error while logging in!'); }); }); } /** * UniFi module functions * * @type {{create: (function(*, number=, null=, boolean=): Promise<*>), remove: (function(*, boolean=): Promise<*>), list: (function(boolean=): Promise<*>), guests: (function(boolean=): Promise<*>)}} */ const unifiModule = { /** * Creates a new UniFi Voucher * * @param type * @param amount * @param note * @param retry * @return {Promise} */ create: (type, amount = 1, note = null, retry = true) => { return new Promise((resolve, reject) => { startSession().then(() => { controller.createVouchers(type.expiration, amount, parseInt(type.usage), note, typeof type.upload !== "undefined" ? type.upload : null, typeof type.download !== "undefined" ? type.download : null, typeof type.megabytes !== "undefined" ? type.megabytes : null).then((voucher_data) => { if(amount > 1) { log.info(`[UniFi] Created ${amount} vouchers`); resolve(true); } else { controller.getVouchers(voucher_data[0].create_time).then((voucher_data_complete) => { const voucher = `${[voucher_data_complete[0].code.slice(0, 5), '-', voucher_data_complete[0].code.slice(5)].join('')}`; log.info(`[UniFi] Created voucher with code: ${voucher}`); resolve(voucher); }).catch((e) => { log.error('[UniFi] Error while getting voucher!'); log.debug(e); reject('[UniFi] Error while getting voucher!'); }); } }).catch((e) => { log.error('[UniFi] Error while creating voucher!'); log.debug(e); // Check if token expired, if true attempt login then try again if (e.response) { if(e.response.status === 401 && retry) { log.info('[UniFi] Attempting re-authentication & retry...'); controller = null; unifiModule.create(type, amount, note, false).then((e) => { resolve(e); }).catch((e) => { reject(e); }); } else { // Something else went wrong lets clear the current controller so a user can retry log.error(`[UniFi] Unexpected ${JSON.stringify({status: e.response.status, retry})} cleanup controller...`); controller = null; reject('[UniFi] Error while creating voucher!'); } } else { // Something else went wrong lets clear the current controller so a user can retry log.error('[UniFi] Unexpected cleanup controller...'); controller = null; reject('[UniFi] Error while creating voucher!'); } }); }).catch((e) => { reject(e); }); }); }, /** * Removes a UniFi Voucher * * @param id * @param retry * @return {Promise} */ remove: (id, retry = true) => { return new Promise((resolve, reject) => { startSession().then(() => { controller.revokeVoucher(id).then(() => { resolve(true); }).catch((e) => { log.error('[UniFi] Error while removing voucher!'); log.debug(e); // Check if token expired, if true attempt login then try again if (e.response) { if(e.response.status === 401 && retry) { log.info('[UniFi] Attempting re-authentication & retry...'); controller = null; unifiModule.remove(id, false).then((e) => { resolve(e); }).catch((e) => { reject(e); }); } else { // Something else went wrong lets clear the current controller so a user can retry log.error(`[UniFi] Unexpected ${JSON.stringify({status: e.response.status, retry})} cleanup controller...`); controller = null; reject('[UniFi] Error while removing voucher!'); } } else { // Something else went wrong lets clear the current controller so a user can retry log.error('[UniFi] Unexpected cleanup controller...'); controller = null; reject('[UniFi] Error while removing voucher!'); } }); }).catch((e) => { reject(e); }); }); }, /** * Returns a list with all UniFi Vouchers * * @param retry * @return {Promise} */ list: (retry = true) => { return new Promise((resolve, reject) => { startSession().then(() => { controller.getVouchers().then((vouchers) => { log.info(`[UniFi] Found ${vouchers.length} voucher(s)`); resolve(vouchers); }).catch((e) => { log.error('[UniFi] Error while getting vouchers!'); log.debug(e); // Check if token expired, if true attempt login then try again if (e.response) { if(e.response.status === 401 && retry) { log.info('[UniFi] Attempting re-authentication & retry...'); controller = null; unifiModule.list(false).then((e) => { resolve(e); }).catch((e) => { reject(e); }); } else { // Something else went wrong lets clear the current controller so a user can retry log.error(`[UniFi] Unexpected ${JSON.stringify({status: e.response.status, retry})} cleanup controller...`); controller = null; reject('[UniFi] Error while getting vouchers!'); } } else { // Something else went wrong lets clear the current controller so a user can retry log.error('[UniFi] Unexpected cleanup controller...'); controller = null; reject('[UniFi] Error while getting vouchers!'); } }); }).catch((e) => { reject(e); }); }); }, /** * Returns a list with all UniFi Guests * * @param retry * @return {Promise} */ guests: (retry = true) => { return new Promise((resolve, reject) => { startSession().then(() => { controller.getGuests().then((guests) => { log.info(`[UniFi] Found ${guests.length} guest(s)`); resolve(guests); }).catch((e) => { log.error('[UniFi] Error while getting guests!'); log.debug(e); // Check if token expired, if true attempt login then try again if (e.response) { if(e.response.status === 401 && retry) { log.info('[UniFi] Attempting re-authentication & retry...'); controller = null; unifiModule.guests(false).then((e) => { resolve(e); }).catch((e) => { reject(e); }); } else { // Something else went wrong lets clear the current controller so a user can retry log.error(`[UniFi] Unexpected ${JSON.stringify({status: e.response.status, retry})} cleanup controller...`); controller = null; reject('[UniFi] Error while getting guests!'); } } else { // Something else went wrong lets clear the current controller so a user can retry log.error('[UniFi] Unexpected cleanup controller...'); controller = null; reject('[UniFi] Error while getting guests!'); } }); }).catch((e) => { reject(e); }); }); } } /** * Exports the UniFi module functions */ module.exports = unifiModule;