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