Skip to content
This repository has been archived by the owner on Feb 8, 2018. It is now read-only.

Commit

Permalink
Shelve
Browse files Browse the repository at this point in the history
  • Loading branch information
chadwhitacre committed Mar 3, 2017
1 parent 4ac1d86 commit a487ef5
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 18 deletions.
17 changes: 17 additions & 0 deletions emails/claim-package.spt
@@ -0,0 +1,17 @@
{{ _("Claim {0} on Gratipay?", project) }}

[---] text/html
{{ _("We've received a request to connect {0} to the {1} account on Gratipay. Sound familiar?",
('<b>%s</b>'|safe) % email,
('<b><a href="https://gratipay.com/~{0}/">{0}</a></b>'|safe).format(username)) }}
<br>
<br>
<a href="{{ link }}" style="{{ button_style }}">{{ _("Yes, proceed!") }}</a>

[---] text/plain
{{ _("We've received a request to connect {0} to the {1} account on Gratipay. Sound familiar?",
email, username) }}

{{ _("Follow this link to finish connecting your email:") }}

{{ link }}
7 changes: 0 additions & 7 deletions gratipay/models/package/__init__.py
Expand Up @@ -40,10 +40,3 @@ def from_names(cls, package_manager, name):
"""
return cls.db.one("SELECT packages.*::packages FROM packages "
"WHERE package_manager=%s and name=%s", (package_manager, name))


# Emails
# ======

def send_confirmation_email(self, address):
pass
13 changes: 10 additions & 3 deletions gratipay/models/participant/email.py
Expand Up @@ -41,22 +41,25 @@ class Email(object):
"""

def add_email(self, email):
def add_email(self, email, package=None):
"""Add an email address for a participant.
This is called when adding a new email address, and when resending the
verification email for an unverified email address.
:param unicode email: the email address to add
:returns: ``None``
:param Package package: a package the participant is claiming
:raises EmailAlreadyVerified: if the email is already verified for
this participant
:raises EmailTaken: if the email is verified for a different participant
:raises TooManyEmailAddresses: if the participant already has 10 emails
:raises Throttled: if the participant adds too many emails too quickly
:returns: the number of emails sent
If ``package`` is provided, then
"""

# Check that this address isn't already verified
Expand All @@ -67,6 +70,10 @@ def add_email(self, email):
WHERE e.address = %(email)s
AND e.verified IS true
""", locals())

if package:
return self.initiate_package_claim(package, email)

if owner:
if owner == self.username:
raise EmailAlreadyVerified(email)
Expand Down
37 changes: 37 additions & 0 deletions gratipay/models/participant/package_claiming.py
@@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals


class PackageClaiming(object):

"""Gratipay participants may claim packages on the Node package manager
(npm), bringing them into Gratipay as projects similar to any other. The
claiming process is handled via email: ``initiate_package_claim`` sends an
email to an address registered with npm, and a link back from the email
lands in ``claim_package`` to finalize the claim.
Packages can also be unclaimed, and reclaimed.
"""

def initiate_package_claim(self, package, email):
"""Initiate a claim on the given package.
:param Package package: a ``Package`` instance
:returns: ``None``
"""
assert email in package.emails # sanity check

r = self.send_email('claim_package',
email=email,
link=link.format(**locals()),
include_unsubscribe=False)
assert r == 1 # Make sure the verification email was sent
if self.email_address:
self.send_email('verification_notice',
new_email=email,
include_unsubscribe=False)
return 2
return 1
12 changes: 7 additions & 5 deletions gratipay/testing/harness.py
Expand Up @@ -17,6 +17,7 @@
from gratipay.exceptions import NoSelfTipping, NoTippee, BadAmount
from gratipay.models.account_elsewhere import AccountElsewhere
from gratipay.models.exchange_route import ExchangeRoute
from gratipay.models.package import NPM, Package
from gratipay.models.participant import Participant, MAX_TIP, MIN_TIP
from gratipay.security import user
from gratipay.testing.vcr import use_cassette
Expand Down Expand Up @@ -195,14 +196,15 @@ def make_team(self, *a, **kw):
return team


def make_package(self, package_manager='npm', name='foo', description='Foo',
def make_package(self, package_manager=NPM, name='foo', description='Foo',
emails=['alice@example.com']):
"""Factory for packages.
"""
return self.db.one( 'INSERT INTO packages (package_manager, name, description, emails) '
'VALUES (%s, %s, %s, %s) RETURNING *'
, (package_manager, name, description, emails)
)
self.db.run( 'INSERT INTO packages (package_manager, name, description, emails) '
'VALUES (%s, %s, %s, %s) RETURNING *'
, (package_manager, name, description, emails)
)
return Package.from_names(NPM, name)


def make_participant(self, username, **kw):
Expand Down
10 changes: 10 additions & 0 deletions tests/py/test_packages.py
Expand Up @@ -3,6 +3,7 @@

from gratipay.models.package import NPM, Package
from gratipay.testing import Harness
from gratipay.testing.emails import EmailHarness


class TestPackage(Harness):
Expand All @@ -14,3 +15,12 @@ def test_can_be_instantiated_from_id(self):
def test_can_be_instantiated_from_names(self):
self.make_package()
assert Package.from_names(NPM, 'foo').name == 'foo'


class TestClaiming(EmailHarness):

def test_participant_can_initiate_package_claim(self):
alice = self.make_participant('alice', claimed_time='now')
p = self.make_package()
alice.initiate_package_claim(p)
assert self.get_last_email()
5 changes: 2 additions & 3 deletions www/~/%username/emails/modify.json.spt
Expand Up @@ -39,8 +39,7 @@ if action in ('add-email', 'resend'):
raise Response(400, _( "You have already added and verified {email_address}."
, email_address=address
))
else:
msg = _("A verification email has been sent to {email_address}.", email_address=address)
msg = _("Check your inbox for a verification link.")
elif action == 'set-primary':
participant.update_email(address)
elif action == 'remove':
Expand All @@ -49,7 +48,7 @@ elif action == 'add-email-and-claim-package':
package_id = request.body['package_id']
package = Package.from_id(package_id)
package.send_confirmation_email(address)
msg = _("Check {email} for a confirmation link.", email=address)
msg = _("Check your inbox for a confirmation link.")
else:
raise Response(400, 'unknown action "%s"' % action)

Expand Down

0 comments on commit a487ef5

Please sign in to comment.