mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-27 10:50:10 +03:00
Merge branch 'feature-3541'
This commit is contained in:
commit
aff2965106
@ -75,6 +75,26 @@ public:
|
||||
return del_collection_id(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a User to the admin set. ACL Rules are updated only for this user.
|
||||
*
|
||||
* @param user_id ID of the user
|
||||
* @param error_msg Returns the error reason, if any
|
||||
*
|
||||
* @return 0 on success
|
||||
*/
|
||||
int add_admin(int user_id, string& error_msg);
|
||||
|
||||
/**
|
||||
* Deletes a User from the admin set. ACL Rules are updated only for this user.
|
||||
*
|
||||
* @param user_id ID of the user
|
||||
* @param error_msg Returns the error reason, if any
|
||||
*
|
||||
* @return 0 on success
|
||||
*/
|
||||
int del_admin(int user_id, string& error_msg);
|
||||
|
||||
/**
|
||||
* Object quotas, provides set and check interface
|
||||
*/
|
||||
@ -113,7 +133,8 @@ private:
|
||||
Group(int id, const string& name):
|
||||
PoolObjectSQL(id,GROUP,name,-1,-1,"","",table),
|
||||
ObjectCollection("USERS"),
|
||||
quota()
|
||||
quota(),
|
||||
admins("ADMINS")
|
||||
{
|
||||
// Allow users in this group to see it
|
||||
group_u = 1;
|
||||
@ -126,6 +147,18 @@ private:
|
||||
delete obj_template;
|
||||
};
|
||||
|
||||
// *************************************************************************
|
||||
// Administrators
|
||||
// *************************************************************************
|
||||
|
||||
/**
|
||||
* Stores a collection with the admin users
|
||||
*/
|
||||
ObjectCollection admins;
|
||||
|
||||
void add_admin_rules(int user_id);
|
||||
void del_admin_rules(int user_id);
|
||||
|
||||
// *************************************************************************
|
||||
// DataBase implementation (Private)
|
||||
// *************************************************************************
|
||||
|
@ -85,6 +85,16 @@ public:
|
||||
return set<int> (collection_set);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the collection contains the given id
|
||||
* @param id ID to search
|
||||
* @return true if the collection contains the given id
|
||||
*/
|
||||
bool collection_contains(int id)
|
||||
{
|
||||
return collection_set.count(id) > 0;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
|
@ -66,6 +66,66 @@ public:
|
||||
RequestAttributes& att);
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
class GroupEditAdmin : public Request
|
||||
{
|
||||
public:
|
||||
void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att);
|
||||
|
||||
protected:
|
||||
GroupEditAdmin( const string& method_name,
|
||||
const string& help,
|
||||
const string& params)
|
||||
:Request(method_name,params,help)
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
pool = nd.get_gpool();
|
||||
upool = nd.get_upool();
|
||||
|
||||
auth_object = PoolObjectSQL::GROUP;
|
||||
auth_op = AuthRequest::ADMIN;
|
||||
};
|
||||
|
||||
UserPool* upool;
|
||||
|
||||
virtual int edit_admin(Group* group, int user_id, string& error_msg) = 0;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
class GroupAddAdmin : public GroupEditAdmin
|
||||
{
|
||||
public:
|
||||
GroupAddAdmin():
|
||||
GroupEditAdmin( "GroupAddAdmin",
|
||||
"Adds a user to the group admin set",
|
||||
"A:sii"){};
|
||||
|
||||
~GroupAddAdmin(){};
|
||||
|
||||
int edit_admin(Group* group, int user_id, string& error_msg);
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
class GroupDelAdmin : public GroupEditAdmin
|
||||
{
|
||||
public:
|
||||
GroupDelAdmin():
|
||||
GroupEditAdmin( "GroupDelAdmin",
|
||||
"Removes a user from the group admin set",
|
||||
"A:sii"){};
|
||||
|
||||
~GroupDelAdmin(){};
|
||||
|
||||
int edit_admin(Group* group, int user_id, string& error_msg);
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
|
@ -14,6 +14,13 @@
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="ADMINS">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="ID" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="DATASTORE_QUOTA" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
|
@ -18,6 +18,13 @@
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="ADMINS">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="ID" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
@ -169,15 +169,6 @@ EOT
|
||||
"Which resources can be created by group users "<<
|
||||
"(VM+NET+IMAGE+TEMPLATE by default)",
|
||||
:format => String
|
||||
},
|
||||
{
|
||||
:name => 'admin_resources',
|
||||
:large => '--admin_resources res_str',
|
||||
:short => "-o",
|
||||
:description =>
|
||||
"Which resources can be created by the admin user "<<
|
||||
"(VM+NET+IMAGE+TEMPLATE by default)",
|
||||
:format => String
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -286,11 +286,21 @@ class OneGroupHelper < OpenNebulaHelper::OneHelper
|
||||
puts group.template_str
|
||||
puts
|
||||
|
||||
CLIHelper.print_header(str_h1 % "USERS", false)
|
||||
CLIHelper.print_header("%-15s" % ["ID"])
|
||||
group.user_ids.each do |uid|
|
||||
puts "%-15s" % [uid]
|
||||
end
|
||||
admin_ids = group.admin_ids
|
||||
|
||||
CLIHelper::ShowTable.new(nil, self) do
|
||||
column :"USER ID", "", :right, :size=>7 do |d|
|
||||
d
|
||||
end
|
||||
|
||||
column :"ADMIN", "", :left, :size=>5 do |d|
|
||||
if (group.admin_ids.include?(d))
|
||||
"*"
|
||||
else
|
||||
""
|
||||
end
|
||||
end
|
||||
end.show(group.user_ids, {})
|
||||
|
||||
group_hash = group.to_hash
|
||||
|
||||
|
@ -61,24 +61,26 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
helper.list_to_id(arg)
|
||||
end
|
||||
|
||||
set :format, :userid, OpenNebulaHelper.rname_to_id_desc("USER") do |arg|
|
||||
OpenNebulaHelper.rname_to_id(arg, "USER")
|
||||
end
|
||||
|
||||
########################################################################
|
||||
# Commands
|
||||
########################################################################
|
||||
|
||||
create_desc = <<-EOT.unindent
|
||||
Creates a new Group. A group name can be passed as the only argument,
|
||||
or a file containing a group template or via command line arguments
|
||||
or via command line arguments
|
||||
|
||||
Examples:
|
||||
|
||||
- create a group with admin user and allow group users
|
||||
to only create new templates and VMs, and group admin to manage
|
||||
templates, vms, images and virtual networks
|
||||
- create a group with an admin user and allow group users
|
||||
to only create new templates and VMs
|
||||
|
||||
onegroup create --name groupA
|
||||
--admin_user admin_userA --admin_password somestr
|
||||
--resources TEMPLATE+VM
|
||||
--admin_resources TEMPLATE+VM+IMAGE+NET
|
||||
|
||||
EOT
|
||||
|
||||
@ -87,7 +89,8 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
|
||||
|
||||
if !args[0] && options.empty?
|
||||
STDERR.puts "Please use either a group name or command arguments"
|
||||
STDERR.puts "Please use either a group name or command arguments."<<
|
||||
" Run onegroup create -h for more information"
|
||||
next -1
|
||||
end
|
||||
|
||||
@ -101,7 +104,6 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
admin_user[:name] = options[:admin_user]
|
||||
admin_user[:password] = options[:admin_password]
|
||||
admin_user[:auth_driver]= options[:admin_driver] if options[:admin_driver]
|
||||
admin_user[:resources] = options[:admin_resources] if options[:admin_resources]
|
||||
|
||||
options[:group_admin] = admin_user
|
||||
end
|
||||
@ -159,6 +161,26 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
helper.show_resource(group,options)
|
||||
end
|
||||
|
||||
add_admin_desc = <<-EOT.unindent
|
||||
Adds a User to the Group administrators set
|
||||
EOT
|
||||
|
||||
command :addadmin, add_admin_desc, [:range, :groupid_list], :userid do
|
||||
helper.perform_actions(args[0],options,"admin added") do |obj|
|
||||
obj.add_admin(args[1].to_i)
|
||||
end
|
||||
end
|
||||
|
||||
del_admin_desc = <<-EOT.unindent
|
||||
Removes a User from the Group administrators set
|
||||
EOT
|
||||
|
||||
command :deladmin, del_admin_desc, [:range, :groupid_list], :userid do
|
||||
helper.perform_actions(args[0],options,"admin deleted") do |obj|
|
||||
obj.del_admin(args[1].to_i)
|
||||
end
|
||||
end
|
||||
|
||||
quota_desc = <<-EOT.unindent
|
||||
Set the quota limits for the group. If a path is not provided the
|
||||
editor will be launched to modify the current quotas.
|
||||
|
@ -214,6 +214,7 @@ string& Group::to_xml_extended(string& xml, bool extended) const
|
||||
{
|
||||
ostringstream oss;
|
||||
string collection_xml;
|
||||
string admins_xml;
|
||||
string template_xml;
|
||||
|
||||
ObjectCollection::to_xml(collection_xml);
|
||||
@ -223,7 +224,8 @@ string& Group::to_xml_extended(string& xml, bool extended) const
|
||||
"<ID>" << oid << "</ID>" <<
|
||||
"<NAME>" << name << "</NAME>" <<
|
||||
obj_template->to_xml(template_xml) <<
|
||||
collection_xml;
|
||||
collection_xml <<
|
||||
admins.to_xml(admins_xml);
|
||||
|
||||
if (extended)
|
||||
{
|
||||
@ -276,6 +278,19 @@ int Group::from_xml(const string& xml)
|
||||
ObjectXML::free_nodes(content);
|
||||
content.clear();
|
||||
|
||||
// Set of Admin IDs
|
||||
ObjectXML::get_nodes("/GROUP/ADMINS", content);
|
||||
|
||||
if (content.empty())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc += admins.from_xml_node(content[0]);
|
||||
|
||||
ObjectXML::free_nodes(content);
|
||||
content.clear();
|
||||
|
||||
// Get associated metadata for the group
|
||||
ObjectXML::get_nodes("/GROUP/TEMPLATE", content);
|
||||
|
||||
@ -296,3 +311,181 @@ int Group::from_xml(const string& xml)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
int Group::add_admin(int user_id, string& error_msg)
|
||||
{
|
||||
int rc;
|
||||
ostringstream oss;
|
||||
|
||||
if ( collection_contains(user_id) == false )
|
||||
{
|
||||
oss << "User " << user_id << " is not part of Group "
|
||||
<< oid << ".";
|
||||
|
||||
error_msg = oss.str();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = admins.add_collection_id(user_id);
|
||||
|
||||
if (rc == -1)
|
||||
{
|
||||
oss << "User " << user_id << " is already an administrator of Group "
|
||||
<< oid << ".";
|
||||
|
||||
error_msg = oss.str();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
add_admin_rules(user_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
void Group::add_admin_rules(int user_id)
|
||||
{
|
||||
int rc;
|
||||
string error_msg;
|
||||
|
||||
AclManager* aclm = Nebula::instance().get_aclm();
|
||||
|
||||
// #<uid> USER/@<gid> USE+MANAGE+ADMIN+CREATE *
|
||||
rc = aclm->add_rule(
|
||||
AclRule::INDIVIDUAL_ID |
|
||||
user_id,
|
||||
|
||||
PoolObjectSQL::USER |
|
||||
AclRule::GROUP_ID |
|
||||
oid,
|
||||
|
||||
AuthRequest::USE |
|
||||
AuthRequest::MANAGE |
|
||||
AuthRequest::ADMIN |
|
||||
AuthRequest::CREATE,
|
||||
|
||||
AclRule::ALL_ID,
|
||||
|
||||
error_msg);
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
NebulaLog::log("GROUP",Log::ERROR,error_msg);
|
||||
}
|
||||
|
||||
// #<uid> VM+NET+IMAGE+TEMPLATE+DOCUMENT+SECGROUP/@<gid> USE+MANAGE *
|
||||
rc = aclm->add_rule(
|
||||
AclRule::INDIVIDUAL_ID |
|
||||
user_id,
|
||||
|
||||
PoolObjectSQL::VM |
|
||||
PoolObjectSQL::NET |
|
||||
PoolObjectSQL::IMAGE |
|
||||
PoolObjectSQL::TEMPLATE |
|
||||
PoolObjectSQL::DOCUMENT |
|
||||
PoolObjectSQL::SECGROUP |
|
||||
AclRule::GROUP_ID |
|
||||
oid,
|
||||
|
||||
AuthRequest::USE |
|
||||
AuthRequest::MANAGE,
|
||||
|
||||
AclRule::ALL_ID,
|
||||
|
||||
error_msg);
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
NebulaLog::log("GROUP",Log::ERROR,error_msg);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
int Group::del_admin(int user_id, string& error_msg)
|
||||
{
|
||||
int rc = admins.del_collection_id(user_id);
|
||||
|
||||
if (rc == -1)
|
||||
{
|
||||
ostringstream oss;
|
||||
oss << "User " << user_id << " is not an administrator of Group "
|
||||
<< oid << ".";
|
||||
|
||||
error_msg = oss.str();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
del_admin_rules(user_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
void Group::del_admin_rules(int user_id)
|
||||
{
|
||||
int rc;
|
||||
string error_msg;
|
||||
|
||||
AclManager* aclm = Nebula::instance().get_aclm();
|
||||
|
||||
// #<uid> USER/@<gid> USE+MANAGE+ADMIN+CREATE *
|
||||
rc = aclm->del_rule(
|
||||
AclRule::INDIVIDUAL_ID |
|
||||
user_id,
|
||||
|
||||
PoolObjectSQL::USER |
|
||||
AclRule::GROUP_ID |
|
||||
oid,
|
||||
|
||||
AuthRequest::USE |
|
||||
AuthRequest::MANAGE |
|
||||
AuthRequest::ADMIN |
|
||||
AuthRequest::CREATE,
|
||||
|
||||
AclRule::ALL_ID,
|
||||
|
||||
error_msg);
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
NebulaLog::log("GROUP",Log::ERROR,error_msg);
|
||||
}
|
||||
|
||||
// #<uid> VM+NET+IMAGE+TEMPLATE+DOCUMENT+SECGROUP/@<gid> USE+MANAGE *
|
||||
rc = aclm->del_rule(
|
||||
AclRule::INDIVIDUAL_ID |
|
||||
user_id,
|
||||
|
||||
PoolObjectSQL::VM |
|
||||
PoolObjectSQL::NET |
|
||||
PoolObjectSQL::IMAGE |
|
||||
PoolObjectSQL::TEMPLATE |
|
||||
PoolObjectSQL::DOCUMENT |
|
||||
PoolObjectSQL::SECGROUP |
|
||||
AclRule::GROUP_ID |
|
||||
oid,
|
||||
|
||||
AuthRequest::USE |
|
||||
AuthRequest::MANAGE,
|
||||
|
||||
AclRule::ALL_ID,
|
||||
|
||||
error_msg);
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
NebulaLog::log("GROUP",Log::ERROR,error_msg);
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,8 @@ public class Group extends PoolElement{
|
||||
private static final String DELETE = METHOD_PREFIX + "delete";
|
||||
private static final String QUOTA = METHOD_PREFIX + "quota";
|
||||
private static final String UPDATE = METHOD_PREFIX + "update";
|
||||
private static final String ADD_ADMIN = METHOD_PREFIX + "addadmin";
|
||||
private static final String DEL_ADMIN = METHOD_PREFIX + "deladmin";
|
||||
|
||||
/**
|
||||
* Creates a new Group representation.
|
||||
@ -124,6 +126,32 @@ public class Group extends PoolElement{
|
||||
return client.call(UPDATE, id, new_template, append ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a User to the Group administrators set
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param id The group id of the target group we want to modify.
|
||||
* @param uid User ID
|
||||
* @return If successful the message contains the group id.
|
||||
*/
|
||||
public static OneResponse addAdmin(Client client, int id, int uid)
|
||||
{
|
||||
return client.call(ADD_ADMIN, id, uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a User from the Group administrators set
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param id The group id of the target group we want to modify.
|
||||
* @param uid User ID
|
||||
* @return If successful the message contains the group id.
|
||||
*/
|
||||
public static OneResponse delAdmin(Client client, int id, int uid)
|
||||
{
|
||||
return client.call(DEL_ADMIN, id, uid);
|
||||
}
|
||||
|
||||
// =================================
|
||||
// Instanced object XML-RPC methods
|
||||
// =================================
|
||||
@ -185,6 +213,28 @@ public class Group extends PoolElement{
|
||||
return update(client, id, new_template, append);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a User to the Group administrators set
|
||||
*
|
||||
* @param uid User ID
|
||||
* @return If successful the message contains the group id.
|
||||
*/
|
||||
public OneResponse addAdmin(int uid)
|
||||
{
|
||||
return addAdmin(client, id, uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a User from the Group administrators set
|
||||
*
|
||||
* @param uid User ID
|
||||
* @return If successful the message contains the group id.
|
||||
*/
|
||||
public OneResponse delAdmin(int uid)
|
||||
{
|
||||
return delAdmin(client, id, uid);
|
||||
}
|
||||
|
||||
// =================================
|
||||
// Helpers
|
||||
// =================================
|
||||
@ -200,4 +250,16 @@ public class Group extends PoolElement{
|
||||
String res = xpath("USERS/ID[.="+uid+"]");
|
||||
return res != null && res.equals(""+uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the user is an admin of this group
|
||||
*
|
||||
* @param uid The user ID.
|
||||
* @return Whether or not the user is an admin of this group
|
||||
*/
|
||||
public boolean containsAdmin(int uid)
|
||||
{
|
||||
String res = xpath("ADMINS/ID[.="+uid+"]");
|
||||
return res != null && res.equals(""+uid);
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
@ -29,13 +29,16 @@ import org.opennebula.client.OneResponse;
|
||||
import org.opennebula.client.OneSystem;
|
||||
import org.opennebula.client.group.Group;
|
||||
import org.opennebula.client.group.GroupPool;
|
||||
import org.opennebula.client.user.*;
|
||||
import org.w3c.dom.Node;
|
||||
import java.util.Hashtable;
|
||||
|
||||
public class GroupTest
|
||||
{
|
||||
|
||||
private static Group group;
|
||||
private static GroupPool groupPool;
|
||||
private static User user;
|
||||
|
||||
private static Client client;
|
||||
|
||||
@ -69,8 +72,17 @@ public class GroupTest
|
||||
{
|
||||
res = Group.allocate(client, group_name);
|
||||
|
||||
assertTrue( res.getErrorMessage(), !res.isError() );
|
||||
|
||||
int group_id = res.isError() ? -1 : Integer.parseInt(res.getMessage());
|
||||
group = new Group(group_id, client);
|
||||
|
||||
res = User.allocate(client, "new_test_user", "new_test_password");
|
||||
|
||||
assertTrue( res.getErrorMessage(), !res.isError() );
|
||||
|
||||
int uid = Integer.parseInt(res.getMessage());
|
||||
user = new User(uid, client);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,6 +91,7 @@ public class GroupTest
|
||||
@After
|
||||
public void tearDown() throws Exception
|
||||
{
|
||||
user.delete();
|
||||
group.delete();
|
||||
}
|
||||
|
||||
@ -160,8 +173,68 @@ public class GroupTest
|
||||
}
|
||||
}
|
||||
|
||||
// Commented out, secondary groups do not exist any more
|
||||
/*
|
||||
@Test
|
||||
public void addAdmin()
|
||||
{
|
||||
res = group.info();
|
||||
assertTrue( res.getErrorMessage(), !res.isError() );
|
||||
|
||||
assertFalse( group.contains(user.id()) );
|
||||
assertFalse( group.containsAdmin(user.id()) );
|
||||
|
||||
res = group.addAdmin( user.id() );
|
||||
assertTrue( res.isError() );
|
||||
|
||||
group.info();
|
||||
assertFalse( group.contains(user.id()) );
|
||||
assertFalse( group.containsAdmin(user.id()) );
|
||||
|
||||
res = user.chgrp( group.id() );
|
||||
assertTrue( res.getErrorMessage(), !res.isError() );
|
||||
|
||||
group.info();
|
||||
assertTrue( group.contains(user.id()) );
|
||||
assertFalse( group.containsAdmin(user.id()) );
|
||||
|
||||
res = group.addAdmin( user.id() );
|
||||
assertTrue( res.getErrorMessage(), !res.isError() );
|
||||
|
||||
group.info();
|
||||
assertTrue( group.contains(user.id()) );
|
||||
assertTrue( group.containsAdmin(user.id()) );
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void delAdmin()
|
||||
{
|
||||
res = group.info();
|
||||
assertTrue( res.getErrorMessage(), !res.isError() );
|
||||
|
||||
res = group.delAdmin( user.id() );
|
||||
assertTrue( res.isError() );
|
||||
|
||||
res = user.chgrp( group.id() );
|
||||
assertTrue( res.getErrorMessage(), !res.isError() );
|
||||
|
||||
res = group.delAdmin( user.id() );
|
||||
assertTrue( res.isError() );
|
||||
|
||||
res = group.addAdmin( user.id() );
|
||||
assertTrue( res.getErrorMessage(), !res.isError() );
|
||||
|
||||
group.info();
|
||||
assertTrue( group.contains(user.id()) );
|
||||
assertTrue( group.containsAdmin(user.id()) );
|
||||
|
||||
res = group.delAdmin( user.id() );
|
||||
assertTrue( res.getErrorMessage(), !res.isError() );
|
||||
|
||||
group.info();
|
||||
assertTrue( group.contains(user.id()) );
|
||||
assertFalse( group.containsAdmin(user.id()) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void userGroupRelations()
|
||||
{
|
||||
@ -211,26 +284,6 @@ public class GroupTest
|
||||
assertTrue( !g.info().isError() );
|
||||
}
|
||||
|
||||
assertTrue( users.get("a").isPartOf( groups.get("a").id() ) );
|
||||
assertTrue( users.get("a").isPartOf( groups.get("b").id() ) );
|
||||
assertFalse( users.get("a").isPartOf( groups.get("c").id() ) );
|
||||
assertFalse( users.get("a").isPartOf( groups.get("d").id() ) );
|
||||
|
||||
assertFalse( users.get("b").isPartOf( groups.get("a").id() ) );
|
||||
assertTrue( users.get("b").isPartOf( groups.get("b").id() ) );
|
||||
assertFalse( users.get("b").isPartOf( groups.get("c").id() ) );
|
||||
assertFalse( users.get("b").isPartOf( groups.get("d").id() ) );
|
||||
|
||||
assertFalse( users.get("c").isPartOf( groups.get("a").id() ) );
|
||||
assertTrue( users.get("c").isPartOf( groups.get("b").id() ) );
|
||||
assertTrue( users.get("c").isPartOf( groups.get("c").id() ) );
|
||||
assertTrue( users.get("c").isPartOf( groups.get("d").id() ) );
|
||||
|
||||
assertFalse( users.get("d").isPartOf( groups.get("a").id() ) );
|
||||
assertTrue( users.get("d").isPartOf( groups.get("b").id() ) );
|
||||
assertTrue( users.get("d").isPartOf( groups.get("c").id() ) );
|
||||
assertTrue( users.get("d").isPartOf( groups.get("d").id() ) );
|
||||
|
||||
assertTrue( groups.get("a").contains( users.get("a").id() ) );
|
||||
assertFalse( groups.get("a").contains( users.get("b").id() ) );
|
||||
assertFalse( groups.get("a").contains( users.get("c").id() ) );
|
||||
@ -250,5 +303,4 @@ public class GroupTest
|
||||
assertTrue( groups.get("d").contains( users.get("c").id() ) );
|
||||
assertTrue( groups.get("d").contains( users.get("d").id() ) );
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
@ -28,7 +28,9 @@ module OpenNebula
|
||||
:allocate => "group.allocate",
|
||||
:update => "group.update",
|
||||
:delete => "group.delete",
|
||||
:quota => "group.quota"
|
||||
:quota => "group.quota",
|
||||
:add_admin => "group.addadmin",
|
||||
:del_admin => "group.deladmin",
|
||||
}
|
||||
|
||||
# Flag for requesting connected user's group info
|
||||
@ -83,6 +85,10 @@ module OpenNebula
|
||||
# in SUNSTONE_VIEWS
|
||||
# group_hash[:default_view] Default sunstone view name, to be stored
|
||||
# in DEFAULT_VIEW
|
||||
# group_hash[:admin_views] Array of sunstone view names, to be stored
|
||||
# in GROUP_ADMIN_VIEWS
|
||||
# group_hash[:default_admin_view] Default sunstone view name, to be stored
|
||||
# in DEFAULT_ADMIN_DEFAULT_VIEW
|
||||
#
|
||||
def create(group_hash)
|
||||
# Check arguments
|
||||
@ -134,24 +140,31 @@ module OpenNebula
|
||||
end
|
||||
|
||||
str = ""
|
||||
update = false
|
||||
|
||||
# Add Sunstone views for the group
|
||||
if group_hash[:views]
|
||||
str += "SUNSTONE_VIEWS=\"#{group_hash[:views].join(",")}\"\n"
|
||||
update = true
|
||||
end
|
||||
|
||||
# Add Sunstone views for the group
|
||||
if group_hash[:default_view]
|
||||
str += "DEFAULT_VIEW=\"#{group_hash[:default_view]}\"\n"
|
||||
update = true
|
||||
end
|
||||
|
||||
if update
|
||||
self.update(str, true)
|
||||
# And the admin views
|
||||
if group_hash[:admin_views]
|
||||
str += "GROUP_ADMIN_VIEWS=\"#{group_hash[:admin_views].join(",")}\"\n"
|
||||
else
|
||||
str += "GROUP_ADMIN_VIEWS=#{GROUP_ADMIN_SUNSTONE_VIEWS}\n"
|
||||
end
|
||||
|
||||
if group_hash[:default_admin_view]
|
||||
str += "GROUP_ADMIN_DEFAULT_VIEW=\"#{group_hash[:default_admin_view]}\"\n"
|
||||
else
|
||||
str += "GROUP_ADMIN_DEFAULT_VIEW=#{GROUP_ADMIN_SUNSTONE_VIEWS}"
|
||||
end
|
||||
|
||||
self.update(str, true)
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
@ -193,6 +206,24 @@ module OpenNebula
|
||||
return rc
|
||||
end
|
||||
|
||||
# Adds a User to the Group administrators set
|
||||
# @param user_id [Integer] User ID
|
||||
#
|
||||
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
||||
# otherwise
|
||||
def add_admin(user_id)
|
||||
return call(GROUP_METHODS[:add_admin], @pe_id, user_id.to_i)
|
||||
end
|
||||
|
||||
# Removes a User from the Group administrators set
|
||||
# @param user_id [Integer] User ID
|
||||
#
|
||||
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
||||
# otherwise
|
||||
def del_admin(user_id)
|
||||
return call(GROUP_METHODS[:del_admin], @pe_id, user_id.to_i)
|
||||
end
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Helpers to get information
|
||||
# ---------------------------------------------------------------------
|
||||
@ -206,15 +237,31 @@ module OpenNebula
|
||||
return id_array != nil && id_array.include?(uid.to_s)
|
||||
end
|
||||
|
||||
# Returns whether or not the user with id 'uid' is an admin of this group
|
||||
def contains_admin(uid)
|
||||
#This doesn't work in ruby 1.8.5
|
||||
#return self["ADMINS/ID[.=#{uid}]"] != nil
|
||||
|
||||
id_array = retrieve_elements('ADMINS/ID')
|
||||
return id_array != nil && id_array.include?(uid.to_s)
|
||||
end
|
||||
|
||||
# Returns an array with the numeric user ids
|
||||
def user_ids
|
||||
array = Array.new
|
||||
ids = self.retrieve_elements("USERS/ID")
|
||||
|
||||
return [] if ids.nil?
|
||||
|
||||
self.each("USERS/ID") do |id|
|
||||
array << id.text.to_i
|
||||
end
|
||||
return ids.collect! {|x| x.to_i}
|
||||
end
|
||||
|
||||
return array
|
||||
# Returns an array with the numeric admin user ids
|
||||
def admin_ids
|
||||
ids = self.retrieve_elements("ADMINS/ID")
|
||||
|
||||
return [] if ids.nil?
|
||||
|
||||
return ids.collect! {|x| x.to_i}
|
||||
end
|
||||
|
||||
private
|
||||
@ -260,10 +307,6 @@ module OpenNebula
|
||||
# gdef[:group_admin][:name] username for group admin
|
||||
# gdef[:group_admin][:password] password for group admin
|
||||
# gdef[:group_admin][:auth_driver] auth driver for group admin
|
||||
# gdef[:group_admin][:resources] resources that group admin manage
|
||||
# gdef[:group_admin][:manage_resources] whether group admin manages
|
||||
# group users
|
||||
# gdef[:resources] resources that group users manage
|
||||
#
|
||||
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
||||
def create_admin_user(gdef)
|
||||
@ -299,37 +342,13 @@ module OpenNebula
|
||||
return rc
|
||||
end
|
||||
|
||||
# Set the default admin view to groupadmin
|
||||
group_admin.update("DEFAULT_VIEW=#{GROUP_ADMIN_SUNSTONE_VIEWS}", true)
|
||||
|
||||
#Create admin group acls
|
||||
acls = Array.new
|
||||
|
||||
acls_str = (gdef[:group_admin][:resources] || \
|
||||
gdef[:resources] || GROUP_DEFAULT_ACLS)
|
||||
|
||||
manage_users = gdef[:group_admin][:manage_users] || "YES"
|
||||
|
||||
if manage_users.upcase == "YES"
|
||||
acls << "##{group_admin.id} USER/@#{self.id} CREATE+USE+MANAGE+ADMIN"
|
||||
end
|
||||
|
||||
acls << "##{group_admin.id} #{acls_str}/@#{self.id} " +
|
||||
"CREATE+USE+MANAGE"
|
||||
|
||||
rc, tmp = create_group_acls(acls)
|
||||
rc = self.add_admin(group_admin.id)
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
group_admin.delete
|
||||
return rc
|
||||
end
|
||||
|
||||
#Set Sunstone Views for the group
|
||||
gtmpl = "GROUP_ADMINS=#{gdef[:group_admin][:name]}\n"
|
||||
gtmpl << "GROUP_ADMIN_VIEWS=#{GROUP_ADMIN_SUNSTONE_VIEWS}\n"
|
||||
|
||||
self.update(gtmpl, true)
|
||||
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
@ -470,6 +470,22 @@ EOT
|
||||
end
|
||||
end
|
||||
|
||||
slave_admins_elem = slave_doc.root.at_xpath("ADMINS")
|
||||
master_admins_elem = master_doc.root.at_xpath("ADMINS")
|
||||
|
||||
slave_admins_elem.xpath("ID").each do |id|
|
||||
user = users[id.text.to_i]
|
||||
|
||||
if !user.nil?
|
||||
user_id = user[:oid]
|
||||
|
||||
if master_admins_elem.at_xpath("ID [.=#{user_id}]").nil?
|
||||
master_admins_elem.add_child(
|
||||
master_doc.create_element("ID")).content = user_id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
slave_template = slave_doc.root.at_xpath("TEMPLATE")
|
||||
master_template = master_doc.root.at_xpath("TEMPLATE")
|
||||
|
||||
@ -501,18 +517,34 @@ EOT
|
||||
users_elem = slave_doc.root.at_xpath("USERS")
|
||||
users_elem.remove
|
||||
|
||||
new_elem = slave_doc.create_element("USERS")
|
||||
new_users_elem = slave_doc.create_element("USERS")
|
||||
|
||||
users_elem.xpath("ID").each do |id|
|
||||
user = users[id.text.to_i]
|
||||
|
||||
if !user.nil?
|
||||
new_elem.add_child(slave_doc.create_element("ID")).
|
||||
new_users_elem.add_child(slave_doc.create_element("ID")).
|
||||
content = user[:oid]
|
||||
end
|
||||
end
|
||||
|
||||
slave_doc.root.add_child(new_elem)
|
||||
slave_doc.root.add_child(new_users_elem)
|
||||
|
||||
admins_elem = slave_doc.root.at_xpath("ADMINS")
|
||||
admins_elem.remove
|
||||
|
||||
new_admins_elem = slave_doc.create_element("ADMINS")
|
||||
|
||||
admins_elem.xpath("ID").each do |id|
|
||||
user = users[id.text.to_i]
|
||||
|
||||
if !user.nil?
|
||||
new_admins_elem.add_child(slave_doc.create_element("ID")).
|
||||
content = user[:oid]
|
||||
end
|
||||
end
|
||||
|
||||
slave_doc.root.add_child(new_admins_elem)
|
||||
|
||||
# Update resource providers
|
||||
slave_doc.root.xpath("RESOURCE_PROVIDER").each do |elem|
|
||||
|
@ -86,6 +86,40 @@ EOT
|
||||
end
|
||||
end
|
||||
|
||||
admin_v_elem = doc.at_xpath("/GROUP/TEMPLATE/GROUP_ADMIN_VIEWS")
|
||||
|
||||
if (!admin_v_elem.nil?)
|
||||
aux_e = doc.at_xpath("/GROUP/TEMPLATE/GROUP_ADMIN_DEFAULT_VIEW")
|
||||
aux_e.remove if !aux_e.nil?
|
||||
|
||||
doc.at_xpath("/GROUP/TEMPLATE").add_child(
|
||||
doc.create_element("GROUP_ADMIN_DEFAULT_VIEW")).
|
||||
add_child(Nokogiri::XML::CDATA.new(
|
||||
doc,
|
||||
admin_v_elem.text))
|
||||
end
|
||||
|
||||
admins_elem = doc.root.add_child( doc.create_element("ADMINS") )
|
||||
|
||||
elem = doc.at_xpath("/GROUP/TEMPLATE/GROUP_ADMINS")
|
||||
|
||||
if (!elem.nil?)
|
||||
elem.remove
|
||||
|
||||
elem.text.split(",").each do |uname|
|
||||
@db.fetch("SELECT oid FROM user_pool \
|
||||
WHERE name=\"#{uname.strip}\"") do |user_row|
|
||||
|
||||
# Check that user is part of this group first
|
||||
if !doc.at_xpath("/GROUP/USERS/ID[.=#{user_row[:oid]}]").nil?
|
||||
admins_elem.add_child(
|
||||
doc.create_element("ID") ).content =
|
||||
user_row[:oid]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
res_providers = doc.xpath("/GROUP/RESOURCE_PROVIDER")
|
||||
|
||||
res_providers.each do |provider|
|
||||
|
@ -484,23 +484,31 @@ void RequestManager::register_xml_methods()
|
||||
xmlrpc_c::method * group_allocate_pt;
|
||||
xmlrpc_c::method * group_update_pt;
|
||||
xmlrpc_c::method * group_delete_pt;
|
||||
xmlrpc_c::method * group_add_admin_pt;
|
||||
xmlrpc_c::method * group_del_admin_pt;
|
||||
|
||||
if (nebula.is_federation_slave())
|
||||
{
|
||||
group_allocate_pt = new RequestManagerProxy("one.group.allocate");
|
||||
group_delete_pt = new RequestManagerProxy("one.group.delete");
|
||||
group_update_pt = new RequestManagerProxy("one.group.update");
|
||||
group_add_admin_pt = new RequestManagerProxy("one.group.addadmin");
|
||||
group_del_admin_pt = new RequestManagerProxy("one.group.deladmin");
|
||||
}
|
||||
else
|
||||
{
|
||||
group_allocate_pt = new GroupAllocate();
|
||||
group_delete_pt = new GroupDelete();
|
||||
group_update_pt = new GroupUpdateTemplate();
|
||||
group_add_admin_pt = new GroupAddAdmin();
|
||||
group_del_admin_pt = new GroupDelAdmin();
|
||||
}
|
||||
|
||||
xmlrpc_c::methodPtr group_allocate(group_allocate_pt);
|
||||
xmlrpc_c::methodPtr group_delete(group_delete_pt);
|
||||
xmlrpc_c::methodPtr group_update(group_update_pt);
|
||||
xmlrpc_c::methodPtr group_add_admin(group_add_admin_pt);
|
||||
xmlrpc_c::methodPtr group_del_admin(group_del_admin_pt);
|
||||
|
||||
xmlrpc_c::methodPtr group_info(new GroupInfo());
|
||||
xmlrpc_c::methodPtr group_set_quota(new GroupSetQuota());
|
||||
@ -513,6 +521,8 @@ void RequestManager::register_xml_methods()
|
||||
RequestManagerRegistry.addMethod("one.group.info", group_info);
|
||||
RequestManagerRegistry.addMethod("one.group.quota", group_set_quota);
|
||||
RequestManagerRegistry.addMethod("one.group.update", group_update);
|
||||
RequestManagerRegistry.addMethod("one.group.addadmin", group_add_admin);
|
||||
RequestManagerRegistry.addMethod("one.group.deladmin", group_del_admin);
|
||||
|
||||
RequestManagerRegistry.addMethod("one.grouppool.info", grouppool_info);
|
||||
|
||||
|
@ -81,3 +81,113 @@ void GroupSetQuota::
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void GroupEditAdmin::request_execute(
|
||||
xmlrpc_c::paramList const& paramList,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
int group_id = xmlrpc_c::value_int(paramList.getInt(1));
|
||||
int user_id = xmlrpc_c::value_int(paramList.getInt(2));
|
||||
|
||||
PoolObjectAuth group_perms;
|
||||
PoolObjectAuth user_perms;
|
||||
|
||||
string group_name;
|
||||
string user_name;
|
||||
string error_str;
|
||||
|
||||
Group* group;
|
||||
|
||||
int rc;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Authorize the action
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
rc = get_info(pool, group_id, PoolObjectSQL::GROUP,
|
||||
att, group_perms, group_name, true);
|
||||
|
||||
if ( rc == -1 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rc = get_info(upool, user_id, PoolObjectSQL::USER, att, user_perms,
|
||||
user_name, false);
|
||||
|
||||
if ( rc == -1 )
|
||||
{
|
||||
failure_response(NO_EXISTS, get_error(object_name(PoolObjectSQL::USER),
|
||||
user_id), att);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( att.uid != 0 )
|
||||
{
|
||||
AuthRequest ar(att.uid, att.group_ids);
|
||||
|
||||
ar.add_auth(AuthRequest::ADMIN, group_perms); // MANAGE GROUP
|
||||
|
||||
ar.add_auth(AuthRequest::ADMIN, user_perms); // MANAGE USER
|
||||
|
||||
if (UserPool::authorize(ar) == -1)
|
||||
{
|
||||
failure_response(AUTHORIZATION,
|
||||
authorization_error(ar.message, att),
|
||||
att);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
group = static_cast<GroupPool*>(pool)->get(group_id, true);
|
||||
|
||||
if ( group == 0 )
|
||||
{
|
||||
failure_response(NO_EXISTS,
|
||||
get_error(object_name(auth_object),group_id),
|
||||
att);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
rc = edit_admin(group, user_id, error_str);
|
||||
|
||||
if (rc == 0)
|
||||
{
|
||||
pool->update(group);
|
||||
}
|
||||
|
||||
group->unlock();
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
failure_response(INTERNAL,
|
||||
request_error("Cannot edit group", error_str),
|
||||
att);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
success_response(group_id, att);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int GroupAddAdmin::edit_admin(Group* group, int user_id, string& error_msg)
|
||||
{
|
||||
return group->add_admin(user_id, error_msg);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int GroupDelAdmin::edit_admin(Group* group, int user_id, string& error_msg)
|
||||
{
|
||||
return group->del_admin(user_id, error_msg);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -98,6 +98,7 @@ tabs:
|
||||
Group.create_dialog: true
|
||||
Group.quotas_dialog: true
|
||||
Group.delete: true
|
||||
Group.edit_admins: true
|
||||
vdcs-tab:
|
||||
panel_tabs:
|
||||
vdc_info_tab: true
|
||||
|
@ -96,6 +96,7 @@ tabs:
|
||||
Group.create_dialog: true
|
||||
Group.quotas_dialog: true
|
||||
Group.delete: true
|
||||
Group.edit_admins: true
|
||||
acls-tab:
|
||||
panel_tabs:
|
||||
table_columns:
|
||||
|
@ -97,6 +97,7 @@ tabs:
|
||||
Group.create_dialog: true
|
||||
Group.quotas_dialog: true
|
||||
Group.delete: true
|
||||
Group.edit_admins: true
|
||||
acls-tab:
|
||||
panel_tabs:
|
||||
table_columns:
|
||||
|
@ -39,6 +39,8 @@ module OpenNebulaJSON
|
||||
when "chown" then self.chown(action_hash['params'])
|
||||
when "update" then self.update_json(action_hash['params'])
|
||||
when "set_quota" then self.set_quota(action_hash['params'])
|
||||
when "add_admin" then self.add_admin_json(action_hash['params'])
|
||||
when "del_admin" then self.del_admin_json(action_hash['params'])
|
||||
else
|
||||
error_msg = "#{action_hash['perform']} action not " <<
|
||||
" available for this resource"
|
||||
@ -59,5 +61,13 @@ module OpenNebulaJSON
|
||||
quota_template = template_to_str(quota_json)
|
||||
super(quota_template)
|
||||
end
|
||||
|
||||
def add_admin_json(params=Hash.new)
|
||||
add_admin(params['admin_id'].to_i)
|
||||
end
|
||||
|
||||
def del_admin_json(params=Hash.new)
|
||||
del_admin(params['admin_id'].to_i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -87,10 +87,10 @@ class SunstoneViews
|
||||
available << @views_config['groups'][group.name]
|
||||
end
|
||||
|
||||
gadmins = group["TEMPLATE/GROUP_ADMINS"]
|
||||
gadmins = group.admin_ids
|
||||
gadmins_views = group["TEMPLATE/GROUP_ADMIN_VIEWS"]
|
||||
|
||||
if gadmins && gadmins.split(',').include?(user_name) && gadmins_views
|
||||
if gadmins && gadmins.include?(user.id) && gadmins_views
|
||||
views_array = gadmins_views.split(",")
|
||||
available << views_array.each{|v| v.strip!}
|
||||
end
|
||||
|
@ -1141,6 +1141,14 @@ var OpenNebula = {
|
||||
},
|
||||
"accounting" : function(params){
|
||||
OpenNebula.Action.monitor(params,OpenNebula.Group.resource,false);
|
||||
},
|
||||
"add_admin" : function(params){
|
||||
var action_obj = params.data.extra_param;
|
||||
OpenNebula.Action.simple_action(params,OpenNebula.Group.resource,"add_admin",action_obj);
|
||||
},
|
||||
"del_admin" : function(params){
|
||||
var action_obj = params.data.extra_param;
|
||||
OpenNebula.Action.simple_action(params,OpenNebula.Group.resource,"del_admin",action_obj);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -66,7 +66,7 @@ function create_group_tmpl(dialog_name){
|
||||
<div class="large-12 columns">\
|
||||
<p class="subheader">'
|
||||
+tr("Allow users in this group to use the following Sunstone views")+
|
||||
' <span class="tip">'+tr("Views available to the group users")+'</span>\
|
||||
' <span class="tip">'+tr("Views available to the group users. If the default is unset, the one set in sunstone-views.yaml will be used")+'</span>\
|
||||
</p>\
|
||||
</div>\
|
||||
</div>\
|
||||
@ -75,19 +75,6 @@ function create_group_tmpl(dialog_name){
|
||||
insert_views(dialog_name)
|
||||
+'</div>\
|
||||
</div>\
|
||||
<div class="row">\
|
||||
<div class="large-12 columns">\
|
||||
<p class="subheader">'
|
||||
+tr("Set the default Sunstone view")+
|
||||
' <span class="tip">'+tr("Default view for the group users. If it is unset, the default is set in sunstone-views.yaml")+'</span>\
|
||||
</p>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class="row">\
|
||||
<div class="large-12 columns">'+
|
||||
insert_views_default(dialog_name)
|
||||
+'</div>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div id="administrators" class=" content">\
|
||||
<div class="row">\
|
||||
@ -97,7 +84,7 @@ function create_group_tmpl(dialog_name){
|
||||
<label>\
|
||||
<input type="checkbox" id="admin_user" name="admin_user" value="YES" />\
|
||||
'+tr("Create an administrator user")+'\
|
||||
<span class="tip">'+tr("You can create now an administrator user that will be assigned to the new regular group, with the administrator group as a secondary one.")+'</span>\
|
||||
<span class="tip">'+tr("You can create now an administrator user. More administrators can be added later.")+'</span>\
|
||||
</label>\
|
||||
</div>\
|
||||
</div>' +
|
||||
@ -119,7 +106,7 @@ function create_group_tmpl(dialog_name){
|
||||
<div class="large-12 columns">\
|
||||
<p class="subheader">'
|
||||
+tr("Allow users in this group to create the following resources")+
|
||||
' <span class="tip">'+tr("This will create new ACL Rules to define which virtual resources this group's users will be able to create. You can set different resources for the administrator group, and decide if the administrators will be allowed to create new users.")+'</span>\
|
||||
' <span class="tip">'+tr("This will create new ACL Rules to define which virtual resources this group's users will be able to create.")+'</span>\
|
||||
</p>\
|
||||
</div>\
|
||||
</div>\
|
||||
@ -127,7 +114,6 @@ function create_group_tmpl(dialog_name){
|
||||
<div class="large-12 columns">\
|
||||
<table class="dataTable" style="table-layout:fixed">\
|
||||
<thead><tr>\
|
||||
<th/>\
|
||||
<th>'+tr("VMs")+'</th>\
|
||||
<th>'+tr("VNets")+'</th>\
|
||||
<th>'+tr("Security Groups")+'</th>\
|
||||
@ -137,7 +123,6 @@ function create_group_tmpl(dialog_name){
|
||||
</tr></thead>\
|
||||
<tbody>\
|
||||
<tr>\
|
||||
<th>'+tr("Users")+'</th>\
|
||||
<td><input type="checkbox" id="group_res_vm" name="group_res_vm" class="resource_cb" value="VM"></input></td>\
|
||||
<td><input type="checkbox" id="group_res_net" name="group_res_net" class="resource_cb" value="NET"></input></td>\
|
||||
<td><input type="checkbox" id="group_res_sg" name="group_res_sg" class="resource_cb" value="SECGROUP"></input></td>\
|
||||
@ -146,15 +131,6 @@ function create_group_tmpl(dialog_name){
|
||||
<td><input type="checkbox" id="group_res_document" name="group_res_document" class="resource_cb" value="DOCUMENT"></input></td>\
|
||||
<td/>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<th>'+tr("Admins")+'</th>\
|
||||
<td><input type="checkbox" id="group_admin_res_vm" name="group_admin_res_vm" class="resource_cb" value="VM"></input></td>\
|
||||
<td><input type="checkbox" id="group_admin_res_net" name="group_admin_res_net" class="resource_cb" value="NET"></input></td>\
|
||||
<td><input type="checkbox" id="group_admin_res_sg" name="group_admin_res_sg" class="resource_cb" value="SECGROUP"></input></td>\
|
||||
<td><input type="checkbox" id="group_admin_res_image" name="group_admin_res_image" class="resource_cb" value="IMAGE"></input></td>\
|
||||
<td><input type="checkbox" id="group_admin_res_template" name="group_admin_res_template" class="resource_cb" value="TEMPLATE"></input></td>\
|
||||
<td><input type="checkbox" id="group_admin_res_document" name="group_admin_res_document" class="resource_cb" value="DOCUMENT"></input></td>\
|
||||
</tr>\
|
||||
</tbody>\
|
||||
</table>\
|
||||
</div>\
|
||||
@ -319,6 +295,24 @@ var group_actions = {
|
||||
//plot_graph(response,'#group_acct_tabTab','group_acct_', info);
|
||||
},
|
||||
error: onError
|
||||
},
|
||||
|
||||
"Group.add_admin" : {
|
||||
type: "single",
|
||||
call : OpenNebula.Group.add_admin,
|
||||
callback : function (req) {
|
||||
Sunstone.runAction('Group.show',req.request.data[0][0]);
|
||||
},
|
||||
error : onError
|
||||
},
|
||||
|
||||
"Group.del_admin" : {
|
||||
type: "single",
|
||||
call : OpenNebula.Group.del_admin,
|
||||
callback : function (req) {
|
||||
Sunstone.runAction('Group.show',req.request.data[0][0]);
|
||||
},
|
||||
error : onError
|
||||
}
|
||||
}
|
||||
|
||||
@ -396,33 +390,62 @@ Sunstone.addMainTab('groups-tab',groups_tab);
|
||||
Sunstone.addInfoPanel("group_info_panel",group_info_panel);
|
||||
|
||||
function insert_views(dialog_name){
|
||||
var views_checks_str = "";
|
||||
var views_array = config['all_views'];
|
||||
for (var i = 0; i < views_array.length; i++)
|
||||
{
|
||||
var checked = views_array[i] == 'cloud' ? "checked" : "";
|
||||
var headers = "<tr><th/>";
|
||||
var row = "<tr><td>"+tr("Users")+"</td>";
|
||||
var admin_row = "<tr><td>"+tr("Admins")+"</td>";
|
||||
var default_row = "<tr><td>"+tr("Users default")+"</td>";
|
||||
var default_admin_row = "<tr><td>"+tr("Admins default")+"</td>";
|
||||
|
||||
views_checks_str = views_checks_str +
|
||||
'<input type="checkbox" id="group_view_'+dialog_name+'_'+views_array[i]+
|
||||
'" value="'+views_array[i]+'" '+checked+'/>' +
|
||||
'<label for="group_view_'+dialog_name+'_'+views_array[i]+'">'+views_array[i]+
|
||||
'</label>'
|
||||
}
|
||||
return views_checks_str;
|
||||
}
|
||||
var views_array = config['all_views'];
|
||||
|
||||
function insert_views_default(dialog_name){
|
||||
var views_checks_str = "";
|
||||
var views_array = config['all_views'];
|
||||
for (var i = 0; i < views_array.length; i++)
|
||||
{
|
||||
views_checks_str = views_checks_str +
|
||||
'<input type="radio" name="group_default_view_'+dialog_name+'" id="group_default_view_'+dialog_name+'_'+views_array[i]+
|
||||
'" value="'+views_array[i]+'"/>' +
|
||||
'<label for="group_default_view_'+dialog_name+'_'+views_array[i]+'">'+views_array[i]+
|
||||
'</label>'
|
||||
}
|
||||
return views_checks_str;
|
||||
for (var i = 0; i < views_array.length; i++){
|
||||
headers += "<th>"+views_array[i]+"</th>";
|
||||
|
||||
var checked = views_array[i] == 'cloud' ? "checked" : "";
|
||||
|
||||
row += '<td>\
|
||||
<input type="checkbox" \
|
||||
id="group_view_'+dialog_name+'_'+views_array[i]+'" \
|
||||
value="'+views_array[i]+'" '+checked+'/>\
|
||||
</td>';
|
||||
|
||||
checked = views_array[i] == 'groupadmin' ? "checked" : "";
|
||||
|
||||
admin_row += '<td>\
|
||||
<input type="checkbox" \
|
||||
id="group_admin_view_'+dialog_name+'_'+views_array[i]+'" \
|
||||
value="'+views_array[i]+'" '+checked+'/>\
|
||||
</td>';
|
||||
|
||||
default_row += '<td>\
|
||||
<input type="radio" \
|
||||
name="group_default_view_'+dialog_name+'" \
|
||||
id="group_default_view_'+dialog_name+'_'+views_array[i]+'" \
|
||||
value="'+views_array[i]+'"/>\
|
||||
</td>'
|
||||
|
||||
default_admin_row += '<td>\
|
||||
<input type="radio" \
|
||||
name="group_default_admin_view_'+dialog_name+'" \
|
||||
id="group_default_admin_view_'+dialog_name+'_'+views_array[i]+'" \
|
||||
value="'+views_array[i]+'"/>\
|
||||
</td>'
|
||||
}
|
||||
|
||||
headers += "</tr>";
|
||||
row += "</tr>";
|
||||
admin_row += "</tr>";
|
||||
default_row += "</tr>";
|
||||
default_admin_row += "</tr>";
|
||||
|
||||
return '<table class="dataTable" style="table-layout:fixed">'+
|
||||
headers+
|
||||
row+
|
||||
default_row+
|
||||
headers+
|
||||
admin_row+
|
||||
default_admin_row+
|
||||
"</table>";
|
||||
}
|
||||
|
||||
function groupElements(){
|
||||
@ -557,6 +580,12 @@ function updateGroupInfo(request,group){
|
||||
</div>'
|
||||
}
|
||||
|
||||
var users_tab = {
|
||||
title : tr("Users"),
|
||||
icon: "fa-users",
|
||||
content: group_users_tab_content(info)
|
||||
};
|
||||
|
||||
var default_group_quotas = Quotas.default_quotas(info.DEFAULT_GROUP_QUOTAS);
|
||||
|
||||
var quotas_html = initQuotasPanel(info, default_group_quotas,
|
||||
@ -577,6 +606,7 @@ function updateGroupInfo(request,group){
|
||||
|
||||
|
||||
Sunstone.updateInfoPanelTab("group_info_panel","group_info_tab",info_tab);
|
||||
Sunstone.updateInfoPanelTab("group_info_panel","group_users_tab",users_tab);
|
||||
Sunstone.updateInfoPanelTab("group_info_panel","group_quotas_tab",quotas_tab);
|
||||
Sunstone.updateInfoPanelTab("group_info_panel","group_accounting_tab",accounting_tab);
|
||||
|
||||
@ -592,6 +622,8 @@ function updateGroupInfo(request,group){
|
||||
|
||||
Sunstone.popUpInfoPanel("group_info_panel", 'groups-tab');
|
||||
|
||||
setup_group_users_tab_content(info);
|
||||
|
||||
if (Config.isFeatureEnabled("showback")) {
|
||||
showbackGraphs(
|
||||
$("#group_showback","#group_info_panel"),
|
||||
@ -615,6 +647,126 @@ function updateGroupInfo(request,group){
|
||||
"Group");
|
||||
}
|
||||
|
||||
function group_users_tab_content(group_info){
|
||||
|
||||
var html = "";
|
||||
|
||||
if (Config.isTabActionEnabled("groups-tab", "Group.edit_admins")) {
|
||||
html +=
|
||||
'<div class="row">\
|
||||
<div class="large-4 columns right">\
|
||||
<span>\
|
||||
<button class="button secondary small radius" id="edit_admins_button" style="width: 100%;">\
|
||||
<span class="fa fa-pencil-square-o"></span> '+tr("Edit administrators")+'\
|
||||
</button>\
|
||||
<button class="button alert small radius" id="cancel_admins_button" style="display: none">\
|
||||
'+tr("Cancel")+'\
|
||||
</button>\
|
||||
<button class="button success small radius" id="submit_admins_button" style="display: none">\
|
||||
'+tr("Apply")+'\
|
||||
</button>\
|
||||
</span>\
|
||||
</div>\
|
||||
</div>';
|
||||
}
|
||||
|
||||
html += '<div class="group_users_info_table">\
|
||||
'+generateUserTableSelect("group_users_list")+'\
|
||||
</div>';
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
function setup_group_users_tab_content(group_info){
|
||||
|
||||
var users = [];
|
||||
|
||||
if (group_info.USERS.ID != undefined){
|
||||
users = group_info.USERS.ID;
|
||||
|
||||
if (!$.isArray(users)){
|
||||
users = [users];
|
||||
}
|
||||
}
|
||||
|
||||
var admins = [];
|
||||
|
||||
if (group_info.ADMINS.ID != undefined){
|
||||
admins = group_info.ADMINS.ID;
|
||||
|
||||
if (!$.isArray(admins)){
|
||||
admins = [admins];
|
||||
}
|
||||
}
|
||||
|
||||
var opts = {
|
||||
read_only: true,
|
||||
fixed_ids: users,
|
||||
admin_ids: admins
|
||||
}
|
||||
|
||||
setupUserTableSelect($("#group_info_panel"), "group_users_list", opts);
|
||||
|
||||
refreshUserTableSelect($("#group_info_panel"), "group_users_list");
|
||||
|
||||
if (Config.isTabActionEnabled("groups-tab", "Group.edit_admins")) {
|
||||
$("#group_info_panel").off("click", "#edit_admins_button");
|
||||
$("#group_info_panel").on("click", "#edit_admins_button", function() {
|
||||
$("#edit_admins_button", "#group_info_panel").hide();
|
||||
$("#cancel_admins_button", "#group_info_panel").show();
|
||||
$("#submit_admins_button", "#group_info_panel").show();
|
||||
|
||||
$("#group_info_panel div.group_users_info_table").html(
|
||||
generateUserTableSelect("group_users_edit_list") );
|
||||
|
||||
|
||||
var opts = {
|
||||
multiple_choice: true,
|
||||
fixed_ids: users,
|
||||
admin_ids: admins
|
||||
}
|
||||
|
||||
setupUserTableSelect($("#group_info_panel"), "group_users_edit_list", opts);
|
||||
|
||||
selectUserTableSelect($("#group_info_panel"), "group_users_edit_list", { ids : admins });
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$("#group_info_panel").off("click", "#cancel_admins_button");
|
||||
$("#group_info_panel").on("click", "#cancel_admins_button", function() {
|
||||
Sunstone.runAction("Group.show", group_info.ID);
|
||||
return false;
|
||||
});
|
||||
|
||||
$("#group_info_panel").off("click", "#submit_admins_button");
|
||||
$("#group_info_panel").on("click", "#submit_admins_button", function() {
|
||||
// Add/delete admins
|
||||
|
||||
var selected_admins_list = retrieveUserTableSelect(
|
||||
$("#group_info_panel"), "group_users_edit_list");
|
||||
|
||||
$.each(selected_admins_list, function(i,admin_id){
|
||||
if (admins.indexOf(admin_id) == -1){
|
||||
Sunstone.runAction("Group.add_admin",
|
||||
group_info.ID, {admin_id : admin_id});
|
||||
}
|
||||
});
|
||||
|
||||
$.each(admins, function(i,admin_id){
|
||||
if (selected_admins_list.indexOf(admin_id) == -1){
|
||||
Sunstone.runAction("Group.del_admin",
|
||||
group_info.ID, {admin_id : admin_id});
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
function disableAdminUser(dialog){
|
||||
$('#username',dialog).attr('disabled','disabled');
|
||||
$('#pass',dialog).attr('disabled','disabled');
|
||||
@ -665,16 +817,8 @@ function setupCreateGroupDialog(){
|
||||
var dialog = $create_group_dialog;
|
||||
if ($(this).prop('checked')) {
|
||||
enableAdminUser(dialog);
|
||||
|
||||
$.each($('[id^="group_admin_res"]', dialog), function(){
|
||||
$(this).removeAttr("disabled");
|
||||
});
|
||||
} else {
|
||||
disableAdminUser(dialog);
|
||||
|
||||
$.each($('[id^="group_admin_res"]', dialog), function(){
|
||||
$(this).attr('disabled', 'disabled');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@ -684,13 +828,7 @@ function setupCreateGroupDialog(){
|
||||
$(this).prop("checked", true);
|
||||
});
|
||||
|
||||
$.each($('[id^="group_admin_res"]', dialog), function(){
|
||||
$(this).attr('disabled', 'disabled');
|
||||
$(this).prop("checked", true);
|
||||
});
|
||||
|
||||
$("#group_res_net", dialog).prop("checked", false);
|
||||
$("#group_admin_res_net", dialog).prop("checked", false);
|
||||
|
||||
$('#create_group_form',dialog).submit(function(){
|
||||
var name = $('#name',this).val();
|
||||
@ -730,18 +868,6 @@ function setupCreateGroupDialog(){
|
||||
group_json['group']['shared_resources'] = "VM+DOCUMENT";
|
||||
}
|
||||
|
||||
if (user_json){
|
||||
resources = "";
|
||||
separator = "";
|
||||
|
||||
$.each($('[id^="group_admin_res"]:checked', dialog), function(){
|
||||
resources += (separator + $(this).val());
|
||||
separator = "+";
|
||||
});
|
||||
|
||||
group_json["group"]["group_admin"]["resources"] = resources;
|
||||
}
|
||||
|
||||
group_json['group']['views'] = [];
|
||||
|
||||
$.each($('[id^="group_view"]:checked', dialog), function(){
|
||||
@ -753,6 +879,17 @@ function setupCreateGroupDialog(){
|
||||
group_json['group']['default_view'] = default_view;
|
||||
}
|
||||
|
||||
group_json['group']['admin_views'] = [];
|
||||
|
||||
$.each($('[id^="group_admin_view"]:checked', dialog), function(){
|
||||
group_json['group']['admin_views'].push($(this).val());
|
||||
});
|
||||
|
||||
var default_view = $('[id^="group_default_admin_view"]:checked', dialog).val();
|
||||
if (default_view != undefined){
|
||||
group_json['group']['default_admin_view'] = default_view;
|
||||
}
|
||||
|
||||
Sunstone.runAction("Group.create",group_json);
|
||||
return false;
|
||||
});
|
||||
@ -820,38 +957,92 @@ function popUpUpdateGroupDialog(group, dialog)
|
||||
|
||||
var views_str = "";
|
||||
|
||||
$('input[id^="group_view"]', dialog).removeAttr('checked');
|
||||
|
||||
if (group.TEMPLATE.SUNSTONE_VIEWS){
|
||||
views_str = group.TEMPLATE.SUNSTONE_VIEWS;
|
||||
|
||||
var views = views_str.split(",");
|
||||
$.each(views, function(){
|
||||
$('input[id^="group_view"][value="'+this.trim()+'"]', dialog).attr('checked','checked');
|
||||
$('input[id^="group_view"][value="'+this.trim()+'"]',
|
||||
dialog).attr('checked','checked');
|
||||
});
|
||||
}
|
||||
|
||||
$('input[id^="group_default_view"]', dialog).removeAttr('checked');
|
||||
|
||||
if (group.TEMPLATE.DEFAULT_VIEW){
|
||||
$('input[id^="group_default_view"][value="'+group.TEMPLATE.DEFAULT_VIEW.trim()+'"]',
|
||||
dialog).attr('checked','checked');
|
||||
}
|
||||
|
||||
$('input[id^="group_admin_view"]', dialog).removeAttr('checked');
|
||||
|
||||
if (group.TEMPLATE.GROUP_ADMIN_VIEWS){
|
||||
views_str = group.TEMPLATE.GROUP_ADMIN_VIEWS;
|
||||
|
||||
var views = views_str.split(",");
|
||||
$.each(views, function(){
|
||||
$('input[id^="group_admin_view"][value="'+this.trim()+'"]',
|
||||
dialog).attr('checked','checked');
|
||||
});
|
||||
}
|
||||
|
||||
$('input[id^="group_default_admin_view"]', dialog).removeAttr('checked');
|
||||
|
||||
if (group.TEMPLATE.GROUP_ADMIN_DEFAULT_VIEW){
|
||||
$('input[id^="group_default_admin_view"][value="'+group.TEMPLATE.GROUP_ADMIN_DEFAULT_VIEW.trim()+'"]',
|
||||
dialog).attr('checked','checked');
|
||||
}
|
||||
|
||||
$(dialog).off("click", 'button#update_group_submit');
|
||||
$(dialog).on("click", 'button#update_group_submit', function(){
|
||||
|
||||
// Update Views
|
||||
//-------------------------------------
|
||||
var new_views_str = "";
|
||||
var separator = "";
|
||||
var template_json = group.TEMPLATE;
|
||||
|
||||
delete template_json["SUNSTONE_VIEWS"];
|
||||
delete template_json["DEFAULT_VIEW"];
|
||||
delete template_json["GROUP_ADMIN_VIEWS"];
|
||||
delete template_json["GROUP_ADMIN_DEFAULT_VIEW"];
|
||||
|
||||
var views = [];
|
||||
|
||||
$.each($('[id^="group_view"]:checked', dialog), function(){
|
||||
new_views_str += (separator + $(this).val());
|
||||
separator = ",";
|
||||
views.push($(this).val());
|
||||
});
|
||||
|
||||
if (new_views_str != views_str){
|
||||
var template_json = group.TEMPLATE;
|
||||
delete template_json["SUNSTONE_VIEWS"];
|
||||
template_json["SUNSTONE_VIEWS"] = new_views_str;
|
||||
|
||||
var template_str = convert_template_to_string(template_json);
|
||||
|
||||
Sunstone.runAction("Group.update_template",group.ID,template_str);
|
||||
if (views.length != 0){
|
||||
template_json["SUNSTONE_VIEWS"] = views.join(",");
|
||||
}
|
||||
|
||||
var default_view = $('[id^="group_default_view"]:checked', dialog).val();
|
||||
|
||||
if (default_view != undefined){
|
||||
template_json["DEFAULT_VIEW"] = default_view;
|
||||
}
|
||||
|
||||
var admin_views = [];
|
||||
|
||||
$.each($('[id^="group_admin_view"]:checked', dialog), function(){
|
||||
admin_views.push($(this).val());
|
||||
});
|
||||
|
||||
if (admin_views.length != 0){
|
||||
template_json["GROUP_ADMIN_VIEWS"] = admin_views.join(",");
|
||||
}
|
||||
|
||||
var default_admin_view = $('[id^="group_default_admin_view"]:checked', dialog).val();
|
||||
|
||||
if (default_admin_view != undefined){
|
||||
template_json["GROUP_ADMIN_DEFAULT_VIEW"] = default_admin_view;
|
||||
}
|
||||
|
||||
var template_str = convert_template_to_string(template_json);
|
||||
|
||||
Sunstone.runAction("Group.update_template",group.ID,template_str);
|
||||
|
||||
// Close the dialog
|
||||
//-------------------------------------
|
||||
|
||||
|
@ -6990,6 +6990,185 @@ function selectGroupTableSelect(section, context_id, opts){
|
||||
return selectResourceTableSelect(section, context_id, opts);
|
||||
}
|
||||
|
||||
function generateUserTableSelect(context_id){
|
||||
|
||||
var columns = [
|
||||
"",
|
||||
tr("ID"),
|
||||
tr("Name"),
|
||||
tr("Group"),
|
||||
tr("Auth driver"),
|
||||
tr("VMs"),
|
||||
tr("Memory"),
|
||||
tr("CPU"),
|
||||
tr("Group ID"),
|
||||
tr("Hidden User Data")
|
||||
];
|
||||
|
||||
var options = {
|
||||
"id_index": 1,
|
||||
"name_index": 2,
|
||||
"select_resource": tr("Please select a User from the list"),
|
||||
"you_selected": tr("You selected the following User:"),
|
||||
"select_resource_multiple": tr("Please select one or more users from the list"),
|
||||
"you_selected_multiple": tr("You selected the following users:")
|
||||
};
|
||||
|
||||
return generateResourceTableSelect(context_id, columns, options);
|
||||
}
|
||||
|
||||
// opts.bVisible: dataTable bVisible option. If not set, the .yaml visibility will be used
|
||||
// opts.filter_fn: boolean function to filter which elements to show
|
||||
// opts.select_callback(aData, options): function called after a row is selected
|
||||
// opts.multiple_choice: boolean true to enable multiple element selection
|
||||
// opts.read_only: boolean true so user is not asked to select elements
|
||||
// opts.fixed_ids: Array of IDs to show. Any other ID will be filtered out. If
|
||||
// an ID is not returned by the pool, it will be included as a
|
||||
// blank row
|
||||
// opts.admin_ids: Array of User IDs that will be marked as admin
|
||||
function setupUserTableSelect(section, context_id, opts){
|
||||
|
||||
if(opts == undefined){
|
||||
opts = {};
|
||||
}
|
||||
|
||||
if(opts.bVisible == undefined){
|
||||
// Use the settings in the conf, but removing the checkbox
|
||||
var config = Config.tabTableColumns('users-tab').slice(0);
|
||||
var i = config.indexOf(0);
|
||||
|
||||
if(i != -1){
|
||||
config.splice(i,1);
|
||||
}
|
||||
|
||||
opts.bVisible = config;
|
||||
}
|
||||
|
||||
if(opts.multiple_choice == undefined){
|
||||
opts.multiple_choice = false;
|
||||
}
|
||||
|
||||
var fixed_ids_map_orig = {};
|
||||
|
||||
if(opts.fixed_ids != undefined){
|
||||
$.each(opts.fixed_ids,function(){
|
||||
fixed_ids_map_orig[this] = true;
|
||||
});
|
||||
}
|
||||
|
||||
var admin_ids_map = {};
|
||||
|
||||
if(opts.admin_ids != undefined){
|
||||
$.each(opts.admin_ids,function(){
|
||||
admin_ids_map[this] = true;
|
||||
});
|
||||
}
|
||||
|
||||
var options = {
|
||||
"dataTable_options": {
|
||||
"bAutoWidth":false,
|
||||
"iDisplayLength": 4,
|
||||
"sDom" : '<"H">t<"F"p>',
|
||||
"bRetrieve": true,
|
||||
"bSortClasses" : false,
|
||||
"bDeferRender": true,
|
||||
"aoColumnDefs": [
|
||||
{ "sWidth": "35px", "aTargets": [0] },
|
||||
{ "bVisible": true, "aTargets": opts.bVisible},
|
||||
{ "bVisible": false, "aTargets": ['_all']}
|
||||
]
|
||||
},
|
||||
|
||||
"multiple_choice": opts.multiple_choice,
|
||||
"read_only": opts.read_only,
|
||||
"fixed_ids": opts.fixed_ids,
|
||||
|
||||
"id_index": 1,
|
||||
"name_index": 2,
|
||||
|
||||
"update_fn": function(datatable){
|
||||
OpenNebula.User.list({
|
||||
timeout: true,
|
||||
success: function (request, resource_list){
|
||||
var list_array = [];
|
||||
|
||||
var fixed_ids_map = $.extend({}, fixed_ids_map_orig);
|
||||
|
||||
$.each(resource_list,function(){
|
||||
var add = true;
|
||||
|
||||
if(opts.filter_fn){
|
||||
add = opts.filter_fn(this.USER);
|
||||
}
|
||||
|
||||
if(opts.fixed_ids != undefined){
|
||||
add = (add && fixed_ids_map[this.USER.ID]);
|
||||
}
|
||||
|
||||
if(add){
|
||||
var user_arr = userElementArray(this);
|
||||
|
||||
if (opts.admin_ids != undefined){
|
||||
|
||||
if (admin_ids_map[this.USER.ID]){
|
||||
user_arr[2] =
|
||||
('<i class="fa fa-star fa-fw"></i> ' +
|
||||
user_arr[2]) // NAME INDEX
|
||||
} else {
|
||||
user_arr[2] =
|
||||
('<i class="fa fa-fw"></i> ' +
|
||||
user_arr[2]) // NAME INDEX
|
||||
}
|
||||
}
|
||||
|
||||
list_array.push(user_arr);
|
||||
|
||||
delete fixed_ids_map[this.USER.ID];
|
||||
}
|
||||
});
|
||||
|
||||
var n_columns = 10; // SET FOR EACH RESOURCE
|
||||
|
||||
$.each(fixed_ids_map, function(id,v){
|
||||
var empty = [];
|
||||
|
||||
for(var i=0; i<=n_columns; i++){
|
||||
empty.push("");
|
||||
}
|
||||
|
||||
empty[1] = id; // SET FOR EACH RESOURCE, id_index
|
||||
|
||||
list_array.push(empty);
|
||||
});
|
||||
|
||||
updateView(list_array, datatable);
|
||||
},
|
||||
error: onError
|
||||
});
|
||||
},
|
||||
|
||||
"select_callback": opts.select_callback
|
||||
};
|
||||
|
||||
return setupResourceTableSelect(section, context_id, options);
|
||||
}
|
||||
|
||||
// Clicks the refresh button
|
||||
function refreshUserTableSelect(section, context_id){
|
||||
return refreshResourceTableSelect(section, context_id);
|
||||
}
|
||||
|
||||
// Returns an ID, or an array of IDs for opts.multiple_choice
|
||||
function retrieveUserTableSelect(section, context_id){
|
||||
return retrieveResourceTableSelect(section, context_id);
|
||||
}
|
||||
|
||||
// Clears the current selection, and selects the given IDs
|
||||
// opts.ids must be a single ID, or an array of IDs for options.multiple_choice
|
||||
// opts.names must be an array of {name, uname}
|
||||
function selectUserTableSelect(section, context_id, opts){
|
||||
return selectResourceTableSelect(section, context_id, opts);
|
||||
}
|
||||
|
||||
function generateClusterTableSelect(context_id){
|
||||
|
||||
|
@ -235,6 +235,8 @@ helpers do
|
||||
|
||||
if user['TEMPLATE/DEFAULT_VIEW']
|
||||
session[:default_view] = user['TEMPLATE/DEFAULT_VIEW']
|
||||
elsif group.contains_admin(user.id) && group['TEMPLATE/GROUP_ADMIN_DEFAULT_VIEW']
|
||||
session[:default_view] = group['TEMPLATE/GROUP_ADMIN_DEFAULT_VIEW']
|
||||
elsif group['TEMPLATE/DEFAULT_VIEW']
|
||||
session[:default_view] = group['TEMPLATE/DEFAULT_VIEW']
|
||||
else
|
||||
|
Loading…
x
Reference in New Issue
Block a user