Esempio n. 1
0
    def test_discount(self):
        # A unique number on all the giftcards.
        serial = "1678"
        # A "correct" hash, based on what the actual code does.
        correct_hash = hashlib.sha1(serial + self.code).hexdigest()
        correct_hash = re.sub("[a-f]", "", correct_hash)[:8]
        gift_code = "1337" + serial + correct_hash
        print "Using test gift code: %s" % (gift_code)

        # Now try using this code.
        user = Membership.get_by_hash(self.user_hash)
        user.referrer = gift_code
        user.put()

        response = self.test_app.post("/account/" + self.user_hash,
                                      self._TEST_PARAMS)
        self.assertEqual(302, response.status_int)

        # We should have a record of the used code.
        codes = main.UsedCode.all().run()
        for code in codes:
            # We should only have one code in there.
            self.assertEqual(gift_code, code.code)
            self.assertEqual("*****@*****.**", code.email)
            self.assertEqual("OK", code.extra)

        user = Membership.get_by_hash(self.user_hash)
        user.username = None
        user.put()

        # Try to use the same code again.
        response = self.test_app.post("/account/" + self.user_hash,
                                      self._TEST_PARAMS,
                                      expect_errors=True)
        self.assertEqual(422, response.status_int)
        self.assertIn("already been used", response.body)

        # Now we should have individual records of the same code being used twice.
        codes = main.UsedCode.all().run()
        # Turn the iterator into a list.
        codes = [code for code in codes]

        self.assertEqual(gift_code, codes[0].code)
        self.assertEqual(gift_code, codes[1].code)
        self.assertEqual("*****@*****.**", codes[0].email)
        self.assertEqual("*****@*****.**", codes[1].email)
        if codes[0].extra == "OK":
            # The other one should be the duplicate.
            self.assertEqual("2nd+ attempt", codes[1].extra)
        elif codes[0].extra == "2nd+ attempt":
            # The other one should be the good one.
            self.assertEqual("OK", codes[1].extra)
        else:
            fail("Got unexpected extra '%s'." % (codes[0].extra))
Esempio n. 2
0
  def test_discount(self):
    # A unique number on all the giftcards.
    serial = "1678"
    # A "correct" hash, based on what the actual code does.
    correct_hash = hashlib.sha1(serial + self.code).hexdigest()
    correct_hash = re.sub("[a-f]", "", correct_hash)[:8]
    gift_code = "1337" + serial + correct_hash
    print "Using test gift code: %s" % (gift_code)

    # Now try using this code.
    user = Membership.get_by_hash(self.user_hash)
    user.referrer = gift_code
    user.put()

    response = self.test_app.post("/account/" + self.user_hash,
                                  self._TEST_PARAMS)
    self.assertEqual(302, response.status_int)

    # We should have a record of the used code.
    codes = main.UsedCode.all().run()
    for code in codes:
      # We should only have one code in there.
      self.assertEqual(gift_code, code.code)
      self.assertEqual("*****@*****.**", code.email)
      self.assertEqual("OK", code.extra)

    user = Membership.get_by_hash(self.user_hash)
    user.username = None
    user.put()

    # Try to use the same code again.
    response = self.test_app.post("/account/" + self.user_hash,
                                  self._TEST_PARAMS, expect_errors=True)
    self.assertEqual(422, response.status_int)
    self.assertIn("already been used", response.body)

    # Now we should have individual records of the same code being used twice.
    codes = main.UsedCode.all().run()
    # Turn the iterator into a list.
    codes = [code for code in codes]

    self.assertEqual(gift_code, codes[0].code)
    self.assertEqual(gift_code, codes[1].code)
    self.assertEqual("*****@*****.**", codes[0].email)
    self.assertEqual("*****@*****.**", codes[1].email)
    if codes[0].extra == "OK":
      # The other one should be the duplicate.
      self.assertEqual("2nd+ attempt", codes[1].extra)
    elif codes[0].extra == "2nd+ attempt":
      # The other one should be the good one.
      self.assertEqual("OK", codes[1].extra)
    else:
      fail("Got unexpected extra '%s'." % (codes[0].extra))
Esempio n. 3
0
  def test_create_user(self):
    response = self.test_app.post("/tasks/create_user", self.params)
    self.assertEqual(200, response.status_int)

    # Check that it's sending the right parameters to the domain app.
    self.assertIn("username=testy.testerson", response.body)
    self.assertIn("password=notasecret", response.body)
    self.assertIn("first_name=Testy", response.body)
    self.assertIn("last_name=Testerson", response.body)

    user = Membership.get_by_hash(self.user_hash)
    # Check that the user ended up with a username.
    self.assertEqual("testy.testerson", user.username)
    # Check that domain_user got set.
    self.assertTrue(user.domain_user)
    # Check that the password got cleared.
    self.assertEqual(None, user.password)

    # Check that it sent the right email.
    messages = self.mail_stub.get_sent_messages(to="*****@*****.**")
    self.assertEqual(1, len(messages))

    # It should give the user this data.
    body = str(messages[0].body)
    self.assertIn(user.username, body)
Esempio n. 4
0
    def test_create_user(self):
        response = self.test_app.post("/tasks/create_user", self.params)
        self.assertEqual(200, response.status_int)

        # Check that it's sending the right parameters to the domain app.
        self.assertIn("username=testy.testerson", response.body)
        self.assertIn("password=notasecret", response.body)
        self.assertIn("first_name=Testy", response.body)
        self.assertIn("last_name=Testerson", response.body)

        user = Membership.get_by_hash(self.user_hash)
        # Check that the user ended up with a username.
        self.assertEqual("testy.testerson", user.username)
        # Check that domain_user got set.
        self.assertTrue(user.domain_user)
        # Check that the password got cleared.
        self.assertEqual(None, user.password)

        # Check that it sent the right email.
        messages = self.mail_stub.get_sent_messages(to="*****@*****.**")
        self.assertEqual(1, len(messages))

        # It should give the user this data.
        body = str(messages[0].body)
        self.assertIn(user.username, body)
