{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -O0 #-} -- TODO https://github.com/haskell-servant/servant/issues/986

module Cachix.Client.Servant
  ( isErr
  , cachixClient
  , cachixBCClient
  , cachixBCStreamingClient
  , runAuthenticatedClient
  , Cachix.Client.Servant.ClientError
  ) where

import           Protolude

import qualified Cachix.Api as Api
import           Cachix.Api.Error
import qualified Cachix.Client.Config as Config
import qualified Cachix.Client.Env as Env
import qualified Cachix.Client.Exception as Exception
import           Network.HTTP.Types (Status)
import           Servant.API.Generic
import           Servant.Auth             ()
import           Servant.Auth.Client      (Token)
import qualified Servant.Client
import           Servant.Client.Generic   (AsClientT)
import           Servant.Client.Streaming hiding (ClientError)
import           Servant.Conduit          ()

type ClientError =
#if !MIN_VERSION_servant_client(0,16,0)
  Servant.Client.ServantError
#else
  Servant.Client.ClientError
#endif

isErr :: ClientError -> Status -> Bool
#if MIN_VERSION_servant_client(0,16,0)
isErr :: ClientError -> Status -> Bool
isErr (Servant.Client.FailureResponse _ resp :: Response
resp) status :: Status
status
#else
isErr (Servant.Client.FailureResponse resp) status
#endif
  | Response -> Status
forall a. ResponseF a -> Status
Servant.Client.responseStatusCode Response
resp Status -> Status -> Bool
forall a. Eq a => a -> a -> Bool
== Status
status = Bool
True
isErr _ _ = Bool
False

cachixClient :: Api.CachixAPI (AsClientT ClientM)
cachixClient :: CachixAPI (AsClientT ClientM)
cachixClient = ToServant CachixAPI (AsClientT ClientM)
-> CachixAPI (AsClientT ClientM)
forall (routes :: * -> *) mode.
GenericServant routes mode =>
ToServant routes mode -> routes mode
fromServant (ToServant CachixAPI (AsClientT ClientM)
 -> CachixAPI (AsClientT ClientM))
-> ToServant CachixAPI (AsClientT ClientM)
-> CachixAPI (AsClientT ClientM)
forall a b. (a -> b) -> a -> b
$ Proxy
  ("api"
   :> ("v1"
       :> (((("logout"
              :> (CachixAuth
                  :> Post302
                       '[JSON]
                       '[Header "Set-Cookie" SetCookie, Header "Set-Cookie" SetCookie]))
             :<|> ("login" :> Get302 '[JSON] '[]))
            :<|> (("login"
                   :> ("callback"
                       :> (QueryParam "code" Text
                           :> (QueryParam "state" Text
                               :> Get302
                                    '[JSON]
                                    '[Header "Set-Cookie" SetCookie,
                                      Header "Set-Cookie" SetCookie]))))
                  :<|> (CachixAuth :> ("user" :> Get '[JSON] User))))
           :<|> (((CachixAuth
                   :> ("token" :> (ReqBody '[JSON] CreateToken :> Post '[JSON] Text)))
                  :<|> (CachixAuth
                        :> ("cache" :> Get '[JSON] [BinaryCacheAuthenticated])))
                 :<|> (("cache"
                        :> (Capture "name" Text
                            :> ((((CachixAuth :> Get '[JSON] BinaryCache)
                                  :<|> (CachixAuth
                                        :> (ReqBody '[JSON] BinaryCacheCreate
                                            :> Post '[JSON] NoContent)))
                                 :<|> ((CachixAuth :> Delete '[JSON] NoContent)
                                       :<|> (CachixAuth
                                             :> ("nix-cache-info"
                                                 :> Get '[XNixCacheInfo, JSON] NixCacheInfo))))
                                :<|> (((CachixAuth
                                        :> (Capture "narinfo" NarInfoC
                                            :> Get '[XNixNarInfo, JSON] NarInfo))
                                       :<|> (CachixAuth :> (Capture "narinfo" NarInfoC :> Head)))
                                      :<|> ((CachixAuth
                                             :> ("narinfo"
                                                 :> (Summary
                                                       "Given a list of store hashes, return a list of those that are missing"
                                                     :> (ReqBody '[JSON] [Text]
                                                         :> Post '[JSON] [Text]))))
                                            :<|> ((Capture "narinfo" NarInfoC
                                                   :> (ReqBody '[JSON] NarInfoCreate
                                                       :> Post '[JSON] NoContent))
                                                  :<|> (CachixAuth
                                                        :> ("key"
                                                            :> (ReqBody '[JSON] SigningKeyCreate
                                                                :> Post '[JSON] NoContent)))))))))
                       :<|> (("install"
                              :> ((Summary
                                     "Redirects to a tarball containing nix expression to build the latest version of cachix cli"
                                   :> Get302 '[JSON] '[])
                                  :<|> (Summary
                                          "Redirects to a tarball containing nix expression to build given version of cachix cli"
                                        :> (Capture "version" Text :> Get302 '[JSON] '[]))))
                             :<|> ("github"
                                   :> ((CachixAuth :> ("orgs" :> Get '[JSON] [Text]))
                                       :<|> (CachixAuth
                                             :> ("orgs"
                                                 :> (Capture "org" Text
                                                     :> ("teams"
                                                         :> Get '[JSON] [GitHubTeam]))))))))))))
-> Client
     ClientM
     ("api"
      :> ("v1"
          :> (((("logout"
                 :> (CachixAuth
                     :> Post302
                          '[JSON]
                          '[Header "Set-Cookie" SetCookie, Header "Set-Cookie" SetCookie]))
                :<|> ("login" :> Get302 '[JSON] '[]))
               :<|> (("login"
                      :> ("callback"
                          :> (QueryParam "code" Text
                              :> (QueryParam "state" Text
                                  :> Get302
                                       '[JSON]
                                       '[Header "Set-Cookie" SetCookie,
                                         Header "Set-Cookie" SetCookie]))))
                     :<|> (CachixAuth :> ("user" :> Get '[JSON] User))))
              :<|> (((CachixAuth
                      :> ("token" :> (ReqBody '[JSON] CreateToken :> Post '[JSON] Text)))
                     :<|> (CachixAuth
                           :> ("cache" :> Get '[JSON] [BinaryCacheAuthenticated])))
                    :<|> (("cache"
                           :> (Capture "name" Text
                               :> ((((CachixAuth :> Get '[JSON] BinaryCache)
                                     :<|> (CachixAuth
                                           :> (ReqBody '[JSON] BinaryCacheCreate
                                               :> Post '[JSON] NoContent)))
                                    :<|> ((CachixAuth :> Delete '[JSON] NoContent)
                                          :<|> (CachixAuth
                                                :> ("nix-cache-info"
                                                    :> Get '[XNixCacheInfo, JSON] NixCacheInfo))))
                                   :<|> (((CachixAuth
                                           :> (Capture "narinfo" NarInfoC
                                               :> Get '[XNixNarInfo, JSON] NarInfo))
                                          :<|> (CachixAuth :> (Capture "narinfo" NarInfoC :> Head)))
                                         :<|> ((CachixAuth
                                                :> ("narinfo"
                                                    :> (Summary
                                                          "Given a list of store hashes, return a list of those that are missing"
                                                        :> (ReqBody '[JSON] [Text]
                                                            :> Post '[JSON] [Text]))))
                                               :<|> ((Capture "narinfo" NarInfoC
                                                      :> (ReqBody '[JSON] NarInfoCreate
                                                          :> Post '[JSON] NoContent))
                                                     :<|> (CachixAuth
                                                           :> ("key"
                                                               :> (ReqBody '[JSON] SigningKeyCreate
                                                                   :> Post
                                                                        '[JSON] NoContent)))))))))
                          :<|> (("install"
                                 :> ((Summary
                                        "Redirects to a tarball containing nix expression to build the latest version of cachix cli"
                                      :> Get302 '[JSON] '[])
                                     :<|> (Summary
                                             "Redirects to a tarball containing nix expression to build given version of cachix cli"
                                           :> (Capture "version" Text :> Get302 '[JSON] '[]))))
                                :<|> ("github"
                                      :> ((CachixAuth :> ("orgs" :> Get '[JSON] [Text]))
                                          :<|> (CachixAuth
                                                :> ("orgs"
                                                    :> (Capture "org" Text
                                                        :> ("teams"
                                                            :> Get '[JSON] [GitHubTeam]))))))))))))
forall api.
HasClient ClientM api =>
Proxy api -> Client ClientM api
client Proxy CachixServantAPI
Proxy
  ("api"
   :> ("v1"
       :> (((("logout"
              :> (CachixAuth
                  :> Post302
                       '[JSON]
                       '[Header "Set-Cookie" SetCookie, Header "Set-Cookie" SetCookie]))
             :<|> ("login" :> Get302 '[JSON] '[]))
            :<|> (("login"
                   :> ("callback"
                       :> (QueryParam "code" Text
                           :> (QueryParam "state" Text
                               :> Get302
                                    '[JSON]
                                    '[Header "Set-Cookie" SetCookie,
                                      Header "Set-Cookie" SetCookie]))))
                  :<|> (CachixAuth :> ("user" :> Get '[JSON] User))))
           :<|> (((CachixAuth
                   :> ("token" :> (ReqBody '[JSON] CreateToken :> Post '[JSON] Text)))
                  :<|> (CachixAuth
                        :> ("cache" :> Get '[JSON] [BinaryCacheAuthenticated])))
                 :<|> (("cache"
                        :> (Capture "name" Text
                            :> ((((CachixAuth :> Get '[JSON] BinaryCache)
                                  :<|> (CachixAuth
                                        :> (ReqBody '[JSON] BinaryCacheCreate
                                            :> Post '[JSON] NoContent)))
                                 :<|> ((CachixAuth :> Delete '[JSON] NoContent)
                                       :<|> (CachixAuth
                                             :> ("nix-cache-info"
                                                 :> Get '[XNixCacheInfo, JSON] NixCacheInfo))))
                                :<|> (((CachixAuth
                                        :> (Capture "narinfo" NarInfoC
                                            :> Get '[XNixNarInfo, JSON] NarInfo))
                                       :<|> (CachixAuth :> (Capture "narinfo" NarInfoC :> Head)))
                                      :<|> ((CachixAuth
                                             :> ("narinfo"
                                                 :> (Summary
                                                       "Given a list of store hashes, return a list of those that are missing"
                                                     :> (ReqBody '[JSON] [Text]
                                                         :> Post '[JSON] [Text]))))
                                            :<|> ((Capture "narinfo" NarInfoC
                                                   :> (ReqBody '[JSON] NarInfoCreate
                                                       :> Post '[JSON] NoContent))
                                                  :<|> (CachixAuth
                                                        :> ("key"
                                                            :> (ReqBody '[JSON] SigningKeyCreate
                                                                :> Post '[JSON] NoContent)))))))))
                       :<|> (("install"
                              :> ((Summary
                                     "Redirects to a tarball containing nix expression to build the latest version of cachix cli"
                                   :> Get302 '[JSON] '[])
                                  :<|> (Summary
                                          "Redirects to a tarball containing nix expression to build given version of cachix cli"
                                        :> (Capture "version" Text :> Get302 '[JSON] '[]))))
                             :<|> ("github"
                                   :> ((CachixAuth :> ("orgs" :> Get '[JSON] [Text]))
                                       :<|> (CachixAuth
                                             :> ("orgs"
                                                 :> (Capture "org" Text
                                                     :> ("teams"
                                                         :> Get '[JSON] [GitHubTeam]))))))))))))
Api.servantApi

cachixBCClient :: Text -> Api.BinaryCacheAPI (AsClientT ClientM)
cachixBCClient :: Text -> BinaryCacheAPI (AsClientT ClientM)
cachixBCClient name :: Text
name = ToServant BinaryCacheAPI (AsClientT ClientM)
-> BinaryCacheAPI (AsClientT ClientM)
forall (routes :: * -> *) mode.
GenericServant routes mode =>
ToServant routes mode -> routes mode
fromServant (ToServant BinaryCacheAPI (AsClientT ClientM)
 -> BinaryCacheAPI (AsClientT ClientM))
-> ToServant BinaryCacheAPI (AsClientT ClientM)
-> BinaryCacheAPI (AsClientT ClientM)
forall a b. (a -> b) -> a -> b
$ CachixAPI (AsClientT ClientM)
-> Text
-> (((Token -> ClientM BinaryCache)
     :<|> (Token -> BinaryCacheCreate -> ClientM NoContent))
    :<|> ((Token -> ClientM NoContent)
          :<|> (Token -> ClientM NixCacheInfo)))
   :<|> (((Token -> NarInfoC -> ClientM NarInfo)
          :<|> (Token -> NarInfoC -> ClientM NoContent))
         :<|> ((Token -> [Text] -> ClientM [Text])
               :<|> ((NarInfoC -> NarInfoCreate -> ClientM NoContent)
                     :<|> (Token -> SigningKeyCreate -> ClientM NoContent))))
forall route.
CachixAPI route
-> route
   :- ("cache"
       :> (Capture "name" Text :> ToServantApi BinaryCacheAPI))
Api.cache CachixAPI (AsClientT ClientM)
cachixClient Text
name

cachixBCStreamingClient :: Text -> Api.BinaryCacheStreamingAPI (AsClientT ClientM)
cachixBCStreamingClient :: Text -> BinaryCacheStreamingAPI (AsClientT ClientM)
cachixBCStreamingClient name :: Text
name = ToServant BinaryCacheStreamingAPI (AsClientT ClientM)
-> BinaryCacheStreamingAPI (AsClientT ClientM)
forall (routes :: * -> *) mode.
GenericServant routes mode =>
ToServant routes mode -> routes mode
fromServant (ToServant BinaryCacheStreamingAPI (AsClientT ClientM)
 -> BinaryCacheStreamingAPI (AsClientT ClientM))
-> ToServant BinaryCacheStreamingAPI (AsClientT ClientM)
-> BinaryCacheStreamingAPI (AsClientT ClientM)
forall a b. (a -> b) -> a -> b
$ Proxy
  ("api"
   :> ("v1"
       :> ("cache"
           :> (Capture "name" Text
               :> ((CachixAuth
                    :> ("nar"
                        :> (Capture "nar" NarFileName
                            :> StreamGet
                                 NoFraming OctetStream (ConduitT () ByteString (ResourceT IO) ()))))
                   :<|> (("nar"
                          :> (StreamBody
                                NoFraming XNixNar (ConduitT () ByteString (ResourceT IO) ())
                              :> Post '[JSON] NoContent))
                         :<|> (CachixAuth
                               :> ("serve"
                                   :> (Capture "storehash" Text
                                       :> (CaptureAll "filepath" Text
                                           :> (Summary "Serve a file from a given store path"
                                               :> Get
                                                    '[OctetStream]
                                                    (Headers
                                                       '[Header "X-Content-Type-Options" Text]
                                                       ByteString))))))))))))
-> Text
-> (Token
    -> NarFileName
    -> ClientM (ConduitT () ByteString (ResourceT IO) ()))
   :<|> ((ConduitT () ByteString (ResourceT IO) ()
          -> ClientM NoContent)
         :<|> (Token
               -> Text
               -> [Text]
               -> ClientM
                    (Headers '[Header "X-Content-Type-Options" Text] ByteString)))
forall api.
HasClient ClientM api =>
Proxy api -> Client ClientM api
client (Proxy BinaryCachStreamingServantAPI
forall k (t :: k). Proxy t
Proxy :: Proxy Api.BinaryCachStreamingServantAPI) Text
name

runAuthenticatedClient :: NFData a => Env.Env -> (Token -> ClientM a) -> IO a
runAuthenticatedClient :: Env -> (Token -> ClientM a) -> IO a
runAuthenticatedClient env :: Env
env m :: Token -> ClientM a
m = do
  Config
config <- Either CachixException Config -> IO Config
forall exc (m :: * -> *) a.
(Exception exc, MonadThrow m) =>
Either exc a -> m a
escalate (Either CachixException Config -> IO Config)
-> Either CachixException Config -> IO Config
forall a b. (a -> b) -> a -> b
$ CachixException -> Maybe Config -> Either CachixException Config
forall e a. e -> Maybe a -> Either e a
maybeToEither (Text -> CachixException
Exception.NoConfig
     "Start with visiting https://cachix.org and copying the token to $ cachix authtoken <token>") (Env -> Maybe Config
Env.config Env
env)
  Either ClientError a -> IO a
forall exc (m :: * -> *) a.
(Exception exc, MonadThrow m) =>
Either exc a -> m a
escalate (Either ClientError a -> IO a)
-> (ClientM a -> IO (Either ClientError a)) -> ClientM a -> IO a
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< (ClientM a -> ClientEnv -> IO (Either ClientError a)
forall a.
NFData a =>
ClientM a -> ClientEnv -> IO (Either ClientError a)
`runClientM` Env -> ClientEnv
Env.clientenv Env
env) (ClientM a -> IO a) -> ClientM a -> IO a
forall a b. (a -> b) -> a -> b
$
    Token -> ClientM a
m (Config -> Token
Config.authToken Config
config)