cli: anonymize declared accounts also

Fixes simonmichael/hledger#901
This commit is contained in:
Mykola Orliuk 2019-10-19 22:11:35 +02:00 committed by Simon Michael
parent 5287fe671b
commit 0a273561f7
5 changed files with 94 additions and 25 deletions

View File

@ -0,0 +1,52 @@
{-|
Instances for anonymizing sensitive data in various types.
Note that there is no clear way to anonymize numbers.
-}
module Hledger.Cli.Anon
( Anon(..)
, anonAccount
)
where
import Control.Arrow (first)
import Data.Hashable (hash)
import Data.Word (Word32)
import Numeric (showHex)
import qualified Data.Text as T
import Hledger.Data
class Anon a where
-- | Consistent converter to structure with sensitive data anonymized
anon :: a -> a
instance Anon Journal where
-- Apply the anonymisation transformation on a journal after finalisation
anon j = j { jtxns = map anon . jtxns $ j
, jparseparentaccounts = map anonAccount $ jparseparentaccounts j
, jparsealiases = [] -- already applied
, jdeclaredaccounts = map (first anon) $ jdeclaredaccounts j
}
instance Anon Posting where
anon p = p { paccount = anonAccount . paccount $ p
, pcomment = T.empty
, ptransaction = fmap anon . ptransaction $ p -- Note that this will be overriden
, poriginal = anon <$> poriginal p
}
instance Anon Transaction where
anon txn = txnTieKnot $ txn { tpostings = map anon . tpostings $ txn
, tdescription = anon . tdescription $ txn
, tcomment = T.empty
}
-- | Anonymize account name preserving hierarchy
anonAccount :: AccountName -> AccountName
anonAccount = T.intercalate (T.pack ":") . map anon . T.splitOn (T.pack ":")
instance Anon T.Text where anon = T.pack . flip showHex "" . (fromIntegral :: Int -> Word32) . hash

View File

@ -31,14 +31,11 @@ where
import Control.Exception as C
import Control.Monad
import Data.Hashable (hash)
import Data.List
import Data.Maybe
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Data.Time (Day, addDays)
import Data.Word
import Numeric
import Safe (readMay)
import System.Console.CmdArgs
import System.Directory (getModificationTime, getDirectoryContents, copyFile)
@ -54,6 +51,7 @@ import System.Time (ClockTime(TOD))
import Data.Time.Clock.POSIX (utcTimeToPOSIXSeconds)
import Hledger.Cli.CliOptions
import Hledger.Cli.Anon
import Hledger.Data
import Hledger.Read
import Hledger.Reports
@ -98,27 +96,9 @@ pivotByOpts opts =
-- | Apply the anonymisation transformation on a journal, if option is present
anonymiseByOpts :: CliOpts -> Journal -> Journal
anonymiseByOpts opts =
case maybestringopt "anon" . rawopts_ $ opts of
Just _ -> anonymise
Nothing -> id
-- | Apply the anonymisation transformation on a journal
anonymise :: Journal -> Journal
anonymise j
= let
pAnons p = p { paccount = T.intercalate (T.pack ":") . map anon . T.splitOn (T.pack ":") . paccount $ p
, pcomment = T.empty
, ptransaction = fmap tAnons . ptransaction $ p
, poriginal = pAnons <$> poriginal p
}
tAnons txn = txn { tpostings = map pAnons . tpostings $ txn
, tdescription = anon . tdescription $ txn
, tcomment = T.empty
}
in
j { jtxns = map tAnons . jtxns $ j }
where
anon = T.pack . flip showHex "" . (fromIntegral :: Int -> Word32) . hash
if anon_ . inputopts_ $ opts
then anon
else id
-- | Generate periodic transactions from all periodic transaction rules in the journal.
-- These transactions are added to the in-memory Journal (but not the on-disk file).

View File

@ -4,7 +4,7 @@ cabal-version: 1.12
--
-- see: https://github.com/sol/hpack
--
-- hash: cfbd7109f5527399580a07f847fc8f5d01951caffc3667948b6348f82183be52
-- hash: 8f2e354491d77c4334484836a2b1f0f95f6810abf49fffeaebeb19d37132a15a
name: hledger
version: 1.15.99
@ -109,6 +109,7 @@ library
Hledger.Cli.CliOptions
Hledger.Cli.DocFiles
Hledger.Cli.Utils
Hledger.Cli.Anon
Hledger.Cli.Version
Hledger.Cli.Commands
Hledger.Cli.Commands.Accounts

View File

@ -155,6 +155,7 @@ library:
- Hledger.Cli.CliOptions
- Hledger.Cli.DocFiles
- Hledger.Cli.Utils
- Hledger.Cli.Anon
- Hledger.Cli.Version
- Hledger.Cli.Commands
- Hledger.Cli.Commands.Accounts

35
tests/journal/anon.test Normal file
View File

@ -0,0 +1,35 @@
# Input for the following tests:
account assets
account expenses
alias tips=expenses:tips
2019-01-01 (receipt) ; signed
(assets) 2
2019-02-01 borrow
(liabilities) 1
(tips) 3
# Basic tests on accounts
$ hledger -f- print --anon
> !/assets|liabilities|expenses|tips/
$ hledger -f- reg --anon
> !/assets|liabilities|expenses|tips/
$ hledger -f- bal --anon
> !/assets|liabilities|expenses|tips/
$ hledger -f- accounts --anon
> !/assets|liabilities|expenses|tips/
# Basic tests on descriptions and comments
$ hledger -f- print --anon
> !/borrow|signed/
$ hledger -f- reg --anon
> !/borrow/