From 45e88d813ba931f67e18398c03bc783fd84ec0e2 Mon Sep 17 00:00:00 2001 From: Aditya Manthramurthy Date: Mon, 22 May 2023 12:32:34 -0700 Subject: [PATCH] Enable StrictData and bump up version for release (#189) * Enable StrictData and bump up version for release - Types defined in Credentials.Types and Network.Minio.Data are now strict * ormolu fixes --- .github/workflows/ci.yml | 4 +++- minio-hs.cabal | 2 +- src/Lib/Prelude.hs | 2 +- src/Network/Minio/API.hs | 6 +++--- src/Network/Minio/Credentials.hs | 2 +- src/Network/Minio/Credentials/AssumeRole.hs | 4 +++- src/Network/Minio/Credentials/Types.hs | 9 +++++++-- src/Network/Minio/Data.hs | 16 ++++++---------- src/Network/Minio/Data/Crypto.hs | 16 ++++++++-------- src/Network/Minio/SelectAPI.hs | 14 +++++++------- src/Network/Minio/Sign/V4.hs | 2 +- src/Network/Minio/Utils.hs | 4 ++-- src/Network/Minio/XmlCommon.hs | 2 +- src/Network/Minio/XmlParser.hs | 2 +- test/LiveServer.hs | 4 ++-- 15 files changed, 47 insertions(+), 42 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 86a342c..8557d4e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: mrkkrp/ormolu-action@v8 + - uses: haskell-actions/run-ormolu@v12 + with: + version: "0.5.0.1" hlint: runs-on: ubuntu-latest diff --git a/minio-hs.cabal b/minio-hs.cabal index 620ef4c..77d7557 100644 --- a/minio-hs.cabal +++ b/minio-hs.cabal @@ -1,6 +1,6 @@ cabal-version: 2.4 name: minio-hs -version: 1.6.0 +version: 1.7.0 synopsis: A MinIO Haskell Library for Amazon S3 compatible cloud storage. description: The MinIO Haskell client library provides simple APIs to diff --git a/src/Lib/Prelude.hs b/src/Lib/Prelude.hs index 5d16a89..d3af2bd 100644 --- a/src/Lib/Prelude.hs +++ b/src/Lib/Prelude.hs @@ -42,7 +42,7 @@ import UnliftIO as Exports both :: (a -> b) -> (a, a) -> (b, b) both f (a, b) = (f a, f b) -showBS :: Show a => a -> ByteString +showBS :: (Show a) => a -> ByteString showBS a = encodeUtf8 (show a :: Text) toStrictBS :: LByteString -> ByteString diff --git a/src/Network/Minio/API.hs b/src/Network/Minio/API.hs index 34f45dd..cb4b309 100644 --- a/src/Network/Minio/API.hs +++ b/src/Network/Minio/API.hs @@ -150,7 +150,7 @@ getHostPathRegion ri = do -- | requestSTSCredential requests temporary credentials using the Security Token -- Service API. The returned credential will include a populated 'SessionToken' -- and an 'ExpiryTime'. -requestSTSCredential :: STSCredentialProvider p => p -> IO (CredentialValue, ExpiryTime) +requestSTSCredential :: (STSCredentialProvider p) => p -> IO (CredentialValue, ExpiryTime) requestSTSCredential p = do endpoint <- maybe (throwIO $ MErrValidation MErrVSTSEndpointNotFound) return $ getSTSEndpoint p let endPt = NC.parseRequest_ $ toString endpoint @@ -337,7 +337,7 @@ isValidBucketName bucket = isIPCheck = and labelAsNums && length labelAsNums == 4 -- Throws exception iff bucket name is invalid according to AWS rules. -checkBucketNameValidity :: MonadIO m => Bucket -> m () +checkBucketNameValidity :: (MonadIO m) => Bucket -> m () checkBucketNameValidity bucket = unless (isValidBucketName bucket) $ throwIO $ @@ -347,7 +347,7 @@ isValidObjectName :: Object -> Bool isValidObjectName object = T.length object > 0 && B.length (encodeUtf8 object) <= 1024 -checkObjectNameValidity :: MonadIO m => Object -> m () +checkObjectNameValidity :: (MonadIO m) => Object -> m () checkObjectNameValidity object = unless (isValidObjectName object) $ throwIO $ diff --git a/src/Network/Minio/Credentials.hs b/src/Network/Minio/Credentials.hs index 2920370..5058596 100644 --- a/src/Network/Minio/Credentials.hs +++ b/src/Network/Minio/Credentials.hs @@ -47,7 +47,7 @@ data STSCredentialStore = STSCredentialStore refreshAction :: Endpoint -> NC.Manager -> IO (CredentialValue, ExpiryTime) } -initSTSCredential :: STSCredentialProvider p => p -> IO STSCredentialStore +initSTSCredential :: (STSCredentialProvider p) => p -> IO STSCredentialStore initSTSCredential p = do let action = retrieveSTSCredentials p -- start with dummy credential, so that refresh happens for first request. diff --git a/src/Network/Minio/Credentials/AssumeRole.hs b/src/Network/Minio/Credentials/AssumeRole.hs index 0328ec6..7a2df24 100644 --- a/src/Network/Minio/Credentials/AssumeRole.hs +++ b/src/Network/Minio/Credentials/AssumeRole.hs @@ -41,6 +41,8 @@ defaultDurationSeconds :: Second defaultDurationSeconds = 3600 -- | Assume Role API argument. +-- +-- @since 1.7.0 data STSAssumeRole = STSAssumeRole { -- | Credentials to use in the AssumeRole STS API. sarCredentials :: CredentialValue, @@ -119,7 +121,7 @@ data AssumeRoleResult = AssumeRoleResult -- c6104cbe-af31-11e0-8154-cbc7ccf896c7 -- -- -parseSTSAssumeRoleResult :: MonadIO m => ByteString -> Text -> m AssumeRoleResult +parseSTSAssumeRoleResult :: (MonadIO m) => ByteString -> Text -> m AssumeRoleResult parseSTSAssumeRoleResult xmldata namespace = do r <- parseRoot $ LB.fromStrict xmldata let s3Elem' = s3Elem namespace diff --git a/src/Network/Minio/Credentials/Types.hs b/src/Network/Minio/Credentials/Types.hs index a9c33bc..0579758 100644 --- a/src/Network/Minio/Credentials/Types.hs +++ b/src/Network/Minio/Credentials/Types.hs @@ -14,6 +14,7 @@ -- limitations under the License. -- {-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE StrictData #-} module Network.Minio.Credentials.Types where @@ -37,11 +38,13 @@ newtype SessionToken = SessionToken {unSessionToken :: BA.ScrubbedBytes} deriving newtype (Eq, IsString, Semigroup, Monoid) -- | Object storage credential data type. It has support for the optional --- for using temporary credentials requested via STS. +-- [SessionToken](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html) +-- for using temporary credentials requested via STS. -- -- The show instance for this type does not print the value of secrets for -- security. +-- +-- @since 1.7.0 data CredentialValue = CredentialValue { cvAccessKey :: AccessKey, cvSecretKey :: SecretKey, @@ -70,6 +73,8 @@ credentialValueText cv = type Endpoint = (ByteString, Int, Bool) -- | Typeclass for STS credential providers. +-- +-- @since 1.7.0 class STSCredentialProvider p where retrieveSTSCredentials :: p -> diff --git a/src/Network/Minio/Data.hs b/src/Network/Minio/Data.hs index 6e53d5a..a0a47a3 100644 --- a/src/Network/Minio/Data.hs +++ b/src/Network/Minio/Data.hs @@ -16,6 +16,7 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE StrictData #-} {-# LANGUAGE TypeFamilies #-} module Network.Minio.Data where @@ -156,15 +157,10 @@ instance IsString ConnectInfo where connectDisableTLSCertValidation = False } --- | Contains access key and secret key to access object storage. -data Credentials = Credentials - { cAccessKey :: Text, - cSecretKey :: Text - } - deriving stock (Eq, Show) - -- | A 'CredentialLoader' is an action that may return a 'CredentialValue'. -- Loaders may be chained together using 'findFirst'. +-- +-- @since 1.7.0 type CredentialLoader = IO (Maybe CredentialValue) -- | Combines the given list of loaders, by calling each one in @@ -232,7 +228,7 @@ setCreds cv connInfo = -- | 'setSTSCredential' configures `ConnectInfo` to retrieve temporary -- credentials via the STS API on demand. It is automatically refreshed on -- expiry. -setSTSCredential :: STSCredentialProvider p => p -> ConnectInfo -> IO ConnectInfo +setSTSCredential :: (STSCredentialProvider p) => p -> ConnectInfo -> IO ConnectInfo setSTSCredential p ci = do store <- initSTSCredential p return ci {connectCreds = CredsSTS store} @@ -308,7 +304,7 @@ newtype SSECKey = SSECKey BA.ScrubbedBytes -- | Validates that the given ByteString is 32 bytes long and creates -- an encryption key. -mkSSECKey :: MonadThrow m => ByteString -> m SSECKey +mkSSECKey :: (MonadThrow m) => ByteString -> m SSECKey mkSSECKey keyBytes | B.length keyBytes /= 32 = throwM MErrVInvalidEncryptionKeyLength @@ -325,7 +321,7 @@ data SSE where -- argument is the optional KMS context that must have a -- `A.ToJSON` instance - please refer to the AWS S3 documentation -- for detailed information. - SSEKMS :: A.ToJSON a => Maybe ByteString -> Maybe a -> SSE + SSEKMS :: (A.ToJSON a) => Maybe ByteString -> Maybe a -> SSE -- | Specifies server-side encryption with customer provided -- key. The argument is the encryption key to be used. SSEC :: SSECKey -> SSE diff --git a/src/Network/Minio/Data/Crypto.hs b/src/Network/Minio/Data/Crypto.hs index af51cb3..3180859 100644 --- a/src/Network/Minio/Data/Crypto.hs +++ b/src/Network/Minio/Data/Crypto.hs @@ -43,26 +43,26 @@ import qualified Data.Conduit as C hashSHA256 :: ByteString -> ByteString hashSHA256 = digestToBase16 . hashWith SHA256 -hashSHA256FromSource :: Monad m => C.ConduitM () ByteString m () -> m ByteString +hashSHA256FromSource :: (Monad m) => C.ConduitM () ByteString m () -> m ByteString hashSHA256FromSource src = do digest <- C.connect src sinkSHA256Hash return $ digestToBase16 digest where -- To help with type inference - sinkSHA256Hash :: Monad m => C.ConduitM ByteString Void m (Digest SHA256) + sinkSHA256Hash :: (Monad m) => C.ConduitM ByteString Void m (Digest SHA256) sinkSHA256Hash = sinkHash -- Returns MD5 hash hex encoded. hashMD5 :: ByteString -> ByteString hashMD5 = digestToBase16 . hashWith MD5 -hashMD5FromSource :: Monad m => C.ConduitM () ByteString m () -> m ByteString +hashMD5FromSource :: (Monad m) => C.ConduitM () ByteString m () -> m ByteString hashMD5FromSource src = do digest <- C.connect src sinkMD5Hash return $ digestToBase16 digest where -- To help with type inference - sinkMD5Hash :: Monad m => C.ConduitM ByteString Void m (Digest MD5) + sinkMD5Hash :: (Monad m) => C.ConduitM ByteString Void m (Digest MD5) sinkMD5Hash = sinkHash hmacSHA256 :: ByteString -> ByteString -> HMAC SHA256 @@ -71,15 +71,15 @@ hmacSHA256 message key = hmac key message hmacSHA256RawBS :: ByteString -> ByteString -> ByteString hmacSHA256RawBS message key = convert $ hmacSHA256 message key -digestToBS :: ByteArrayAccess a => a -> ByteString +digestToBS :: (ByteArrayAccess a) => a -> ByteString digestToBS = convert -digestToBase16 :: ByteArrayAccess a => a -> ByteString +digestToBase16 :: (ByteArrayAccess a) => a -> ByteString digestToBase16 = convertToBase Base16 -- Returns MD5 hash base 64 encoded. -hashMD5ToBase64 :: ByteArrayAccess a => a -> ByteString +hashMD5ToBase64 :: (ByteArrayAccess a) => a -> ByteString hashMD5ToBase64 = convertToBase Base64 . hashWith MD5 -encodeToBase64 :: ByteArrayAccess a => a -> ByteString +encodeToBase64 :: (ByteArrayAccess a) => a -> ByteString encodeToBase64 = convertToBase Base64 diff --git a/src/Network/Minio/SelectAPI.hs b/src/Network/Minio/SelectAPI.hs index 01db5e7..621e86c 100644 --- a/src/Network/Minio/SelectAPI.hs +++ b/src/Network/Minio/SelectAPI.hs @@ -119,7 +119,7 @@ instance Exception EventStreamException chunkSize :: Int chunkSize = 32 * 1024 -parseBinary :: Bin.Binary a => ByteString -> IO a +parseBinary :: (Bin.Binary a) => ByteString -> IO a parseBinary b = do case Bin.decodeOrFail $ LB.fromStrict b of Left (_, _, msg) -> throwIO $ ESEDecodeFail msg @@ -135,7 +135,7 @@ bytesToHeaderName t = case t of _ -> throwIO ESEInvalidHeaderType parseHeaders :: - MonadUnliftIO m => + (MonadUnliftIO m) => Word32 -> C.ConduitM ByteString a m [MessageHeader] parseHeaders 0 = return [] @@ -163,7 +163,7 @@ parseHeaders hdrLen = do -- readNBytes returns N bytes read from the string and throws an -- exception if N bytes are not present on the stream. -readNBytes :: MonadUnliftIO m => Int -> C.ConduitM ByteString a m ByteString +readNBytes :: (MonadUnliftIO m) => Int -> C.ConduitM ByteString a m ByteString readNBytes n = do b <- LB.toStrict <$> (C.takeCE n .| C.sinkLazy) if B.length b /= n @@ -171,7 +171,7 @@ readNBytes n = do else return b crcCheck :: - MonadUnliftIO m => + (MonadUnliftIO m) => C.ConduitM ByteString ByteString m () crcCheck = do b <- readNBytes 12 @@ -208,7 +208,7 @@ crcCheck = do then accumulateYield n' c' else return c' -handleMessage :: MonadUnliftIO m => C.ConduitT ByteString EventMessage m () +handleMessage :: (MonadUnliftIO m) => C.ConduitT ByteString EventMessage m () handleMessage = do b1 <- readNBytes 4 msgLen :: Word32 <- liftIO $ parseBinary b1 @@ -254,7 +254,7 @@ handleMessage = do passThrough $ n - B.length b selectProtoConduit :: - MonadUnliftIO m => + (MonadUnliftIO m) => C.ConduitT ByteString EventMessage m () selectProtoConduit = crcCheck .| handleMessage @@ -281,7 +281,7 @@ selectObjectContent b o r = do return $ NC.responseBody resp .| selectProtoConduit -- | A helper conduit that returns only the record payload bytes. -getPayloadBytes :: MonadIO m => C.ConduitT EventMessage ByteString m () +getPayloadBytes :: (MonadIO m) => C.ConduitT EventMessage ByteString m () getPayloadBytes = do evM <- C.await case evM of diff --git a/src/Network/Minio/Sign/V4.hs b/src/Network/Minio/Sign/V4.hs index f822e44..f306249 100644 --- a/src/Network/Minio/Sign/V4.hs +++ b/src/Network/Minio/Sign/V4.hs @@ -346,7 +346,7 @@ chunkSizeConstant = 64 * 1024 -- base16Len computes the number of bytes required to represent @n (> 0)@ in -- hexadecimal. -base16Len :: Integral a => a -> Int +base16Len :: (Integral a) => a -> Int base16Len n | n == 0 = 0 | otherwise = 1 + base16Len (n `div` 16) diff --git a/src/Network/Minio/Utils.hs b/src/Network/Minio/Utils.hs index f985ddc..1fcaa84 100644 --- a/src/Network/Minio/Utils.hs +++ b/src/Network/Minio/Utils.hs @@ -175,7 +175,7 @@ isSuccessStatus sts = in (s >= 200 && s < 300) httpLbs :: - MonadIO m => + (MonadIO m) => NC.Request -> NC.Manager -> m (NC.Response LByteString) @@ -239,7 +239,7 @@ http req mgr = do -- Similar to mapConcurrently but limits the number of threads that -- can run using a quantity semaphore. limitedMapConcurrently :: - MonadUnliftIO m => + (MonadUnliftIO m) => Int -> (t -> m a) -> [t] -> diff --git a/src/Network/Minio/XmlCommon.hs b/src/Network/Minio/XmlCommon.hs index 6c428ce..6892523 100644 --- a/src/Network/Minio/XmlCommon.hs +++ b/src/Network/Minio/XmlCommon.hs @@ -35,7 +35,7 @@ uncurry6 :: (a -> b -> c -> d -> e -> f -> g) -> (a, b, c, d, e, f) -> g uncurry6 f (a, b, c, d, e, g) = f a b c d e g -- | Parse time strings from XML -parseS3XMLTime :: MonadIO m => Text -> m UTCTime +parseS3XMLTime :: (MonadIO m) => Text -> m UTCTime parseS3XMLTime t = maybe (throwIO $ MErrVXmlParse $ "timestamp parse failure: " <> t) return $ iso8601ParseM $ diff --git a/src/Network/Minio/XmlParser.hs b/src/Network/Minio/XmlParser.hs index 46e4bcf..ffc2230 100644 --- a/src/Network/Minio/XmlParser.hs +++ b/src/Network/Minio/XmlParser.hs @@ -218,7 +218,7 @@ parseNotification xmldata = do events (Filter $ FilterKey $ FilterRules rules) -parseSelectProgress :: MonadIO m => ByteString -> m Progress +parseSelectProgress :: (MonadIO m) => ByteString -> m Progress parseSelectProgress xmldata = do r <- parseRoot $ LB.fromStrict xmldata let bScanned = T.concat $ r $/ element "BytesScanned" &/ content diff --git a/test/LiveServer.hs b/test/LiveServer.hs index 7f73070..b946da1 100644 --- a/test/LiveServer.hs +++ b/test/LiveServer.hs @@ -50,7 +50,7 @@ tests :: TestTree tests = testGroup "Tests" [liveServerUnitTests] -- conduit that generates random binary stream of given length -randomDataSrc :: MonadIO m => Int64 -> C.ConduitM () ByteString m () +randomDataSrc :: (MonadIO m) => Int64 -> C.ConduitM () ByteString m () randomDataSrc = genBS where concatIt bs n = @@ -68,7 +68,7 @@ randomDataSrc = genBS yield $ concatIt byteArr64 oneMiB genBS (s - oneMiB) -mkRandFile :: R.MonadResource m => Int64 -> m FilePath +mkRandFile :: (R.MonadResource m) => Int64 -> m FilePath mkRandFile size = do dir <- liftIO getTemporaryDirectory C.runConduit $ randomDataSrc size C..| CB.sinkTempFile dir "miniohstest.random"