<commit_before>(function ($) {

	"use strict";

	var app = angular.module('RbsChange'),
		TAG_COLORS = ['red', 'orange', 'yellow', 'green', 'blue', 'purple', 'gray'];

	/**
	 * <rbs-tag-color-selector/>
	 */
	app.directive('rbsTagColorSelector', function () {

		return {
			restrict : 'E',
			require  : 'ngModel',
			scope    : true,
			template :
				'' +
				'' +
				'',

			link : function (scope, elm, attrs, ngModel) {
				scope.colors = TAG_COLORS;

				ngModel.$render = function () {
					scope.selectedColor = ngModel.$viewValue;
				};

				scope.iconSize = attrs.iconSize || 'icon-large';

				scope.setColor = function ($event, color) {
					ngModel.$setViewValue(color);
					ngModel.$render();
				};
			}
		};

	});

	/**
	 * <rbs-tag/>
	 */
	app.directive('rbsTag', ['RbsChange.i18n', function (i18n) {
		return {
			restrict : 'A',
			replace  : true,
			template :
				'' +
					' ' +
					' ' +
					'(= rbsTag.label =)' +
					'' +
				'',

			scope : {
				'rbsTag'   : '=',
				'onRemove' : '&'
			},

			link : function (scope, elm) {
				elm.addClass('tag');
				scope.canBeRemoved = elm.is('[on-remove]');
				scope.remove = function () {
					scope.onRemove();
				};
				scope.$watch('rbsTag', function (value) {
					if (value) {
						elm.addClass(value.color);
						if (value.unsaved) {
							elm.addClass('new');
						} else {
							elm.removeClass('new');
						}
						if (value.used) {
							elm.addClass('opacity-half');
						} else {
							elm.removeClass('opacity-half');
						}
					}
				}, true);

				function buildDnDRepresentation (tag) {
					return JSON.stringify({
						"id" : tag.id,
						"label" : tag.label,
						"color" : tag.color,
						"userTag" : tag.userTag
					});
				}

				elm.on({
					'dragstart.rbs.tag': function (e) {
						e.dataTransfer.setData('Rbs/Tag', buildDnDRepresentation(scope.rbsTag));
						e.dataTransfer.effectAllowed = "copy";
					}
				});

			}
		};
	}]);

	/**
	 * <input class="rbs-auto-size-input" ... />
	 *
	 * Used in <rbs-tag-selector/>
	 */
	app.directive('rbsAutoSizeInput', function () {

		var options = {
			maxWidth: 1000,
			comfortZone: 18
		};

		return {
			restrict : 'AC',

			link : function (scope, elm) {

				var val = '',
					input = $(elm),
					testSubject = $('<tester/>').css({
						position: 'absolute',
						top: -9999,
						left: -9999,
						width: 'auto',
						fontSize: input.css('fontSize'),
						fontFamily: input.css('fontFamily'),
						fontWeight: input.css('fontWeight'),
						letterSpacing: input.css('letterSpacing'),
						whiteSpace: 'nowrap'
					}),
					check = function() {
						if (val === (val = input.val())) {return;}
						var escaped = val.replace(/&/g, '&').replace(/\s/g,' ').replace(/</g, '<').replace(/>/g, '>');
						testSubject.html(escaped);
						input.width(Math.min(testSubject.width() + options.comfortZone, options.maxWidth));
					};

				testSubject.insertAfter(input);

				$(elm).bind('keydown keyup blur update', check);

			}
		};

	});

	/**
	 * <rbs-tag-selector ng-model="document.tags"></rbs-tag-selector>
	 */
	app.directive(
		'rbsTagSelector',
		[
			'$timeout', '$compile', 'RbsChange.ArrayUtils', 'RbsChange.TagService', 'RbsChange.i18n',
			rbsTagSelectorFn
		]
	);

	function rbsTagSelectorFn ($timeout, $compile, ArrayUtils, TagService, i18n) {

		var	autocompleteEl;

		function loadAvailTags () {
			return TagService.getList();
		}

		// Popover element that shows suggestions.
		$('

').css({
			'position' : 'absolute',
			'display'  : 'none'
		}).appendTo('body');
		autocompleteEl = $('#rbsTagSelectorAutocompleteList');

		return {
			restrict : 'E',
			replace  : true,
			require  : 'ngModel',
			scope    : true,
			template :
				'
' +
					'<button class="btn btn-mini btn-inverse pull-right" title="' + i18n.trans('m.rbs.tag.admin.js.show-hide-all-tags | ucf') + '" type="button" ng-click="showAll=!showAll">' +
					'' +
					'</button>' +
					'' +
					'' +
					'' +
					'' +
					'' +
					'<input autocapitalize="off" autocomplete="off" autocorrect="off" type="text" rbs-auto-size-input="" ng-if="tag.input" ng-keyup="autocomplete()" ng-keydown="keydown($event, $index)">' +
					'' +
					'
' +
					'

' +
					'' +
					'
' +
				'
',

			link : function (scope, elm, attrs, ngModel) {

				var inputIndex = -1, tempTagCounter = 0;

				ngModel.$render = function ngModelRenderFn () {
					if (angular.isArray(ngModel.$viewValue)) {
						scope.tags = angular.copy(ngModel.$viewValue);
					} else {
						scope.tags = [];
					}
					if (inputIndex === -1) {
						scope.tags.push({'input': true});
					} else {
						scope.tags.splice(inputIndex, 0, {'input': true});
					}
				};

				scope.availTags = loadAvailTags();
				scope.showAll = false;

				function getInput() {
					return elm.find('input[type=text]');
				}

				function update () {
					var value = [];
					angular.forEach(scope.tags, function (tag, i) {
						if (tag.input) {
							inputIndex = i;
						} else {
							value.push(tag);
						}
					});
					ngModel.$setViewValue(value.length === 0 ? undefined : value);
				}

				function backspace () {
					if (scope.tags.length > 1) {
						scope.tags[inputIndex-1].used = false;
						scope.tags.splice(inputIndex-1, 1);
						update();
					}
				}

				function findTag (label) {
					var i;
					for (i=0 ; i<scope.availTags.length ; i++) {
						if (angular.lowercase(scope.availTags[i].label) === angular.lowercase(label)) {
							return scope.availTags[i];
						}
					}
					return null;
				}

				function add (value) {
					var tag = findTag(value);
					if (!tag) {
						tag = createTemporaryTag(value);
					}
					appendTag(tag);
				}

				function createTemporaryTag (value) {
					return {
						'id'      : --tempTagCounter,
						'label'   : value,
						'unsaved' : true,
						'userTag' : true
					};
				}

				function appendTag (tag) {
					if (!scope.isUsed(tag)) {
						scope.tags.splice(inputIndex, 0, tag);
						tag.used = true;
						update();
					}
				}
				scope.appendTag = appendTag;

				function moveInput (value, offset) {
					if (value.length === 0 && (inputIndex+offset) < (scope.tags.length)) {
						var r = ArrayUtils.move(scope.tags, inputIndex, inputIndex + offset);
						update();
						scope.focus();
						return r;
					}
					return false;
				}

				scope.isUsed = function (tag) {
					var i;
					for (i=0 ; i<scope.tags.length ; i++) {
						if (! scope.tags[i].input && scope.tags[i].id === tag.id) {
							return true;
						}
					}
					return false;
				};

				scope.removeTag = function (index) {
					scope.tags[index].used = false;
					scope.tags.splice(index, 1);
					update();
				};

				scope.focus = function () {
					$timeout(function () {
						getInput().focus();
					});
				};

				scope.moveLeft = function () {
					moveInput(getInput().val().trim(), -1);
				};
				scope.moveRight = function () {
					moveInput(getInput().val().trim(), +1);
				};

				scope.keydown = function ($event, index) {
					var	input = getInput(),
						value = input.val().trim();
					inputIndex = index;

					switch ($event.keyCode) {

						// Backspace
						case 8 :
							if (value.length === 0 && !$event.shiftKey && !$event.metaKey) {
								backspace();
								$event.preventDefault();
								$event.stopPropagation();
							}
							break;

						// Tab
						case 9 :
						// Coma
						case 188 :
							if (value.length > 0) {
								add(value);
								input.val('');
								$event.preventDefault();
								$event.stopPropagation();
							}
							break;

						// Enter
						case 13 :
							if (scope.suggestions.length) {
								$event.preventDefault();
								$event.stopPropagation();
								scope.autocompleteAdd(scope.suggestions[0]);
							} else if (value.length > 0) {
								add(value);
								input.val('');
								$event.preventDefault();
								$event.stopPropagation();
							}
							break;

						// Left arrow
						case 37 :
							if (moveInput(value, -1)) {
								$event.preventDefault();
								$event.stopPropagation();
							}
							break;

						// Right arrow
						case 39 :
							if (moveInput(value, 1)) {
								$event.preventDefault();
								$event.stopPropagation();
							}
							break;

						// Down arrow
						case 40 :
							if ($event.ctrlKey) {
								$event.preventDefault();
								$event.stopPropagation();
								scope.showAll = true;
							}
							break;

						// Up arrow
						case 38 :
							if ($event.ctrlKey) {
								$event.preventDefault();
								$event.stopPropagation();
								scope.showAll = false;
							}
							break;

						// Ctrl+R
						case 82 :
							if ($event.ctrlKey) {
								scope.availTags = loadAvailTags();
								$event.preventDefault();
								$event.stopPropagation();
							}
							break;
					}

				};

				scope.autocompleteAdd = function (tag) {
					autocompleteEl.hide();
					getInput().val('');
					appendTag(tag);
					focus();
				};

				scope.autocomplete = function () {
					var	input = getInput(),
						value = input.val().trim(),
						suggestions = [];

					if (value.length) {
						value = angular.lowercase(value);
						angular.forEach(scope.availTags, function (tag) {
							var label = angular.lowercase(tag.label), p;
							if (ArrayUtils.inArray(tag, scope.tags) === -1) {
								p = label.indexOf(value);
								if (p === 0) {
									// Tag begins with the entered value?
									// Add it at the beginning of the autocomplete list.
									suggestions.unshift(tag);
								} else if (p > 0) {
									// Tag contains the entered value?
									// Add it at the end of the autocomplete list.
									suggestions.push(tag);
								}
							}
						});
					}
					scope.suggestions = suggestions;

					function buildSuggestionsList () {
						return '(= tag.label =)
' + i18n.trans('m.rbs.tag.admin.js.enter-selects-first-tag | ucf') + '';
					}

					if (suggestions.length) {
						$compile(buildSuggestionsList())(scope, function (clone) {
							autocompleteEl.empty();
							autocompleteEl.append(clone);
							autocompleteEl.css({
								'left' : input.offset().left + 'px',
								'top'  : (input.outerHeight() + input.offset().top + 3)  + 'px'
							});
							autocompleteEl.show();
						});
					} else {
						autocompleteEl.hide();
					}

				};

			}
		};
	}

})(window.jQuery);<commit_msg>Added possibility to reload the tags list in `<rbs-tag-selector/>` by clicking the Shift key.<commit_after>(function ($) {

	"use strict";

	var app = angular.module('RbsChange'),
		TAG_COLORS = ['red', 'orange', 'yellow', 'green', 'blue', 'purple', 'gray'];

	/**
	 * <rbs-tag-color-selector/>
	 */
	app.directive('rbsTagColorSelector', function () {

		return {
			restrict : 'E',
			require  : 'ngModel',
			scope    : true,
			template :
				'' +
				'' +
				'',

			link : function (scope, elm, attrs, ngModel) {
				scope.colors = TAG_COLORS;

				ngModel.$render = function () {
					scope.selectedColor = ngModel.$viewValue;
				};

				scope.iconSize = attrs.iconSize || 'icon-large';

				scope.setColor = function ($event, color) {
					ngModel.$setViewValue(color);
					ngModel.$render();
				};
			}
		};

	});

	/**
	 * <rbs-tag/>
	 */
	app.directive('rbsTag', ['RbsChange.i18n', function (i18n) {
		return {
			restrict : 'A',
			replace  : true,
			template :
				'' +
					' ' +
					' ' +
					'(= rbsTag.label =)' +
					'' +
				'',

			scope : {
				'rbsTag'   : '=',
				'onRemove' : '&'
			},

			link : function (scope, elm) {
				elm.addClass('tag');
				scope.canBeRemoved = elm.is('[on-remove]');
				scope.remove = function () {
					scope.onRemove();
				};
				scope.$watch('rbsTag', function (value) {
					if (value) {
						elm.addClass(value.color);
						if (value.unsaved) {
							elm.addClass('new');
						} else {
							elm.removeClass('new');
						}
						if (value.used) {
							elm.addClass('opacity-half');
						} else {
							elm.removeClass('opacity-half');
						}
					}
				}, true);

				function buildDnDRepresentation (tag) {
					return JSON.stringify({
						"id" : tag.id,
						"label" : tag.label,
						"color" : tag.color,
						"userTag" : tag.userTag
					});
				}

				elm.on({
					'dragstart.rbs.tag': function (e) {
						e.dataTransfer.setData('Rbs/Tag', buildDnDRepresentation(scope.rbsTag));
						e.dataTransfer.effectAllowed = "copy";
					}
				});

			}
		};
	}]);

	/**
	 * <input class="rbs-auto-size-input" ... />
	 *
	 * Used in <rbs-tag-selector/>
	 */
	app.directive('rbsAutoSizeInput', function () {

		var options = {
			maxWidth: 1000,
			comfortZone: 18
		};

		return {
			restrict : 'AC',

			link : function (scope, elm) {

				var val = '',
					input = $(elm),
					testSubject = $('<tester/>').css({
						position: 'absolute',
						top: -9999,
						left: -9999,
						width: 'auto',
						fontSize: input.css('fontSize'),
						fontFamily: input.css('fontFamily'),
						fontWeight: input.css('fontWeight'),
						letterSpacing: input.css('letterSpacing'),
						whiteSpace: 'nowrap'
					}),
					check = function() {
						if (val === (val = input.val())) {return;}
						var escaped = val.replace(/&/g, '&').replace(/\s/g,' ').replace(/</g, '<').replace(/>/g, '>');
						testSubject.html(escaped);
						input.width(Math.min(testSubject.width() + options.comfortZone, options.maxWidth));
					};

				testSubject.insertAfter(input);

				$(elm).bind('keydown keyup blur update', check);

			}
		};

	});

	/**
	 * <rbs-tag-selector ng-model="document.tags"></rbs-tag-selector>
	 */
	app.directive(
		'rbsTagSelector',
		[
			'$timeout', '$compile', 'RbsChange.ArrayUtils', 'RbsChange.TagService', 'RbsChange.i18n',
			rbsTagSelectorFn
		]
	);

	function rbsTagSelectorFn ($timeout, $compile, ArrayUtils, TagService, i18n) {

		var	autocompleteEl;

		function loadAvailTags () {
			return TagService.getList();
		}

		// Popover element that shows suggestions.
		$('

').css({
			'position' : 'absolute',
			'display'  : 'none'
		}).appendTo('body');
		autocompleteEl = $('#rbsTagSelectorAutocompleteList');

		return {
			restrict : 'E',
			replace  : true,
			require  : 'ngModel',
			scope    : true,
			template :
				'
' +
					'<button class="btn btn-mini btn-inverse pull-right" title="' + i18n.trans('m.rbs.tag.admin.js.show-hide-all-tags | ucf') + '" type="button" ng-click="toggleShowAll($event)">' +
					'' +
					'</button>' +
					'' +
					'' +
					'' +
					'' +
					'' +
					'<input autocapitalize="off" autocomplete="off" autocorrect="off" type="text" rbs-auto-size-input="" ng-if="tag.input" ng-keyup="autocomplete()" ng-keydown="keydown($event, $index)">' +
					'' +
					'
' +
					'

' +
					'' +
					'
' +
				'
',

			link : function (scope, elm, attrs, ngModel) {

				var inputIndex = -1, tempTagCounter = 0;

				ngModel.$render = function ngModelRenderFn () {
					if (angular.isArray(ngModel.$viewValue)) {
						scope.tags = angular.copy(ngModel.$viewValue);
					} else {
						scope.tags = [];
					}
					if (inputIndex === -1) {
						scope.tags.push({'input': true});
					} else {
						scope.tags.splice(inputIndex, 0, {'input': true});
					}
				};

				scope.availTags = null;
				scope.showAll = false;

				scope.toggleShowAll = function ($event) {
					scope.showAll = ! scope.showAll;
					if (scope.showAll && (! scope.availTags || $event.shiftKey)) {
						scope.availTags = loadAvailTags();
					}
				};

				function getInput() {
					return elm.find('input[type=text]');
				}

				function update () {
					var value = [];
					angular.forEach(scope.tags, function (tag, i) {
						if (tag.input) {
							inputIndex = i;
						} else {
							value.push(tag);
						}
					});
					ngModel.$setViewValue(value.length === 0 ? undefined : value);
				}

				function backspace () {
					if (scope.tags.length > 1) {
						scope.tags[inputIndex-1].used = false;
						scope.tags.splice(inputIndex-1, 1);
						update();
					}
				}

				function findTag (label) {
					var i;
					for (i=0 ; i<scope.availTags.length ; i++) {
						if (angular.lowercase(scope.availTags[i].label) === angular.lowercase(label)) {
							return scope.availTags[i];
						}
					}
					return null;
				}

				function add (value) {
					var tag = findTag(value);
					if (!tag) {
						tag = createTemporaryTag(value);
					}
					appendTag(tag);
				}

				function createTemporaryTag (value) {
					return {
						'id'      : --tempTagCounter,
						'label'   : value,
						'unsaved' : true,
						'userTag' : true
					};
				}

				function appendTag (tag) {
					if (!scope.isUsed(tag)) {
						scope.tags.splice(inputIndex, 0, tag);
						tag.used = true;
						update();
					}
				}
				scope.appendTag = appendTag;

				function moveInput (value, offset) {
					if (value.length === 0 && (inputIndex+offset) < (scope.tags.length)) {
						var r = ArrayUtils.move(scope.tags, inputIndex, inputIndex + offset);
						update();
						scope.focus();
						return r;
					}
					return false;
				}

				scope.isUsed = function (tag) {
					var i;
					for (i=0 ; i<scope.tags.length ; i++) {
						if (! scope.tags[i].input && scope.tags[i].id === tag.id) {
							return true;
						}
					}
					return false;
				};

				scope.removeTag = function (index) {
					scope.tags[index].used = false;
					scope.tags.splice(index, 1);
					update();
				};

				scope.focus = function () {
					$timeout(function () {
						getInput().focus();
					});
				};

				scope.moveLeft = function () {
					moveInput(getInput().val().trim(), -1);
				};
				scope.moveRight = function () {
					moveInput(getInput().val().trim(), +1);
				};

				scope.keydown = function ($event, index) {
					var	input = getInput(),
						value = input.val().trim();
					inputIndex = index;

					switch ($event.keyCode) {

						// Backspace
						case 8 :
							if (value.length === 0 && !$event.shiftKey && !$event.metaKey) {
								backspace();
								$event.preventDefault();
								$event.stopPropagation();
							}
							break;

						// Tab
						case 9 :
						// Coma
						case 188 :
							if (value.length > 0) {
								add(value);
								input.val('');
								$event.preventDefault();
								$event.stopPropagation();
							}
							break;

						// Enter
						case 13 :
							if (scope.suggestions.length) {
								$event.preventDefault();
								$event.stopPropagation();
								scope.autocompleteAdd(scope.suggestions[0]);
							} else if (value.length > 0) {
								add(value);
								input.val('');
								$event.preventDefault();
								$event.stopPropagation();
							}
							break;

						// Left arrow
						case 37 :
							if (moveInput(value, -1)) {
								$event.preventDefault();
								$event.stopPropagation();
							}
							break;

						// Right arrow
						case 39 :
							if (moveInput(value, 1)) {
								$event.preventDefault();
								$event.stopPropagation();
							}
							break;

						// Down arrow
						case 40 :
							if ($event.ctrlKey) {
								$event.preventDefault();
								$event.stopPropagation();
								scope.showAll = true;
							}
							break;

						// Up arrow
						case 38 :
							if ($event.ctrlKey) {
								$event.preventDefault();
								$event.stopPropagation();
								scope.showAll = false;
							}
							break;

						// Ctrl+R
						case 82 :
							if ($event.ctrlKey) {
								scope.availTags = loadAvailTags();
								$event.preventDefault();
								$event.stopPropagation();
							}
							break;
					}

				};

				scope.autocompleteAdd = function (tag) {
					autocompleteEl.hide();
					getInput().val('');
					appendTag(tag);
					focus();
				};

				scope.autocomplete = function () {
					var	input = getInput(),
						value = input.val().trim(),
						suggestions = [];

					if (value.length) {
						value = angular.lowercase(value);
						angular.forEach(scope.availTags, function (tag) {
							var label = angular.lowercase(tag.label), p;
							if (ArrayUtils.inArray(tag, scope.tags) === -1) {
								p = label.indexOf(value);
								if (p === 0) {
									// Tag begins with the entered value?
									// Add it at the beginning of the autocomplete list.
									suggestions.unshift(tag);
								} else if (p > 0) {
									// Tag contains the entered value?
									// Add it at the end of the autocomplete list.
									suggestions.push(tag);
								}
							}
						});
					}
					scope.suggestions = suggestions;

					function buildSuggestionsList () {
						return '(= tag.label =)
' + i18n.trans('m.rbs.tag.admin.js.enter-selects-first-tag | ucf') + '';
					}

					if (suggestions.length) {
						$compile(buildSuggestionsList())(scope, function (clone) {
							autocompleteEl.empty();
							autocompleteEl.append(clone);
							autocompleteEl.css({
								'left' : input.offset().left + 'px',
								'top'  : (input.outerHeight() + input.offset().top + 3)  + 'px'
							});
							autocompleteEl.show();
						});
					} else {
						autocompleteEl.hide();
					}

				};

			}
		};
	}

})(window.jQuery);<|endoftext|>


