Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
d44cfd3
(refactor) Import votesStore unqualified
tomjaguarpaw Jul 11, 2026
53beefc
(refactor) Move votesScore
tomjaguarpaw Jul 11, 2026
033d2c3
(refactor) Move votesStateComponent
tomjaguarpaw Jul 11, 2026
abbe19f
(refactor) Introduce Votes abstraction layer
tomjaguarpaw Jul 11, 2026
bac2187
(refactor) eta reduce
tomjaguarpaw Jul 11, 2026
518a680
(whitespace) Unwrap lines
tomjaguarpaw Jul 11, 2026
2033851
(refactor) Move platformStateComponent
tomjaguarpaw Jul 11, 2026
64b4356
(refactor) Introduce HaskellPlatform abstraction layer
tomjaguarpaw Jul 11, 2026
0253991
(refactor) Move analyticsPixelsStateComponent
tomjaguarpaw Jul 11, 2026
3d84d24
(refactor) Introduce AnalyticsPixels abstraction layer
tomjaguarpaw Jul 11, 2026
6332197
(refactor) Eta reduce
tomjaguarpaw Jul 11, 2026
1a77e9f
(refactor) Move mirrorersStateComponent
tomjaguarpaw Jul 11, 2026
b7d1694
(whitespace) Wrap lines
tomjaguarpaw Jul 11, 2026
f516070
(refactor) Introduce Mirror abstraction layer
tomjaguarpaw Jul 11, 2026
39dc4b6
(refactor) Introduce Core abstraction layer
tomjaguarpaw Jul 11, 2026
776d99b
(refactor) Introduce TarIndexCache abstraction layer
tomjaguarpaw Jul 11, 2026
7fddce4
(refactor) Move packagesStateComponent
tomjaguarpaw Jul 11, 2026
e328e0c
(refactor) Introduce Core abstraction layer
tomjaguarpaw Jul 11, 2026
9d717e7
(refactor) Pull out pkgs
tomjaguarpaw Jul 14, 2026
ecfafb2
Add package name lookup store query
tomjaguarpaw Jul 14, 2026
19fd228
(refactor) Pull out mpkg
tomjaguarpaw Jul 14, 2026
7835139
Add package ID lookup store query
tomjaguarpaw Jul 14, 2026
4109e33
(refactor) Pull out PackageList add-hook pkgs
tomjaguarpaw Jul 14, 2026
c359268
(refactor) Pull out PackageList preferred-hook pkgs
tomjaguarpaw Jul 14, 2026
a15f8c3
Use package name lookup query in list and search
tomjaguarpaw Jul 14, 2026
b61dc16
(refactor) Add Search pkgname let
tomjaguarpaw Jul 14, 2026
e49d07a
(refactor) Apply last earlier
tomjaguarpaw Jul 14, 2026
e28ae20
(refactor) Extract latest package earlier
tomjaguarpaw Jul 14, 2026
0642621
(refactor) Pull out latestPackages
tomjaguarpaw Jul 14, 2026
f6955cf
Add latest package versions query
tomjaguarpaw Jul 14, 2026
6e52ca1
(refactor) Run allPackageNames earlier
tomjaguarpaw Jul 15, 2026
6a7bd8e
(refactor) Pull out pkgNames
tomjaguarpaw Jul 15, 2026
46da158
(refactor) Use queryLatestPackages instead of queryGetPackageIndex
tomjaguarpaw Jul 15, 2026
ceb2ba2
(refactor) Move AdminLog into new module
tomjaguarpaw Sep 25, 2026
c4c6358
(refactor) Move adminLogStateComponent to AdminLog.Acid
tomjaguarpaw Sep 25, 2026
b1d6a55
(refactor) Introduce AdminLog abstraction layer
tomjaguarpaw Sep 25, 2026
7c86353
(refactor) Move UserDetails state into UserDetails.State
tomjaguarpaw Sep 25, 2026
c086f2d
(refactor) Move userDetailsStateComponent to UserDetails.Acid
tomjaguarpaw Sep 25, 2026
56afb38
(refactor) Introduce UserDetails abstraction layer
tomjaguarpaw Sep 25, 2026
08b14c0
(refactor) Move vouchStateComponent to Vouch.Acid
tomjaguarpaw Sep 25, 2026
b7eeadb
(refactor) Introduce Vouch abstraction layer
tomjaguarpaw Sep 25, 2026
3190bea
(refactor) Move SignupResetTable into UserSignup.State
tomjaguarpaw Sep 25, 2026
0e1f42a
(refactor) Move signupResetStateComponent to UserSignup.Acid
tomjaguarpaw Sep 25, 2026
a359279
(refactor) Introduce UserSignup abstraction layer
tomjaguarpaw Sep 25, 2026
078de4d
(refactor) Move documentationStateComponent to Documentation.Acid
tomjaguarpaw Sep 25, 2026
0f02966
(refactor) Introduce Documentation abstraction layer
tomjaguarpaw Sep 25, 2026
2642f36
(refactor) Move inMemStateComponent to DownloadCount.Acid
tomjaguarpaw Sep 25, 2026
3700a1d
(refactor) Pull out backendState
tomjaguarpaw Sep 25, 2026
ba0a194
(refactor) Introduce InMemStats abstraction layer
tomjaguarpaw Sep 25, 2026
629be1b
(refactor) Move distrosStateComponent to Distro.Acid
tomjaguarpaw Sep 25, 2026
c034772
(refactor) Introduce Distro abstraction layer
tomjaguarpaw Sep 25, 2026
d0d2654
(refactor) Move preferredStateComponent to PreferredVersions.Acid
tomjaguarpaw Sep 25, 2026
5490cb3
(refactor) Introduce PreferredVersions abstraction layer
tomjaguarpaw Sep 25, 2026
60e625c
(refactor) Move tag state components to Tags.Acid
tomjaguarpaw Sep 25, 2026
66b418d
(refactor) Introduce Tags abstraction layer
tomjaguarpaw Sep 25, 2026
d80fdc7
(refactor) Move reportsStateComponent to BuildReports.Acid
tomjaguarpaw Sep 25, 2026
5622cc8
(refactor) Introduce BuildReports abstraction layer
tomjaguarpaw Sep 25, 2026
fd37702
(refactor) Move notifyStateComponent to UserNotify.Acid.Component
tomjaguarpaw Sep 25, 2026
fcf1189
(refactor) Introduce UserNotify abstraction layer
tomjaguarpaw Sep 25, 2026
533c0ac
(refactor) Move candidatesStateComponent to PackageCandidates.Acid
tomjaguarpaw Sep 25, 2026
eff2165
(refactor) Introduce PackageCandidates abstraction layer
tomjaguarpaw Sep 25, 2026
c5dd34c
(refactor) Move securityStateComponent to Security.Acid
tomjaguarpaw Sep 25, 2026
81669b8
(refactor) Introduce Security abstraction layer
tomjaguarpaw Sep 25, 2026
9fb4363
(refactor) Move user state components to Users.Acid
tomjaguarpaw Sep 25, 2026
b559c00
(refactor) Name user state components
tomjaguarpaw Sep 27, 2026
f15b758
(refactor) Introduce Users abstraction layer
tomjaguarpaw Sep 27, 2026
92623c0
(refactor) Move upload state components to Upload.Acid
tomjaguarpaw Sep 25, 2026
557e789
(refactor) Introduce Upload abstraction layer
tomjaguarpaw Sep 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 45 additions & 3 deletions hackage-server.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -307,10 +307,13 @@ library
Distribution.Server.Features.Browse.Options
Distribution.Server.Features.Browse.Parsers
Distribution.Server.Features.Core
Distribution.Server.Features.Core.Acid
Distribution.Server.Features.Core.State
Distribution.Server.Features.Core.Backup
Distribution.Server.Features.Security
Distribution.Server.Features.Security.Backup
Distribution.Server.Features.Core.Store
Distribution.Server.Features.Core.Backup
Distribution.Server.Features.Security
Distribution.Server.Features.Security.Acid
Distribution.Server.Features.Security.Backup
Distribution.Server.Features.Security.FileInfo
Distribution.Server.Features.Security.Layout
Distribution.Server.Features.Security.MD5
Expand All @@ -319,14 +322,25 @@ library
Distribution.Server.Features.Security.ResponseContentTypes
Distribution.Server.Features.Security.SHA256
Distribution.Server.Features.Security.State
Distribution.Server.Features.Security.Store
Distribution.Server.Features.Mirror
Distribution.Server.Features.Mirror.Acid
Distribution.Server.Features.Mirror.Store
Distribution.Server.Features.TarIndexCache.Acid
Distribution.Server.Features.TarIndexCache.Store
Distribution.Server.Features.Upload
Distribution.Server.Features.Upload.Acid
Distribution.Server.Features.Upload.Store
Distribution.Server.Features.Upload.State
Distribution.Server.Features.Upload.Backup
Distribution.Server.Features.Users
Distribution.Server.Features.Users.Acid
Distribution.Server.Features.Users.Store
Distribution.Server.Features.UserNotify
Distribution.Server.Features.UserNotify.Acid
Distribution.Server.Features.UserNotify.Acid.Component
Distribution.Server.Features.UserNotify.Backup
Distribution.Server.Features.UserNotify.Store
Distribution.Server.Features.UserNotify.Types


