Change to use UUIDs instead of ints for primary keys.

[?]
May 12, 2015, 11:43 PM
RPAJLHMTUJU4AYNBOHVGHGGB4NY2NLY3BVPYN5FMWB3ZIMAUQHCQC

Dependencies

  • [2] 4SCFOJGN Specs for recovering intervals from the log now pass.
  • [3] O5FVTOM6 Undo JSON silliness, enable a couple more routes.
  • [4] BROSTG5K Beginning of modularization of server.
  • [5] 7KZP4RHZ Switch from Data.Time to Data.Thyme
  • [6] LAROLAYU WIP
  • [7] FD7SV5I6 Fix handling of event_t columns.
  • [8] TNR3TEHK Switch to Postgres + snaplet arch compiles.
  • [9] NVOCQVAS Initial failing tests.
  • [10] RSEB2NFG Replacing Snap with Scotty.
  • [11] VJPT6HDR Fix remaining type errors after addition of login handler.
  • [12] PBD7LZYQ Postgres & auth are beginning to function.
  • [13] XTBSG4C7 Adding serveJSON combinator to eliminate some boilerplate from handlers.
  • [14] TCOAKCGG Completed conversion to snap.
  • [15] HE3JTXO3 Added client call to payouts.
  • [16] GKGVYBZG Added JSON serialization to TimeLog
  • [17] 5DRIWGLU Improving TimeLog specs
  • [18] NJZ3DKZY THEY CAN TALK!
  • [19] EMVTF2IW WIP moving back to snap.
  • [20] I2KHGVD4 Require project permissions for access to most data.
  • [21] A6HKMINB Attempting to improve JSON handling.
  • [22] 75N3UJ4J More progression toward lenses.
  • [23] TLQ72DSJ Lenses, sqlite-simple
  • [24] KNSI575V Cleanup of EventLog types.
  • [25] 7DBNV3GV Initial, stack-based impl of time log event reduction.
  • [26] W35DDBFY Factor common JSON conversions up into client lib module.
  • [27] MWUPXTBF A few steps down a road to be abandoned.
  • [28] IZEVQF62 Work in progress replacing sqlite with postgres.
  • [29] OBFPJS2G Project successfully builds and tests under nix.
  • [30] 4IQVQL4T Added client for payouts endpoint.
  • [31] SLL7262C Make depreciation functions more flexible.
  • [32] 2G3GNDDU Event logging is now functioning in postgres.
  • [33] Z7KS5XHH Very WIP. Wow.
  • [34] Y35QCWYW Minor improvement in WorkIndex type to eliminate duplicated information.
  • [35] 64C6AWH6 Rename Ananke -> Quixotic, project reboot.
  • [36] Z3M53KTL Adrift.
  • [37] EZQG2APB Update task list.
  • [38] WO2MINIF Auctions now compile!
  • [39] 2Y2QZFVF Switch to more modern cabal2nix-based workflow.
  • [*] 5XFJNUAZ Start of addition of project infrastructure.
  • [*] EQXRXRZD Changed to use tasty instead of test-framework
  • [*] SCXG6TJW Make log reduction safer in presence of overlapping events.
  • [*] 7XN3I3QJ Add 'loggedIntervals' endpoint.
  • [*] WZUHEZSB Start of migration back toward snap.
  • [*] ADMKQQGC Initial empty Snap project.