<commit_before>import { spawn as nodeSpawn } from 'child_process';
import path from 'path';
import R from 'ramda';
import {
  createCredRequestId,
  clearUsernameAndPassword,
  ensureAuthServer,
  getAuthServerPort,
  getNodeBinaryPath,
  storeUsernameAndPassword
} from './authService';
import {
  regex
} from '../constants';

const parseUrlFromErrorMessage = (errorMessage) => {
  let url = null;
  const matches = regex.CREDENTIALS_NOT_FOUND.exec(errorMessage);
  if (matches && matches.length > 1) {
    url = matches[1];
  }
  return url;
};

const spawnCommand = (command, opts, stdin = '') => new Promise((resolve, reject) => {
  const [cmd, ...args] = command.trim().split(' ');
  const childProcess = nodeSpawn(cmd, args, R.mergeDeepRight(opts, { stdio: 'pipe' }));

  const stdoutData = [];
  const stderrData = [];

  const makeDataAccumulator = accumulator => (data) => {
    accumulator.push(data);
  };

  childProcess.stdout.on('data', makeDataAccumulator(stdoutData));
  childProcess.stderr.on('data', makeDataAccumulator(stderrData));
  childProcess.on('error', () => {
    reject({ status: null, stdout: '', stderr: '' });
  });
  childProcess.on('close', (status) => {
    const stdout = Buffer.concat(stdoutData);
    const stderr = Buffer.concat(stderrData);
    resolve({ status, stdout, stderr });
  });

  childProcess.stdin.write(stdin);
  childProcess.stdin.end();
});