Expand All @@ -342,35 +356,49 @@ library
Distribution.Server.Features.AdminLog
Distribution.Server.Features.AdminLog.Acid
Distribution.Server.Features.AdminLog.Backup
Distribution.Server.Features.AdminLog.State
Distribution.Server.Features.AdminLog.Store
Distribution.Server.Features.AdminLog.Types
Distribution.Server.Features.BuildReports
Distribution.Server.Features.BuildReports.BuildReport
Distribution.Server.Features.BuildReports.BuildReports
Distribution.Server.Features.BuildReports.Acid
Distribution.Server.Features.BuildReports.Backup
Distribution.Server.Features.BuildReports.Store
Distribution.Server.Features.BuildReports.Render
Distribution.Server.Features.BuildReports.State
Distribution.Server.Features.PackageCandidates
Distribution.Server.Features.PackageCandidates.Acid
Distribution.Server.Features.PackageCandidates.Types
Distribution.Server.Features.PackageCandidates.State
Distribution.Server.Features.PackageCandidates.Backup
Distribution.Server.Features.PackageCandidates.Store
Distribution.Server.Features.PackageFeed
Distribution.Server.Features.PackageList
Distribution.Server.Features.Distro
Distribution.Server.Features.Distro.Acid
Distribution.Server.Features.Distro.Distributions
Distribution.Server.Features.Distro.Backup
Distribution.Server.Features.Distro.State
Distribution.Server.Features.Distro.Store
Distribution.Server.Features.Distro.Types
Distribution.Server.Features.Documentation
Distribution.Server.Features.Documentation.Acid
Distribution.Server.Features.Documentation.State
Distribution.Server.Features.Documentation.Store
Distribution.Server.Features.DownloadCount
Distribution.Server.Features.DownloadCount.Acid
Distribution.Server.Features.DownloadCount.State
Distribution.Server.Features.DownloadCount.Store
Distribution.Server.Features.DownloadCount.Backup
Distribution.Server.Features.EditCabalFiles
Distribution.Server.Features.Html
Distribution.Server.Features.Html.HtmlUtilities
Distribution.Server.Features.HoogleData
Distribution.Server.Features.HaskellPlatform
Distribution.Server.Features.HaskellPlatform.Acid
Distribution.Server.Features.HaskellPlatform.State
Distribution.Server.Features.HaskellPlatform.Store
Distribution.Server.Features.PackageInfoJSON
Distribution.Server.Features.Search
Distribution.Server.Features.Search.BM25F
Expand All @@ -385,33 +413,47 @@ library
Distribution.Server.Features.Search.TermBag
Distribution.Server.Features.Sitemap.Functions
Distribution.Server.Features.Votes
Distribution.Server.Features.Votes.Acid
Distribution.Server.Features.Votes.Render
Distribution.Server.Features.Votes.State
Distribution.Server.Features.Votes.Store
Distribution.Server.Features.Votes.Types
Distribution.Server.Features.Vouch
Distribution.Server.Features.Vouch.Acid
Distribution.Server.Features.Vouch.State
Distribution.Server.Features.Vouch.Store
Distribution.Server.Features.Vouch.Types
Distribution.Server.Features.RecentPackages
Distribution.Server.Features.PreferredVersions
Distribution.Server.Features.PreferredVersions.Acid
Distribution.Server.Features.PreferredVersions.State
Distribution.Server.Features.PreferredVersions.Types
Distribution.Server.Features.PreferredVersions.Backup
Distribution.Server.Features.PreferredVersions.Store
Distribution.Server.Features.ReverseDependencies
Distribution.Server.Features.ReverseDependencies.State
Distribution.Server.Features.Tags
Distribution.Server.Features.Tags.Acid
Distribution.Server.Features.Tags.Backup
Distribution.Server.Features.Tags.Store
Distribution.Server.Features.Tags.State
Distribution.Server.Features.Tags.Types
Distribution.Server.Features.AnalyticsPixels
Distribution.Server.Features.AnalyticsPixels.Acid
Distribution.Server.Features.AnalyticsPixels.State
Distribution.Server.Features.AnalyticsPixels.Store
Distribution.Server.Features.AnalyticsPixels.Types
Distribution.Server.Features.UserDetails
Distribution.Server.Features.UserDetails.Acid
Distribution.Server.Features.UserDetails.Backup
Distribution.Server.Features.UserDetails.State
Distribution.Server.Features.UserDetails.Store
Distribution.Server.Features.UserDetails.Types
Distribution.Server.Features.UserSignup
Distribution.Server.Features.UserSignup.Acid
Distribution.Server.Features.UserSignup.Backup
Distribution.Server.Features.UserSignup.State
Distribution.Server.Features.UserSignup.Store
Distribution.Server.Features.UserSignup.Types
Distribution.Server.Features.StaticFiles
Distribution.Server.Features.ServerIntrospect
Expand Down
45 changes: 15 additions & 30 deletions src/Distribution/Server/Features/AdminLog.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@