Esempio n. 5
0
 def get(self, hash):
     member = Membership.get_by_hash(hash)
     conf = Config()
     if member:
         success_html = urlfetch.fetch(conf.SUCCESS_HTML_URL).content
         success_html = success_html.replace("joining!", "joining, %s!" % member.first_name)
         is_prod = conf.is_prod
         self.response.out.write(self.render("templates/success.html", locals()))
Esempio n. 6
0
 def get(self, hash):
     member = Membership.get_by_hash(hash)
     c = Config()
     if member:
       success_html = urlfetch.fetch(SUCCESS_HTML_URL).content
       success_html = success_html.replace('joining!', 'joining, %s!' % member.first_name)
       is_prod = c.is_prod
       self.response.out.write(render('templates/success.html', locals()))
Esempio n. 7
0
  def test_retry_no_token(self):
    # Make a user with no token.
    user = Membership.get_by_hash(self.user_hash)
    user.spreedly_token=None
    user.put()

    # Try to create an account for this user.
    response = self.test_app.post("/tasks/create_user", self.params)
    self.assertEqual(200, response.status_int)

    # We should have a new task now.
    taskqueue_stub = self.testbed.get_stub(testbed.TASKQUEUE_SERVICE_NAME)
    tasks = taskqueue_stub.GetTasks("default")
    self.assertEqual(1, len(tasks))

    # The user shouldn't have a domain account yet.
    user = Membership.get_by_hash(self.user_hash)
    self.assertFalse(user.domain_user)
Esempio n. 8
0
  def test_get(self):
    query = urllib.urlencode({"plan": "newhive"})
    response = self.test_app.get("/account/%s?%s" % (self.user_hash, query))
    self.assertEqual(200, response.status_int)
    # Our username should be templated in.
    self.assertIn("testy.testerson", response.body)

    user = Membership.get_by_hash(self.user_hash)
    self.assertEqual("newhive", user.plan)
Esempio n. 9
0
    def test_retry_no_token(self):
        # Make a user with no token.
        user = Membership.get_by_hash(self.user_hash)
        user.spreedly_token = None
        user.put()

        # Try to create an account for this user.
        response = self.test_app.post("/tasks/create_user", self.params)
        self.assertEqual(200, response.status_int)

        # We should have a new task now.
        taskqueue_stub = self.testbed.get_stub(testbed.TASKQUEUE_SERVICE_NAME)
        tasks = taskqueue_stub.GetTasks("default")
        self.assertEqual(1, len(tasks))

        # The user shouldn't have a domain account yet.
        user = Membership.get_by_hash(self.user_hash)
        self.assertFalse(user.domain_user)
Esempio n. 10
0
    def test_get(self):
        query = urllib.urlencode({"plan": "newhive"})
        response = self.test_app.get("/account/%s?%s" %
                                     (self.user_hash, query))
        self.assertEqual(200, response.status_int)
        # Our username should be templated in.
        self.assertIn("testy.testerson", response.body)

        user = Membership.get_by_hash(self.user_hash)
        self.assertEqual("newhive", user.plan)
Esempio n. 11
0
 def get(self, hash):
     member = Membership.get_by_hash(hash)
     conf = Config()
     if member:
         success_html = urlfetch.fetch(conf.SUCCESS_HTML_URL).content
         success_html = success_html.replace(
             "joining!", "joining, %s!" % member.first_name)
         is_prod = conf.is_prod
         self.response.out.write(
             self.render("templates/success.html", locals()))
Esempio n. 12
0
  def test_already_active(self):
    user = Membership.get_by_hash(self.user_hash)
    user.status = "active"
    user.put()

    query = urllib.urlencode(self._TEST_PARAMS)
    response = self.test_app.post("/account/" + self.user_hash, query)

    self.assertEqual(302, response.status_int)
    self.assertIn("success", response.location)
    self.assertIn(self.user_hash, response.location)
Esempio n. 13
0
    def test_post(self):
        query = urllib.urlencode(self._TEST_PARAMS)
        response = self.test_app.post("/account/" + self.user_hash, query)
        self.assertEqual(302, response.status_int)

        user = Membership.get_by_hash(self.user_hash)

        # We should be redirected to a personal spreedly page.
        self.assertIn("subs.pinpayments.com", response.location)
        self.assertIn(self.test_plan.plan_id, response.location)
        self.assertIn(str(user.key().id()), response.location)
        self.assertIn("testy.testerson", response.location)

        # The account information should be in the datastore.
        user = Membership.get_by_hash(self.user_hash)
        self.assertEqual("testy.testerson", user.username)
        self.assertEqual("notasecret", user.password)

        # We shouldn't have a domain account yet.
        self.assertFalse(user.domain_user)
Esempio n. 14
0
  def test_bad_length_code(self):
    code = "133712345"

    user = Membership.get_by_hash(self.user_hash)
    user.referrer = code
    user.put()

    response = self.test_app.post("/account/" + self.user_hash,
                                  self._TEST_PARAMS, expect_errors=True)
    self.assertEqual(422, response.status_int)
    self.assertIn("must be 16 digits", response.body)
Esempio n. 15
0
    def test_already_active(self):
        user = Membership.get_by_hash(self.user_hash)
        user.status = "active"
        user.put()

        query = urllib.urlencode(self._TEST_PARAMS)
        response = self.test_app.post("/account/" + self.user_hash, query)

        self.assertEqual(302, response.status_int)
        self.assertIn("success", response.location)
        self.assertIn(self.user_hash, response.location)
