Skip to content

Commit edc2f01

Browse files
committed
Make it compile
1 parent 192b695 commit edc2f01

25 files changed

+304
-224
lines changed

flake.nix

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,6 @@
4444
-p ${postgres.port}:5432 \
4545
-d postgres
4646
'';
47-
48-
ZUREG_DB =
49-
"postgresql://postgres:${postgres.password}@localhost:${postgres.port}/${postgres.db}";
50-
51-
ZUREG_HACKATHON_NAME = "ZuriHac 2025";
52-
ZUREG_HACKATHON_URL = "https://zureg.zfoh.ch";
53-
ZUREG_HACKATHON_CONTACT_URL = "https://zfoh.ch/zurihac2025/#contact";
54-
ZUREG_HACKATHON_CAPACITY = "500";
55-
ZUREG_HACKATHON_CONFIRMATION = "true";
5647
};
5748
};
5849
formatter = pkgs.nixfmt;
Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,31 @@
1-
module Amazonka.Extended
2-
( module Amazonka
1+
{-# LANGUAGE TemplateHaskell #-}
2+
module Zureg.AWS
3+
( Config
34
, smartEnv
45
) where
56

67
import Amazonka
8+
import qualified Data.Aeson as A
9+
import qualified Data.Aeson.TH.Extended as A
710
import qualified Amazonka.Data as Amazonka
811
import qualified Data.Text as T
912
import System.Environment (lookupEnv)
1013
import qualified System.IO as IO
1114

15+
data Config = Config
16+
{ configRegion :: !T.Text
17+
} deriving (Show)
18+
1219
-- | AWS region is not retrieved correctly from environment variables, and
1320
-- neither from the AWS profile.
14-
smartEnv :: IO Env
15-
smartEnv = do
21+
smartEnv :: Config -> IO Env
22+
smartEnv conf = do
1623
logger' <- newLogger Debug IO.stderr
17-
maybeRegion <- lookupEnv "AWS_REGION"
18-
region' <- case maybeRegion of
19-
Just str | Right r <- Amazonka.fromText $ T.pack str -> pure r
20-
_ -> fail "AWS_REGION needs to be set"
24+
region' <- either fail pure $ Amazonka.fromText (configRegion conf)
2125
env <- newEnv discover
2226
pure env
2327
{ logger = logger'
2428
, region = region'
2529
}
30+
31+
$(A.deriveJSON A.options ''Config)

lib/Zureg/Config.hs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{-# LANGUAGE TemplateHaskell #-}
2+
module Zureg.Config
3+
( Config (..)
4+
, load
5+
) where
6+
7+
import qualified Data.Aeson as A
8+
import qualified Data.Aeson.TH.Extended as A
9+
import qualified Data.Text as T
10+
import qualified Zureg.AWS as AWS
11+
import qualified Zureg.Captcha.HCaptcha as HCaptcha
12+
import qualified Zureg.Database as Database
13+
import qualified Zureg.Hackathon.Interface as Hackathon
14+
import qualified Zureg.Hackathon.ZuriHac2020.Discord as Discord
15+
16+
data Config = Config
17+
{ configHackathon :: !Hackathon.Hackathon
18+
, configDatabase :: !Database.Config
19+
, configDiscord :: !Discord.Config
20+
, configCaptcha :: !(Maybe HCaptcha.Config)
21+
, configAws :: !AWS.Config
22+
, configScannerSecret :: !T.Text
23+
} deriving (Show)
24+
25+
$(A.deriveFromJSON A.options ''Config)
26+
27+
load :: IO Config
28+
load = either fail pure =<< A.eitherDecodeFileStrict "config.json"

lib/Zureg/Database.hs

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
-- | Storing the registrants in a DynamoDB table. Uses the `Eventful` library.
2-
{-# LANGUAGE OverloadedStrings #-}
3-
{-# LANGUAGE RecordWildCards #-}
4-
{-# LANGUAGE TemplateHaskell #-}
5-
{-# LANGUAGE TypeFamilies #-}
2+
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3+
{-# LANGUAGE OverloadedStrings #-}
4+
{-# LANGUAGE RecordWildCards #-}
5+
{-# LANGUAGE TemplateHaskell #-}
6+
{-# LANGUAGE TypeFamilies #-}
67
module Zureg.Database
78
( Config (..)
89
, configFromEnv
910
, Handle
1011
, withHandle
12+
, Transaction
13+
, withTransaction
1114

1215
-- Old stuff
1316
, getRegistrant
@@ -22,16 +25,23 @@ module Zureg.Database
2225
, putRegistrantsSummary
2326

2427
-- New stuff
28+
, migrate
2529
, insertRegistration
30+
, selectRegistration
31+
, selectAttending
2632
, setRegistrationState
2733
, setRegistrationScanned
2834
) where
2935

30-
import Control.Exception (Exception)
31-
import qualified Data.Aeson.TH.Extended as A
32-
import qualified Data.Text as T
33-
import Data.UUID (UUID)
34-
import System.Environment (lookupEnv)
36+
import Control.Exception (Exception)
37+
import qualified Data.Aeson as A
38+
import qualified Data.Aeson.TH.Extended as A
39+
import qualified Data.Text as T
40+
import Data.UUID (UUID)
41+
import qualified Database.PostgreSQL.Simple as Pg
42+
import System.Environment (lookupEnv)
43+
import Zureg.Database.Internal
44+
import Zureg.Database.Migrations
3545
import Zureg.Database.Models
3646

3747
data DatabaseException
@@ -42,23 +52,11 @@ data DatabaseException
4252

4353
instance Exception DatabaseException
4454

45-
data Config = Config
46-
{ cConnectionString :: !T.Text
47-
}
48-
4955
configFromEnv :: IO Config
5056
configFromEnv = do
5157
cstring <- lookupEnv "ZUREG_DB" >>= maybe (fail "ZUREG_DB not set") pure
5258
pure Config {cConnectionString = T.pack cstring}
5359

54-
data Handle = Handle
55-
{ hConfig :: !Config
56-
}
57-
58-
withHandle :: Config -> (Handle -> IO a) -> IO a
59-
withHandle hConfig f = do
60-
f Handle {..}
61-
6260
getRegistrant :: Handle -> UUID -> IO Registration
6361
getRegistrant _ _ = undefined
6462

@@ -92,11 +90,25 @@ putRegistrantsSummary _ _ = pure ()
9290
lookupRegistrantsSummary :: Handle -> IO RegistrantsSummary
9391
lookupRegistrantsSummary _ = undefined
9492

95-
insertRegistration :: Handle -> UUID -> InsertRegistration -> IO Registration
96-
insertRegistration _ _ _ = undefined
93+
insertRegistration :: Transaction -> InsertRegistration -> IO Registration
94+
insertRegistration (Transaction conn) ir = do
95+
print ir
96+
pure undefined
97+
98+
selectAttending :: Transaction -> IO Int
99+
selectAttending (Transaction conn) = do
100+
rows <- Pg.query conn
101+
"SELECT COUNT(*) FROM registrations WHERE state = ? OR state = ?"
102+
(Registered, Confirmed) :: IO [Pg.Only Int]
103+
case rows of
104+
[Pg.Only c] -> pure c
105+
_ -> fail "selectAttending: expected one row"
106+
107+
selectRegistration :: Transaction -> UUID -> IO Registration
108+
selectRegistration _ _ = undefined
97109

98-
setRegistrationState :: Handle -> UUID -> RegistrationState -> IO Registration
110+
setRegistrationState :: Transaction -> UUID -> RegistrationState -> IO Registration
99111
setRegistrationState _ _ _ = undefined
100112

101-
setRegistrationScanned :: Handle -> UUID -> IO Registration
113+
setRegistrationScanned :: Transaction -> UUID -> IO Registration
102114
setRegistrationScanned _ _ = undefined

lib/Zureg/Database/Internal.hs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2+
{-# LANGUAGE RecordWildCards #-}
3+
module Zureg.Database.Internal
4+
( Config (..)
5+
, Handle (..)
6+
, withHandle
7+
, Transaction (..)
8+
, withTransaction
9+
) where
10+
11+
import Control.Exception (bracket)
12+
import qualified Data.Aeson as A
13+
import qualified Data.ByteString.Char8 as BS8
14+
import qualified Data.Text as T
15+
import qualified Data.Text.Encoding as T
16+
import qualified Database.PostgreSQL.Simple as Pg
17+
18+
newtype Config = Config
19+
{ cConnectionString :: T.Text
20+
} deriving (A.FromJSON, Show)
21+
22+
data Handle = Handle
23+
{ hConfig :: !Config
24+
}
25+
26+
withHandle :: Config -> (Handle -> IO a) -> IO a
27+
withHandle hConfig f = do
28+
f Handle {..}
29+
30+
newtype Transaction = Transaction Pg.Connection
31+
32+
withTransaction :: Handle -> (Transaction -> IO a) -> IO a
33+
withTransaction Handle {..} = bracket
34+
(fmap Transaction $ Pg.connectPostgreSQL $
35+
T.encodeUtf8 $ cConnectionString hConfig)
36+
(\(Transaction conn) -> Pg.close conn)

lib/Zureg/Database/Migrations.hs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,17 @@ module Zureg.Database.Migrations
33
( migrate
44
) where
55

6-
import qualified Data.ByteString.Char8 as BS8
76
import Data.Char (isDigit)
87
import Data.Foldable (for_)
98
import Data.List (sortOn)
109
import Data.String (fromString)
1110
import Data.Traversable (for)
1211
import qualified Database.PostgreSQL.Simple as Pg
1312
import qualified System.Directory as Directory
14-
import System.Environment (lookupEnv)
1513
import System.FilePath ((</>))
1614
import qualified System.IO as IO
1715
import Text.Read (readMaybe)
16+
import Zureg.Database.Internal
1817

1918
listMigrations :: IO [(Int, FilePath)]
2019
listMigrations = sortOn fst <$> do
@@ -27,18 +26,17 @@ listMigrations = sortOn fst <$> do
2726
where
2827
dir = "lib/Zureg/Database/Migrations"
2928

30-
migrate :: IO ()
31-
migrate = do
32-
pgstring <- lookupEnv "ZUREG_DB" >>= maybe (fail "ZUREG_DB not set") pure
33-
conn <- Pg.connectPostgreSQL $ BS8.pack pgstring
34-
_ <- Pg.execute_ conn "\
29+
migrate :: Handle -> IO ()
30+
migrate h = do
31+
_ <- withTransaction h $ \(Transaction conn) -> Pg.execute_ conn "\
3532
\CREATE TABLE IF NOT EXISTS migrations (\n\
3633
\ version INT NOT NULL PRIMARY KEY,\n\
3734
\ path TEXT NOT NULL\n\
3835
\)"
3936

4037
migrations <- listMigrations
41-
for_ migrations $ \(version, path) -> Pg.withTransaction conn $ do
38+
for_ migrations $ \(version, path) -> withTransaction h $
39+
\(Transaction conn) -> do
4240
rows <- Pg.query conn
4341
"SELECT version FROM migrations WHERE version = ?"
4442
(Pg.Only version) :: IO [Pg.Only Int]
@@ -53,5 +51,3 @@ migrate = do
5351
"INSERT INTO migrations (version, path) VALUES (?, ?)"
5452
(version, path)
5553
pure ()
56-
57-
Pg.close conn

lib/Zureg/Database/Migrations/01-init.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ INSERT INTO occupations (occupation) VALUES ('Tech');
3232
INSERT INTO occupations (occupation) VALUES ('Academia');
3333
INSERT INTO occupations (occupation) VALUES ('Other');
3434

35+
CREATE TABLE registration_states (
36+
state TEXT NOT NULL PRIMARY KEY
37+
);
38+
3539
CREATE TABLE registrations (
3640
id UUID NOT NULL PRIMARY KEY DEFAULT GEN_RANDOM_UUID(),
3741
email TEXT NOT NULL,

lib/Zureg/Database/Models.hs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@ module Zureg.Database.Models
1515
, Registration (..)
1616
) where
1717

18-
import qualified Data.Aeson.TH.Extended as A
19-
import qualified Data.List as L
20-
import qualified Data.Text as T
21-
import qualified Data.Time as Time
22-
import Data.UUID (UUID)
23-
import Text.Read (readMaybe)
18+
import qualified Data.Aeson.TH.Extended as A
19+
import qualified Data.List as L
20+
import qualified Data.Text as T
21+
import qualified Data.Time as Time
22+
import Data.UUID (UUID)
23+
import qualified Database.PostgreSQL.Simple.ToField as Pg
24+
import Text.Read (readMaybe)
2425

2526
data TShirtSize = XS | S | M | L | XL | XXL deriving (Bounded, Enum, Eq, Show)
2627

@@ -86,7 +87,7 @@ data InsertRegistration = InsertRegistration
8687
, irOccupation :: !(Maybe Occupation)
8788
, irBeginnerTrackInterest :: !Bool
8889
, irProject :: !Project
89-
}
90+
} deriving (Show)
9091

9192
data Registration = Registration
9293
{ rUuid :: !UUID
@@ -112,3 +113,6 @@ $(A.deriveJSON A.options ''ContributorLevel)
112113
$(A.deriveJSON A.options ''Project)
113114
$(A.deriveJSON A.options ''RegistrationState)
114115
$(A.deriveJSON A.options ''Registration)
116+
117+
instance Pg.ToField RegistrationState where
118+
toField = Pg.toField . show

lib/Zureg/Hackathon/Interface.hs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
1+
{-# LANGUAGE TemplateHaskell #-}
12
module Zureg.Hackathon.Interface
23
( Hackathon (..)
34
, hackathonFromEnv
45
) where
56

67
import qualified Data.Text as T
78
import qualified Data.Time as Time
9+
import qualified Data.Aeson.TH.Extended as A
810

911
data Hackathon = Hackathon
1012
{
1113
-- | Name of the Hackathon, e.g. "ZuriHac 2020"
1214
name :: T.Text
1315
-- | Base URL, e.g. "https://zureg.zfoh.ch"
14-
, baseUrl :: T.Text
16+
, baseURL :: T.Text
1517
-- | URL of the contact homepage, e.g. "https://zfoh.ch/zurihac2019/#contact"
16-
, contactUrl :: T.Text
18+
, contactURL :: T.Text
1719
-- | Total capacity of the event
1820
, capacity :: Int
1921
-- | When 'True', registrants can/must confirm their registration
@@ -23,9 +25,9 @@ data Hackathon = Hackathon
2325
, emailFrom :: T.Text
2426
-- | When T-shirt order is sent.
2527
, tShirtDeadline :: Maybe Time.UTCTime
26-
-- | Secret for accessing the scanner page.
27-
, scannerSecret :: T.Text
28-
}
28+
} deriving (Show)
2929

3030
hackathonFromEnv :: IO Hackathon
3131
hackathonFromEnv = pure undefined
32+
33+
$(A.deriveJSON A.defaultOptions ''Hackathon)

0 commit comments

Comments
 (0)