module Distribution.Server.Features.AdminLog where

import qualified Distribution.Server.Features.AdminLog.Acid as Acid
import Distribution.Server.Features.AdminLog.Backup
import Distribution.Server.Features.AdminLog.Acid (acidStore)
import qualified Distribution.Server.Features.AdminLog.Store as Store
import Distribution.Server.Features.AdminLog.Types
import Distribution.Server.Users.Types (UserId)
import Distribution.Server.Users.Group
import Distribution.Server.Framework
import Distribution.Server.Framework.BackupRestore

import Distribution.Server.Pages.AdminLog
import Distribution.Server.Features.Users

import Data.Time.Clock (getCurrentTime)
import Data.Time.Clock (getCurrentTime, UTCTime)
import qualified Data.ByteString.Lazy.Char8 as BS
import Distribution.Server.Util.Parse

--TODO Maybe Reason
Expand All @@ -29,38 +29,38 @@ mkAdminAction gd isAdd uid = (if isAdd then Admin_GroupAddUser else Admin_GroupD

data AdminLogFeature = AdminLogFeature {
adminLogFeatureInterface :: HackageFeature
, queryGetAdminLog :: forall m. MonadIO m => m Acid.AdminLog
, queryGetAdminLog :: forall m. MonadIO m => m [(UTCTime,UserId,AdminAction,BS.ByteString)]
}

instance IsHackageFeature AdminLogFeature where
getFeatureInterface = adminLogFeatureInterface

initAdminLogFeature :: ServerEnv -> IO (UserFeature -> IO AdminLogFeature)
initAdminLogFeature ServerEnv{serverStateDir} = do
adminLogState <- adminLogStateComponent serverStateDir
adminLogBackend <- acidStore serverStateDir
return $ \users@UserFeature{groupChangedHook} -> do

let feature = adminLogFeature users adminLogState
let feature = adminLogFeature users adminLogBackend

registerHook groupChangedHook $ \(gd,addOrDel,actorUid,targetUid,reason) -> do
now <- getCurrentTime
updateState adminLogState $ Acid.AddAdminLog
Store.addAdminLog (Store.backendStore adminLogBackend)
(now, actorUid, mkAdminAction gd addOrDel targetUid, packUTF8 reason)

return feature

adminLogFeature :: UserFeature
-> StateComponent AcidState Acid.AdminLog
-> Store.Backend
-> AdminLogFeature
adminLogFeature UserFeature{..} adminLogState
adminLogFeature UserFeature{..} Store.Backend{backendStore = adminLogStore, backendState}
= AdminLogFeature {..}

where
adminLogFeatureInterface =
(emptyHackageFeature "admin-actions-log") {
featureDesc = "Log of additions and removals of users from groups.",
featureResources = [adminLogResource],
featureState = [abstractAcidStateComponent adminLogState]
featureState = backendState
}

adminLogResource :: Resource
Expand All @@ -70,13 +70,13 @@ adminLogFeature UserFeature{..} adminLogState
resourceGet = [("html", serveAdminLogGet)]
}

