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.Exception as C
import Control.Monad import Control.Monad
import Data.Hashable (hash)
import Data.List import Data.List
import Data.Maybe import Data.Maybe
import qualified Data.Text as T import qualified Data.Text as T
import qualified Data.Text.IO as T import qualified Data.Text.IO as T
import Data.Time (Day, addDays) import Data.Time (Day, addDays)
import Data.Word
import Numeric
import Safe (readMay) import Safe (readMay)
import System.Console.CmdArgs import System.Console.CmdArgs
import System.Directory (getModificationTime, getDirectoryContents, copyFile) import System.Directory (getModificationTime, getDirectoryContents, copyFile)
@ -54,6 +51,7 @@ import System.Time (ClockTime(TOD))
import Data.Time.Clock.POSIX (utcTimeToPOSIXSeconds) import Data.Time.Clock.POSIX (utcTimeToPOSIXSeconds)
import Hledger.Cli.CliOptions import Hledger.Cli.CliOptions
import Hledger.Cli.Anon
import Hledger.Data import Hledger.Data
import Hledger.Read import Hledger.Read
import Hledger.Reports import Hledger.Reports
@ -98,27 +96,9 @@ pivotByOpts opts =
-- | Apply the anonymisation transformation on a journal, if option is present -- | Apply the anonymisation transformation on a journal, if option is present
anonymiseByOpts :: CliOpts -> Journal -> Journal anonymiseByOpts :: CliOpts -> Journal -> Journal
anonymiseByOpts opts = anonymiseByOpts opts =
case maybestringopt "anon" . rawopts_ $ opts of if anon_ . inputopts_ $ opts
Just _ -> anonymise then anon
Nothing -> id else 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
-- | Generate periodic transactions from all periodic transaction rules in the journal. -- | 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). -- 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 -- see: https://github.com/sol/hpack
-- --
-- hash: cfbd7109f5527399580a07f847fc8f5d01951caffc3667948b6348f82183be52 -- hash: 8f2e354491d77c4334484836a2b1f0f95f6810abf49fffeaebeb19d37132a15a
name: hledger name: hledger
version: 1.15.99 version: 1.15.99
@ -109,6 +109,7 @@ library
Hledger.Cli.CliOptions Hledger.Cli.CliOptions
Hledger.Cli.DocFiles Hledger.Cli.DocFiles
Hledger.Cli.Utils Hledger.Cli.Utils
Hledger.Cli.Anon
Hledger.Cli.Version Hledger.Cli.Version
Hledger.Cli.Commands Hledger.Cli.Commands
Hledger.Cli.Commands.Accounts Hledger.Cli.Commands.Accounts

View File

@ -155,6 +155,7 @@ library:
- Hledger.Cli.CliOptions - Hledger.Cli.CliOptions
- Hledger.Cli.DocFiles - Hledger.Cli.DocFiles
- Hledger.Cli.Utils - Hledger.Cli.Utils
- Hledger.Cli.Anon
- Hledger.Cli.Version - Hledger.Cli.Version
- Hledger.Cli.Commands - Hledger.Cli.Commands
- Hledger.Cli.Commands.Accounts - 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/