Users with valid invitation codes don't have to provide captcha validation.
UD5T5B7ACLIM7CPSRYGXSQ3EFNS6DTPABPXJE4HQCBI7JYLE5K3QC MU6WOCCJQWG4A5NLD3GBFATCE3SRE3QQCYXYH6WIKSGLHQOOBVRAC QMRKFEPGFBCEWAIXPEIG5ILKAJ2JH5L3TOITHR4HNJXK5FN3KXBQC X3ES7NUA42D2BF7CQDDKXM5CLMVCYA3H5YU5KXLPTGDBFPE2LNVAC 64C6AWH66FDKU6UE6Z6JPX2J2GBM2JOPTH2GL6LHKAIUBGNGDZ5AC 2XQD6KKKD6QVHFHAEMVE3XXY7X2T7BLTLL7XIILZAXNJJH2YONUQC HMDM3B557TO5RYP2IGFFC2C2VN6HYZTDQ47CJY2O37BW55DSMFZAC MB5SHULBN3WP7TGUWZDP6BRGP423FTYKF67T5IF5YHHLNXKQ5REAC EFSXYZPOGA5M4DN65IEIDO7JK6U34DMQELAPHOIL2UAT6HRC66BAC Z7KS5XHHC6PAMTVBHXY7KUSS3BWAOU6FSYIITUCFOOJZU4OUJHBAC JUFBTX45TKSZMB2D4CGNB73UYM5FXAV2QMKIHBSMHEQDAECYP7HQC M4PWY5RUV72AEDCNC4O7UKBPHBIACR4354YTSC3SUZGWFV5UBJBQC BROSTG5KP3NUNLSYPVQID254TE47E5RKQAKLPIY7PGWETE6JNMTAC 5IDB3IWSB6LFW4U772Y7BH5Y3FQOQ7IFWLVXDZE5XS6SKJITFV4QC F4ONFXF4MSA3QM64T7ATRVO3NQR2MC3RVZGVNGSQXCKXXQX2UG7QC U256ZALIPTVWLNACYPIMWLNEYDQWP7CHF4Y4CGMILQTONJHMGQVQC ENNZIQJG4XJ62QCNRMLNAXN7ICTPCHQFZTURX6QSUYYWNADFJHXQC SQ7UMLN5WCPHIF66RO4UQVX6RSNRRZBOVZP7HEMSKP7VO6YNQPRAC NEDDHXUK3GNFMOFO3KLU7NRIHCTYNWBT3D6HTKZAOXFDE6HMDZ6AC M3KUPGZK2UTW4FG3Q632K7P7MI4FVWD5TTIP45UTI3E72UKOWJBAC findInvitation :: (MonadDB m) => InvitationCode -> m (Maybe Invitation)findInvitation ic = liftdb $ FindInvitation ic
findCurrentInvitation :: (MonadDB m) => C.UTCTime -> InvitationCode -> m (Either InvitationError Invitation)findCurrentInvitation t ic =maybe (Left InvitationNotFound) checkInvitation <$> liftdb (FindInvitation ic)wherecheckInvitation i| t .-. (i ^. invitationTime) > fromSeconds (60 * 60 * 72 :: Int) = Left InvitationExpired| isJust (i ^. acceptanceTime) = Left InvitationAlreadyAccepted| otherwise = Right i
Nothing -> raiseSubjectNotFound actJust i| t .-. (i ^. invitationTime) > fromSeconds (60 * 60 * 72 :: Int) ->raiseOpForbidden uid InvitationExpired actJust i| isJust (i ^. acceptanceTime) ->raiseOpForbidden uid InvitationAlreadyAccepted actJust i -> withProjectAuth (i ^. P.projectId) (i ^. P.invitingUser) act
Left InvitationNotFound -> raiseSubjectNotFound actLeft InvitationExpired -> raiseOpForbidden uid (InvitationError InvitationExpired) actLeft InvitationAlreadyAccepted -> raiseOpForbidden uid (InvitationError InvitationAlreadyAccepted) actRight i -> withProjectAuth (i ^. P.projectId) (i ^. P.invitingUser) act
ALTER TABLE bids ADD COLUMN currency currency_t NOT NULL;
captchaResult <- liftIO $ checkCaptcha cfg (userData ^. captchaToken)case captchaResult ofLeft err ->let cmsg = "Captcha check failed, please try again."in snapErrorJS 400 cmsg (RegCaptchaError err)Right _ -> pure ()
now <- liftIO C.getCurrentTime(_, invs) <- partitionEithers <$> snapEval (traverse (findCurrentInvitation now) (userData ^. invitationCodes))if null invsthen checkCaptcha' (userData ^. captchaToken)else pure () -- skip the captcha check with a valid invitation code
wherecheckCaptcha' = \caseJust ct -> docaptchaResult <- liftIO $ checkCaptcha cfg ctcase captchaResult ofLeft err ->let cmsg = "Captcha check failed, please try again."in snapErrorJS 400 cmsg (RegCaptchaError err)Right _ -> pure ()Nothing ->let cmsg = "Captcha token or invitation code required."in snapErrorJS 400 cmsg ()
curl -k -v -H 'Content-Type: application/json' -d '{"username":"USER", "password":"PASS", "email":"$to_email$", "btcAddr":"BTC_ADDR", "invitation_codes":["$inv_code$"]}' 'https://aftok.com/register'
curl --header 'Content-Type: application/json' \\--data '{"username":"USER", "password":"PASS", "recoveryType": "email", "recoveryEmail":"$to_email$", "invitation_codes":["$inv_code$"]}' \\'https://aftok.com/api/register'