Code coverage report for lib\common\services\servicesettings.js

Statements: 100% (90 / 90)      Branches: 86.11% (31 / 36)      Functions: 100% (13 / 13)      Lines: 100% (90 / 90)      Ignored: none     

All files » lib/common/services/ » servicesettings.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261                                1   1 1 1   1         1   1 8 8     1 1   1                 1 4                   1 4                     1 72     72 72 197 6     191 191 1 190   1     189     189 3     186   186 185     1       66                         1 370 262 262   262 690 690       262 594 594     594   262 262   258   258 258   332   106         152   14   138                       1 4   4 133 133   69       64 86   63         1     4               1 25 25               1 160 160               1 185 185                   1 11 11 11   11                     1 185   185 262 262   258 108   150         73  
// 
// Copyright (c) Microsoft and contributors.  All rights reserved.
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//   http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// 
// See the License for the specific language governing permissions and
// limitations under the License.
// 
 
var util = require('util');
 
var azureUtil = require('../util/util');
var SR = require('../util/sr');
var Constants = require('../util/constants');
 
exports = module.exports;
 
/**
* The default protocol.
*/
exports.DEFAULT_PROTOCOL = Constants.HTTPS;
 
var NoMatchError = function (msg, constr) {
  Error.captureStackTrace(this, constr || this);
  this.message = msg || 'Error';
};
 
util.inherits(NoMatchError, Error);
NoMatchError.prototype.name = 'NoMatchError';
 
exports.NoMatchError = NoMatchError;
 
/**
* Throws an exception if the connection string format does not match any of the
* available formats.
*
* @param {string} connectionString The invalid formatted connection string.
* @return none
*/
exports.noMatchConnectionString = function (connectionString) {
  throw new NoMatchError('The provided connection string "' + connectionString + '" does not have complete configuration settings.');
};
 
/**
* Throws an exception if the settings dont match any of the
* available formats.
*
* @param {object} settings The invalid settings.
* @return none
*/
exports.noMatchSettings = function (settings) {
  throw new NoMatchError('The provided settings ' + JSON.stringify(settings) + ' are not complete.');
};
 
/**
* Parses the connection string and then validate that the parsed keys belong to
* the validSettingKeys
*
* @param {string} connectionString The user provided connection string.
* @param {array}  validKeys        The valid keys.
* @return {array} The tokenized connection string keys.
*/
exports.parseAndValidateKeys = function (connectionString, validKeys) {
  var parsedConnectionString = { };
 
  // parse key/value pairs from connection string
  var pairs = connectionString.split(';');
  for (var m = 0; m < pairs.length; m++) {
    if (pairs[m].length === 0) {
        continue;
    }
 
    var equalDex = pairs[m].indexOf('=');
    if (equalDex < 0) {
        throw new Error(SR.INVALID_CONNECTION_STRING);
    } else if (equalDex === 0) {
      // empty key name.
      throw new Error(SR.INVALID_CONNECTION_STRING_EMPTY_KEY);
    }
 
    var key = pairs[m].substring(0, equalDex);
 
    // assure that all given keys are valid.
    if (!azureUtil.inArrayInsensitive(key, validKeys)) {
      throw new Error(util.format(SR.INVALID_CONNECTION_STRING_BAD_KEY, key));
    }
 
    var value = pairs[m].substring(equalDex + 1);
    
    if(typeof parsedConnectionString[key] === 'undefined'){
      parsedConnectionString[key] = value;
    } else {
      // duplicate key name
      throw new Error(util.format(SR.INVALID_CONNECTION_STRING_DUPLICATE_KEY, key));
    }
  }
 
  return parsedConnectionString;
};
 