const spawn = async (command, stdin, opts = {}, credentialsCallback, repoPath = null) => {
  const resolvedStdin = stdin || '';
  const resolvedRepoPath = repoPath || R.path('cwd', opts);
  const noAuthResult = await spawnCommand(
    command,
    R.mergeDeepRight(
      opts,
      {
        env: {
          GIT_TERMINAL_PROMPT: 0
        }
      }
    ),
    resolvedStdin
  );
  if (noAuthResult.status === 0) {
    // then we're done, return the data
    return { stdout: noAuthResult.stdout };
  }

  const errorMessage = noAuthResult.stderr.toString();
  if (!errorMessage.includes('Git credentials')) {
    throw new Error(errorMessage);
  }

  await ensureAuthServer();
  const url = parseUrlFromErrorMessage(errorMessage);
  const credRequestId = createCredRequestId(resolvedRepoPath);
  const tryCredentialsUntilCanceled = async () => {
    const { username, password } = await credentialsCallback({
      type: 'CREDS_REQUESTED',
      credRequestId,
      repoPath: resolvedRepoPath,
      url
    });
    storeUsernameAndPassword(credRequestId, username, password);
    try {
      const authResult = await spawnCommand(
        command,
        R.mergeDeepRight(
          opts,
          {
            env: {
              GIT_TERMINAL_PROMPT: 0,
              GIT_ASKPASS: `${path.join(__dirname, '..', '..', '..', 'askpass.sh')}`,
              NODEGIT_LFS_ASKPASS_STATE: credRequestId,
              NODEGIT_LFS_ASKPASS_PORT: getAuthServerPort(),
              NODEGIT_LFS_ASKPASS_PATH: path.join(__dirname, 'GitAskPass.js'),
              NODEGIT_LFS_NODE_PATH: getNodeBinaryPath()
            }
          }
        ),
        resolvedStdin
      );
      if (authResult.status === 0) {
        await credentialsCallback({
          type: 'CREDS_SUCCEEDED',
          credRequestId,
          repoPath: resolvedRepoPath,
          verifiedCredentials: { username, password },
          url
        });
        clearUsernameAndPassword(credRequestId);
        return { stdout: noAuthResult.stdout };
      }

      const stderr = authResult.stderr.toString();
      if (stderr.includes('Git credentials')) {
        const authError = new Error('Auth error');
        authError.isAuthError = true;
        throw authError;
      }

      throw new Error(stderr);
    } catch (e) {
      if (e.isAuthError) {
        clearUsernameAndPassword(credRequestId);
        await credentialsCallback({
          type: 'CREDS_FAILED',
          credRequestId,
          repoPath: resolvedRepoPath,
          url
        });
        return tryCredentialsUntilCanceled();
      }

      throw e;
    }
  };

  try {
    return await tryCredentialsUntilCanceled();
  } catch (e) {
    throw e;
  }
};

export default spawn;
<commit_msg>Fix spawn returning wrong stdout on successful authenticated request<commit_after>import { spawn as nodeSpawn } from 'child_process';
import path from 'path';
import R from 'ramda';
import {
  createCredRequestId,
  clearUsernameAndPassword,
  ensureAuthServer,
  getAuthServerPort,
  getNodeBinaryPath,
  storeUsernameAndPassword
} from './authService';
import {
  regex
} from '../constants';

const parseUrlFromErrorMessage = (errorMessage) => {
  let url = null;
  const matches = regex.CREDENTIALS_NOT_FOUND.exec(errorMessage);
  if (matches && matches.length > 1) {
    url = matches[1];
  }
  return url;
};

const spawnCommand = (command, opts, stdin = '') => new Promise((resolve, reject) => {
  const [cmd, ...args] = command.trim().split(' ');
  const childProcess = nodeSpawn(cmd, args, R.mergeDeepRight(opts, { stdio: 'pipe' }));

  const stdoutData = [];
  const stderrData = [];

  const makeDataAccumulator = accumulator => (data) => {
    accumulator.push(data);
  };

  childProcess.stdout.on('data', makeDataAccumulator(stdoutData));
  childProcess.stderr.on('data', makeDataAccumulator(stderrData));
  childProcess.on('error', () => {
    reject({ status: null, stdout: '', stderr: '' });
  });
  childProcess.on('close', (status) => {
    const stdout = Buffer.concat(stdoutData);
    const stderr = Buffer.concat(stderrData);
    resolve({ status, stdout, stderr });
  });

  childProcess.stdin.write(stdin);
  childProcess.stdin.end();
});

const spawn = async (command, stdin, opts = {}, credentialsCallback, repoPath = null) => {
  const resolvedStdin = stdin || '';
  const resolvedRepoPath = repoPath || R.path('cwd', opts);
  const noAuthResult = await spawnCommand(
    command,
    R.mergeDeepRight(
      opts,
      {
        env: {
          GIT_TERMINAL_PROMPT: 0
        }
      }
    ),
    resolvedStdin
  );
  if (noAuthResult.status === 0) {
    // then we're done, return the data
    return { stdout: noAuthResult.stdout };
  }

  const errorMessage = noAuthResult.stderr.toString();
  if (!errorMessage.includes('Git credentials')) {
    throw new Error(errorMessage);
  }

  await ensureAuthServer();
  const url = parseUrlFromErrorMessage(errorMessage);
  const credRequestId = createCredRequestId(resolvedRepoPath);
  const tryCredentialsUntilCanceled = async () => {
    const { username, password } = await credentialsCallback({
      type: 'CREDS_REQUESTED',
      credRequestId,
      repoPath: resolvedRepoPath,
      url
    });
    storeUsernameAndPassword(credRequestId, username, password);
    try {
      const authResult = await spawnCommand(
        command,
        R.mergeDeepRight(
          opts,
          {
            env: {
              GIT_TERMINAL_PROMPT: 0,
              GIT_ASKPASS: `${path.join(__dirname, '..', '..', '..', 'askpass.sh')}`,
              NODEGIT_LFS_ASKPASS_STATE: credRequestId,
              NODEGIT_LFS_ASKPASS_PORT: getAuthServerPort(),
              NODEGIT_LFS_ASKPASS_PATH: path.join(__dirname, 'GitAskPass.js'),
              NODEGIT_LFS_NODE_PATH: getNodeBinaryPath()
            }
          }
        ),
        resolvedStdin
      );
      if (authResult.status === 0) {
        await credentialsCallback({
          type: 'CREDS_SUCCEEDED',
          credRequestId,
          repoPath: resolvedRepoPath,
          verifiedCredentials: { username, password },
          url
        });
        clearUsernameAndPassword(credRequestId);
        return { stdout: authResult.stdout };
      }

      const stderr = authResult.stderr.toString();
      if (stderr.includes('Git credentials')) {
        const authError = new Error('Auth error');
        authError.isAuthError = true;
        throw authError;
      }

      throw new Error(stderr);
    } catch (e) {
      if (e.isAuthError) {
        clearUsernameAndPassword(credRequestId);
        await credentialsCallback({
          type: 'CREDS_FAILED',
          credRequestId,
          repoPath: resolvedRepoPath,
          url
        });
        return tryCredentialsUntilCanceled();
      }

      throw e;
    }
  };

  try {
    return await tryCredentialsUntilCanceled();
  } catch (e) {
    throw e;
  }
};

export default spawn;
<|endoftext|>


<commit_before>/** @jsx React.DOM */

var data = [
	{filename: "grandparents-day", extension: "jpg", type: "photo", title: "grandparents-day"},
	{filename: "mom-maggie-and-marie", extension: "jpg", type: "photo", title: "mom-maggie-and-marie"}
];

var DefaultRoute = Router.DefaultRoute,
		Link = Router.Link,
		Route = Router.Route,
		RouteHandler = Router.RouteHandler,
		routes;

routes = (
	React.createElement(Route, {name: "app", path: "/", handler: App},
		React.createElement(Route, {name: "detail", handler: Detail}),
		React.createElement(Route, {name: "about", handler: About}),
		React.createElement(Route, {name: "donate", handler: Donate}),
		React.createElement(DefaultRoute, {handler: Gallery})
	)
)

Router.run(routes, function (Handler) {
	React.render(React.createElement(Handler, null), document.getElementById('container'))
});<commit_msg>Temporarily commenting out routes for troubleshooting<commit_after>/** @jsx React.DOM */

var data = [
	{filename: "grandparents-day", extension: "jpg", type: "photo", title: "grandparents-day"},
	{filename: "mom-maggie-and-marie", extension: "jpg", type: "photo", title: "mom-maggie-and-marie"}
];

// var DefaultRoute = Router.DefaultRoute,
// 		Link = Router.Link,
// 		Route = Router.Route,
// 		RouteHandler = Router.RouteHandler,
// 		routes;

// routes = (
// 	<Route name="app" path="/" handler={App}>
// 		<Route name="detail" handler={Detail}/>
// 		<Route name="about" handler={About}/>
// 		<Route name="donate" handler={Donate}/>
// 		<DefaultRoute handler={Gallery}/>
// 	</Route>
// )

// Router.run(routes, function (Handler) {
// 	React.render(<Handler/>, document.getElementById('container'))
// });

React.render(React.createElement(App, null), document.getElementById('container'));<|endoftext|>


<commit_before>/** @babel */
import {Range} from 'atom';
import {generateRange} from 'atom-linter';
import ruleURI from 'eslint-rule-documentation';

// (editor: Object) => function
export default function format(editor) {
	// (report?: Object) => Array<Object>
	return report => {
		if (!report) {
			return [];
		}

		const {results = []} = report;
		const [result] = results;

		if (!result) {
			return [];
		}

		const {messages} = result;

		if (!messages) {
			return [];
		}

		return messages.map(message => {
			return {
				location: selectLocation(editor, message),
				url: selectUrl(message),
				excerpt: selectExcerpt(message),
				severity: selectSeverity(message),
				solutions: selectSolutions(editor, message)
			};
		});
	};
}

