PageRenderTime 97ms CodeModel.GetById 55ms app.highlight 10ms RepoModel.GetById 30ms app.codeStats 0ms

/kai/model/human.py

https://bitbucket.org/bbangert/kai/
Python | 133 lines | 120 code | 11 blank | 2 comment | 5 complexity | c57f7ad7e81be757954a34702dda1dbb MD5 | raw file
  1import os
  2import md5
  3import sha
  4from datetime import datetime
  5
  6import pylons
  7from couchdb.schema import DateTimeField, Document, TextField, ListField, View
  8
  9from kai.model.paste import Paste
 10from kai.model.traceback import Traceback
 11
 12
 13class Human(Document):
 14    """Represents a human user"""
 15    type = TextField(default='Human')
 16    displayname = TextField()
 17    email = TextField()
 18    timezone = TextField()
 19    password = TextField()
 20    created = DateTimeField(default=datetime.utcnow)
 21    last_login = DateTimeField(default=datetime.utcnow)
 22    blog = TextField()
 23    session_id = TextField()
 24    
 25    email_token = TextField()
 26    password_token = TextField()
 27    
 28    email_token_issue = DateTimeField()
 29    password_token_issue = DateTimeField()    
 30    
 31    openids = ListField(TextField())
 32    groups = ListField(TextField())
 33    
 34    by_openid = View('human', '''
 35        function(doc) {
 36          if (doc.type == 'Human' && doc.openids) {
 37            for (var idx in doc.openids) {
 38              emit(doc.openids[idx], null);
 39            }
 40          }
 41        }''', include_docs=True)
 42    
 43    by_displayname = View('human', '''
 44        function(doc) {
 45          if (doc.type == 'Human') {
 46            emit(doc.displayname, null);
 47          }
 48        }''', include_docs=True)
 49    
 50    by_email = View('human', '''
 51        function(doc) {
 52          if (doc.type == 'Human') {
 53            emit(doc.email, null);
 54          }
 55        }''', include_docs=True)
 56    
 57    by_email_token = View('human', '''
 58        function(doc) {
 59          if (doc.type == 'Human' && doc.email_token) {
 60            emit(doc.email_token, null);
 61          }
 62        }''', include_docs=True)
 63    
 64    by_password_token = View('human', '''
 65        function(doc) {
 66          if (doc.type == 'Human' && doc.password_token) {
 67            emit(doc.password_token, null);
 68          }
 69        }''', include_docs=True)
 70    
 71    @staticmethod
 72    def hash_password(plain_text):
 73        """Returns a crypted/salted password field
 74        
 75        The salt is stored in front of the password, for per user 
 76        salts.
 77        
 78        """
 79        if isinstance(plain_text, unicode):
 80            plain_text = plain_text.encode('utf-8')
 81        password_salt = sha.new(os.urandom(60)).hexdigest()
 82        crypt = sha.new(plain_text + password_salt).hexdigest()
 83        return password_salt + crypt
 84    
 85    def verify_password(self, plain_text):
 86        """Verify a plain text string is the users password"""  
 87        if isinstance(plain_text, unicode):
 88            plain_text = plain_text.encode('utf-8')
 89        
 90        # Some users don't have passwords, like OpenID users, so they
 91        # can't use a password to login
 92        if not self.password:
 93            return False
 94        
 95        password_salt = self.password[:40]
 96        crypt_pass = sha.new(plain_text + password_salt).hexdigest()
 97        if crypt_pass == self.password[40:]:
 98            return True
 99        else:
100            return False
101    
102    def email_hash(self):
103        return md5.md5(self.email).hexdigest()
104    
105    def generate_token(self):
106        """Generate's a token for use either for forgot password or
107        email verification"""
108        return sha.new(os.urandom(60)).hexdigest()
109    
110    def valid_password_token(self):
111        diff = datetime.now() - self.password_token_issue
112        token_lifespan = pylons.config['sso.password_token_lifespan']
113        if diff.days < 1 and diff.seconds < token_lifespan:
114            return True
115        else:
116            return False
117    
118    def in_group(self, group):
119        if group in list(self.groups):
120            return True
121        else:
122            return False
123    
124    def process_login(self):
125        session = pylons.session._current_obj()
126        session['logged_in'] = True
127        session['displayname'] = self.displayname
128        session['user_id'] = self.id
129        session.save()
130        self.session_id = session.id
131        self.store(pylons.tmpl_context.db)
132        Paste.associate_pasties(self)
133        Traceback.associate_tracebacks(self)