33{-# LANGUAGE TemplateHaskell #-}
44{-# LANGUAGE TypeFamilies #-}
55{-# LANGUAGE DerivingStrategies #-}
6- module Distribution.Server.Features.Vouch where
6+ module Distribution.Server.Features.Vouch ( VouchError ( .. ), VouchSuccess ( .. ), initVouchFeature , judgeVouch ) where
77
88import Control.Monad (when , join )
99import Control.Monad.Except (runExceptT , throwError )
@@ -91,23 +91,32 @@ instance IsHackageFeature VouchFeature where
9191 getFeatureInterface = vouchFeatureInterface
9292
9393requiredCountOfVouches :: Int
94- requiredCountOfVouches = 3
94+ requiredCountOfVouches = 2
9595
9696isWithinLastMonth :: UTCTime -> (UserId , UTCTime ) -> Bool
9797isWithinLastMonth now (_, vouchTime) =
98- addUTCTime (30 * nominalDay) vouchTime < now
98+ addUTCTime (30 * nominalDay) vouchTime >= now
9999
100- data Err
100+ data VouchError
101101 = NotAnUploader
102102 | You'reTooNew
103103 | VoucheeAlreadyUploader
104104 | AlreadySufficientlyVouched
105105 | YouAlreadyVouched
106-
107- data Success = AddVouchComplete | AddVouchIncomplete
108-
109- judge :: Group. UserIdSet -> UTCTime -> UserId -> [(UserId , UTCTime )] -> [(UserId , UTCTime )] -> UserId -> Either Err (Either Err Success )
110- judge ugroup now vouchee vouchersForVoucher existingVouchers voucher = runExceptT $ do
106+ deriving stock (Show , Eq )
107+
108+ data VouchSuccess = AddVouchComplete | AddVouchIncomplete Int
109+ deriving stock (Show , Eq )
110+
111+ judgeVouch
112+ :: Group. UserIdSet
113+ -> UTCTime
114+ -> UserId
115+ -> [(UserId , UTCTime )]
116+ -> [(UserId , UTCTime )]
117+ -> UserId
118+ -> Either VouchError VouchSuccess
119+ judgeVouch ugroup now vouchee vouchersForVoucher existingVouchers voucher = join . runExceptT $ do
111120 when (not (voucher `Group.member` ugroup)) $
112121 throwError NotAnUploader
113122 -- You can only vouch for non-uploaders, so if this list has items, the user is uploader because of these vouches.
@@ -116,33 +125,35 @@ judge ugroup now vouchee vouchersForVoucher existingVouchers voucher = runExcept
116125 throwError You'reTooNew
117126 when (vouchee `Group.member` ugroup) $
118127 throwError VoucheeAlreadyUploader
119- when (length existingVouchers >= 3 ) $
128+ when (length existingVouchers >= requiredCountOfVouches ) $
120129 throwError AlreadySufficientlyVouched
121130 when (voucher `elem` map fst existingVouchers) $
122131 throwError YouAlreadyVouched
123132 pure $
124133 if length existingVouchers == requiredCountOfVouches - 1
125134 then AddVouchComplete
126- else AddVouchIncomplete
135+ else
136+ let stillRequired = requiredCountOfVouches - length existingVouchers - 1
137+ in AddVouchIncomplete stillRequired
127138
128139renderToLBS :: (UserId -> ServerPartE UserInfo ) -> [(UserId , UTCTime )] -> ServerPartE TemplateAttr
129140renderToLBS lookupUserInfo vouches = do
130- rendered <- traverse renderVouchers vouches
141+ rendered <- traverse ( renderVouchers lookupUserInfo) vouches
131142 pure $
132143 templateUnescaped " vouches" $
133144 if null rendered
134145 then LBS. pack " Nobody has vouched yet."
135146 else LBS. intercalate mempty rendered
136- where
137- renderVouchers :: (UserId , UTCTime ) -> ServerPartE LBS. ByteString
138- renderVouchers (uid, timestamp) = do
139- info <- lookupUserInfo uid
140- let UserName name = userName info
141- -- We don't need to show millisecond precision
142- -- So we truncate it off here
143- truncated = truncate $ utctDayTime timestamp
144- newUTCTime = timestamp {utctDayTime = secondsToDiffTime truncated}
145- pure . toUTF8LBS . prettyHtmlFragment . li . stringToHtml $ name <> " vouched on " <> formatShow iso8601Format newUTCTime
147+
148+ renderVouchers :: ( UserId -> ServerPartE UserInfo ) -> (UserId , UTCTime ) -> ServerPartE LBS. ByteString
149+ renderVouchers lookupUserInfo (uid, timestamp) = do
150+ info <- lookupUserInfo uid
151+ let UserName name = userName info
152+ -- We don't need to show millisecond precision
153+ -- So we truncate it off here
154+ truncated = truncate $ utctDayTime timestamp
155+ newUTCTime = timestamp {utctDayTime = secondsToDiffTime truncated}
156+ pure . toUTF8LBS . prettyHtmlFragment . li . stringToHtml $ name <> " vouched on " <> formatShow iso8601Format newUTCTime
146157
147158initVouchFeature :: ServerEnv -> IO (UserFeature -> UploadFeature -> IO VouchFeature )
148159initVouchFeature ServerEnv {serverStateDir, serverTemplatesDir, serverTemplatesMode} = do
@@ -170,7 +181,7 @@ initVouchFeature ServerEnv{serverStateDir, serverTemplatesDir, serverTemplatesMo
170181 vouchee <- lookupUserName =<< userNameInPath dpath
171182 vouchersForVoucher <- queryState vouchState $ GetVouchesFor voucher
172183 existingVouchers <- queryState vouchState $ GetVouchesFor vouchee
173- case join $ judge ugroup now vouchee vouchersForVoucher existingVouchers voucher of
184+ case judgeVouch ugroup now vouchee vouchersForVoucher existingVouchers voucher of
174185 Left NotAnUploader ->
175186 errBadRequest " Not an uploader" [MText " You must be an uploader yourself to vouch for other users." ]
176187 Left You'reTooNew ->
@@ -191,8 +202,7 @@ initVouchFeature ServerEnv{serverStateDir, serverTemplatesDir, serverTemplatesMo
191202 [ " msg" $= " Added vouch. User is now an uploader!"
192203 , param
193204 ]
194- AddVouchIncomplete -> do
195- let stillRequired = requiredCountOfVouches - length existingVouchers - 1
205+ AddVouchIncomplete stillRequired ->
196206 pure . toResponse $ vouchTemplate
197207 [ " msg" $=
198208 " Added vouch. User still needs "
0 commit comments