packages feed

lambdacms-core 0.0.8.0 → 0.1.0.0

raw patch · 7 files changed

+220/−355 lines, 7 files

Files

CHANGES.md view
@@ -4,11 +4,14 @@ #### dev * ... +#### 0.1.0.0+* Fixes compilation issues with LTS Haskell 2.x+ #### 0.0.8.0-* Fixed action logging to also work outside of LambdaCms.Core+* Fixes action logging to also work outside of LambdaCms.Core  #### 0.0.7.2-* Fixed broken package+* Fixes broken package  #### 0.0.7.1 * Initial upload to Hackage
LICENSE view
@@ -1,1 +1,20 @@-MIT+Copyright (c) 2015 Hoppinger BV, http://lambdacms.org++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be+included in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
LambdaCms/Core/Foundation.hs view
@@ -39,7 +39,7 @@ import           Network.Wai                (requestMethod) import           Text.Hamlet                (hamletFile) import           Yesod-import           Yesod.Auth+import           Yesod.Auth                 hiding (Authenticated)  -- | Foundation type. data CoreAdmin = CoreAdmin
LambdaCms/I18n.hs view
@@ -4,9 +4,11 @@  import           Data.Text import           LambdaCms.I18n.Dutch+import           LambdaCms.I18n.Italian import           System.Locale  -- | Helper function to get the right time locale. lambdaCmsTimeLocale :: [Text] -> TimeLocale lambdaCmsTimeLocale ("nl":_) = dutchTimeLocale+lambdaCmsTimeLocale ("it":_) = italianTimeLocale lambdaCmsTimeLocale _        = defaultTimeLocale
+ LambdaCms/I18n/Italian.hs view
@@ -0,0 +1,35 @@+module LambdaCms.I18n.Italian where++import           System.Locale++-- | Italian time locale.+italianTimeLocale :: TimeLocale+italianTimeLocale =  TimeLocale+    {+        wDays  = [("Domenica",  "Do"),  ("Lunedì",   "Lu"),+                  ("Martedì",   "Ma"),  ("Mercoledì","Me"),+                  ("Giovedì",   "Gi"),  ("Venerdì",  "Ve"),+                  ("Sabato",    "Sa")],++        months = [("Gennaio",   "Gen"), ("Febbraio",  "Feb"),+                  ("Marzo",     "Mar"), ("Aprile",    "Apr"),+                  ("Maggio",    "Mag"), ("Giugno",    "Giu"),+                  ("Luglio",    "Lug"), ("Agosto",    "Ago"),+                  ("Settembre", "Set"), ("Ottobre",   "Ott"),+                  ("Novembre",  "Nov"), ("Dicembre",  "Dic")],++        intervals = [ ("anno",  "anni")+                    , ("mese",  "mesi")+                    , ("giorno","giorni")+                    , ("ora",   "ore")+                    , ("min",   "mins")+                    , ("sec",   "secs")+                    , ("usec",  "usecs")+                    ],++        amPm = ("AM", "PM"),+        dateTimeFmt = "%a %b %e %H:%M:%S %Z %Y",+        dateFmt = "%d-%m-%y",+        timeFmt = "%H:%M:%S",+        time12Fmt = "%H:%M:%S"+    }
README.md view
@@ -11,478 +11,283 @@  # Rationale -LambdaCms is a bunch of packaged libraries, containing sub-sites for the-[Yesod application framework](http://www.yesodweb.com), which allow rapid+LambdaCms is a set of packaged libraries —containing subsites for the+[Yesod application framework](http://www.yesodweb.com)— which allow rapid development of robust and highly performant websites with content management functionality.  The `lambdacms-*` packages each provide some functionality and can depend on eachother as they depend on other packages. The only mandatory package is `lambdacms-core` (this package), it provides-functionality that all other `lambdacms-*` packages can rely on.+functionality that all other `lambdacms-*` packages depend on. -As mentioned, each `lambdacms-*` package contains a sub-site which is+As mentioned, each `lambdacms-*` package contains a subsite which is "mounted" in a standard Yesod application, which we will refer to as "the base application" or simply "base".-Before a packaged sub-site can be mounted, the package needs to be+Before a packaged subsite can be mounted, the package needs to be included as a dependency to the base app's `.cabal` file.  After that some glue code needs to be added to the base app, as explained below.  In the base app we have to:-* organize the main menu of the admin backend,-* configure a the database connection,-* specify the authentication strategies, and++* configure a database connection,+* organize the admin backend's menu,+* specify the authentication strategies for admins, and * define admin user roles and their permissions. -In the base app we may optionally also:+In the base app we optionally may also:+ * override default behavior, * override UI texts, * provide a means to send email notifications, and last but not least, * write the themes so the website can actually be visited (recommended).  -# Getting started+# Setting up a site with LambdaCms -Using this guide you will create a CMS website named `mysite`.-For a real project you want to substitute this name, but for trying-out LambdaCms it is recommended to keep it for the convenience of-copy-pasting the instructions that follow.+This section walk through the steps of setting up a site with LambdaCms.   ### Prerequisites  You need to be reasonably acquinted with Haskell in order to follow-along with this guide. To learn basic Haskell skill we recommend+along with this guide. To learn basic Haskell skills we recommend Brent Yorgey's excellent [Introduction to Haskell](http://www.seas.upenn.edu/~cis194/spring13) course.  Besides Haskell you need to be somewhat familliar with:-* the web technologies (HTTP, HTML, CSS, JS, REST),-* SQL (as LambdaCms makes use of a relational database), and-* the Yesod web application framework ([book](http://yesodweb.com/book)). --### The tool chain--Make sure to have **GHC** 7.8.3+, **cabal-install** 1.20+, **happy**, **alex**-, **yesod-bin** 1.4.3.3+ installed, and their binaries available from your-shell's `$PATH`.--To check that you are good to go, you can use these commands.--    ghc -V-    cabal -V-    happy -V-    alex -V-    yesod version--In case you are **not** good to go, you may want to follow the-[installation guide on the Stackage website](http://www.stackage.org/install)-which provides instructions for all dependencies except `yesod-bin`.--Once you meet all the requirements except `yesod-bin`, install it.--    cabal install "yesod-bin >= 1.4.3.3"+* the web technologies (HTTP, HTML, CSS, JS, REST),+* RDBMS/SQL (LambdaCms makes use of a relational database), and+* the Yesod web application framework (for which an [awesome book](http://yesodweb.com/book) exists).  -### Required non-Haskell dependencies+### Non-Haskell dependencies  For the connection with the database, Haskell libraries typically compile against non-Haskell libraries. One of the following libraries needs to be available:  * For Postgres:- * Ubuntu: `libpq-dev`- * Homebrew on OSX: `postgres`-* For Mysql:-  * Ubuntu: `libmysqlclient-dev`-  * Homebrew on OSX: `mysql`-* For Sqlite-  * Ubuntu: `libsqlite3-dev`-  * Homebrew on OSX: `sqlite` -On other platforms these packages might have different names, but are-most likely available.--If you are going to use a database other than Sqlite, you also need-to install that.--### Create the base application--With the following command you create a "scaffolded" Yesod application.-The command is interactive; you need to supply some configuration values.-Pick the database of your choice, and choose a project name--    yesod init--After scaffolding `cd` into the project folder.--If you have chosen a database other than Sqlite, you need to create a-database and a sufficiently priviledged user, and supply the-credentials to the `config/setting.yml` file.---### Using LTS Haskell--To avoid spending too much time on build issues we use and recommend-[LTS Haskell](https://github.com/fpco/lts-haskell#readme).--Currently we develop and test LambdaCms only against the lastest-LTS Haskell release. As minor releases of LTS Haskell should never-contain breaking changes we only provide the major release number,-thereby automatically using the most recent minor release in that-series.--Run the following commands from within your project's root folder,-to install the most recent LTS Haskell package set in the `1.x` series.--    wget http://www.stackage.org/lts/1/cabal.config-    cabal update--The install all dependencies and build your application with (this-may take a while the first time you run it).--    cabal install --enable-tests . --max-backjumps=-1 --reorder-goals+  * Debian/Ubuntu: `libpq-dev`+  * CentOS/Fedora/RHEL: `postgresql-devel`+  * Homebrew (OSX): `postgres` -In case you experience problems with `cabal install` try adding-`-j1` as a flag (prevents concurrent building).+* For Mysql: -When you experience problems during builds, while using LTS `1.x`,-we consider this a bug. Please-[raise an issue](https://github.com/lambdacms/lambdacms-core/issues).+  * Debian/Ubuntu: `libmysqlclient-dev`+  * CentOS/Fedora/RHEL: `mysql-devel`+  * Homebrew (OSX): `mysql` -The following commands will run your scaffolded Yesdo application-in development mode.+* For Sqlite -    yesod devel+  * Debian/Ubuntu: `libsqlite3-dev`+  * CentOS/Fedora/RHEL: `sqlite-devel`+  * Homebrew (OSX): `sqlite` -Now test it by pointing the browser to `localhost:3000`.+On other platforms these packages might have different names, but are+most likely available. -If all went well you are ready to add LambdaCms to your app.+If you are going to use a database other than Sqlite (which directly writes+to a file), you need to have a database accessible from where you run your+site. This means you might have to install and setup a database server locally.  -### Add LambdaCms--LambdaCms is on Hackage! Install with: `cabal install lambdacms-core`--In the following sub-sections we explain how to install `lambdacms-core` into-the base application.  Much of what we show here can be accomplished in-many different ways, in this guide we merely provide a way to get you started.--#### Patching a new Yesod application--To setup a new LambdaCms website the easy way we created patch files to convert-a new Yesod application to a LambdaCms website. Those patches can be found in-[lambdamcs-patches](https://github.com/lambdacms/lambdacms-patches). Either clone-the repository or copy only the required patches to your local environment and-run the following command (replace `/path/to` with the actual path to the patch-file):--    patch -p1 < /path/to/lambdacms.patch--This patches all files at the same time. Documentation about how to patch files-individually can be found in the `lambdacms-patches`-[README](https://github.com/lambdacms/lambdacms-patches/blob/master/README.md).--To manually add LambdaCms to a Yesod application follow the steps below.--#### Modify the `.cabal` file+### The tool chain -First add `lambdacms-core` to the dependencies list of the `.cabal`-file (name of the file depends on the name of your project).+Make sure to have **GHC** 7.8.3+, **cabal-install** 1.20+, **happy** and **alex**+installed; and their binaries available from your shell's `$PATH`. -Add the follwing to the end of the `build-depends` section:+Use the following command to check your system meets the requirements: -```-, lambdacms-core                >= 0.0.7      && < 0.1-, wai                           >= 3.0.2      && < 3.1+```bash+for c in ghc cabal happy alex; do $c -V | head -n1; done ``` -And add the following line to the `library/exposed-modules` section:+When good to go the output should be similar to:  ```-Roles+The Glorious Glasgow Haskell Compilation System, version 7.8.4+cabal-install version 1.20.0.3+Happy Version 1.19.5 Copyright (c) 1993-1996 Andy Gill, Simon Marlow (c) 1997-2005 Simon Marlow+Alex version 3.1.4, (c) 2003 Chris Dornan and Simon Marlow ``` -#### Modify the `config/routes` file+In case you are **not** good to go, you may want to follow the+[per operating system installation guides on the haskell.org website](https://www.haskell.org/downloads)+which provides instructions for installing the tool chain and setting+up your `$PATH`. -Replace **all** of the file's content with: -```-/static StaticR Static appStatic--/favicon.ico FaviconR GET-/robots.txt RobotsR GET+### Create a project folder -/ HomeR GET+Choose a name for your project.  In below we chose `mysite`, which you+probably want to change. Make sure to choose a valid unix file name+to avoid naming issues.  Now create a directory for your project and+`cd` into it, by running the following commands: -/admin/auth        AuthR                 Auth            getAuth-/admin/core        CoreAdminR            CoreAdmin       getLambdaCms-/admin             AdminHomeRedirectR    GET+```bash+export PROJECT_NAME=mysite; mkdir $PROJECT_NAME; cd $PROJECT_NAME ``` -#### Modify Settings -There are two files to modify here. One is `config/settings.yml` and the the other is `Settings.hs`.+### Initialize a cabal sandbox -In `config/settings.yml`, add the following line to the bottom of the file-```-admin: "_env:LAMBDACMS_ADMIN:<your email address>"-```+To avoid running into version conflicts with other Haskell projects+you might be working on from the same system, we setup a cabal sandbox. -Then, in `Settings.hs`, append the following record to the `AppSettings` data type:+From within your project's folder run the following commmand: -```haskell-    , appAdmin                  :: Text+```bash+cabal sandbox init ``` -In `instance FromJSON AppSettings`, find this line: -Add the following line just before the line containing `return AppSettings {..}`:+### Using LTS Haskell -```haskell-        appAdmin                  <- o .: "admin"-```+To avoid spending too much time on build issues we use and recommend+[LTS Haskell](https://github.com/fpco/lts-haskell#readme). -#### Modify the `config/models` file+Currently we develop and test LambdaCms only against the `2.x`+LTS Haskell releases. As minor releases of LTS Haskell should never+contain breaking changes, you can safely use the latest release of+a major LTS version. -Replace **all** of the file's content with the following `UserRole` definition:+Run the following commands from within your project's folder,+to install the most recent LTS Haskell package set in the `2.x` series. -```-UserRole-    userId UserId-    roleName RoleName-    UniqueUserRole userId roleName-    deriving Typeable Show+```bash+wget http://www.stackage.org/lts/2/cabal.config+cabal update ``` -#### Modify the `Model.hs` file -Add the following imports:--```haskell-import Roles-import LambdaCms.Core-```--#### Modify the `Application.hs` file--Add the following imports:--```haskell-import LambdaCms.Core-import LambdaCms.Core.Settings (generateUUID)-import Network.Wai.Middleware.MethodOverridePost-```+### Initializing the base application -Add the following function:+First we need to install the `yesod` command, this command requires a+lot of dependent packages to be downloaded and build (may a while).+Run this from your project's folder: -```haskell-getAdminHomeRedirectR :: Handler Html-getAdminHomeRedirectR = do-    redirect $ CoreAdminR AdminHomeR+```bash+cabal install yesod-bin ``` -In the `makeFoundation` function, add this line to beginning:+With the following command you create a "scaffolded" Yesod application.+The command is interactive; you need to supply some configuration values.+Pick the database of your choice, and choose a project name: -```haskell-let getLambdaCms = CoreAdmin+```bash+yesod init --bare ``` -Then, find this code:+If you have chosen a database other than Sqlite, you need to create a+database and a sufficiently priviledged database user, and set these+credentials in the `config/setting.yml` file. -```haskell-    -- Perform database migration using our application's logging settings.-    runLoggingT (runSqlPool (runMigration migrateAll) pool) logFunc+This installs all dependencies and builds the scaffoled application +(may take a while): -    -- Return the foundation-    return $ mkFoundation pool+```bash+cabal install -j --enable-tests --max-backjumps=-1 --reorder-goals ``` -And replace it with:+In case you experience problems with `cabal install` try changing+`-j` into `-j1` to prevents concurrent building, and/or simply retry+the command until you consistently run into the same error. -```haskell-    -- Perform database migration using our application's logging settings.-    let theFoundation = mkFoundation pool-    runLoggingT-        (runSqlPool (mapM_ runMigration [migrateAll, migrateLambdaCmsCore]) pool)-        (messageLoggerSource theFoundation appLogger)+When you experience problems during builds, while using LTS `2.x`,+we consider this a bug. Please+[raise an issue](https://github.com/lambdacms/lambdacms-core/issues). -    -- Create a user if no user exists yet-    let admin = appAdmin appSettings-    madmin <- runSqlPool (getBy (UniqueEmail admin)) pool-    case madmin of-        Nothing -> do-            timeNow <- getCurrentTime-            uuid <- generateUUID-            flip runSqlPool pool $ do-                uid <- insert User { userIdent     = uuid-                                   , userPassword  = Nothing-                                   , userName      = takeWhile (/= '@') admin-                                   , userEmail     = admin-                                   , userActive    = True-                                   , userToken     = Nothing-                                   , userCreatedAt = timeNow-                                   , userLastLogin = Nothing-                                   , userDeletedAt = Nothing-                                   }-                -- assign all roles to the first user-                mapM_ (insert_ . UserRole uid) [minBound .. maxBound]-        _ -> return () -    -- Return the foundation-    return theFoundation-```-+### Testing your Yesod app -In the function `makeApplication` replace this line:+The following commands will run your scaffolded Yesdo application+in development mode. -```haskell-    return $ logWare $ defaultMiddlewaresNoLogging appPlain+```bash+yesod devel ``` -With this line (adding a WAI middleware is needed to make RESTful-forms work on older browsers):+Now test it by pointing the browser to:+[`http://localhost:3000`](http://localhost:3000) -```haskell-    return $ logWare $ methodOverridePost appPlain-```+If all went well you are ready to add LambdaCms to your app. -## Create the `Roles.hs` file -Create the `Roles.hs` file (in the root directory of your-application) and add the following content to it:+### Patching a freshly init'ed Yesod app to use `lambdacms-core` -```haskell-module Roles where+To add `lambdacms-core` to a freshly initialized Yesod application a number+of files need to be edited. We have prepared a patch-set to simplify this+process into a couple of commands. -import ClassyPrelude.Yesod+First we need to download the patches by cloning the repository, we do so in+`/tmp`. Then we apply the patches with the good old `patch` command. -data RoleName = Admin-              | Blogger-              deriving (Eq, Ord, Show, Read, Enum, Bounded, Typeable)+Run the following from the root of your newly created Yesod project: -derivePersistField "RoleName"+```bash+(cd /tmp; git clone https://github.com/lambdacms/lambdacms-patches.git)+patch -p1 < /tmp/lambdacms-patches/all_patches_combined.patch ``` -## Modify the `Foundation.hs` file+Because the cabal file has a different name for each project+(i.e. `<project_name>.cabal`) the patch command will notice a patched file+is missing (we named it `project_name.cabal`).+When the patch command tries to patch this file you will be prompted for+the name of your projects cabal file, after providing the name it will+successfully complete patching. -Add the following imports: -```haskell-import qualified Data.Set                    as S-import qualified Network.Wai                 as W-import LambdaCms.Core-import Roles-```--Append the following record to the `App` data type:--```haskell-    , getLambdaCms   :: CoreAdmin-```--Change the implementation of `isAuthorized` (in `instance Yesod App`) to the-following, which allows fine-grained authorization based on `UserRoles`:--```haskell-    isAuthorized theRoute _ =-        case theRoute of-            (StaticR _)                   -> return Authorized-            (CoreAdminR (AdminStaticR _)) -> return Authorized-            _                             -> do-                mauthId <- maybeAuthId-                wai     <- waiRequest-                y       <- getYesod-                murs    <- mapM getUserRoles mauthId-                return $ isAuthorizedTo y murs $ actionAllowedFor theRoute (W.requestMethod wai)--```--Change the implementation of `getAuthId` (in `instance YesodAuth App`) to:--```haskell-    getAuthId = getLambdaCmsAuthId-```--In `instance YesodAuth App` replace:--```haskell-    loginDest _ = HomeR-    logoutDest _ = HomeR-```--With:--```haskell-    loginDest _ = CoreAdminR AdminHomeR-    logoutDest _ = AuthR LoginR-```+#### Alternatives to the patch set -And add:+There are two alternatives to using the patch set: -```haskell-    authLayout = adminAuthLayout-```+1. Patch files individually, how to do so is explained in the `lambdacms-patches`+   [README](https://github.com/lambdacms/lambdacms-patches/blob/master/README.md).+2. Follow the [Getting Started Manually](https://github.com/lambdacms/lambdacms-core/wiki/Getting-Started-Manually)+   guide on the wiki.  -Add the following instance to allow `Unauthenticated` `GET` requests for the-`HomeR` route (likely to be `/`) and other common routes such as `/robots.txt`.-The last pattern allows access to any unspecified routes for just Admins -- which is a role defined in Roles.hs.-It is in `actionAllowedFor` that you will setup permissions for the roles.--```haskell-instance LambdaCmsAdmin App where-    type Roles App = RoleName--    actionAllowedFor (FaviconR) "GET" = Unauthenticated-    actionAllowedFor (RobotsR)  "GET" = Unauthenticated-    actionAllowedFor (HomeR)    "GET" = Unauthenticated-    actionAllowedFor (AuthR _)  _     = Unauthenticated-    actionAllowedFor _          _     = Roles $ S.fromList [Admin]--    coreR = CoreAdminR-    authR = AuthR-    masterHomeR = HomeR--    -- cache user roles to reduce the amount of DB calls-    getUserRoles userId = cachedBy cacheKey . fmap toRoleSet . runDB $ selectList [UserRoleUserId ==. userId] []-        where-            cacheKey = encodeUtf8 $ toPathPiece userId-            toRoleSet = S.fromList . map (userRoleRoleName . entityVal)+### Configure the initial administrator -    setUserRoles userId rs = runDB $ do-        deleteWhere [UserRoleUserId ==. userId]-        mapM_ (insert_ . UserRole userId) $ S.toList rs+By default the application uses Mozilla's [Persona](https://persona.org)+to log in: the email address used to log in need to be registered with Persona.+It is recommended to use an email address of a Persona account for+development as it simplifies logging in during development. -    adminMenu =  (defaultCoreAdminMenu CoreAdminR)-    renderLanguages _ = ["en", "nl"]+Edit `config/settings.yml` to insert a valid email address. -    mayAssignRoles = do-        authId <- requireAuthId-        roles <- getUserRoles authId-        return $ isAdmin roles+```yaml+admin: "_env:LAMBDACMS_ADMIN:<email address>" ``` -#### Add an `isAdmin` function to the bottom of `Foundation.hs`--Remember that the `Admin` role is defined in Roles.hs-```haskell-isAdmin :: S.Set RoleName -> Bool-isAdmin = S.member Admin-```+Replace `<email address>` with the email address of an initial administrator+or developer, so the admin inteface can be accessed.  -### Give it a try+### Enjoy! -LambdaCms should now be installed. You can give it a try.+After applying the patches `lambdacms-core` is installed in your Yesod application.+Run `cabal install` (possibly with `-j1`) to fetch and build the dependencies.+Then run the development server.      yesod devel -Now point your browser to `http://localhost:3000/admin` and you will be+Now point your browser to+[`http://localhost:3000/admin`](http://localhost:3000/admin) and you will be prompted to login.  The setup as described above has selected Mozilla's Persona as the only means of authentication.  In `config/settings.yml` you have provided an email address for the admin user that is created if no users exist. If this email address is known to Mozilla Persona then you can procede to log in.+++# License++All code in this repository is released under the MIT license, as specified+in the [LICENSE file](https://github.com/lambdacms/lambdacms-core/blob/master/LICENSE).++
lambdacms-core.cabal view
@@ -1,13 +1,13 @@ name:               lambdacms-core-version:            0.0.8.0+version:            0.1.0.0 license:            MIT license-file:       LICENSE author:             Cies Breijs, Mats Rietdijk, Rutger van Aalst maintainer:         cies@AT-hoppinger.com-copyright:          (c) 2014 Hoppinger-bug-reports:        https://github.com/lambdacms/lambdacms-core+copyright:          (c) 2014-2015 Hoppinger+bug-reports:        https://github.com/lambdacms/lambdacms-core/issues homepage:           http://lambdacms.org-synopsis:           Core CMS extension for Yesod apps+synopsis:           LambdaCms Core subsite for Yesod apps description:        LambdaCms is a Content Management System (CMS) in Haskell                     using Yesod. stability:          alpha@@ -53,6 +53,7 @@                   , LambdaCms.Core.Handler.ActionLog                   , LambdaCms.I18n                   , LambdaCms.I18n.Dutch+                  , LambdaCms.I18n.Italian    build-depends:    base                               >= 4.3     && < 5                   , yesod