<s> """<STR_LIT>""" <EOL> import time <EOL> try : <EOL> from ndb import model <EOL> except ImportError : <EOL> from google . appengine . ext . ndb import model <EOL> from webapp2_extras import auth <EOL> from webapp2_extras import security <EOL> class Unique ( model . Model ) : <EOL> """<STR_LIT>""" <EOL> @ classmethod <EOL> def create ( cls , value ) : <EOL> """<STR_LIT>""" <EOL> entity = cls ( key = model . Key ( cls , value ) ) <EOL> txn = lambda : entity . put ( ) if not entity . key . get ( ) else None <EOL> return model . transaction ( txn ) is not None <EOL> @ classmethod <EOL> def create_multi ( cls , values ) : <EOL> """<STR_LIT>""" <EOL> keys = [ model . Key ( cls , value ) for value in values ] <EOL> entities = [ cls ( key = key ) for key in keys ] <EOL> func = lambda e : e . put ( ) if not e . key . get ( ) else None <EOL> created = [ model . transaction ( lambda : func ( e ) ) for e in entities ] <EOL> if created != keys : <EOL> model . delete_multi ( k for k in created if k ) <EOL> return False , [ k . id ( ) for k in keys if k not in created ] <EOL> return True , [ ] <EOL> @ classmethod <EOL> def delete_multi ( cls , values ) : <EOL> """<STR_LIT>""" <EOL> return model . delete_multi ( model . Key ( cls , v ) for v in values ) <EOL> class UserToken ( model . Model ) : <EOL> """<STR_LIT>""" <EOL> created = model . DateTimeProperty ( auto_now_add = True ) <EOL> updated = model . DateTimeProperty ( auto_now = True ) <EOL> user = model . StringProperty ( required = True , indexed = False ) <EOL> subject = model . StringProperty ( required = True ) <EOL> token = model . StringProperty ( required = True ) <EOL> @ classmethod <EOL> def get_key ( cls , user , subject , token ) : <EOL> """<STR_LIT>""" <EOL> return model . Key ( cls , '<STR_LIT>' % ( str ( user ) , subject , token ) ) <EOL> @ classmethod <EOL> def create ( cls , user , subject , token = None ) : <EOL> """<STR_LIT>""" <EOL> user = str ( user ) <EOL> token = token or security . generate_random_string ( entropy = <NUM_LIT> ) <EOL> key = cls . get_key ( user , subject , token ) <EOL> entity = cls ( key = key , user = user , subject = subject , token = token ) <EOL> entity . put ( ) <EOL> return entity <EOL> @ classmethod <EOL> def get ( cls , user = None , subject = None , token = None ) : <EOL> """<STR_LIT>""" <EOL> if user and subject and token : <EOL> return cls . get_key ( user , subject , token ) . get ( ) <EOL> assert subject and token , '<STR_LIT>' <EOL> return cls . query ( cls . subject == subject , cls . token == token ) . get ( ) <EOL> class User ( model . Expando ) : <EOL> """<STR_LIT>""" <EOL> unique_model = Unique <EOL> token_model = UserToken <EOL> created = model . DateTimeProperty ( auto_now_add = True ) <EOL> updated = model . DateTimeProperty ( auto_now = True ) <EOL> auth_ids = model . StringProperty ( repeated = True ) <EOL> password = model . StringProperty ( ) <EOL> def get_id ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _key . id ( ) <EOL> def add_auth_id ( self , auth_id ) : <EOL> """<STR_LIT>""" <EOL> self . auth_ids . append ( auth_id ) <EOL> unique = '<STR_LIT>' % ( self . __class__ . __name__ , auth_id ) <EOL> ok = self . unique_model . create ( unique ) <EOL> if ok : <EOL> self . put ( ) <EOL> return True , self <EOL> else : <EOL> return False , [ '<STR_LIT>' ] <EOL> @ classmethod <EOL> def get_by_auth_id ( cls , auth_id ) : <EOL> """<STR_LIT>""" <EOL> return cls . query ( cls . auth_ids == auth_id ) . get ( ) <EOL> @ classmethod <EOL> def get_by_auth_token ( cls , user_id , token ) : <EOL> """<STR_LIT>""" <EOL> token_key = cls . token_model . get_key ( user_id , '<STR_LIT>' , token ) <EOL> user_key = model . Key ( cls , user_id ) <EOL> valid_token , user = model . get_multi ( [ token_key , user_key ] ) <EOL> if valid_token and user : <EOL> timestamp = int ( time . mktime ( valid_token . created . timetuple ( ) ) ) <EOL> return user , timestamp <EOL> return None , None <EOL> @ classmethod <EOL> def get_by_auth_password ( cls , auth_id , password ) : <EOL> """<STR_LIT>""" <EOL> user = cls . get_by_auth_id ( auth_id ) <EOL> if not user : <EOL> raise auth . InvalidAuthIdError ( ) <EOL> if not security . check_password_hash ( password , user . password ) : <EOL> raise auth . InvalidPasswordError ( ) <EOL> return user <EOL> @ classmethod <EOL> def validate_token ( cls , user_id , subject , token ) : <EOL> """<STR_LIT>""" <EOL> return cls . token_model . get ( user = user_id , subject = subject , <EOL> token = token ) is not None <EOL> @ classmethod <EOL> def create_auth_token ( cls , user_id ) : <EOL> """<STR_LIT>""" <EOL> return cls . token_model . create ( user_id , '<STR_LIT>' ) . token <EOL> @ classmethod <EOL> def validate_auth_token ( cls , user_id , token ) : <EOL> return cls . validate_token ( user_id , '<STR_LIT>' , token ) <EOL> @ classmethod <EOL> def delete_auth_token ( cls , user_id , token ) : <EOL> """<STR_LIT>""" <EOL> cls . token_model . get_key ( user_id , '<STR_LIT>' , token ) . delete ( ) <EOL> @ classmethod <EOL> def create_signup_token ( cls , user_id ) : <EOL> entity = cls . token_model . create ( user_id , '<STR_LIT>' ) <EOL> return entity . token <EOL> @ classmethod <EOL> def validate_signup_token ( cls , user_id , token ) : <EOL> return cls . validate_token ( user_id , '<STR_LIT>' , token ) <EOL> @ classmethod <EOL> def delete_signup_token ( cls , user_id , token ) : <EOL> cls . token_model . get_key ( user_id , '<STR_LIT>' , token ) . delete ( ) <EOL> @ classmethod <EOL> def create_user ( cls , auth_id , unique_properties = None , ** user_values ) : <EOL> """<STR_LIT>""" <EOL> assert user_values . get ( '<STR_LIT:password>' ) is None , '<STR_LIT>' <EOL> assert not isinstance ( auth_id , list ) , '<STR_LIT>' '<STR_LIT>' <EOL> if '<STR_LIT>' in user_values : <EOL> user_values [ '<STR_LIT:password>' ] = security . generate_password_hash ( <EOL> user_values . pop ( '<STR_LIT>' ) , length = <NUM_LIT:12> ) <EOL> user_values [ '<STR_LIT>' ] = [ auth_id ] <EOL> user = cls ( ** user_values ) <EOL> uniques = [ ( '<STR_LIT>' % ( cls . __name__ , auth_id ) , '<STR_LIT>' ) ] <EOL> if unique_properties : <EOL> for name in unique_properties : <EOL> key = '<STR_LIT>' % ( cls . __name__ , name , user_values [ name ] ) <EOL> uniques . append ( ( key , name ) ) <EOL> ok , existing = cls . unique_model . create_multi ( k for k , v in uniques ) <EOL> if ok : <EOL> user . put ( ) <EOL> return True , user <EOL> else : <EOL> properties = [ v for k , v in uniques if k in existing ] <EOL> return False , properties </s>
