RiverMeadow.Release.Login/RiverMeadow.Release.Login.psm1
using module '../Common/Result' Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath Common | Join-Path -ChildPath Error | Join-Path -ChildPath Error) Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath Common |Join-Path -ChildPath Wrappers | Join-Path -ChildPath Wrappers) Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath Util |Join-Path -ChildPath Util) function Invoke-RMLogin { param ( [Alias("ea")] [string] $EmailAddress, [Alias("pw")] [string] $Password, [Alias("mfavc")] [string] $MFAVerificationCode ) try { [RMReturn] $RMReturn = [RMReturn]::new() if (0 -eq $PSBoundParameters.Count) { $EmailAddress = Read-RMString -UserMessage "Enter email address" -IsRequired $true -ParameterName "Email address" $Password = Read-RMSecureString -UserMessage "Enter password" -IsRequired $true -ParameterName "Password" } elseif ([string]::IsNullOrEmpty($EmailAddress) -or [string]::IsNullOrEmpty($Password)) { $RMReturn.SetReturnCode([RMReturn]::ERROR) if ([string]::IsNullOrEmpty($EmailAddress)) { $UserMessage = "EmailAddress is required" Write-RMError -Message $UserMessage $RMReturn.AddRMError([RMError]::new($UserMessage)) } if ([string]::IsNullOrEmpty($Password)) { $UserMessage = "Password is required" Write-RMError -Message $UserMessage $RMReturn.AddRMError([RMError]::new($UserMessage)) } return $RMReturn } $Uri = Get-RMUri $Body = @{ email = $EmailAddress password = $Password } if ($MFAVerificationCode) { $Body['mfa_token'] = $MFAVerificationCode } $JsonBody = $Body | ConvertTo-Json $Headers = @{ Accept = "application/rm+json" } $Params = @{ Method = "Post" Uri = $Uri + "/login" Body = $JsonBody ContentType = "application/json" Headers = $Headers } if (Get-Variable -Name "RMContext-UserLogin" -ErrorAction SilentlyContinue) { # Delete the previous Login result before attempting a new one Remove-RMVariable } $UserLogin = Invoke-RestMethod @Params Set-Variable -Name "RMContext-UserLogin" -Value $UserLogin -Scope Global Set-Variable -Name "RMContext-ReactorURI" -Value $Uri -Scope Global Get-RMUser -UserId $UserLogin.user_id -Uri $Uri $CurrentOrg = (Get-Variable -Name "RMContext-CurrentOrganizationName").Value $CurrentProjectName = (Get-Variable -Name "RMContext-CurrentProjectName").Value Write-Output "Current Organization Name: $CurrentOrg" | Out-Host Write-Output "Current Project Name: $CurrentProjectName" | Out-Host $RMReturn.SetReturnCode([RMReturn]::SUCCESS) $RMReturn.SetOutputData(@{"Current_Organization_Name" = $CurrentOrg; ` "Current_Project_Name" = $CurrentProjectName;}) return $RMReturn } catch { $ErrorString = $PSItem.ToString() if ($ErrorString.Contains("error_code")) { $ErrorString = $ErrorString | ConvertFrom-Json if ($ErrorString.error_code -eq "mfa_token_required") { return Get-RMMFACode -InputParameter $PSBoundParameters -ErrorCode $ErrorString.error_code } else { Show-RMError -ErrorObj $PSItem return Build-RMError -ErrorObj $PSItem } } elseif ($PSVersionTable.PSVersion.Major -eq 5 -and $ErrorString.Contains("403")) { return Get-RMMFACode -InputParameter $PSBoundParameters } else { Show-RMError -ErrorObj $PSItem return Build-RMError -ErrorObj $PSItem } } } function Invoke-RMLogout { param () try { [RMReturn] $RMReturn = [RMReturn]::new() if (-not (Get-Variable -Name "RMContext-UserLogin" -ErrorAction SilentlyContinue)) { $UserMessage = "No user is currently logged in." Write-RMError -Message $UserMessage $RMReturn.SetReturnCode([RMReturn]::ERROR) $RMReturn.AddRMError([RMError]::new($UserMessage)) return $RMReturn } Remove-RMVariable Write-Output "Logout was successful." | Out-Host $RMReturn.SetReturnCode([RMReturn]::SUCCESS) return $RMReturn } catch { Show-RMError -ErrorObj $PSItem return Build-RMError -ErrorObj $PSItem } } function Get-RMUri { param() $Uri = "https://migrate.rivermeadow.com/api/v3" $RMHost = Get-RMHost if ([string]::IsNullOrEmpty($RMHost)) { # Env. variable RMHost is not set, use production URI return $Uri } if ($RMHost.Contains("http://") -or $RMHost.Contains("https://")) { $Uri = $RMHost.TrimEnd("/") + "/api/v3" } else { $Uri = "http://" + $RMHost.TrimEnd("/") + "/api/v3" } return $Uri } # Currently Pester doesn't support mocking .Net methods, so in order # to able to mock the method "GetEnvironmentVariable", we are putting it # in the wrapper method below. function Get-RMHost { param() return [Environment]::GetEnvironmentVariable('RMHost') } function Get-RMUser { param( [Parameter(Mandatory)] [string]$UserId, [Parameter(Mandatory)] [string]$Uri ) $LoginResult = Get-Variable -Name "RMContext-UserLogin" $Headers = @{ "Accept" = "application/rm+json" "X-Auth-Token" = $LoginResult.Value.token } $Params = @{ Method = "Get" Uri = $Uri + "/users/" + $UserId Headers = $Headers } $UserInfo = Invoke-RestMethod @Params Set-Variable -Name "RMContext-UserOrganizations" -Value $UserInfo.organizations -Scope Global $CurrentOrgName = Get-RMParentOrganizationNameById -OrganizationId $UserInfo.organization $CurrentProjectName = Get-RMOrganizationNameById -OrganizationId $UserInfo.organization Set-Variable -Name "RMContext-CurrentOrganizationName" -Value $CurrentOrgName -Scope Global Set-Variable -Name "RMContext-CurrentProjectName" -Value $CurrentProjectName -Scope Global Set-Variable -Name "RMContext-CurrentProjectId" -Value $UserInfo.organization -Scope Global } function Get-RMOrganizationNameById { param( [string] $OrganizationId ) $UserOrgs = Get-Variable -Name "RMContext-UserOrganizations" foreach($Org in $UserOrgs.Value) { if ($Org.id -eq $OrganizationId) { return $Org.name } } throw "No organization or project exists by the given $OrganizationId" } function Get-RMParentOrganizationIdById { param( [string] $OrganizationId ) $UserOrgs = Get-Variable -Name "RMContext-UserOrganizations" foreach($Org in $UserOrgs.Value) { if ($Org.id -eq $OrganizationId) { return $Org.parent_organization_id } } throw "No organization or project exists by the given $OrganizationId" } function Get-RMParentOrganizationNameById { param( [string] $OrganizationId ) $ParentOrgId = Get-RMParentOrganizationIdById -OrganizationId $OrganizationId $UserOrgs = Get-Variable -Name "RMContext-UserOrganizations" foreach($Org in $UserOrgs.Value) { if ($Org.id -eq $ParentOrgId) { return $Org.name } } throw "No organization or project exists by the given $OrganizationId" } function Remove-RMVariable { param() Remove-Variable -Name "RMContext-UserLogin" -Scope Global -ErrorAction SilentlyContinue Remove-Variable -Name "RMContext-UserOrganizations" -Scope Global -ErrorAction SilentlyContinue Remove-Variable -Name "RMContext-CurrentOrganizationName" -Scope Global -ErrorAction SilentlyContinue Remove-Variable -Name "RMContext-CurrentProjectName" -Scope Global -ErrorAction SilentlyContinue Remove-Variable -Name "RMContext-CurrentProjectId" -Scope Global -ErrorAction SilentlyContinue } function Get-RMMFACode { param( [hashtable] $InputParameter, [string] $ErrorCode ) if (0 -eq $InputParameter.Count) { $VerificationCode = Read-Host "We sent you the Verification Code. Please enter it here" Invoke-RMLogin -EmailAddress $EmailAddress -Password $Password -MFAVerificationCode $VerificationCode # This is an internal recursive call, no need to return an object of RMReturn from here. return } $UserMessage = "We sent you the Verification Code, please re-run this cmdlet as 'Invoke-RMLogin -EmailAddress <email address> -Password <password> -MFAVerificationCode <received verification code>'" Write-Output $UserMessage |Out-Host $RMReturn.SetReturnCode([RMReturn]::ERROR) $RMReturn.AddRMError([RMError]::new($ErrorCode, $UserMessage)) return $RMReturn } Export-ModuleMember -Function Invoke-RMLogin, Invoke-RMLogout |