# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: Persons.py,v 1.20 2006/11/24 12:06:00 thierry Exp $
+# $Id: Persons.py,v 1.29 2007/01/08 16:34:12 tmack Exp $
#
from types import StringTypes
import crypt
from PLC.Faults import *
+from PLC.Debug import log
from PLC.Parameter import Parameter
from PLC.Filter import Filter
from PLC.Table import Row, Table
from PLC.Keys import Key, Keys
+from PLC.Messages import Message, Messages
import PLC.Sites
class Person(Row):
'bio': Parameter(str, "Biography", max = 254, nullok = True),
'enabled': Parameter(bool, "Has been enabled"),
'password': Parameter(str, "Account password in crypt() form", max = 254),
- 'last_updated': Parameter(int, "Date and time of last update", ro = True),
+ 'verification_key': Parameter(str, "Reset password key", max = 254),
+ 'verification_expires': Parameter(str, "Date/Time when verification_key expires", max = 254),
+ 'last_updated': Parameter(int, "Date and time of last update", ro = True),
'date_created': Parameter(int, "Date and time when account was created", ro = True),
'role_ids': Parameter([int], "List of role identifiers"),
'roles': Parameter([str], "List of roles"),
# for Cache
class_key = 'email'
foreign_fields = ['first_name', 'last_name', 'title', 'email', 'phone', 'url',
- 'bio', 'enabled', 'password', 'last_updated', 'date_created']
- #foreign_xrefs = { 'Node' : { 'field' : 'node_ids' ,
- # 'table': 'slice_node' } }
- foreign_xrefs = {
- 'Key' : { 'field' : 'key_ids', 'table' : 'person_key' } ,
- 'Site' : { 'field' : 'site_ids', 'table' : 'person_site'},
-# 'key_ids': Parameter([int], "List of key identifiers"),
+ 'bio', 'enabled', 'password', ]
+ # forget about these ones, they are read-only anyway
+ # handling them causes Cache to re-sync all over again
+ # 'last_updated', 'date_created'
+ foreign_xrefs = [
+ {'field' : 'key_ids', 'class': 'Key', 'table' : 'person_key' } ,
+ {'field' : 'site_ids', 'class': 'Site', 'table' : 'person_site'},
+# xxx this is not handled by Cache yet
# 'role_ids': Parameter([int], "List of role identifiers"),
-# 'roles': Parameter([str], "List of roles"),
-# 'site_ids': Parameter([int], "List of site identifiers"),
-# 'slice_ids': Parameter([int], "List of slice identifiers"),
-}
+]
def validate_email(self, email):
"""
salt = md5.md5(salt).hexdigest()[:8]
return crypt.crypt(password.encode(self.api.encoding), magic + salt + "$")
+ # timestamps
+ # verification_expires in the DB but not exposed here
+ def validate_date_created (self, timestamp):
+ return self.validate_timestamp (timestamp)
+ def validate_last_updated (self, timestamp):
+ return self.validate_timestamp (timestamp)
+
def can_update(self, person):
"""
Returns true if we can update the specified person. We can
self['site_ids'].remove(site_id)
self['site_ids'].insert(0, site_id)
+ def send_initiate_password_reset_email(self):
+ # email user next step instructions
+ to_addr = {}
+ to_addr[self['email']] = "%s %s" % \
+ (self['first_name'], self['last_name'])
+ from_addr = {}
+ from_addr[self.api.config.PLC_MAIL_SUPPORT_ADDRESS] = \
+ "%s %s" % ('Planetlab', 'Support')
+
+ # fill in template
+ messages = Messages(self.api, ['ASSWORD_RESET_INITIATE'])
+ if not messages:
+ print >> log, "No such message template"
+ return 1
+
+ message = messages[0]
+ subject = message['subject']
+ template = message['template'] % \
+ (self.api.config.PLC_WWW_HOST,
+ self['verification_key'], self['person_id'],
+ self.api.config.PLC_MAIL_SUPPORT_ADDRESS,
+ self.api.config.PLC_WWW_HOST)
+
+ self.api.mailer.mail(to_addr, None, from_addr, subject, template)
+
+ def send_account_registered_email(self, site):
+
+ to_addr = {}
+ cc_addr = {}
+ from_addr = {}
+ from_addr[self.api.config.PLC_MAIL_SUPPORT_ADDRESS] = \
+ "%s %s" % ('Planetlab', 'Support')
+
+ # email user
+ user_full_name = "%s %s" % (self['first_name'], self['last_name'])
+ to_addr[self['email']] = "%s" % user_full_name
+
+ # if the account had a admin role or a pi role, email support.
+ if set(['admin', 'pi']).intersection(self['roles']):
+ to_addr[self.api.config.PLC_MAIL_SUPPORT_ADDRESS] = \
+ "%s %s" % ('Planetlab', 'Support')
+
+ # cc site pi's
+ site_persons = Persons(self.api, site['person_ids'])
+ for person in site_persons:
+ if 'pi' in person['roles'] and not person['email'] in to_addr.keys():
+ cc_addr[person['email']] = "%s %s" % \
+ (person['first_name'], person['last_name'])
+
+ # fill in template
+ messages = Messages(self.api, ['ACCOUNT_REGISTERED'])
+ if not messages:
+ print >> log, "No such message template"
+ return 1
+
+ message = messages[0]
+ subject = message['subject'] % (user_full_name, site['name'])
+ template = message['template'] % \
+ (user_full_name, site['name'], ", ".join(self['roles']),
+ self.api.config.PLC_WWW_HOST, self['person_id'],
+ self.api.config.PLC_MAIL_SUPPORT_ADDRESS,
+ self.api.config.PLC_WWW_HOST)
+
+ self.api.mailer.mail(to_addr, cc_addr, from_addr, subject, template)
+
def delete(self, commit = True):
"""
Delete existing account.
elif isinstance(person_filter, dict):
person_filter = Filter(Person.fields, person_filter)
sql += " AND (%s)" % person_filter.sql(api, "AND")
-
self.selectall(sql)