Merge pull request #46 from GoodOlClint/fix/issues-43-44-45

fix: resolve issues #43, #44, #45
This commit is contained in:
GoodOlClint
2026-03-27 10:36:40 -05:00
committed by GitHub
5 changed files with 35 additions and 9 deletions
@@ -23,10 +23,20 @@ public class PveApiToken
/// <summary> /// <summary>
/// The full token identifier in "user@realm!tokenid" format, e.g., "admin@pam!automation". /// The full token identifier in "user@realm!tokenid" format, e.g., "admin@pam!automation".
/// Only populated by New-PveApiToken; not returned by the list/get endpoints. /// Computed from UserId and TokenId. The "full-tokenid" JSON field from New-PveApiToken
/// is captured by <see cref="RawFullTokenId"/> for deserialization, but this property
/// always returns a computed value so it works for list/get endpoints too.
/// </summary>
public string FullTokenId =>
string.IsNullOrEmpty(UserId) || string.IsNullOrEmpty(TokenId)
? RawFullTokenId ?? string.Empty
: $"{UserId}!{TokenId}";
/// <summary>
/// Raw "full-tokenid" value from the API (only present on token creation responses).
/// </summary> /// </summary>
[JsonProperty("full-tokenid")] [JsonProperty("full-tokenid")]
public string? FullTokenId { get; set; } public string? RawFullTokenId { get; set; }
/// <summary> /// <summary>
/// The token secret UUID. <b>Only present on creation</b> — store it immediately, /// The token secret UUID. <b>Only present on creation</b> — store it immediately,
@@ -642,6 +642,7 @@ namespace PSProxmoxVE.Core.Services
/// <param name="roles">Comma-separated role IDs.</param> /// <param name="roles">Comma-separated role IDs.</param>
/// <param name="users">Comma-separated user IDs.</param> /// <param name="users">Comma-separated user IDs.</param>
/// <param name="groups">Comma-separated group names.</param> /// <param name="groups">Comma-separated group names.</param>
/// <param name="tokens">Comma-separated API token IDs (user@realm!tokenid).</param>
/// <param name="propagate">Whether to propagate the permission to sub-paths.</param> /// <param name="propagate">Whether to propagate the permission to sub-paths.</param>
/// <param name="delete">If true, removes the specified ACL entries.</param> /// <param name="delete">If true, removes the specified ACL entries.</param>
public void SetPermission( public void SetPermission(
@@ -650,6 +651,7 @@ namespace PSProxmoxVE.Core.Services
string roles, string roles,
string? users = null, string? users = null,
string? groups = null, string? groups = null,
string? tokens = null,
bool propagate = true, bool propagate = true,
bool delete = false) bool delete = false)
{ {
@@ -666,6 +668,7 @@ namespace PSProxmoxVE.Core.Services
}; };
if (!string.IsNullOrEmpty(users)) formData["users"] = users!; if (!string.IsNullOrEmpty(users)) formData["users"] = users!;
if (!string.IsNullOrEmpty(groups)) formData["groups"] = groups!; if (!string.IsNullOrEmpty(groups)) formData["groups"] = groups!;
if (!string.IsNullOrEmpty(tokens)) formData["tokens"] = tokens!;
IPveHttpClient client = _injectedClient ?? new PveHttpClient(session); IPveHttpClient client = _injectedClient ?? new PveHttpClient(session);
try try
@@ -48,10 +48,14 @@ namespace PSProxmoxVE.Cmdlets.Connection
[Parameter(Mandatory = false, HelpMessage = "Skip TLS certificate validation.")] [Parameter(Mandatory = false, HelpMessage = "Skip TLS certificate validation.")]
public SwitchParameter SkipCertificateCheck { get; set; } public SwitchParameter SkipCertificateCheck { get; set; }
/// <summary>When specified, writes the resulting PveSession object to the pipeline.</summary> /// <summary>Deprecated — session is now always output. Kept for backwards compatibility.</summary>
[Parameter(Mandatory = false, HelpMessage = "Output the session object to the pipeline.")] [Parameter(Mandatory = false, DontShow = true)]
public SwitchParameter PassThru { get; set; } public SwitchParameter PassThru { get; set; }
/// <summary>When specified, suppresses the session object from the pipeline output.</summary>
[Parameter(Mandatory = false, HelpMessage = "Do not output the session object to the pipeline.")]
public SwitchParameter Quiet { get; set; }
protected override void ProcessRecord() protected override void ProcessRecord()
{ {
PveSession session; PveSession session;
@@ -122,7 +126,7 @@ namespace PSProxmoxVE.Cmdlets.Connection
WriteVerbose($"Connected to {Server}:{Port} as {session.AuthMode} (PVE {session.ServerVersion})."); WriteVerbose($"Connected to {Server}:{Port} as {session.AuthMode} (PVE {session.ServerVersion}).");
if (PassThru.IsPresent) if (!Quiet.IsPresent)
WriteObject(session); WriteObject(session);
} }
} }
@@ -27,9 +27,10 @@ namespace PSProxmoxVE.Cmdlets.Users
[Parameter(Mandatory = true, Position = 2, HelpMessage = "The role to assign (e.g. Administrator).")] [Parameter(Mandatory = true, Position = 2, HelpMessage = "The role to assign (e.g. Administrator).")]
public string Role { get; set; } = string.Empty; public string Role { get; set; } = string.Empty;
/// <summary>The ACL entry type: "user" or "group".</summary> /// <summary>The ACL entry type: "user", "token", or "group". When set to "user", API tokens
[Parameter(Mandatory = false, HelpMessage = "ACL entry type: user or group.")] /// (UgId containing "!") are automatically detected and sent as the "tokens" parameter.</summary>
[ValidateSet("user", "group", IgnoreCase = true)] [Parameter(Mandatory = false, HelpMessage = "ACL entry type: user, token, or group.")]
[ValidateSet("user", "token", "group", IgnoreCase = true)]
public string Type { get; set; } = "user"; public string Type { get; set; } = "user";
/// <summary>Whether to propagate this ACL to child paths.</summary> /// <summary>Whether to propagate this ACL to child paths.</summary>
@@ -58,6 +59,8 @@ namespace PSProxmoxVE.Cmdlets.Users
if (string.Equals(Type, "group", System.StringComparison.OrdinalIgnoreCase)) if (string.Equals(Type, "group", System.StringComparison.OrdinalIgnoreCase))
data["groups"] = UgId; data["groups"] = UgId;
else if (string.Equals(Type, "token", System.StringComparison.OrdinalIgnoreCase) || UgId.Contains("!"))
data["tokens"] = UgId;
else else
data["users"] = UgId; data["users"] = UgId;
@@ -94,12 +94,18 @@ Describe 'Connect-PveServer' {
Should -Be ([System.Management.Automation.SwitchParameter]) Should -Be ([System.Management.Automation.SwitchParameter])
} }
It 'Should have a PassThru switch parameter' { It 'Should have a PassThru switch parameter (deprecated, hidden)' {
$script:Cmd.Parameters.ContainsKey('PassThru') | Should -BeTrue $script:Cmd.Parameters.ContainsKey('PassThru') | Should -BeTrue
$script:Cmd.Parameters['PassThru'].ParameterType | $script:Cmd.Parameters['PassThru'].ParameterType |
Should -Be ([System.Management.Automation.SwitchParameter]) Should -Be ([System.Management.Automation.SwitchParameter])
} }
It 'Should have a Quiet switch parameter' {
$script:Cmd.Parameters.ContainsKey('Quiet') | Should -BeTrue
$script:Cmd.Parameters['Quiet'].ParameterType |
Should -Be ([System.Management.Automation.SwitchParameter])
}
It 'Credential and ApiToken should belong to different parameter sets' { It 'Credential and ApiToken should belong to different parameter sets' {
$credSets = $script:Cmd.Parameters['Credential'].ParameterSets.Keys $credSets = $script:Cmd.Parameters['Credential'].ParameterSets.Keys
$tokenSets = $script:Cmd.Parameters['ApiToken'].ParameterSets.Keys $tokenSets = $script:Cmd.Parameters['ApiToken'].ParameterSets.Keys