Skip to content

Commit 8130aca

Browse files
author
Azure DevOps Pipeline
committed
Triggered by OmadaWeb.PS Create Artifact 20251020.1.
1 parent 3a5361d commit 8130aca

12 files changed

+798
-127
lines changed

Build/build.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#Requires -Version 7.0
22
#Requires -PSEdition Core
3-
[cmdletbinding()]
3+
[CmdletBinding()]
44
param(
55
[string[]]$Task = 'default',
66
[string[]]$BuildVersion = ""

Build/psakeBuild.ps1

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Properties {
1010
}
1111

1212

13-
Task default -depends Analyze, Test, Build, ImportModule
13+
Task default -depends Analyze, Build, ImportModule, Test
1414
Task DeployOnly -depends Build, Deploy
1515

1616
Task Analyze {
@@ -27,18 +27,7 @@ Task Analyze {
2727
}
2828
}
2929

30-
Task Test -depends Analyze {
31-
$Tests = Get-ChildItem ..\Tests -Filter *.Tests.ps1 -Recurse
32-
if ($Tests.Count -eq 0) {
33-
'No tests found' | Write-Warning
34-
}
35-
foreach ($Test in $Tests) {
36-
"{0} - Running tests from file: {1}" -f $MyInvocation.MyCommand, $Test.FullName | Write-Host -ForegroundColor Magenta
37-
. $Test.FullName
38-
}
39-
}
40-
41-
Task Build -depends Test {
30+
Task Build -depends Analyze {
4231

4332
$FormattingSettings = @{
4433
IncludeRules = @("PSPlaceOpenBrace", "PSUseConsistentIndentation", "PsAvoidUsingCmdletAliases", "PSUseConsistentWhitespace", "PSAlignAssignmentStatement", "PSPlaceCloseBrace")
@@ -100,6 +89,15 @@ Task Build -depends Test {
10089
return $HeaderRow
10190

10291
}
92+
93+
#Read Functions
94+
$Public = @(Get-ChildItem -Path $ModuleSource\Public\*.ps1 -Recurse)
95+
$Private = @(Get-ChildItem -Path $ModuleSource\Private\*.ps1)
96+
$PublicModules = @()
97+
foreach ($import in $Public) {
98+
$PublicModules += ($import.BaseName)
99+
}
100+
103101
$ModulePsd1 = Import-PowerShellDataFile (Join-Path $ModuleSource -ChildPath ("{0}.psd1" -f $ModuleName))
104102
$ModulePsd1.FunctionsToExport = $PublicModules
105103

@@ -192,16 +190,11 @@ Task Build -depends Test {
192190
}
193191
elseif ($ExcludeRegion -and !$FunctionsAdded) {
194192
"Adding functions" | Write-Host -ForegroundColor Magenta
195-
$PublicModules = @()
196-
$Public = @(Get-ChildItem -Path $ModuleSource\Public\*.ps1 -Recurse)
197-
$Private = @(Get-ChildItem -Path $ModuleSource\Private\*.ps1)
198-
199193
$ModuleContent += "#region public functions`n"
200194
foreach ($import in $Public) {
201195
$Content = Get-Content $import.FullName -Encoding UTF8 | Where-Object { $_ -notmatch '^\s*#requires' -and $_ -notmatch '^\s*#' }
202196
$ModuleContent += $Content.Trim() -join "`n"
203197
$ModuleContent += "`n`n"
204-
$PublicModules += $import.Basename
205198
}
206199
$ModuleContent += "#endregion`n`n#region private functions`n"
207200
foreach ($import in $Private) {
@@ -253,7 +246,7 @@ Task ImportModule -depends Build {
253246
$Test = Import-Module "$OutputDir\$ModuleName.psd1" -Force -PassThru
254247
if ($Test) {
255248
"Module loaded successfully" | Write-Verbose
256-
Remove-Module -Name $Test.Name -Force
249+
Remove-Module -name $Test.Name -Force
257250
}
258251
else {
259252
"Module failed to load" | Write-Error -ErrorAction Stop
@@ -274,4 +267,43 @@ Task ImportModule -depends Build {
274267
Write-Host "Error importing module: $_" -ForegroundColor Red
275268
$PSCmdlet.ThrowTerminatingError($PSItem)
276269
}
277-
}
270+
}
271+
272+
273+
Task Test -depends ImportModule {
274+
$Tests = Get-ChildItem ..\Tests -Filter *.Tests.ps1 -Recurse
275+
if ($Tests.Count -eq 0) {
276+
'No tests found' | Write-Warning
277+
}
278+
foreach ($Test in $Tests) {
279+
"{0} - Running tests from file: {1}" -f $MyInvocation.MyCommand, $Test.FullName | Write-Host -ForegroundColor Magenta
280+
. $Test.FullName -ModulePath (Join-Path -Path $OutputDir -ChildPath ("{0}.psm1" -f $ModuleName))
281+
}
282+
}
283+
284+
# Task Test {
285+
286+
# $ScriptBlock = {
287+
# param(
288+
# [string]$OutputDir,
289+
# [string]$ModuleName,
290+
# [string]$BasePath
291+
# )
292+
# Set-Location -Path $BasePath
293+
# $Tests = Get-ChildItem ..\Tests -Filter *.Tests.ps1 -Recurse
294+
# if ($Tests.Count -eq 0) {
295+
# 'No tests found' | Write-Warning
296+
# }
297+
# foreach ($Test in $Tests) {
298+
# "{0} - Running tests from file: {1}" -f $MyInvocation.MyCommand, $Test.FullName | Write-Host -ForegroundColor Magenta
299+
# . $Test.FullName -ModulePath (Join-Path -Path $OutputDir -ChildPath ("{0}.psm1" -f $ModuleName))
300+
# }
301+
# }
302+
# Wait-Debugger
303+
# $BasePath = $PSScriptRoot
304+
# "Run function tests on Windows PowerShell" | Write-Host -ForegroundColor Magenta
305+
# & (Get-Command powershell.exe).Source -NoLogo -Command $ScriptBlock -Args @($OutputDir, $ModuleName, $BasePath) -ExecutionPolicy Unrestricted
306+
# "Run function tests on PowerShell Core" | Write-Host -ForegroundColor Magenta
307+
# & (Get-Command pwsh.exe).Source -NoLogo -Command $ScriptBlock -Args @($OutputDir, $ModuleName, $BasePath) -ExecutionPolicy Unrestricted
308+
309+
# }

OmadaWeb.PS/OmadaWeb.PS.psm1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ elseif ($null -ne $MsEdgeFixedRunTimePath -and (Test-Path $MsEdgeFixedRunTimePat
227227
"{0} - Using fixed MsEdgeWebView2 runtime: '{1}'" -f $MyInvocation.MyCommand, $Script:InstalledEdgeWebView2Path | Write-Verbose
228228
}
229229
else {
230-
"MsEdgeWebView2.exe was not found in the expected folder: '{0}'. It is needed when using WebView2. The module will try to locate it automatically.`nIn case you get an error you can download the fixed version from 'https://developer.microsoft.com/en-us/Microsoft-edge/webview2/' (x86/x64) and follow these steps.`n1. Download the cab file`n2. Open a CMD commandline and run the following command (replace the variables <var> accordingly):`n set TARGETDIR=%LOCALAPPDATA\OmadaWeb.PS\Bin\WebView2RunTime\<win-x86 or win-x64>;`n mkdir %TARGETDIR%;'`n expand `"<downloaded cab file path>`" -F:* `"%TARGETDIR%`";" -f $InstalledEdgeBasePath | Write-Warning
230+
"MsEdgeWebView2.exe was not found in the expected folder: '{0}'. It is needed when using WebView2. The module will try to locate it automatically.`nIn case you get an error you can download the fixed version from 'https://developer.microsoft.com/en-us/Microsoft-edge/webview2/' (x86/x64) and follow these steps.`n1. Download the cab file`n2. Open a CMD commandline and run the following command (replace the variables <var> accordingly):`n set TARGETDIR=%LOCALAPPDATA\OmadaWeb.PS\Bin\WebView2RunTime\<win-x86 or win-x64>;`n mkdir %TARGETDIR%;`n expand `"<downloaded cab file path>`" -F:* `"%TARGETDIR%`";" -f $InstalledEdgeBasePath | Write-Warning
231231
$Script:InstalledEdgeWebView2Path = $null
232232
}
233233

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
function Get-DataFromWebDriver {
2+
[CmdletBinding()]
3+
param(
4+
[string]$EdgeProfile,
5+
[switch]$InPrivate
6+
)
7+
8+
"{0} - Invoking data from WebDriver" -f $MyInvocation.MyCommand | Write-Verbose
9+
10+
$AuthCookie = $null
11+
12+
"Opening Edge to retrieve authentication cookie" | Write-Host
13+
try {
14+
$Script:LoginRetryCount++
15+
"`n{0} - Login try {1} of max {2}" -f $MyInvocation.MyCommand, $Script:LoginRetryCount, $Script:MaxLoginRetries | Write-Verbose
16+
17+
$EdgeDriver = Start-EdgeDriver -InPrivate:$InPrivate.IsPresent -EdgeProfile $EdgeProfile
18+
19+
Start-EdgeDriverLogin
20+
21+
$AgentString = $EdgeDriver.ExecuteScript("return navigator.userAgent")
22+
23+
Start-Sleep -Seconds 1
24+
$LoginMessageShown = $false
25+
$MfaRequestDisplayed = $false
26+
$PhoneLinkActive = $false
27+
if ((Get-Process | Where-Object { $_.ProcessName -eq "PhoneExperienceHost" } | Measure-Object).Count -gt 0) {
28+
$PhoneLinkActive = $true
29+
}
30+
do {
31+
if (-not $LoginMessageShown) {
32+
Write-Host "`r`nBrowser opened, please login! Waiting for login." -NoNewline -ForegroundColor Yellow
33+
if ($Script:Credential -and ![string]::IsNullOrWhiteSpace($Script:Credential.UserName)) {
34+
" Execute automated login steps for user: {0}" -f $Script:Credential.UserName.Trim() | Write-Host -ForegroundColor Yellow -NoNewline
35+
}
36+
$LoginMessageShown = $true
37+
}
38+
39+
Write-Host "." -NoNewline -ForegroundColor Yellow
40+
Start-Sleep -Milliseconds 500
41+
42+
if ($Script:Credential -and ![string]::IsNullOrWhiteSpace($Script:Credential.UserName.Trim())) {
43+
44+
if ($EdgeDriver.url -like "https://login.microsoftonline.com/*") {
45+
try {
46+
$UserNameElementId = "i0116"
47+
$PasswordElementId = "i0118"
48+
$SubmitButton = "idSIButton9"
49+
#$DisplayNameElement = "displayName"
50+
$CantAccessAccountId = "cantAccessAccount"
51+
$MfaElementId = "idRichContext_DisplaySign"
52+
$MfaRetryId1 = "idA_SAASTO_Resend"
53+
$MfaRetryId2 = "idA_SAASDS_Resend"
54+
$ButtonBackId = "idBtn_Back"
55+
$ButtonSubmitId = "idSIButton9"
56+
57+
$Elements = $EdgeDriver.FindElements([OpenQA.Selenium.By]::XPath("//*[@id]"))
58+
$IdAttributes = $Elements.GetAttribute("id")
59+
60+
if ($IdAttributes -contains $UserNameElementId `
61+
-and $IdAttributes -contains $PasswordElementId `
62+
-and $IdAttributes -notcontains $ButtonBackId `
63+
-and $IdAttributes -contains $ButtonSubmitId `
64+
-and $IdAttributes -contains $CantAccessAccountId `
65+
-and $EdgeDriver.FindElement([OpenQA.Selenium.By]::Id($ButtonSubmitId)).ComputedAccessibleLabel -eq "Next" `
66+
) {
67+
Start-Sleep -Milliseconds 500
68+
"Enter username" | Write-Verbose
69+
$EdgeDriver.FindElements([OpenQA.Selenium.By]::Id($UserNameElementId))[0].SendKeys($Script:Credential.UserName.Trim())
70+
$EdgeDriver.FindElement([OpenQA.Selenium.By]::Id($SubmitButton)).Click()
71+
}
72+
73+
if ($IdAttributes -notcontains $UserNameElementId `
74+
-and $IdAttributes -contains $PasswordElementId `
75+
-and $IdAttributes -contains $ButtonSubmitId `
76+
-and $IdAttributes -notcontains $CantAccessAccountId `
77+
-and $EdgeDriver.FindElement([OpenQA.Selenium.By]::Id($ButtonSubmitId)).ComputedAccessibleLabel -eq "Sign in"
78+
) {
79+
"Enter password" | Write-Verbose
80+
$EdgeDriver.FindElements([OpenQA.Selenium.By]::Id($PasswordElementId))[0].SendKeys($Script:Credential.GetNetworkCredential().Password)
81+
$EdgeDriver.FindElement([OpenQA.Selenium.By]::Id($SubmitButton)).Click()
82+
}
83+
84+
if ($IdAttributes -notcontains $UserNameElementId `
85+
-and $IdAttributes -notcontains $PasswordElementId `
86+
-and $IdAttributes -contains $SelectUserElementId
87+
) {
88+
"Select logged-in account" | Write-Verbose
89+
if ($AccountElement.GetAttribute("data-test-id") -eq $Script:Credential.UserName.Trim()) {
90+
$AccountElement.Click()
91+
}
92+
}
93+
94+
if ($IdAttributes -notcontains $UserNameElementId `
95+
-and $IdAttributes -notcontains $PasswordElementId `
96+
-and $IdAttributes -notcontains $SelectUserElementId `
97+
-and $IdAttributes -contains $ButtonBackId `
98+
-and $IdAttributes -contains $ButtonSubmitId `
99+
-and $EdgeDriver.FindElement([OpenQA.Selenium.By]::Id($ButtonBackId)).ComputedAccessibleLabel -eq "No" `
100+
-and $EdgeDriver.FindElement([OpenQA.Selenium.By]::Id($ButtonSubmitId)).ComputedAccessibleLabel -eq "Yes" `
101+
) {
102+
"Decline Stay signed in? " | Write-Verbose
103+
$EdgeDriver.FindElement([OpenQA.Selenium.By]::Id($ButtonBackId)).Click()
104+
}
105+
106+
if ($IdAttributes -notcontains $UserNameElementId `
107+
-and $IdAttributes -notcontains $PasswordElementId `
108+
-and $IdAttributes -notcontains $ButtonBackId `
109+
-and ($EdgeDriver.FindElements([OpenQA.Selenium.By]::XPath("//*[@data-test-id]")) | Measure-Object).Count -gt 0) {
110+
111+
"Select logged-in user " | Write-Verbose
112+
$EdgeDriver.FindElements([OpenQA.Selenium.By]::XPath("//*[@data-test-id]")) | ForEach-Object {
113+
if ($_.GetAttribute("data-test-id") -eq $Script:Credential.UserName.Trim()) {
114+
$_.Click()
115+
}
116+
}
117+
}
118+
119+
if ($MfaRequestDisplayed -ne $true `
120+
-and $IdAttributes -notcontains $UserNameElementId `
121+
-and $IdAttributes -notcontains $PasswordElementId `
122+
-and $IdAttributes -contains $MFAElementId `
123+
-and $IdAttributes -notcontains $MfaRetryId `
124+
-and ($EdgeDriver.FindElements([OpenQA.Selenium.By]::XPath("//*[@data-test-id]")) | Measure-Object).Count -eq 0
125+
) {
126+
$Message = "`nWaiting for your approve this sign-in request."
127+
if ($null -ne $EdgeDriver.FindElements([OpenQA.Selenium.By]::Id($MfaElementId)).Text) {
128+
if ($PhoneLinkActive) {
129+
$Message = "{0}. {1} (This value is now in your clipboard so you can paste it into your Authenticator app using PhoneLink)." -f $Message.TrimEnd("."), $EdgeDriver.FindElements([OpenQA.Selenium.By]::Id($MfaElementId)).Text
130+
$EdgeDriver.FindElements([OpenQA.Selenium.By]::Id($MfaElementId)).Text | Clip
131+
}
132+
else {
133+
$Message = "{0}. {1}" -f $Message.TrimEnd("."), $EdgeDriver.FindElements([OpenQA.Selenium.By]::Id($MfaElementId)).Text
134+
}
135+
}
136+
$Message | Write-Host -ForegroundColor Yellow
137+
$MfaRequestDisplayed = $true
138+
}
139+
140+
if ($MfaRequestDisplayed `
141+
-and $IdAttributes -notcontains $UserNameElementId `
142+
-and $IdAttributes -notcontains $PasswordElementId `
143+
-and $IdAttributes -notcontains $MFAElementId `
144+
-and (
145+
$IdAttributes -contains $MfaRetryId1 `
146+
-or $IdAttributes -contains $MfaRetryId2 )`
147+
-and ($EdgeDriver.FindElements([OpenQA.Selenium.By]::XPath("//*[@data-test-id]")) | Measure-Object).Count -eq 0
148+
) {
149+
"`nMFA failed! Please retry!" | Write-Warning
150+
$MfaRequestDisplayed = $false
151+
$LoginMessageShown = $false
152+
}
153+
}
154+
catch {}
155+
}
156+
}
157+
158+
$EdgeDriverHost = "-1"
159+
$OmadaWebBaseHost = "-2"
160+
$EdgeDriverAbsolutePath = $null
161+
if ($null -ne $EdgeDriver.url) {
162+
$EdgeDriverHost = [System.Uri]::new($EdgeDriver.url).Host
163+
$EdgeDriverAbsolutePath = [System.Uri]::new($EdgeDriver.url).AbsolutePath
164+
$OmadaWebBaseHost = [System.Uri]::new($Script:OmadaWebBaseUrl).Host
165+
}
166+
167+
if ($OmadaWebBaseHost -ne $EdgeDriverHost -and $EdgeDriverAbsolutePath -ne "/home" ) {
168+
if ($null -eq $EdgeDriver -or ($EdgeDriver.WindowHandles | Measure-Object).Count -le 0) {
169+
throw "EdgeDriver window is closed"
170+
}
171+
}
172+
else {
173+
"{0} - Logged in to Omada Web" -f $MyInvocation.MyCommand | Write-Verbose
174+
$AuthCookie = $EdgeDriver.Manage().Cookies.AllCookies | Where-Object { $_.Name -eq 'oisauthtoken' }
175+
break
176+
}
177+
}
178+
while ($Script:LoginRetryCount -le $Script:MaxLoginRetries)
179+
"{0} (Line {1}): {2}" -f $MyInvocation.MyCommand, $MyInvocation.ScriptLineNumber, $$ | Write-Verbose
180+
181+
#$CredentialsEntered = $false
182+
Close-EdgeDriver
183+
if ($null -ne $AuthCookie) {
184+
$Script:LoginRetryCount = 0
185+
return $AuthCookie, $AgentString
186+
}
187+
else {
188+
"Could not authenticate to '{0}" -f $Script:OmadaWebBaseUrl | Write-Error -ErrorAction "Stop"
189+
}
190+
}
191+
catch {
192+
"invalid session id: session deleted as the browser has closed the connection" -match "as the browser has closed the connection"
193+
194+
if (
195+
$_.Exception.Message -like '*Exception calling "ExecuteScript" with "*" argument(s): "no such window: target window already closed*"' -or
196+
$_.Exception.Message -like '*Exception calling "Window" with "*" argument(s): "no such window*' -or
197+
$_.Exception.Message -like "*EdgeDriver window is closed*" -or
198+
$_.Exception.Message -like 'Exception calling "Window" with "*" argument(s): *invalid session id*'
199+
) {
200+
if ($Script:LoginRetryCount -ge $Script:MaxLoginRetries) {
201+
Close-EdgeDriver
202+
"`nLogin try count ({0}) exceeded! Cannot continue!" -f $Script:MaxLoginRetries | Write-Error -ErrorAction "Stop" -Category AuthenticationError
203+
break
204+
}
205+
206+
"" | Write-Host
207+
"Edge WebDriver was unable to complete the process to retrieve a cookie. Re-open Edge WebDriver in 2 seconds!" | Write-Host -ForegroundColor Yellow
208+
Start-Sleep -Seconds 2
209+
$LoginMessageShown = $false
210+
try {
211+
Close-EdgeDriver
212+
}
213+
catch {}
214+
Get-DataFromWebDriver -InPrivate:$InPrivate.IsPresent -EdgeProfile $EdgeProfile
215+
}
216+
else {
217+
$PSCmdlet.ThrowTerminatingError($PSItem)
218+
}
219+
Close-EdgeDriver
220+
$PSCmdlet.ThrowTerminatingError($PSItem)
221+
}
222+
}

0 commit comments

Comments
 (0)