feat: auto token acquisition + import helpers for Ka-Note scripts
- get-token.ps1: MSAL.PS-based token acquisition (browser popup once, then cached refresh token) - download/upload/unlock.ps1: auto-call get-token.ps1 when no -Token/-env provided - import-helpers.ps1: reusable functions (Upsert-Context, Add-Topic, Add-HistoryEntry) with correct schema - import-jf-sysadmins.ps1: idempotent import script using helpers Fixes: - Token file no longer stored in work/ (deleted on download) - Upsert-Context resurrects soft-deleted contexts (500 was caused by uploading topics for deleted context) - History uses topicId + YYYY-MM-DD date (not contextId + timestamp) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
28221232d6
commit
3b6ae8c92b
|
|
@ -80,9 +80,12 @@ if (Test-Path $WorkDir) {
|
|||
|
||||
if ($Prod) {
|
||||
$BaseUrl = "https://ka-note.azurewebsites.net"
|
||||
$BearerToken = if ($Token) { $Token } else { $env:KA_NOTE_TOKEN }
|
||||
$BearerToken = if ($Token) { $Token } elseif ($env:KA_NOTE_TOKEN) { $env:KA_NOTE_TOKEN } else {
|
||||
Write-Host " Acquiring token via MSAL..." -ForegroundColor DarkGray
|
||||
& "$PSScriptRoot\get-token.ps1"
|
||||
}
|
||||
if (-not $BearerToken) {
|
||||
Write-Err "Prod mode requires a Bearer token. Pass -Token or set `$env:KA_NOTE_TOKEN."
|
||||
Write-Err "Failed to acquire a Bearer token."
|
||||
exit 1
|
||||
}
|
||||
$Headers = @{ Authorization = "Bearer $BearerToken" }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
<#
|
||||
.SYNOPSIS
|
||||
Gets a Bearer token for the Ka-Note production API via MSAL.PS.
|
||||
Installs MSAL.PS automatically if missing.
|
||||
Uses cached tokens / refresh tokens — browser login only needed on first run
|
||||
or after token cache is cleared.
|
||||
|
||||
.OUTPUTS
|
||||
Writes the access token string to stdout.
|
||||
|
||||
.EXAMPLE
|
||||
$token = & "$PSScriptRoot\get-token.ps1"
|
||||
#>
|
||||
param()
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$ClientId = '1aba7af7-eec1-4e49-b87e-9f941c0e8630'
|
||||
$TenantId = '94cf90d7-e9ff-49a1-bc3b-a5b94d3cc8ca'
|
||||
$Scopes = "api://$ClientId/access"
|
||||
|
||||
# --- Ensure MSAL.PS is available ---------------------------------------------
|
||||
if (-not (Get-Module -ListAvailable -Name 'MSAL.PS')) {
|
||||
Write-Host " [INFO] Installing MSAL.PS module..." -ForegroundColor DarkGray
|
||||
Install-Module -Name 'MSAL.PS' -Scope CurrentUser -Force -AllowClobber
|
||||
}
|
||||
Import-Module MSAL.PS -ErrorAction Stop
|
||||
|
||||
# --- Acquire token -----------------------------------------------------------
|
||||
$params = @{
|
||||
ClientId = $ClientId
|
||||
TenantId = $TenantId
|
||||
Scopes = $Scopes
|
||||
}
|
||||
|
||||
$result = $null
|
||||
|
||||
# 1. Try silent first (uses cached access token or refresh token)
|
||||
try {
|
||||
$result = Get-MsalToken @params -Silent 2>$null
|
||||
} catch {
|
||||
# No cached token or refresh failed — fall back to interactive
|
||||
}
|
||||
|
||||
# 2. Interactive browser login
|
||||
if (-not $result) {
|
||||
Write-Host " [AUTH] Opening browser for login..." -ForegroundColor Yellow
|
||||
$result = Get-MsalToken @params -Interactive
|
||||
}
|
||||
|
||||
if (-not $result -or -not $result.AccessToken) {
|
||||
Write-Error "Failed to acquire token."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Output only the token (callers capture via $token = & .\get-token.ps1)
|
||||
Write-Output $result.AccessToken
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
<#
|
||||
.SYNOPSIS
|
||||
Shared helper functions for UpNote → Ka-Note bundle imports.
|
||||
Dot-source this file in import scripts: . "$PSScriptRoot\import-helpers.ps1"
|
||||
|
||||
.NOTES
|
||||
Bundle file formats (as of current schema):
|
||||
|
||||
contexts.json — array of AgendaContext:
|
||||
id, name, type (meeting|project|person|company), sortOrder,
|
||||
updatedAt, deletedAt, version, archivedAt, isFavorite, meta
|
||||
|
||||
topics.json — array of Topic:
|
||||
id, contextId, title, body, sortOrder, isPinned,
|
||||
deletedAt, updatedAt, version
|
||||
|
||||
history/<id>.meta.json — HistoryEntry (without text):
|
||||
id, topicId, date (YYYY-MM-DD), sortOrder, linkedContextId,
|
||||
doneAt, wiedervorlageDate, wiedervorlageResolvedAt,
|
||||
updatedAt, deletedAt, version
|
||||
history/<id>.md — plain text / markdown content
|
||||
|
||||
IMPORTANT:
|
||||
- History is TOPIC-scoped (topicId), NOT context-scoped.
|
||||
- History date is "YYYY-MM-DD" (no time part).
|
||||
- History has no "title" field.
|
||||
- Soft-deleted contexts cause 500 on upload if new topics reference them
|
||||
→ always call Upsert-Context which auto-resurrects deleted contexts.
|
||||
#>
|
||||
|
||||
# Globals set by Initialize-BundleSession
|
||||
$script:WorkDir = $null
|
||||
$script:Now = $null
|
||||
|
||||
function Initialize-BundleSession {
|
||||
param([string]$WorkDir)
|
||||
$script:WorkDir = $WorkDir
|
||||
$script:Now = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ")
|
||||
if (-not (Test-Path "$WorkDir\history")) { New-Item -ItemType Directory "$WorkDir\history" | Out-Null }
|
||||
}
|
||||
|
||||
# Upsert a context: creates new OR resurrects if soft-deleted OR skips if active.
|
||||
# Always bumps version and sets name/type/sortOrder if changed.
|
||||
function Upsert-Context {
|
||||
param(
|
||||
[string]$CtxPath,
|
||||
[string]$Id,
|
||||
[string]$Name,
|
||||
[string]$Type = 'meeting',
|
||||
[int] $SortOrder = 10,
|
||||
[bool] $IsFavorite = $true
|
||||
)
|
||||
$ctxs = Get-Content $CtxPath -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||
$existing = $ctxs | Where-Object { $_.id -eq $Id }
|
||||
|
||||
if ($existing) {
|
||||
$wasDeleted = $null -ne $existing.deletedAt
|
||||
$existing | Add-Member -NotePropertyName deletedAt -NotePropertyValue $null -Force
|
||||
$existing | Add-Member -NotePropertyName name -NotePropertyValue $Name -Force
|
||||
$existing | Add-Member -NotePropertyName updatedAt -NotePropertyValue $script:Now -Force
|
||||
$existing.version++
|
||||
if ($wasDeleted) {
|
||||
Write-Host " [CTX] Resurrected: $Id" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host " [CTX] Already active, updated: $Id" -ForegroundColor DarkGray
|
||||
}
|
||||
} else {
|
||||
$new = [PSCustomObject]@{
|
||||
id = $Id
|
||||
name = $Name
|
||||
type = $Type
|
||||
sortOrder = $SortOrder
|
||||
updatedAt = $script:Now
|
||||
deletedAt = $null
|
||||
version = 1
|
||||
archivedAt = $null
|
||||
isFavorite = $IsFavorite
|
||||
meta = $null
|
||||
}
|
||||
$ctxs = @($ctxs) + $new
|
||||
Write-Host " [CTX] Created: $Id ($Name)" -ForegroundColor Green
|
||||
}
|
||||
$ctxs | ConvertTo-Json -Depth 10 | Set-Content $CtxPath -Encoding UTF8
|
||||
}
|
||||
|
||||
# Soft-delete all topics for a context (cleanup orphans or old data)
|
||||
function Remove-ContextTopics {
|
||||
param([string]$TopicsPath, [string]$ContextId)
|
||||
$tops = Get-Content $TopicsPath -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||
$count = 0
|
||||
foreach ($t in $tops) {
|
||||
if ($t.contextId -eq $ContextId -and -not $t.deletedAt) {
|
||||
$t | Add-Member -NotePropertyName deletedAt -NotePropertyValue $script:Now -Force
|
||||
$t | Add-Member -NotePropertyName updatedAt -NotePropertyValue $script:Now -Force
|
||||
$t.version++
|
||||
$count++
|
||||
}
|
||||
}
|
||||
$tops | ConvertTo-Json -Depth 10 | Set-Content $TopicsPath -Encoding UTF8
|
||||
if ($count -gt 0) { Write-Host " [TOP] Soft-deleted $count orphan topics for $ContextId" -ForegroundColor DarkGray }
|
||||
}
|
||||
|
||||
# Add a new topic. Returns the topic ID.
|
||||
function Add-Topic {
|
||||
param(
|
||||
[string]$TopicsPath,
|
||||
[string]$ContextId,
|
||||
[string]$Title,
|
||||
[string]$Body = '',
|
||||
[int] $SortOrder = 0,
|
||||
[bool] $IsPinned = $false
|
||||
)
|
||||
$id = [System.Guid]::NewGuid().ToString()
|
||||
$tops = Get-Content $TopicsPath -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||
$new = [PSCustomObject]@{
|
||||
id = $id
|
||||
contextId = $ContextId
|
||||
title = $Title
|
||||
body = $Body
|
||||
sortOrder = $SortOrder
|
||||
isPinned = $IsPinned
|
||||
deletedAt = $null
|
||||
updatedAt = $script:Now
|
||||
version = 1
|
||||
}
|
||||
$tops = @($tops) + $new
|
||||
$tops | ConvertTo-Json -Depth 10 | Set-Content $TopicsPath -Encoding UTF8
|
||||
Write-Host " [TOP] + $Title" -ForegroundColor DarkGray
|
||||
return $id
|
||||
}
|
||||
|
||||
# Add a history entry (attached to a topic).
|
||||
# $Date: 'YYYY-MM-DD'
|
||||
# $Text: markdown string
|
||||
function Add-HistoryEntry {
|
||||
param(
|
||||
[string]$TopicId,
|
||||
[string]$Date,
|
||||
[string]$Text,
|
||||
[int] $SortOrder = 0
|
||||
)
|
||||
$id = [System.Guid]::NewGuid().ToString()
|
||||
$meta = [PSCustomObject]@{
|
||||
id = $id
|
||||
topicId = $TopicId
|
||||
date = $Date
|
||||
sortOrder = $SortOrder
|
||||
linkedContextId = $null
|
||||
doneAt = $null
|
||||
wiedervorlageDate = $null
|
||||
wiedervorlageResolvedAt = $null
|
||||
updatedAt = $script:Now
|
||||
deletedAt = $null
|
||||
version = 1
|
||||
}
|
||||
$meta | ConvertTo-Json -Depth 5 | Set-Content "$($script:WorkDir)\history\$id.meta.json" -Encoding UTF8
|
||||
$Text | Set-Content "$($script:WorkDir)\history\$id.md" -Encoding UTF8
|
||||
Write-Host " [HIS] + $Date" -ForegroundColor DarkGray
|
||||
return $id
|
||||
}
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
<#
|
||||
.SYNOPSIS
|
||||
Imports / re-imports the "JF: Team Sysadmins" context into Ka-Note.
|
||||
Idempotent: resurrects soft-deleted context, soft-deletes orphan topics,
|
||||
creates clean topic set and history entries.
|
||||
|
||||
.PARAMETER Prod
|
||||
Target production server.
|
||||
|
||||
.PARAMETER Force
|
||||
Skip upload conflict confirmation.
|
||||
|
||||
.EXAMPLE
|
||||
.\import-jf-sysadmins.ps1
|
||||
.\import-jf-sysadmins.ps1 -Prod
|
||||
#>
|
||||
param(
|
||||
[switch]$Prod,
|
||||
[switch]$Force
|
||||
)
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
. "$PSScriptRoot\import-helpers.ps1"
|
||||
|
||||
$scripts = $PSScriptRoot
|
||||
$RepoRoot = Resolve-Path "$PSScriptRoot\..\.."
|
||||
$workDir = Join-Path $RepoRoot "work"
|
||||
|
||||
# ── 1. Download ───────────────────────────────────────────────────────────────
|
||||
Write-Host "`n[1] Downloading bundle..." -ForegroundColor Cyan
|
||||
$dlArgs = @('-File', "$scripts\download.ps1", '-Force')
|
||||
if ($Prod) { $dlArgs += '-Prod' }
|
||||
& powershell @dlArgs
|
||||
if ($LASTEXITCODE -ne 0) { throw "Download failed (exit $LASTEXITCODE)" }
|
||||
|
||||
Initialize-BundleSession -WorkDir $workDir
|
||||
|
||||
$ctxPath = "$workDir\contexts.json"
|
||||
$topsPath = "$workDir\topics.json"
|
||||
$ctxId = 'jf-sysadmins'
|
||||
|
||||
# ── 2. Upsert context (creates or resurrects soft-deleted) ────────────────────
|
||||
Write-Host "`n[2] Context..." -ForegroundColor Cyan
|
||||
Upsert-Context -CtxPath $ctxPath -Id $ctxId -Name 'JF: Team Sysadmins' -SortOrder 20
|
||||
|
||||
# ── 3. Soft-delete orphan topics ─────────────────────────────────────────────
|
||||
Write-Host "`n[3] Cleanup orphan topics..." -ForegroundColor Cyan
|
||||
Remove-ContextTopics -TopicsPath $topsPath -ContextId $ctxId
|
||||
|
||||
# ── 4. Create topics ──────────────────────────────────────────────────────────
|
||||
Write-Host "`n[4] Creating topics..." -ForegroundColor Cyan
|
||||
|
||||
$journalId = Add-Topic $topsPath $ctxId 'Sitzungsprotokoll' `
|
||||
'Meeting-Notizen chronologisch.' 5 $true
|
||||
|
||||
Add-Topic $topsPath $ctxId 'TISAX: Sperren Produktionsrechner' `
|
||||
"Benutzergruppe kein Internet + VLAN shared`n- EOL-VLAN, SERVICE-ACCOUNT VLAN`n- PC-0259`n- Stas funktioniert nicht" 10 | Out-Null
|
||||
|
||||
Add-Topic $topsPath $ctxId 'TISAX: Allgemeine Anforderungen' `
|
||||
"- Doku Backup-Prozess`n- Situationen simulieren`n- Pen-Test vor TISAX (ueber RES)`n- DocuSnap fuer Notfallhandbuch`n- Anforderung 5.3.2 Netzwerkdienste" 20 | Out-Null
|
||||
|
||||
Add-Topic $topsPath $ctxId 'Backup und SAN' `
|
||||
"- Backup-Probleme DW und BUW (warten auf Ports, Hees, Transaktionslogs, Wartungsjobs)`n- VMware Upgrade HKR: Bootreihenfolge festlegen`n- Rucksicherungstest, Prozess mit Hees beschreiben" 30 | Out-Null
|
||||
|
||||
Add-Topic $topsPath $ctxId 'Citrix Farm Erneuerung' `
|
||||
"- Grundinstallation da, Stefan installiert Programme`n- Sophos Endpoint fehlt`n- GPOs + Netscaler Termin SVA`n- MFA und Citrix: Alternativen SVA ausstehend" 40 | Out-Null
|
||||
|
||||
Add-Topic $topsPath $ctxId 'internal.lan / Access-Manager' `
|
||||
"- Nacharbeiten F+E laufen`n- Dennis + Ossenbuehl starten Vorbereitungen`n- Angebot Access-Manager ausstehend" 50 | Out-Null
|
||||
|
||||
Add-Topic $topsPath $ctxId 'Greenbone / Schwachstellenmanagement' `
|
||||
"- Philip: Analyse-Ergebnis heisst nicht, alles selbst bearbeiten`n- Dokumentation in Arbeit`n- Greenbone ueberwacht auch Citrix-Umgebung (ja)" 60 | Out-Null
|
||||
|
||||
Add-Topic $topsPath $ctxId 'Windows-Upgrade und EOL-Systeme' `
|
||||
"- Win10 bei KAS: isoliert? Hardwareauswahl? Ende 14. Okt.`n- XP-Maschinen fluten Netzwerk`n- Admin-Rechte HKR abschalten`n- Rechner Fertigung: IT-Richtlinie" 70 | Out-Null
|
||||
|
||||
Add-Topic $topsPath $ctxId 'Netzwerk und Core-Switch' `
|
||||
"- Core-Switch Nacharbeiten (VLANs stecken, alten Switch ausbauen)`n- Rückbau IPSec Regeln`n- Aufbau Server-VLAN`n- NAC: Liste Geraete vorbereiten" 80 | Out-Null
|
||||
|
||||
Add-Topic $topsPath $ctxId 'DocuSnap und Notfallhandbuch' `
|
||||
"- Notfallhandbuch HKR`n- DocuSnap: Termin mit Kelobit`n- Verzeichnis Verarbeitungstaetigkeiten`n- V14 eingespielt, Sammler gefixt" 90 | Out-Null
|
||||
|
||||
Add-Topic $topsPath $ctxId 'KI-Richtlinie und IT-Governance' `
|
||||
"- KI-Governance: Philip`n- KI-Workshop: Eray`n- Server kuenftig nur auf Englisch (IT-Richtlinie)`n- KAS: keine Admin-Rechte mehr" 100 | Out-Null
|
||||
|
||||
Add-Topic $topsPath $ctxId 'Teams und Kommunikation' `
|
||||
"- Teams-Probleme HKR: Netzwerkkarten bestellt`n- BZ-Ampere Ticket #507535`n- KRAH-App Service-Status" 110 | Out-Null
|
||||
|
||||
Add-Topic $topsPath $ctxId 'Diverses und Aufgaben' `
|
||||
"- deletion of old user: ZAD, Job einplanen`n- IT Kram WITEC`n- SnipeIT, Teleport, CLM Einfuehrung`n- Passwort-DB ausrollen" 120 | Out-Null
|
||||
|
||||
# ── 5. Create history entries (attached to Sitzungsprotokoll) ─────────────────
|
||||
Write-Host "`n[5] Creating history entries..." -ForegroundColor Cyan
|
||||
|
||||
Add-HistoryEntry $journalId '2026-02-20' "## Next`n`n- TISAX: Sperren Produktionsrechner (Benutzergruppe kein Internet + VLAN shared)`n- IT Kram WITEC`n- deletion of old user: ZAD aktivieren, Job einplanen`n- Windows ressourcenhungriger -> Leasing pruefen`n- Ticket #507535 BZ-Ampere" | Out-Null
|
||||
|
||||
Add-HistoryEntry $journalId '2026-02-18' "## 2026-02-18`n`n- HKR: Warum 10 separate Banfen?`n- TISAX: Sperren Produktionsrechner`n- Greenbone: Analyse-Ergebnis heisst nicht, dass Philip alle bearbeitet`n- Ticket LQS, alte SharePoint Daten" | Out-Null
|
||||
|
||||
Add-HistoryEntry $journalId '2026-02-11' "## 2026-02-11`n`n- Teams-Problem HKR: Steffen bestellt Netzwerkkarten`n- Angebot DL fuer AM: Jenni umgezogen`n- Ticket Ossenbuehl Citrix: alter IE, warten auf neue Farm`n- TISAX Situationen simulieren" | Out-Null
|
||||
|
||||
Add-HistoryEntry $journalId '2026-02-03' "## 2026-02-03`n`n- Pen-Test vor TISAX (ueber RES)`n- Steffen: neue Hardware (PFSense nicht auf alter Sophos)`n- TISAX Produktionsrechner: VLAN, PC-0259`n- Doku Backup-Prozess noch nicht gestartet`n- DocuSnap Termin" | Out-Null
|
||||
|
||||
Add-HistoryEntry $journalId '2026-01-28' "## 2026-01-28`n`n- viflow in Arbeit`n- Notebook Karsten: Rücksprache ML/TG`n- Focus TISAX Doku SteFi`n- Azure Mails an IT-Team / Helpdesk`n- ShutDown Stromverteiler Sa wieder anlaufen`n- B+W Server Aufstellung (EOL, Greenbone, Risiko)" | Out-Null
|
||||
|
||||
Add-HistoryEntry $journalId '2026-01-13' "## 2026-01-13`n`n- Hees in Migration Domaene einbinden`n- Backup-Aufgaben in Plane`n- USV-Analyse mit Hees starten`n- Admin-Rechte HKR abschalten`n- Wildcard-Zertifikat ueberall?`n- NAC: Liste Geraete vorbereiten" | Out-Null
|
||||
|
||||
Add-HistoryEntry $journalId '2026-01-07' "## 2026-01-07`n`n- PC QS: Ticket #393176`n- USB-Sticks sperren HKR (Start KW2 2026)`n- Status Festplattenbestellung IBM?`n- Backlogs AtWork bearbeiten" | Out-Null
|
||||
|
||||
Add-HistoryEntry $journalId '2025-12-11' "## 2025-12-11`n`n- Access to Snipe-IT lost`n- Qlik: Sales + FI, Florian + Steffen einbinden`n- Teleport: Problem Setup`n- KPI Database: Phase 1 Qlik Ersatz, VIZLIB Plugin Test`n- Keine Admin-Rechte mehr fuer KAS" | Out-Null
|
||||
|
||||
Add-HistoryEntry $journalId '2025-12-10' "## 2025-12-10`n`n- KI-Workshop IT-Team: Eray, KI-Governance Philip`n- DC-Problem 2025: warten auf SVA Statement`n- TISAX 5.3.2 Netzwerkdienste`n- Admin-Rechte HKR entfernen (lokale Gruppe NW-Konfig)`n- Reparatur-Prozess: Aufkleber Ticketnummer" | Out-Null
|
||||
|
||||
Add-HistoryEntry $journalId '2025-11-25' "## 2025-11-25`n`n- Neue viFlow Server einrichten`n- USB-Sticks sperren ab 01. Dez`n- Server kuenftig nur auf Englisch`n- Findings HKR: XP fluten Netz, Sky GO`n- Bestellung Kelobit DocuSnap Server" | Out-Null
|
||||
|
||||
Add-HistoryEntry $journalId '2025-11-19' "## 2025-11-19`n`n- Snipe-IT fuer alle (Ausgabe-, Wareneingangs-, Nachbestellprozess)`n- Netzwerkdokumentation aktualisieren`n- Ordnung in Teleport`n- Verrechnung IT-Kosten (SAN, Teleport + GIT -> KST Server)" | Out-Null
|
||||
|
||||
Add-HistoryEntry $journalId '2025-11-12' "## 2025-11-12`n`n- WWP Bollenbach: NiceLabel -> Printer3`n- Win10 PCs HKR: Steffen banft`n- WITEC-Telefone: H+Ue kontaktiert Hersteller" | Out-Null
|
||||
|
||||
Add-HistoryEntry $journalId '2025-11-05' "## 2025-11-05`n`n- Teams: aktuell laeuft es`n- HKR: SIP-Trunk 08. Dez Thalheim`n- BitSight Treffen`n- Visitor process: Android-Tool`n- Praktikanten Bewerbungen" | Out-Null
|
||||
|
||||
Add-HistoryEntry $journalId '2025-10-28' "## 2025-10-28`n`n- Telekom Hardware waehrend Urlaub?`n- Server AccessManager`n- Citrix: Start Testphase?`n- WITEC final zurueckgebaut?`n- Abschaltung altes Intranet Jahresende`n- Angebote Hardware Bechtle vs. Hees" | Out-Null
|
||||
|
||||
# ── 6. Upload ─────────────────────────────────────────────────────────────────
|
||||
Write-Host "`n[6] Uploading..." -ForegroundColor Cyan
|
||||
$ulArgs = @('-File', "$scripts\upload.ps1")
|
||||
if ($Prod) { $ulArgs += '-Prod' }
|
||||
if ($Force) { $ulArgs += '-Force' }
|
||||
& powershell @ulArgs
|
||||
if ($LASTEXITCODE -ne 0) { throw "Upload failed (exit $LASTEXITCODE)" }
|
||||
|
||||
Write-Host "`n[DONE] JF Sysadmins import complete." -ForegroundColor Green
|
||||
|
|
@ -71,9 +71,12 @@ if (-not $LockToken) {
|
|||
|
||||
if ($Prod) {
|
||||
$BaseUrl = "https://ka-note.azurewebsites.net"
|
||||
$BearerToken = if ($Token) { $Token } else { $env:KA_NOTE_TOKEN }
|
||||
$BearerToken = if ($Token) { $Token } elseif ($env:KA_NOTE_TOKEN) { $env:KA_NOTE_TOKEN } else {
|
||||
Write-Host " Acquiring token via MSAL..." -ForegroundColor DarkGray
|
||||
& "$PSScriptRoot\get-token.ps1"
|
||||
}
|
||||
if (-not $BearerToken) {
|
||||
Write-Err "Prod mode requires a Bearer token. Pass -Token or set `$env:KA_NOTE_TOKEN."
|
||||
Write-Err "Failed to acquire a Bearer token."
|
||||
exit 1
|
||||
}
|
||||
$Headers = @{ Authorization = "Bearer $BearerToken"; "Content-Type" = "application/json" }
|
||||
|
|
|
|||
|
|
@ -65,9 +65,12 @@ if (-not $LockToken) {
|
|||
|
||||
if ($Prod) {
|
||||
$BaseUrl = "https://ka-note.azurewebsites.net"
|
||||
$BearerToken = if ($Token) { $Token } else { $env:KA_NOTE_TOKEN }
|
||||
$BearerToken = if ($Token) { $Token } elseif ($env:KA_NOTE_TOKEN) { $env:KA_NOTE_TOKEN } else {
|
||||
Write-Host " Acquiring token via MSAL..." -ForegroundColor DarkGray
|
||||
& "$PSScriptRoot\get-token.ps1"
|
||||
}
|
||||
if (-not $BearerToken) {
|
||||
Write-Err "Prod mode requires a Bearer token. Pass -Token or set `$env:KA_NOTE_TOKEN."
|
||||
Write-Err "Failed to acquire a Bearer token."
|
||||
exit 1
|
||||
}
|
||||
$Headers = @{ Authorization = "Bearer $BearerToken"; "Content-Type" = "application/octet-stream" }
|
||||
|
|
@ -89,7 +92,23 @@ Write-Host ""
|
|||
Write-Host " Compressing work/..." -ForegroundColor DarkGray
|
||||
|
||||
if (Test-Path $ZipPath) { Remove-Item $ZipPath -Force }
|
||||
Compress-Archive -Path "$WorkDir\*" -DestinationPath $ZipPath
|
||||
|
||||
# Use .NET ZipArchive directly to ensure forward-slash entry names (Compress-Archive uses backslashes on Windows)
|
||||
Add-Type -Assembly 'System.IO.Compression'
|
||||
Add-Type -Assembly 'System.IO.Compression.FileSystem'
|
||||
$zipStream = [System.IO.File]::Open($ZipPath, [System.IO.FileMode]::Create)
|
||||
$archive = [System.IO.Compression.ZipArchive]::new($zipStream, [System.IO.Compression.ZipArchiveMode]::Create)
|
||||
Get-ChildItem -Path $WorkDir -Recurse -File | Where-Object { $_.FullName -ne $ZipPath } | ForEach-Object {
|
||||
$entryName = $_.FullName.Substring($WorkDir.Length + 1).Replace('\', '/')
|
||||
$entry = $archive.CreateEntry($entryName, [System.IO.Compression.CompressionLevel]::Optimal)
|
||||
$entryStream = $entry.Open()
|
||||
$fileStream = [System.IO.File]::OpenRead($_.FullName)
|
||||
$fileStream.CopyTo($entryStream)
|
||||
$fileStream.Dispose()
|
||||
$entryStream.Dispose()
|
||||
}
|
||||
$archive.Dispose()
|
||||
$zipStream.Dispose()
|
||||
|
||||
$ZipSizeKb = [math]::Round((Get-Item $ZipPath).Length / 1KB, 1)
|
||||
Write-KV "zip size" "${ZipSizeKb} KB"
|
||||
|
|
|
|||
Loading…
Reference in New Issue