// (editor: Object, message: Object) => Array<Object>
function selectSolutions(editor, message) {
	const fix = {message};
	const buffer = editor.getBuffer();

	if (!fix) {
		return [];
	}

	const {range, text} = fix;

	if (!Array.isArray(range)) {
		return [];
	}

	if (typeof text !== 'string') {
		return [];
	}

	const position = new Range(...range.map(index => buffer.positionForCharacterIndex(index)));
	return {position, replaceWith: text};
}

// (message: Object) => string
function selectUrl(message) {
	const result = ruleURI(message.ruleId || '');
	return result.found ? result.url : '';
}

// (message: Object) => string
function selectExcerpt(message) {
	return message.message;
}

// (editor: Object, message: Object) => Array<number>
function selectLocation(editor, x) {
	return {
		file: editor.getPath(),
		position: selectPosition(editor, x)
	};
}

// (editor: Object, message: Object) => Array<number>
function selectPosition(editor, x) {
	const msgLine = x.line - 1;

	if (typeof x.endColumn === 'number' && typeof x.endLine === 'number') {
		const msgCol = Math.max(0, x.column - 1);
		return [[msgLine, msgCol], [x.endLine - 1, x.endColumn - 1]];
	} else if (typeof x.line === 'number' && typeof x.column === 'number') {
		// We want msgCol to remain undefined if it was intentional so
		// `rangeFromLineNumber` will give us a range over the entire line
		const msgCol = typeof x.column === 'undefined' ? x.column : x.column - 1;

		try {
			return generateRange(editor, msgLine, msgCol);
		} catch (err) {
			throw new Error(`Failed getting range. This is most likely an issue with ESLint. (${x.ruleId} - ${x.message} at ${x.line}:${x.column})`);
		}
	}
}

// (message: Object) => string
function selectSeverity(message) {
	return message.severity === 2 ? 'error' : 'warning';
}
<commit_msg>Fix outdated comment (#84)<commit_after>/** @babel */
import {Range} from 'atom';
import {generateRange} from 'atom-linter';
import ruleURI from 'eslint-rule-documentation';

// (editor: Object) => function
export default function format(editor) {
	// (report?: Object) => Array<Object>
	return report => {
		if (!report) {
			return [];
		}

		const {results = []} = report;
		const [result] = results;

		if (!result) {
			return [];
		}

		const {messages} = result;

		if (!messages) {
			return [];
		}

		return messages.map(message => {
			return {
				location: selectLocation(editor, message),
				url: selectUrl(message),
				excerpt: selectExcerpt(message),
				severity: selectSeverity(message),
				solutions: selectSolutions(editor, message)
			};
		});
	};
}

// (editor: Object, message: Object) => Array<Object>
function selectSolutions(editor, message) {
	const fix = {message};
	const buffer = editor.getBuffer();

	if (!fix) {
		return [];
	}

	const {range, text} = fix;

	if (!Array.isArray(range)) {
		return [];
	}

	if (typeof text !== 'string') {
		return [];
	}

	const position = new Range(...range.map(index => buffer.positionForCharacterIndex(index)));
	return {position, replaceWith: text};
}

// (message: Object) => string
function selectUrl(message) {
	const result = ruleURI(message.ruleId || '');
	return result.found ? result.url : '';
}

// (message: Object) => string
function selectExcerpt(message) {
	return message.message;
}

// (editor: Object, message: Object) => Array<number>
function selectLocation(editor, x) {
	return {
		file: editor.getPath(),
		position: selectPosition(editor, x)
	};
}

// (editor: Object, message: Object) => Array<number>
function selectPosition(editor, x) {
	const msgLine = x.line - 1;

	if (typeof x.endColumn === 'number' && typeof x.endLine === 'number') {
		const msgCol = Math.max(0, x.column - 1);
		return [[msgLine, msgCol], [x.endLine - 1, x.endColumn - 1]];
	} else if (typeof x.line === 'number' && typeof x.column === 'number') {
		// We want msgCol to remain undefined if it was intentional so
		// `generateRange` will give us a range over the entire line
		const msgCol = typeof x.column === 'undefined' ? x.column : x.column - 1;

		try {
			return generateRange(editor, msgLine, msgCol);
		} catch (err) {
			throw new Error(`Failed getting range. This is most likely an issue with ESLint. (${x.ruleId} - ${x.message} at ${x.line}:${x.column})`);
		}
	}
}

// (message: Object) => string
function selectSeverity(message) {
	return message.severity === 2 ? 'error' : 'warning';
}
<|endoftext|>


<commit_before>/*jshint node:true, indent:2, curly:false, eqeqeq:true, immed:true, latedef:true, newcap:true, noarg:true,
regexp:true, undef:true, strict:true, trailing:true, white:true */
/*global X:true, XM:true, issue:true, XT:true */

(function () {
  "use strict";

  var _ = X._;
  //var _util = X.util;

  /**
    Session object for datasource.

    @class
    @extends X.Object
   */
  X.Session = X.Object.extend(/** @lends X.Session.prototype */{

    isReady: false,
    isLoaded: false,

    init: function () {
      var id = this.get("id"), sid = this.get("sid"),
          selected = this.get("selected"), logout = this.get("logout");

      if (logout) {
        this.load(_.bind(this.didLoadForLogout, this));
      } else if (!sid) {
        X.Session.init.call(this);
        process.nextTick(_.bind(function () { this.set("isReady", true); }, this));
        this.commit();
      } else if (selected && id && sid) {

        //X.debugging = true;
        //X.debug("ABOUT TO SELECT: ", id, selected, sid);

        this.load(_.bind(this.didLoadForSelection, this));
      } else {

        //X.debugging = true;
        //X.debug("ABOUT LOAD: ", id, sid, selected);

        this.load();
      }
    },

    //.....................................
    // ACTION METHODS
    //
    /**
      Commit.

     */
    commit: function () {
      //X.log("commit(): ", _util.inspect(this));

      var K = this.get("model"),
        k = new K(),
        that = this,
        options = {};

      if (this.get("isLoaded")) {
        // we were loaded so a commit needs to update
        // not create a new session entry
        options.success = function (res) { that.updateForCommit(null, k); };
        options.error = function (model, err) { that.updateForCommit(err); };
        options.id = this.get("sid");
        return k.fetch(options);
      }

      options.success = function () { that.didCommit(); };
      k.initialize(null, {isNew: true});
      k.save(this.get("details"), options);
    },
    /**
      Update for commit

     */
    updateForCommit: function (err, res) {
      //X.log("updateForCommit(): ");

      var details = this.get("details"),
        that = this,
        options = {},
        key;

      if (err || !res) {
        return this.set("error", "could not update");
      }

      for (key in details) {
        if (!details.hasOwnProperty(key)) continue;
        res.set(key, details[key]);
      }

      options.success = function () { that.didCommit(); };
      options.error = function (model, err) { that.didCommit(err); };
      res.save(null, options);
    },

    //.....................................
    // POST-ACTION METHODS
    //

    didLoad: function (err, res) {
      //X.log("didLoad(): ", err, res);
      var loaded,
        prop;

      if (err) {
        return this.set("error", err.message, {stack: err.stack});
      } else if (!res) {
        // something is wrong, we could not find the session that
        // was requested
        return this.set("error", "could not retrieve session", {code: "SESSION_NOT_FOUND"});
      }

      loaded = res.toJSON();

      // Need to remove null values... no, it doesn't make a lot of sense
      for (prop in loaded) {
        if (loaded.hasOwnProperty(prop)) {
          if (_.isNull(loaded[prop])) {
            delete loaded[prop];
          }
        }
      }

      X.mixin(this, loaded);

      this.set("isLoaded", true);

      this.created = res.get('created');
      this.checksum = res.get('checksum');
      this.lastModified = X.Session.timestamp();
      this.set("isReady", true);

      //this.isReadyDidChange();

      // commit update?
      process.nextTick(_.bind(this.commit, this));
    },

    didCommit: function (err) {
      //X.log("didCommit(): ", err);

      if (err) {
        this.set("error", err.message(), err.code);
      } else {
        // TODO: this _can_ be done lazily right?
        // this.set("isReady", true);
        this.emit("didCommit");
      }
    },

    didLoadForSelection: function (err, res) {
      //X.debug("didLoadForSelection(): ", res);
      var organizations = this.get("organizations"), selected, found;
      if (!organizations || organizations.length <= 0) {
        return this.set("error", "no organizations available for selection");
      } else if (err) { return this.didLoad(err, res); }
      selected = this.get("selected");
      if ((found = _.find(organizations, function (o) {
        return o.name === selected ? true: false;
      }))) {
        // TODO: this needs to seriously be reevaluated
        // as it seems like if for any reason the session
        // already had an organization listed (somehow)
        // it will be overwritten and cause unknown
        // behaviors as a result
        this.set("organization", selected);
        this.set("username", found.username);
        this.didLoad(null, res);
      } else this.set("error", "invalid organization selected for user");
    },

    didLoadForLogout: function (err, res) {
      if (err) {
        return this.set("error", "could not load the session to logout");
      }
      // successfully loaded the session which means its valid
      // lets go ahead and logout by destroying ourselves
      this.set("isLoaded", true);
      this.destroy(res);
    },

    destroy: function (session) {
      if (session && session.destroy) { session.destroy(); }
      this.set("isReady", true);
    },

    query: function (query, callback) {
      var options,
        organization = this.get("organization"), orig = callback;
      if (!this.get("isLoaded")) {
        X.warn("Error: cannot query unloaded session");
        return this.set("error", "cannot query unloaded session");
      }
      callback = _.bind(this.didQuery, this, orig);
      X.debug("query: %@".f(query));
      if (this.payload.databaseType === 'global' && this.payload.requestType === 'fetch') {
        // TODO XXX Authentication!?!!?
        // run this query against the global database
        options = JSON.parse(JSON.stringify(this.payload)); // clone
        options.success = function (resp) { callback(null, resp); };
        options.error = function (model, err) { callback(err); };
        XT.dataSource.fetch(options);
      } else {
        // run this query against an instance database
        X.database.query(organization, query, callback);
      }
      return this;
    },

    didQuery: function (callback, err, res) {
      if (err) return callback(err);
      if (res) {
        callback(null, res);
      } else this.set("error", "no result from query");
    },

    //.....................................
    // PROPERTY METHODS
    //

    model: function () {
      return XM.Session;
    }.property(),

    details: function () {
      var d = {
        id: this.get("id"),
        sid: this.get("sid"),
        lastModified: this.get("lastModified") || X.Session.timestamp(),
        created: this.get("created"),
        checksum: "",
        username: this.get("username"),
        organization: this.get("organization"),
        organizations: this.get("organizations"),
        socket: this.get("socket")
      };

      //X.debug("details", d);

      return d;
    }.property(),

    socket: function (socket) {
      if (arguments.length === 0) return this._socketId;
      this._socketId = socket.id;
      this.commit();
    }.property(),

    error: function () {
      if (arguments.length === 0) return this._error;
      var err = this._error = {}, args = X.$A(arguments);
      err.reason = args.shift();
      while (args.length > 0) {
        X.mixin(err, args.shift());
      }
    }.property(),

    //.....................................
    // PROXIED METHODS
    //

    load: function () {
      return X.Session.load.apply(this, arguments);
    }
  });

  X.mixin(X.Session, /** @lends X.Session */{

    cache: null,

    load: function (callback) {
      //X.log("load(): ");

      var K = this.get("model"),
        k = new K(),
        options = {};

      if (!callback) { callback = _.bind(this.didLoad, this); }
      options.id = this.get("sid");
      options.success = function (resp) { callback(null, resp); };
      options.error = function (model, err) { callback(err); };

      //X.log("load(): ", details);

      k.fetch(options);
      return this;
    },

    checksum: function () {
      //var hash = X.Session.sha1hash(), data = ;
      //data = X.typeOf(data) === X.T_HASH ? X.json(data) : data;
      //return hash.update(data).digest('hex');
    },

    init: function () {
      this.sid = X.Session.generateSID();
      this.created = X.Session.timestamp();
    },

    generateSID: function () {
      // http://www.ietf.org/rfc/rfc4122.txt
      var s = [];
      var hexDigits = "0123456789abcdef";
      for (var i = 0; i < 36; i++) {
        s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
      }
      s[14] = "4";  // bits 12-15 of the time_hi_and_version field to 0010
      s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);  // bits 6-7 of the clock_seq_hi_and_reserved to 01
      s[8] = s[13] = s[18] = s[23] = "-";

      var uuid = s.join("");
      return uuid;
    },

    timestamp: function () { return new Date().getTime(); },

    sha1hash: function () { return X.crypto.createHash('sha1'); },

    md5hash: function () { return X.crypto.createHash('md5'); },

    /**
      Polls database and logs users out upon session timeout. This method
      can be used to do any actions that are driven from the cache.
     */
    pollCache: function () {
      var sessions = new XM.SessionCollection(),
        i,
        diff,
        ok,
        now,
        model,
        socket,
        sockets,
        options = {};

      sockets = X.Server.getServer("Data").socketsFor("/clientsock");

      options.success = function () {
        ok = (X.options.datasource.sessionTimeout || 15) * 60000;
        now = X.Session.timestamp();

        //console.log("RUNNING", ok, now);

        if (sessions && sessions.length > 0) {
          for (i = 0; i < sessions.length; ++i) {
            model = sessions.at(i);
            diff = Math.abs(now - (model.get('lastModified') || 1000000000));
            if (diff > ok) {
              socket = sockets[model.get('socket')];
              if (socket) {
                socket.emit("timeout");
                socket.disconnect();
              }
              model.destroy();
            }
          }
        }
      };
      options.error = function (model, err) {
        // we have serious issues if we have an error here!
        return issue(X.fatal("error polling cache", err.message(), err.code));
      };
      sessions.fetch(options);
    },

    isActiveSession: function () {
    }
  });

}());
<commit_msg>issue #18649: support for global dispatch<commit_after>/*jshint node:true, indent:2, curly:false, eqeqeq:true, immed:true, latedef:true, newcap:true, noarg:true,
regexp:true, undef:true, strict:true, trailing:true, white:true */
/*global X:true, XM:true, issue:true, XT:true */

