ImplementingModule/ImplementingModule.psm1

# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
#requires -module PoshKeePass

function ValidateKeePassDatabase ($AdditionalParameters) {
    if (-not (Test-Path $AdditionalParameters.Path)) {
        throw "Could not find the keepass database $($AdditionalParameters.Path). Please verify the file exists or re-register the vault"
    }
    switch ($AdditionalParameters.MasterKey.GetType()) {
        ([String]) {
            $AdditionalParameters.MasterKey = $AdditionalParameters.MasterKey | ConvertTo-SecureString -AsPlainText -Force
            break
        }
        ([PSCredential]) {
            $AdditionalParameters.MasterKey = $AdditionalParameters.MasterKey.Password
            break
        }
        ([SecureString]) {
            #No Action, just don't fail
            break
        }
        default {
            #Try to cast whatever object was provided to string and use it as the master key
            [String]$AdditionalParameters.MasterKey = $AdditionalParameters.MasterKey.toString()
            break
        }
    }
    if (-not (Get-KeePassDatabaseConfiguration -DatabaseProfileName $AdditionalParameters.Name)) {
        New-KeePassDatabaseConfiguration -DatabaseProfileName $AdditionalParameters.Name -DatabasePath $AdditionalParameters.Path -UseMasterKey
    }
}

function GetKeepassParams ($AdditionalParameters) {
    $KeepassParams = @{}
    if ($AdditionalParameters.Name) {$KeepassParams.DatabaseProfileName = $AdditionalParameters.Name}
    if ($AdditionalParameters.MasterKey) {$KeepassParams.MasterKey = $AdditionalParameters.MasterKey}
    return $KeepassParams
}

function Get-Secret
{
    param (
        [string] $Name,
        [hashtable] $AdditionalParameters
    )

    ValidateKeePassDatabase $AdditionalParameters
    $KeepassParams = GetKeepassParams $AdditionalParameters
    $keepassGetResult = Get-KeePassEntry @KeepassParams -Title $Name | Where-Object ParentGroup -notmatch 'RecycleBin'
    if ($keepassGetResult.count -gt 1) {throw "Multiple ambiguous entries found for $Name, please remove the duplicate entry"}
    if (-not $keepassGetResult.Username) {
        $keepassGetResult.Password
    }
    else {
        [PSCredential]::new($KeepassGetResult.UserName, $KeepassGetResult.Password)
    }
}

function Set-Secret
{
    param (
        [string] $Name,
        [object] $Secret,
        [hashtable] $AdditionalParameters
    )

    ValidateKeePassDatabase $AdditionalParameters
    $KeepassParams = GetKeepassParams $AdditionalParameters

    #Set default group
    [String]$KeepassParams.KeePassEntryGroupPath = Get-KeePassGroup @KeepassParams | 
    Where-Object fullpath -notmatch '/' | 
    ForEach-Object fullpath | 
    Select-Object -first 1

    switch ($Secret.GetType()) {
        ([String]) {
            $KeepassParams.Username = $null
            $KeepassParams.KeepassPassword = $Secret
        }
        ([PSCredential]) {
            $KeepassParams.Username = $Secret.Username
            $KeepassParams.KeepassPassword = $Secret.Password
        }
        default {
            throw 'This vault provider only accepts string and PSCredential secrets'
        }
    }

    return [Bool](New-KeePassEntry @KeepassParams -Title $Name -PassThru)
}

function Remove-Secret
{
    param (
        [string] $Name,
        [hashtable] $AdditionalParameters
    )

    ValidateKeePassDatabase $AdditionalParameters
    $KeepassParams = GetKeepassParams $AdditionalParameters
    $GetKeePassResult = Get-KeePassEntry @KeepassParams -Title $Name
    if (-not $GetKeePassResult) {throw "No Keepass Entry named $Name found"}
    Remove-KeepassEntry @KeepassParams -KeepassEntry $GetKeePassResult -erroraction stop -Confirm:$false
    return $true
}

function Get-SecretInfo
{
    param(
        [string] $Filter,
        [hashtable] $AdditionalParameters
    )
    ValidateKeePassDatabase $AdditionalParameters
    $KeepassParams = GetKeepassParams $AdditionalParameters
    $KeepassGetResult = Get-KeePassEntry @KeepassParams | Where-Object ParentGroup -notmatch 'RecycleBin'
    $KeepassGetResult.where{$PSItem.Title -like $filter}.foreach{
        [PSCustomObject]@{
            Name = $PSItem.Title
            Value = if (-not $PSItem.Username) {'String'} else {'PSCredential'}
        } 
    }
}