clckwrks-0.13.0: Clckwrks/Plugin.hs
{-# LANGUAGE RecordWildCards, FlexibleContexts, Rank2Types, OverloadedStrings #-}
module Clckwrks.Plugin where
import Clckwrks
import Clckwrks.Admin.Route (routeAdmin)
import Clckwrks.BasicTemplate (basicTemplate)
import Clckwrks.Page.Acid (GetPageTitle(..), IsPublishedPage(..))
import Clckwrks.Page.Atom (handleAtomFeed)
import Clckwrks.ProfileData.Route (routeProfileData)
import Clckwrks.Page.PreProcess (pageCmd)
import Clckwrks.Server (checkAuth)
import Control.Monad.State (MonadState(get))
import Data.Text (Text)
import qualified Data.Text.Lazy as TL
import Happstack.Auth (handleAuthProfile)
import Happstack.Server.FileServe.BuildingBlocks (guessContentTypeM, isSafePath, serveFile)
import Network.URI (unEscapeString)
import System.FilePath ((</>), makeRelative, splitDirectories)
import Web.Plugins.Core (Plugin(..), addHandler, getTheme, getPluginRouteFn, initPlugin)
import Paths_clckwrks (getDataDir)
themeTemplate :: ( EmbedAsChild (ClckT ClckURL (ServerPartT IO)) headers
, EmbedAsChild (ClckT ClckURL (ServerPartT IO)) body) =>
ClckPlugins
-> Text
-> headers
-> body
-> ClckT ClckURL (ServerPartT IO) Response
themeTemplate plugins ttl hdrs bdy =
do mTheme <- getTheme plugins
case mTheme of
Nothing -> escape $ internalServerError $ toResponse $ ("No theme package is loaded." :: Text)
(Just theme) -> fmap toResponse $ unXMLGenT $ (_themeTemplate theme ttl hdrs bdy)
clckHandler :: (ClckURL -> [(Text, Maybe Text)] -> Text)
-> ClckPlugins
-> [Text]
-> ClckT ClckURL (ServerPartT IO) Response
clckHandler showRouteFn _plugins paths =
case parseSegments fromPathSegments paths of
(Left e) -> notFound $ toResponse (show e)
(Right u) -> routeClck u
routeClck :: ClckURL
-> Clck ClckURL Response
routeClck url' =
do url <- checkAuth url'
setUnique 0
case url of
(ViewPage pid) ->
do r <- query (GetPageTitle pid)
case r of
Nothing ->
notFound $ toResponse ("Invalid PageId " ++ show (unPageId pid))
(Just (title, slug)) ->
seeOtherURL (ViewPageSlug pid (toSlug title slug))
(ViewPageSlug pid _slug) ->
do published <- query (IsPublishedPage pid)
if published
then do setCurrentPage pid
cs <- get
ttl <- getPageTitle
bdy <- getPageContent
themeTemplate (plugins cs) ttl () bdy
else do notFound $ toResponse ("Invalid PageId " ++ show (unPageId pid))
(Blog) ->
do p <- plugins <$> get
mTheme <- getTheme p
case mTheme of
Nothing -> escape $ internalServerError $ toResponse $ ("No theme package is loaded." :: Text)
(Just theme) -> fmap toResponse $ unXMLGenT $ themeBlog theme
AtomFeed ->
do handleAtomFeed
(ThemeData fp') ->
do p <- plugins <$> get
mTheme <- getTheme p
case mTheme of
Nothing -> notFound $ toResponse ("No theme package is loaded." :: Text)
(Just theme) ->
do fp <- liftIO $ themeDataDir theme
let fp'' = makeRelative "/" (unEscapeString fp')
if not (isSafePath (splitDirectories fp''))
then notFound (toResponse ())
else serveFile (guessContentTypeM mimeTypes) (fp </> "data" </> fp'')
(PluginData plugin fp') ->
do pp <- liftIO getDataDir
let fp'' = makeRelative "/" (unEscapeString fp')
if not (isSafePath (splitDirectories fp''))
then notFound (toResponse ())
else serveFile (guessContentTypeM mimeTypes) (pp </> "data" </> fp'')
(Admin adminURL) ->
routeAdmin adminURL
(Profile profileDataURL) ->
do nestURL Profile $ routeProfileData profileDataURL
(Auth apURL) ->
do Acid{..} <- acidState <$> get
u <- showURL $ Profile CreateNewProfileData
nestURL Auth $ handleAuthProfile acidAuth acidProfile basicTemplate Nothing Nothing u apURL
clckInit :: ClckPlugins
-> IO (Maybe Text)
clckInit plugins =
do (Just clckShowFn) <- getPluginRouteFn plugins (pluginName clckPlugin)
addPreProc plugins (pageCmd clckShowFn)
addHandler plugins (pluginName clckPlugin) (clckHandler clckShowFn)
return Nothing
clckPlugin :: Plugin ClckURL Theme (ClckT ClckURL (ServerPartT IO) Response) (ClckT ClckURL IO ()) ClckwrksConfig ([TL.Text -> ClckT ClckURL IO TL.Text])
clckPlugin = Plugin
{ pluginName = "clck"
, pluginInit = clckInit
, pluginDepends = []
, pluginToPathInfo = toPathInfo
, pluginPostHook = return ()
}
plugin :: ClckPlugins
-> Text
-> IO (Maybe Text)
plugin plugins baseURI =
initPlugin plugins baseURI clckPlugin