(function () {
  "use strict";

  var _ = X._;
  //var _util = X.util;

  /**
    Session object for datasource.

    @class
    @extends X.Object
   */
  X.Session = X.Object.extend(/** @lends X.Session.prototype */{

    isReady: false,
    isLoaded: false,

    init: function () {
      var id = this.get("id"), sid = this.get("sid"),
          selected = this.get("selected"), logout = this.get("logout");

      if (logout) {
        this.load(_.bind(this.didLoadForLogout, this));
      } else if (!sid) {
        X.Session.init.call(this);
        process.nextTick(_.bind(function () { this.set("isReady", true); }, this));
        this.commit();
      } else if (selected && id && sid) {

        //X.debugging = true;
        //X.debug("ABOUT TO SELECT: ", id, selected, sid);

        this.load(_.bind(this.didLoadForSelection, this));
      } else {

        //X.debugging = true;
        //X.debug("ABOUT LOAD: ", id, sid, selected);

        this.load();
      }
    },

    //.....................................
    // ACTION METHODS
    //
    /**
      Commit.

     */
    commit: function () {
      //X.log("commit(): ", _util.inspect(this));

      var K = this.get("model"),
        k = new K(),
        that = this,
        options = {};

      if (this.get("isLoaded")) {
        // we were loaded so a commit needs to update
        // not create a new session entry
        options.success = function (res) { that.updateForCommit(null, k); };
        options.error = function (model, err) { that.updateForCommit(err); };
        options.id = this.get("sid");
        return k.fetch(options);
      }

      options.success = function () { that.didCommit(); };
      k.initialize(null, {isNew: true});
      k.save(this.get("details"), options);
    },
    /**
      Update for commit

     */
    updateForCommit: function (err, res) {
      //X.log("updateForCommit(): ");

      var details = this.get("details"),
        that = this,
        options = {},
        key;

      if (err || !res) {
        return this.set("error", "could not update");
      }

      for (key in details) {
        if (!details.hasOwnProperty(key)) continue;
        res.set(key, details[key]);
      }

      options.success = function () { that.didCommit(); };
      options.error = function (model, err) { that.didCommit(err); };
      res.save(null, options);
    },

    //.....................................
    // POST-ACTION METHODS
    //

    didLoad: function (err, res) {
      //X.log("didLoad(): ", err, res);
      var loaded,
        prop;

      if (err) {
        return this.set("error", err.message, {stack: err.stack});
      } else if (!res) {
        // something is wrong, we could not find the session that
        // was requested
        return this.set("error", "could not retrieve session", {code: "SESSION_NOT_FOUND"});
      }

      loaded = res.toJSON();

      // Need to remove null values... no, it doesn't make a lot of sense
      for (prop in loaded) {
        if (loaded.hasOwnProperty(prop)) {
          if (_.isNull(loaded[prop])) {
            delete loaded[prop];
          }
        }
      }

      X.mixin(this, loaded);

      this.set("isLoaded", true);

      this.created = res.get('created');
      this.checksum = res.get('checksum');
      this.lastModified = X.Session.timestamp();
      this.set("isReady", true);

      //this.isReadyDidChange();

      // commit update?
      process.nextTick(_.bind(this.commit, this));
    },

    didCommit: function (err) {
      //X.log("didCommit(): ", err);

      if (err) {
        this.set("error", err.message(), err.code);
      } else {
        // TODO: this _can_ be done lazily right?
        // this.set("isReady", true);
        this.emit("didCommit");
      }
    },

    didLoadForSelection: function (err, res) {
      //X.debug("didLoadForSelection(): ", res);
      var organizations = this.get("organizations"), selected, found;
      if (!organizations || organizations.length <= 0) {
        return this.set("error", "no organizations available for selection");
      } else if (err) { return this.didLoad(err, res); }
      selected = this.get("selected");
      if ((found = _.find(organizations, function (o) {
        return o.name === selected ? true: false;
      }))) {
        // TODO: this needs to seriously be reevaluated
        // as it seems like if for any reason the session
        // already had an organization listed (somehow)
        // it will be overwritten and cause unknown
        // behaviors as a result
        this.set("organization", selected);
        this.set("username", found.username);
        this.didLoad(null, res);
      } else this.set("error", "invalid organization selected for user");
    },

    didLoadForLogout: function (err, res) {
      if (err) {
        return this.set("error", "could not load the session to logout");
      }
      // successfully loaded the session which means its valid
      // lets go ahead and logout by destroying ourselves
      this.set("isLoaded", true);
      this.destroy(res);
    },

    destroy: function (session) {
      if (session && session.destroy) { session.destroy(); }
      this.set("isReady", true);
    },

    query: function (query, callback) {
      var options,
        organization = this.get("organization"), orig = callback;
      if (!this.get("isLoaded")) {
        X.warn("Error: cannot query unloaded session");
        return this.set("error", "cannot query unloaded session");
      }
      callback = _.bind(this.didQuery, this, orig);
      X.debug("query: %@".f(query));
      if (this.payload.databaseType === 'global') {
        // TODO XXX Authentication!?!!?
        // run this query against the global database
        options = JSON.parse(JSON.stringify(this.payload)); // clone
        options.success = function (resp) { callback(null, resp); };
        options.error = function (model, err) { callback(err); };
        if (this.payload.requestType === 'fetch') {
          XT.dataSource.fetch(options);
        } else if (this.payload.requestType === 'dispatch') {
          XT.dataSource.dispatch(this.payload.className, this.payload.functionName, this.payload.parameters, options);
        }
      } else {
        // run this query against an instance database
        X.database.query(organization, query, callback);
      }
      return this;
    },

    didQuery: function (callback, err, res) {
      if (err) return callback(err);
      if (res) {
        callback(null, res);
      } else this.set("error", "no result from query");
    },

    //.....................................
    // PROPERTY METHODS
    //

    model: function () {
      return XM.Session;
    }.property(),

    details: function () {
      var d = {
        id: this.get("id"),
        sid: this.get("sid"),
        lastModified: this.get("lastModified") || X.Session.timestamp(),
        created: this.get("created"),
        checksum: "",
        username: this.get("username"),
        organization: this.get("organization"),
        organizations: this.get("organizations"),
        socket: this.get("socket")
      };

      //X.debug("details", d);

      return d;
    }.property(),

    socket: function (socket) {
      if (arguments.length === 0) return this._socketId;
      this._socketId = socket.id;
      this.commit();
    }.property(),

    error: function () {
      if (arguments.length === 0) return this._error;
      var err = this._error = {}, args = X.$A(arguments);
      err.reason = args.shift();
      while (args.length > 0) {
        X.mixin(err, args.shift());
      }
    }.property(),

    //.....................................
    // PROXIED METHODS
    //

    load: function () {
      return X.Session.load.apply(this, arguments);
    }
  });

  X.mixin(X.Session, /** @lends X.Session */{

    cache: null,

    load: function (callback) {
      //X.log("load(): ");

      var K = this.get("model"),
        k = new K(),
        options = {};

      if (!callback) { callback = _.bind(this.didLoad, this); }
      options.id = this.get("sid");
      options.success = function (resp) { callback(null, resp); };
      options.error = function (model, err) { callback(err); };

      //X.log("load(): ", details);

      k.fetch(options);
      return this;
    },

    checksum: function () {
      //var hash = X.Session.sha1hash(), data = ;
      //data = X.typeOf(data) === X.T_HASH ? X.json(data) : data;
      //return hash.update(data).digest('hex');
    },

    init: function () {
      this.sid = X.Session.generateSID();
      this.created = X.Session.timestamp();
    },

    generateSID: function () {
      // http://www.ietf.org/rfc/rfc4122.txt
      var s = [];
      var hexDigits = "0123456789abcdef";
      for (var i = 0; i < 36; i++) {
        s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
      }
      s[14] = "4";  // bits 12-15 of the time_hi_and_version field to 0010
      s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);  // bits 6-7 of the clock_seq_hi_and_reserved to 01
      s[8] = s[13] = s[18] = s[23] = "-";

      var uuid = s.join("");
      return uuid;
    },

    timestamp: function () { return new Date().getTime(); },

    sha1hash: function () { return X.crypto.createHash('sha1'); },

    md5hash: function () { return X.crypto.createHash('md5'); },

    /**
      Polls database and logs users out upon session timeout. This method
      can be used to do any actions that are driven from the cache.
     */
    pollCache: function () {
      var sessions = new XM.SessionCollection(),
        i,
        diff,
        ok,
        now,
        model,
        socket,
        sockets,
        options = {};

      sockets = X.Server.getServer("Data").socketsFor("/clientsock");

      options.success = function () {
        ok = (X.options.datasource.sessionTimeout || 15) * 60000;
        now = X.Session.timestamp();

        //console.log("RUNNING", ok, now);

        if (sessions && sessions.length > 0) {
          for (i = 0; i < sessions.length; ++i) {
            model = sessions.at(i);
            diff = Math.abs(now - (model.get('lastModified') || 1000000000));
            if (diff > ok) {
              socket = sockets[model.get('socket')];
              if (socket) {
                socket.emit("timeout");
                socket.disconnect();
              }
              model.destroy();
            }
          }
        }
      };
      options.error = function (model, err) {
        // we have serious issues if we have an error here!
        return issue(X.fatal("error polling cache", err.message(), err.code));
      };
      sessions.fetch(options);
    },

    isActiveSession: function () {
    }
  });

}());
<|endoftext|>


