async-refresh-tokens 0.1.0 → 0.2.0.0
raw patch · 6 files changed
+38/−37 lines, 6 filesdep +microlensdep +microlens-thdep −lensdep ~async-refresh
Dependencies added: microlens, microlens-th
Dependencies removed: lens
Dependency ranges changed: async-refresh
Files
- README.md +16/−19
- async-refresh-tokens.cabal +4/−3
- src/Control/Concurrent/Async/Refresh/Tokens.hs +1/−1
- src/Control/Concurrent/Async/Refresh/Tokens/Conf.hs +1/−1
- src/Control/Concurrent/Async/Refresh/Tokens/Lenses.hs +1/−1
- test/Spec.hs +15/−12
README.md view
@@ -1,24 +1,21 @@-# async-refresh-tokens+# async-refresh-tokens [](https://hackage.haskell.org/package/async-refresh-tokens) [](https://www.stackage.org/package/async-refresh-tokens) [](https://travis-ci.org/mtesseract/async-refresh-tokens) -About-=====+### About This is Haskell library built on top of the async-refresh package implementing the logic for refreshing of expiring access tokens. -Usage-=====+### Usage -- Create new token types. Using the `DataKinds` extension we can do- this via `data MyAppTokens = TokenFoo | TokenBar`.+- Create new token types. - Make the tokens be instances of the `IsToken` type classes by defining the `tokenScopes` method and (optionally) `tokenName` (a human readable label for this token). -- Create new token stores (which are basically `TVar's containing the- tokens wrapped in `Either SomeException`) using- `newEmptyTokenStore`.+- Use `newEmptyTokenStore` to create a new token stores (token stores+ are basically `TVar`s containing the tokens wrapped in `Either+ SomeException`). - Create a new configuration by adjusting `defaultTokenConf` using the functions `tokenConfAddRequest` and `tokenConfSetFactor`. The@@ -29,22 +26,22 @@ - Use `newTokenRefresher` to initiate token refreshing for each registered token refreshing request. -Example-=======+- To use the current token, extract it from the `TVar` using+ `readTVar` (and pattern matching on `Right`). +### Example+ ```-{-# LANGUAGE DataKinds #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE PolyKinds #-} -data MyAppTokens = TokenFoo | TokenBar+data TokenFoo -instance IsToken 'TokenFoo where+instance IsToken TokenFoo where tokenScopes _ = ["foo.read", "foo.write"] -createTokenStoreFoo :: IO (TokenStore 'TokenFoo)-createTokenStoreFoo = runStderrLoggingT $ do- tokenFoo <- newEmptyTokenStore (Proxy :: Proxy 'TokenFoo)+createTokenStoreFoo :: LoggingT IO (TokenStore TokenFoo)+createTokenStoreFoo = do+ tokenFoo <- newEmptyTokenStore (Proxy :: Proxy TokenFoo) let conf = defaultTokenConf & tokenConfAddRequest (RequestToken tokenFoo actionFoo) _ <- newTokenRefresher conf
async-refresh-tokens.cabal view
@@ -1,5 +1,5 @@ name: async-refresh-tokens-version: 0.1.0+version: 0.2.0.0 synopsis: Package implementing core logic for refreshing of expiring access tokens description: This package can be used for renewal of expiring access tokens according to user-provided actions. Tokens will be stored in a@@ -23,11 +23,12 @@ , Control.Concurrent.Async.Refresh.Tokens.Prelude , Control.Concurrent.Async.Refresh.Tokens.Conf build-depends: base >= 4.7 && < 5- , async-refresh+ , async-refresh >= 0.2.0.2 , monad-logger , lifted-async , stm- , lens+ , microlens >= 0.4+ , microlens-th >= 0.4 , text , monad-control , safe-exceptions
src/Control/Concurrent/Async/Refresh/Tokens.hs view
@@ -44,7 +44,7 @@ import Control.Concurrent.Async.Refresh.Tokens.Conf import qualified Control.Concurrent.Async.Refresh.Tokens.Lenses as Lens import Control.Concurrent.Async.Refresh.Tokens.Types-import Control.Lens+import Lens.Micro -- | Start a new token refresher for the provided configuration. -- Returns a 'TokenRefresher' handle representing the running token
src/Control/Concurrent/Async/Refresh/Tokens/Conf.hs view
@@ -19,7 +19,7 @@ import qualified Control.Concurrent.Async.Refresh.Tokens.Lenses as Lens import Control.Concurrent.Async.Refresh.Tokens.Types-import Control.Lens+import Lens.Micro -- | Produce default token configuration. defaultTokenConf :: TokenConf m
src/Control/Concurrent/Async/Refresh/Tokens/Lenses.hs view
@@ -15,7 +15,7 @@ module Control.Concurrent.Async.Refresh.Tokens.Lenses where -import Control.Lens+import Lens.Micro.TH import Control.Concurrent.Async.Refresh.Tokens.Types makeFields ''TokenConf
test/Spec.hs view
@@ -1,6 +1,4 @@-{-# LANGUAGE DataKinds #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE PolyKinds #-} module Main where @@ -16,24 +14,29 @@ import Test.Framework.Providers.HUnit (testCase) import Test.HUnit ((@?=)) -data TestTokens = TokenFoo | TokenBar+data TokenFoo -instance IsToken 'TokenFoo where- tokenScopes _ = ["foo.read"]+instance IsToken TokenFoo where+ tokenScopes _ = ["foo.read", "foo.write"] -oneTimeRefresh :: IO ()-oneTimeRefresh = runStderrLoggingT $ do- tokenFoo <- newEmptyTokenStore (Proxy :: Proxy 'TokenFoo)+createTokenStoreFoo :: LoggingT IO (TokenStore TokenFoo)+createTokenStoreFoo = do+ tokenFoo <- newEmptyTokenStore (Proxy :: Proxy TokenFoo) let conf = defaultTokenConf & tokenConfAddRequest (RequestToken tokenFoo actionFoo) _ <- newTokenRefresher conf- liftIO $ threadDelay (10 ^ 6 + 10 ^ 5)- (Right token) <- liftIO . atomically $ readTVar tokenFoo- liftIO $ token @?= Token "foo"+ return tokenFoo where actionFoo :: (MonadIO m, IsToken t) => m (RefreshResult (Token t)) actionFoo =- return $ RefreshResult (Token "foo") Nothing+ return $ RefreshResult (Token "secret-foo-token") Nothing++oneTimeRefresh :: IO ()+oneTimeRefresh = runStderrLoggingT $ do+ tokenFoo <- createTokenStoreFoo+ liftIO $ threadDelay (10 ^ 6 + 10 ^ 5)+ (Right token) <- liftIO . atomically $ readTVar tokenFoo+ liftIO $ token @?= Token "secret-foo-token" main :: IO () main = do