Esempio n. 16
0
  def test_post(self):
    query = urllib.urlencode(self._TEST_PARAMS)
    response = self.test_app.post("/account/" + self.user_hash, query)
    self.assertEqual(302, response.status_int)

    user = Membership.get_by_hash(self.user_hash)

    # We should be redirected to a personal spreedly page.
    self.assertIn("subs.pinpayments.com", response.location)
    self.assertIn(self.test_plan.plan_id, response.location)
    self.assertIn(str(user.key().id()), response.location)
    self.assertIn("testy.testerson", response.location)

    # The account information should be in the datastore.
    user = Membership.get_by_hash(self.user_hash)
    self.assertEqual("testy.testerson", user.username)
    self.assertEqual("notasecret", user.password)

    # We shouldn't have a domain account yet.
    self.assertFalse(user.domain_user)
Esempio n. 17
0
  def test_invalid_code(self):
    code = "1337424242424242"

    user = Membership.get_by_hash(self.user_hash)
    user.referrer = code
    user.put()

    response = self.test_app.post("/account/" + self.user_hash,
                                  self._TEST_PARAMS, expect_errors=True)
    self.assertEqual(422, response.status_int)
    self.assertIn("code was invalid", response.body)
Esempio n. 18
0
    def get(self, hash):
      membership = Membership.get_by_hash(hash)
      if not membership:
        self.response.set_status(422)
        self.response.out.write("Unknown member hash.")
        logging.error("Could not find member with hash '%s'." % (hash))
        return

      # Save the plan they want.
      plan = self.request.get("plan", "newfull")
      membership.plan = plan
      membership.put()

      if ((membership.username and membership.password) and not \
          membership.spreedly_token):
        # We've filled out our account information, but we never started a
        # subscription. (This could be reached by going back and trying to
        # change our plan after we were already taken to the PinPayments
        # page.) In this case, just pass them through to PinPayments.
        query_str = urllib.urlencode({"first_name": membership.first_name,
                                      "last_name": membership.last_name,
                                      "email": membership.email,
                                      "return_url": "http://%s/success/%s" % \
                                          (self.request.host, membership.hash)})
        self.redirect(membership.new_subscribe_url(query_str))

      # steal this part to detect if they registered with hacker dojo email above
      first_part = re.compile(r"[^\w]").sub("", membership.first_name.split(" ")[0]) # First word of first name
      last_part = re.compile(r"[^\w]").sub("", membership.last_name)
      if len(first_part)+len(last_part) >= 15:
          last_part = last_part[0] # Just last initial
      username = "******".join([first_part, last_part]).lower()

      usernames = self.fetch_usernames()
      if usernames == None:
        # Error page is already rendered.
        return
      if username in usernames:
        # Duplicate username. Use the first part of the email instead.
        username = membership.email.split("@")[0].lower()

        user_number = 0
        base_username = username
        while username in usernames:
          # Still a duplicate. Add a number.
          user_number += 1
          username = "******" % (base_username, user_number)

      if self.request.get("pick_username"):
        pick_username = True

      account_url = str("/account/%s" % membership.hash)
      self.response.out.write(self.render("templates/account.html", locals()))
Esempio n. 19
0
    def test_invalid_code(self):
        code = "1337424242424242"

        user = Membership.get_by_hash(self.user_hash)
        user.referrer = code
        user.put()

        response = self.test_app.post("/account/" + self.user_hash,
                                      self._TEST_PARAMS,
                                      expect_errors=True)
        self.assertEqual(422, response.status_int)
        self.assertIn("code was invalid", response.body)
Esempio n. 20
0
    def test_bad_length_code(self):
        code = "133712345"

        user = Membership.get_by_hash(self.user_hash)
        user.referrer = code
        user.put()

        response = self.test_app.post("/account/" + self.user_hash,
                                      self._TEST_PARAMS,
                                      expect_errors=True)
        self.assertEqual(422, response.status_int)
        self.assertIn("must be 16 digits", response.body)
Esempio n. 21
0
    def get(self, hash):
        membership = Membership.get_by_hash(hash)
        if not membership:
            self.response.set_status(422)
            self.response.out.write("Unknown member hash.")
            logging.error("Could not find member with hash '%s'." % (hash))
            return

        # Save the plan they want.
        plan = self.request.get("plan", "newfull")
        membership.plan = plan
        membership.put()

        if ((membership.username and membership.password) and not \
            membership.spreedly_token):
            # We've filled out our account information, but we never started a
            # subscription. (This could be reached by going back and trying to
            # change our plan after we were already taken to the PinPayments
            # page.) In this case, just pass them through to PinPayments.
            self.redirect(
                membership.new_subscribe_url(self.request.host, plan=plan))

        # steal this part to detect if they registered with hacker dojo email above
        first_part = re.compile(r"[^\w]").sub(
            "",
            membership.first_name.split(" ")[0])  # First word of first name
        last_part = re.compile(r"[^\w]").sub("", membership.last_name)
        if len(first_part) + len(last_part) >= 15:
            last_part = last_part[0]  # Just last initial
        username = "******".join([first_part, last_part]).lower()

        usernames = self.fetch_usernames()
        if usernames == None:
            # Error page is already rendered.
            return
        if username in usernames:
            # Duplicate username. Use the first part of the email instead.
            username = membership.email.split("@")[0].lower()

            user_number = 0
            base_username = username
            while username in usernames:
                # Still a duplicate. Add a number.
                user_number += 1
                username = "******" % (base_username, user_number)

        if self.request.get("pick_username"):
            pick_username = True

        account_url = str("/account/%s" % membership.hash)
        self.response.out.write(self.render("templates/account.html",
                                            locals()))
