PBD7LZYQHXAA3KLH2ZUX5GW4UFML6BQ32KXZF4KZ6OYFASUYFJ5QC I2KHGVD44KT4MQJXGCTVSQKMBO6TVCY72F26TLXGWRL6PHGF6RNQC OBFPJS2GHO2PEHBHGEHKIUOUAFIQHPIZXEVD2YIE3ZIE2PVMH5VAC ADMKQQGCGVSHHIMVQ4XFRDCG544SBJCYALSKZV45CQQBZ4ACUH2AC IZEVQF627FA7VV25KJAWYWGGC35LZUUBBQRPN5ZAINTQLPEDRTEAC TNR3TEHKVADAEZSTOD2XLSUTSW5AWST2YUW4CWK5KE7DSC6XHZNAC 5W5M56VJFJEBXMGBVKGCKPHOEMVTKUOQMLPJP7VNDQLTYNJXXLHQC Z7KS5XHHC6PAMTVBHXY7KUSS3BWAOU6FSYIITUCFOOJZU4OUJHBAC NVOCQVASZWTKQJG7GPH7KHKZZR7NUG4WLV5YY4KAIRPCJRWCZPIAC 64C6AWH66FDKU6UE6Z6JPX2J2GBM2JOPTH2GL6LHKAIUBGNGDZ5AC WO2MINIF4TXOHWSE7JWXRZYN64XRVLYIRFMF4SMPSOXKA2V77KMQC HE3JTXO37O4MOMWPZ4BRBHP53KBPZDG3PCSUCVNOKIS7IY26OCIAC 4IQVQL4TS35GL2GYZJG254TKJLL5EHMRSFT77Z4VTRZIG2TMBM3QC AXKKXBWN4EMUOLV43WN52JSKJPBV7TLSGLNJW5EZXHSJNKCYUWOQC BROSTG5KP3NUNLSYPVQID254TE47E5RKQAKLPIY7PGWETE6JNMTAC VJPT6HDRMJAJD5PT3VOYJYW43ISKLICEHLSDWSROX2XZWO2OFZPQC BXGLKYRXO2O4NRM3BLNWQ7AWVPQXAMFS57MFYHJNOZZEZZW5BH6AC localstablesnapletsregtest.confsite_key.txt
module Quixotic.Util.Http whereimport ClassyPreludeimport Data.ByteString (split)import Data.Attoparsec.ByteStringimport qualified Data.ByteString.Base64 as B64type AuthHeader = (Text, ByteString)authHeaderParser :: Parser AuthHeaderauthHeaderParser = dolet isBase64Char w = (w >= 47 && w <= 57 ) ||(w >= 64 && w <= 90 ) ||(w >= 97 && w <= 122) ||(w == 43 || w == 61 )b64 <- string "Basic " *> takeWhile1 isBase64Chardecoded <- either fail pure $ B64.decode b64case split 58 decoded of(uname : pwd : []) -> pure $ (decodeUtf8 uname, pwd)_ -> fail "Could not unpack auth header into username and password components"
#!/bin/bashcurl -v -u "nuttycom:kjntest" -H "Content-Type: application/json" -d '{"projectName":"the"}' http://localhost:8000/projects
#!/bin/bashcurl -v -H "Content-Type: application/json" -d '{"username":"nuttycom", "password":"kjntest", "email":"kris@quixoticcompany.com", "btcAddr":"1KamUn1BaRMd2HwikyQWGTdUvfPScg9QA5"}' http://localhost:8000/register
authHeaderParser :: Parser AuthHeaderauthHeaderParser = dolet isBase64Char w = (w >= 47 && w <= 57 ) ||(w >= 64 && w <= 90 ) ||(w >= 97 && w <= 122) ||(w == 43 || w == 61 )b64 <- string "Basic" *> takeWhile1 isBase64Chardecoded <- either fail pure $ B64.decode b64case split 58 decoded of(uname : pwd : []) -> pure $ (decodeUtf8 uname, pwd)_ -> fail "Could not unpack auth header into username and password components"
Just pid -> error $ "FIXME: implement project access check - got pid " ++ " " ++ show uid ++ " " ++ show pid
Just pid -> doprojects <- liftPG . runReaderT $ findUserProjects uidif any (\p -> p ^. projectId == pid) projectsthen pure pidelse snapError 403 $ "User " ++ (tshow uid) ++ " does not have access to project " ++ (tshow pid)
{-# LANGUAGE TemplateHaskell #-}module Quixotic.Snaplet.Projects( projectsHandler) whereimport ClassyPreludeimport Control.Lensimport Control.Monad.Stateimport Data.Aeson as Aimport Quixoticimport Quixotic.Databaseimport Quixotic.Snapletimport Quixotic.Snaplet.Authimport Snap.Coreimport Snap.Snapletimport Snap.Snaplet.PostgresqlSimpledata CreateProject = CreateProject { createProjectName :: Text }instance FromJSON CreateProject whereparseJSON (Object v) = CreateProject <$> v .: "projectName"parseJSON _ = mzeroprojectsHandler :: Handler App App ()projectsHandler = dovoid $ method POST projectCreateHandlervoid $ method GET projectListHandlerprojectCreateHandler :: Handler App App ProjectIdprojectCreateHandler = doQDB{..} <- view qdb <$> with qm getuid <- requireUserIdrequestBody <- readRequestBody 4096cp <- maybe (snapError 400 "Could not parse project data") pure $ A.decode requestBodytimestamp <- liftIO getCurrentTimeliftPG . runReaderT . createProject $ Project (createProjectName cp) timestamp uidprojectListHandler :: Handler App App [Project]projectListHandler = ok
authUser <- with auth $AU.createUser (userData ^. (cuser.username._UserName)) (userData ^. password)let createQUser = liftPG $ runReaderT (createUser $ userData ^. cuser)
let createSUser = AU.createUser (userData ^. (cuser.username._UserName)) (userData ^. password)createQUser = liftPG $ runReaderT (createUser $ userData ^. cuser)authUser <- with auth createSUser
btc_addr varchar(34) primary key
id serial primary key,handle text not null,btc_addr text not null,email text not null);create table projects (id serial primary key,project_name text not null,inception_date timestamp without time zone not null,initiator_id integer references users (id) not null
btc_addr varchar(34) references users (btc_addr) not null,trust_interval interval not null)
project_id integer references projects(id) not null,user_id integer references users(id) not null,btc_addr text not null,event_type event_t not null,event_time timestamp without time zone not null);
create type event_type as enum ('start_work', 'stop_work');
create table auctions (id serial primary key,project_id integer references projects(id) not null,initiator_id integer references users (id) not null,raise_amount numeric not null,end_time timestamp without time zone not null);
btc_addr varchar(34) references users (btc_addr) not null,log_time timestamp without time zone not null,log_type event_type not null)
auction_id integer references projects (id) not null,bidder_id integer references users (id) not null,bid_seconds integer not null,bid_amount numeric not null,bid_time timestamp without time zone not null);
{-# LANGUAGE OverloadedStrings, ScopedTypeVariables, NoImplicitPrelude #-}module Quixotic.Util.HttpSpec whereimport ClassyPreludeimport Quixotic.Util.Httpimport Data.Attoparsec.ByteStringimport Test.Hspecspec :: Specspec = dodescribe "HTTP Basic header parsing" $ doit "parses the Basic auth header" $ dolet rawHeader = "Basic bnV0dHljb206a2pudGVzdA=="(parseOnly authHeaderParser rawHeader) `shouldBe` (Right ("nuttycom", "kjntest"))main :: IO ()main = hspec spec