| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- # Full API test using /login and database menu queries
- $companyUrl = "http://localhost:8006"
- # Step 1: Login via /login (which is in SecurityConfig anonymous whitelist)
- Write-Host "=== Step 1: Login ==="
- $loginBody = '{"tenantCode":"T202605253515","username":"admin","password":"admin123"}'
- $loginResp = Invoke-WebRequest -Uri "$companyUrl/login" -Method POST -ContentType "application/json" -Body $loginBody -UseBasicParsing
- $loginJson = $loginResp.Content | ConvertFrom-Json
- $token = $loginJson.token
- Write-Host "Token OK, length: $($token.Length)"
- $headers = @{ Authorization = "Bearer $token" }
- # Step 2: Get menu routes via getRouters
- Write-Host "`n=== Step 2: Get Routers ==="
- $routesResp = Invoke-WebRequest -Uri "$companyUrl/getRouters" -Method GET -Headers $headers -UseBasicParsing
- $routesJson = $routesResp.Content | ConvertFrom-Json
- Write-Host "getRouters code: $($routesJson.code)"
- # Recursive extract perms from menu tree
- function Extract-Perms {
- param($menuList)
- $results = @()
- foreach ($menu in $menuList) {
- if ($menu.perms -and $menu.perms.Trim() -ne "") {
- $results += $menu.perms
- }
- if ($menu.children -and $menu.children.Count -gt 0) {
- $results += Extract-Perms -menuList $menu.children
- }
- }
- return $results
- }
- $allPerms = Extract-Perms -menuList $routesJson.data
- Write-Host "Perms from getRouters: $($allPerms.Count)"
- # Step 3: Also get menu list from system/menu/list (has more detail including buttons)
- Write-Host "`n=== Step 3: Get Menu List ==="
- try {
- $menuResp = Invoke-WebRequest -Uri "$companyUrl/system/menu/list" -Method GET -Headers $headers -UseBasicParsing
- $menuJson = $menuResp.Content | ConvertFrom-Json
- Write-Host "system/menu/list code: $($menuJson.code), total: $($menuJson.total)"
-
- # Extract perms from menu list
- $menuPerms = @()
- foreach ($row in $menuJson.rows) {
- if ($row.perms -and $row.perms.Trim() -ne "") {
- $menuPerms += $row.perms
- }
- }
- Write-Host "Perms from system/menu/list: $($menuPerms.Count)"
- } catch {
- Write-Host "system/menu/list error: $($_.Exception.Message)"
- $menuPerms = @()
- }
- # Merge all perms
- $allPerms = $allPerms + $menuPerms | Sort-Object -Unique
- Write-Host "`nTotal unique perms: $($allPerms.Count)"
- # Step 4: Convert perms to API paths
- # perms format: module:entity:action -> /module/entity/action
- $apiPaths = @{}
- foreach ($perm in $allPerms) {
- if ($perm -match "^\s*$") { continue }
- $parts = $perm -split ":"
- if ($parts.Count -ge 3) {
- $mod = $parts[0]
- $ent = $parts[1]
- $act = $parts[2]
- $p = "/$mod/$ent/$act"
- if (-not $apiPaths.ContainsKey($p)) { $apiPaths[$p] = $perm }
- } elseif ($parts.Count -eq 2) {
- $mod = $parts[0]
- $ent = $parts[1]
- $p = "/$mod/$ent/list"
- if (-not $apiPaths.ContainsKey($p)) { $apiPaths[$p] = $perm }
- }
- }
- Write-Host "Total unique API paths from perms: $($apiPaths.Count)"
- # Step 5: Also extract component paths from menus (page routes)
- Write-Host "`n=== Step 5: Extract page routes ==="
- $pagePaths = @{}
- function Extract-PageRoutes {
- param($menuList)
- foreach ($menu in $menuList) {
- if ($menu.path -and $menu.path -ne "" -and $menu.component -and $menu.component -ne "") {
- $pagePaths[$menu.path] = $menu.component
- }
- if ($menu.children -and $menu.children.Count -gt 0) {
- Extract-PageRoutes -menuList $menu.children
- }
- }
- }
- Extract-PageRoutes -menuList $routesJson.data
- Write-Host "Page routes: $($pagePaths.Count)"
- # Step 6: Now scan saasadminui src/api for ALL API URLs
- Write-Host "`n=== Step 6: Scan saasadminui src/api for URLs ==="
- $apiFiles = Get-ChildItem -Path "d:\ylrz\saasadminui\src\api" -Recurse -Filter "*.js"
- $frontendApis = @{}
- foreach ($file in $apiFiles) {
- $content = Get-Content $file.FullName -Raw -Encoding UTF8
- # Match url patterns: url: '/xxx/yyy/zzz' or url: "/xxx/yyy/zzz"
- $matches = [regex]::Matches($content, "url:\s*['`"]([^'`"]+)['`"]")
- foreach ($m in $matches) {
- $url = $m.Groups[1].Value
- # Remove template variables like ${xxx}
- $cleanUrl = $url -replace '\$\{[^}]+\}', '1'
- if (-not $frontendApis.ContainsKey($cleanUrl)) {
- $frontendApis[$cleanUrl] = $file.Name
- }
- }
- }
- Write-Host "Frontend API URLs found: $($frontendApis.Count)"
- # Step 7: Test ALL unique API paths (from perms + frontend)
- Write-Host "`n=== Step 7: Test all API endpoints ==="
- # Merge all paths
- $testPaths = @{}
- foreach ($p in $apiPaths.Keys) { if (-not $testPaths.ContainsKey($p)) { $testPaths[$p] = "perms:$($apiPaths[$p])" } }
- foreach ($p in $frontendApis.Keys) {
- if (-not $testPaths.ContainsKey($p)) { $testPaths[$p] = "frontend:$($frontendApis[$p])" }
- }
- Write-Host "Total unique paths to test: $($testPaths.Count)"
- $ok = [System.Collections.ArrayList]::new()
- $notFound = [System.Collections.ArrayList]::new()
- $serverErr = [System.Collections.ArrayList]::new()
- $forbidden = [System.Collections.ArrayList]::new()
- $timeout = [System.Collections.ArrayList]::new()
- $other = [System.Collections.ArrayList]::new()
- $i = 0
- $total = $testPaths.Count
- foreach ($path in ($testPaths.Keys | Sort-Object)) {
- $i++
- $source = $testPaths[$path]
- if ($i % 100 -eq 0) { Write-Host " Progress: $i / $total" }
-
- # Determine method - GET for list/query, POST for add/edit/remove
- $method = "GET"
- if ($path -match "/add|/edit|/remove|/delete|/save|/update|/import|/export|/upload") {
- $method = "POST"
- }
-
- try {
- if ($method -eq "GET") {
- $resp = Invoke-WebRequest -Uri "$companyUrl$path" -Method GET -Headers $headers -UseBasicParsing -TimeoutSec 8
- } else {
- $resp = Invoke-WebRequest -Uri "$companyUrl$path" -Method POST -Headers $headers -ContentType "application/json" -Body "{}" -UseBasicParsing -TimeoutSec 8
- }
- $body = $resp.Content | ConvertFrom-Json
- if ($body.code -and $body.code -ne 200) {
- $code = "$($body.code)"
- if ($code -eq "404") { [void]$notFound.Add("$path | $source") }
- elseif ($code -eq "500") { [void]$serverErr.Add("$path | $source") }
- elseif ($code -eq "403") { [void]$forbidden.Add("$path | $source") }
- else { [void]$other.Add("$path | $source | code=$code") }
- } else {
- [void]$ok.Add("$path | $source")
- }
- } catch {
- $err = "$($_.Exception.Message)"
- if ($err -match "404") { [void]$notFound.Add("$path | $source") }
- elseif ($err -match "500") { [void]$serverErr.Add("$path | $source") }
- elseif ($err -match "403") { [void]$forbidden.Add("$path | $source") }
- elseif ($err -match "timeout|timed out") { [void]$timeout.Add("$path | $source") }
- else { [void]$other.Add("$path | $source | err") }
- }
- }
- # Step 8: Summary
- Write-Host "`n========================================"
- Write-Host "=== API Test Results ==="
- Write-Host "========================================"
- Write-Host "200 OK: $($ok.Count)"
- Write-Host "404 Not Found: $($notFound.Count)"
- Write-Host "500 Server Error: $($serverErr.Count)"
- Write-Host "403 Forbidden: $($forbidden.Count)"
- Write-Host "TIMEOUT: $($timeout.Count)"
- Write-Host "OTHER: $($other.Count)"
- if ($notFound.Count -gt 0) {
- Write-Host "`n--- 404 Details ---"
- $notFound | Sort-Object | ForEach-Object { Write-Host " $_" }
- }
- if ($serverErr.Count -gt 0) {
- Write-Host "`n--- 500 Details ---"
- $serverErr | Sort-Object | ForEach-Object { Write-Host " $_" }
- }
- if ($forbidden.Count -gt 0) {
- Write-Host "`n--- 403 Details ---"
- $forbidden | Sort-Object | ForEach-Object { Write-Host " $_" }
- }
- if ($timeout.Count -gt 0) {
- Write-Host "`n--- TIMEOUT Details ---"
- $timeout | Sort-Object | ForEach-Object { Write-Host " $_" }
- }
- if ($other.Count -gt 0) {
- Write-Host "`n--- OTHER Details ---"
- $other | Sort-Object | ForEach-Object { Write-Host " $_" }
- }
- # Save results
- $out = [System.Collections.ArrayList]::new()
- [void]$out.Add("API Test Results - $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')")
- [void]$out.Add("=" * 60)
- [void]$out.Add("200 OK: $($ok.Count)")
- [void]$out.Add("404 Not Found: $($notFound.Count)")
- [void]$out.Add("500 Server Error: $($serverErr.Count)")
- [void]$out.Add("403 Forbidden: $($forbidden.Count)")
- [void]$out.Add("TIMEOUT: $($timeout.Count)")
- [void]$out.Add("OTHER: $($other.Count)")
- [void]$out.Add("")
- [void]$out.Add("=== 200 OK ===")
- $ok | Sort-Object | ForEach-Object { [void]$out.Add($_) }
- [void]$out.Add("")
- [void]$out.Add("=== 404 Not Found ===")
- $notFound | Sort-Object | ForEach-Object { [void]$out.Add($_) }
- [void]$out.Add("")
- [void]$out.Add("=== 500 Server Error ===")
- $serverErr | Sort-Object | ForEach-Object { [void]$out.Add($_) }
- [void]$out.Add("")
- [void]$out.Add("=== 403 Forbidden ===")
- $forbidden | Sort-Object | ForEach-Object { [void]$out.Add($_) }
- [void]$out.Add("")
- [void]$out.Add("=== TIMEOUT ===")
- $timeout | Sort-Object | ForEach-Object { [void]$out.Add($_) }
- [void]$out.Add("")
- [void]$out.Add("=== OTHER ===")
- $other | Sort-Object | ForEach-Object { [void]$out.Add($_) }
- [System.IO.File]::WriteAllLines("d:\ylrz\saasadminui\api_test_results.txt", $out, (New-Object System.Text.UTF8Encoding($false)))
- Write-Host "`nResults saved to d:\ylrz\saasadminui\api_test_results.txt"
|