Esempio n. 22
0
    def post(self):
        def fail(exception):
            logging.error("CreateUserTask failed: %s" % exception)
            mail.send_mail(sender=EMAIL_FROM,
                to=INTERNAL_DEV_EMAIL,
                subject="[%s] CreateUserTask failure" % APP_NAME,
                body=str(exception))
        def retry(countdown=3):
            retries = int(self.request.get('retries', 0)) + 1
            if retries <= 5:
                taskqueue.add(url='/tasks/create_user', method='POST', countdown=countdown,
                    params={'hash': self.request.get('hash'), 'retries': retries})
            else:
                fail(Exception("Too many retries for %s" % self.request.get('hash')))
        
        c = Config()
        user_hash = self.request.get('hash')
        membership = Membership.get_by_hash(user_hash)
        if membership is None or membership.username:
            return
        if not membership.spreedly_token:
            logging.warn("CreateUserTask: No spreedly token yet, retrying")
            return retry(300)

            
        try:
            username, password = memcache.get(hashlib.sha1(membership.hash+c.SPREEDLY_APIKEY).hexdigest()).split(':')
        except (AttributeError, ValueError):
            return fail(Exception("Account information expired for %s" % membership.email))
            
        try:
            url = 'http://%s/users' % DOMAIN_HOST
            payload = urllib.urlencode({
                'username': username,
                'password': password,
                'first_name': membership.first_name,
                'last_name': membership.last_name,
                'secret': keymaster.get('api'),
            })
            logging.info("CreateUserTask: About to create user: "******"CreateUserTask: URL: "+url)
            logging.info("CreateUserTask: Payload: "+payload)
            resp = urlfetch.fetch(url, method='POST', payload=payload, deadline=120)
            membership.username = username
            membership.put()
            logging.warn("CreateUserTask: I think that worked: HTTP "+str(resp.status_code))

            # Send the welcome email.
            SuccessHandler.send_email(membership)
        except urlfetch.DownloadError, e:
            logging.warn("CreateUserTask: API response error or timeout, retrying")
            return retry()
Esempio n. 23
0
  def get(self, user_hash):
    member = Membership.get_by_hash(user_hash)

    if not member:
      # Hash is invalid.
      logging.error("Invalid hash '%s'." % (user_hash))
      error = self.render("templates/error.html",
                          message="Invalid reactivation link.")
      self.response.out.write(error)
      self.response.set_status(422)
      return

    self._plan_switch_page(member)
Esempio n. 24
0
    def get(self, user_hash):
        member = Membership.get_by_hash(user_hash)

        if not member:
            # Hash is invalid.
            logging.error("Invalid hash '%s'." % (user_hash))
            error = self.render("templates/error.html",
                                message="Invalid reactivation link.")
            self.response.out.write(error)
            self.response.set_status(422)
            return

        self._plan_switch_page(member)
Esempio n. 25
0
  def test_already_entered(self):
    user = Membership.get_by_hash(self.user_hash)
    user.username = "******"
    user.password = "******"
    user.spreedly_token = None
    user.put()

    response = self.test_app.get("/account/" + self.user_hash,
                                 self._TEST_PARAMS)

    # We should be redirected to a personal spreedly page.
    self.assertEqual(302, response.status_int)
    self.assertIn("subs.pinpayments.com", response.location)
    self.assertIn(self.test_plan.plan_id, response.location)
    self.assertIn(str(user.key().id()), response.location)
    self.assertIn("testy.testerson", response.location)
Esempio n. 26
0
    def test_already_entered(self):
        user = Membership.get_by_hash(self.user_hash)
        user.username = "******"
        user.password = "******"
        user.spreedly_token = None
        user.put()

        response = self.test_app.get("/account/" + self.user_hash,
                                     self._TEST_PARAMS)

        # We should be redirected to a personal spreedly page.
        self.assertEqual(302, response.status_int)
        self.assertIn("subs.pinpayments.com", response.location)
        self.assertIn(self.test_plan.plan_id, response.location)
        self.assertIn(str(user.key().id()), response.location)
        self.assertIn("testy.testerson", response.location)
Esempio n. 27
0
  def test_trivial_failures(self):
    # Give it a bad hash.
    bad_params = {"hash": "badhash"}

    response = self.test_app.post("/tasks/create_user", bad_params,
                                  expect_errors=True)
    self.assertEqual(422, response.status_int)

    # Give it a user with a username already.
    user = Membership.get_by_hash(self.user_hash)
    user.username = "******"
    user.put()

    response = self.test_app.post("/tasks/create_user", self.params)
    # This should be okay, because we don't want PinPayments to think it needs
    # to retry the call.
    self.assertEqual(200, response.status_int)
Esempio n. 28
0
 def get(self, hash):
     membership = Membership.get_by_hash(hash)
     if membership:
       # steal this part to detect if they registered with hacker dojo email above
       first_part = re.compile(r'[^\w]').sub('', membership.first_name.split(' ')[0]) # First word of first name
       last_part = re.compile(r'[^\w]').sub('', membership.last_name)
       if len(first_part)+len(last_part) >= 15:
           last_part = last_part[0] # Just last initial
       username = '******'.join([first_part, last_part]).lower()
       if username in fetch_usernames():
           username = membership.email.split('@')[0].lower()
       if self.request.get('u'):
           pick_username = True
       message = escape(self.request.get('message'))
       account_url = str('/account/%s' % membership.hash)
       self.response.out.write(render('templates/account.html', locals()))
     else:
       self.response.out.write("404 Not Found")