<commit_before>/**
 * Created by pouncilt on 10/21/14.
 */
(function(angular) {
    "use strict";

    angular.module('EscreeningDashboardApp.services.assessmentVariable')
	    .directive('mheAssessmentVarTblDir', ['AssessmentVariableService', 'AssessmentVariableManager', 'MeasureService', 'TemplateBlockService', 'ngTableParams', '$filter', function(AssessmentVariableService, AssessmentVariableManager, MeasureService, TemplateBlockService, ngTableParams, $filter) {

	        return {
	            restrict: 'EA',
	            scope: {
		            assessmentVariable: '=',
		            show: '=',
					block: '='
	            },
				templateUrl: 'resources/editors/js/app/directives/assessmentVariableTable/assessmentVariableTable.html',
	            link: function (scope, element) {

					var parentBlock = AssessmentVariableService.parentBlock || {};

					scope.toggles = {
						list: true,
						transformations: false
					};

		            scope.searchObj = {type: ''};

					scope.assessmentVariableTypes = ['Question', 'Custom', 'Formula'];

					scope.assessmentVariables = AssessmentVariableService.getLastCachedResults().$object;

		            scope.tableParams = new ngTableParams({
						page: 1, // show first page
						count: 10, // count per page
						filter: scope.searchObj
					}, {
						counts: [],
						total: 0,
						getData: function ($defer, params) {
							var avs,
								filteredData;

							if (scope.block && scope.block.type === 'table') {
								// Only display table questions for table block
								filteredData = [];
								_.each(scope.assessmentVariables, function(av) {
									if (av.getMeasureTypeName() === 'table') {
										filteredData.push(av);
									}

								});
							} else {
								if (parentBlock && parentBlock.type === 'table') {
									filteredData = $filter('filter')(scope.assessmentVariables, {parentMeasureId: parentBlock.table.content.measureId});
								} else {
									filteredData = params.filter() ? $filter('filter')(scope.assessmentVariables, params.filter()) : scope.assessmentVariables;

									// Remove child table AVs
									_.each(filteredData, function (av) {
										var parent;
										if (av && av.parentMeasureId) {
											parent = _.find(scope.assessmentVariables, function (fd) {
												return fd.measureId === av.parentMeasureId;
											});

											if (parent && parent.measureTypeId === 4) {
												filteredData = $filter('filter')(scope.assessmentVariables, {parentMeasureId: '!' + parent.measureId});
											}
										}
									});
								}
							}

							avs = filteredData.slice((params.page() - 1) * params.count(), params.page() * params.count());

							params.total(filteredData.length); // set total for recalc pagination
							$defer.resolve(avs);
						},
						$scope: { $data: {} }
					});

		            scope.tableParams.settings().$scope = scope;

		            scope.select = function(e, av) {

			            if (e) e.stopPropagation();

		                if(!scope.assessmentVariable || av.id !== scope.assessmentVariable.id) {
			                // This is needed to trigger a change on in main.js for textAngular (unknown hack)
			                angular.copy(av, scope.assessmentVariable);
			                // This is also needed to the populate the $scope.assessmentVariable
			                scope.assessmentVariable = angular.copy(av);
		                }

						scope.transformationName = (scope.assessmentVariable.id === 6) ? 'appointment' : scope.assessmentVariable.getMeasureTypeName();

						// Do not apply transformations to parent table blocks
						// NOTE: Blocks are not passsed in when directive is called from textAngular
						if (!scope.block || scope.block.type !== 'table') {
							if (scope.assessmentVariable.transformations.length === 0) {
								AssessmentVariableManager.setTransformations(scope.assessmentVariable).then(function (transformations) {
								});
							}

							if (av.getMeasureTypeName() === 'table') {
								// Get the childQuestions table variables
								MeasureService.one(av.measureId).get().then(function (measure) {
									scope.childQuestions = measure.childQuestions;
								});
							}

							// Apply assessmentVariable to block even though it should be done via the two-way data binding
							if (scope.block) {
								scope.block.left.content = scope.assessmentVariable;
							}
						}

						if ((scope.assessmentVariable.type === 'Custom' && scope.assessmentVariable.id !== 6)
							|| scope.transformationName === 'single-select'
							|| (scope.block && scope.block.type === 'table')
							|| (scope.block && scope.assessmentVariable.getMeasureTypeName() === 'multi-select')) {
							scope.show = false;
							scope.$emit('assessmentVariableSelected');

							// Apply AV to block.table for table block types even though it should be working from the view. . .
							if (scope.block && scope.block.type === 'table') {
								scope.block.table.content = scope.assessmentVariable;
							}

						} else if (scope.transformationName === 'freetext') {
							// Doing this manually here because setting transformations is not working as intended
							MeasureService.one(scope.assessmentVariable.measureId).getList('validations').then(function(validations) {
								var found;
								_.each(validations, function (validation) {
									if (validation.value === 'date') {
										found = true;
									}
								});

								if (found) {
									scope.toggles.list = false;
									scope.toggles.transformations = true;
								} else {
									scope.show = false;
									scope.$emit('assessmentVariableSelected');
								}
							});
						} else {
							scope.toggles.list = false;
							scope.toggles.transformations = true;
						}

			            scope.tableParams.reload();
	                };

					scope.applyTransformations = function applyTransformations(newScope) {

						scope.show = false;
						scope.toggles.list = false;
						scope.toggles.transformations = false;

						// Apply select transformation to AV
						if (newScope.transformationType) {
							scope.assessmentVariable.transformations = [newScope.transformationType];
							scope.assessmentVariable.name = newScope.transformationType.name + '_' + scope.assessmentVariable.getName();

							if (newScope.transformationType.params) {

								// Convert delimitedMatrixQuestions rowAvIdToOutputMap array into a list
								if (scope.assessmentVariable.transformations[0].name === 'delimitedMatrixQuestions') {
									scope.assessmentVariable.transformations[0].params[0].join(',');
								}

								// Convert params into strings for freeMarker
								scope.assessmentVariable.transformations[0].params = _.map(newScope.transformationType.params, function(param) {

									return JSON.stringify(param);
								});
							}
							// Remove displayName property which is not to be persisted
							delete scope.assessmentVariable.transformations[0].displayName;
						} else {
							if (scope.assessmentVariable.getMeasureTypeName() === 'table') {
								scope.assessmentVariable.transforamtions = [];
							}
						}

						TemplateBlockService.getVariableHash()[scope.assessmentVariable.id] = scope.assessmentVariable;

						scope.$emit('assessmentVariableSelected');
					};

					scope.dismiss = function dismiss() {
						scope.show = false;
						scope.toggles.transformations = false;
					};

		            element.bind('click', function(e) {
			            // Prevent bubbling
			            e.stopPropagation();
		            });

				}
	        };

	    }]
    );
})(angular);
<commit_msg>t568 Fixed formula in text block bug<commit_after>/**
 * Created by pouncilt on 10/21/14.
 */
(function(angular) {
    "use strict";

    angular.module('EscreeningDashboardApp.services.assessmentVariable')
	    .directive('mheAssessmentVarTblDir', ['AssessmentVariableService', 'AssessmentVariableManager', 'MeasureService', 'TemplateBlockService', 'ngTableParams', '$filter', function(AssessmentVariableService, AssessmentVariableManager, MeasureService, TemplateBlockService, ngTableParams, $filter) {

	        return {
	            restrict: 'EA',
	            scope: {
		            assessmentVariable: '=',
		            show: '=',
					block: '='
	            },
				templateUrl: 'resources/editors/js/app/directives/assessmentVariableTable/assessmentVariableTable.html',
	            link: function (scope, element) {

					var parentBlock = AssessmentVariableService.parentBlock || {};

					scope.toggles = {
						list: true,
						transformations: false
					};

		            scope.searchObj = {type: ''};

					scope.assessmentVariableTypes = ['Question', 'Custom', 'Formula'];

					scope.assessmentVariables = AssessmentVariableService.getLastCachedResults().$object;

		            scope.tableParams = new ngTableParams({
						page: 1, // show first page
						count: 10, // count per page
						filter: scope.searchObj
					}, {
						counts: [],
						total: 0,
						getData: function ($defer, params) {
							var avs,
								filteredData;

							if (scope.block && scope.block.type === 'table') {
								// Only display table questions for table block
								filteredData = [];
								_.each(scope.assessmentVariables, function(av) {
									if (av.getMeasureTypeName() === 'table') {
										filteredData.push(av);
									}

								});
							} else {
								if (parentBlock && parentBlock.type === 'table') {
									filteredData = $filter('filter')(scope.assessmentVariables, {parentMeasureId: parentBlock.table.content.measureId});
								} else {
									filteredData = params.filter() ? $filter('filter')(scope.assessmentVariables, params.filter()) : scope.assessmentVariables;

									// Remove child table AVs
									_.each(filteredData, function (av) {
										var parent;
										if (av && av.parentMeasureId) {
											parent = _.find(scope.assessmentVariables, function (fd) {
												return fd.measureId === av.parentMeasureId;
											});

											if (parent && parent.measureTypeId === 4) {
												filteredData = $filter('filter')(scope.assessmentVariables, {parentMeasureId: '!' + parent.measureId});
											}
										}
									});
								}
							}

							avs = filteredData.slice((params.page() - 1) * params.count(), params.page() * params.count());

							params.total(filteredData.length); // set total for recalc pagination
							$defer.resolve(avs);
						},
						$scope: { $data: {} }
					});

		            scope.tableParams.settings().$scope = scope;

		            scope.select = function(e, av) {

			            if (e) e.stopPropagation();

		                if(!scope.assessmentVariable || av.id !== scope.assessmentVariable.id) {
			                // This is needed to trigger a change on in main.js for textAngular (unknown hack)
			                angular.copy(av, scope.assessmentVariable);
			                // This is also needed to the populate the $scope.assessmentVariable
			                scope.assessmentVariable = angular.copy(av);
		                }

						scope.transformationName = (scope.assessmentVariable.id === 6) ? 'appointment' : scope.assessmentVariable.getMeasureTypeName();

						// Do not apply transformations to parent table blocks
						// NOTE: Blocks are not passsed in when directive is called from textAngular
						if (!scope.block || scope.block.type !== 'table') {
							if (scope.assessmentVariable.transformations.length === 0) {
								AssessmentVariableManager.setTransformations(scope.assessmentVariable).then(function (transformations) {
								});
							}

							if (av.getMeasureTypeName() === 'table') {
								// Get the childQuestions table variables
								MeasureService.one(av.measureId).get().then(function (measure) {
									scope.childQuestions = measure.childQuestions;
								});
							}

							// Apply assessmentVariable to block even though it should be done via the two-way data binding
							if (scope.block) {
								scope.block.left.content = scope.assessmentVariable;
							}
						}

						if ((scope.assessmentVariable.type === 'Custom' && scope.assessmentVariable.id !== 6)
							|| scope.transformationName === 'single-select'
							|| (scope.block && scope.block.type === 'table')
							|| (scope.block && scope.assessmentVariable.getMeasureTypeName() === 'multi-select'
							|| scope.assessmentVariable.type === 'Formula')) {
							scope.show = false;
							scope.$emit('assessmentVariableSelected');

							// Apply AV to block.table for table block types even though it should be working from the view. . .
							if (scope.block && scope.block.type === 'table') {
								scope.block.table.content = scope.assessmentVariable;
							}

						} else if (scope.transformationName === 'freetext') {
							// Doing this manually here because setting transformations is not working as intended
							MeasureService.one(scope.assessmentVariable.measureId).getList('validations').then(function(validations) {
								var found;
								_.each(validations, function (validation) {
									if (validation.value === 'date') {
										found = true;
									}
								});

								if (found) {
									scope.toggles.list = false;
									scope.toggles.transformations = true;
								} else {
									scope.show = false;
									scope.$emit('assessmentVariableSelected');
								}
							});
						} else {
							scope.toggles.list = false;
							scope.toggles.transformations = true;
						}

			            scope.tableParams.reload();
	                };

					scope.applyTransformations = function applyTransformations(newScope) {

						scope.show = false;
						scope.toggles.list = false;
						scope.toggles.transformations = false;

						// Apply select transformation to AV
						if (newScope.transformationType) {
							scope.assessmentVariable.transformations = [newScope.transformationType];
							scope.assessmentVariable.name = newScope.transformationType.name + '_' + scope.assessmentVariable.getName();

							if (newScope.transformationType.params) {

								// Convert delimitedMatrixQuestions rowAvIdToOutputMap array into a list
								if (scope.assessmentVariable.transformations[0].name === 'delimitedMatrixQuestions') {
									scope.assessmentVariable.transformations[0].params[0].join(',');
								}

								// Convert params into strings for freeMarker
								scope.assessmentVariable.transformations[0].params = _.map(newScope.transformationType.params, function(param) {

									return JSON.stringify(param);
								});
							}
							// Remove displayName property which is not to be persisted
							delete scope.assessmentVariable.transformations[0].displayName;
						} else {
							if (scope.assessmentVariable.getMeasureTypeName() === 'table') {
								scope.assessmentVariable.transforamtions = [];
							}
						}

						TemplateBlockService.getVariableHash()[scope.assessmentVariable.id] = scope.assessmentVariable;

						scope.$emit('assessmentVariableSelected');
					};

					scope.dismiss = function dismiss() {
						scope.show = false;
						scope.toggles.transformations = false;
					};

		            element.bind('click', function(e) {
			            // Prevent bubbling
			            e.stopPropagation();
		            });

				}
	        };

	    }]
    );
})(angular);
<|endoftext|>


