~launchpad-pqm/launchpad/devel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# Copyright 2009-2012 Canonical Ltd.  This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).

# pylint: disable-msg=E0211,E0213

"""EmailAddress interfaces."""

__metaclass__ = type
__all__ = [
    'EmailAddressAlreadyTaken',
    'EmailAddressStatus',
    'IEmailAddress',
    'IEmailAddressSet',
    'InvalidEmailAddress']

from lazr.enum import (
    DBEnumeratedType,
    DBItem,
    )
from lazr.restful.declarations import (
    export_as_webservice_entry,
    exported,
    )
from lazr.restful.fields import Reference
from zope.interface import Interface
from zope.schema import (
    Choice,
    Int,
    Object,
    TextLine,
    )

from lp import _
from lp.registry.interfaces.role import IHasOwner
from lp.services.identity.interfaces.account import IAccount


class InvalidEmailAddress(Exception):
    """The email address is not valid."""


class EmailAddressAlreadyTaken(Exception):
    """The email address is already registered in Launchpad."""


class EmailAddressStatus(DBEnumeratedType):
    """Email Address Status

    Launchpad keeps track of email addresses associated with a person. They
    can be used to login to the system, or to associate an Arch changeset
    with a person, or to associate a bug system email message with a person,
    for example.
    """

    NEW = DBItem(1, """
        New Email Address

        This email address has had no validation associated with it. It
        has just been created in the system, either by a person claiming
        it as their own, or because we have stored an email message or
        arch changeset including that email address and have created
        a phantom person and email address to record it. WE SHOULD
        NEVER EMAIL A "NEW" EMAIL.
        """)

    VALIDATED = DBItem(2, """
        Validated Email Address

        We have proven that the person associated with this email address
        can read email sent to this email address, by sending a token
        to that address and getting the appropriate response from that
        person.
        """)

    OLD = DBItem(3, """
        Old Email Address

        The email address was validated for this person, but is now no
        longer accessible or in use by them. We should not use this email
        address to login that person, nor should we associate new incoming
        content from that email address with that person.
        """)

    PREFERRED = DBItem(4, """
        Preferred Email Address

        The email address was validated and is the person's choice for
        receiving notifications from Launchpad.
        """)


class IEmailAddress(IHasOwner):
    """The object that stores the `IPerson`'s emails."""
    export_as_webservice_entry(plural_name='email_addresses')

    id = Int(title=_('ID'), required=True, readonly=True)
    email = exported(
        TextLine(title=_('Email Address'), required=True, readonly=True))
    status = Choice(
        title=_('Email Address Status'), required=True, readonly=False,
        vocabulary=EmailAddressStatus)
    account = Object(title=_('Account'), schema=IAccount, required=False)
    accountID = Int(title=_('AccountID'), required=False, readonly=True)
    person = exported(
        Reference(title=_('Person'), required=False, readonly=False,
                  schema=Interface))
    personID = Int(title=_('PersonID'), required=False, readonly=True)

    rdf_sha1 = TextLine(
        title=_("RDF-ready SHA-1 Hash"),
        description=_("The SHA-1 hash of the preferred email address and "
                      "a mailto: prefix as a hexadecimal string. This is "
                      "used as a key by FOAF RDF spec"),
        readonly=True)

    def destroySelf():
        """Destroy this email address and any associated subscriptions.

        :raises UndeletableEmailAddress: When the email address is a person's
            preferred one or a hosted mailing list's address.
        """

    def syncUpdate():
        """Write updates made on this object to the database.

        This should be used when you can't wait until the transaction is
        committed to have some updates actually written to the database.
        """


class IEmailAddressSet(Interface):
    """The set of EmailAddresses."""

    def new(email, person=None, status=EmailAddressStatus.NEW, account=None):
        """Create a new EmailAddress with the given email.

        The newly created EmailAddress will point to the person
        and/or account. If account is omitted and the person has a linked
        account, that account will be used.

        The given status must be an item of EmailAddressStatus.

        :raises InvalidEmailAddress: If the email address is invalid.
        """

    def getByPerson(person):
        """Return all email addresses for the given person."""

    def getPreferredEmailForPeople(people):
        """Return preferred email addresses for the people provided."""

    def getByEmail(email):
        """Return the EmailAddress object for the given email.

        Return None if there is no such email address.
        """