<commit_before>/*
 * FastrSlowrPlayrUI
 *
 * A jQuery plugin which wraps FastrSlowrPlayr and creates a default UI (skinnable using
 * the jQuery UI framework)
 *
 * Copyright (c) 2009 Kelvin Luck
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://www.kelvinluck.com/projects/fastrslowrplayr
 *
 * Depends:
 *   fastrSlowrPlayr.js
 *   SWFObject
 *   FastrSlowrPlayr.swf
 */
(function($) {

	$.fn.fastrSlowrPlayr = function(settings)
	{
		var settings = $.extend({}, $.fn.fastrSlowrPlayr.defaults, settings);
		var i = 0;
		return this.each(
			function()
			{
				var $this = $(this);

				settings.elementId = '__fsp_' + i;
				$this
					.append('

')
					.addClass('ui-widget ui-widget-content fsp-container')
					;

				var player = FastrSlowrPlayr.init(settings);

				if (settings.showPlayPauseButton) {
					var iconDiv = $('
' + settings.labelPlay + '
')
						.addClass('ui-icon ui-icon-play');
					var playButton = $('')
						.addClass('fsp-button ui-state-default')
						.attr('title', settings.labelPlay)
						.hover(
							function()
							{
								playButton.addClass('ui-state-hover');
							},
							function()
							{
								playButton.removeClass('ui-state-hover');
							}
						)
						.bind(
							'click',
							function(event)
							{
								player[player.getIsPlaying() ? 'pause' : 'play']();
							}
						);
					playButton.append(iconDiv);

					$this.append(playButton);
				}
				if (settings.showStopButton) {
					var stopButton = $('
' + settings.labelStop + '
')
						.addClass('fsp-button ui-state-default')
						.attr('title', settings.labelStop)
						.bind(
							'click',
							function(event)
							{
								player.stop();
							}
						)
						.hover(
							function()
							{
								stopButton.addClass('ui-state-hover');
							},
							function()
							{
								stopButton.removeClass('ui-state-hover');
							}
						);

					$this.append(stopButton);
				}

				// set up event listeners to actually trigger "proper" jQuery events...
				player.addEventListener(
					FastrSlowrPlayr.EVENT_MP3_LOADED,
					function(length)
					{
						$this.trigger(FastrSlowrPlayr.EVENT_MP3_LOADED, length);
					}
				);
				player.addEventListener(
					FastrSlowrPlayr.EVENT_MP3_COMPLETE,
					function()
					{
						$this.trigger(FastrSlowrPlayr.EVENT_MP3_COMPLETE);
					}
				);
				player.addEventListener(
					FastrSlowrPlayr.EVENT_ID3_AVAILABLE,
					function(id3Data)
					{
						if (id3Data) {
							$this.trigger(FastrSlowrPlayr.EVENT_ID3_AVAILABLE, id3Data);
							// it seems to be triggered multiple times - we only want the first one...
							player.removeEventListener(FastrSlowrPlayr.EVENT_ID3_AVAILABLE);
							// TODO: Reinstate the listener if load called...
						}
					}
				);
				player.addEventListener(
					FastrSlowrPlayr.PLAY_STATE_CHANGE,
					function(isPlaying)
					{
						if (playButton) {
							if (isPlaying) {
								playButton.attr('title', settings.labelPause);
								iconDiv
									.text(settings.labelPause)
									.removeClass('ui-icon-play')
									.addClass('ui-icon-pause');
							} else {
								playButton.attr('title', settings.labelPlay);
								iconDiv
									.text(settings.labelPlay)
									.removeClass('ui-icon-pause')
									.addClass('ui-icon-play');
							}
						}
					}
				);
				i++;
			}
		);
	}

	$.fn.fastrSlowrPlayr.defaults = {
		/* FastrSlowrPlayr settings */
		volume:			1,
		pan:			0,
		autoplay:		false,
		playbackSpeed:	1,
		mp3File:		null,
		swfPath:		'../swf/FastrSlowrPlayr.swf',
		loop:			false,
		/* settings to control which UI features are displayed */
		showPlayPauseButton: true,
		showStopButton:	true,
		showProgressBar: true,
		showSongInfo:	false,
		showLoadingBar:	true,
		/* localisation strings */
		labelPlay:		'Play',
		labelPause:		'Pause',
		labelStop:		'Stop'
	};

})(jQuery);
<commit_msg>Clearer naming for local ui elements variables to avoid confusion later on...<commit_after>/*
 * FastrSlowrPlayrUI
 *
 * A jQuery plugin which wraps FastrSlowrPlayr and creates a default UI (skinnable using
 * the jQuery UI framework)
 *
 * Copyright (c) 2009 Kelvin Luck
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://www.kelvinluck.com/projects/fastrslowrplayr
 *
 * Depends:
 *   fastrSlowrPlayr.js
 *   SWFObject
 *   FastrSlowrPlayr.swf
 */
(function($) {

	$.fn.fastrSlowrPlayr = function(settings)
	{
		var settings = $.extend({}, $.fn.fastrSlowrPlayr.defaults, settings);
		var i = 0;
		return this.each(
			function()
			{
				var $this = $(this);

				settings.elementId = '__fsp_' + i;
				$this
					.append('

')
					.addClass('ui-widget ui-widget-content fsp-container')
					;

				var player = FastrSlowrPlayr.init(settings);

				if (settings.showPlayPauseButton) {
					var playPauseIconDiv = $('
' + settings.labelPlay + '
')
						.addClass('ui-icon ui-icon-play');
					var playPauseButton = $('')
						.addClass('fsp-button ui-state-default')
						.attr('title', settings.labelPlay)
						.hover(
							function()
							{
								playPauseButton.addClass('ui-state-hover');
							},
							function()
							{
								playPauseButton.removeClass('ui-state-hover');
							}
						)
						.bind(
							'click',
							function(event)
							{
								player[player.getIsPlaying() ? 'pause' : 'play']();
							}
						);
					playPauseButton.append(playPauseIconDiv);

					$this.append(playPauseButton);
				}
				if (settings.showStopButton) {
					var stopButton = $('
' + settings.labelStop + '
')
						.addClass('fsp-button ui-state-default')
						.attr('title', settings.labelStop)
						.bind(
							'click',
							function(event)
							{
								player.stop();
							}
						)
						.hover(
							function()
							{
								stopButton.addClass('ui-state-hover');
							},
							function()
							{
								stopButton.removeClass('ui-state-hover');
							}
						);

					$this.append(stopButton);
				}

				// set up event listeners to actually trigger "proper" jQuery events...
				player.addEventListener(
					FastrSlowrPlayr.EVENT_MP3_LOADED,
					function(length)
					{
						$this.trigger(FastrSlowrPlayr.EVENT_MP3_LOADED, length);
					}
				);
				player.addEventListener(
					FastrSlowrPlayr.EVENT_MP3_COMPLETE,
					function()
					{
						$this.trigger(FastrSlowrPlayr.EVENT_MP3_COMPLETE);
					}
				);
				player.addEventListener(
					FastrSlowrPlayr.EVENT_ID3_AVAILABLE,
					function(id3Data)
					{
						if (id3Data) {
							$this.trigger(FastrSlowrPlayr.EVENT_ID3_AVAILABLE, id3Data);
							// it seems to be triggered multiple times - we only want the first one...
							player.removeEventListener(FastrSlowrPlayr.EVENT_ID3_AVAILABLE);
							// TODO: Reinstate the listener if load called...
						}
					}
				);
				player.addEventListener(
					FastrSlowrPlayr.PLAY_STATE_CHANGE,
					function(isPlaying)
					{
						if (playPauseButton) {
							if (isPlaying) {
								playPauseButton.attr('title', settings.labelPause);
								playPauseIconDiv
									.text(settings.labelPause)
									.removeClass('ui-icon-play')
									.addClass('ui-icon-pause');
							} else {
								playPauseButton.attr('title', settings.labelPlay);
								playPauseIconDiv
									.text(settings.labelPlay)
									.removeClass('ui-icon-pause')
									.addClass('ui-icon-play');
							}
						}
					}
				);
				i++;
			}
		);
	}

	$.fn.fastrSlowrPlayr.defaults = {
		/* FastrSlowrPlayr settings */
		volume:			1,
		pan:			0,
		autoplay:		false,
		playbackSpeed:	1,
		mp3File:		null,
		swfPath:		'../swf/FastrSlowrPlayr.swf',
		loop:			false,
		/* settings to control which UI features are displayed */
		showPlayPauseButton: true,
		showStopButton:	true,
		showProgressBar: true,
		showSongInfo:	false,
		showLoadingBar:	true,
		/* localisation strings */
		labelPlay:		'Play',
		labelPause:		'Pause',
		labelStop:		'Stop'
	};

})(jQuery);
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
'use strict';

angular.module('ambariAdminConsole')
.controller('UserEditCtrl',
['$scope', '$rootScope', '$routeParams', 'Cluster', 'User', 'View', '$modal', '$location', 'ConfirmationModal', 'Alert', 'Auth', 'getDifference', 'Group', '$q', 'UserConstants', '$translate', 'RoleDetailsModal',
function($scope, $rootScope, $routeParams, Cluster, User, View, $modal, $location, ConfirmationModal, Alert, Auth, getDifference, Group, $q, UserConstants, $translate, RoleDetailsModal) {

  var $t = $translate.instant;
  var nonRole = {
    permission_name: 'NONE',
    permission_label: $t('users.roles.none')
  };

  $scope.constants = {
    user: $t('common.user'),
    status: $t('users.status'),
    admin: $t('users.admin'),
    password: $t('users.password'),
    view: $t('common.view').toLowerCase(),
    cluster: $t('common.cluster').toLowerCase()
  };

  $scope.user = null;
  $scope.isCurrentUser = true;
  $scope.dataLoaded = false;
  $scope.isGroupEditing = false;

  $scope.enableGroupEditing = function () {
    $scope.isGroupEditing = true;
    $scope.editingGroupsList = angular.copy($scope.user.groups);
  };

  $scope.$watch(function () {
    return $scope.editingGroupsList;
  }, function (newValue) {
    if (newValue) {
      if (!angular.equals(newValue, $scope.user.groups)) {
        $scope.updateGroups();
      }
    }
  }, true);

  $scope.showHelpPage = function() {
    Cluster.getRolesWithAuthorizations().then(function(roles) {
      RoleDetailsModal.show(roles);
    });
  };

  $scope.updateRole = function () {
    var clusterName = $rootScope.cluster.Clusters.cluster_name;
    if ($scope.originalRole.permission_name !== $scope.currentRole.permission_name) {
      if ($scope.currentRole.permission_name === 'NONE') {
        deleteUserRoles(clusterName, $scope.user).finally(loadUserInfo);
      } else {
        if ($scope.user.roles.length) {
          deleteUserRoles(clusterName, $scope.user, true).finally(function() {
            addUserRoles(clusterName, $scope.currentRole, $scope.user).finally(loadUserInfo);
          });
        } else {
          addUserRoles(clusterName, $scope.currentRole, $scope.user).finally(loadUserInfo);
        }
      }
    }
  };

  $scope.updateGroups = function () {
    var groups = $scope.editingGroupsList.filter(function (item) {
      return item.trim();
    }).map(function (item) {
      return item.trim();
    });
    var diff = getDifference($scope.user.groups, groups);
    var promises = [];
    // Remove user from groups
    angular.forEach(diff.del, function (groupName) {
      promises.push(Group.removeMemberFromGroup(groupName, $scope.user.user_name).catch(function (data) {
        Alert.error($t('users.alerts.removeUserError'), data.data.message);
      }));
    });
    // Add user to groups
    angular.forEach(diff.add, function (groupName) {
      promises.push(Group.addMemberToGroup(groupName, $scope.user.user_name).catch(function (data) {
        Alert.error($t('users.alerts.cannotAddUser'), data.data.message);
      }));
    });
    $q.all(promises).then(function () {
      loadUserInfo();
    });
    $scope.isGroupEditing = false;
  };

  $scope.getUserMembership = function (userType) {
    if (userType) {
      return $t(UserConstants.TYPES[userType].LABEL_KEY) + " " + $t('users.groupMembership');
    }
  };

  $scope.cancelUpdate = function () {
    $scope.isGroupEditing = false;
    $scope.editingGroupsList = '';
  };

  $scope.openChangePwdDialog = function () {
    var modalInstance = $modal.open({
      templateUrl: 'views/userManagement/modals/changePassword.html',
      resolve: {
        userName: function () {
          return $scope.user.user_name;
        }
      },
      controller: ['$scope', 'userName', function ($scope, userName) {
        $scope.passwordData = {
          password: '',
          currentUserPassword: ''
        };

        $scope.form = {};
        $scope.userName = userName;

        $scope.ok = function () {
          $scope.form.passwordChangeForm.submitted = true;
          if ($scope.form.passwordChangeForm.$valid) {
            modalInstance.close({
              password: $scope.passwordData.password,
              currentUserPassword: $scope.passwordData.currentUserPassword
            });
          }
        };
        $scope.cancel = function () {
          modalInstance.dismiss('cancel');
        };
      }]
    });

    modalInstance.result.then(function (data) {
      User.setPassword($scope.user, data.password, data.currentUserPassword).then(function () {
        Alert.success($t('users.alerts.passwordChanged'));
      }).catch(function (data) {
        Alert.error($t('users.alerts.cannotChangePassword'), data.data.message);
      });
    });
  };

  $scope.toggleUserActive = function () {
    if (!$scope.isCurrentUser) {
      var newStatusKey = $scope.user.active ? 'inactive' : 'active';
      ConfirmationModal.show(
        $t('users.changeStatusConfirmation.title'),
        $t('users.changeStatusConfirmation.message', {
          userName: $scope.user.user_name,
          status: $t('users.' + newStatusKey).toLowerCase()
        })
      ).then(function () {
        User.setActive($scope.user.user_name, $scope.user.active)
        .catch(function (data) {
          Alert.error($t('common.alerts.cannotUpdateStatus'), data.data.message);
          $scope.user.active = !$scope.user.active;
        });
      })
      .catch(function () {
        $scope.user.active = !$scope.user.active;
      });
    }
  };

  $scope.toggleUserAdmin = function () {
    if (!$scope.isCurrentUser) {
      var action = $scope.user.admin ?
        $t('users.changePrivilegeConfirmation.revoke') : $t('users.changePrivilegeConfirmation.grant');
      ConfirmationModal.show(
        $t('users.changePrivilegeConfirmation.title'),
        $t('users.changePrivilegeConfirmation.message', {
          action: action,
          userName: $scope.user.user_name
        })
      ).then(function () {
        User.setAdmin($scope.user.user_name, $scope.user.admin)
        .then(function () {
          loadUserInfo();
        })
        .catch(function (data) {
          Alert.error($t('common.alerts.cannotUpdateAdminStatus'), data.data.message);
          $scope.user.admin = !$scope.user.admin;
        });
      })
      .catch(function () {
        $scope.user.admin = !$scope.user.admin;
      });
    }
  };

  $scope.removeViewPrivilege = function (name, privilege) {
    var privilegeObject = {
      id: privilege.privilege_id,
      view_name: privilege.view_name,
      version: privilege.version,
      instance_name: name
    };
    View.deletePrivilege(privilegeObject).then(function () {
      loadUserInfo();
    });
  };

  $scope.deleteUser = function () {
    ConfirmationModal.show(
      $t('common.delete', {
        term: $t('common.user')
      }),
      $t('common.deleteConfirmation', {
        instanceType: $t('common.user').toLowerCase(),
        instanceName: '"' + $scope.user.user_name + '"'
      })
    ).then(function () {
      Cluster.getPrivilegesForResource({
        nameFilter: $scope.user.user_name,
        typeFilter: {value: 'USER'}
      }).then(function (data) {
        var clusterPrivilegesIds = [];
        var viewsPrivileges = [];
        if (data.items && data.items.length) {
          angular.forEach(data.items[0].privileges, function (privilege) {
            if (privilege.PrivilegeInfo.principal_type === 'USER') {
              if (privilege.PrivilegeInfo.type === 'VIEW') {
                viewsPrivileges.push({
                  id: privilege.PrivilegeInfo.privilege_id,
                  view_name: privilege.PrivilegeInfo.view_name,
                  version: privilege.PrivilegeInfo.version,
                  instance_name: privilege.PrivilegeInfo.instance_name
                });
              } else {
                clusterPrivilegesIds.push(privilege.PrivilegeInfo.privilege_id);
              }
            }
          });
        }
        User.delete($scope.user.user_name).then(function () {
          $location.path('/userManagement?tab=users');
          if (clusterPrivilegesIds.length) {
            Cluster.deleteMultiplePrivileges($rootScope.cluster.Clusters.cluster_name, clusterPrivilegesIds);
          }
          angular.forEach(viewsPrivileges, function (privilege) {
            View.deletePrivilege(privilege);
          });
        });
      });
    });
  };

  function deleteUserRoles(clusterName, user, ignoreAlert) {
    return Cluster.deleteMultiplePrivileges(
      clusterName,
      user.roles.map(function(item) {
        return item.privilege_id;
      })
    ).then(function () {
      if (!ignoreAlert) {
        Alert.success($t('users.alerts.roleChangedToNone', {
          user_name: user.user_name
        }));
      }
    }).catch(function (data) {
      Alert.error($t('common.alerts.cannotSavePermissions'), data.data.message);
    });
  }

  function addUserRoles(clusterName, newRole, user) {
    return Cluster.createPrivileges(
      {
        clusterId: clusterName
      },
      [{
        PrivilegeInfo: {
          permission_name: newRole.permission_name,
          principal_name: user.user_name,
          principal_type: 'USER'
        }
      }]
    ).then(function () {
      Alert.success($t('users.alerts.roleChanged', {
        name: user.user_name,
        role: newRole.permission_label
      }));
    }).catch(function (data) {
      Alert.error($t('common.alerts.cannotSavePermissions'), data.data.message);
    });
  }

  function loadUserInfo() {
    return User.getWithRoles($routeParams.id).then(function (data) {
      $scope.user = User.makeUser(data.data).Users;
      $scope.isCurrentUser = $scope.user.user_name === Auth.getCurrentUser();
      $scope.editingGroupsList = angular.copy($scope.user.groups);
      parsePrivileges(data.data.privileges);
      var clusterRole = $scope.user.roles[0];
      $scope.currentRole = clusterRole || nonRole;
      $scope.originalRole = clusterRole || nonRole;
      $scope.dataLoaded = true;
    });
  }

  function parsePrivileges(rawPrivileges) {
    var privileges = {
      clusters: {},
      views: {}
    };
    angular.forEach(rawPrivileges, function (privilege) {
      privilege = privilege.PrivilegeInfo;
      if (privilege.type === 'CLUSTER') {
        // This is cluster
        if (privileges.clusters[privilege.cluster_name]) {
          var preIndex = Cluster.orderedRoles.indexOf(privileges.clusters[privilege.cluster_name].permission_name);
          var curIndex = Cluster.orderedRoles.indexOf(privilege.permission_name);
          // set more powerful role
          if (curIndex < preIndex) {
            privileges.clusters[privilege.cluster_name] = privilege;
          }
        } else {
          privileges.clusters[privilege.cluster_name] = privilege;
        }
      } else if (privilege.type === 'VIEW') {
        privileges.views[privilege.instance_name] = privileges.views[privilege.instance_name] || {
          privileges: [],
          version: privilege.version,
          view_name: privilege.view_name,
          privilege_id: privilege.privilege_id
        };
        if (privileges.views[privilege.instance_name].privileges.indexOf(privilege.permission_label) === -1) {
          privileges.views[privilege.instance_name].privileges.push(privilege.permission_label);
        }
      }
    });

    $scope.privilegesView = privileges;
    $scope.noClusterPriv = $.isEmptyObject(privileges.clusters);
    $scope.noViewPriv = $.isEmptyObject(privileges.views);
    $scope.hidePrivileges = $scope.noClusterPriv && $scope.noViewPriv;
  }

  function loadRoles() {
    return Cluster.getRoleOptions().then(function (data) {
      $scope.roleOptions = data;
    });
  }

  loadRoles().finally(loadUserInfo);

}]);
<commit_msg>AMBARI-23090. Delete User button from individual user page navigates to clusterInformation page instead of Users page<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
'use strict';

angular.module('ambariAdminConsole')
.controller('UserEditCtrl',
['$scope', '$rootScope', '$routeParams', 'Cluster', 'User', 'View', '$modal', '$location', 'ConfirmationModal', 'Alert', 'Auth', 'getDifference', 'Group', '$q', 'UserConstants', '$translate', 'RoleDetailsModal',
function($scope, $rootScope, $routeParams, Cluster, User, View, $modal, $location, ConfirmationModal, Alert, Auth, getDifference, Group, $q, UserConstants, $translate, RoleDetailsModal) {

  var $t = $translate.instant;
  var nonRole = {
    permission_name: 'NONE',
    permission_label: $t('users.roles.none')
  };

  $scope.constants = {
    user: $t('common.user'),
    status: $t('users.status'),
    admin: $t('users.admin'),
    password: $t('users.password'),
    view: $t('common.view').toLowerCase(),
    cluster: $t('common.cluster').toLowerCase()
  };

  $scope.user = null;
  $scope.isCurrentUser = true;
  $scope.dataLoaded = false;
  $scope.isGroupEditing = false;

  $scope.enableGroupEditing = function () {
    $scope.isGroupEditing = true;
    $scope.editingGroupsList = angular.copy($scope.user.groups);
  };

  $scope.$watch(function () {
    return $scope.editingGroupsList;
  }, function (newValue) {
    if (newValue) {
      if (!angular.equals(newValue, $scope.user.groups)) {
        $scope.updateGroups();
      }
    }
  }, true);

  $scope.showHelpPage = function() {
    Cluster.getRolesWithAuthorizations().then(function(roles) {
      RoleDetailsModal.show(roles);
    });
  };

  $scope.updateRole = function () {
    var clusterName = $rootScope.cluster.Clusters.cluster_name;
    if ($scope.originalRole.permission_name !== $scope.currentRole.permission_name) {
      if ($scope.currentRole.permission_name === 'NONE') {
        deleteUserRoles(clusterName, $scope.user).finally(loadUserInfo);
      } else {
        if ($scope.user.roles.length) {
          deleteUserRoles(clusterName, $scope.user, true).finally(function() {
            addUserRoles(clusterName, $scope.currentRole, $scope.user).finally(loadUserInfo);
          });
        } else {
          addUserRoles(clusterName, $scope.currentRole, $scope.user).finally(loadUserInfo);
        }
      }
    }
  };

  $scope.updateGroups = function () {
    var groups = $scope.editingGroupsList.filter(function (item) {
      return item.trim();
    }).map(function (item) {
      return item.trim();
    });
    var diff = getDifference($scope.user.groups, groups);
    var promises = [];
    // Remove user from groups
    angular.forEach(diff.del, function (groupName) {
      promises.push(Group.removeMemberFromGroup(groupName, $scope.user.user_name).catch(function (data) {
        Alert.error($t('users.alerts.removeUserError'), data.data.message);
      }));
    });
    // Add user to groups
    angular.forEach(diff.add, function (groupName) {
      promises.push(Group.addMemberToGroup(groupName, $scope.user.user_name).catch(function (data) {
        Alert.error($t('users.alerts.cannotAddUser'), data.data.message);
      }));
    });
    $q.all(promises).then(function () {
      loadUserInfo();
    });
    $scope.isGroupEditing = false;
  };

  $scope.getUserMembership = function (userType) {
    if (userType) {
      return $t(UserConstants.TYPES[userType].LABEL_KEY) + " " + $t('users.groupMembership');
    }
  };

  $scope.cancelUpdate = function () {
    $scope.isGroupEditing = false;
    $scope.editingGroupsList = '';
  };

  $scope.openChangePwdDialog = function () {
    var modalInstance = $modal.open({
      templateUrl: 'views/userManagement/modals/changePassword.html',
      resolve: {
        userName: function () {
          return $scope.user.user_name;
        }
      },
      controller: ['$scope', 'userName', function ($scope, userName) {
        $scope.passwordData = {
          password: '',
          currentUserPassword: ''
        };

        $scope.form = {};
        $scope.userName = userName;

        $scope.ok = function () {
          $scope.form.passwordChangeForm.submitted = true;
          if ($scope.form.passwordChangeForm.$valid) {
            modalInstance.close({
              password: $scope.passwordData.password,
              currentUserPassword: $scope.passwordData.currentUserPassword
            });
          }
        };
        $scope.cancel = function () {
          modalInstance.dismiss('cancel');
        };
      }]
    });

    modalInstance.result.then(function (data) {
      User.setPassword($scope.user, data.password, data.currentUserPassword).then(function () {
        Alert.success($t('users.alerts.passwordChanged'));
      }).catch(function (data) {
        Alert.error($t('users.alerts.cannotChangePassword'), data.data.message);
      });
    });
  };

  $scope.toggleUserActive = function () {
    if (!$scope.isCurrentUser) {
      var newStatusKey = $scope.user.active ? 'inactive' : 'active';
      ConfirmationModal.show(
        $t('users.changeStatusConfirmation.title'),
        $t('users.changeStatusConfirmation.message', {
          userName: $scope.user.user_name,
          status: $t('users.' + newStatusKey).toLowerCase()
        })
      ).then(function () {
        User.setActive($scope.user.user_name, $scope.user.active)
        .catch(function (data) {
          Alert.error($t('common.alerts.cannotUpdateStatus'), data.data.message);
          $scope.user.active = !$scope.user.active;
        });
      })
      .catch(function () {
        $scope.user.active = !$scope.user.active;
      });
    }
  };

  $scope.toggleUserAdmin = function () {
    if (!$scope.isCurrentUser) {
      var action = $scope.user.admin ?
        $t('users.changePrivilegeConfirmation.revoke') : $t('users.changePrivilegeConfirmation.grant');
      ConfirmationModal.show(
        $t('users.changePrivilegeConfirmation.title'),
        $t('users.changePrivilegeConfirmation.message', {
          action: action,
          userName: $scope.user.user_name
        })
      ).then(function () {
        User.setAdmin($scope.user.user_name, $scope.user.admin)
        .then(function () {
          loadUserInfo();
        })
        .catch(function (data) {
          Alert.error($t('common.alerts.cannotUpdateAdminStatus'), data.data.message);
          $scope.user.admin = !$scope.user.admin;
        });
      })
      .catch(function () {
        $scope.user.admin = !$scope.user.admin;
      });
    }
  };

  $scope.removeViewPrivilege = function (name, privilege) {
    var privilegeObject = {
      id: privilege.privilege_id,
      view_name: privilege.view_name,
      version: privilege.version,
      instance_name: name
    };
    View.deletePrivilege(privilegeObject).then(function () {
      loadUserInfo();
    });
  };

  $scope.deleteUser = function () {
    ConfirmationModal.show(
      $t('common.delete', {
        term: $t('common.user')
      }),
      $t('common.deleteConfirmation', {
        instanceType: $t('common.user').toLowerCase(),
        instanceName: '"' + $scope.user.user_name + '"'
      })
    ).then(function () {
      Cluster.getPrivilegesForResource({
        nameFilter: $scope.user.user_name,
        typeFilter: {value: 'USER'}
      }).then(function (data) {
        var clusterPrivilegesIds = [];
        var viewsPrivileges = [];
        if (data.items && data.items.length) {
          angular.forEach(data.items[0].privileges, function (privilege) {
            if (privilege.PrivilegeInfo.principal_type === 'USER') {
              if (privilege.PrivilegeInfo.type === 'VIEW') {
                viewsPrivileges.push({
                  id: privilege.PrivilegeInfo.privilege_id,
                  view_name: privilege.PrivilegeInfo.view_name,
                  version: privilege.PrivilegeInfo.version,
                  instance_name: privilege.PrivilegeInfo.instance_name
                });
              } else {
                clusterPrivilegesIds.push(privilege.PrivilegeInfo.privilege_id);
              }
            }
          });
        }
        User.delete($scope.user.user_name).then(function () {
          $location.url('/userManagement?tab=users');
          if (clusterPrivilegesIds.length) {
            Cluster.deleteMultiplePrivileges($rootScope.cluster.Clusters.cluster_name, clusterPrivilegesIds);
          }
          angular.forEach(viewsPrivileges, function (privilege) {
            View.deletePrivilege(privilege);
          });
        });
      });
    });
  };

  function deleteUserRoles(clusterName, user, ignoreAlert) {
    return Cluster.deleteMultiplePrivileges(
      clusterName,
      user.roles.map(function(item) {
        return item.privilege_id;
      })
    ).then(function () {
      if (!ignoreAlert) {
        Alert.success($t('users.alerts.roleChangedToNone', {
          user_name: user.user_name
        }));
      }
    }).catch(function (data) {
      Alert.error($t('common.alerts.cannotSavePermissions'), data.data.message);
    });
  }

  function addUserRoles(clusterName, newRole, user) {
    return Cluster.createPrivileges(
      {
        clusterId: clusterName
      },
      [{
        PrivilegeInfo: {
          permission_name: newRole.permission_name,
          principal_name: user.user_name,
          principal_type: 'USER'
        }
      }]
    ).then(function () {
      Alert.success($t('users.alerts.roleChanged', {
        name: user.user_name,
        role: newRole.permission_label
      }));
    }).catch(function (data) {
      Alert.error($t('common.alerts.cannotSavePermissions'), data.data.message);
    });
  }

  function loadUserInfo() {
    return User.getWithRoles($routeParams.id).then(function (data) {
      $scope.user = User.makeUser(data.data).Users;
      $scope.isCurrentUser = $scope.user.user_name === Auth.getCurrentUser();
      $scope.editingGroupsList = angular.copy($scope.user.groups);
      parsePrivileges(data.data.privileges);
      var clusterRole = $scope.user.roles[0];
      $scope.currentRole = clusterRole || nonRole;
      $scope.originalRole = clusterRole || nonRole;
      $scope.dataLoaded = true;
    });
  }

  function parsePrivileges(rawPrivileges) {
    var privileges = {
      clusters: {},
      views: {}
    };
    angular.forEach(rawPrivileges, function (privilege) {
      privilege = privilege.PrivilegeInfo;
      if (privilege.type === 'CLUSTER') {
        // This is cluster
        if (privileges.clusters[privilege.cluster_name]) {
          var preIndex = Cluster.orderedRoles.indexOf(privileges.clusters[privilege.cluster_name].permission_name);
          var curIndex = Cluster.orderedRoles.indexOf(privilege.permission_name);
          // set more powerful role
          if (curIndex < preIndex) {
            privileges.clusters[privilege.cluster_name] = privilege;
          }
        } else {
          privileges.clusters[privilege.cluster_name] = privilege;
        }
      } else if (privilege.type === 'VIEW') {
        privileges.views[privilege.instance_name] = privileges.views[privilege.instance_name] || {
          privileges: [],
          version: privilege.version,
          view_name: privilege.view_name,
          privilege_id: privilege.privilege_id
        };
        if (privileges.views[privilege.instance_name].privileges.indexOf(privilege.permission_label) === -1) {
          privileges.views[privilege.instance_name].privileges.push(privilege.permission_label);
        }
      }
    });

    $scope.privilegesView = privileges;
    $scope.noClusterPriv = $.isEmptyObject(privileges.clusters);
    $scope.noViewPriv = $.isEmptyObject(privileges.views);
    $scope.hidePrivileges = $scope.noClusterPriv && $scope.noViewPriv;
  }

  function loadRoles() {
    return Cluster.getRoleOptions().then(function (data) {
      $scope.roleOptions = data;
    });
  }

  loadRoles().finally(loadUserInfo);

}]);
<|endoftext|>


<commit_before>// moj.Modules.FeeCalculator.GraduatedPrice
(function(exports, $) {
  var Modules = exports.Modules.FeeCalculator || {};

  Modules.GraduatedPrice = {
    init: function () {
      this.bindEvents();
    },

    bindEvents: function () {
      this.feeDaysChange();
      this.feePpeChange();
      this.pageLoad();
    },

    feeDaysChange: function ($el) {
      var self = this;
      var $els = $el || $('.js-fee-calculator-days');
      if ($('.calculated-grad-fee').exists()) {
        $els.change( function() {
          self.calculateGraduatedPrice();
        });
      }
    },

    feePpeChange: function ($el) {
      var self = this;
      var $els = $el || $('.js-fee-calculator-ppe');
      if ($('.calculated-grad-fee').exists()) {
        $els.change( function() {
          self.calculateGraduatedPrice();
        });
      }
    },

    setAmount: function(data, context) {
      var $input = $(context).find('input.fee-amount');
      var $calculated = $(context).siblings('.js-fee-calculator-success').find('input');
      $input.val(data.toFixed(2));
      $input.change();
      $calculated.val(data > 0);
      $input.prop('readonly', data > 0);
    },

    enableAmount: function(context) {
      $(context).find('input.fee-amount').prop('readonly', false);
    },

    displayError: function(response, context) {
      // only some errors will have a JSON response
      this.clearErrors(context);
      var $label = $(context).find('label');
      var $calculated = $(context).closest('.fx-fee-group').find('.js-fee-calculator-success').find('input');
      var error_html = '
' + response.responseJSON["message"] + '
';
      var new_label = $label.text() + ' ' + error_html;
      var $input = $(context).find('input.fee-amount');

      $input.val('');
      $input.prop("readonly", false);
      $calculated.val(false);
      $label.html(new_label);
    },

    clearErrors: function(context) {
      $(context).find('.js-calculate-error').remove();
    },

    displayHelp: function(context, show) {
      var $help = $(context).siblings('.help-wrapper.form-group');
      show ? $help.show() : $help.hide();
    },

    graduatedPriceAjax: function (data, context) {
      var self = this;
      $.ajax({
        type: 'POST',
        url: '/external_users/claims/' + data.claim_id + '/fees/calculate_price.json',
        data: data,
        dataType: 'json'
      })
      .done(function(response) {
        self.clearErrors(context);
        self.setAmount(response.data.amount, context);
        self.displayHelp(context, true);
      })
      .fail(function(response) {
        if (response.responseJSON['errors'][0] != 'incomplete') {
          self.displayError(response, context);
          self.displayHelp(context, false);
        }
        self.enableAmount(context);
      });
    },

    buildFeeData: function(data, context) {
      data.claim_id = $('#claim-form').data('claimId');
      data.price_type = 'GraduatedPrice';
      data.fee_type_id = $('.fx-fee-group').find('.js-fee-type').val();
      data.ppe = $('.fx-fee-group').find('input.js-fee-calculator-ppe').val();
      data.days = $('.fx-fee-group').find('input.js-fee-calculator-days').val();
    },

    // Calculates the price for a given graduated fee,
    calculateGraduatedPrice: function (context) {
      var self = this;
      var data = {};
      self.buildFeeData(data, context);
      self.graduatedPriceAjax(data, '.js-fee-calculator-effectee');
    },

    pageLoad: function () {
      var self = this;
      $(document).ready( function() {
        $('.calculated-grad-fee').each(function() {
          self.calculateGraduatedPrice(self);
        });
      });
    }
  };

  exports.Modules.FeeCalculator = Modules;
}(moj, jQuery));
<commit_msg>Update calculated grad fee amount on effector keyup<commit_after>// moj.Modules.FeeCalculator.GraduatedPrice
(function(exports, $) {
  var Modules = exports.Modules.FeeCalculator || {};

  Modules.GraduatedPrice = {
    init: function () {
      this.bindEvents();
    },

    bindEvents: function () {
      this.feeDaysChange();
      this.feePpeChange();
      this.pageLoad();
    },

    feeDaysChange: function ($el) {
      var self = this;
      var $els = $el || $('.js-fee-calculator-days');
      if ($('.calculated-grad-fee').exists()) {
        $els.on('change keyup', function() {
          self.calculateGraduatedPrice();
        });
      }
    },

    feePpeChange: function ($el) {
      var self = this;
      var $els = $el || $('.js-fee-calculator-ppe');
      if ($('.calculated-grad-fee').exists()) {
        $els.on('change keyup', function() {
          self.calculateGraduatedPrice();
        });
      }
    },

    setAmount: function(data, context) {
      var $input = $(context).find('input.fee-amount');
      var $calculated = $(context).siblings('.js-fee-calculator-success').find('input');
      $input.val(data.toFixed(2));
      $input.change();
      $calculated.val(data > 0);
      $input.prop('readonly', data > 0);
    },

    enableAmount: function(context) {
      $(context).find('input.fee-amount').prop('readonly', false);
    },

    displayError: function(response, context) {
      // only some errors will have a JSON response
      this.clearErrors(context);
      var $label = $(context).find('label');
      var $calculated = $(context).closest('.fx-fee-group').find('.js-fee-calculator-success').find('input');
      var error_html = '
' + response.responseJSON["message"] + '
';
      var new_label = $label.text() + ' ' + error_html;
      var $input = $(context).find('input.fee-amount');

      $input.val('');
      $input.prop("readonly", false);
      $calculated.val(false);
      $label.html(new_label);
    },

    clearErrors: function(context) {
      $(context).find('.js-calculate-error').remove();
    },

    displayHelp: function(context, show) {
      var $help = $(context).siblings('.help-wrapper.form-group');
      show ? $help.show() : $help.hide();
    },

    graduatedPriceAjax: function (data, context) {
      var self = this;
      $.ajax({
        type: 'POST',
        url: '/external_users/claims/' + data.claim_id + '/fees/calculate_price.json',
        data: data,
        dataType: 'json'
      })
      .done(function(response) {
        self.clearErrors(context);
        self.setAmount(response.data.amount, context);
        self.displayHelp(context, true);
      })
      .fail(function(response) {
        if (response.responseJSON['errors'][0] != 'incomplete') {
          self.displayError(response, context);
          self.displayHelp(context, false);
        }
        self.enableAmount(context);
      });
    },

    buildFeeData: function(data, context) {
      data.claim_id = $('#claim-form').data('claimId');
      data.price_type = 'GraduatedPrice';
      data.fee_type_id = $('.fx-fee-group').find('.js-fee-type').val();
      data.ppe = $('.fx-fee-group').find('input.js-fee-calculator-ppe').val();
      data.days = $('.fx-fee-group').find('input.js-fee-calculator-days').val();
    },

    // Calculates the price for a given graduated fee,
    calculateGraduatedPrice: function (context) {
      var self = this;
      var data = {};
      self.buildFeeData(data, context);
      self.graduatedPriceAjax(data, '.js-fee-calculator-effectee');
    },

    pageLoad: function () {
      var self = this;
      $(document).ready( function() {
        $('.calculated-grad-fee').each(function() {
          self.calculateGraduatedPrice(self);
        });
      });
    }
  };

  exports.Modules.FeeCalculator = Modules;
}(moj, jQuery));
<|endoftext|>


<commit_before>$(function () {
	$(window).scroll(function() {
		if ($(".navbar").offset().top>30) {
			$(".navbar-inner").addClass("sticky");
		}
		else {
			$(".navbar-inner").removeClass("sticky");
		}
	});

	// Flex
	if ($(".flexslider").length) {
		$('.flexslider').flexslider({controlNav: false});
	}

	servicesCircle.initialize();

	staticHeader.initialize();

	portfolioItem.initialize();
});

var portfolioItem = {
	initialize: function () {
		var $container = $("#portfolio_tem .left_box");
		var $bigPics = $container.find(".big img");
		var $thumbs = $container.find(".thumbs .thumb");

		$bigPics.hide().eq(0).show();

		$thumbs.click(function (e) {
			e.preventDefault();
			var index = $thumbs.index(this);
			$bigPics.fadeOut();
			$bigPics.eq(index).fadeIn();
		});
	}
};

var staticHeader = {
	initialize: function () {
		if ($(".navbar-static-top").length) {
			$("body").css("padding-top", 0);
		}
	}
};

var servicesCircle = {
	initialize: function () {
		var $container = $(".services_circles");
		var $texts = $container.find(".description .text");
		var $circles = $container.find(".areas .circle");

		$circles.click(function () {
			var index = $circles.index(this);
			$texts.fadeOut();
			$texts.eq(index).fadeIn();
			$circles.removeClass("active");
			$(this).addClass("active");
		});
	}
};
<commit_msg>js/theme: reduzindo tempo entre as imagens no slideshow<commit_after>$(function () {
	$(window).scroll(function() {
		if ($(".navbar").offset().top>30) {
			$(".navbar-inner").addClass("sticky");
		}
		else {
			$(".navbar-inner").removeClass("sticky");
		}
	});

	// Flex
	if ($(".flexslider").length) {
		$('.flexslider').flexslider({controlNav: false, slideshowSpeed: 2000});
	}

	servicesCircle.initialize();

	staticHeader.initialize();

	portfolioItem.initialize();
});

var portfolioItem = {
	initialize: function () {
		var $container = $("#portfolio_tem .left_box");
		var $bigPics = $container.find(".big img");
		var $thumbs = $container.find(".thumbs .thumb");

		$bigPics.hide().eq(0).show();

		$thumbs.click(function (e) {
			e.preventDefault();
			var index = $thumbs.index(this);
			$bigPics.fadeOut();
			$bigPics.eq(index).fadeIn();
		});
	}
};

var staticHeader = {
	initialize: function () {
		if ($(".navbar-static-top").length) {
			$("body").css("padding-top", 0);
		}
	}
};

var servicesCircle = {
	initialize: function () {
		var $container = $(".services_circles");
		var $texts = $container.find(".description .text");
		var $circles = $container.find(".areas .circle");

		$circles.click(function () {
			var index = $circles.index(this);
			$texts.fadeOut();
			$texts.eq(index).fadeIn();
			$circles.removeClass("active");
			$(this).addClass("active");
		});
	}
};
<|endoftext|>


<commit_before>// angular-property-binder
// version: 0.1.5
// author: Gaignoux Nicolas
// generated: Wed Jan 28 2015 00:09:32 GMT+0100 (Europe de l’Ouest)
// Autogenerated, do not edit. All changes will be undone.
!function(a,b,angular){"use strict";angular.module("PropertyBinder",[]),angular.module("PropertyBinder").provider("PropertyBinder.providers.binder",function(){this.$get=function(){var a=function(){var a=function(a){void 0===a&&(a=[]),this._properties=a instanceof Array?a:[a],this._binded=!1,this._sealed=!1,this._to=void 0,this._from=void 0,this._path=[],this._aliases={},this._change=function(){}};return a.prototype.from=function(a,b){return void 0===b&&(b=[]),this._throwErrorIfAlreadyBinded(),this._path="string"==typeof b?b=b.split("."):b,this._from=a,this},a.prototype.to=function(a){return this._throwErrorIfAlreadyBinded(),this._to=a,this},a.prototype.as=function(a){if(void 0===a&&(a={}),this._throwErrorIfAlreadyBinded(),a instanceof Object)if(a instanceof Array)for(var b=0;b<a.length;b++)this._properties[b]&&(this._aliases[this._properties[b]]=a[b]);else this._aliases=a;else if("string"==typeof a){if(1!==this._properties.length)throw Error("Ambiguous aliases");var c=a;this._aliases={},this._aliases[this._properties[0]]=c}return this},a.prototype.onchange=function(a){return void 0===a&&(a=function(){}),this._change=a,this},a.prototype.seal=function(){return this._sealed=!0,this},a.prototype.unseal=function(){return this._sealed=!1,this},a.prototype.toggleSealing=function(){return this._sealed=!this._sealed,this},a.prototype.apply=function(){if(this._throwErrorIfAlreadyBinded(),this._from&&this._to&&this._properties.length>0)for(var a=0;a<this._properties.length;a++)this._createProperty(this._properties[a]);return this._binded=!0,this},a.prototype.destroy=function(){for(var a=0;a<this._properties.length;a++)this._deleteProperty(this._properties[a]);return this._binded=!1,this},a.prototype._deleteProperty=function(a){var b=this._aliases[a]||a;delete this._to[b]},a.prototype._createProperty=function(a){var b=this;Object.defineProperty(this._to,this._aliases[a]||a,{enumerable:!0,configurable:!0,get:function(){var c=b._from;if(b._path.length>0)for(var d=0;d<b._path.length;d++)if(c=c[b._path[d]],!c)throw Error("unable to acces to the given property");return c[a]instanceof Function?c[a].bind(c):c[a]},set:function(c){if(b._sealed)throw Error("Trying to update a sealed property");var d=b._from[a];b._from[a]=c,d!==c&&b._change(c,d)}})},a.prototype._throwErrorIfAlreadyBinded=function(){if(this._binded)throw Error("Property already binded")},a}();return a}});var c=Array.prototype.slice,d=function(a,b){var c=Object.create(a.prototype),d=a.apply(c,b);return null==d||"object"!=typeof d&&"function"!=typeof d?c:d},e=function(a){return Array.isArray(a)?a:Array.from(a)};angular.module("PropertyBinder").service("PropertyBinder.services.binder",["PropertyBinder.providers.binder",function(a){return function(){var b=c.call(arguments);return d(a,e(b))}}])}(window,window.document,window.angular);<commit_msg>updates version<commit_after>// angular-property-binder
// version: 0.1.5
// author: Gaignoux Nicolas
// generated: Wed Jan 28 2015 11:13:03 GMT+0100 (Europe de l’Ouest)
// Autogenerated, do not edit. All changes will be undone.
!function(a,b,angular){"use strict";angular.module("PropertyBinder",[]),angular.module("PropertyBinder").provider("PropertyBinder.providers.binder",function(){this.$get=function(){var a=function(){var a=function(a){void 0===a&&(a=[]),this._properties=a instanceof Array?a:[a],this._binded=!1,this._sealed=!1,this._to=void 0,this._from=void 0,this._path=[],this._aliases={},this._change=function(){}};return a.prototype.from=function(a,b){return void 0===b&&(b=[]),this._throwErrorIfAlreadyBinded(),this._path="string"==typeof b?b=b.split("."):b,this._from=a,this},a.prototype.to=function(a){return this._throwErrorIfAlreadyBinded(),this._to=a,this},a.prototype.as=function(a){if(void 0===a&&(a={}),this._throwErrorIfAlreadyBinded(),a instanceof Object)if(a instanceof Array)for(var b=0;b<a.length;b++)this._properties[b]&&(this._aliases[this._properties[b]]=a[b]);else this._aliases=a;else if("string"==typeof a){if(1!==this._properties.length)throw Error("Ambiguous aliases");var c=a;this._aliases={},this._aliases[this._properties[0]]=c}return this},a.prototype.onchange=function(a){return void 0===a&&(a=function(){}),this._change=a,this},a.prototype.seal=function(){return this._sealed=!0,this},a.prototype.unseal=function(){return this._sealed=!1,this},a.prototype.toggleSealing=function(){return this._sealed=!this._sealed,this},a.prototype.apply=function(){if(this._throwErrorIfAlreadyBinded(),this._from&&this._to&&this._properties.length>0)for(var a=0;a<this._properties.length;a++)this._createProperty(this._properties[a]);return this._binded=!0,this},a.prototype.destroy=function(){for(var a=0;a<this._properties.length;a++)this._deleteProperty(this._properties[a]);return this._binded=!1,this},a.prototype._deleteProperty=function(a){var b=this._aliases[a]||a;delete this._to[b]},a.prototype._createProperty=function(a){var b=this;Object.defineProperty(this._to,this._aliases[a]||a,{enumerable:!0,configurable:!0,get:function(){var c=b._getSrc();return c[a]instanceof Function?c[a].bind(c):c[a]},set:function(c){if(b._sealed)throw Error("Trying to update a sealed property");var d=b._getSrc(),e=d[a];d[a]=c,e!==c&&b._change(c,e)}})},a.prototype._getSrc=function(){var a=this._from;if(this._path.length>0)for(var b=0;b<this._path.length;b++)if(a=a[this._path[b]],!a)throw Error("unable to acces to the given property");return a},a.prototype._throwErrorIfAlreadyBinded=function(){if(this._binded)throw Error("Property already binded")},a}();return a}});var c=Array.prototype.slice,d=function(a,b){var c=Object.create(a.prototype),d=a.apply(c,b);return null==d||"object"!=typeof d&&"function"!=typeof d?c:d},e=function(a){return Array.isArray(a)?a:Array.from(a)};angular.module("PropertyBinder").service("PropertyBinder.services.binder",["PropertyBinder.providers.binder",function(a){return function(){var b=c.call(arguments);return d(a,e(b))}}])}(window,window.document,window.angular);<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

var WebSocket = require('ws');
var PubSub = require('./pubsub');

function MessageHandler(pubsub, storage) {
  this.pubsub = pubsub;
  this.storage = storage;
}

MessageHandler.prototype = {
  /**
   * Parses a message and dispatches it to the right handler.
   **/
  dispatch: function(session, data, cb) {
    var inboundMessage = this.decode(data);

    var handlers = {
      hello: "handleHello",
      action: "handleAction"
    };

    if (!handlers.hasOwnProperty(messageType)) {
      cb(new Error("Unknown messageType"));
      return;
    }
    var handler = this[handlers[messageType]];
    handler(inboundMessage, function(outboundMessage) {
      cb(null, this.encode(outboundMessage));
    });
  },

  handleHello: function(session, message, cb) {
    // Check that message contains requireParams, otherwise return an error.
    try {
      this.requireParams(message, 'callId', 'auth');
    } catch (e) {
      cb(e);
      return;
    }

    // Check authentication
    // XXX We want to sign messages with the hawkId + secret rather
    // than using it as a bearer token.
    var hawkId = message.auth;

    // Configure the current session with user information.
    session.callId = message.callId;

    this.storage.getHawkUser(hawkId, function(err, user) {
      if (user !== null) {
        session.user = user;
      } else {
        session.user = hawkId;
      }

      this.storage.getCall(session.callId, function(err, call) {
        if (err) {
          cb(err);
          return;
        }

        session.type = (call.userMac === session.user) ? "caller" : "caller";

        // Get current call state to answer hello message.
        this.storage.getCallState(session.callId, function(err, state) {
          if (err) {
            cb(err);
            return;
          }

          // Answer the hello message.
          cb(null, {
            messageType: "hello",
            state: state
          });
        });

        // Alert clients on call state changes.
        this.pubsub.on("message", function(channel, receivedState) {
          if (channel !== session.callId) {
            this.handleCallStateChange(session, receivedState, cb);
          }
        });

        // Subscribe to the channel to setup progress updates.
        this.pubsub.subscribe(session.callId);
      });
    });
  },

  handleAction: function(session, message, cb) {
    // We received a session changed
    try {
      this.requireParams(message, "event");
    } catch (e) {
      cb(e);
      return;
    }

    var validEvents = ["accept", "media-up", "terminate"];
    var event = message.event;

    if (validEvents.indexOf(event) === -1) {
      cb(
        new Error(event + " state is invalid. Should be: " +
                  validEvents.join(", "))
      );
      return;
    }

    // If terminate, close the call
    if (event === "terminate") {
      this.broadcastState(session.callId, "terminated", cb);
      return;
    }

    // Get current state
    this.storage.getCallState(session.callId, function(err, currentState) {
      var stateMachine = {
        "accept": [
          ["alerting", "connecting"]
        ],
        "media-up": [
          ["connecting", "half-connected"],
          ["half-connected", "connected"],
          validateState
        ]
      };

      // Get the validator
      var validator = stateMachine[event].pop();
      if (typeof validator === "object") {
        stateMachine[event].push(validator);
        validator = undefined;
      }

      var handled = false;

      stateMachine[event].forEach(function(transition, key) {
        if (transition[0] === currentState) {
          handled = true;
          if (validator !== undefined) {
            if (validator(callId, currentState, event)) {
              this.broadcastState(session.callId, stateMachine[event][1], cb);
            }
            return;
          }
          this.broadcastState(session.callId, stateMachine[event][1], cb);
        }
      });

      if (!handled) {
        cb(
          new Error("No transition from " + currentState +
                    " state with " + event + " event.")
        );
      }
    });
  },

  broadcastState: function(callId, state, closeConnection, cb) {
    if (cb === undefined) {
      cb = closeConnection;
      closeConnection = undefined;
    }

    this.storage.setCallState(callId, state, function(err) {
      if (err) throw err;

      this.pubsub.publish(callId, state, function(err) {
        if (err) throw err;

        cb(null, {
          messageType: "progress",
          state: state
        }, closeConnection);
      });
    });
  },

  createError: function(errorMessage) {
    return this.encode({
      messageType: "error",
      reason: errorMessage
    });
  },

  encode: function(data) {
    return JSON.stringify(data);
  },

  decode: function(data) {
    return JSON.parse(data);
  },

  requireParams: function() {
    var params = Array.prototype.slice.call(arguments);
    var inboundMessage = params.shift();

    var missingParams;

    missingParams = params.filter(function(param) {
      return inboundMessage[param] === undefined;
    });

    if (missingParams.length > 0) {
      throw new Error("Missing parameters: " + missingParams.join(', '));
    }
  }
};

module.exports = function(storage, logError, conf) {
  var register = function(server) {
    var pubsub = new PubSub(conf.get('pubsub'));
    var messageHandler = new MessageHandler(pubsub, storage);
    var wss = new WebSocket.Server({server: server});

    wss.on('connection', function(ws) {
      var session = {};
      // Check authentication with hawk.
      ws.on('message', function(data) {
        try {
          messageHandler.dispatch(session, data, function(err, outboundMessage, terminate) {
            // Regular error
            if (err) {
              ws.send(messageHandler.createError(err.message));
              ws.close();
            }

            ws.send(outboundMessage);
            if (terminate === "closeConnection") {
              ws.close();
            }
          });
        } catch(e) {
          // Programmation error.
          ws.send(messageHandler.createError(new Error("Service Unavailable")));
          ws.close();
        }
      });
      ws.on('close', function() {
        ws.close();
      });
      ws.on('error', console.log);
    });
  };

  return {
    'register': register
  };
};
<commit_msg>Added comments, finished the state machine implementation<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

var WebSocket = require('ws');
var PubSub = require('./pubsub');

function MessageHandler(pubsub, storage) {
  this.pubsub = pubsub;
  this.storage = storage;
}

MessageHandler.prototype = {

  /**
   * Parses a message and dispatches it to the right handler.
   **/
  dispatch: function(session, data, cb) {
    var inboundMessage = this.decode(data);

    var handlers = {
      hello: "handleHello",
      action: "handleAction"
    };

    var messageType = inboundMessage.messageType;

    if (!handlers.hasOwnProperty(messageType)) {
      cb(new Error("Unknown messageType"));
      return;
    }
    var handler = this[handlers[messageType]];
    handler(inboundMessage, function(outboundMessage) {
      cb(null, this.encode(outboundMessage));
    });
  },

  /**
   * Handles the hello message.
   *
   * Does authentication (checks that the passed hawk credentials are valid,
   * and answers with the status of the call.
   *
   * In addition to that, listens on the pubsub for forward events about this
   * call.
   **/
  handleHello: function(session, message, cb) {
    // Check that message contains requireParams, otherwise return an error.
    try {
      this.requireParams(message, 'callId', 'auth');
    } catch (e) {
      cb(e);
      return;
    }

    // Check authentication
    // XXX We want to sign messages with the hawkId + secret rather
    // than using it as a bearer token.
    var hawkId = message.auth;

    // Configure the current session with user information.
    session.callId = message.callId;

    this.storage.getHawkUser(hawkId, function(err, user) {
      if (user !== null) {
        session.user = user;
      } else {
        session.user = hawkId;
      }

      this.storage.getCall(session.callId, function(err, call) {
        if (err) {
          cb(err);
          return;
        }

        session.type = (call.userMac === session.user) ? "caller" : "caller";

        // Get current call state to answer hello message.
        this.storage.getCallState(session.callId, function(err, state) {
          if (err) {
            cb(err);
            return;
          }

          // Answer the hello message.
          cb(null, {
            messageType: "hello",
            state: state
          });
        });

        // Alert clients on call state changes.
        this.pubsub.on("message", function(channel, receivedState) {
          if (channel !== session.callId) {
            this.handleCallStateChange(session, receivedState, cb);
          }
        });

        // Subscribe to the channel to setup progress updates.
        this.pubsub.subscribe(session.callId);
      });
    });
  },

  /**
   * Handles state changes submitted by the clients.
   *
   * Update the current state of the call using the information passed by the
   * clients. Once the new state is defined, broadcast it to the interested
   * parties using the pubsub.
   **/
  handleAction: function(session, message, cb) {
    // We received a session changed
    try {
      this.requireParams(message, "event");
    } catch (e) {
      cb(e);
      return;
    }

    var validEvents = ["accept", "media-up", "terminate"];
    var event = message.event;

    if (validEvents.indexOf(event) === -1) {
      cb(
        new Error(event + " state is invalid. Should be: " +
                  validEvents.join(", "))
      );
      return;
    }

    // If terminate, close the call
    if (event === "terminate") {
      this.broadcastState(session.callId, "terminated", cb);
      return;
    }

    // Get current state
    this.storage.getCallState(session.callId, function(err, currentState) {

      // Ensure half-connected is not send twice by the same party.
      var validateState = function(callId, currentState, event) {
        return true;
      };

      var stateMachine = {
        "accept": {
          transitions: [
            ["alerting", "connecting"]
          ],
        },
        "media-up": {
          transitions: [
            ["connecting", "half-connected"],
            ["half-connected", "connected"]
          ],
          validator: validateState
        }
      };

      var handled = false;

      if (stateMachine.hasOwnProperty(event)) {
        var validated = true;
        var state = stateMachine[event];

        state.transitions.forEach(function(transition, key) {
          if(transition[0] === currentState) {
            handled = true;
            var validator = stateMachine[event].validator;
            if (validator !== undefined) {
              if (!validator(session.callId, currentState, event)) {
                validated = false;
              }
            }
            if (validated === true) {

              // In case we're connected, close the connection.
              var terminate;
              if (transition[1] === "connected") {
                terminate = "closeConnection";
              }
              this.broadcastState(session.callId, transition[1], terminate, cb);
            }
            return;
          }
        });
      }
      if (!handled) {
        cb(
          new Error("No transition from " + currentState + " state with " +
                    event + " event.")
        );
      }
    });
  },

  /**
   * Broadcast the call-state data to the interested parties.
   **/
  broadcastState: function(callId, state, closeConnection, cb) {
    if (cb === undefined) {
      cb = closeConnection;
      closeConnection = undefined;
    }

    this.storage.setCallState(callId, state, function(err) {
      if (err) throw err;

      this.pubsub.publish(callId, state, function(err) {
        if (err) throw err;

        cb(null, {
          messageType: "progress",
          state: state
        }, closeConnection);
      });
    });
  },

  /**
   * Creates an error message to be consumed by the client.
   **/
  createError: function(errorMessage) {
    return this.encode({
      messageType: "error",
      reason: errorMessage
    });
  },

  encode: function(data) {
    return JSON.stringify(data);
  },

  decode: function(data) {
    return JSON.parse(data);
  },

  /**
   * Checks that the given parameters are present in the message.
   *
   * Message is passed as the last argument of the function.
   **/
  requireParams: function() {
    var params = Array.prototype.slice.call(arguments);
    var inboundMessage = params.shift();

    var missingParams;

    missingParams = params.filter(function(param) {
      return inboundMessage[param] === undefined;
    });

    if (missingParams.length > 0) {
      throw new Error("Missing parameters: " + missingParams.join(', '));
    }
  }
};

module.exports = function(storage, logError, conf) {
  /**
   * Allow a server to register itself as a websocket provider.
   **/
  var register = function(server) {
    var pubsub = new PubSub(conf.get('pubsub'));
    var messageHandler = new MessageHandler(pubsub, storage);
    var wss = new WebSocket.Server({server: server});

    wss.on('connection', function(ws) {
      var session = {};
      // Check authentication with hawk.
      ws.on('message', function(data) {
        try {
          messageHandler.dispatch(session, data,
            function(err, outboundMessage, terminate) {
              // Handle regular error.
              if (err) {
                ws.send(messageHandler.createError(err.message));
                ws.close();
              }

              ws.send(outboundMessage);
              if (terminate === "closeConnection") {
                ws.close();
              }
            });
        } catch(e) {
          // Handle programmation / uncatched errors.
          ws.send(messageHandler.createError(new Error("Service Unavailable")));
          ws.close();
        }
      });
      ws.on('close', function() {
        ws.close();
      });
      ws.on('error', console.log);
    });
  };

  return {
    'register': register
  };
};
<|endoftext|>


<commit_before>"use strict";

/*
 * NOTICE:
 * A lot of this code is based on https://github.com/skylarstein/bme280-sensor
 * We need this to be synchronous and use the same I2C instance as for all other devices; thus the rewrite.
MIT License

Copyright (c) 2016 Skylar Stein

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 */

function create(deviceConfig, i2cAdapter) {
    return new BME280(deviceConfig, i2cAdapter);
}

function BME280(deviceConfig, i2cAdapter) {
    // consts:
    this.REGISTER_DIG_T1 = 0x88;
    this.REGISTER_DIG_T2 = 0x8A;
    this.REGISTER_DIG_T3 = 0x8C;

    this.REGISTER_DIG_P1 = 0x8E;
    this.REGISTER_DIG_P2 = 0x90;
    this.REGISTER_DIG_P3 = 0x92;
    this.REGISTER_DIG_P4 = 0x94;
    this.REGISTER_DIG_P5 = 0x96;
    this.REGISTER_DIG_P6 = 0x98;
    this.REGISTER_DIG_P7 = 0x9A;
    this.REGISTER_DIG_P8 = 0x9C;
    this.REGISTER_DIG_P9 = 0x9E;

    this.REGISTER_DIG_H1 = 0xA1;
    this.REGISTER_DIG_H2 = 0xE1;
    this.REGISTER_DIG_H3 = 0xE3;
    this.REGISTER_DIG_H4 = 0xE4;
    this.REGISTER_DIG_H5 = 0xE5;
    this.REGISTER_DIG_H6 = 0xE7;

    this.REGISTER_CHIPID = 0xD0;
    this.REGISTER_RESET  = 0xE0;

    this.REGISTER_CONTROL_HUM   = 0xF2;
    this.REGISTER_CONTROL       = 0xF4;
    this.REGISTER_PRESSURE_DATA = 0xF7;
    this.REGISTER_TEMP_DATA     = 0xFA;
    this.REGISTER_HUMIDITY_DATA = 0xFD;

    // variables:
    this.address = deviceConfig.address;
    this.name = deviceConfig.name || 'BME280';
    this.hexAddress = i2cAdapter.toHexString(this.address);

    this.config = deviceConfig.BME280;

    this.i2cAdapter = i2cAdapter;
    this.adapter = this.i2cAdapter.adapter;
}

BME280.prototype.start = function () {
    var that = this;
    that.debug('Starting');
    that.adapter.extendObject(
        that.hexAddress,
        {
            type: 'device',
            common: {
                name: that.hexAddress + ' (' + that.name + ')',
                role: 'thermo'
            },
            native: that.config
        },
        function () {
            that.loadSystemConfig(
                function() {
                    that.createStates(
                        function() {
                            that.checkChipId();
                            that.loadCalibration();
                            that.configureChip();
                            that.readCurrentValues();
                            if (that.config.pollingInterval && parseInt(that.config.pollingInterval) > 0) {
                                that.pollingTimer = setInterval(
                                    function () { that.readCurrentValues(); },
                                    parseInt(that.config.pollingInterval) * 1000);
                            }
                        });
                });
        });
};

BME280.prototype.stop = function () {
    this.debug('Stopping');
    clearInterval(this.pollingTimer);
};

BME280.prototype.loadSystemConfig = function (callback) {
    var that = this;
    that.adapter.getForeignObject('system.config', function (err, obj) {
        that.debug('system.config = ' + JSON.stringify(obj));
        that.useAmericanUnits = obj && obj.common && obj.common.tempUnit == '°F';

        callback();
    });
};

BME280.prototype.createStates = function (callback) {
    var that = this;
    that.adapter.extendObject(
        that.hexAddress + '.temperature',
        {
            type: 'state',
            common: {
                name: that.hexAddress + ' Temperature',
                read: true,
                write: false,
                type: 'number',
                role: 'value.temperature',
                unit: that.useAmericanUnits ? '°F' : '°C'
            }
        },
        function() {
            that.adapter.extendObject(
                that.hexAddress + '.humidity',
                {
                    type: 'state',
                    common: {
                        name: that.hexAddress + ' Humidity',
                        read: true,
                        write: false,
                        type: 'number',
                        role: 'value.humidity',
                        unit: '%'
                    }
                },
                function() {
                    that.adapter.extendObject(
                        that.hexAddress + '.pressure',
                        {
                            type: 'state',
                            common: {
                                name: that.hexAddress + ' Pressure',
                                read: true,
                                write: false,
                                type: 'number',
                                role: 'value.pressure',
                                unit: that.useAmericanUnits ? 'inHg' : 'mbar'
                            }
                        },
                        callback);
                });
        });
};

BME280.prototype.checkChipId = function () {
    this.i2cAdapter.bus.writeByteSync(this.address, this.REGISTER_CHIPID, 0);
    var chipId = this.i2cAdapter.bus.readByteSync(this.address, this.REGISTER_CHIPID);
    this.info('Chip ID: 0x' + this.i2cAdapter.toHexString(chipId));
    if (chipId < 0x56 || chipId > 0x60 || chipId == 0x59) {
        throw 'Unsupported chip ID ' + this.i2cAdapter.toHexString(chipId) + '; are you sure this is a BME280?';
    }
};

BME280.prototype.loadCalibration = function () {
    var buffer = new Buffer(24);
    this.i2cAdapter.bus.readI2cBlockSync(this.address, this.REGISTER_DIG_T1, 24, buffer);
    var h1   = this.i2cAdapter.bus.readByteSync(this.address, this.REGISTER_DIG_H1);
    var h2   = this.i2cAdapter.bus.readWordSync(this.address, this.REGISTER_DIG_H2);
    var h3   = this.i2cAdapter.bus.readByteSync(this.address, this.REGISTER_DIG_H3);
    var h4   = this.i2cAdapter.bus.readByteSync(this.address, this.REGISTER_DIG_H4);
    var h5   = this.i2cAdapter.bus.readByteSync(this.address, this.REGISTER_DIG_H5);
    var h5_1 = this.i2cAdapter.bus.readByteSync(this.address, this.REGISTER_DIG_H5 + 1);
    var h6   = this.i2cAdapter.bus.readByteSync(this.address, this.REGISTER_DIG_H6);

    this.cal = {
        dig_T1: this.uint16(buffer[1], buffer[0]),
        dig_T2: this.int16(buffer[3], buffer[2]),
        dig_T3: this.int16(buffer[5], buffer[4]),

        dig_P1: this.uint16(buffer[7], buffer[6]),
        dig_P2: this.int16(buffer[9], buffer[8]),
        dig_P3: this.int16(buffer[11], buffer[10]),
        dig_P4: this.int16(buffer[13], buffer[12]),
        dig_P5: this.int16(buffer[15], buffer[14]),
        dig_P6: this.int16(buffer[17], buffer[16]),
        dig_P7: this.int16(buffer[19], buffer[18]),
        dig_P8: this.int16(buffer[21], buffer[20]),
        dig_P9: this.int16(buffer[23], buffer[22]),

        dig_H1: h1,
        dig_H2: h2,
        dig_H3: h3,
        dig_H4: (h4 << 4) | (h5 & 0xF),
        dig_H5: (h5_1 << 4) | (h5 >> 4),
        dig_H6: h6
    };

    this.debug('cal = ' + JSON.stringify(this.cal));
};

BME280.prototype.configureChip = function () {
    // Humidity 16x oversampling
    this.i2cAdapter.bus.writeByteSync(this.address, this.REGISTER_CONTROL_HUM, 0b00000101);

    // Temperture/pressure 16x oversampling, normal mode
    this.i2cAdapter.bus.writeByteSync(this.address, this.REGISTER_CONTROL, 0b10110111);
};

BME280.prototype.readCurrentValues = function () {
    this.debug('Reading current values');
    try {
        // Grab temperature, humidity, and pressure in a single read
        var buffer = new Buffer(8);
        this.i2cBus.readI2cBlockSync(this.i2cAddress, this.REGISTER_PRESSURE_DATA, 8, buffer);

        // Temperature (temperature first since we need t_fine for pressure and humidity)
        var adc_T = this.uint20(buffer[3], buffer[4], buffer[5]);
        var tvar1 = ((((adc_T >> 3) - (this.cal.dig_T1 << 1))) * this.cal.dig_T2) >> 11;
        var tvar2  = (((((adc_T >> 4) - this.cal.dig_T1) * ((adc_T >> 4) - this.cal.dig_T1)) >> 12) * this.cal.dig_T3) >> 14;
        var t_fine = tvar1 + tvar2;

        var temperature_C = ((t_fine * 5 + 128) >> 8) / 100;

        // Pressure
        var adc_P = this.uint20(buffer[0], buffer[1], buffer[2]);
        var pvar1 = t_fine / 2 - 64000;
        var pvar2 = pvar1 * pvar1 * this.cal.dig_P6 / 32768;
        pvar2 = pvar2 + pvar1 * this.cal.dig_P5 * 2;
        pvar2 = pvar2 / 4 + this.cal.dig_P4 * 65536;
        pvar1 = (this.cal.dig_P3 * pvar1 * pvar1 / 524288 + this.cal.dig_P2 * pvar1) / 524288;
        pvar1 = (1 + pvar1 / 32768) * this.cal.dig_P1;

        var pressure_hPa = 0;

        if(pvar1 !== 0) {
            var p = 1048576 - adc_P;
            p = ((p - pvar2 / 4096) * 6250) / pvar1;
            pvar1 = this.cal.dig_P9 * p * p / 2147483648;
            pvar2 = p * this.cal.dig_P8 / 32768;
            p = p + (pvar1 + pvar2 + this.cal.dig_P7) / 16;

            pressure_hPa = p / 100;
        }

        // Humidity (available on the BME280, will be zero on the BMP280 since it has no humidity sensor)
        var adc_H = this.uint16(buffer[6], buffer[7]);

        var h = t_fine - 76800;
        h = (adc_H - (this.cal.dig_H4 * 64 + this.cal.dig_H5 / 16384 * h)) *
            (this.cal.dig_H2 / 65536 * (1 + this.cal.dig_H6 / 67108864 * h * (1 + this.cal.dig_H3 / 67108864 * h)));
        h = h * (1 - this.cal.dig_H1 * h / 524288);

        var humidity = (h > 100) ? 100 : (h < 0 ? 0 : h);

        this.debug('Read: ' + JSON.stringify({
            temp : temperature_C,
            hum  : humidity,
            press: pressure_hPa
        }));

        this.setStateAck('humidity', humidity);
        if (this.useAmericanUnits) {
            this.setStateAck('temperature', (temperature_C * 9 / 5) + 32);
            this.setStateAck('pressure', pressure_hPa * 0.02952998751);
        } else {
            this.setStateAck('temperature', temperature_C);
            this.setStateAck('pressure', pressure_hPa); // hPa == mbar :-)
        }
    } catch (e) {
        this.error("Couldn't read current values: " + e);
    }
};

BME280.prototype.debug = function (message) {
    this.adapter.log.debug('BME280 ' + this.address + ': ' + message);
};

BME280.prototype.info = function (message) {
    this.adapter.log.info('BME280 ' + this.address + ': ' + message);
};

BME280.prototype.error = function (message) {
    this.adapter.log.error('BME280 ' + this.address + ': ' + message);
};

BME280.prototype.setStateAck = function (name, value) {
    return this.i2cAdapter.setStateAck(this.hexAddress + '.' + name, value);
};

BME280.prototype.getStateValue = function (name) {
    return this.i2cAdapter.getStateValue(this.hexAddress + '.' + name);
};

BME280.prototype.int16 = function (msb, lsb) {
    var val = this.uint16(msb, lsb);
    return val > 32767 ? (val - 65536) : val;
};

BME280.prototype.uint16 = function (msb, lsb) {
    return msb << 8 | lsb;
};

BME280.prototype.uint20 = function (msb, lsb, xlsb) {
    return ((msb << 8 | lsb) << 8 | xlsb) >> 4;
};

module.exports.create = create;<commit_msg>Improved logging and fixed a C&P mistake.<commit_after>"use strict";

/*
 * NOTICE:
 * A lot of this code is based on https://github.com/skylarstein/bme280-sensor
 * We need this to be synchronous and use the same I2C instance as for all other devices; thus the rewrite.
MIT License

Copyright (c) 2016 Skylar Stein

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 */

function create(deviceConfig, i2cAdapter) {
    return new BME280(deviceConfig, i2cAdapter);
}

function BME280(deviceConfig, i2cAdapter) {
    // consts:
    this.REGISTER_DIG_T1 = 0x88;
    this.REGISTER_DIG_T2 = 0x8A;
    this.REGISTER_DIG_T3 = 0x8C;

    this.REGISTER_DIG_P1 = 0x8E;
    this.REGISTER_DIG_P2 = 0x90;
    this.REGISTER_DIG_P3 = 0x92;
    this.REGISTER_DIG_P4 = 0x94;
    this.REGISTER_DIG_P5 = 0x96;
    this.REGISTER_DIG_P6 = 0x98;
    this.REGISTER_DIG_P7 = 0x9A;
    this.REGISTER_DIG_P8 = 0x9C;
    this.REGISTER_DIG_P9 = 0x9E;

    this.REGISTER_DIG_H1 = 0xA1;
    this.REGISTER_DIG_H2 = 0xE1;
    this.REGISTER_DIG_H3 = 0xE3;
    this.REGISTER_DIG_H4 = 0xE4;
    this.REGISTER_DIG_H5 = 0xE5;
    this.REGISTER_DIG_H6 = 0xE7;

    this.REGISTER_CHIPID = 0xD0;
    this.REGISTER_RESET  = 0xE0;

    this.REGISTER_CONTROL_HUM   = 0xF2;
    this.REGISTER_CONTROL       = 0xF4;
    this.REGISTER_PRESSURE_DATA = 0xF7;
    this.REGISTER_TEMP_DATA     = 0xFA;
    this.REGISTER_HUMIDITY_DATA = 0xFD;

    // variables:
    this.address = deviceConfig.address;
    this.name = deviceConfig.name || 'BME280';
    this.hexAddress = i2cAdapter.toHexString(this.address);

    this.config = deviceConfig.BME280;

    this.i2cAdapter = i2cAdapter;
    this.adapter = this.i2cAdapter.adapter;
}

BME280.prototype.start = function () {
    var that = this;
    that.debug('Starting');
    that.adapter.extendObject(
        that.hexAddress,
        {
            type: 'device',
            common: {
                name: that.hexAddress + ' (' + that.name + ')',
                role: 'thermo'
            },
            native: that.config
        },
        function () {
            that.loadSystemConfig(
                function() {
                    that.createStates(
                        function() {
                            that.checkChipId();
                            that.loadCalibration();
                            that.configureChip();
                            that.readCurrentValues();
                            if (that.config.pollingInterval && parseInt(that.config.pollingInterval) > 0) {
                                that.pollingTimer = setInterval(
                                    function () { that.readCurrentValues(); },
                                    parseInt(that.config.pollingInterval) * 1000);
                            }
                        });
                });
        });
};

BME280.prototype.stop = function () {
    this.debug('Stopping');
    clearInterval(this.pollingTimer);
};

BME280.prototype.loadSystemConfig = function (callback) {
    var that = this;
    that.adapter.getForeignObject('system.config', function (err, obj) {
        that.useAmericanUnits = obj && obj.common && obj.common.tempUnit == '°F';
        that.info('Using ' + (that.useAmericanUnits ? 'American' : 'metric') + ' units');

        callback();
    });
};

BME280.prototype.createStates = function (callback) {
    var that = this;
    that.adapter.extendObject(
        that.hexAddress + '.temperature',
        {
            type: 'state',
            common: {
                name: that.hexAddress + ' Temperature',
                read: true,
                write: false,
                type: 'number',
                role: 'value.temperature',
                unit: that.useAmericanUnits ? '°F' : '°C'
            }
        },
        function() {
            that.adapter.extendObject(
                that.hexAddress + '.humidity',
                {
                    type: 'state',
                    common: {
                        name: that.hexAddress + ' Humidity',
                        read: true,
                        write: false,
                        type: 'number',
                        role: 'value.humidity',
                        unit: '%'
                    }
                },
                function() {
                    that.adapter.extendObject(
                        that.hexAddress + '.pressure',
                        {
                            type: 'state',
                            common: {
                                name: that.hexAddress + ' Pressure',
                                read: true,
                                write: false,
                                type: 'number',
                                role: 'value.pressure',
                                unit: that.useAmericanUnits ? 'inHg' : 'mbar'
                            }
                        },
                        callback);
                });
        });
};

BME280.prototype.checkChipId = function () {
    this.i2cAdapter.bus.writeByteSync(this.address, this.REGISTER_CHIPID, 0);
    var chipId = this.i2cAdapter.bus.readByteSync(this.address, this.REGISTER_CHIPID);
    this.info('Chip ID: 0x' + this.i2cAdapter.toHexString(chipId));
    if (chipId < 0x56 || chipId > 0x60 || chipId == 0x59) {
        throw 'Unsupported chip ID ' + this.i2cAdapter.toHexString(chipId) + '; are you sure this is a BME280?';
    }
};

BME280.prototype.loadCalibration = function () {
    var buffer = new Buffer(24);
    this.i2cAdapter.bus.readI2cBlockSync(this.address, this.REGISTER_DIG_T1, 24, buffer);
    var h1   = this.i2cAdapter.bus.readByteSync(this.address, this.REGISTER_DIG_H1);
    var h2   = this.i2cAdapter.bus.readWordSync(this.address, this.REGISTER_DIG_H2);
    var h3   = this.i2cAdapter.bus.readByteSync(this.address, this.REGISTER_DIG_H3);
    var h4   = this.i2cAdapter.bus.readByteSync(this.address, this.REGISTER_DIG_H4);
    var h5   = this.i2cAdapter.bus.readByteSync(this.address, this.REGISTER_DIG_H5);
    var h5_1 = this.i2cAdapter.bus.readByteSync(this.address, this.REGISTER_DIG_H5 + 1);
    var h6   = this.i2cAdapter.bus.readByteSync(this.address, this.REGISTER_DIG_H6);

    this.cal = {
        dig_T1: this.uint16(buffer[1], buffer[0]),
        dig_T2: this.int16(buffer[3], buffer[2]),
        dig_T3: this.int16(buffer[5], buffer[4]),

        dig_P1: this.uint16(buffer[7], buffer[6]),
        dig_P2: this.int16(buffer[9], buffer[8]),
        dig_P3: this.int16(buffer[11], buffer[10]),
        dig_P4: this.int16(buffer[13], buffer[12]),
        dig_P5: this.int16(buffer[15], buffer[14]),
        dig_P6: this.int16(buffer[17], buffer[16]),
        dig_P7: this.int16(buffer[19], buffer[18]),
        dig_P8: this.int16(buffer[21], buffer[20]),
        dig_P9: this.int16(buffer[23], buffer[22]),

        dig_H1: h1,
        dig_H2: h2,
        dig_H3: h3,
        dig_H4: (h4 << 4) | (h5 & 0xF),
        dig_H5: (h5_1 << 4) | (h5 >> 4),
        dig_H6: h6
    };

    this.debug('cal = ' + JSON.stringify(this.cal));
};

BME280.prototype.configureChip = function () {
    // Humidity 16x oversampling
    this.i2cAdapter.bus.writeByteSync(this.address, this.REGISTER_CONTROL_HUM, 0b00000101);

    // Temperture/pressure 16x oversampling, normal mode
    this.i2cAdapter.bus.writeByteSync(this.address, this.REGISTER_CONTROL, 0b10110111);
};

BME280.prototype.readCurrentValues = function () {
    this.debug('Reading current values');
    try {
        // Grab temperature, humidity, and pressure in a single read
        var buffer = new Buffer(8);
        this.i2cAdapter.bus.readI2cBlockSync(this.address, this.REGISTER_PRESSURE_DATA, 8, buffer);

        // Temperature (temperature first since we need t_fine for pressure and humidity)
        var adc_T = this.uint20(buffer[3], buffer[4], buffer[5]);
        var tvar1 = ((((adc_T >> 3) - (this.cal.dig_T1 << 1))) * this.cal.dig_T2) >> 11;
        var tvar2  = (((((adc_T >> 4) - this.cal.dig_T1) * ((adc_T >> 4) - this.cal.dig_T1)) >> 12) * this.cal.dig_T3) >> 14;
        var t_fine = tvar1 + tvar2;

        var temperature_C = ((t_fine * 5 + 128) >> 8) / 100;

        // Pressure
        var adc_P = this.uint20(buffer[0], buffer[1], buffer[2]);
        var pvar1 = t_fine / 2 - 64000;
        var pvar2 = pvar1 * pvar1 * this.cal.dig_P6 / 32768;
        pvar2 = pvar2 + pvar1 * this.cal.dig_P5 * 2;
        pvar2 = pvar2 / 4 + this.cal.dig_P4 * 65536;
        pvar1 = (this.cal.dig_P3 * pvar1 * pvar1 / 524288 + this.cal.dig_P2 * pvar1) / 524288;
        pvar1 = (1 + pvar1 / 32768) * this.cal.dig_P1;

        var pressure_hPa = 0;

        if(pvar1 !== 0) {
            var p = 1048576 - adc_P;
            p = ((p - pvar2 / 4096) * 6250) / pvar1;
            pvar1 = this.cal.dig_P9 * p * p / 2147483648;
            pvar2 = p * this.cal.dig_P8 / 32768;
            p = p + (pvar1 + pvar2 + this.cal.dig_P7) / 16;

            pressure_hPa = p / 100;
        }

        // Humidity (available on the BME280, will be zero on the BMP280 since it has no humidity sensor)
        var adc_H = this.uint16(buffer[6], buffer[7]);

        var h = t_fine - 76800;
        h = (adc_H - (this.cal.dig_H4 * 64 + this.cal.dig_H5 / 16384 * h)) *
            (this.cal.dig_H2 / 65536 * (1 + this.cal.dig_H6 / 67108864 * h * (1 + this.cal.dig_H3 / 67108864 * h)));
        h = h * (1 - this.cal.dig_H1 * h / 524288);

        var humidity = (h > 100) ? 100 : (h < 0 ? 0 : h);

        this.debug('Read: ' + JSON.stringify({
            temp : temperature_C,
            hum  : humidity,
            press: pressure_hPa
        }));

        this.setStateAck('humidity', humidity);
        if (this.useAmericanUnits) {
            this.setStateAck('temperature', (temperature_C * 9 / 5) + 32);
            this.setStateAck('pressure', pressure_hPa * 0.02952998751);
        } else {
            this.setStateAck('temperature', temperature_C);
            this.setStateAck('pressure', pressure_hPa); // hPa == mbar :-)
        }
    } catch (e) {
        this.error("Couldn't read current values: " + e);
    }
};

BME280.prototype.debug = function (message) {
    this.adapter.log.debug('BME280 ' + this.address + ': ' + message);
};

BME280.prototype.info = function (message) {
    this.adapter.log.info('BME280 ' + this.address + ': ' + message);
};

BME280.prototype.error = function (message) {
    this.adapter.log.error('BME280 ' + this.address + ': ' + message);
};

BME280.prototype.setStateAck = function (name, value) {
    return this.i2cAdapter.setStateAck(this.hexAddress + '.' + name, value);
};

BME280.prototype.getStateValue = function (name) {
    return this.i2cAdapter.getStateValue(this.hexAddress + '.' + name);
};

BME280.prototype.int16 = function (msb, lsb) {
    var val = this.uint16(msb, lsb);
    return val > 32767 ? (val - 65536) : val;
};

BME280.prototype.uint16 = function (msb, lsb) {
    return msb << 8 | lsb;
};

BME280.prototype.uint20 = function (msb, lsb, xlsb) {
    return ((msb << 8 | lsb) << 8 | xlsb) >> 4;
};

module.exports.create = create;<|endoftext|>


<commit_before>'use strict';

const db = require('../models/db');
var config = require('config');

module.exports = (req, res, next) => {

  // authentication via API token
  const api_token = req.headers["x-spacedeck-api-token"];

  if (api_token && api_token.length>7) {
    db.User.findOne({where: {api_token: api_token}}).then(user => {
      req.user = user;
      next();
    }).error(err => {
      res.status(403).json({
        "error": "invalid_api-token"
      });
      next();
    });

    return;
  }

  // authentication via session/cookie
  const token = req.cookies["sdsession"];

  if (token && token != "null" && token != null) {
    db.Session.findOne({where: {token: token}})
      .then(session => {
        if (!session) {
          // session not found
          next();
        }
        else db.User.findOne({where: {_id: session.user_id}})
          .then(user => {
            if (!user) {
              var domain = (process.env.NODE_ENV == "production") ? new URL(config.get('endpoint')).hostname : req.headers.hostname;
              res.clearCookie('sdsession', { domain: domain });

              if (req.accepts("text/html")) {
                res.send("Please clear your cookies and try again.");
              } else if (req.accepts('application/json')) {
                res.status(403).json({
                  "error": "token_not_found"
                });
              } else {
                res.send("Please clear your cookies and try again.");
              }

            } else {
              req["token"] = token;
              req["user"] = user;
              next();
            }
          });
      })
      .error(err => {
        console.error("Session resolve error",err);
        next();
      });
  } else {
    next();
  }
}
<commit_msg>fix api-token check<commit_after>"use strict";

const db = require("../models/db");
var config = require("config");

module.exports = (req, res, next) => {
  // authentication via API token
  const api_token = req.headers["x-spacedeck-api-token"];

  if (api_token && api_token.length > 7) {
    db.User.findOne({ where: { api_token: api_token } }).then((user) => {
      if (user) {
        req.user = user;
        next();
      } else {
        res.status(403).json({
          error: "invalid_api-token",
        });
      }
    });

    return;
  }

  // authentication via session/cookie
  const token = req.cookies["sdsession"];

  if (token && token != "null" && token != null) {
    db.Session.findOne({ where: { token: token } })
      .then((session) => {
        if (!session) {
          // session not found
          next();
        } else
          db.User.findOne({ where: { _id: session.user_id } }).then((user) => {
            if (!user) {
              var domain =
                process.env.NODE_ENV == "production"
                  ? new URL(config.get("endpoint")).hostname
                  : req.headers.hostname;
              res.clearCookie("sdsession", { domain: domain });

              if (req.accepts("text/html")) {
                res.send("Please clear your cookies and try again.");
              } else if (req.accepts("application/json")) {
                res.status(403).json({
                  error: "token_not_found",
                });
              } else {
                res.send("Please clear your cookies and try again.");
              }
            } else {
              req["token"] = token;
              req["user"] = user;
              next();
            }
          });
      })
      .error((err) => {
        console.error("Session resolve error", err);
        next();
      });
  } else {
    next();
  }
};
<|endoftext|>


<commit_before>'use strict';

var EXPRESS_PORT    = 1111,
    LIVERELOAD_PORT = 1112,

    gulp       = require('gulp'),
    browserify = require('gulp-browserify'),
    clean      = require('gulp-clean'),
    refresh    = require('gulp-livereload'),
    livereload = require('tiny-lr')(),

    recess = require('gulp-recess'),
    less   = require('gulp-less');

gulp.task('clean', function () {
    gulp
    .src('build', { read: false })
    .pipe(clean());
});

gulp.task('express', function () {
    var express = require('express'),
        connectLiveReload = require('connect-livereload'),
        app = express();

    app.use(connectLiveReload({ port: LIVERELOAD_PORT }));
    app.use(express.directory(__dirname + '/build'));
    app.use(express.static(__dirname + '/build'));
    app.use(express.errorHandler());

    app.listen(EXPRESS_PORT);
});

gulp.task('livereload', function () {
    livereload.listen(LIVERELOAD_PORT);
});

gulp.task('website-pages-css', function () {
    gulp.src('src/website/pages/*/main.less')
    .pipe(recess())
    .pipe(less())
    .pipe(gulp.dest('build/website/pages'))
    .pipe(refresh(livereload));
});

gulp.task('website-pages-html', function () {
    gulp.src('src/website/pages/*/{demo,main,test}.html')
    .pipe(gulp.dest('build/website/pages'))
    .pipe(refresh(livereload));
});

gulp.task('website-pages-js', function () {
    gulp.src('src/website/pages/*/{demo,main,test}.js')
    .pipe(browserify({
        basedir: 'src',
        debug: true
    }))
    .on('prebundle', function (bundle) {
        bundle.external('bootstrap');
        bundle.external('can');
        bundle.external('jQuery');
    })
    .pipe(gulp.dest('build/website/pages'))
    .pipe(refresh(livereload));
});

gulp.task('website-shared-css', function () {
    gulp.src('src/website/shared.less')
    .pipe(recess())
    .pipe(less())
    .pipe(gulp.dest('build/website'))
    .pipe(refresh(livereload));
});

gulp.task('website-shared-js', function () {
    gulp.src('src/website/shared.js')
    .pipe(browserify({
        shim: {
            bootstrap: {
                depends: { jQuery: 'jQuery' },
                exports: null,
                path: 'bower_components/bootstrap/dist/js/bootstrap.js'
            },
            can: {
                depends: { jQuery: 'jQuery' },
                exports: 'can',
                path: 'bower_components/canjs/can.jquery.js'
            },
            jQuery: {
                exports: 'jQuery',
                path: 'bower_components/jquery/jquery.js'
            }
        }
    }))
    .pipe(gulp.dest('build/website'))
    .pipe(refresh(livereload));
});

gulp.task('default', [
    'express',
    'livereload',
    'website-pages-css',
    'website-pages-html',
    'website-pages-js',
    'website-shared-css',
    'website-shared-js',
], function () {
    gulp.watch('src/website/shared.less', ['website-shared-css']);
    gulp.watch('src/website/shared.js', ['website-shared-js']);
    gulp.watch('src/website/{components,pages}/*/*.js', ['website-pages-js']);
    gulp.watch('src/website/{components,pages}/*/*.less', ['website-pages-css']);
});
<commit_msg>watch html and mustache files<commit_after>'use strict';

var EXPRESS_PORT    = 1111,
    LIVERELOAD_PORT = 1112,

    gulp       = require('gulp'),
    browserify = require('gulp-browserify'),
    clean      = require('gulp-clean'),
    refresh    = require('gulp-livereload'),
    livereload = require('tiny-lr')(),

    recess = require('gulp-recess'),
    less   = require('gulp-less');

gulp.task('clean', function () {
    gulp
    .src('build', { read: false })
    .pipe(clean());
});

gulp.task('express', function () {
    var express = require('express'),
        connectLiveReload = require('connect-livereload'),
        app = express();

    app.use(connectLiveReload({ port: LIVERELOAD_PORT }));
    app.use(express.directory(__dirname + '/build'));
    app.use(express.static(__dirname + '/build'));
    app.use(express.errorHandler());

    app.listen(EXPRESS_PORT);
});

gulp.task('livereload', function () {
    livereload.listen(LIVERELOAD_PORT);
});

gulp.task('website-pages-css', function () {
    gulp.src('src/website/pages/*/main.less')
    .pipe(recess())
    .pipe(less())
    .pipe(gulp.dest('build/website/pages'))
    .pipe(refresh(livereload));
});

gulp.task('website-pages-html', function () {
    gulp.src('src/website/pages/*/{demo,main,test}.html')
    .pipe(gulp.dest('build/website/pages'))
    .pipe(refresh(livereload));
});

gulp.task('website-pages-js', function () {
    gulp.src('src/website/pages/*/{demo,main,test}.js')
    .pipe(browserify({
        basedir: 'src',
        debug: true
    }))
    .on('prebundle', function (bundle) {
        bundle.external('bootstrap');
        bundle.external('can');
        bundle.external('jQuery');
    })
    .pipe(gulp.dest('build/website/pages'))
    .pipe(refresh(livereload));
});

gulp.task('website-shared-css', function () {
    gulp.src('src/website/shared.less')
    .pipe(recess())
    .pipe(less())
    .pipe(gulp.dest('build/website'))
    .pipe(refresh(livereload));
});

gulp.task('website-shared-js', function () {
    gulp.src('src/website/shared.js')
    .pipe(browserify({
        shim: {
            bootstrap: {
                depends: { jQuery: 'jQuery' },
                exports: null,
                path: 'bower_components/bootstrap/dist/js/bootstrap.js'
            },
            can: {
                depends: { jQuery: 'jQuery' },
                exports: 'can',
                path: 'bower_components/canjs/can.jquery.js'
            },
            jQuery: {
                exports: 'jQuery',
                path: 'bower_components/jquery/jquery.js'
            }
        }
    }))
    .pipe(gulp.dest('build/website'))
    .pipe(refresh(livereload));
});

gulp.task('default', [
    'express',
    'livereload',
    'website-pages-css',
    'website-pages-html',
    'website-pages-js',
    'website-shared-css',
    'website-shared-js',
], function () {
    gulp.watch('src/website/shared.less', ['website-shared-css']);
    gulp.watch('src/website/shared.js', ['website-shared-js']);
    gulp.watch('src/website/{components,pages}/*/*.html', ['website-pages-html']);
    gulp.watch('src/website/{components,pages}/*/*.{js,mustache}', ['website-pages-js']);
    gulp.watch('src/website/{components,pages}/*/*.less', ['website-pages-css']);
});
<|endoftext|>