/src/main/webapp/scripts/xnat/admin/usersGroups.js
JavaScript | 1796 lines | 1431 code | 136 blank | 229 comment | 110 complexity | b4934aaa5810205cac3ee5f7207b75ec MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*
- * web: usersGroups.js
- * XNAT http://www.xnat.org
- * Copyright (c) 2005-2017, Washington University School of Medicine and Howard Hughes Medical Institute
- * All Rights Reserved
- *
- * Released under the Simplified BSD.
- */
- console.log('usersGroups.js');
- var XNAT = getObject(XNAT);
- (function(factory){
- if (typeof define === 'function' && define.amd) {
- define(factory);
- }
- else if (typeof exports === 'object') {
- module.exports = factory();
- }
- else {
- return factory();
- }
- }(function(){
- var undefined, usersGroups, newUser = '',
- BASE_URL = '/xapi/users',
- passwordComplexity =
- XNAT.data.siteConfig.passwordComplexity
- .replace(/^\^*/, '^')
- .replace(/\$*$/, '$'),
- passwordComplexityMessage = XNAT.data.siteConfig.passwordComplexityMessage,
- activeUsers = XNAT.data['/xapi/users/active'];
- var userTableContainer = 'div#user-table-container';
- XNAT.admin = getObject(XNAT.admin || {});
- XNAT.admin.usersGroups = usersGroups =
- getObject(XNAT.admin.usersGroups || {});
- XNAT.usersGroups = extend(true, usersGroups, XNAT.usersGroups);
- var userAdminPage = (XNAT.page && XNAT.page.userAdminPage) || false;
- // usersGroups.showAdvanced = true;
- usersGroups.showAdvanced = userAdminPage;
- usersGroups.adminControls = userAdminPage;
- // return a url for doing a rest call
- function setUrl(part1, part2, part3){
- var fullUrl = BASE_URL +
- (part1 ? ('/' + part1) : '') +
- (part2 ? ('/' + part2) : '') +
- (part3 ? ('/' + part3) : '');
- return XNAT.url.rootUrl(fullUrl)
- }
- usersGroups.setUrl = setUrl;
- // create urls based on minimal input
- function usersUrl(user){
- // resolve url arguments
- function urlArgs(username, path, param){
- username = username || user || '';
- param = param || username || '';
- username = (username||'') === param ? user : username;
- return setUrl(username, path, param)
- }
- return {
- allUsers: function(){
- return setUrl()
- },
- userProfile: function(username){
- return setUrl(username||user)
- },
- allUserProfiles: function(){
- return setUrl('profiles')
- },
- activeUser: function(username){
- return setUrl('active', username||user)
- },
- allActiveUsers: function(){
- return setUrl('active')
- },
- enabledUser: function(username, flag){
- return urlArgs(username, 'enabled', flag)
- },
- // XNAT.admin.usersGroups.url('bob').groups()
- // XNAT.admin.usersGroups.url().groups('bob')
- // --> '/xapi/users/bob/groups'
- groups: function(username, group){
- return urlArgs(username, 'groups', group)
- },
- roles: function(username, role){
- return urlArgs(username, 'roles', role)
- },
- verified: function(username, flag){
- return urlArgs(username, 'verified', flag)
- }
- }
- }
- usersGroups.url = usersUrl;
- function xapiUsers(method, url, opts){
- method = method || 'get';
- var methodGET = /^get$/i.test(method);
- opts = cloneObject(opts);
- opts.url = opts.url || url;
- if (methodGET){
- // the 'restuUrl' method adds a cache-busting parameter
- opts.url = XNAT.url.restUrl(opts.url);
- }
- else {
- opts.url = XNAT.url.rootUrl(opts.url);
- }
- return XNAT.xhr[method](opts).done(function(data){
- // cache returned 'get' data at URL
- if (methodGET) XNAT.data[url] = data;
- });
- }
- // get or set data via REST
- usersGroups.userData = function(user){
- var methods = {
- // generic method for any kind of request
- request: function(method, path, data, opts){
- path = [].concat(path);
- opts = getObject(opts);
- opts.data = data || opts.data || '';
- return xapiUsers(method, setUrl.apply(null, path), opts)
- },
- userList: function(opts){
- return xapiUsers('get', setUrl(), opts);
- },
- allProfiles: function(opts){
- return xapiUsers('get', setUrl('profiles'), opts);
- },
- // XNAT.usersGroups.userData('bob').profile().done(someCallbackFunction)
- getProfile: function(opts){
- return xapiUsers('get', setUrl('profile/' + user), opts);
- },
- createProfile: function(data, opts){
- opts = getObject(opts);
- opts.data = data || opts.data || '';
- return xapiUsers('postJSON', setUrl(user), opts)
- },
- updateProfile: function(data, opts){
- opts = getObject(opts);
- opts.data = data || opts.data || '';
- return xapiUsers('putJSON', setUrl(user), opts)
- },
- activeUsers: function(opts){
- return xapiUsers('get', setUrl('active'), opts)
- }
- };
- methods.allUsers = methods.userList;
- methods.usernames = methods.userList;
- methods.profiles = methods.allProfiles;
- methods.userProfiles = methods.allProfiles;
- methods.allUserProfiles = methods.allProfiles;
- // decide whether to GET or POST
- // based on presence of 'data' argument
- methods.profile = function(data, opts){
- var method = 'createProfile';
- if (!data && !opts) {
- method = 'getProfile'
- }
- return methods[method](data, opts);
- };
- methods.createUser = methods.createProfile;
- methods.updateUser = methods.updateProfile;
- return methods;
- };
- // RETURNS A DOM ELEMENT
- usersGroups.userSwitchElement = function(username, type, status){
- return XNAT.ui.input.switchbox({
- value: firstDefined(status, '') + '',
- element: {
- name: type,
- className: 'user-' + type,
- checked: status,
- title: username + ':' + type
- },
- onText: 'Yes',
- offText: 'No'
- }).get();
- };
- // use this to spawn the user account form separately
- function renderUserAccountForm(data, container){
- return XNAT.spawner.spawn({
- userAccountForm: userAccountForm(data)
- }).render(container)
- }
- function saveUserData(form, opts){
- var $form = $$(form);
- // var username = $form.find('input#username').val();
- opts = cloneObject(opts);
- opts.cache = false;
- var successMsg = opts.msg || 'User info saved.';
- var doSubmit = $form.submitJSON(opts);
- if (doSubmit.done) {
- doSubmit.done(function(){
- // xmodal.loading.open();
- XNAT.ui.banner.top(2000, successMsg, 'success')
- });
- }
- if (doSubmit.fail) {
- doSubmit.fail(function(e){
- XNAT.ui.dialog.alert('' +
- 'An error occurred saving user data.' +
- '<br>' +
- '<div class="error">' + e + '</div>' +
- '');
- });
- }
- return doSubmit;
- }
- // define the user properties dialog
- function editUserDialog(data, onclose){
- if (data && !data.username) {
- return XNAT.dialog.message('Error', 'An error occurred displaying user data.');
- }
- // define the <form> Spawner element
- function userForm(){
- return {
- userForm: {
- tag: 'div.user-account-info',
- //kind: 'panel.multiForm',
- //classes: 'user-details',
- // label: 'User Details',
- //header: false,
- //footer: false,
- contents: {
- userAccountForm: userAccountForm(data)//,
- //userProjects: userProjects(),
- //userSecurity: userSecurity()
- }
- }
- }
- }
- // TODO: replace old 'advanced' project settings with this
- function userProjects(){
- return {
- kind: 'panel.form',
- title: 'Project Membership & Roles',
- contents: {
- projectMembership: {
- tag: 'div.project-membership',
- content: '<i>project membership and role menus go here</i>'
- }
- }
- }
- }
- // TODO: replace old 'advanced' security settings with this
- function userSecurity(){
- return {
- kind: 'panel.form',
- name: 'securitySettings',
- title: 'Security Settings',
- // action: '#!',
- // action: '/xapi/users/' + data.username + '/roles',
- // action: '/data/user/' + data.username + '/roles',
- // _action: '/app/action/ModifyUserGroups',
- contents: {
- systemRolesSubhead: {
- kind: 'panel.subhead',
- label: 'System Roles'
- },
- csrfToken: {
- kind: 'input.hidden',
- name: 'XNAT_CSRF',
- value: csrfToken
- },
- siteManager: {
- kind: 'panel.input.switchbox',
- label: 'Site Manager',
- id: 'custom-role-administrator',
- name: 'custom_role',
- value: 'Administrator',
- element: {
- checked: (data.roles.indexOf('Administrator') > -1)
- },
- description: '<p>This allows users to access the Administrative pages of the web interface.</p>' +
- '<div class="warning">' +
- '<b>WARNING:</b> Granting administrative privileges allows this user great power ' +
- 'over the entire site.' +
- '</div>'
- },
- nonExpiring: {
- kind: 'panel.input.switchbox',
- label: 'Non-Expiring',
- id: 'custom-role-non-expiring',
- name: 'custom_role',
- value: 'non_expiring',
- element: {
- checked: (data.roles.indexOf('non_expiring') > -1)
- },
- description: '<p>This prevents this accounts password from expiring.</p>' +
- '<div class="warning">' +
- '<b>WARNING:</b> Granting a user account a non-expiring password is a security risk ' +
- 'and should be limited to accounts that perform automated system tasks. In addition, ' +
- 'if any users are designated as non-expiring access to the user list should be ' +
- 'restricted to administrators.' +
- '</div>'
- },
- allDataSubhead: {
- kind: 'panel.subhead',
- label: 'Allow All Data Access'
- },
- allDataRadios: {
- tag: 'div.all-data-radios',
- contents: {
- noRadio: {
- kind: 'input.radio',
- id: 'data_none',
- name: 'xdat:user.groups.groupID[0].groupID',
- label: 'No',
- value: 'NULL'//,
- // afterElement: 'No'
- },
- readOnlyRadio: {
- kind: 'input.radio',
- id: 'data_access',
- name: 'xdat:user.groups.groupID[0].groupID',
- label: 'Read Only',
- value: 'ALL_DATA_ACCESS'
- },
- readEditDeleteRadio: {
- kind: 'input.radio',
- id: 'data_admin',
- name: 'xdat:user.groups.groupID[0].groupID',
- label: 'Read, Edit, Delete',
- value: 'ALL_DATA_ADMIN'
- }
- }
- },
- allDataWarning: {
- tag: 'div.warning',
- content: 'WARNING: Allowing full access to data will allow this user to see ALL data ' +
- 'stored in this system. It supersedes project membership. Most accounts on your server ' +
- 'should NOT have All Data Access allowed.'
- }
- }
- }
- }
- var updated = false;
- return XNAT.dialog.open({
- width: 600,
- // height: 600,
- speed: 200,
- esc: true,
- enter: false,
- title: 'User Properties for <b>' + data.username + '</b>',
- content: XNAT.spawner.spawn(userForm()).get(),
- buttons: [
- {
- label: 'Save',
- close: false,
- isDefault: true,
- action: function(obj){
- var $form = obj.$modal.find('form');
- if (XNAT.validate.form($form)){
- var doSave = saveUserData($form);
- doSave.done(function(){
- updated = true;
- obj.close();
- });
- }
- }
- },
- {
- label: 'Cancel',
- close: true
- }
- ],
- onClose: function(obj){
- if (typeof onclose === 'function') {
- onclose(obj)
- }
- if (updated) {
- updateUserData(data.username);
- // renderUsersTable();
- }
- }
- })
- }
- // get user data and return AJAX promise object
- function getUserData(username){
- var _url = XNAT.url.restUrl('/xapi/users/profile/' + username);
- delete XNAT.data['/xapi/users/profile/' + username];
- delete XNAT.data['/xapi/users/profiles'];
- delete XNAT.data['/xapi/users/current'];
- delete XNAT.data['/xapi/users/' + username];
- return XNAT.xhr.get(_url)
- }
- // get user roles and return AJAX promise object
- function getUserRoles(username){
- var _url = XNAT.url.restUrl('/xapi/users/' + username + '/roles');
- return XNAT.xhr.get(_url);
- }
- function getActiveUsers(success, failure){
- // console.log(getActiveUsers.name);
- return XNAT.xhr.get({
- url: XNAT.url.restUrl('/xapi/users/active'),
- success: function(data){
- XNAT.data['/xapi/users/active'] = data;
- if (isFunction(success)) {
- success.apply(this, arguments);
- }
- },
- failure: failure
- })
- }
- function showUsersTable(){
- // console.log('showUsersTable');
- // $$($table).removeClass('hidden');
- // $$($table).show();
- }
- usersGroups.showUsersTable = showUsersTable;
- // render or update the users table
- function renderUsersTable(container, url){
- // console.log('renderUsersTable');
- var $container = container ? $$(container) : $(userTableContainer);
- if ($container.length) {
- setTimeout(function(){
- $container.html('loading...');
- setTimeout(function(){
- XNAT.dialog.loadingBar.show();
- XNAT.spawner.spawn({
- usersTable: usersGroups.spawnUsersTable(url)
- }).render($container.empty(), function(){
- XNAT.dialog.loadingBar.hide();
- });
- }, 10);
- }, 1);
- // return _usersTable;
- }
- }
- usersGroups.renderUsersTable = renderUsersTable;
- // TODO: re-render *only* the table rows, not the whole table
- function updateUsersTable(refresh, all){
- var URL = all ? '/xapi/users/profiles' : '/xapi/users/current';
- if (!refresh && XNAT.data[URL]) {
- getActiveUsers(function(){
- renderUsersTable();
- });
- return {
- done: function(callback){
- callback.call()
- }
- }
- }
- return XNAT.xhr.get({
- url: XNAT.url.restUrl(URL),
- success: function(data){
- XNAT.data[URL] = data;
- // console.log(data);
- getActiveUsers(function(){
- renderUsersTable();
- });
- }
- })
- }
- usersGroups.updateUsersTable = updateUsersTable;
- // get profile data for ALL users
- function getUserProfiles(success, failure){
- return XNAT.xhr.get({
- url: XNAT.url.restUrl('/xapi/users/profiles'),
- success: function(data){
- XNAT.data['/xapi/users/profiles'] = data;
- if (isFunction(success)) {
- success.apply(this, arguments);
- }
- },
- failure: failure
- })
- }
- usersGroups.getUserProfiles = getUserProfiles;
- // get profile data for users considered 'current'
- function getCurrentUsers(success, failure){
- return XNAT.xhr.get({
- url: XNAT.url.restUrl('/xapi/users/current'),
- success: function(data){
- XNAT.data['/xapi/users/current'] = data;
- if (isFunction(success)) {
- success.apply(this, arguments);
- }
- },
- failure: failure
- })
- }
- usersGroups.getCurrentUsers = getCurrentUsers;
- // renders cells for 'verified' and 'enabled' status
- function userStatusInfo(type, off){
- var username = escapeHtml(this.username || '');
- var status = realValue(this[type]);
- var SORTER = status ? 1 : 0;
- var iconClass = status ? '.fa-check' : '';
- return spawn('!', [
- ['i.hidden.sorting.filtering.' + type, SORTER+''],
- ['a.user-' + type + '-status.edit-user', {
- title: username + ': ' + (status ? type : off),
- href: '#!',
- style: { display: 'block', padding: '2px' }
- }, [['i.fa' + iconClass ]]]
- ]);
- }
- // renders cells for 'active' users column
- function activeUserInfo(){
- var username = escapeHtml(this.username || '');
- var sessionCount = 0;
- activeUsers = XNAT.data['/xapi/users/active'];
- if (username && activeUsers && activeUsers[username] && activeUsers[username].sessions.length) {
- sessionCount = activeUsers[username].sessions.length
- }
- if (sessionCount) {
- return spawn('!', [
- ['i.hidden.sorting', zeroPad(sessionCount, 6)],
- ['a.active-user', {
- title: username + ': kill ' + sessionCount + ' active session(s)',
- href: '#!',
- style: { display: 'block', padding: '2px' }
- }, [['i.fa.fa-user-circle']]]
- ])
- }
- }
- // renders cells for last login column
- function lastLoginInfo(value){
- value = realValue(value) || 0;
- return spawn('!', [
- ['i.last-login.hidden.sorting', (9999999999999-value || '9999999999999')+''],
- ['input.hidden.last-login.timestamp.filtering|type=hidden', { value: value }],
- ['span.date-time', (value ? (new Date(value)).toLocaleString() : '')]
- ])
- }
- // set unique id attribute for <tr> elements
- // by combining username and user id
- function setRowId(profile){
- return profile.username + '-' + profile.id;
- }
- // update ONLY the row of the edited user
- function updateUserRow(profile){
- var rowId = setRowId(profile);
- var $row = $(document.getElementById(rowId));
- // full name column
- $row.find('a.full-name')
- .html(escapeHtml(profile.lastName + ', ' + profile.firstName));
- // email column
- $row.find('a.send-email')
- .attr('title', profile.email + ': send email')
- .html(escapeHtml(profile.email));
- // verified status column
- $row.find('td.verified')
- .empty()
- .append(userStatusInfo.call(profile, 'verified', 'unverified'));
- // enabled status column
- $row.find('td.enabled')
- .empty()
- .append(userStatusInfo.call(profile, 'enabled', 'disabled'));
- // active status column
- $row.find('td.active')
- .empty()
- .append(activeUserInfo.call(profile));
- // last login column
- $row.find('td.last-login')
- .empty()
- .append(lastLoginInfo(profile.lastSuccessfulLogin));
- }
- function updateUserData(username, delay){
- var USERNAME = typeof username === 'string' ? username : this.title.split(':')[0];
- var USER_URL = USERNAME === 'profiles' ? '/xapi/users/profiles' : '/xapi/users/profile/' + USERNAME;
- return XNAT.xhr.get({
- url: XNAT.url.restUrl(USER_URL),
- success: function(DATA){
- // XNAT.data[USER_URL] = DATA;
- if (userAdminPage) {
- window.setTimeout(function(){
- getActiveUsers().done(function(ACTIVE){
- XNAT.data['/xapi/users/active'] = ACTIVE;
- forEach([].concat(DATA), function(profile, i){
- updateUserRow(profile);
- });
- })
- }, delay||100);
- }
- }
- })
- }
- usersGroups.changePasswordDialog = function(data){
- function changePasswordForm(){
- var form = {
- kind: 'panel.form',
- name: 'changeUserPasswordForm',
- id: 'change-user-password-form',
- label: 'Change Password',
- footer: false,
- validate: true,
- method: 'PUT',
- contentType: 'json',
- refresh: false,
- reload: true,
- action: '~/xapi/users/' + data.username,
- element: {
- autocomplete: 'off'
- },
- contents: {
- username: {
- kind: 'panel.input.hidden',
- value: data.username
- },
- password: {
- kind: 'panel.input.password',
- label: 'Password',
- element: {
- placeholder: '*****',
- autocomplete: 'off',
- data: { message: passwordComplexityMessage }
- },
- validate: 'required pattern:'+passwordComplexity+' max-length:255'
- },
- confirmPassword: {
- kind: 'panel.input.password',
- label: 'Confirm Password',
- element: {
- placeholder: '*****',
- autocomplete: 'off',
- data: { message: 'Password fields must match' }
- },
- validate: 'matches:[name=password]'
- }
- }
- };
- return form;
- }
- var cpForm$ = null;
- var updated = false;
- var formContainer$ = null;
- XNAT.dialog.open({
- title: 'Change Password for '+data.username,
- width: 500,
- content: '<div id="change-password-form"></div>',
- beforeShow: function(obj){
- formContainer$ = obj.dialog$.find('#change-password-form');
- XNAT.spawner.spawn({
- changePasswordForm: changePasswordForm()
- }).render(formContainer$);
- },
- afterShow: function(){
- cpForm$ = formContainer$.find('form');
- },
- buttons: [
- {
- label: 'Update Password',
- close: false,
- isDefault: true,
- action: function(obj){
- var doSave = saveUserData(cpForm$, { msg: 'User password updated successfully' });
- doSave.done(function(){
- updated = true;
- obj.close();
- });
- }
- },
- {
- label: 'Cancel',
- close: true
- }
- ]
- });
- };
- function userAccountForm(data){
- data = data || {};
- var usernameEsc = data.username = escapeHtml(data.username || '');
- var _load = data ? XNAT.url.restUrl('/xapi/users/profile/' + data.username) : false;
- var doEdit = _load && data.username;
- // username could be text or input element
- function usernameField(username){
- var obj = {
- label: 'Username'
- };
- if (data && data.username) {
- obj.kind = 'panel.element';
- obj.contents = {
- usernameText: {
- kind: 'html',
- content: usernameEsc
- },
- usernameInput: {
- kind: 'input.hidden',
- name: 'username',
- value: data.username || ''
- }
- };
- }
- else {
- obj.kind = 'panel.input.text';
- obj.name = 'username';
- obj.validate = 'username required';
- obj.value = '';
- }
- return obj;
- }
- function passwordField(){
- var obj = {
- label: 'Password'
- };
- if (data && data.username) {
- obj.kind = 'panel.element';
- obj.contents = {
- changePasswordLink: {
- kind: 'html',
- content:
- '<a href="#!" class="change-password" style="display: inline-block; margin: -4px 0 4px;" data-username="'+data.username+'">' +
- '<button class="btn btn-sm">Change User Password</button></a>'
- }
- }
- }
- else {
- obj.kind = 'panel.input.password';
- obj.element = {
- placeholder: '*****',
- autocomplete: 'off',
- data: { message: passwordComplexityMessage }
- };
- obj.validate = 'allow-empty pattern:'+passwordComplexity+' max-length:255'
- }
- return obj;
- }
- function confirmPasswordField(){
- if (data && data.username) {
- return false;
- }
- else {
- return {
- kind: 'panel.input.password',
- label: 'Confirm Password',
- element: {
- placeholder: '*****',
- autocomplete: 'off',
- data: { message: 'Password fields must match' }
- },
- validate: 'matches:[name=password]'
- }
- }
- }
- var userVerified = data.verified || 'false';
- var userEnabled = data.enabled || 'false';
- var form = {
- kind: 'panel.form',
- name: 'userAccountForm',
- id: 'user-account-form',
- label: 'Account Information',
- footer: false,
- validate: true,
- method: doEdit ? 'PUT' : 'POST',
- contentType: 'json',
- load: doEdit ? '$? *' + _load : '',
- refresh: true,
- reload: true,
- action: '~/xapi/users' + (doEdit ? ('/' + data.username) : ''),
- element: {
- autocomplete: 'off'
- },
- contents: {
- // details: {
- // kind: 'panel.subhead',
- // label: 'User Details'
- // },
- // id: {
- // kind: 'panel.input.hidden',
- // validate: _load ? 'number required' : 'allow-empty',
- // value: data.id || ''
- // },
- // pad: {
- // html: '<br>'
- // },
- usernameField: usernameField(),
- password: passwordField(),
- confirmPassword: confirmPasswordField(),
- firstName: {
- kind: 'panel.input.text',
- label: 'First Name',
- validate: 'name-safe required',
- value: data.firstName || ''
- },
- lastName: {
- kind: 'panel.input.text',
- label: 'Last Name',
- validate: 'name-safe required',
- value: data.lastName || ''
- },
- email: {
- kind: 'panel.input.email',
- label: 'Email',
- validate: 'email required',
- value: data.email || ''
- }
- }
- };
- // only show admin controls if this form is being shown from within the Admin Users UI
- if (usersGroups.adminControls) {
- form.contents.verified = {
- kind: 'panel.input.switchbox',
- label: 'Verified',
- options: 'true|false',
- value: userVerified,
- // checked: !/false/i.test(userVerified)//,
- element: {
- // disabled: !!_load,
- checked: !/false/i.test(userVerified)//,
- // title: username + ':verified'//,
- // on: { click: _load ? setVerified : diddly }
- }
- };
- form.contents.enabled = {
- kind: 'panel.input.switchbox',
- label: 'Enabled',
- options: 'true|false',
- value: userEnabled,
- // checked: !/false/i.test(userEnabled)//,
- element: {
- //disabled: !!_load,
- checked: !/false/i.test(userEnabled)//,
- //title: username + ':enabled'//,
- //on: { click: _load ? setEnabled : diddly }
- }
- }
- }
- // add 'Advanced Settings' when editing existing user
- if (doEdit && usersGroups.showAdvanced) {
- form.contents.advancedSettings = {
- kind: 'panel.element',
- label: 'Advanced',
- contents: {
- advancedLink: {
- tag: 'a.edit-advanced-settings.link',
- element: {
- href: '#!',
- title: data.username + ':advanced',
- on: {
- click: function(e){
- e.preventDefault();
- var modalId = $(this).closest('div.xnat-dialog').attr('data-dialog');
- XNAT.dialog.getDialog(modalId).close();
- window.top.usernameForUserThatIsCurrentlyBeingEdited = data.username;
- userProjectsAndSecurity(e, data.username);
- }
- }
- },
- content: 'Edit Advanced Settings'
- },
- description: {
- tag: 'div.description',
- content: "Edit this user's project and security settings."
- }
- }
- }
- }
- // Add a submit button if this form is being displayed outside the Admin Users UI
- if (doEdit && !usersGroups.adminControls) {
- form.contents.submitButton = {
- kind: 'panel.element',
- contents: {
- submitUserFormButton: {
- kind: 'html',
- content: '<button class="btn primary" id="save-user-profile">Update Profile</button>'
- }
- }
- }
- }
- usersGroups.showAdvanced = true;
- return form;
- }
- usersGroups.userAccountForm = userAccountForm;
- // open a separate dialog to edit user password
- $(document).on('click','.change-password',function(){
- var username = $(this).data('username');
- usersGroups.changePasswordDialog({ username: username });
- });
- // external user profile form validation and submission
- $(document).on('click','#save-user-profile',function(){
- var $form = $(this).parents('form'), updated;
- if (XNAT.validate.form($form)){
- var doSave = saveUserData($form);
- doSave.done(function(){
- updated = true;
- });
- }
- });
- // open a dialog to edit user properties
- function editUser(e, onclose){
- e.preventDefault();
- var username =
- (this.title || '').split(':')[0] ||
- $(this).data('username') ||
- $(this).closest('tr').data('username') ||
- (this.innerText || '').trim();
- window.top.usernameForUserThatIsCurrentlyBeingEdited = username;
- getUserData(username).done(function(data){
- getUserRoles(username).done(function(roles){
- data.roles = roles;
- // save the data to namespaced object before opening dialog
- XNAT.data['/xapi/users/profile/' + username] = data;
- editUserDialog(data, onclose);
- })
- });
- }
- usersGroups.editUser = editUser;
- // immediately toggles user's "Verified" status
- function setVerified(e, username, flag){
- username = username || this.title.split(':')[0];
- flag = flag || this.checked;
- return XNAT.xhr.put({
- url: XNAT.url.rootUrl('/xapi/users/' + username + '/verified/' + flag),
- success: function(){
- XNAT.ui.banner.top(2000, 'User has been set to ' + (flag ? '"verified"' : '"unverified"') + '.', 'success')
- },
- error: function(){
- XNAT.ui.banner.top(3000, 'An error occurred setting "verified" status.', 'error')
- }
- })
- }
- usersGroups.setVerified = setVerified;
- // immediately toggles user's "Enabled" status
- function setEnabled(e, username, flag){
- username = username || this.title.split(':')[0];
- flag = flag || this.checked;
- return XNAT.xhr.put({
- url: XNAT.url.rootUrl('/xapi/users/' + username + '/enabled/' + flag),
- success: function(){
- XNAT.ui.banner.top(2000, 'User status has been set to ' + (flag ? '"enabled"' : '"disabled"') + '.', 'success')
- },
- error: function(){
- XNAT.ui.banner.top(3000, 'An error occurred setting "enabled" status.', 'error')
- }
- })
- }
- usersGroups.setEnabled = setEnabled;
- function userProjectsAndSecurity(e, usr){
- var _username = usr || $(this).data('username');
- var _url = XNAT.url.rootUrl('/app/action/DisplayItemAction/search_value/' + _username + '/search_element/xdat:user/search_field/xdat:user.login/popup/true');
- return xmodal.iframe({
- src: _url,
- name: 'advanced-user-settings',
- width: 800,
- height: '80%',
- title: 'Edit User Info',
- // footer: false,
- okLabel: 'Close',
- cancel: false,
- beforeShow: function(){
- XNAT.dialog.close(XNAT.dialog.topUID, true);
- },
- onClose: function(){
- var editedUser = window.top.usernameForUserThatIsCurrentlyBeingEdited;
- if (!window.top.XNAT.page.userAdminPage) {
- return false;
- }
- if (editedUser){
- usersGroups.userData(editedUser).getProfile().done(function(profileData){
- updateUserRow(profileData)
- });
- }
- else {
- updateUsersTable(true);
- }
- }
- })
- }
- // open a dialog for creating a new user
- function newUserDialog(){
- var updated = false;
- var formContainer$ = null;
- return XNAT.dialog.open({
- width: 600,
- // height: 500,
- speed: 200,
- title: 'Create New User',
- content: (function(){
- formContainer$ = $.spawn('div.new-user-form');
- renderUserAccountForm(null, formContainer$);
- return formContainer$[0];
- })(),
- buttons: [
- {
- label: 'Save',
- close: false,
- isDefault: true,
- action: function(obj){
- // userAccountForm
- var userForm$ = formContainer$.find('form');
- var _username = userForm$.find('input[name="username"]').val();
- // make sure new username is not a duplicate
- var getUserList = usersGroups.userData().usernames();
- getUserList.done(function(users){
- if (users.indexOf(_username) > -1) {
- XNAT.ui.dialog.alert('The username ' +
- '<b>' + _username + '</b> is already in use. ' +
- 'Please enter a different username value and ' +
- 'try again.');
- return false;
- }
- var doSave = saveUserData(userForm$);
- doSave.done(function(){
- updated = true;
- obj.close();
- });
- });
- }
- }
- ],
- onClose: function(){
- // always update the whole table when adding a user.
- // usersGroups.spawnTabs();
- // renderUsersTable();
- if (updated) {
- updateUsersTable(true);
- }
- }
- })
- }
- function setupTabs(){
- // console.log(setupTabs.name);
- function tabs(){
- return {
- kind: 'tabs',
- layout: 'top', // trying a top tabs layout
- contents: {
- usersTab: usersTab(),
- groupsTab: groupsTab()
- }
- }
- }
- function usersTab(){
- return {
- kind: 'tab',
- name: 'users',
- label: 'Users',
- active: true,
- contents: usersTabContents()
- }
- }
- function createUserButton(){
- return {
- tag: 'button#create-new-user',
- element: {
- html: 'Create New User',
- on: {
- click: function(e){
- // console.log('clicked');
- newUserDialog();
- }
- }
- }
- }
- }
- function reloadUserListButton(){
- return {
- tag: 'button#reload-user-list',
- element: {
- html: 'Reload User List',
- style: {
- marginLeft: '20px'
- },
- on: {
- click: function(e){
- // console.log('clicked');
- // updateUserData('profiles', 10);
- // var $container = $('#user-table-container');
- // $container.empty().html('loading...');
- // spawnUsersTable().render($container.empty());
- // usersGroups.spawnTabs();
- setTimeout(function(){
- XNAT.dialog.loadingBar.show();
- updateUsersTable(true);
- }, 1);
- }
- }
- }
- }
- }
- function loadAllUsersButton(){
- return {
- tag: 'button#load-all-users',
- element: {
- html: 'Load All Users',
- style: {
- marginLeft: '10px'
- },
- on: {
- click: function(e){
- setTimeout(function(){
- XNAT.dialog.loadingBar.show();
- renderUsersTable($(userTableContainer), '/xapi/users/profiles');
- }, 1);
- }
- }
- }
- }
- }
- function allUsersButtonInfoText(){
- return {
- tag: 'span.tip.shadowed',
- element: {
- style: {
- width: '350px',
- left: '-385px',
- top: '-75px',
- // backgroundColor: '#ffc',
- zIndex: 10000
- }
- },
- content: [
- 'By default, the table below only shows "current" users: users that are <b>enabled</b>, or who ' +
- 'may be <b>disabled</b> but have logged in during the past year, or have an unused account created less ' +
- 'than a year ago.' +
- '<br><br>' +
- 'Click the <b>"Load All Users"</b> button to view <i>all</i> users that have accounts on this system, ' +
- 'even if their account is not "current."'
- ],
- filler: null
- }
- }
- // var alternateInfoText = '' +
- //
- // 'By default, the table below only shows "current" users: users that are <b>enabled</b>, users that have ' +
- // 'logged in during the past year but are <b>disabled</b>, or users with accounts that were ' +
- // 'created created in the past year but never used.' +
- // '<br><br>' +
- // 'Click the <b>"Load All Users"</b> button to view <i>all</i> users that have accounts on this system, ' +
- // 'even if their account is not "current."' +
- //
- // '';
- function allUsersButtonInfo(){
- return {
- tag: 'span.tip_icon',
- element: {
- style: {
- marginRight: '3px',
- left: '2px',
- top: '3px'
- }
- },
- contents: {
- allUsersButtonInfoText: allUsersButtonInfoText()
- }
- }
- }
- function allUsersButtonElements(){
- return {
- tag: 'div',
- element: {
- style: {
- float: 'right'
- }
- },
- contents: {
- allUsersButtonInfo: allUsersButtonInfo(),
- loadAllUsersButton: loadAllUsersButton()
- }
- }
- }
- function selectAllUsers(){
- var $this = $(this);
- var $table = $this.closest('table');
- var $inputs = $table.find('input.select-user');
- if ($this.hasClass('selected')) {
- $inputs.prop('checked', false);
- $this.removeClass('selected');
- }
- else {
- $inputs.prop('checked', true);
- $this.addClass('selected');
- }
- }
- function usersTabContents(){
- return {
- tag: 'div.manage-users',
- contents: {
- style: {
- tag: 'style',
- content: '#user-profiles .new-user { background: #ffc }'
- },
- // actions: {
- // kind: 'panel',
- // label: 'Actions',
- // footer: false,
- // contents: {
- // viewActiveUsers: {
- // tag: 'button#view-active-users.btn1',
- // element: {
- // type: 'button',
- // html: 'View Active Users'
- // }
- // }//,
- // // things: {
- // // kind: 'html',
- // // content: '' +
- // // '<div class="active-users">' +
- // // '<button type="button" id="view-active-users" class="btn1">View Active Users</button>' +
- // // '</div>'//,
- // // element: spawn('div.active-users', {
- // // style: { marginBottom: '20px' }
- // // }, [['a#view-active-users|href=#!', 'View Active Users']])
- // // }
- // }
- // },
- userActions: {
- tag: 'div.user-actions',
- element: {
- style: {
- position: 'relative',
- marginBottom: '30px',
- paddingTop: '30px',
- borderTop: '1px solid #c8c8c8'
- }
- },
- contents: {
- createUserButton: createUserButton(),
- reloadUserListButton: reloadUserListButton(),
- allUsersButtonElements: allUsersButtonElements()
- }
- },
- usersTablePanel: {
- tag: 'div#user-accounts',
- contents: {
- tableContainer: {
- tag: userTableContainer,
- contents: {
- usersTable: spawnUsersTable()
- }
- }
- }
- }
- }
- }
- }
- // kill all active sessions for the specified user
- function killActiveSessions(e){
- e.preventDefault();
- var username = this.title.split(':')[0].trim();
- return XNAT.dialog.confirm({
- title: 'Kill Active Sessions?',
- content: 'Kill all active sessions for <b>' + username + '</b>?',
- okClose: false,
- okAction: function(obj){
- XNAT.xhr['delete']({
- url: XNAT.url.rootUrl('/xapi/users/active/' + username),
- success: function(){
- obj.close();
- XNAT.ui.banner.top(2000, 'Sessions closed', 'success');
- // wait a few seconds before updating the row
- updateUserData(username, 2000);
- // updateUsersTable(true);
- }
- })
- }
- });
- }
- // TODO: view active sessions
- function viewSessionInfo(e){
- e.preventDefault();
- var username = this.title;
- }
- …
Large files files are truncated, but you can click here to view the full file