<commit_before>/**
 * Add the collection
 */
_.extend(Posts, {
  /**
   * Add the collection
   * @type {Meteor}
   */
  collection:  new Meteor.Collection('posts'),

  /**
   * Create a post
   */
  create: function(post, callback) {
    return Posts.collection.insert(post, callback);
  },

  /**
   * Create a new draft post object
   */
  draft: function(callback) {
    return Posts.collection.insert({
      title:    "Draft",
      content:  "",
      draft: true
    }, callback);
  },

  /**
   * Update a post entity with changes given in a key/value
   * pair.
   */
  update: function(postId, changes, callback) {
    return Posts.collection.update({_id: postId}, {"$set": changes}, callback);
  },

  /**
   * Add a tag to a blog post
   * @param {String} postId Post ids
   * @param {String} tag    Tag value
   */
  addTags: function(postId, tags, callback) {
    Posts.collection.update({_id: postId}, {"$addToSet": {tags: {"$each": tags}}}, callback);
  },

  /**
   * Add a tag to a blog post
   * @param {String} postId Post ids
   * @param {String} tag    Tag value
   */
  removeTag: function(postId, tag, callback) {
    Posts.collection.update({_id: postId}, {"$pull": {tags: tag}}, callback);
  },

  /**
   * Add a category to a blog post
   * @param {String} postId     Post id
   * @param {String} categroy   Category id
   */
  addCategory: function(postId, category, callback) {
    Posts.collection.update({_id: postId}, {"$addToSet": {categories: category}}, callback);
  },

  /**
   * Add a category to a blog post
   * @param {String} postId     Post ids
   * @param {String} category   Tag value
   */
  removeCategory: function(postId, category, callback) {
    Posts.collection.update({_id: postId}, {"$pull": {categories: category}}, callback);
  },

  /**
   * Return the top latest posts
   * @return {Mongo.Cursor}
   */
  latest: function(limit, callback) {
    return Posts.collection.find({}, {"$limit": limit || 10}, callback)
  },

  /**
   * Return the top latest posts
   * @return {Mongo.Cursor}
   */
  all: function(callback) {
    return Posts.collection.find({}, {}, callback);
  },

  /**
   * Find
   * @param  {[type]} clause [description]
   * @return {[type]}        [description]
   */
  where: function(clause, callback) {
    return Posts.collection.find(clause, {}, callback);
  },

  /**
   * Return a single post
   * @param  {String} id Post id
   * @return {Document}
   */
  get: function(id, callback) {
    return Posts.collection.findOne({_id: id}, {}, callback);
  },

  /**
   * Remove a post
   * @param  {Stirng} id object ID
   */
  remove: function(id, callback) {
    return Posts.collection.remove({_id: id}, callback);
  }
});
<commit_msg>Add published method to posts model<commit_after>/**
 * Add the collection
 */
_.extend(Posts, {
  /**
   * Add the collection
   * @type {Meteor}
   */
  collection:  new Meteor.Collection('posts'),

  /**
   * Create a post
   */
  create: function(post, callback) {
    return Posts.collection.insert(post, callback);
  },

  /**
   * Create a new draft post object
   */
  draft: function(callback) {
    return Posts.collection.insert({
      title:    "Draft",
      content:  "",
      draft: true
    }, callback);
  },

  /**
   * Update a post entity with changes given in a key/value
   * pair.
   */
  update: function(postId, changes, callback) {
    return Posts.collection.update({_id: postId}, {"$set": changes}, callback);
  },

  /**
   * Add a tag to a blog post
   * @param {String} postId Post ids
   * @param {String} tag    Tag value
   */
  addTags: function(postId, tags, callback) {
    Posts.collection.update({_id: postId}, {"$addToSet": {tags: {"$each": tags}}}, callback);
  },

  /**
   * Add a tag to a blog post
   * @param {String} postId Post ids
   * @param {String} tag    Tag value
   */
  removeTag: function(postId, tag, callback) {
    Posts.collection.update({_id: postId}, {"$pull": {tags: tag}}, callback);
  },

  /**
   * Add a category to a blog post
   * @param {String} postId     Post id
   * @param {String} categroy   Category id
   */
  addCategory: function(postId, category, callback) {
    Posts.collection.update({_id: postId}, {"$addToSet": {categories: category}}, callback);
  },

  /**
   * Add a category to a blog post
   * @param {String} postId     Post ids
   * @param {String} category   Tag value
   */
  removeCategory: function(postId, category, callback) {
    Posts.collection.update({_id: postId}, {"$pull": {categories: category}}, callback);
  },

  /**
   * Return the top latest posts
   * @return {Mongo.Cursor}
   */
  latest: function(limit, callback) {
    return Posts.collection.find({}, {"$limit": limit || 10}, callback)
  },

  /**
   * Return the top latest posts
   * @return {Mongo.Cursor}
   */
  all: function(callback) {
    return Posts.collection.find({}, {}, callback);
  },

  /**
   * Return the latest published posts
   * @return {Mongo.Cursor}
   */
  published: function(callback) {
    return Posts.where({published: true, draft: false}, callback);
  },

  /**
   * Find
   * @param  {[type]} clause [description]
   * @return {[type]}        [description]
   */
  where: function(clause, callback) {
    return Posts.collection.find(clause, {}, callback);
  },

  /**
   * Return a single post
   * @param  {String} id Post id
   * @return {Document}
   */
  get: function(id, callback) {
    return Posts.collection.findOne({_id: id}, {}, callback);
  },

  /**
   * Remove a post
   * @param  {Stirng} id object ID
   */
  remove: function(id, callback) {
    return Posts.collection.remove({_id: id}, callback);
  }
});
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011 Vinay Pulim <vinay@milewise.com>
 * MIT Licensed
 */

var http = require('./http'),
    assert = require('assert');

var Client = function(wsdl) {
    this.wsdl = wsdl;
    this._initializeServices(null);
}

Client.prototype.setEndpoint = function(endpoint) {
    this.endpoint = endpoint;
    this._initializeServices(endpoint);
}

Client.prototype.describe = function() {
    return this.wsdl.describeServices();
}

Client.prototype.setSecurity = function(security) {
    this.security = security;
}

Client.prototype._initializeServices = function(endpoint) {
    var definitions = this.wsdl.definitions,
        services = definitions.services;
    for (var name in services) {
        this[name] = this._defineService(services[name], endpoint);
    }
}

Client.prototype._defineService = function(service, endpoint) {
    var ports = service.ports,
        def = {};
    for (var name in ports) {
        def[name] = this._definePort(ports[name], endpoint ? endpoint : ports[name].location);
    }
    return def;
}

Client.prototype._definePort = function(port, endpoint) {
    var location = endpoint,
        binding = port.binding,
        methods = binding.methods,
        def = {};
    for (var name in methods) {
        def[name] = this._defineMethod(methods[name], location);
        if (!this[name]) this[name] = def[name];
    }
    return def;
}

Client.prototype._defineMethod = function(method, location) {
    var self = this;
    return function(args, callback) {
        if (typeof args === 'function') {
            callback = args;
            args = {};
        }
        self._invoke(method, args, location, function(error, result) {
            callback(error, result);
        })
    }
}

Client.prototype._invoke = function(method, arguments, location, callback) {
    var self = this,
        name = method.$name,
        input = method.input,
        output = method.output,
        style = method.style,
        defs = this.wsdl.definitions,
        ns = defs.$targetNamespace,
        encoding = '';
        message = '';
        xml = null,
        headers = {
            SOAPAction: ((ns.lastIndexOf("/") != ns.length - 1) ? ns + "/" : ns) + name,
            'Content-Type': "text/xml; charset=utf-8"
        };
        options = {};

    // Allow the security object to add headers
    if (self.security && self.security.addHeaders)
        self.security.addHeaders(headers);
    if (self.security && self.security.addOptions)
        self.security.addOptions(options);

    if (input.element) {
        assert.ok(style == 'document', 'invalid message definition for rpc style binding');
        message = self.wsdl.objectToDocumentXML(input.element.$name, arguments);
    }
    else {
        assert.ok(style == 'rpc', 'invalid message definition for document style binding');
        message = self.wsdl.objectToRpcXML(name, arguments);
        encoding = 'soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" ';
    }
    xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
        "<soap:Envelope " +
            "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" " +
            encoding +
            "xmlns:ns0=\""+ns+"\">" +
            "<soap:Header>" +
                (self.security ? self.security.toXML() : "") +
            "</soap:Header>" +
            "<soap:Body>" +
                message +
            "</soap:Body>" +
        "</soap:Envelope>";

    http.request(location, xml, function(err, response, body) {
        if (err) {
            callback(err);
        }
        else {
            try {
                var obj = self.wsdl.xmlToObject(body);
                callback(null, obj[output.$name]);
            }
            catch (error) {
                callback(error);
            }
        }
    }, headers, options);
}

