/******************************************************************************* Copyright (c) 2011, Perforce Software, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE SOFTWARE, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *******************************************************************************/ /******************************************************************************* * Name : Repository.Group.cs * * Author : dbb * * Description : Group operation for the Repository. * ******************************************************************************/ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace Perforce.P4 { public partial class Repository { /// /// Create a new group in the repository. /// /// Group specification for the new group /// The '-i' flags are required when creating a new group /// The Group object if new group was created, null if creation failed /// The '-i' flag is added if not specified by the caller ///
///
p4 help group ///
///
group -- Change members of user group ///
///
p4 group [-a |-A] name ///
p4 group -d [-a] name ///
p4 group -o name ///
p4 group -i [-a] ///
///
Create a group or modify the membership of an existing group. ///
A group can contain users and other groups. The group specification ///
is put into a temporary file and the editor (configured by the ///
environment variable $P4EDITOR) is invoked. ///
///
A group exists when it has any users or other groups in it, and ///
ceases to exist if all users and groups in it are removed. ///
///
Each group has MaxResults, MaxScanRows, and MaxLockTime fields, ///
which limit the resources committed to operations performed by ///
members of the group. For these fields, 'unlimited' or 'unset' ///
means no limit for that group. An individual user's limit is the ///
highest of any group with a limit to which he belongs, unlimited if ///
any of his groups has 'unlimited' for that field, or unlimited ///
if he belongs to no group with a limit. See 'p4 help maxresults' ///
for more information on MaxResults, MaxScanRows and MaxLockTime. ///
///
Each group also has a Timeout field, which specifies how long (in ///
seconds) a 'p4 login' ticket remains valid. A value of 'unset' or ///
'unlimited' is equivalent to no timeout. An individual's timeout is ///
the highest of any group with a limit to which he belongs, unlimited ///
if any of his groups has 'unlimited' for the timeout value, or ///
unlimited if he belongs to no group with a limit. See 'p4 help login' ///
for more information. ///
///
Each group has a PasswordTimeout field, which determines how long a ///
password remains valid for members of the group. ///
///
The -d flag deletes a group. ///
///
The -o flag writes the group specification to standard output. The ///
user's editor is not invoked. ///
///
The -i flag reads a group specification from standard input. The ///
user's editor is not invoked. The new group specification replaces ///
the previous one. ///
///
The -a flag enables a user without 'super' access to modify the group ///
if that user is an 'owner' of that group. Group owners are specified ///
in the 'Owners' field of the group spec. ///
///
The -A flag enables a user with 'admin' access to add a new group. ///
Existing groups may not be modified when this flag is used. ///
///
All commands that require access granted by 'p4 protect' consider a ///
user's groups when calculating access levels. ///
///
'p4 group' requires 'super' access granted by 'p4 protect' unless ///
invoked with the '-a' flag by a qualified user. ///
///
///
/// /// To create the group 'Mygroup' with the owner 'Bob' and a user 'Ted' /// when connected as super user: /// /// /// string targetGroup = "Mygroup"; /// Group group = new Group(); /// group.Id = targetGroup; /// group.UserNames = new List<string> { "Ted" }; /// group.OwnerNames = new List<string> { "Bob" }; /// _repository.CreateGroup(group, null); /// /// /// To create a group "everyone" when connected as a user with admin level /// rights: /// /// /// string targetGroup = "everyone"; /// Group group = new Group(); /// group.Id = targetGroup; /// group.UserNames = new List<string> { "Ted" }; /// group.OwnerNames = new List<string> { "Bob" }; /// _repository.CreateGroup(group, new Options(GroupCmdFlags.AdminAdd)); /// /// /// /// public Group CreateGroup(Group group, Options options) { if (group == null) { throw new ArgumentNullException("group"); } P4Command cmd = new P4Command(this, "group", true); cmd.DataSet = group.ToString(); if (options == null) { options = new Options(); } options["-i"] = null; P4CommandResult results = cmd.Run(options); if (results.Success) { return group; } else { P4Exception.Throw(results.ErrorList); } return null; } /// /// Create a new group in the repository. /// /// Group specification for the new group /// The Group object if new group was created, null if creation failed /// /// To create the group 'Mygroup' with the owner 'Bob' and a users 'Ted' and 'Alex': /// /// /// string targetGroup = "Mygroup"; /// Group group = new Group(); /// group.Id = targetGroup; /// group.UserNames = new List<string> { "Ted", "Alex" }; /// group.OwnerNames = new List<string> { "Bob" }; /// _repository.CreateGroup(group); /// /// /// public Group CreateGroup(Group group) { return CreateGroup(group, null); } /// /// Update the record for a group in the repository /// /// Group specification for the group being updated /// The Group object if new group was saved, null if creation failed /// /// To add the user 'Carol' to the group 'Mygroup': /// /// /// string targetGroup = "Mygroup"; /// Group group = GetGroup(targetGroup, null); /// group.UserNames.Add("Carol"); /// _repository.UpdateGroup(group); /// /// /// public Group UpdateGroup(Group group) { return CreateGroup(group, null); } /// /// Update the record for a group in the repository /// /// Group specification for the group being updated /// The Group object if new group was saved, null if creation failed /// /// To add the user 'Carol' to the group 'Mygroup': /// /// /// string targetGroup = "Mygroup"; /// Group group = GetGroup(targetGroup, null); /// group.UserNames.Add("Carol"); /// _repository.UpdateGroup(group); /// /// /// public Group UpdateGroup(Group group, Options options) { return CreateGroup(group, options); } /// /// Get the record for an existing group from the repository. /// /// Group name /// The Owner Access flag (-a) needs to be used if a user /// without 'super' access is an 'owner' of that group. /// The Group object if new group was found, null if creation failed /// /// To get the group 'everyone' when connected as a user with super access: /// /// /// string targetGroup = "everyone"; /// Group group = _repository.GetGroup(targetGroup, null); /// /// /// To get the group 'Mygroup' when connected as a without super access /// who is the owner of that group: /// /// /// string targetGroup = "everyone"; /// GroupCmdOptions opts = new GroupCmdOptions(GroupCmdFlags.OwnerAccess); /// Group group = _repository.GetGroup(targetGroup, opts); /// /// /// /// public Group GetGroup(string group, Options options) { if (group == null) { throw new ArgumentNullException("group"); } P4Command cmd = new P4Command(this, "group", true, group); if (options == null) { options = new Options(); } options["-o"] = null; P4CommandResult results = cmd.Run(options); if (results.Success) { if ((results.TaggedOutput == null) || (results.TaggedOutput.Count <= 0)) { return null; } Group value = new Group(); value.FromGroupCmdTaggedOutput((results.TaggedOutput[0])); return value; } else { P4Exception.Throw(results.ErrorList); } return null; } /// /// Get the record for an existing group from the repository. /// /// Group name /// The Group object if new group was found, null if creation failed /// /// To get the group 'everyone': /// /// /// string targetGroup = "everyone"; /// IList<Group> group = _repository.getGroup(targetGroup); /// /// /// public Group GetGroup(string group) { return GetGroup(group, null); } /// /// Get a list of groups from the repository /// /// options for the groups command /// A list containing the matching groups /// ///
p4 help groups ///
///
groups -- List groups (of users) ///
///
p4 groups [-m max] [[[-i] user | group] | [-v [group]]] ///
///
List all user groups defined in the server. If a user argument is, ///
specified, only groups containing that user are displayed. If a group ///
argument is specified, only groups containing the group are displayed. ///
///
The -i flag also displays groups that the user or group belongs to ///
indirectly by means of membership in subgroups. ///
///
The -m max flag limits output to the specified number of groups. ///
///
The -v flag displays the MaxResults, MaxScanRows, MaxLockTime, and ///
Timeout values for the specified group. ///
///
///
/// /// To get the first 10 groups: /// /// /// Options opts = new Options(GroupsCmdFlags.None, 10); /// IList<Group> groups = _repository.getGroups(opts); /// /// /// To get all groups that 'Bob' belongs to, including subgroups: /// /// /// Options opts = new Options(GroupsCmdFlags.IncludeIndirect, -1); /// IList<Group> groups = _repository.getGroups(opts, "Bob"); /// /// /// To get all the groups with the MaxResults, MaxScanRows, MaxLockTime, and /// Timeout values for the specified group: /// /// /// Options opts = new Options(GroupsCmdFlags.IncludeAllValues, -1); /// IList<Group> groups = _repository.getGroups(opts); /// /// /// /// public IList GetGroups(Options options, params string[] groups) { P4Command cmd = null; if ((groups != null) && (groups.Length > 0)) { cmd = new P4Command(this, "groups", true, groups); } else { cmd = new P4Command(this, "groups", true); } P4CommandResult results = cmd.Run(options); if (results.Success) { if ((results.TaggedOutput == null) || (results.TaggedOutput.Count <= 0)) { return null; } List value = new List(); Dictionary map = new Dictionary(); foreach (TaggedObject obj in results.TaggedOutput) { string groupName = obj["group"]; Group group = null; if (map.ContainsKey(groupName)) { group = map[groupName]; } else { group = new Group(groupName); int v = -1; if (obj.ContainsKey("maxResults")) { int.TryParse(obj["maxResults"], out v); } group.MaxResults = v; v = -1; if (obj.ContainsKey("maxScanRows")) { int.TryParse(obj["maxScanRows"], out v); } group.MaxScanRows = v; v = -1; if (obj.ContainsKey("maxLockTime")) { int.TryParse(obj["maxLockTime"], out v); } group.MaxLockTime = v; v = -1; if (obj.ContainsKey("timeout")) { int.TryParse(obj["timeout"], out v); } group.TimeOut = v; v = -1; if (obj.ContainsKey("passTimeout")) { int.TryParse(obj["passTimeout"], out v); } group.MaxResults = v; map[groupName] = group; value.Add(group); } string user = null; if (obj.ContainsKey("user")) { user = obj["user"]; } else { // no user name, can't continue } if ((obj.ContainsKey("isUser")) && (obj["isUser"] == "1")) { if (group.UserNames == null) { group.UserNames = new List(); } group.UserNames.Add(user); } if ((obj.ContainsKey("isOwner")) && (obj["isOwner"] == "1")) { if (group.OwnerNames == null) { group.OwnerNames = new List(); } group.OwnerNames.Add(user); } if ((obj.ContainsKey("isSubGroup")) && (obj["isSubGroup"] == "1")) { if (group.SubGroups == null) { group.SubGroups = new List(); } group.SubGroups.Add(user); } } return value; } else { P4Exception.Throw(results.ErrorList); } return null; } /// /// Delete a group from the repository /// /// The group to be deleted /// The -a flag is needed to delete /// a group when the user is an owner but not a superuser /// /// To delete the group 'Mygroup' when the user is a superuser: /// /// /// string targetGroup = "Mygroup"; /// Group group = new Group(); /// group.Id = targetGroup; /// _repository.DeleteGroup(group, null); /// /// /// To delete the group 'Mygroup' when the user is an owner but not a superuser: /// /// /// string targetGroup = "Mygroup"; /// Group group = new _repository.GetGroup(targetGroup); /// GroupCmdOptions opts = new GroupCmdOptions(GroupCmdFlags.OwnerAccess); /// _repository.DeleteGroup(group, opts); /// /// /// /// public void DeleteGroup(Group group, Options options) { if (group == null) { throw new ArgumentNullException("group"); } P4Command cmd = new P4Command(this, "group", true, group.Id); if (options == null) { options = new Options(); } options["-d"] = null; P4CommandResult results = cmd.Run(options); if (results.Success == false) { P4Exception.Throw(results.ErrorList); } } } }