Esempio n. 29
0
    def test_trivial_failures(self):
        # Give it a bad hash.
        bad_params = {"hash": "badhash"}

        response = self.test_app.post("/tasks/create_user",
                                      bad_params,
                                      expect_errors=True)
        self.assertEqual(422, response.status_int)

        # Give it a user with a username already.
        user = Membership.get_by_hash(self.user_hash)
        user.username = "******"
        user.put()

        response = self.test_app.post("/tasks/create_user", self.params)
        # This should be okay, because we don't want PinPayments to think it needs
        # to retry the call.
        self.assertEqual(200, response.status_int)
Esempio n. 30
0
    def test_requirements(self):
        # Giving it passwords that don't match should be a problem.
        params = self._TEST_PARAMS.copy()
        params["password"] = "******"
        params["password_confirm"] = "stillnotasecret"
        query = urllib.urlencode(params)
        response = self.test_app.post("/account/" + self.user_hash,
                                      query,
                                      expect_errors=True)

        self.assertEqual(422, response.status_int)
        self.assertIn("do not match", response.body)
        # The plan should be in there correctly.
        self.assertIn("value=\"test\"", response.body)

        # Giving it a password that is too short should also be a problem.
        params = self._TEST_PARAMS.copy()
        params["password"] = "******"
        params["password_confirm"] = "daniel"
        query = urllib.urlencode(params)
        response = self.test_app.post("/account/" + self.user_hash,
                                      query,
                                      expect_errors=True)

        self.assertEqual(422, response.status_int)
        self.assertIn("at least 8 characters", response.body)
        self.assertIn("value=\"test\"", response.body)

        user = Membership.get_by_hash(self.user_hash)
        user.domain_user = True
        user.put()

        # If there is already a domain account associated with this user, we should
        # fail as well.
        query = urllib.urlencode(self._TEST_PARAMS)
        response = self.test_app.post("/account/" + self.user_hash,
                                      query,
                                      expect_errors=True)

        self.assertEqual(422, response.status_int)
        self.assertIn("already have an account", response.body)
        self.assertIn("value=\"test\"", response.body)
Esempio n. 31
0
  def test_requirements(self):
    # Giving it passwords that don't match should be a problem.
    params = self._TEST_PARAMS.copy()
    params["password"] = "******"
    params["password_confirm"] = "stillnotasecret"
    query = urllib.urlencode(params)
    response = self.test_app.post("/account/" + self.user_hash, query,
                                  expect_errors=True)

    self.assertEqual(422, response.status_int)
    self.assertIn("do not match", response.body)
    # The plan should be in there correctly.
    self.assertIn("value=\"test\"", response.body)

    # Giving it a password that is too short should also be a problem.
    params = self._TEST_PARAMS.copy()
    params["password"] = "******"
    params["password_confirm"] = "daniel"
    query = urllib.urlencode(params)
    response = self.test_app.post("/account/" + self.user_hash, query,
                                  expect_errors=True)

    self.assertEqual(422, response.status_int)
    self.assertIn("at least 8 characters", response.body)
    self.assertIn("value=\"test\"", response.body)

    user = Membership.get_by_hash(self.user_hash)
    user.domain_user = True
    user.put()

    # If there is already a domain account associated with this user, we should
    # fail as well.
    query = urllib.urlencode(self._TEST_PARAMS)
    response = self.test_app.post("/account/" + self.user_hash, query,
                                  expect_errors=True)

    self.assertEqual(422, response.status_int)
    self.assertIn("already have an account", response.body)
    self.assertIn("value=\"test\"", response.body)
Esempio n. 32
0
    def post(self, hash):
        username = self.request.get("username")
        password = self.request.get("password")
        plan = self.request.get("plan")
        plan_object = plans.Plan.get_by_name(plan)
        account_url = str("/account/%s" % hash)

        conf = Config()
        if password != self.request.get("password_confirm"):
            self.response.out.write(
                self.render("templates/account.html",
                            locals(),
                            message="Passwords do not match."))
            self.response.set_status(422)
            return
        elif len(password) < 8:
            self.response.out.write(
                self.render("templates/account.html",
                            locals(),
                            message="Password must be at least 8 characters."))
            self.response.set_status(422)
            return

        membership = Membership.get_by_hash(hash)

        if membership.domain_user:
            logging.warning(
                "Duplicate user '%s' should have been caught" \
                " in first step." % (membership.username))
            self.response.out.write(
                self.render("templates/account.html",
                            locals(),
                            message="You already have an account."))
            self.response.set_status(422)
            return

        # Start saving the parameters for new-style accounts now, so that these
        # people won't have to re-enter anything when we make the transition.
        membership.set_password(password)

        # Set a username and password in the datastore.
        membership.username = username
        membership.password = password
        membership.put()

        if membership.status in ("active", "no_visits"):
            taskqueue.add(url="/tasks/create_user",
                          method="POST",
                          params={
                              "hash": membership.hash,
                              "username": username,
                              "password": password
                          },
                          countdown=3)
            self.redirect(
                str("http://%s/success/%s" %
                    (self.request.host, membership.hash)))
            return

        customer_id = membership.key().id()

        # All our giftcards start out with 1337.
        if (membership.referrer and "1337" in membership.referrer):

            if len(membership.referrer) != 16:
                message = "<p>Error: code must be 16 digits."
                message += "<p>Please contact %s if you believe this \
                          message is in error and we can help!"                                                                % \
                          (conf.SIGNUP_HELP_EMAIL)
                message += "<p><a href=\"/\">Start again</a>"
                internal = False
                self.response.out.write(
                    self.render("templates/error.html", locals()))
                self.response.set_status(422)
                return

            # A unique number on all the giftcards.
            serial = membership.referrer[4:8]
            # How we know it's valid.
            hash = membership.referrer[8:16]
            confirmation_hash = re.sub(
                "[a-f]", "",
                hashlib.sha1(serial +
                             keymaster.get("code:hash")).hexdigest())[:8]

            if hash != confirmation_hash:
                message = "<p>Error: this code was invalid: %s" % \
                    (membership.referrer)
                message += "<p>Please contact %s if you believe this \
                          message is in error and we can help!"                                                                % \
                          (conf.SIGNUP_HELP_EMAIL)
                message += "<p><a href=\"/\">Start again</a>"
                internal = False
                uc = UsedCode(code=membership.referrer,
                              email=membership.email,
                              extra="invalid code")
                uc.put()
                self.response.out.write(
                    self.render("templates/error.html", locals()))
                self.response.set_status(422)
                return

            previous = UsedCode.all().filter("code =",
                                             membership.referrer).get()
            if previous:
                message = "<p>Error: this code has already been used: " + membership.referrer
                message += "<p>Please contact %s if you believe this" \
                            " message is in error and we can help!" % \
                            (conf.SIGNUP_HELP_EMAIL)
                message += "<p><a href=\"/\">Start again</a>"
                internal = False
                uc = UsedCode(code=membership.referrer,
                              email=membership.email,
                              extra="2nd+ attempt")
                uc.put()
                self.response.out.write(
                    self.render("templates/error.html", locals()))
                self.response.set_status(422)
                return

            # If we're testing, I don't want it doing random things on
            # pinpayments.
            if not Config().is_testing:
                headers = {"Authorization": "Basic %s" % \
                    base64.b64encode("%s:X" % conf.get_api_key()),
                    "Content-Type":"application/xml"}
                # Create subscriber
                data = "<subscriber><customer-id>%s</customer-id><email>%s</email></subscriber>" % (
                    customer_id, membership.email)
                resp = \
                    urlfetch.fetch("https://subs.pinpayments.com"
                                  "/api/v4/%s/subscribers.xml" % \
                                  (conf.SPREEDLY_ACCOUNT),
                                  method="POST", payload=data,
                                  headers = headers, deadline=5)
                # Credit
                data = "<credit><amount>95.00</amount></credit>"
                resp = \
                    urlfetch.fetch("https://subs.pinpayments.com/api/v4"
                                  "/%s/subscribers/%s/credits.xml" % \
                                  (conf.SPREEDLY_ACCOUNT, customer_id),
                                  method="POST", payload=data,
                                  headers=headers, deadline=5)

            uc = UsedCode(code=membership.referrer,
                          email=membership.email,
                          extra="OK")
            uc.put()

        # Redirect them to the PinPayments page, where they actually pay.
        self.redirect(
            membership.new_subscribe_url(self.request.host, plan=plan))
Esempio n. 33
0
    def post(self, hash):
        username = self.request.get("username")
        password = self.request.get("password")
        plan = self.request.get("plan")
        plan_object = plans.Plan.get_by_name(plan)
        account_url = str("/account/%s" % hash)

        conf = Config()
        if password != self.request.get("password_confirm"):
            self.response.out.write(self.render("templates/account.html", locals(), message="Passwords do not match."))
            self.response.set_status(422)
            return
        elif len(password) < 8:
            self.response.out.write(
                self.render("templates/account.html", locals(), message="Password must be at least 8 characters.")
            )
            self.response.set_status(422)
            return

        membership = Membership.get_by_hash(hash)

        if membership.domain_user:
            logging.warning("Duplicate user '%s' should have been caught" " in first step." % (membership.username))
            self.response.out.write(
                self.render("templates/account.html", locals(), message="You already have an account.")
            )
            self.response.set_status(422)
            return

        # Start saving the parameters for new-style accounts now, so that these
        # people won't have to re-enter anything when we make the transition.
        membership.set_password(password)

        # Set a username and password in the datastore.
        membership.username = username
        membership.password = password
        membership.put()

        if membership.status in ("active", "no_visits"):
            taskqueue.add(
                url="/tasks/create_user",
                method="POST",
                params={"hash": membership.hash, "username": username, "password": password},
                countdown=3,
            )
            self.redirect(str("http://%s/success/%s" % (self.request.host, membership.hash)))
            return

        customer_id = membership.key().id()

        # All our giftcards start out with 1337.
        if membership.referrer and "1337" in membership.referrer:

            if len(membership.referrer) != 16:
                message = "<p>Error: code must be 16 digits."
                message += (
                    "<p>Please contact %s if you believe this \
                          message is in error and we can help!"
                    % (conf.SIGNUP_HELP_EMAIL)
                )
                message += '<p><a href="/">Start again</a>'
                internal = False
                self.response.out.write(self.render("templates/error.html", locals()))
                self.response.set_status(422)
                return

            # A unique number on all the giftcards.
            serial = membership.referrer[4:8]
            # How we know it's valid.
            hash = membership.referrer[8:16]
            confirmation_hash = re.sub("[a-f]", "", hashlib.sha1(serial + keymaster.get("code:hash")).hexdigest())[:8]

            if hash != confirmation_hash:
                message = "<p>Error: this code was invalid: %s" % (membership.referrer)
                message += (
                    "<p>Please contact %s if you believe this \
                          message is in error and we can help!"
                    % (conf.SIGNUP_HELP_EMAIL)
                )
                message += '<p><a href="/">Start again</a>'
                internal = False
                uc = UsedCode(code=membership.referrer, email=membership.email, extra="invalid code")
                uc.put()
                self.response.out.write(self.render("templates/error.html", locals()))
                self.response.set_status(422)
                return

            previous = UsedCode.all().filter("code =", membership.referrer).get()
            if previous:
                message = "<p>Error: this code has already been used: " + membership.referrer
                message += "<p>Please contact %s if you believe this" " message is in error and we can help!" % (
                    conf.SIGNUP_HELP_EMAIL
                )
                message += '<p><a href="/">Start again</a>'
                internal = False
                uc = UsedCode(code=membership.referrer, email=membership.email, extra="2nd+ attempt")
                uc.put()
                self.response.out.write(self.render("templates/error.html", locals()))
                self.response.set_status(422)
                return

            # If we're testing, I don't want it doing random things on
            # pinpayments.
            if not Config().is_testing:
                headers = {
                    "Authorization": "Basic %s" % base64.b64encode("%s:X" % conf.get_api_key()),
                    "Content-Type": "application/xml",
                }
                # Create subscriber
                data = "<subscriber><customer-id>%s</customer-id><email>%s</email></subscriber>" % (
                    customer_id,
                    membership.email,
                )
                resp = urlfetch.fetch(
                    "https://subs.pinpayments.com" "/api/v4/%s/subscribers.xml" % (conf.SPREEDLY_ACCOUNT),
                    method="POST",
                    payload=data,
                    headers=headers,
                    deadline=5,
                )
                # Credit
                data = "<credit><amount>95.00</amount></credit>"
                resp = urlfetch.fetch(
                    "https://subs.pinpayments.com/api/v4"
                    "/%s/subscribers/%s/credits.xml" % (conf.SPREEDLY_ACCOUNT, customer_id),
                    method="POST",
                    payload=data,
                    headers=headers,
                    deadline=5,
                )

            uc = UsedCode(code=membership.referrer, email=membership.email, extra="OK")
            uc.put()

        # Redirect them to the PinPayments page, where they actually pay.
        self.redirect(membership.new_subscribe_url(self.request.host, plan=plan))
