mirror of https://github.com/apache/cloudstack.git
Support invitation-based project user management
This commit is contained in:
parent
b4a6dd512a
commit
bcd8f85d38
|
|
@ -8,7 +8,7 @@
|
|||
if (user.role == 'admin')
|
||||
return args.context.sections;
|
||||
|
||||
return ['dashboard', 'instances', 'storage', 'templates', 'events'];
|
||||
return ['dashboard', 'instances', 'storage', 'templates', 'events', 'projects'];
|
||||
},
|
||||
sections: {
|
||||
dashboard: {},
|
||||
|
|
@ -20,9 +20,9 @@
|
|||
domains: {},
|
||||
events: {},
|
||||
system: {},
|
||||
projects: {},
|
||||
'global-settings': {},
|
||||
configuration: {},
|
||||
projects: {}
|
||||
configuration: {}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
(function($, cloudStack, testData) {
|
||||
cloudStack.projects = {
|
||||
requireInvitation: function(args) {
|
||||
return cloudStack.context.users[0].username == 'jdoe';
|
||||
},
|
||||
|
||||
add: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success({
|
||||
|
|
@ -11,6 +15,54 @@
|
|||
});
|
||||
}, 1000);
|
||||
},
|
||||
inviteForm: {
|
||||
noSelect: true,
|
||||
fields: {
|
||||
'email': { edit: true, label: 'E-mail' },
|
||||
'add-user': { addButton: true, label: '' }
|
||||
},
|
||||
add: {
|
||||
label: 'Invite',
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success({
|
||||
data: args.data,
|
||||
notification: {
|
||||
label: 'Invited user to project',
|
||||
poll: testData.notifications.testPoll
|
||||
}
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
actionPreFilter: function(args) {
|
||||
if (cloudStack.context.projects &&
|
||||
cloudStack.context.projects[0] &&
|
||||
!cloudStack.context.projects[0].isNew) {
|
||||
return args.context.actions;
|
||||
}
|
||||
|
||||
return ['destroy'];
|
||||
},
|
||||
|
||||
actions: {},
|
||||
|
||||
// Project users data provider
|
||||
dataProvider: function(args) {
|
||||
var data = cloudStack.context.projects ?
|
||||
[
|
||||
{ email: 'brian.federle@citrix.com' },
|
||||
{ email: 'john.doe@aol.com' },
|
||||
{ email: 'some.user@gmail.com' }
|
||||
] : [];
|
||||
|
||||
setTimeout(function() {
|
||||
args.response.success({
|
||||
data: data
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
addUserForm: {
|
||||
noSelect: true,
|
||||
fields: {
|
||||
|
|
@ -18,7 +70,7 @@
|
|||
'add-user': { addButton: true, label: '' }
|
||||
},
|
||||
add: {
|
||||
label: 'Invite',
|
||||
label: 'Add user',
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success({
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
(function(cloudStack, testData) {
|
||||
cloudStack.projects = {
|
||||
requireInvitation: function(args) {
|
||||
return false;
|
||||
},
|
||||
|
||||
add: function(args) {
|
||||
setTimeout(function() {
|
||||
$.ajax({
|
||||
url: createURL('createProject'),
|
||||
url: createURL('createProject', { ignoreProject: true }),
|
||||
data: {
|
||||
account: args.context.users[0].account,
|
||||
domainId: args.context.users[0].domainid,
|
||||
|
|
@ -25,6 +29,73 @@
|
|||
});
|
||||
}, 100);
|
||||
},
|
||||
inviteForm: {
|
||||
noSelect: true,
|
||||
fields: {
|
||||
'email': { edit: true, label: 'E-mail' },
|
||||
'add-user': { addButton: true, label: '' }
|
||||
},
|
||||
add: {
|
||||
label: 'Invite',
|
||||
action: function(args) {
|
||||
$.ajax({
|
||||
url: createURL('addAccountToProject', { ignoreProject: true }),
|
||||
data: {
|
||||
projectId: args.context.projects[0].id,
|
||||
email: args.data.email
|
||||
},
|
||||
dataType: 'json',
|
||||
async: true,
|
||||
success: function(data) {
|
||||
data: args.data,
|
||||
args.response.success({
|
||||
_custom: {
|
||||
jobId: data.addaccounttoprojectresponse.jobid
|
||||
},
|
||||
notification: {
|
||||
label: 'Invited user to project',
|
||||
poll: pollAsyncJobResult
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
actionPreFilter: function(args) {
|
||||
if (cloudStack.context.projects &&
|
||||
cloudStack.context.projects[0] &&
|
||||
!cloudStack.context.projects[0].isNew) {
|
||||
return args.context.actions;
|
||||
}
|
||||
|
||||
return ['destroy'];
|
||||
},
|
||||
|
||||
actions: {},
|
||||
|
||||
// Project users data provider
|
||||
dataProvider: function(args) {
|
||||
$.ajax({
|
||||
url: createURL('listProjectInvitations', { ignoreProject: true }),
|
||||
data: {
|
||||
projectId: args.context.projects[0].id
|
||||
},
|
||||
dataType: 'json',
|
||||
async: true,
|
||||
success: function(data) {
|
||||
var invites = data.listprojectinvitationsresponse.projectinvitation;
|
||||
args.response.success({
|
||||
data: $.map(invites, function(elem) {
|
||||
return {
|
||||
id: elem.id,
|
||||
email: elem.email ? elem.email : elem.account
|
||||
};
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
addUserForm: {
|
||||
noSelect: true,
|
||||
fields: {
|
||||
|
|
@ -32,10 +103,10 @@
|
|||
'add-user': { addButton: true, label: '' }
|
||||
},
|
||||
add: {
|
||||
label: 'Invite',
|
||||
label: 'Add user',
|
||||
action: function(args) {
|
||||
$.ajax({
|
||||
url: createURL('addAccountToProject'),
|
||||
url: createURL('addAccountToProject', { ignoreProject: true }),
|
||||
data: {
|
||||
projectId: args.context.projects[0].id,
|
||||
account: args.data.username
|
||||
|
|
@ -79,7 +150,7 @@
|
|||
label: 'Remove user from project',
|
||||
action: function(args) {
|
||||
$.ajax({
|
||||
url: createURL('deleteAccountFromProject'),
|
||||
url: createURL('deleteAccountFromProject', { ignoreProject: true }),
|
||||
data: {
|
||||
projectId: args.context.projects[0].id,
|
||||
account: args.context.multiRule[0].username
|
||||
|
|
@ -105,7 +176,7 @@
|
|||
label: 'Make user project owner',
|
||||
action: function(args) {
|
||||
$.ajax({
|
||||
url: createURL('updateProject'),
|
||||
url: createURL('updateProject', { ignoreProject: true }),
|
||||
data: {
|
||||
id: cloudStack.context.projects[0].id,
|
||||
account: args.context.multiRule[0].username
|
||||
|
|
@ -131,7 +202,7 @@
|
|||
// Project users data provider
|
||||
dataProvider: function(args) {
|
||||
$.ajax({
|
||||
url: createURL('listProjectAccounts'),
|
||||
url: createURL('listProjectAccounts', { ignoreProject: true }),
|
||||
data: {
|
||||
projectId: args.context.projects[0].id
|
||||
},
|
||||
|
|
@ -157,7 +228,7 @@
|
|||
var user = args.context.users[0];
|
||||
|
||||
$.ajax({
|
||||
url: createURL('listProjects'),
|
||||
url: createURL('listProjects', { ignoreProject: true }),
|
||||
data: {
|
||||
accountId: user.userid
|
||||
},
|
||||
|
|
@ -192,7 +263,7 @@
|
|||
|
||||
dataProvider: function(args) {
|
||||
$.ajax({
|
||||
url: createURL('listProjects'),
|
||||
url: createURL('listProjects', { ignoreProject: true }),
|
||||
dataType: 'json',
|
||||
async: true,
|
||||
success: function(data) {
|
||||
|
|
@ -230,7 +301,7 @@
|
|||
label: 'Remove project',
|
||||
action: function(args) {
|
||||
$.ajax({
|
||||
url: createURL('deleteProject'),
|
||||
url: createURL('deleteProject', { ignoreProject: true }),
|
||||
data: {
|
||||
id: args.data.id
|
||||
},
|
||||
|
|
|
|||
|
|
@ -62,10 +62,11 @@ var pollAsyncJobResult = function(args) {
|
|||
}
|
||||
|
||||
//API calls
|
||||
function createURL(apiName) {
|
||||
function createURL(apiName, options) {
|
||||
if (!options) options = {};
|
||||
var urlString = clientApiUrl + "?" + "command=" + apiName +"&response=json&sessionkey=" + g_sessionKey;
|
||||
|
||||
if (cloudStack.context && cloudStack.context.projects) {
|
||||
if (cloudStack.context && cloudStack.context.projects && !options.ignoreProject) {
|
||||
urlString = urlString + '&projectid=' + cloudStack.context.projects[0].id;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@
|
|||
* User management multi-edit
|
||||
*/
|
||||
userManagement: function(args) {
|
||||
var multiEdit = cloudStack.projects.addUserForm;
|
||||
var multiEdit = !args.useInvites ?
|
||||
cloudStack.projects.addUserForm :
|
||||
cloudStack.projects.inviteForm;
|
||||
|
||||
return $('<div>').multiEdit($.extend(true, {}, multiEdit, {
|
||||
context: args.context
|
||||
|
|
@ -22,9 +24,13 @@
|
|||
};
|
||||
|
||||
if (cloudStack.context.projects) {
|
||||
tabs['Manage'] = function() {
|
||||
tabs['Users'] = function() {
|
||||
return $('<div>').addClass('management');
|
||||
};
|
||||
|
||||
tabs['Invitations'] = function() {
|
||||
return $('<div>').addClass('management-invite');
|
||||
};
|
||||
}
|
||||
|
||||
var $tabs = $('<div>').addClass('tab-content').append($('<ul>'));
|
||||
|
|
@ -49,13 +55,26 @@
|
|||
$tabs.bind('tabsshow', function(event, ui) {
|
||||
var $panel = $(ui.panel);
|
||||
var $management = $panel.find('.management');
|
||||
var $managementInvite = $panel.find('.management-invite');
|
||||
|
||||
if ($management.size()) {
|
||||
$management.children().remove();
|
||||
$management.append(pageElems.userManagement({
|
||||
context: cloudStack.context
|
||||
}));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($managementInvite.size()) {
|
||||
$managementInvite.children().remove();
|
||||
$managementInvite.append(pageElems.userManagement({
|
||||
context: cloudStack.context,
|
||||
useInvites: true
|
||||
}));
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
return $('<div>').addClass('project-dashboard')
|
||||
|
|
@ -136,7 +155,8 @@
|
|||
var $userManagement = pageElems.userManagement({
|
||||
context: $.extend(true, {}, cloudStack.context, {
|
||||
projects: [project]
|
||||
})
|
||||
}),
|
||||
useInvites: cloudStack.projects.requireInvitation()
|
||||
});
|
||||
var $nextButton = $('<div>').addClass('button confirm next').html('Next');
|
||||
|
||||
|
|
@ -185,11 +205,12 @@
|
|||
listView: {
|
||||
id: 'project-accounts',
|
||||
disableInfiniteScrolling: true,
|
||||
|
||||
fields: {
|
||||
fields: !cloudStack.projects.requireInvitation() ? {
|
||||
username: { label: 'Account' }
|
||||
} : {
|
||||
email: { label: 'E-mail invite'}
|
||||
},
|
||||
actions: {
|
||||
actions: !cloudStack.projects.requireInvitation() ? {
|
||||
destroy: {
|
||||
label: 'Remove account from project',
|
||||
action: {
|
||||
|
|
@ -214,14 +235,16 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
} : {},
|
||||
dataProvider: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success({
|
||||
data: $.map($userManagement.find('.data-item tr'), function(elem) {
|
||||
// Store previous user data in list table
|
||||
return {
|
||||
return !cloudStack.projects.requireInvitation() ? {
|
||||
username: $(elem).find('td.username span').html()
|
||||
} : {
|
||||
email: $(elem).find('td.email span').html()
|
||||
};
|
||||
})
|
||||
});
|
||||
|
|
@ -351,16 +374,19 @@
|
|||
// Initial load
|
||||
loadData(function() {
|
||||
if (!$list.find('li').size()) {
|
||||
showDashboard();
|
||||
cloudStack.dialog.notice({
|
||||
message: 'You do not have any projects. '
|
||||
+ 'Please create a new project from the projects section.'
|
||||
}).closest('.ui-dialog');
|
||||
$.merge($selector, $('.overlay')).remove();
|
||||
|
||||
return;
|
||||
$('.select.default-view').click();
|
||||
} else {
|
||||
$selector.dialog({
|
||||
title: 'Select Project',
|
||||
dialogClass: 'project-selector-dialog',
|
||||
width: 420
|
||||
}).closest('.ui-dialog').overlay();
|
||||
showDashboard();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -444,7 +470,6 @@
|
|||
return true;
|
||||
}
|
||||
|
||||
showDashboard();
|
||||
$(this).addClass('active');
|
||||
$(this).siblings().removeClass('active');
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue