7 from PLC.Debug import log
8 from PLC.Faults import *
9 from PLC.Method import Method
10 from PLC.Parameter import Parameter, Mixed
11 from PLC.Persons import Person, Persons
12 from PLC.Sites import Site, Sites
13 from PLC.Messages import Message, Messages
14 from PLC.Auth import Auth
15 from PLC.sendmail import sendmail
17 class VerifyPerson(Method):
19 Verify a new (must be disabled) user's e-mail address and registration.
21 If verification_key is not specified, then a new verification_key
22 will be generated and stored with the user's account. The key will
23 be e-mailed to the user in the form of a link to a web page.
25 The web page should verify the key by calling this function again
26 and specifying verification_key. If the key matches what has been
27 stored in the user's account, then an e-mail will be sent to the
28 user's PI (and support if the user is requesting a PI role),
29 asking the PI (or support) to enable the account.
31 Returns 1 if the verification key if valid.
38 Mixed(Person.fields['person_id'],
39 Person.fields['email']),
40 Person.fields['verification_key'],
41 Person.fields['verification_expires']
44 returns = Parameter(int, '1 if verification_key is valid')
46 def call(self, auth, person_id_or_email, verification_key = None, verification_expires = None):
47 # Get account information
48 persons = Persons(self.api, [person_id_or_email])
50 raise PLCInvalidArgument, "No such account %r"%person_id_or_email
53 if person['peer_id'] is not None:
54 raise PLCInvalidArgument, "Not a local account %r"%person_id_or_email
57 raise PLCInvalidArgument, "Account %r must be new (disabled)"%person_id_or_email
59 # Get the primary site name
60 person_sites = Sites(self.api, person['site_ids'])
62 site_name = person_sites[0]['name']
66 # Generate 32 random bytes
67 bytes = random.sample(xrange(0, 256), 32)
68 # Base64 encode their string representation
69 random_key = base64.b64encode("".join(map(chr, bytes)))
71 if verification_key is None or \
72 (verification_key is not None and person['verification_expires'] and \
73 person['verification_expires'] < time.time()):
74 # Only allow one verification at a time
75 if person['verification_expires'] is not None and \
76 person['verification_expires'] > time.time():
77 raise PLCPermissionDenied, "Verification request already pending"
79 if verification_expires is None:
80 verification_expires = int(time.time() + (24 * 60 * 60))
82 person['verification_key'] = random_key
83 person['verification_expires'] = verification_expires
87 To = ("%s %s" % (person['first_name'], person['last_name']), person['email'])
90 message_id = 'Verify account'
93 elif verification_key is not None:
94 if person['verification_key'] is None or \
95 person['verification_expires'] is None:
96 raise PLCPermissionDenied, "Invalid Verification key"
97 elif person['verification_key'] != verification_key:
98 raise PLCPermissionDenied, "Verification key incorrect"
100 person['verification_key'] = None
101 person['verification_expires'] = None
104 # Get the PI(s) of each site that the user is registering with
106 for site in person_sites:
107 person_ids.update(site['person_ids'])
108 persons = Persons(self.api, person_ids)
109 pis = filter(lambda person: 'pi' in person['roles'] and person['enabled'], persons)
111 # Send e-mail to PI(s) and copy the user
112 To = [("%s %s" % (pi['first_name'], pi['last_name']), pi['email']) for pi in pis]
113 Cc = ("%s %s" % (person['first_name'], person['last_name']), person['email'])
115 if 'pi' in person['roles']:
116 # And support if user is requesting a PI role
117 To.append(("%s Support" % self.api.config.PLC_NAME,
118 self.api.config.PLC_MAIL_SUPPORT_ADDRESS))
119 message_id = 'New PI account'
121 message_id = 'New account'
123 messages = Messages(self.api, [message_id])
125 # Send message to user
126 message = messages[0]
128 params = {'PLC_NAME': self.api.config.PLC_NAME,
129 'PLC_MAIL_SUPPORT_ADDRESS': self.api.config.PLC_MAIL_SUPPORT_ADDRESS,
130 'PLC_WWW_HOST': self.api.config.PLC_WWW_HOST,
131 'PLC_WWW_SSL_PORT': self.api.config.PLC_WWW_SSL_PORT,
132 'person_id': person['person_id'],
133 # Will be used in a URL, so must quote appropriately
134 'verification_key': urllib.quote_plus(random_key),
135 'site_name': site_name,
136 'first_name': person['first_name'],
137 'last_name': person['last_name'],
138 'email': person['email'],
139 'roles': ", ".join(person['roles'])}
144 Subject = message['subject'] % params,
145 Body = message['template'] % params)
147 print >> log, "Warning: No message template '%s'" % message_id
150 self.event_objects = {'Person': [person['person_id']]}
151 self.message = message_id
153 if verification_key is not None and person['verification_expires'] and \
154 person['verification_expires'] < time.time():
155 raise PLCPermissionDenied, "Verification key has expired. Another email has been sent."