Esempio n. 34
0
    def post(self):
        """ Report a failure of this task. """
        def fail(exception):
            logging.error("CreateUserTask failed: %s" % exception)
            mail.send_mail(sender=Config().EMAIL_FROM,
                           to=Config().INTERNAL_DEV_EMAIL,
                           subject="[%s] CreateUserTask failure" %
                           Config().APP_NAME,
                           body=str(exception))

            self.response.set_status(500)

        """ Retry this task.
    countdown: How long to wait before running it again. """

        def retry(countdown=3):
            retries = int(self.request.get("retries", 0)) + 1
            if retries <= 5:
                taskqueue.add(url="/tasks/create_user",
                              method="POST",
                              countdown=countdown,
                              params={
                                  "hash": self.request.get("hash"),
                                  "username": self.request.get("username"),
                                  "password": self.request.get("password"),
                                  "retries": retries
                              })
            else:
                logging.error("Too many retries for %s" %
                              self.request.get("hash"))
                # We don't want it to retry again.
                self.response.set_status(200)

        user_hash = self.request.get("hash")
        membership = Membership.get_by_hash(user_hash)

        if membership is None:
            logging.error("Got nonexistent hash: %s" % (user_hash))
            self.response.set_status(422)
            return
        if membership.domain_user:
            logging.warning(
                "Not creating domain account for already-existing user '%s'." \
                % (membership.username))
            # Don't set another status here, because we don't want the
            # PinPayments system to keep retrying the call.
            return

        if not membership.spreedly_token:
            logging.warn("CreateUserTask: No spreedly token yet, retrying")
            return retry(300)

        username = self.request.get("username")
        password = self.request.get("password")

        try:
            url = "http://%s/users" % Config().DOMAIN_HOST
            payload = urllib.urlencode({
                "username": username,
                "password": password,
                "first_name": membership.first_name,
                "last_name": membership.last_name,
            })
            logging.info("CreateUserTask: About to create user: "******"CreateUserTask: URL: " + url)
            logging.info("CreateUserTask: Payload: " + payload)

            if not Config().is_testing:
                resp = urlfetch.fetch(url,
                                      method="POST",
                                      payload=payload,
                                      deadline=120,
                                      follow_redirects=False)
                if resp.status_code == 200:
                    logging.info("I think that worked.")
                else:
                    logging.error("I think that failed: HTTP %d" %
                                  (resp.status_code))
                    return retry()

            else:
                # I want to see what query string it would have used.
                self.response.out.write(payload)

            # Invalidate the current cached usernames, since we added a new one.
            self.invalidate_cached_usernames()

            membership.domain_user = True
            # We'll never use the password again, and there's no sense in
            # leaving this sensitive information sitting in the datastore, so we
            # might as well get rid of it.
            membership.password = None
            membership.put()

            # Send the welcome email.
            SuccessHandler.send_email(self, membership)
        except urlfetch.DownloadError, e:
            logging.error("Domain app response error or timeout, retrying")
            return retry()