exports.Client = Client;
<commit_msg>input no longer contains an element so use input.parts instead to recognize a document-style binding<commit_after>/*
 * Copyright (c) 2011 Vinay Pulim <vinay@milewise.com>
 * MIT Licensed
 */

var http = require('./http'),
    assert = require('assert');

var Client = function(wsdl) {
    this.wsdl = wsdl;
    this._initializeServices(null);
}

Client.prototype.setEndpoint = function(endpoint) {
    this.endpoint = endpoint;
    this._initializeServices(endpoint);
}

Client.prototype.describe = function() {
    return this.wsdl.describeServices();
}

Client.prototype.setSecurity = function(security) {
    this.security = security;
}

Client.prototype._initializeServices = function(endpoint) {
    var definitions = this.wsdl.definitions,
        services = definitions.services;
    for (var name in services) {
        this[name] = this._defineService(services[name], endpoint);
    }
}

Client.prototype._defineService = function(service, endpoint) {
    var ports = service.ports,
        def = {};
    for (var name in ports) {
        def[name] = this._definePort(ports[name], endpoint ? endpoint : ports[name].location);
    }
    return def;
}

Client.prototype._definePort = function(port, endpoint) {
    var location = endpoint,
        binding = port.binding,
        methods = binding.methods,
        def = {};
    for (var name in methods) {
        def[name] = this._defineMethod(methods[name], location);
        if (!this[name]) this[name] = def[name];
    }
    return def;
}

Client.prototype._defineMethod = function(method, location) {
    var self = this;
    return function(args, callback) {
        if (typeof args === 'function') {
            callback = args;
            args = {};
        }
        self._invoke(method, args, location, function(error, result) {
            callback(error, result);
        })
    }
}

Client.prototype._invoke = function(method, arguments, location, callback) {
    var self = this,
        name = method.$name,
        input = method.input,
        output = method.output,
        style = method.style,
        defs = this.wsdl.definitions,
        ns = defs.$targetNamespace,
        encoding = '';
        message = '';
        xml = null,
        headers = {
            SOAPAction: ((ns.lastIndexOf("/") != ns.length - 1) ? ns + "/" : ns) + name,
            'Content-Type': "text/xml; charset=utf-8"
        };
        options = {};

    // Allow the security object to add headers
    if (self.security && self.security.addHeaders)
        self.security.addHeaders(headers);
    if (self.security && self.security.addOptions)
        self.security.addOptions(options);

    if (input.parts) {
        assert.ok(style == 'rpc', 'invalid message definition for document style binding');
        message = self.wsdl.objectToRpcXML(name, arguments);
        encoding = 'soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" ';
    }
    else {
        assert.ok(style == 'document', 'invalid message definition for rpc style binding');
        message = self.wsdl.objectToDocumentXML(input.$name, arguments);
    }
    xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
        "<soap:Envelope " +
            "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" " +
            encoding +
            "xmlns:ns0=\""+ns+"\">" +
            "<soap:Header>" +
                (self.security ? self.security.toXML() : "") +
            "</soap:Header>" +
            "<soap:Body>" +
                message +
            "</soap:Body>" +
        "</soap:Envelope>";

    http.request(location, xml, function(err, response, body) {
        if (err) {
            callback(err);
        }
        else {
            try {
                var obj = self.wsdl.xmlToObject(body);
                callback(null, obj[output.$name]);
            }
            catch (error) {
                callback(error);
            }
        }
    }, headers, options);
}

exports.Client = Client;
<|endoftext|>


<commit_before>function getComment(db, commentId, callback) {
    db.collection('comments').findOne({"_id": commentId }, function(err, comment) {

        if(err) {
            callback({
                "success" : false,
                "error": err,
                "errorType": "database"
            });
            return;
        }

        comment.success = true;
        callback(comment);
    });
}

function createComment(db, userId, postId, text, type, href, callback) {
    var comment = {
        "userId": userId,
        "postId": postId,
        "text": text,
        "type": type,
        "href": href,
        "createdOn": Date.now(),
        "votes": {
            "upvotes": 0,
            "downvotes": 0
        }
    };

    db.collection('comments').insert(comment, function(err, inserted) {

        if(err){
            callback( {
                "success": false,
                "error": err,
                "errorType": "database"
            });
            return;
        }

        inserted.success = true;
        callback(inserted);
    })
}

function deleteComment(db, commentId, callback) {
    db.collection('comments').remove({ "_id": commentId }, function(err, removed) {
        if(err) {
            callback({
                "success": false,
                "error": err,
                "errorType": "database"
            });
            return;
        }

        result.success = true;
        callback(removed);
    });
}

function getComments(db, postId, callback) {
    var numberOfComments = 50;
    db.collection('posts').find({"$query": {"postId": postId}, "$orderBy": { "createdOn" : -1 } }).limit(numberOfComments).toArray(function(result) {
        if(err) {
            callback({
                "success": false,
                "error": err,
                "errorType": "database"
            });
            return;
        }

        callback(result);
    });
}

function incrementCommentUpvotes(db, commentId, callback) {
    db.collection('comments').update({ "_id": commentId }, { "$inc": { "votes.$.upvotes": 1 } }, function(err, result) {
        if(err) {
            callback({
                "success": false,
                "error": err,
                "errorType": "database"
            });
            return;
        }

        result.success = true;
        callback(result);
    });
}

function decrementCommentUpvotes(db, commentId, callback) {
    db.collection('comments').update({ "_id": commentId }, { "$inc": { "votes.$.upvotes": -1 } }, function(err, result) {
        if(err) {
            callback({
                "success": false,
                "error": err,
                "errorType": "database"
            });
            return;
        }

        result.success = true;
        callback(result);
    });
}

function incrementCommentDownvotes(db, commentId, callback) {
    db.collection('comments').update({ "_id": commentId }, { "$inc": { "votes.$.downvotes": 1 } }, function(err, result) {
        if(err) {
            callback({
                "success": false,
                "error": err,
                "errorType": "database"
            });
            return;
        }

        result.success = true;
        callback(result);
    });
}

function decrementCommentDownvotes(db, commentId, callback) {
    db.collection('comments').update({ "_id": commentId }, { "$inc": { "votes.$.downvotes": -1 } }, function(err, result) {
        if(err) {
            callback({
                "success": false,
                "error": err,
                "errorType": "database"
            });
            return;
        }

        result.success = true;
        callback(result);
    });
}

module.exports = {
    getComment: getComment,
    createComment: createComment,
    deleteComment: deleteComment,
    getComments: getComments,
    incrementCommentUpvotes: incrementCommentUpvotes,
    decrementCommentUpvotes: decrementCommentUpvotes,
    incrementCommentDownvotes: incrementCommentDownvotes,
    decrementCommentDownvotes: decrementCommentDownvotes
}
<commit_msg>creating comment updates comment count on post object<commit_after>function getComment(db, commentId, callback) {
    db.collection('comments').findOne({"_id": commentId }, function(err, comment) {

        if(err) {
            callback({
                "success" : false,
                "error": err,
                "errorType": "database"
            });
            return;
        }

        comment.success = true;
        callback(comment);
    });
}

function createComment(db, userId, postId, text, type, href, callback) {
    var comment = {
        "userId": userId,
        "postId": postId,
        "text": text,
        "type": type,
        "href": href,
        "createdOn": Date.now(),
        "votes": {
            "upvotes": 0,
            "downvotes": 0
        }
    };

    db.collection('comments').insert(comment, function(err, inserted) {

        if(err){
            callback( {
                "success": false,
                "error": err,
                "errorType": "database"
            });
            return;
        }

        var commentTypePath = "comments$" + type;
        var toUpdate = { "$inc": { } };
        toUpdate["$inc"][commentTypePath] = 1;

        db.collection('posts').update({ "_id": postId }, toUpdate, function(err, result) {
            if(err) {
                callback({
                    "success": false,
                    "error": err,
                    "errorType": "database"
                });
                return;
            }

            inserted.success = true;
            callback(inserted);
        });
    })
}

function deleteComment(db, commentId, callback) {
    db.collection('comments').remove({ "_id": commentId }, function(err, removed) {
        if(err) {
            callback({
                "success": false,
                "error": err,
                "errorType": "database"
            });
            return;
        }

        result.success = true;
        callback(removed);
    });
}

function getComments(db, postId, callback) {
    var numberOfComments = 50;
    db.collection('posts').find({"$query": {"postId": postId}, "$orderBy": { "createdOn" : -1 } }).limit(numberOfComments).toArray(function(result) {
        if(err) {
            callback({
                "success": false,
                "error": err,
                "errorType": "database"
            });
            return;
        }

        callback(result);
    });
}

function incrementCommentUpvotes(db, commentId, callback) {
    db.collection('comments').update({ "_id": commentId }, { "$inc": { "votes.$.upvotes": 1 } }, function(err, result) {
        if(err) {
            callback({
                "success": false,
                "error": err,
                "errorType": "database"
            });
            return;
        }

        result.success = true;
        callback(result);
    });
}

function decrementCommentUpvotes(db, commentId, callback) {
    db.collection('comments').update({ "_id": commentId }, { "$inc": { "votes.$.upvotes": -1 } }, function(err, result) {
        if(err) {
            callback({
                "success": false,
                "error": err,
                "errorType": "database"
            });
            return;
        }

        result.success = true;
        callback(result);
    });
}

function incrementCommentDownvotes(db, commentId, callback) {
    db.collection('comments').update({ "_id": commentId }, { "$inc": { "votes.$.downvotes": 1 } }, function(err, result) {
        if(err) {
            callback({
                "success": false,
                "error": err,
                "errorType": "database"
            });
            return;
        }

        result.success = true;
        callback(result);
    });
}

function decrementCommentDownvotes(db, commentId, callback) {
    db.collection('comments').update({ "_id": commentId }, { "$inc": { "votes.$.downvotes": -1 } }, function(err, result) {
        if(err) {
            callback({
                "success": false,
                "error": err,
                "errorType": "database"
            });
            return;
        }

        result.success = true;
        callback(result);
    });
}

module.exports = {
    getComment: getComment,
    createComment: createComment,
    deleteComment: deleteComment,
    getComments: getComments,
    incrementCommentUpvotes: incrementCommentUpvotes,
    decrementCommentUpvotes: decrementCommentUpvotes,
    incrementCommentDownvotes: incrementCommentDownvotes,
    decrementCommentDownvotes: decrementCommentDownvotes
}
<|endoftext|>