dotfiles/win/Modules/Pass/Pass.psm1

174 lines
4.3 KiB
PowerShell

$PASSWORD_STORE_DIR = (Get-Item "~\.password-store").FullName
$CLEAR_TIMEOUT = 45
function GeneratePassword {
param(
[Int] $Size = 10,
[Char[]] $Charsets = "ULNS",
[Char[]] $Exclude
)
$Chars = @(); $TokenSet = @()
If (!$TokenSets) {
$Global:TokenSets = @{
U = [Char[]]'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
L = [Char[]]'abcdefghijklmnopqrstuvwxyz'
N = [Char[]]'0123456789'
S = [Char[]]'!"#$%&''()*+,-./:;<=>?@[\]^_`{|}~'
}
}
$CharSets | ForEach {
$Tokens = $TokenSets."$_" | ForEach {If ($Exclude -cNotContains $_) {$_}}
If ($Tokens) {
$TokensSet += $Tokens
If ($_ -cle [Char]"Z") {$Chars += $Tokens | Get-Random}
}
}
While ($Chars.Count -lt $Size) {$Chars += $TokensSet | Get-Random}
return ($Chars | Sort-Object {Get-Random}) -Join ""
}
function EnsurePath {
param(
[String] $OrigPassPath,
[Bool] $CreateParents=$false
)
if (!$OrigPassPath) {
throw "path is empty!"
}
$PassPath = Join-Path $PASSWORD_STORE_DIR $OrigPassPath
if (!$PassPath.EndsWith(".gpg")) {
$PassPath = $PassPath + ".gpg"
}
$dir = Split-Path $PassPath
if (!$dir) {
$dir = "."
}
if ($CreateParents -and !(Test-Path -PathType Container $dir)) {
# all output will be returned, suppress all output for all subcommands
New-Item -ItemType Directory -Path $dir > $null
}
return $PassPath
}
function GetUid {
if ((gpg --list-secret-keys | findstr uid) -match '<(.*?)>') {
$matches[1]
} else {
throw "unable to find default uid"
}
}
function FzfPass {
Get-ChildItem $PASSWORD_STORE_DIR -Recurse -Filter *.gpg | %{
$_.FullName.SubString(
$PASSWORD_STORE_DIR.Length+1,
$_.FullName.Length-$PASSWORD_STORE_DIR.Length-5
)
} | fzf
}
function Edit-Pass {
[Cmdletbinding()]
param(
[String] $PassPath
)
if (!$PassPath) {
$PassPath = FzfPass
if (!$?) {
return
}
}
$PassPath = EnsurePath -CreateParents $true $PassPath
$tmpfile = (New-TemporaryFile).FullName
gpg --decrypt $PassPath > $tmpfile
nvim $tmpfile
if ($?) {
gpg -r (GetUid) -o "$tmpfile.gpg" --encrypt $tmpfile
Move-Item -Path "$tmpfile.gpg" -Destination "$PassPath" -Force
Remove-Item $tmpfile -Force
}
}
function New-Pass {
[Cmdletbinding()]
param(
[Parameter(Mandatory=$true)] [String] $PassPath
)
$PassPath = EnsurePath -CreateParents $true $PassPath
$pass = GeneratePassword
if (Test-Path -PathType Leaf $PassPath) {
$text = gpg --decrypt $PassPath
if ($text -is [string]) {
$text = @($pass)
} else {
$text[0] = $pass
}
Remove-Item $PassPath -Force
} else {
$text = @($pass)
}
$text | gpg -r (GetUid) -o $PassPath --encrypt -
Set-Clipboard $pass
Write-Host $pass
Write-Host "new password is saved and copied to Clipboard"
}
function Get-Pass {
[Cmdletbinding()]
param(
[Parameter(Mandatory=$true)] [String] $PassPath,
[Bool] $Clipboard=$true
)
$PassPath = EnsurePath $PassPath
if ($Clipboard) {
$pass = gpg --decrypt $PassPath | Select -First 1
if ($pass) {
Set-Clipboard $pass
Write-Host "password is copied to Clipboard successfully"
if ($CLEAR_TIMEOUT -gt 0) {
Write-Host "and will be cleared out in $CLEAR_TIMEOUT seconds"
Start-Job -ArgumentList $pass,$CLEAR_TIMEOUT -ScriptBlock {
start-sleep -s $args[1] > $null
if ( (get-clipboard) -eq $args[0]) {
$null | clip.exe
}
} > $null
}
} else {
throw "password is empty"
}
} else {
Write-Host $pass
}
}
function Find-Pass {
$selected = FzfPass
if ($selected) {
Get-Pass $selected
}
}
function Find-Login {
$selected = FzfPass
if ($selected) {
$login = Split-Path -Leaf $selected
Write-Host $login
Set-Clipboard $login
}
}
Export-ModuleMember -Function Edit-Pass,New-Pass,Get-Pass,Find-Pass,Find-Login