queryGetAdminLog :: MonadIO m => m Acid.AdminLog
queryGetAdminLog = queryState adminLogState Acid.GetAdminLog
queryGetAdminLog :: MonadIO m => m [(UTCTime,UserId,AdminAction,BS.ByteString)]
queryGetAdminLog = Store.getAdminLog adminLogStore

serveAdminLogGet _ = do
aLog <- queryState adminLogState Acid.GetAdminLog
aLog <- queryGetAdminLog
users <- queryGetUserDb
return . toResponse . adminLogPage users . map mkRow . Acid.adminLog $ aLog
return . toResponse . adminLogPage users . map mkRow $ aLog

mkRow (time, actorId, Admin_GroupDelUser targetId group, reason) =
(time, actorId, "Acid.Delete", targetId, nameIt group, unpackUTF8 reason)
Expand All @@ -87,18 +87,3 @@ adminLogFeature UserFeature{..} adminLogState
nameIt AdminGroup = "Administrators"
nameIt TrusteeGroup = "Trustees"
nameIt (OtherGroup s) = unpackUTF8 s

adminLogStateComponent :: FilePath -> IO (StateComponent AcidState Acid.AdminLog)
adminLogStateComponent stateDir = do
st <- openLocalStateFrom (stateDir </> "db" </> "AdminLog") Acid.initialAdminLog
return StateComponent {
stateDesc = "AdminLog"
, stateHandle = st
, getState = query st Acid.GetAdminLog
, putState = update st . Acid.ReplaceAdminLog
, backupState = \_ (Acid.AdminLog xs) ->
[BackupByteString ["adminLog.txt"] . backupLogEntries $ xs]
, restoreState = restoreAdminLogBackup
, resetState = adminLogStateComponent
}

