<commit_before>'use strict'

let log = require("./logger.js")(__filename, "info");

let fs = require('fs');
let f = require('./Firewalla.js');

const redis = require('redis')
const rclient = redis.createClient()
const sclient_publish = redis.createClient()
const sclient_subscribe = redis.createClient()
sclient_publish.setMaxListeners(0)
sclient_subscribe.setMaxListeners(0)

const async = require('asyncawait/async')
const await = require('asyncawait/await')

const dynamicConfigKey = "sys:features"

var dynamicConfigs = {}

let config = null;

function getConfig() {
  if(!config) {
    let defaultConfig = JSON.parse(fs.readFileSync(f.getFirewallaHome() + "/net2/config.json", 'utf8'));
    let userConfigFile = f.getUserConfigFolder() + "/config.json";
    let userConfig = {};
    if(fs.existsSync(userConfigFile)) {
      userConfig = JSON.parse(fs.readFileSync(userConfigFile, 'utf8'));
    }

    let testConfig = {};
    if(process.env.NODE_ENV === 'test') {
      let testConfigFile = f.getUserConfigFolder() + "/config.test.json";
      if(fs.existsSync(testConfigFile)) {
        testConfig = JSON.parse(fs.readFileSync(testConfigFile, 'utf8'));
        log.warn("Test config is being used", testConfig, {});
      }
    }

    // user config will override system default config file
    config = Object.assign({}, defaultConfig, userConfig, testConfig);
  }
  return config;
}

function isFeatureOn_Static(featureName) {
  let config = getConfig()
  return config.userFeatures && config.userFeatures[featureName]
}

function isFeatureOn_Dynamic(featureName) {
  return dynamicConfigs && dynamicConfigs[featureName] && dynamicConfigs[featureName] === '1'
}

function isFeatureOn(featureName) {
  if(isFeatureOn_Static(featureName) || isFeatureOn_Dynamic(featureName)) {
    return true
  } else {
    return false
  }
}

function syncDynamicFeaturesConfigs() {
  return async(() => {
    let configs = await (rclient.hgetallAsync(dynamicConfigKey))
    if(configs) {
      dynamicConfigs = configs
    } else {
      dynamicConfigs = {}
    }
  })()
}

function enableDynamicFeature(featureName) {
  return async(() => {
    await (rclient.hsetAsync(dynamicConfigKey, featureName, '1'))
    sclient_publish.publish("config:feature:dynamic:enable", featureName)
    dynamicConfigs[featureName] = '1'
  })()
}

function disableDynamicFeature(featureName) {
  return async(() => {<commit_msg>BUG: can't disable feature when feature is by default on in static config<commit_after>'use strict'

let log = require("./logger.js")(__filename, "info");

let fs = require('fs');
let f = require('./Firewalla.js');

const redis = require('redis')
const rclient = redis.createClient()
const sclient_publish = redis.createClient()
const sclient_subscribe = redis.createClient()
sclient_publish.setMaxListeners(0)
sclient_subscribe.setMaxListeners(0)

const async = require('asyncawait/async')
const await = require('asyncawait/await')

const dynamicConfigKey = "sys:features"

var dynamicConfigs = {}

let config = null;

function getConfig() {
  if(!config) {
    let defaultConfig = JSON.parse(fs.readFileSync(f.getFirewallaHome() + "/net2/config.json", 'utf8'));
    let userConfigFile = f.getUserConfigFolder() + "/config.json";
    let userConfig = {};
    if(fs.existsSync(userConfigFile)) {
      userConfig = JSON.parse(fs.readFileSync(userConfigFile, 'utf8'));
    }

    let testConfig = {};
    if(process.env.NODE_ENV === 'test') {
      let testConfigFile = f.getUserConfigFolder() + "/config.test.json";
      if(fs.existsSync(testConfigFile)) {
        testConfig = JSON.parse(fs.readFileSync(testConfigFile, 'utf8'));
        log.warn("Test config is being used", testConfig, {});
      }
    }

    // user config will override system default config file
    config = Object.assign({}, defaultConfig, userConfig, testConfig);
  }
  return config;
}

function isFeatureOn_Static(featureName) {
  let config = getConfig()
  if(config.userFeatures && featureName in config.userFeatures) {
    if(config.userFeatures[featureName]) {
      return true
    } else {
      return false
    }
  } else {
    return undefined
  }
}

// undefined: feature not exists
// true: feature enabled
// false: feature disabled
function isFeatureOn_Dynamic(featureName) {
  if(dynamicConfigs && featureName in dynamicConfigs) {
    if(dynamicConfigs[featureName] === '1' ) {
      return true
    } else {
      return false
    }
  } else {
    return undefined
  }
}

function isFeatureOn(featureName) {
  const dynamicFlag = isFeatureOn_Dynamic(featureName)
  if(dynamicFlag !== undefined) {
    return dynamicFlag
  }

  const staticFlag = isFeatureOn_Static(featureName)
  if(staticFlag !== undefined) {
    return staticFlag
  } else {
    return false // default disabled
  }
}

function syncDynamicFeaturesConfigs() {
  return async(() => {
    let configs = await (rclient.hgetallAsync(dynamicConfigKey))
    if(configs) {
      dynamicConfigs = configs
    } else {
      dynamicConfigs = {}
    }
  })()
}

function enableDynamicFeature(featureName) {
  return async(() => {
    await (rclient.hsetAsync(dynamicConfigKey, featureName, '1'))
    sclient_publish.publish("config:feature:dynamic:enable", featureName)
    dynamicConfigs[featureName] = '1'
  })()
}

function disableDynamicFeature(featureName) {
  return async(() => {
{'fraction_non_alphanumeric': 0.1310615989515072, 'fraction_numerical': 0.0033701554016101853, 'mean_word_length': 4.161352657004831, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3774562', 'n_tokens_mistral': 1630, 'n_tokens_neox': 1637, 'n_words': 341}