Jump to content

P4API.NET How to check if a user/group can access a file on a given host.

protects .net

  • Please log in to reply
4 replies to this topic

#1 laurent_tr



  • Members
  • PipPip
  • 10 posts

Posted 10 June 2019 - 07:34 AM

Hello all,

I would like to verify if a given user has access to a given file without having to interpret the whole protection table.
It is said from the documentation of the "p4 protects" that this could be done by specifying the -M parameter ; which I do not manage to find an equivalent in the .NET API. There is the flag GetProtectionEntriesCmdFlags.AccessSummary which is equivalent to -m.

Anyhow, I have tried to use this .NET flag, and the API keeps throwing a KeyNotFoundException, without any information on which key it is complaining about. The reported line number does not match any line from my Decompiler.

Here is the Exception details as reported by Visual studio
  Message=The given key was not present in the dictionary.
   at System.ThrowHelper.ThrowKeyNotFoundException()
   at Perforce.P4.Repository.GetProtectionEntries(IList`1 filespecs, Options options) in c:\tmp\99902514\P4.NET\r19.1\p4api.net\p4api.net\Repository.cs:line 2830
   at ...GetAccessSummary() in ...Test.cs:line 316
   at ...MainClass.Main(String[] args) in ...MainClass.cs:line 9

Do you have any suggestion about where the cause could be ?

Here is the snippet of code that reproduces the exception. I am using the version 2019.1.177.4442.
internal static int GetAccessSummary()
	// initialize the connection variables
	// note: this is a connection without using a password
	var uri = "";
	var user = "";
	var pwd = "";
	var ws_client = "admin_space";

	// define the server, repository and connection
	var server = new Server(new ServerAddress(uri));
	var repository = new Repository(server);
	var connection = repository.Connection;

	// use the connection variables for this connection
	connection.UserName = user;
	connection.Client = new Client();
	connection.Client.Name = ws_client;

	// connect to the server
	var bOk = connection.Connect(null);
	if (!bOk)
		return -1;
	var userToCheck = "";
	var opts = new GetProtectionEntriesCmdOptions(GetProtectionEntriesCmdFlags.AccessSummary, null, userToCheck, null);
	var res = repository.GetProtectionEntries(new List<FileSpec>()
		new FileSpec(new DepotPath(""), null, null, null)
	}, opts);

	return 0;

#2 p4bill


    Advanced Member

  • Members
  • PipPipPip
  • 217 posts

Posted 10 June 2019 - 07:52 PM

This is a bug in P4API.NET. I'll file that here in our system. Almost all variants of the p4 protects command will return protection lines, which the GetProtectionEntries method attempts to parse from tagged output. When using the -m or -M flags a single word summary of the maximum access level is reported. That results in the exception you are seeing. Until this is fixed in P4API.NET, you can create your own command and use that. Something like this should work:

	 public ProtectionMode GetMaxProtectionAccess(IList<FileSpec> filespecs, Options options)
		 P4.P4Command protectsCmd = new P4Command(this, "protects", true, FileSpec.ToStrings(filespecs));
		 P4.P4CommandResult r = protectsCmd.Run(options);
		 if (r.Success != true)
			 return new ProtectionMode();
		 if ((r.TaggedOutput == null) || (r.TaggedOutput.Count <= 0))
			 return new ProtectionMode();
		 StringEnum<ProtectionMode> mode = null;
		 foreach (P4.TaggedObject obj in r.TaggedOutput)
			 mode = obj["permMax"];
		 return mode;

#3 laurent_tr



  • Members
  • PipPip
  • 10 posts

Posted 11 June 2019 - 06:50 AM

Hello p4bill

Thank you for your reply.
I would like to ask a side question if you don't mind.

I have noticed that p4 protects -a only returns inclusion rule, at least with the P4 .NET API, which is a little bit limiting for me.
I have a use case where I need to determine which users and groups have access to a given file (we don't have restriction on machine IP), so it is interesting for me to know all the protection rules - inclusion and exclusion that apply to a given file path.
With the current protects command, I will have to first call p4 protects -a to get all inclusion rules and then iterate over the subject of these rules and ask for the maximum access level with p4 protects -M to take into account the exclusion rules.

I know that there is GetProtectionTables() in the P4 .NET API that returns the full protection table but it is not as useful as GetProtectionEntries()
I wonder if it is useful to have p4 protects -a to return all protection rules instead of only inclusion ones.


#4 laurent_tr



  • Members
  • PipPip
  • 10 posts

Posted 11 June 2019 - 09:51 AM

Hello p4bill,

I have had a second look at the command p4 protects -a.
The Perforce API does return the exclusion rules however the method GetProtectionEntries() in .NET does not interpret it correctly as an exclusion.

In my test case, I have this kind of protection table

I have copied the GetProtectionEntries() method to be able to debug it.
When I debug it with a file in "//test/root/not_accessible_by_group2/", I receive an entry related to the rule number 11. (cf debug.PNG)

However, this entry is interpreted as an inclusion rule by the .NET library, due to the fact that the "unmap" property is not read.
I think we need a bug report for this one too.


Attached Thumbnails

  • protection table.PNG
  • debug.PNG

#5 p4bill


    Advanced Member

  • Members
  • PipPipPip
  • 217 posts

Posted 11 June 2019 - 01:40 PM

Hello laurent_tr,

Thank you for the additional feedback. I'll confirm your findings here and log the relevant issue/bug in our system.

Also tagged with one or more of these keywords: protects, .net

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users