/**
* Creates an anonymous function that acts as predicate to perform a validation.
*
* @param array   {requirements} The array of conditions to satisfy.
* @param boolean {isRequired}   Either these conditions are all required or all
* optional.
* @param boolean {atLeastOne}   Indicates that at least one requirement must
* succeed.
* @return {function}
*/
exports.getValidator = function (requirements, isRequired, atLeastOne) {
  return function (userSettings) {
    var oneFound = false;
    var result = { };
 
    for (var key in userSettings) {
      Eif (userSettings.hasOwnProperty(key)) {
        result[key.toLowerCase()] = userSettings[key];
      }
    }
 
    for (var requirement in requirements) {
      Eif (requirements.hasOwnProperty(requirement)) {
        var settingName = requirements[requirement].SettingName.toLowerCase();
 
        // Check if the setting name exists in the provided user settings.
        if (result[settingName]) {
          // Check if the provided user setting value is valid.
          var validationFunc = requirements[requirement].SettingConstraint;
          var isValid = validationFunc(result[settingName]);
 
          Eif (isValid) {
            // Remove the setting as indicator for successful validation.
            delete result[settingName];
            oneFound = true;
          }
        } else if (isRequired) {
          // If required then fail because the setting does not exist
          return null;
        }
      }
    }
 
    if (atLeastOne) {
      // At least one requirement must succeed, otherwise fail.
      return oneFound ? result : null;
    } else {
      return result;
    }
  };
};
 
/**
* Creates a setting value condition that validates it is one of the
* passed valid values.
*
* @param {string} name The setting key name.
* @return {array}
*/
exports.setting = function (name) {
  var validValues = Array.prototype.slice.call(arguments, 1, arguments.length);
 
  var predicate = function (settingValue) {
    var validValuesString = JSON.stringify(validValues);
    if (validValues.length === 0) {
      // No restrictions, succeed.
      return true;
    }
 
    // Check to find if the settingValue is valid or not.
    for (var index = 0; index < validValues.length; index++) {
      if (settingValue.toString() == validValues[index].toString()) {
        // SettingValue is found in valid values set, succeed.
        return true;
      }
    }
 
    // settingValue is missing in valid values set, fail.
    throw new Error('The provided config value ' + settingValue + ' does not belong to the valid values subset:\n' + validValuesString);
  };
 
  return exports.settingWithFunc(name, predicate);
};
 
/**
* Creates an "at lease one" predicate for the provided list of requirements.
*
* @return callable
*/
exports.atLeastOne = function () {
  var allSettings = arguments;
  return exports.getValidator(allSettings, false, true);
};
 
/**
* Creates an optional predicate for the provided list of requirements.
*
* @return {function}
*/
exports.optional = function () {
  var optionalSettings = arguments;
  return exports.getValidator(optionalSettings, false, false);
};
 
/**
* Creates an required predicate for the provided list of requirements.
*
* @return {function}
*/
exports.allRequired = function () {
  var requiredSettings = arguments;
  return exports.getValidator(requiredSettings, true, false);
};
 
/**
* Creates a setting value condition using the passed predicate.
*
* @param {string}   name      The setting key name.
* @param {function} predicate The setting value predicate.
* @return {array}
*/
exports.settingWithFunc = function (name, predicate) {
  var requirement = {};
  requirement.SettingName = name;
  requirement.SettingConstraint = predicate;
 
  return requirement;
};
 
 
/**
* Tests to see if a given list of settings matches a set of filters exactly.
*
* @param array $settings The settings to check.
* @return boolean If any filter returns null, false. If there are any settings
* left over after all filters are processed, false. Otherwise true.
*/
exports.matchedSpecification = function (settings) {
  var constraints = Array.prototype.slice.call(arguments, 1, arguments.length);
 
  for (var constraint in constraints) {
    Eif (constraints.hasOwnProperty(constraint)) {
      var remainingSettings = constraints[constraint](settings);
 
      if (!remainingSettings) {
        return false;
      } else {
        settings = remainingSettings;
      }
    }
  }
 
  return azureUtil.objectKeysLength(settings) === 0;
};