forked from commercialhaskell/haskellers
/
Application.hs
136 lines (124 loc) · 4.51 KB
/
Application.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Application
( makeApplication
, getApplicationDev
, makeFoundation
) where
import Import
import Settings
import Yesod.Auth
import Yesod.Default.Config
import Yesod.Default.Main
import Yesod.Default.Handlers
import Network.Wai.Middleware.RequestLogger (logStdout, logStdoutDev)
import qualified Database.Persist.Store
import Database.Persist.GenericSql (runMigration)
import Network.HTTP.Conduit (newManager, def)
import Data.IORef
import Control.Monad
import Control.Concurrent
import Database.Persist.GenericSql
import Data.Maybe
import qualified Data.Set as Set
-- Import all relevant handler modules here.
-- Don't forget to add new modules to your cabal file!
import Handler.Root
import Handler.Profile
import Handler.User
import Handler.Admin
import Handler.Email
import Handler.Skills
import Handler.Package
import Handler.Faq
import Handler.News
import Handler.Job
import Handler.Team
import Handler.Topic
import Handler.Bling
import Handler.Poll
-- This line actually creates our YesodSite instance. It is the second half
-- of the call to mkYesodData which occurs in Foundation.hs. Please see
-- the comments there for more details.
mkYesodDispatch "App" resourcesApp
-- This function allocates resources (such as a database connection pool),
-- performs initialization and creates a WAI application. This is also the
-- place to put your migrate statements to have automatic database
-- migrations handled by Yesod.
makeApplication :: AppConfig DefaultEnv Extra -> IO Application
makeApplication conf = do
foundation <- makeFoundation conf
app <- toWaiAppPlain foundation
return $ logWare app
where
logWare = if development then logStdoutDev
else logStdout
makeFoundation :: AppConfig DefaultEnv Extra -> IO App
makeFoundation conf = do
manager <- newManager def
s <- staticSite
dbconf <- withYamlEnvironment "config/postgresql.yml" (appEnv conf)
Database.Persist.Store.loadConfig >>=
Database.Persist.Store.applyEnv
p <- Database.Persist.Store.createPoolConfig (dbconf :: Settings.PersistConfig)
Database.Persist.Store.runPool dbconf (runMigration migrateAll) p
hprofs <- newIORef ([], 0)
pprofs <- newIORef []
if production
then do
_ <- forkIO $ forever $ do
_ <- fillProfs p hprofs pprofs
threadDelay (1000 * 1000 * 60 * 5)
return ()
else fillProfs p hprofs pprofs
return $ App conf s p manager dbconf hprofs pprofs
-- for yesod devel
getApplicationDev :: IO (Int, Application)
getApplicationDev =
defaultDevelApp loader makeApplication
where
loader = loadConfig (configSettings Development)
{ csParseExtra = parseExtra
}
getHomepageProfs :: ConnectionPool -> IO [Profile]
getHomepageProfs pool = flip runSqlPool pool $ do
users <-
selectList [ UserVerifiedEmail ==. True
, UserVisible ==. True
, UserReal ==. True
, UserBlocked ==. False
-- FIXME , UserRealPicEq True
] []
fmap catMaybes $ mapM userToProfile users
getPublicProfs :: ConnectionPool -> IO [Profile]
getPublicProfs pool = flip runSqlPool pool $ do
users <-
selectList [ UserVerifiedEmail ==. True
, UserVisible ==. True
, UserBlocked ==. False
]
[ Desc UserReal
, Asc UserHaskellSince
, Asc UserFullName
]
fmap catMaybes $ mapM userToProfile users
fillProfs :: ConnectionPool -> IORef ([Profile], Int) -> IORef [Profile] -> IO ()
fillProfs pool hprofs pprofs = do
hprofs' <- getHomepageProfs pool
pprofs' <- getPublicProfs pool
writeIORef hprofs (hprofs', length hprofs')
writeIORef pprofs pprofs'
userToProfile :: (Functor (b m), PersistUnique b m, b ~ SqlPersist) => Entity User -> b m (Maybe Profile)
userToProfile (Entity uid u) =
case userEmail u of
Nothing -> return Nothing
Just e -> do
mun <- fmap (fmap entityVal) $ getBy $ UniqueUsernameUser uid
return $ Just Profile
{ profileUserId = uid
, profileName = userFullName u
, profileEmail = e
, profileUser = u
, profileSkills = Set.fromList [] -- FIXME
, profileUsername = mun
, profileLocation = Location <$> userLongitude u <*> userLatitude u
}