Change contents

  • edit in lib/Quixotic/Auction.hs at line 8
    [4.43]
    [4.3]
    import Data.UUID
  • replacement in lib/Quixotic/Auction.hs at line 13
    [4.5214][4.3:59]()
    newtype AuctionId = AuctionId Int64 deriving (Show, Eq)
    [4.5214]
    [4.28]
    newtype AuctionId = AuctionId UUID deriving (Show, Eq)
  • edit in lib/Quixotic/Database/PostgreSQL.hs at line 23
    [4.1077]
    [4.1077]
    import Quixotic.Interval
  • edit in lib/Quixotic/Database/PostgreSQL.hs at line 112
    [4.2484]
    [4.2484]
    newtype PUTCTime = PUTCTime C.UTCTime
    instance ToField PUTCTime where
    toField (PUTCTime t) = toField $ fromThyme t
  • replacement in lib/Quixotic/Database/PostgreSQL.hs at line 166
    [4.1043][4.1043:1073]()
    , fromThyme $ eventTime e
    [4.1043]
    [4.1073]
    , fromThyme $ e ^. eventTime
  • edit in lib/Quixotic/Database/PostgreSQL.hs at line 171
    [4.3406]
    [4.1715]
    findEvents' :: ProjectId -> UserId -> Interval' -> QDBM [LogEntry]
    findEvents' (ProjectId pid) (UserId uid) ival =
    let q (Before e) = pquery
    "SELECT btc_addr, event_type, event_time, event_metadata FROM work_events \
    \WHERE project_id = ? AND user_id = ? AND event_time <= ?"
    (pid, uid, PUTCTime e)
    q (During s e) = pquery
    "SELECT btc_addr, event_type, event_time, event_metadata FROM work_events \
    \WHERE project_id = ? AND user_id = ? \
    \AND event_time >= ? AND event_time <= ?"
    (pid, uid, PUTCTime s, PUTCTime e)
    q (After s) = pquery
    "SELECT btc_addr, event_type, event_time, event_metadata FROM work_events \
    \WHERE project_id = ? AND user_id = ? AND event_time >= ?"
    (pid, uid, PUTCTime s)
    in fmap pLogEntry <$> q ival
  • replacement in lib/Quixotic/Database/PostgreSQL.hs at line 207
    [4.2411][4.304:405]()
    "SELECT btc_addr, event_type, event_time, event_metadata from work_events WHERE project_id = ?"
    [4.2411]
    [4.740]
    "SELECT btc_addr, event_type, event_time, event_metadata FROM work_events WHERE project_id = ?"
  • edit in lib/Quixotic/Database/PostgreSQL.hs at line 296
    [4.3066]
    [4.5618]
    , findEvents = findEvents'
  • edit in lib/Quixotic/Database.hs at line 10
    [4.1388]
    [4.5020]
    import Quixotic.Interval
  • edit in lib/Quixotic/Database.hs at line 28
    [4.3190]
    [41.296]
    , findEvents :: ProjectId -> UserId -> Interval' -> m [LogEntry]
  • edit in lib/Quixotic/Interval.hs at line 5
    [2.48]
    [4.3192]
    , Interval'(..), interval', start', end'
  • edit in lib/Quixotic/Interval.hs at line 23
    [43.130]
    [4.1840]
    data Interval' = Before { _end' :: C.UTCTime }
    | During { _start' :: C.UTCTime, _end' :: C.UTCTime }
    | After { _start' :: C.UTCTime }
  • edit in lib/Quixotic/Interval.hs at line 29
    [4.1887]
    [44.115]
    makeLenses ''Interval'
  • edit in lib/Quixotic/Interval.hs at line 34
    [43.132]
    [43.132]
    interval' :: C.UTCTime -> C.UTCTime -> Interval'
    interval' s e = if s < e then During s e else During e s
  • replacement in lib/Quixotic/Json.hs at line 63
    [3.1573][3.1573:1630]()
    object [ "projectId" .= (qp ^. (projectId._ProjectId))
    [3.1573]
    [3.1630]
    object [ "projectId" .= (tshow $ qp ^. (projectId._ProjectId))
  • replacement in lib/Quixotic/Json.hs at line 71
    [4.5417][4.5417:5477]()
    , "initiator" .= (p ^. (initiator._UserId)) ]
    [4.5417]
    [4.2560]
    , "initiator" .= (tshow $ p ^. (initiator._UserId)) ]
  • edit in lib/Quixotic/Json.hs at line 86
    [3.2133]
    [3.2133]
    logEntryJSON :: LogEntry -> Value
    logEntryJSON (LogEntry a ev m) =
    object [ "btcAddr" .= (a ^. _BtcAddr)
    , "eventType" .= eventName ev
    , "eventTime" .= (ev ^. eventTime)
    , "eventMeta" .= m
    ]
  • replacement in lib/Quixotic/TimeLog.hs at line 8
    [4.1130][4.3569:3594](),[4.3569][4.3569:3594]()
    , eventName, nameEvent
    [4.1130]
    [3.2136]
    , eventName, nameEvent, eventTime
  • replacement in lib/Quixotic/TimeLog.hs at line 37
    [4.1225][4.1131:1237]()
    data LogEvent = StartWork { eventTime :: C.UTCTime }
    | StopWork { eventTime :: C.UTCTime }
    [4.1225]
    [4.1237]
    data LogEvent = StartWork { _eventTime :: C.UTCTime }
    | StopWork { _eventTime :: C.UTCTime }
  • replacement in lib/Quixotic/TimeLog.hs at line 40
    [4.1271][4.1271:1293]()
    makePrisms ''LogEvent
    [4.1271]
    [4.5414]
    makeLenses ''LogEvent
  • edit in lib/Quixotic.hs at line 8
    [4.1838]
    [4.2691]
    import Data.UUID
  • replacement in lib/Quixotic.hs at line 17
    [4.2764][4.2721:2771]()
    newtype UserId = UserId Int64 deriving (Show, Eq)
    [4.2764]
    [4.2771]
    newtype UserId = UserId UUID deriving (Show, Eq)
  • replacement in lib/Quixotic.hs at line 30
    [4.1911][4.2985:3041]()
    newtype ProjectId = ProjectId Int64 deriving (Show, Eq)
    [4.1911]
    [4.3041]
    newtype ProjectId = ProjectId UUID deriving (Show, Eq)
  • replacement in payouts/Main.hs at line 38
    [4.541][4.2173:2223](),[4.2173][4.2173:2223]()
    cfg <- C.load [C.Required (fpToString cfgFile)]
    [4.541]
    [4.542]
    cfg <- C.load [C.Required cfgFile]
  • replacement in quixotic.cabal at line 32
    [4.1607][4.1607:1650](),[4.1667][4.1667:1742](),[4.1742][4.1104:1143](),[4.1143][4.1214:1252]()
    base >= 4 && < 5
    , classy-prelude >= 0.10.1
    , aeson >= 0.8.0.2
    , attoparsec >= 0.12.1.2
    , base64-bytestring >= 1.0.0.1
    [4.1607]
    [4.3072]
    base >= 4 && < 5
    , classy-prelude >= 0.10.1
    , aeson >= 0.8.0.2
    , attoparsec >= 0.12.1.2
    , base64-bytestring >= 1.0.0.1
  • replacement in quixotic.cabal at line 38
    [4.3089][4.1253:1281]()
    , blaze-builder
    [4.3089]
    [4.1144]
    , blaze-builder
  • replacement in quixotic.cabal at line 40
    [4.1161][4.1780:1818](),[4.3089][4.1780:1818](),[4.1780][4.1780:1818](),[4.1818][4.1014:1047](),[4.1047][4.1818:1854](),[4.1818][4.1818:1854](),[4.5084][4.5084:5120](),[4.5120][4.1282:1474]()
    , containers >= 0.5.5.1
    , configurator
    , either >= 4.3.1
    , errors >= 1.4.7
    , groups >= 0.4
    , heaps >= 0.3.1
    , hourglass >= 0.2.6 && < 0.3
    , lens >= 4.4.0.2
    , network-bitcoin >= 1.7.0
    [4.1161]
    [4.1892]
    , containers >= 0.5.5.1
    , configurator
    , either >= 4.3.1
    , errors >= 1.4.7
    , groups >= 0.4
    , heaps >= 0.3.1
    , hourglass >= 0.2.6 && < 0.3
    , lens >= 4.4.0.2
    , network-bitcoin >= 1.7.0
  • replacement in quixotic.cabal at line 50
    [4.5169][4.7275:7323](),[4.7323][4.1475:1511]()
    , postgresql-simple >= 0.4.9 && < 0.5
    , safe >= 0.3.8
    [4.1909]
    [4.1511]
    , postgresql-simple >= 0.4.9 && < 0.5
    , safe >= 0.3.8
  • replacement in quixotic.cabal at line 53
    [4.1528][4.1528:1576]()
    , sqlite-simple >= 0.4.8 && < 0.5
    [4.1528]
    [4.1576]
    , sqlite-simple >= 0.4.8 && < 0.5
  • replacement in quixotic.cabal at line 55
    [4.1599][4.1947:1981](),[4.5169][4.1947:1981](),[4.7351][4.1947:1981](),[4.1947][4.1947:1981](),[4.1981][4.2850:2886]()
    , text >= 1.2
    , thyme >= 0.3.5
    [4.1599]
    [4.2887]
    , text >= 1.2
    , thyme >= 0.3.5
    , uuid >= 1.3.10
  • edit in quixotic.cabal at line 105
    [45.161]
    [45.161]
    , iso8601-time
  • replacement in server/Main.hs at line 50
    [4.8568][4.8568:8653]()
    initCookieSessionManager (fpToString authSiteKey) "quookie" cookieTimeout
    [4.8568]
    [4.8653]
    initCookieSessionManager authSiteKey "quookie" cookieTimeout
  • replacement in server/Main.hs at line 58
    [3.2480][3.2480:2569]()
    loggedIntervalsRoute = serveJSON workIndexJSON $ method GET loggedIntervalsHandler
    [3.2480]
    [3.2569]
    logEntriesRoute = serveJSON (fmap logEntryJSON) $ method GET logEntriesHandler
    logIntervalsRoute = serveJSON workIndexJSON $ method GET loggedIntervalsHandler
    --amendEventRoute = void $ method PUT amendEventHandler
  • edit in server/Main.hs at line 70
    [3.2968]
    [3.2968]
    --, ("events/:eventId/amend", amendEventHandler),
  • replacement in server/Main.hs at line 72
    [3.3049][3.3049:3299]()
    , ("projects/:projectId/logEnd/:btcAddr", logEventRoute StopWork)
    , ("projects/:projectId/log/:btcAddr", loggedIntervalsRoute)
    , ("projects/:projectId", projectRoute)
    , ("projects", listProjectsRoute)
    [3.3049]
    [3.3299]
    , ("projects/:projectId/logEnd/:btcAddr", logEventRoute StopWork)
    , ("projects/:projectId/logEntries", logEntriesRoute)
    , ("projects/:projectId/intervals", logIntervalsRoute)
  • replacement in server/Main.hs at line 76
    [3.3346][3.3346:3397]()
    , ("payouts/:projectId", payoutsRoute)
    [3.3346]
    [4.8999]
    , ("projects", listProjectsRoute)
    , ("projects/:projectId", projectRoute)
    , ("projects/:projectId/payouts", payoutsRoute)
  • replacement in server/Main.hs at line 84
    [4.495][4.505:555](),[4.379][4.505:555]()
    cfg <- C.load [C.Required (fpToString cfgFile)]
    [4.495]
    [4.496]
    cfg <- C.load [C.Required cfgFile]
  • replacement in server/Main.hs at line 91
    [4.143][4.9052:9110]()
    <*> (fmap fpFromText $ C.require cfg "siteKey")
    [4.143]
    [4.9110]
    <*> C.require cfg "siteKey"
  • replacement in server/Quixotic/Snaplet/Auth.hs at line 41
    [4.2162][4.2162:2252]()
    requireProjectAccess :: UserId -> Handler App App ProjectId
    requireProjectAccess uid = do
    [4.2162]
    [4.2062]
    requireProjectAccess :: Handler App App (UserId, ProjectId)
    requireProjectAccess = do
  • edit in server/Quixotic/Snaplet/Auth.hs at line 48
    [4.2120]
    [4.2120]
    uid <- requireUserId
  • replacement in server/Quixotic/Snaplet/Auth.hs at line 51
    [4.2233][4.2233:2255]()
    then pure pid
    [4.2233]
    [4.2255]
    then pure (uid, pid)
  • replacement in server/Quixotic/Snaplet/Projects.hs at line 43
    [3.3507][3.3507:3564]()
    uid <- requireUserId
    pid <- requireProjectAccess uid
    [3.3507]
    [3.3564]
    pid <- fmap snd requireProjectAccess
  • file addition: Util.hs (----------)
    [4.182]
    module Quixotic.Snaplet.Util where
    import ClassyPrelude
    import Control.Monad.Trans.Maybe
    import Data.ByteString.Char8 as B
    import Data.Time.ISO8601
    import Data.Thyme.Time
    import Data.Thyme.Clock as C
    import Snap.Core
    timeParam :: MonadSnap m => ByteString -> m (Maybe C.UTCTime)
    timeParam k = runMaybeT $ do
    bs <- MaybeT $ getParam k
    t <- MaybeT . pure . parseISO8601 $ B.unpack bs
    pure $ toThyme t
  • edit in server/Quixotic/Snaplet/WorkLog.hs at line 12
    [4.5683]
    [4.5704]
    import Quixotic.Interval
  • edit in server/Quixotic/Snaplet/WorkLog.hs at line 17
    [4.3340]
    [4.5755]
    import Quixotic.Snaplet.Util
  • replacement in server/Quixotic/Snaplet/WorkLog.hs at line 26
    [4.5971][4.3370:3427]()
    uid <- requireUserId
    pid <- requireProjectAccess uid
    [4.5971]
    [4.5971]
    (uid, pid) <- requireProjectAccess
  • replacement in server/Quixotic/Snaplet/WorkLog.hs at line 31
    [4.3324][3.3688:3758]()
    storeEv addr = runReaderT . createEvent pid uid $ logEntry addr
    [4.3324]
    [4.6163]
    storeEv addr = runReaderT . createEvent pid uid $ logEntry addr
  • replacement in server/Quixotic/Snaplet/WorkLog.hs at line 39
    [4.6474][4.3457:3515]()
    uid <- requireUserId
    pid <- requireProjectAccess uid
    [4.6474]
    [4.1619]
    pid <- fmap snd requireProjectAccess
  • edit in server/Quixotic/Snaplet/WorkLog.hs at line 42
    [4.6632]
    [4.1662]
    logEntriesHandler :: Handler App App [LogEntry]
    logEntriesHandler = do
    QDB{..} <- view qdb <$> with qm get
    (uid, pid) <- requireProjectAccess
    endpoints <- (,) <$> timeParam "after" <*> timeParam "before"
    ival <- case endpoints of
    (Just s, Just e) -> pure $ During s e
    (Nothing, Just e) -> pure $ Before e
    (Just s, Nothing) -> pure $ After s
    (Nothing, Nothing) -> snapError 400 $ "You must at least one of the \"after\" or \"before\" query parameter"
    liftPG . runReaderT $ findEvents pid uid ival
  • replacement in server/Quixotic/Snaplet/WorkLog.hs at line 57
    [4.6744][4.3672:3730]()
    uid <- requireUserId
    pid <- requireProjectAccess uid
    [4.6744]
    [4.3730]
    pid <- fmap snd requireProjectAccess
  • edit in server/Quixotic/Snaplet/WorkLog.hs at line 62
    [4.3782]
    -- amendEventHandler :: Handler App App AmendmentId