126 changes: 32 additions & 94 deletions src/Distribution/Server/Features/AdminLog/Acid.hs
Original file line number Diff line number Diff line change
@@ -1,96 +1,34 @@
{-# LANGUAGE DeriveDataTypeable, TypeFamilies, TemplateHaskell, BangPatterns,
GeneralizedNewtypeDeriving, NamedFieldPuns, RecordWildCards,
PatternGuards, RankNTypes #-}
module Distribution.Server.Features.AdminLog.Acid
( acidStore
) where

module Distribution.Server.Features.AdminLog.Acid where

import Distribution.Server.Features.AdminLog.Types
import Distribution.Server.Users.Types (UserId)
import Distribution.Server.Features.AdminLog.Backup
import qualified Distribution.Server.Features.AdminLog.State as State
import Distribution.Server.Features.AdminLog.Store
import Distribution.Server.Framework

import Control.Monad.Reader
import qualified Control.Monad.State as State
import Data.Time (UTCTime)
import qualified Data.ByteString.Lazy.Char8 as BS
import Data.Acid.Compat

newtype AdminLog = AdminLog {
adminLog :: [(UTCTime,UserId,AdminAction,BS.ByteString)]
} deriving (Show, MemSize)

deriveSafeCopy 0 'base ''AdminLog

initialAdminLog :: AdminLog
initialAdminLog = AdminLog []

getAdminLog :: Query AdminLog AdminLog
getAdminLog = ask

addAdminLog :: (UTCTime, UserId, AdminAction, BS.ByteString) -> Update AdminLog ()
addAdminLog x = State.modify (\(AdminLog xs) -> AdminLog (x : xs))

instance Eq AdminLog where
(AdminLog (x:_)) == (AdminLog (y:_)) = x == y
(AdminLog []) == (AdminLog []) = True
_ == _ = False

replaceAdminLog :: AdminLog -> Update AdminLog ()
replaceAdminLog = State.put

------------------------------
-- IsAcidic machinery
--
-- See Note [Acid Migration] in "Data.Acid.Compat"
-- original module name was Distribution.Server.Features.AdminLog"

-- makeAcidic ''AdminLog ['getAdminLog
-- ,'replaceAdminLog
-- ,'addAdminLog]

instance IsAcidic AdminLog where
acidEvents
= [QueryEvent
(\ GetAdminLog -> getAdminLog) safeCopyMethodSerialiser,
UpdateEvent
(\ (ReplaceAdminLog arg_aDn6) -> replaceAdminLog arg_aDn6)
safeCopyMethodSerialiser,
UpdateEvent
(\ (AddAdminLog arg_aDn7) -> addAdminLog arg_aDn7)
safeCopyMethodSerialiser]
data GetAdminLog = GetAdminLog
instance SafeCopy GetAdminLog where
putCopy GetAdminLog = contain (do return ())
getCopy = contain (return GetAdminLog)
errorTypeName _ = "Data.SafeCopy.SafeCopy.SafeCopy GetAdminLog"
instance Data.Acid.Compat.Method GetAdminLog where
type MethodResult GetAdminLog = AdminLog
type MethodState GetAdminLog = AdminLog
methodTag = movedMethodTag "Distribution.Server.Features.AdminLog"
instance QueryEvent GetAdminLog
newtype ReplaceAdminLog = ReplaceAdminLog AdminLog
instance SafeCopy ReplaceAdminLog where
putCopy (ReplaceAdminLog arg_aDmO)
= contain
(do safePut arg_aDmO
return ())
getCopy = contain (return ReplaceAdminLog <*> safeGet)
errorTypeName _ = "Data.SafeCopy.SafeCopy.SafeCopy ReplaceAdminLog"
instance Data.Acid.Compat.Method ReplaceAdminLog where
type MethodResult ReplaceAdminLog = ()
type MethodState ReplaceAdminLog = AdminLog
methodTag = movedMethodTag "Distribution.Server.Features.AdminLog"
instance UpdateEvent ReplaceAdminLog
newtype AddAdminLog
= AddAdminLog (UTCTime, UserId, AdminAction, BS.ByteString)
instance SafeCopy AddAdminLog where
putCopy (AddAdminLog arg_aDmT)
= contain
(do safePut arg_aDmT
return ())
getCopy = contain (return AddAdminLog <*> safeGet)
errorTypeName _ = "Data.SafeCopy.SafeCopy.SafeCopy AddAdminLog"
instance Data.Acid.Compat.Method AddAdminLog where
type MethodResult AddAdminLog = ()
type MethodState AddAdminLog = AdminLog
methodTag = movedMethodTag "Distribution.Server.Features.AdminLog"
instance UpdateEvent AddAdminLog
import Distribution.Server.Framework.BackupRestore

acidStore :: FilePath -> IO Backend
acidStore stateDir = do
adminLogState <- adminLogStateComponent stateDir
pure Backend {
backendStore = Store {
getAdminLog = State.adminLog <$> queryState adminLogState State.GetAdminLog
, addAdminLog = \entry -> updateState adminLogState (State.AddAdminLog entry)
}
, backendState = [abstractAcidStateComponent adminLogState]
}

adminLogStateComponent :: FilePath -> IO (StateComponent AcidState State.AdminLog)
adminLogStateComponent stateDir = do
st <- openLocalStateFrom (stateDir </> "db" </> "AdminLog") State.initialAdminLog
return StateComponent {
stateDesc = "AdminLog"
, stateHandle = st
, getState = query st State.GetAdminLog
, putState = update st . State.ReplaceAdminLog
, backupState = \_ (State.AdminLog xs) ->
[BackupByteString ["adminLog.txt"] . backupLogEntries $ xs]
, restoreState = restoreAdminLogBackup
, resetState = adminLogStateComponent
}
Loading
Loading