Update docker build, clean up migration for payments tables.
[?]
Mar 2, 2017, 5:28 AM
EW2XN7KUMCAQNVFJJ5YTAVDZCPHNWDOEDMRFBUGLY6IE2HKNNX5ACDependencies
- [2]
45AI46JNMove readme to inception.md - [3]
LEINLS3XUpdate deployment documentation. - [4]
WZFQDWW4Add retrieval/storage of current exchange rate data to payment recording. - [5]
Q5X5RYQLstylish-haskell reformatting - [6]
HMDM3B55Implement core of payments/billing infrastructure. - [7]
64C6AWH6Rename Ananke -> Quixotic, project reboot. - [8]
7HPY3QPFFix linting errors. (yay hlint!) - [9]
DXIGERDTChange order of Docker build to avoid rebuilding the universe. - [10]
4ZLEDBK7Initial attempts at dockerizing, cabal isn't cooperating. - [11]
AXKKXBWNInitial attempt at writing down my ideas for a company based on trust. - [12]
M4KM76DGMerge branch 'stackify' - [13]
DFOBMSAOInitial work on payments API - [14]
WAIX6AGNAdd event serialization for PaymentRequest & Payment - [15]
Z7KS5XHHVery WIP. Wow. - [16]
O5FVTOM6Undo JSON silliness, enable a couple more routes. - [17]
V2VDN77HEnable postgres configuration via environment variable for Heroku. - [18]
EPOYLP7OA little .gitignore cleanup. - [19]
E2KOBKIJAdd setup script detailing the setup of the docker host. - [20]
QMRKFEPGRefactor QDB to use a free monad algebra instead. - [21]
TA6RIVTQRevising... - [22]
Y3LIJ5USAdd handler for CreatePaymentRequest - [23]
ADMKQQGCInitial empty Snap project. - [24]
ZKJJVD2HFix aftok-server runit script permissions. - [25]
RB2ETNIFAdd skeletal PureScript client project. - [26]
OBFPJS2GProject successfully builds and tests under nix. - [27]
POX3UAMTEnabling logging of time to contributor/project accounts - [28]
O227CEAVAdds storage of original event JSON for some DBOp constructors. - [29]
GCVQD44VCreate amends endpoint, switch to UUID primary keys - [30]
O722AOKEAdd route to allow crediting of events to users/projects. - [31]
RPAJLHMTChange to use UUIDs instead of ints for primary keys. - [32]
45QJYWN3Fixing up the README. Still struggling with the ending. - [33]
BSIUHCGFAdd payment response handler. - [34]
DLZRD7VBAdd a preliminary, probably somewhat broken set of setup instructions. - [35]
IRG4KNAETrivial deletion. - [36]
SEWTRB6SImplement payment request creation functions. - [37]
2WOOGXDHUse dbmigrations to manage database state. - [38]
Z3MK2PJ5Add GET handler for retrieving auction data. - [39]
EQXRXRZDChanged to use tasty instead of test-framework - [40]
AL37SVTCImplement payments service endpoints. - [41]
7VGYLTMUClean up schema version handling. - [42]
2XQD6KKKAdd invitation logic and clean up DBProg error handling. - [43]
JEOPOOPTDockerfile now builds correctly. - [44]
ASF3UPJLAdd auction creation and bid handlers - [45]
NLZ3JXLOFix formatting with stylish-haskell. - [46]
73NDXDEZBegin implementation of billing event persistence. - [47]
RSEB2NFGReplacing Snap with Scotty. - [48]
NVOCQVASInitial failing tests. - [49]
PBD7LZYQPostgres & auth are beginning to function. - [50]
RN7EI6INUpdate database layer to use CreditTo - [51]
NTPC7KJETrivial changes, feature scratchpad. - [52]
KEP5WUFJConvert project to stack-based build. - [53]
QO4NFWIYAdded sample config file. - [54]
T44T2PDLRename trust.txt to README.md - [55]
LAROLAYUWIP - [56]
EZQG2APBUpdate task list. - [57]
ZP62WC47Begin conversion to build with stack. - [58]
373LXH2XAdd MAYBE.md, update task list. - [59]
2Y2QZFVFSwitch to more modern cabal2nix-based workflow. - [60]
M3KUPGZKAdd invitation email template. - [61]
2LZYVHFSUpgrade to Stack-based build in Docker - [62]
5W5M56VJMove library code to 'lib' - [63]
W35DDBFYFactor common JSON conversions up into client lib module. - [64]
4U7F3CPITHE GREAT RENAMING OF THINGS! - [*]
SPJCFHXWUpdate shell scripts to point to https://aftok.com and prompt for input. - [*]
VV6ESCEVUpdate .gitignore for client libs. - [*]
IZEVQF62Work in progress replacing sqlite with postgres. - [*]
JFOEOFGAstylish-haskell formatting. - [*]
BWN72T44Don't accept work timestamp from an external source.
Change contents
- file deletion: notes.md
Aftok=====> *"I have to figure out how to balance the work I can make a living on with the> work I can’t, because the work I can’t make a living on is more important."*> -- [Meredith L. Patterson](https://medium.com/message/how-i-explained-heartbleed-to-my-therapist-4c1dbcbe1099)It's impossible to make a living writing open-source software. Certainly, thereare exceptions; a few companies eke out a relatively spare existence selling"enterprise support" licenses for free software, and lots of people employed byprivate companies contribute to open-source products on time paid for by theiremployer. Nonetheless, a great deal of the open-source software that developedis a labor of love. OSS developers are artists, but they're fortunate thattheir art is in a medium that also, at present, makes it easy enough to findpaid work that few of us have to starve while making our art.Unlike many other arts (excepting music) open-source software development isfrequently a deeply collaborative endeavor.* Trust cannot be imposed, it can only be grown.* Last section needs to be more positive, deemphasize risk.(12:36:54 PM) nuttycom1: Reiterating my earlier question, this time via StackOverflow: http://stackoverflow.com/questions/30466275/http-basic-auth-in-snap(12:41:03 PM) dmj`: nuttycom1: why not use snap's cookie-based auth?(12:41:33 PM) carter_cloud: mightybyte: lpsmith did that posgres-simple snaplet transaction bug ever get fixed?(12:41:40 PM) nuttycom1: dmj`: my clients aren't necessarily browsers.(12:41:55 PM) nuttycom1: In fact, they're mostly not browsers.(12:43:17 PM) dmj`: nuttycom1: are they mobile clients?(12:43:31 PM) nuttycom1: dmj`: no, other servers.(12:48:21 PM) dmj`: nuttycom1: basic auth isn't secure, you're sending the password (base-64 encoded) on every request, it could be fine if it's all over https. But still, a token based system would be more secure. Are these severs internal / external? (i.e. yours or someone elses)(12:53:16 PM) nuttycom1: dmj`: Token-based systems are no more secure if they're not over https, but that's a side point; in my experience it's common in any case to use the Authorization headers to carry authentication tokens so that they don't have to pollute the request payload in other ways.(12:54:14 PM) nuttycom1: I have a bunch of CLI tools that access my services via curl and such, which prompt for auth credentials along the way. Using Basic is convenient for these kinds of tools.(12:54:49 PM) nuttycom1: All the servers *are* in my control, however. I suppose I could use an X-My-Auth header or some such, but I don't much see the point.(12:55:38 PM) nuttycom1: At least, they're under my control at the moment, but obviously the API I'm providing is ultimately going to be accessible to anyone on the open web, so I might as well make things easy for them.(12:59:00 PM) mightybyte: carter_cloud: Yes(12:59:32 PM) mightybyte: http://blog.melding-monads.com/2015/02/12/announcing-snaplet-postgresql-simple-0-6/(01:00:42 PM) dmj`: nuttycom1: token based systems only transmit the credentials on the initialize request to generate the token, not on every request, so not sure how it's just as secure. It seems like setting up your own oauth provider would be ideal in this case, especially if you plan on releasing this api to the public. If your servers are not exposed to the outside world, why even have them authenticate against each other, if you're using A(01:00:43 PM) dmj`: you using a VPC?(01:00:49 PM) dmj`: initial*(01:00:52 PM) mightybyte: carter_cloud: I guess that post never hit reddit.(01:02:17 PM) mightybyte: nuttycom1: I don't know of a basic auth package for snap (probably in part due to the concerns dmj` has pointed out), but I wouldn't expect that it would be too hard to write.(01:02:42 PM) nuttycom1: mightybyte: Hah.... yeah, I provide one as context in my SO question.(01:04:49 PM) carter_cloud: mightybyte: btw Stephen Diehl has a neat prototype of a streaming Postgres binding https://github.com/elsen-trading/pgstream(01:07:49 PM) nuttycom1: dmj`: fair enough; I suppose that I can add token handling to the CLI tools, it's just a little more work since I'll have to encrypt the token before it's stored locally, and require the user to decrypt on each request rather than provide credentials. That's probably the right way to go.(01:07:51 PM) dmj`: nuttycom1: I can't speak for other token-based systems, but json web tokens are typically encrpyted (HMAC SHA-256), basic auth data is just encoded. So your last line of defense in basic auth is ssl, and your surface area (every request) is much larger. I dunno, if you think basic auth suits your needs then go for it, but it sounds to me like you should become an oauth provider here.(01:08:16 PM) mightybyte: nuttycom1: responded(01:09:10 PM) nuttycom1: mightybyte: thanks!(01:10:45 PM) dmj`: nuttycom1: yea, you can create your own key server! Then create tcp connections from your key server to all other api servers. You should change the key somewhat frequently (This secret key is used to hash all tokens). So your key server can broadcast the new secret to all servers via tcp, then (if you're using haskell and not that node.js single-threaded stuff) you could migrate everyones tokens over to the new key transparen(01:10:45 PM) dmj`: if new key has been sent, then rehash with it, and put it in the header).(01:11:16 PM) dmj`: only one-thread, I don't know how people do it(01:11:20 PM) dmj`: one thread*(01:12:18 PM) nuttycom1: Interesting, thanks dmj`. Looks like I have some additional investigation to do. - edit in .dockerignore at line 1
.git.gitignore.stack-work - edit in .dockerignore at line 5[5.3]
localmigrationsworkMakefileDockerfile./*.md./*.cfg - edit in .gitignore at line 19
bin - replacement in Dockerfile at line 14
apt-get install -y --no-install-recommends libpq-dev stackapt-get install -y --no-install-recommends \build-essential autotools-dev autoconf dh-autoreconf \libpq-dev libsqlite3-dev \git stack - replacement in Dockerfile at line 19
# Set up /etc/aftok volume for configuration information# Set up /etc/aftok volume for mounting configuration from the host system - edit in Dockerfile at line 22
ADD ./conf/aftok.cfg.example /etc/aftok/aftok.cfg - edit in Dockerfile at line 31
# Install ghc globally so that we don't have to reinstall it# whenever we change stack.yaml or aftok.cabalRUN stack --resolver lts-7.16 setup - replacement in Dockerfile at line 37
ADD ./docker/stack.yaml /opt/aftok/stack.yamlADD ./stack.yaml /opt/aftok/stack.yaml - edit in Dockerfile at line 44[3.1142]→[3.1142:1211](∅→∅),[5.136]→[5.1024:1025](∅→∅),[5.368]→[5.1024:1025](∅→∅),[5.482]→[5.1024:1025](∅→∅),[5.871]→[5.1024:1025](∅→∅),[3.1211]→[5.1024:1025](∅→∅),[5.1024]→[5.1024:1025](∅→∅)
RUN apt-get install -y libsqlite3-devRUN stack install dbmigrations - edit in Dockerfile at line 47
ADD ./migrations /opt/aftok/migrations - replacement in Makefile at line 2
docker build -t aftok/aftok:latest .sudo docker build -t aftok/aftok:latest . - replacement in Makefile at line 4
run-local-docker:docker run --net=host -it -v /home/nuttycom/projects/aftok/docker-conf/:/etc/aftok aftok/aftok:latestrun-local-docker: build-containersudo docker run --net=host -it -v /home/nuttycom/projects/aftok/local/conf/:/etc/aftok aftok/aftok:latest - file addition: bin[5.2]
- file addition: .keep[0.703]
- file deletion: stack.yaml
flags: {}packages:- '.'extra-deps:- snaplet-postgresql-simple-0.6.0.4- resource-pool-catchio-0.2.1.0resolver: lts-5.3#allow-newer: truelocal-bin-path: /opt/aftok/bin - file addition: docs[5.2]
- file move: README.md → design.md
- file move: features.md → features.md
- file move: inception.md → inception.md
- file move: MAYBE.md → maybe.md
- file move: TASKS.md → tasks.md
- replacement in lib/Aftok/Database/PostgreSQL.hs at line 218
storeEvent (CreateSubscription uid bid) =Just $ storeEventJSON (Just uid) "create_subscription" (createSubscriptionJSON uid bid)storeEvent (CreateSubscription uid bid t) =Just $ storeEventJSON (Just uid) "create_subscription" (createSubscriptionJSON uid bid t) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 438
\(project_id, event_id, name, description, recurrence_type, recurrence_count, billing_amount, grace_period_days) \\( project_id, event_id, name, description \\, recurrence_type, recurrence_count \\, billing_amount, grace_period_days) \ - replacement in lib/Aftok/Database/PostgreSQL.hs at line 460
pgEval dbop @ (CreateSubscription uid bid) = dopgEval dbop @ (CreateSubscription uid bid start_date) = do - replacement in lib/Aftok/Database/PostgreSQL.hs at line 465
\VALUES (?, ?, ?) RETURNING id"\VALUES (?, ?, ?, ?) RETURNING id" - edit in lib/Aftok/Database/PostgreSQL.hs at line 469
, fromThyme start_date - edit in lib/Aftok/Database.hs at line 14
import Data.Thyme.Time as T (Day) - replacement in lib/Aftok/Database.hs at line 56
CreateSubscription :: UserId -> BillableId -> DBOp SubscriptionIdCreateSubscription :: UserId -> BillableId -> T.Day -> DBOp SubscriptionId - replacement in lib/Aftok/Json.hs at line 9
import ClassyPreludeimport ClassyPrelude hiding (Day) - edit in lib/Aftok/Json.hs at line 26[70.58][5.3094]
import Data.Thyme.Time (Day) - replacement in lib/Aftok/Json.hs at line 105
idJSON :: forall a. Lens' a UUID -> a -> ValueidJSON l a = toJSON . tshow $ view l aidValue :: forall a. Lens' a UUID -> a -> ValueidValue l a = toJSON . tshow $ view l aidJSON :: forall a. Text -> Lens' a UUID -> a -> ValueidJSON t l a = v1 $ obj [ t .= idValue l a ] - replacement in lib/Aftok/Json.hs at line 113
obj [ "projectId" .= tshow (pid ^. _ProjectId)obj [ "projectId" .= idValue _ProjectId pid - replacement in lib/Aftok/Json.hs at line 118
projectIdJSON pid = v1 $obj [ "projectId" .= tshow (pid ^. _ProjectId) ]projectIdJSON = idJSON "projectId" _ProjectId - replacement in lib/Aftok/Json.hs at line 128
auctionIdJSON pid = v1 $obj [ "auctionId" .= tshow (pid ^. _AuctionId) ]auctionIdJSON = idJSON "auctionId" _AuctionId - replacement in lib/Aftok/Json.hs at line 132
obj [ "projectId" .= tshow (x ^. (A.projectId._ProjectId)), "initiator" .= tshow (x ^. (A.initiator._UserId))obj [ "projectId" .= idValue (A.projectId._ProjectId) x, "initiator" .= idValue (A.initiator._UserId) x - replacement in lib/Aftok/Json.hs at line 143
creditToJSON (CreditToUser uid) = v2 $ obj [ "creditToUser" .= tshow (uid ^. _UserId) ]creditToJSON (CreditToUser uid) = v2 $ obj [ "creditToUser" .= idValue _UserId uid ] - replacement in lib/Aftok/Json.hs at line 163[5.2094]→[5.5450:5483](∅→∅),[5.5483]→[5.2202:2235](∅→∅),[5.2235]→[5.1798:1799](∅→∅),[5.5519]→[5.1798:1799](∅→∅),[5.2133]→[5.1798:1799](∅→∅)
eventIdJSON (EventId eid) = v1 $obj [ "eventId" .= tshow eid ]eventIdJSON = idJSON "eventId" _EventId - replacement in lib/Aftok/Json.hs at line 176
amendmentIdJSON (AmendmentId aid) = v1 $obj [ "amendmentId" .= tshow aid ]amendmentIdJSON = idJSON "amendmentId" _AmendmentId - replacement in lib/Aftok/Json.hs at line 183
[ "projectId" .= (b ^. (B.project . _ProjectId . to tshow))[ "projectId" .= idValue (B.project . _ProjectId) b - replacement in lib/Aftok/Json.hs at line 199
createSubscriptionJSON :: UserId -> B.BillableId -> ValuecreateSubscriptionJSON uid bid = v1 $obj [ "user_id" .= idJSON _UserId uid, "billable_id" .= idJSON B._BillableId bidcreateSubscriptionJSON :: UserId -> B.BillableId -> Day -> ValuecreateSubscriptionJSON uid bid d = v1 $obj [ "user_id" .= idValue _UserId uid, "billable_id" .= idValue B._BillableId bid, "start_date" .= showGregorian d - replacement in lib/Aftok/Json.hs at line 211
[ "user_id" .= idJSON (B.customer . _UserId) sub, "billable_id" .= idJSON (B.billable . B._BillableId) sub[ "user_id" .= idValue (B.customer . _UserId) sub, "billable_id" .= idValue (B.billable . B._BillableId) sub - replacement in lib/Aftok/Json.hs at line 222
[ "subscription_id" .=view (subscription . B._SubscriptionId . to tshow) r, "payment_request_protobuf_64" .=view (paymentRequest . to (decodeUtf8 . B64.encode . runPut . encodeMessage)) r[ "subscription_id" .= idValue (subscription . B._SubscriptionId) r, "payment_request_protobuf_64" .= view prBytes r - edit in lib/Aftok/Json.hs at line 228
whereprBytes = (paymentRequest . to (decodeUtf8 . B64.encode . runPut . encodeMessage)) - replacement in lib/Aftok/Json.hs at line 246
obj [ "payment_request_id" .= (r ^. (request . _PaymentRequestId . to tshow)), "payment_protobuf_64" .= (r ^. (payment . to (decodeUtf8 . B64.encode . runPut . encodeMessage)))obj [ "payment_request_id" .= idValue (request . _PaymentRequestId) r, "payment_protobuf_64" .= view paymentBytes r - edit in lib/Aftok/Json.hs at line 250
wherepaymentBytes = payment . to (decodeUtf8 . B64.encode . runPut . encodeMessage) - edit in lib/Aftok/Json.hs at line 337
parseBillable :: Value -> Parser B.BillableparseBillable = unversion "Billable" p where--p (Version 1 0) o =p v o = badVersion "Billable" v o - edit in lib/Aftok/Json.hs at line 344[5.988]
- replacement in migrations/2016-12-31_03-45-17_create-payments.txt at line 58
request_data bytea not nullrequest_data bytea not null,url_key text not null,request_time timestamp with time zone not null,billing_date date not null - replacement in migrations/2016-12-31_03-45-17_create-payments.txt at line 68
payment_data bytea not nullpayment_data bytea not null,payment_date timestamp with time zone not null,exchange_rates json - edit in migrations/2016-12-31_03-45-17_create-payments.txt at line 78
drop type recurrence_t; - edit in migrations/2016-12-31_03-45-17_create-payments.txt at line 80
drop type aftok_event_t; - edit in migrations/2016-12-31_03-45-17_create-payments.txt at line 83[5.9696]
- replacement in stack.yaml at line 5
git: git@github.com:aftok/bippy.gitgit: https://github.com/aftok/bippy.git - edit in stack.yaml at line 15[5.23448]
local-bin-path: ./bin