Esempio n. 35
0
    def post(self):
        def fail(exception):
            logging.error("CreateUserTask failed: %s" % exception)
            mail.send_mail(sender=Config().EMAIL_FROM,
                to=Config().INTERNAL_DEV_EMAIL,
                subject="[%s] CreateUserTask failure" % Config().APP_NAME,
                body=str(exception))

            self.response.set_status(500)
        def retry(countdown=3):
            retries = int(self.request.get("retries", 0)) + 1
            if retries <= 5:
                taskqueue.add(url="/tasks/create_user", method="POST", countdown=countdown,
                    params={"hash": self.request.get("hash"),
                            "username": self.request.get("username"),
                            "password": self.request.get("password"),
                            "retries": retries})
            else:
                fail(Exception("Too many retries for %s" % self.request.get("hash")))

        user_hash = self.request.get("hash")
        membership = Membership.get_by_hash(user_hash)

        if membership is None:
            logging.error("Got nonexistent hash: %s" % (user_hash))
            self.response.set_status(422)
            return
        if membership.domain_user:
            logging.warning(
                "Not creating domain account for already-existing user '%s'." \
                % (membership.username))
            # Don't set another status here, because we don't want the
            # PinPayments system to keep retrying the call.
            return

        if not membership.spreedly_token:
            logging.warn("CreateUserTask: No spreedly token yet, retrying")
            return retry(300)

        username = self.request.get("username")
        password = self.request.get("password")

        try:
            url = "http://%s/users" % Config().DOMAIN_HOST
            payload = urllib.urlencode({
                "username": username,
                "password": password,
                "first_name": membership.first_name,
                "last_name": membership.last_name,
            })
            logging.info("CreateUserTask: About to create user: "******"CreateUserTask: URL: "+url)
            logging.info("CreateUserTask: Payload: "+payload)

            if not Config().is_testing:
              resp = urlfetch.fetch(url, method="POST", payload=payload,
                                    deadline=120, follow_redirects=False)
              logging.warning("CreateUserTask: I think that worked: HTTP %d" % \
                              (resp.status_code))

            else:
              # I want to see what query string it would have used.
              self.response.out.write(payload)

            membership.domain_user = True
            # We'll never use the password again, and there's no sense in
            # leaving this sensitive information sitting in the datastore, so we
            # might as well get rid of it.
            membership.password = None
            membership.put()

            # Send the welcome email.
            SuccessHandler.send_email(self, membership)
        except urlfetch.DownloadError, e:
            logging.warn("CreateUserTask: API response error or timeout, retrying")
            return retry()
Esempio n. 36
0
    def post(self, hash):
        username = self.request.get('username')
        password = self.request.get('password')
        c = Config()
        if password != self.request.get('password_confirm'):
            self.redirect(str(self.request.path + "?message=Passwords don't match"))
        elif len(password) < 8:
            self.redirect(str(self.request.path + "?message=Password must be 8 characters or longer"))
        else:
            membership = Membership.get_by_hash(hash)
            if membership.username:
                self.redirect(str(self.request.path + "?message=You already have a user account"))
                return
            
            # Yes, storing their username and password temporarily so we can make their account later
            memcache.set(str(hashlib.sha1(str(membership.hash)+c.SPREEDLY_APIKEY).hexdigest()), 
                '%s:%s' % (username, password), time=3600)
            
            if membership.status == 'active':
                taskqueue.add(url='/tasks/create_user', method='POST', params={'hash': membership.hash}, countdown=3)
                self.redirect(str('http://%s/success/%s' % (self.request.host, membership.hash)))
            else:
                customer_id = membership.key().id()
                
                # This code is not weird...
                if "1337" in membership.referrer:

                    if len(membership.referrer) !=16:
                        error = "<p>Error: code must be 16 digits."
                        error += "<p>Please contact "+ SIGNUP_HELP_EMAIL+" if you believe this message is in error and we can help!"
                        error += "<p><a href='/'>Start again</a>"
                        self.response.out.write(render('templates/error.html', locals()))
                        return

                    serial = membership.referrer[4:8]
                    hash = membership.referrer[8:16]
                    confirmation_hash = re.sub('[a-f]','',hashlib.sha1(serial+keymaster.get('code:hash')).hexdigest())[:8]

                    if hash != confirmation_hash:
                        error = "<p>Error: this code was invavlid: "+ membership.referrer
                        error += "<p>Please contact "+ SIGNUP_HELP_EMAIL+" if you believe this message is in error and we can help!"
                        error += "<p><a href='/'>Start again</a>"
                        uc = UsedCode(code=membership.referrer,email=membership.email,extra="invalid code")
                        uc.put()
                        self.response.out.write(render('templates/error.html', locals()))
                        return

                    previous = UsedCode.all().filter('code =', membership.referrer).get()
                    if previous:
                        error = "<p>Error: this code has already been used: "+ membership.referrer
                        error += "<p>Please contact "+ SIGNUP_HELP_EMAIL+" if you believe this message is in error and we can help!"
                        error += "<p><a href='/'>Start again</a>"
                        uc = UsedCode(code=membership.referrer,email=membership.email,extra="2nd+ attempt")
                        uc.put()
                        self.response.out.write(render('templates/error.html', locals()))
                        return

                    headers = {'Authorization': "Basic %s" % base64.b64encode('%s:X' % c.SPREEDLY_APIKEY),
                        'Content-Type':'application/xml'}
                    # Create subscriber
                    data = "<subscriber><customer-id>%s</customer-id><email>%s</email></subscriber>" % (customer_id, membership.email)
                    resp = urlfetch.fetch("https://subs.pinpayments.com/api/v4/%s/subscribers.xml" % (c.SPREEDLY_ACCOUNT), 
                            method='POST', payload=data, headers = headers, deadline=5)
                    # Credit
                    data = "<credit><amount>95.00</amount></credit>"
                    resp = urlfetch.fetch("https://subs.pinpayments.com/api/v4/%s/subscribers/%s/credits.xml" % (c.SPREEDLY_ACCOUNT, customer_id), 
                            method='POST', payload=data, headers=headers, deadline=5)

                    uc = UsedCode(code=membership.referrer,email=membership.email,extra='OK')
                    uc.put()
                
                query_str = urllib.urlencode({'first_name': membership.first_name, 'last_name': membership.last_name, 
                    'email': membership.email, 'return_url':
                    'http://%s/success/%s' % (self.request.host, membership.hash)})
                # check if they are active already since we didn't create a new member above
                # apparently the URL will be different
                self.redirect(str("https://spreedly.com/%s/subscribers/%s/subscribe/%s/%s?%s" % 
                    (c.SPREEDLY_ACCOUNT, customer_id, c.PLAN_IDS[membership.plan], username, query_str)))