Private/Credential.psm1

#!/usr/bin/env pwsh
using namespace System
using namespace System.Net

using module ./Auth.psm1

# Credential classes
# .DESCRIPTION
# Like PsCredetial class but with more strict validation
# .EXAMPLE
# $c = [credentialProvider]::new("cnpc", "12233")
# $c.GetNetworkCredential().Password -eq "12233" # True
class CredentialProvider : System.Net.NetworkCredential {
  [ValidateNotNullOrWhiteSpace()][string]$UserName
  [ValidateNotNullOrEmpty()][securestring]$Password
  CredentialProvider() {}
  CredentialProvider([string]$UserName, [string]$passw0rd) : base ($UserName, $Passw0rd) {
    [ValidateNotNullOrWhiteSpace()][string]$passw0rd = $passw0rd
    $this._SetReadOnlyProperties(@{
        UserName = $UserName
        Password = $passw0rd
      }
    )
  }
  CredentialProvider([string]$UserName, [securestring]$Password) : base ([string]$UserName, [securestring]$Password) {
    $this._SetReadOnlyProperties(@{
        UserName = $UserName
        Password = $Password
      }
    )
    [ValidateNotNullOrWhiteSpace()][string]$password = $Password
    $this._Init($UserName)
  }
  hidden [void] _SetReadOnlyProperties([hashtable]$props) {
    [ValidateNotNull()]$props = $props
    $name = $props["UserName"]; $pass = $props["Password"]
    [ValidateNotNullOrWhiteSpace()][string]$name = $name
    ($pass -is [string]) ? ([ValidateNotNullOrWhiteSpace()][string]$pass = $pass) : ([ValidateNotNullOrEmpty()][securestring]$pass = $pass)
    $this.PsObject.Properties.Add([psscriptproperty]::new("UserName", [scriptblock]::create("return '$name'"), { throw "UserName is read-only" }))
    $this.PsObject.Properties.Add([psscriptproperty]::new("Password", { return $this.SecurePassword }, { throw "Password is read-only" }))
  }
  [System.Net.NetworkCredential] GetNetworkCredential() {
    return [System.Net.NetworkCredential]::new($this.UserName, $this.Password)
  }
  [AuthStrategy] ToAuthStrategy() {
    return [AuthStrategy]::new()
  }
}

class ClientCredentialProvider : CredentialProvider {
  [string] $ClientId
  [string] $ClientSecret

  ClientCredentialProvider([string]$clientId, [string]$clientSecret) {
    $this.ClientId = $clientId
    $this.ClientSecret = $clientSecret
  }

  [AuthStrategy] ToAuthStrategy() {
    return [TokenAuthStrategy]::new("$($this.ClientId):$($this.ClientSecret)")
  }
}

class OrgsClientCredentialProvider : CredentialProvider {
  [string] $ClientId
  [string] $ClientSecret

  OrgsClientCredentialProvider([string]$clientId, [string]$clientSecret) {
    $this.ClientId = $clientId
    $this.ClientSecret = $clientSecret
  }

  [AuthStrategy] ToAuthStrategy() {
    return [BasicAuthStrategy]::new($this.ClientId, $this.ClientSecret)
  }
}