'use strict'; /* global Clipboard:false */ +/* global asyncForEach:false */ angular.module('Application').controller('UsersController', ['$scope', '$location', '$timeout', 'Client', function ($scope, $location, $timeout, Client) { Client.onReady(function () { if (!Client.hasScope('users')) $location.path('/'); }); $scope.ready = false; $scope.users = []; $scope.usersById = []; $scope.groups = []; $scope.groupsById = { }; $scope.config = Client.getConfig(); $scope.userInfo = Client.getUserInfo(); $scope.userremove = { busy: false, error: {}, userInfo: {}, password: '', show: function (userInfo) { $scope.userremove.error.username = null; $scope.userremove.error.password = null; $scope.userremove.password = ''; $scope.userremove.userInfo = userInfo; $scope.userremove_form.$setPristine(); $scope.userremove_form.$setUntouched(); $('#userRemoveModal').modal('show'); }, submit: function () { $scope.userremove.error.password = null; $scope.userremove.busy = true; // transfer to self for now. not transferred to owner because this user probably wants to "manage" it immediately // FIXME: this may awkwardly transfer resources but fail with incorrect password Client.transferOwnership($scope.userremove.userInfo.id, $scope.userInfo.id, function (error) { if (error) return console.error('Unable to transfer resources.', error); Client.removeUser($scope.userremove.userInfo.id, $scope.userremove.password, function (error) { $scope.userremove.busy = false; if (error && error.statusCode === 403) { $scope.userremove.error.password = 'Wrong password'; $scope.userremove.password = ''; $scope.userremove_form.password.$setPristine(); $('#inputUserRemovePassword').focus(); return; } if (error) return console.error('Unable to delete user.', error); $scope.userremove.userInfo = {}; $scope.userremove.password = ''; $scope.userremove_form.$setPristine(); $scope.userremove_form.$setUntouched(); refresh(); $('#userRemoveModal').modal('hide'); }); }); } }; $scope.useradd = { busy: false, alreadyTaken: false, error: {}, email: '', username: '', displayName: '', sendInvite: true, selectedGroups: [], superuser: false, show: function () { $scope.useradd.error = {}; $scope.useradd.email = ''; $scope.useradd.username = ''; $scope.useradd.displayName = ''; $scope.useradd.selectedGroups = []; $scope.useradd.superuser = false; $scope.useradd_form.$setUntouched(); $scope.useradd_form.$setPristine(); $('#userAddModal').modal('show'); }, submit: function () { $scope.useradd.busy = true; $scope.useradd.alreadyTaken = false; $scope.useradd.error.email = null; $scope.useradd.error.username = null; $scope.useradd.error.displayName = null; Client.createUser($scope.useradd.username || null, $scope.useradd.email, $scope.useradd.displayName, $scope.useradd.sendInvite, function (error, newUserInfo) { if (error) { $scope.useradd.busy = false; if (error.statusCode === 409) { if (error.message.toLowerCase().indexOf('email') !== -1) { $scope.useradd.error.email = 'Email already taken'; $scope.useradd_form.email.$setPristine(); $('#inputUserAddEmail').focus(); } else if (error.message.toLowerCase().indexOf('username') !== -1 || error.message.toLowerCase().indexOf('mailbox') !== -1) { $scope.useradd.error.username = 'Username already taken'; $scope.useradd_form.username.$setPristine(); $('#inputUserAddUsername').focus(); } else { // should not happen!! console.error(error.message); } return; } else if (error.statusCode === 400) { if (error.message.toLowerCase().indexOf('email') !== -1) { $scope.useradd.error.email = 'Invalid Email'; $scope.useradd.error.emailAttempted = $scope.useradd.email; $scope.useradd_form.email.$setPristine(); $('#inputUserAddEmail').focus(); } else if (error.message.toLowerCase().indexOf('username') !== -1) { $scope.useradd.error.username = error.message; $scope.useradd_form.username.$setPristine(); $('#inputUserAddUsername').focus(); } else { console.error('Unable to create user.', error.statusCode, error.message); } return; } else { return console.error('Unable to create user.', error.statusCode, error.message); } } var groupIds = $scope.useradd.selectedGroups.map(function (g) { return g.id; }); if ($scope.useradd.superuser) { if (groupIds.indexOf('admin') === -1) groupIds.push('admin'); } else { groupIds = groupIds.filter(function (groupId) { return groupId !== 'admin'; }); } Client.setGroups(newUserInfo.id, groupIds, function (error) { $scope.useradd.busy = false; if (error) return console.error('Unable to update groups for user:', error); refresh(); $('#userAddModal').modal('hide'); }); }); } }; $scope.useredit = { busy: false, error: {}, userInfo: {}, email: '', fallbackEmail: '', aliases: {}, displayName: '', superuser: false, selectedGroups: [], show: function (userInfo) { $scope.useredit.error = {}; $scope.useredit.email = userInfo.email; $scope.useredit.displayName = userInfo.displayName; $scope.useredit.fallbackEmail = userInfo.fallbackEmail; $scope.useredit.userInfo = userInfo; $scope.useredit.selectedGroups = userInfo.groupIds.map(function (gid) { return $scope.groupsById[gid]; }); $scope.useredit.superuser = userInfo.groupIds.indexOf('admin') !== -1; $scope.useredit_form.$setPristine(); $scope.useredit_form.$setUntouched(); $('#userEditModal').modal('show'); }, submit: function () { $scope.useredit.error = {}; $scope.useredit.busy = true; var userId = $scope.useredit.userInfo.id; var data = { id: userId, email: $scope.useredit.email, displayName: $scope.useredit.displayName, fallbackEmail: $scope.useredit.fallbackEmail }; Client.updateUser(data, function (error) { if (error) { $scope.useredit.busy = false; if (error.statusCode === 409) { $scope.useredit.error.email = 'Email already taken'; $scope.useredit_form.email.$setPristine(); $('#inputUserEditEmail').focus(); } else { console.error('Unable to update user:', error); } return; } var groupIds = $scope.useredit.selectedGroups.map(function (g) { return g.id; }); if ($scope.useredit.superuser) { if (groupIds.indexOf('admin') === -1) groupIds.push('admin'); } else { groupIds = groupIds.filter(function (groupId) { return groupId !== 'admin'; }); } Client.setGroups(data.id, groupIds, function (error) { $scope.useredit.busy = false; if (error) return console.error('Unable to update groups for user:', error); refresh(); $('#userEditModal').modal('hide'); }); }); } }; $scope.groupAdd = { busy: false, error: {}, name: '', roles: { canManageUsers: false, canManageApps: false, canManageDomains: false, }, show: function () { $scope.groupAdd.busy = false; $scope.groupAdd.error = {}; $scope.groupAdd.name = ''; $scope.groupAddForm.$setUntouched(); $scope.groupAddForm.$setPristine(); $('#groupAddModal').modal('show'); }, submit: function () { $scope.groupAdd.busy = true; $scope.groupAdd.error = {}; var roles = [ ]; if ($scope.groupAdd.roles.canManageApps) roles.push('manage_apps'); if ($scope.groupAdd.roles.canManageUsers) roles.push('manage_users'); if ($scope.groupAdd.roles.canManageDomains) roles.push('manage_domains'); Client.createGroup($scope.groupAdd.name, roles, function (error) { $scope.groupAdd.busy = false; if (error && error.statusCode === 409) { $scope.groupAdd.error.name = 'Name already taken'; $scope.groupAddForm.name.$setPristine(); $('#groupAddName').focus(); return; } if (error && error.statusCode === 400) { $scope.groupAdd.error.name = error.message; $scope.groupAddForm.name.$setPristine(); $('#groupAddName').focus(); return; } if (error) return console.error('Unable to create group.', error.statusCode, error.message); refresh(); $('#groupAddModal').modal('hide'); }); } }; $scope.groupEdit = { busy: false, error: {}, groupInfo: {}, name: '', selectedUsers: [], roles: { canManageUsers: false, canManageApps: false, canManageDomains: false, }, show: function (groupInfo) { $scope.groupEdit.error = {}; $scope.groupEdit.groupInfo = groupInfo; $scope.groupEdit.name = groupInfo.name; $scope.groupEdit.selectedUsers = groupInfo.userIds.map(function (uid) { return $scope.usersById[uid]; }); for (var i = 0; i < groupInfo.roles.length; i++) { switch (groupInfo.roles[i]) { case 'manage_apps': $scope.groupEdit.roles.canManageApps = true; break; case 'manage_users': $scope.groupEdit.roles.canManageUsers = true; break; case 'manage_domains': $scope.groupEdit.roles.canManageDomains = true; break; default: break; } } $scope.groupEdit_form.$setPristine(); $scope.groupEdit_form.$setUntouched(); $('#groupEditModal').modal('show'); }, submit: function () { $scope.groupEdit.busy = true; $scope.groupEdit.error = {}; var roles = [ ]; if ($scope.groupEdit.roles.canManageApps) roles.push('manage_apps'); if ($scope.groupEdit.roles.canManageUsers) roles.push('manage_users'); if ($scope.groupEdit.roles.canManageDomains) roles.push('manage_domains'); Client.updateGroup($scope.groupEdit.groupInfo.id, $scope.groupEdit.name, roles, function (error) { if (error) { $scope.groupEdit.busy = false; if (error.statusCode === 409) { $scope.groupEdit.error.name = 'Name already taken'; $scope.groupEditForm.name.$setPristine(); $('#groupEditName').focus(); return; } else if (error.statusCode === 400) { $scope.groupEdit.error.name = error.message; $scope.groupEditForm.name.$setPristine(); $('#groupEditName').focus(); return; } else { return console.error('Unable to edit group.', error.statusCode, error.message); } } var userIds = $scope.groupEdit.selectedUsers.map(function (u) { return u.id; }); Client.setGroupMembers($scope.groupEdit.groupInfo.id, userIds, function (error) { $scope.groupEdit.busy = false; if (error) return console.error('Unable to edit group.', error.statusCode, error.message); refresh(); $('#groupEditModal').modal('hide'); }); }); } }; $scope.inviteSent = { email: '', setupLink: '' }; $scope.groupRemove = { busy: false, error: {}, group: null, password: '', memberCount: 0, show: function (group) { $scope.groupRemove.busy = false; $scope.groupRemove.error = {}; $scope.groupRemove.password = ''; $scope.groupRemove.group = angular.copy(group); $scope.groupRemoveForm.$setUntouched(); $scope.groupRemoveForm.$setPristine(); Client.getGroup(group.id, function (error, result) { if (error) return console.error('Unable to fetch group information.', error.statusCode, error.message); $scope.groupRemove.memberCount = result.userIds.length; $('#groupRemoveModal').modal('show'); }); }, submit: function () { $scope.groupRemove.busy = true; $scope.groupRemove.error = {}; Client.removeGroup($scope.groupRemove.group.id, $scope.groupRemove.password, function (error) { $scope.groupRemove.busy = false; if (error && error.statusCode === 403) { $scope.groupRemove.error.password = 'Wrong password'; $scope.groupRemove.password = ''; $scope.groupRemoveForm.password.$setPristine(); $('#groupRemovePasswordInput').focus(); return; } if (error) return console.error('Unable to remove group.', error.statusCode, error.message); refresh(); $('#groupRemoveModal').modal('hide'); }); } }; $scope.isMe = function (user) { return user.username === Client.getUserInfo().username; }; $scope.sendInvite = function (user) { $scope.inviteSent.email = user.fallbackEmail; $scope.inviteSent.setupLink = ''; Client.sendInvite(user, function (error, resetToken) { if (error) return console.error(error); // Client.notify('', 'Invitation was successfully sent to ' + user.email + '.', false, 'success'); $scope.inviteSent.setupLink = location.origin + '/api/v1/session/account/setup.html?reset_token=' + resetToken + '&email=' + encodeURIComponent(user.email); $('#inviteSentModal').modal('show'); }); }; $scope.copyToClipboard = function (/*value*/) { document.execCommand('copy'); }; function getUsers(callback) { var users = [ ]; Client.getUsers(function (error, results) { if (error) return console.error(error); asyncForEach(results, function (result, iteratorDone) { Client.getUser(result.id, function (error, user) { if (error) return iteratorDone(error); users.push(user); iteratorDone(); }); }, function (error) { callback(error, users); }); }); } function getGroups(callback) { var groups = [ ]; Client.getGroups(function (error, results) { if (error) return console.error(error); asyncForEach(results, function (result, iteratorDone) { Client.getGroup(result.id, function (error, group) { if (error) return iteratorDone(error); groups.push(group); iteratorDone(); }); }, function (error) { callback(error, groups); }); }); } function refresh() { getGroups(function (error, result) { if (error) return console.error('Unable to get group listing.', error); angular.copy(result, $scope.groups); $scope.groupsById = { }; for (var i = 0; i < result.length; i++) { $scope.groupsById[result[i].id] = result[i]; } getUsers(function (error, result) { if (error) return console.error('Unable to get user listing.', error); angular.copy(result, $scope.users); $scope.usersById = { }; for (var i = 0; i < result.length; i++) { $scope.usersById[result[i].id] = result[i]; } $scope.ready = true; }); }); } Client.onReady(refresh); // setup all the dialog focus handling ['userAddModal', 'userRemoveModal', 'userEditModal', 'groupAddModal', 'groupEditModal', 'groupRemoveModal'].forEach(function (id) { $('#' + id).on('shown.bs.modal', function () { $(this).find("[autofocus]:first").focus(); }); }); var clipboard = new Clipboard('#setupLinkButton'); clipboard.on('success', function(e) { $('#setupLinkButton').tooltip({ title: 'Copied!', trigger: 'manual' }).tooltip('show'); $timeout(function () { $('#setupLinkButton').tooltip('hide'); }, 2000); e.clearSelection(); }); clipboard.on('error', function(/*e*/) { $('#setupLinkButton').tooltip({ title: 'Press Ctrl+C to copy', trigger: 'manual' }).tooltip('show'); $timeout(function () { $('#setupLinkButton').tooltip('hide'); }, 2000); }); $('.modal-backdrop').remove(); }]);