packages feed

yesod-fb (empty) → 0.1

raw patch · 5 files changed

+193/−0 lines, 5 filesdep +aesondep +basedep +bytestringsetup-changed

Dependencies added: aeson, base, bytestring, conduit, crypto-api, fb, http-conduit, text, wai, yesod-core

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c)2012, Felipe Lessa++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Felipe Lessa nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README view
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Yesod/Facebook.hs view
@@ -0,0 +1,121 @@+{-# LANGUAGE OverloadedStrings #-}+module Yesod.Facebook+  ( -- * Running @FacebookT@ actions inside @GHandler@+    YesodFacebook(..)+  , runFacebookT+  , runNoAuthFacebookT+  , getFbCredentials++    -- * Real-time update notifications+  , parseRealTimeUpdateNotifications+  , answerRealTimeUpdateChallenge+  ) where++import Control.Applicative ((<$>))+import Crypto.Classes (constTimeEq)+import Data.ByteString.Char8 () -- IsString+import qualified Data.Aeson as A+import qualified Data.ByteString.Lazy.Char8 as L+import qualified Data.Conduit as C+import qualified Data.Conduit.List as CL+import qualified Data.Text.Encoding as TE+import qualified Facebook as FB+import qualified Network.Wai as W+import qualified Network.HTTP.Conduit as HTTP+import qualified Yesod.Core as Y+++-- | The 'YesodFacebook' class for foundation datatypes that+-- support running 'FB.FacebookT' actions.+class Y.Yesod master => YesodFacebook master where+  -- | The credentials of your app.+  fbCredentials :: master -> FB.Credentials+  -- | HTTP manager used for contacting Facebook (may be the same+  -- as the one used for @yesod-auth@).+  fbHttpManager :: master -> HTTP.Manager+++-- | Returns Facebook's 'FB.Credentials' from inside a+-- 'Y.GHandler'.  Just a convenience wrapper around+-- 'fbCredentials'.+getFbCredentials :: YesodFacebook master =>+                    Y.GHandler sub master FB.Credentials+getFbCredentials = fbCredentials <$> Y.getYesod+++-- | Run a 'FacebookT' action inside a 'Y.GHandler' using your+-- credentials.+runFacebookT ::+     YesodFacebook master =>+     FB.FacebookT FB.Auth (Y.GHandler sub master) a+  -> Y.GHandler sub master a+runFacebookT act = do+  master <- Y.getYesod+  let creds   = fbCredentials master+      manager = fbHttpManager master+  FB.runFacebookT creds manager act+++-- | Run a 'FacebookT' action inside a 'Y.GHandler' without using+-- your credentials.  Usually you won't need to use this function+-- but it's provided for completeness' sake.+runNoAuthFacebookT ::+     YesodFacebook master =>+     FB.FacebookT FB.NoAuth (Y.GHandler sub master) a+  -> Y.GHandler sub master a+runNoAuthFacebookT act = do+  master <- Y.getYesod+  let manager = fbHttpManager master+  FB.runNoAuthFacebookT manager act+++----------------------------------------------------------------------+++-- | Same as 'getRealTimeUpdateNotifications' but does the+-- heavy-lifting for you.  Throws an exception whenever any step+-- fails (signature header not found, invalid signature, invalid+-- JSON).+parseRealTimeUpdateNotifications ::+  (YesodFacebook master, A.FromJSON a) =>+  Y.GHandler sub master (FB.RealTimeUpdateNotification a)+parseRealTimeUpdateNotifications = do+  let myFail = fail . ("parseRealTimeUpdateNotifications: " ++)+  -- Get request's signature.+  waiReq <- Y.waiRequest+  case lookup "X-Hub-Signature" (W.requestHeaders waiReq) of+    Nothing  -> myFail "X-Hub-Signature not found."+    Just sig -> do+      uncheckedData <- L.fromChunks <$> Y.lift (W.requestBody waiReq C.$$ CL.consume)+      mcheckedData <- runFacebookT $ FB.verifyRealTimeUpdateNotifications sig uncheckedData+      case mcheckedData of+        Nothing -> myFail "Signature is invalid."+        Just checkedData ->+          case A.decode checkedData of+            Nothing  -> myFail "Could not decode data."+            Just ret -> return ret+++-- | Answer Facebook's challenge if the 'FB.RealTimeUpdateToken'+-- matches.+--+-- Whenever you modify your subscriptions, Facebook will try to+-- contact your server with the 'FB.RealTimeUpdateToken' that you+-- gave on your call to 'FB.modifySubscription'.  This function+-- will correctly answer Facebook's challenge if the+-- 'FB.RealTimeUpdateToken' matches, otherwise it will return+-- 'Y.notFound'.+answerRealTimeUpdateChallenge ::+     FB.RealTimeUpdateToken+  -> Y.GHandler sub master Y.RepPlain+answerRealTimeUpdateChallenge token = do+  mhubMode        <- Y.lookupGetParam "hub.mode"+  mhubChallenge   <- Y.lookupGetParam "hub.challenge"+  mhubVerifyToken <- Y.lookupGetParam "hub.verify_token"+  case (mhubMode, mhubChallenge, mhubVerifyToken) of+    -- FIXME: Is hub.mode always subscribe?  Facebook's docs say+    -- so, but I don't believe them =).+    (Just "subscribe", Just hubChallenge, Just hubVerifyToken)+      | TE.encodeUtf8 hubVerifyToken `constTimeEq` token ->+          return $ Y.RepPlain (Y.toContent hubChallenge)+    _ -> Y.notFound
+ yesod-fb.cabal view
@@ -0,0 +1,40 @@+Name:                yesod-fb+Version:             0.1+Synopsis:            Useful glue functions between the fb library and Yesod.+Homepage:            https://github.com/meteficha/yesod-fb+License:             BSD3+License-file:        LICENSE+Author:              Felipe Lessa+Maintainer:          Felipe Lessa <felipe.lessa@gmail.com>+Category:            Web+Build-type:          Simple+Cabal-version:       >= 1.6+Extra-source-files:  README++Description:+  This package contains useful glue functions between the fb+  package (http://hackage.haskell.org/package/fb) and Yesod.+  These functions can't be included on the fb package itself+  because it should not depend on Yesod.++Source-repository head+  type:     git+  location: git://github.com/meteficha/yesod-fb.git++Library+  hs-source-dirs: src++  Build-depends:   base         >= 4.3     && < 5+                 , yesod-core   == 1.1.*+                 , fb           >= 0.11.1  && < 0.12++                 , crypto-api+                 , http-conduit+                 , wai+                 , conduit+                 , aeson+                 , text+                 , bytestring++  Exposed-modules: Yesod.Facebook+  GHC-options: -Wall