#Requires -Version 5.1 <# .SYNOPSIS Регистрирует публичные SSH-ключи в Gitea через API (kalinamall, papatramp). #> [CmdletBinding()] param( [string]$ConfigDir = "$HOME\CursorRules\local", [string]$HostsConfig = '', [switch]$WhatIf ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' function Write-Step([string]$Message) { Write-Host "[*] $Message" -ForegroundColor Cyan } function Write-Ok([string]$Message) { Write-Host "[+] $Message" -ForegroundColor Green } function Write-Warn([string]$Message) { Write-Host "[!] $Message" -ForegroundColor Yellow } function Read-KeyValueFile { param([string]$Path) $data = @{} Get-Content -LiteralPath $Path | ForEach-Object { if ($_ -match '^([^#=]+)=(.*)$') { $data[$Matches[1].Trim()] = $Matches[2].Trim() } } return $data } function Read-GitSshHostsConfig { param([string]$Path) $profiles = @{} $currentProfile = $null Get-Content -LiteralPath $Path | ForEach-Object { $line = $_.Trim() if (-not $line -or $line.StartsWith('#')) { return } if ($line -match '^\[profile:(.+)\]$') { $currentProfile = $Matches[1] $profiles[$currentProfile] = @{} return } if ($line -match '^\[host:') { $currentProfile = $null; return } if ($line -match '^([^=]+)=(.*)$' -and $currentProfile) { $profiles[$currentProfile][$Matches[1].Trim()] = $Matches[2].Trim() } } return $profiles } function Get-GiteaAuthHeader { param([hashtable]$Cfg) $pair = '{0}:{1}' -f $Cfg.GiteaApiUser, $Cfg.GiteaApiPassword $auth = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes($pair)) return @{ Authorization = $auth; 'Content-Type' = 'application/json' } } function Register-GiteaKey { param( [hashtable]$Cfg, [string]$PublicKeyPath, [string]$Title ) if (-not $Cfg.GiteaApiPassword) { Write-Warn "$Title : GiteaApiPassword empty - add key manually in Gitea UI" Write-Host (Get-Content -LiteralPath $PublicKeyPath -Raw).Trim() return } $base = $Cfg.GiteaApiUrl.TrimEnd('/') $headers = Get-GiteaAuthHeader -Cfg $Cfg $pub = (Get-Content -LiteralPath $PublicKeyPath -Raw).Trim() $existing = Invoke-RestMethod -Method Get -Uri "$base/api/v1/user/keys" -Headers $headers -TimeoutSec 15 foreach ($item in @($existing)) { if ($item.key.Trim() -eq $pub) { Write-Ok "$Title : key already registered ($($item.title))" return } } $body = (@{ title = $Title; key = $pub } | ConvertTo-Json) if ($WhatIf) { Write-Step "WhatIf: POST $base/api/v1/user/keys ($Title)" return } $created = Invoke-RestMethod -Method Post -Uri "$base/api/v1/user/keys" -Headers $headers -Body $body -TimeoutSec 30 Write-Ok "$Title : registered ($($created.title))" } if (-not $HostsConfig) { $HostsConfig = Join-Path $ConfigDir 'git-ssh-hosts.conf' } if (-not (Test-Path -LiteralPath $HostsConfig)) { throw "Config not found: $HostsConfig" } $profiles = Read-GitSshHostsConfig -Path $HostsConfig $sshDir = Join-Path $HOME '.ssh' $machine = $env:COMPUTERNAME if (-not $machine) { $machine = [Environment]::MachineName } $registered = @{} foreach ($profileName in $profiles.Keys) { $profile = $profiles[$profileName] $giteaConfigName = $profile.GiteaConfig if (-not $giteaConfigName) { continue } $keyName = $profile.KeyName if ($registered.ContainsKey($keyName)) { continue } $registered[$keyName] = $true $giteaPath = Join-Path $ConfigDir $giteaConfigName if (-not (Test-Path -LiteralPath $giteaPath)) { Write-Warn "Gitea config not found: $giteaPath" continue } $cfg = Read-KeyValueFile -Path $giteaPath $pubPath = Join-Path $sshDir "$keyName.pub" if (-not (Test-Path -LiteralPath $pubPath)) { Write-Warn "Public key not found: $pubPath (run Setup-GitSsh first)" continue } $title = "$machine-$keyName" Write-Step "Registering $keyName on $($cfg.GiteaHost)" Register-GiteaKey -Cfg $cfg -PublicKeyPath $pubPath -Title $title } Write-Ok 'Gitea SSH key registration done'