class UserToken(model.Model): """Stores validation tokens for users.""" created = model.DateTimeProperty(auto_now_add=True) updated = model.DateTimeProperty(auto_now=True) user = model.StringProperty(required=True, indexed=False) subject = model.StringProperty(required=True) token = model.StringProperty(required=True) @classmethod def get_key(cls, user, subject, token): """Returns a token key.""" return model.Key(cls, '%s.%s.%s' % (user, subject, token)) @classmethod def create(cls, user, subject, token=None): """Fetches a user token.""" token = token or security.generate_random_string(entropy=64) key = cls.get_key(user, subject, token) entity = cls(key=key, user=user, subject=subject, token=token) entity.put() return entity @classmethod def get(cls, user=None, subject=None, token=None): """Fetches a user token.""" if user and subject and token: return cls.get_key(user, subject, token).get() assert subject and token, \ 'subject and token must be provided to UserToken.get().' return cls.query(cls.subject == subject, cls.token == token).get()
class UrlSummary(model.Model): """Metadata about a URL.""" MAX_AGE = 60 url = model.StringProperty() title = model.StringProperty() when = model.FloatProperty()
class All(model.Model): s = model.StringProperty() i = model.IntegerProperty() f = model.FloatProperty() t = model.TextProperty() b = model.BlobProperty() k = model.KeyProperty()
class Collection(model.Model): # key_name=urlname, parent=Publisher """Model for a collection of records.""" name = model.StringProperty('n', required=True) urlname = model.ComputedProperty(lambda self: urlname(self.name)) owner = model.UserProperty('o', required=True) admins = model.UserProperty('a', repeated=True) created = model.DateTimeProperty('c', auto_now_add=True) updated = model.DateTimeProperty('u', auto_now=True) json = model.TextProperty('j', required=True) # JSON representation @classmethod def create(cls, name, publisher_key): return Collection( parent=publisher_key, id=urlname(name), name=name, owner=users.get_current_user(), json=simplejson.dumps(dict( name=name, admin=users.get_current_user().nickname(), url='http://%s.%s.appspot.com/publishers/%s/%s' % \ (appver, appid, publisher_key.id(), urlname(name))))) @classmethod def get_by_urlname(cls, urlname, publisher_key): return model.Key('Collection', urlname, parent=publisher_key).get() @classmethod def all_by_publisher(cls, publisher_key): return Collection.query(ancestor=publisher_key).fetch()
class Publisher(model.Model): # key_name=urlname """Model for a VertNet data Publisher.""" name = model.StringProperty('n', required=True) urlname = model.ComputedProperty(lambda self: urlname(self.name)) owner = model.UserProperty('o', required=True) admins = model.UserProperty('a', repeated=True) created = model.DateTimeProperty('c', auto_now_add=True) updated = model.DateTimeProperty('u', auto_now=True) json = model.TextProperty('j', required=True) # JSON representation @classmethod def create(cls, name): return Publisher( id=urlname(name), name=name, owner=users.get_current_user(), json=simplejson.dumps(dict( url='http://%s.%s.appspot.com/publishers/%s' % \ (appver, appid, urlname(name)), name=name, admin=users.get_current_user().nickname()))) @classmethod def get_by_urlname(cls, urlname): return model.Key('Publisher', urlname).get()
class MyModel(model.Model): b = model.BooleanProperty() p = model.IntegerProperty() q = model.StringProperty() d = model.FloatProperty() k = model.KeyProperty() u = model.UserProperty() xy = model.GeoPtProperty()
class MyModel(model.Model): bb = model.BooleanProperty('b') pp = model.IntegerProperty('p') qq = model.StringProperty('q') dd = model.FloatProperty('d') kk = model.KeyProperty('k') uu = model.UserProperty('u') xxyy = model.GeoPtProperty('xy')
class Employee(model.Model): name = model.StringProperty() age = model.IntegerProperty('Age') rank = model.IntegerProperty() @classmethod def seniors(cls, min_age, min_rank): q = cls.query().filter(cls.age >= min_age, cls.rank <= min_rank) q = q.order(cls.name, -cls.age) return q
class TestArticle(model.Model): title = model.StringProperty() description = model.StringProperty() created = model.DateTimeProperty(auto_now=True) @classmethod def add_property(cls, name, property, **kwargs): """ Method for dynamical adding model properties """ setattr(cls, name, property(name, **kwargs)) cls._fix_up_properties() @classmethod def del_property(cls, name): """ Method for dynamical adding model properties """ delattr(cls, name) cls._fix_up_properties()
class ComputedTest(model.Model): name = model.StringProperty() name_lower = model.ComputedProperty(lambda self: self.name.lower()) @model.ComputedProperty def size(self): return len(self.name) def _compute_hash(self): return hash(self.name) hash = model.ComputedProperty(_compute_hash, name='hashcode')
class MigrationEntry(model.Model): """ Represents Migration in storage. """ id = model.StringProperty() application = model.StringProperty() ctime = model.DateTimeProperty(auto_now_add=True) status = model.StringProperty(required=True, choices=["apply in process", "rollback in process", "apply failed", "rollback failed", "apply success", "rollback success", ]) @classmethod def _pre_delete_hook(cls, key): memcache.delete(key.kind()) def _post_put_hook(self, future): super(MigrationEntry, self)._post_put_hook(future) memcache.delete(self.key.kind())
class RecordIndex(model.Expando): # parent=Record """Index relation for Record.""" corpus = model.StringProperty('c', repeated=True) # full text @classmethod def create(cls, rec, collection_key): key = model.Key('RecordIndex', rec['occurrenceid'], parent=model.Key('Record', rec['occurrenceid'], parent=collection_key)) index = RecordIndex(key=key, corpus=cls.getcorpus(rec)) for concept, value in rec.iteritems(): index.__setattr__(concept, value.lower()) return index @classmethod def search(cls, args={}, keywords=[]): qry = RecordIndex.query() if len(args) > 0: gql = 'SELECT * FROM RecordIndex WHERE' for k, v in args.iteritems(): gql = "%s %s='%s' AND " % (gql, k, v) gql = gql[:-5] # Removes trailing AND qry = query.parse_gql(gql)[0] for keyword in keywords: qry = qry.filter(RecordIndex.corpus == keyword) logging.info('QUERY=' + str(qry)) return model.get_multi([x.parent() for x in qry.fetch(keys_only=True)]) @classmethod def getcorpus(cls, rec): # verbatim values lower case corpus = set([x.strip().lower() for x in rec.values()]) corpus.update( reduce( lambda x, y: x + y, map(lambda x: [s.strip().lower() for s in x.split() if s], rec.values()))) # adds tokenized values return list(corpus)
class Message(model.Model, DateMixin): sender_key = model.KeyProperty() subject = model.StringProperty() body = model.LocalStructuredProperty(_FormattableContent) recipients = model.StructuredProperty(_DisplayState, repeated=True) @property def sent_at(self): return self.created @property def sender(self): """ :return: A User object from the stored sender_key """ return self.sender_key.get() @classmethod def create(cls, sender_key, body, recipient_keys, **kwargs): """Creates a new message and returns it. :param sender_key: Key of the message sender. :param body: The raw message body, usually coming from a text field. :return: The newly created message. """ kwargs['sender_key'] = sender_key if not kwargs['subject']: kwargs['subject'] = '%s...' % body[0:25] escaped_body = cgi.escape(body) html_body = escaped_body kwargs['body'] = _FormattableContent(raw=body, html=html_body) message = cls(**kwargs) message.recipients = [_DisplayState(user_key=r, state=0) for r in recipient_keys] message.put() return message
class Account(model.Model): """User account.""" email = model.StringProperty() userid = model.StringProperty() nickname = model.StringProperty()
class User(model.Expando): """Stores user authentication credentials or authorization ids.""" #: The model used to ensure uniqueness. unique_model = Unique #: The model used to store tokens. token_model = UserToken created = model.DateTimeProperty(auto_now_add=True) updated = model.DateTimeProperty(auto_now=True) # ID for third party authentication, e.g. 'google:username'. UNIQUE. auth_ids = model.StringProperty(repeated=True) # Hashed password. Not required because third party authentication # doesn't use password. password = model.StringProperty() def get_id(self): """Returns this user's unique ID, which can be an integer or string.""" return self._key.id() @classmethod def get_by_auth_id(cls, auth_id): """Returns a user object based on a auth_id. :param auth_id: String representing a unique id for the user. Examples: - own:username - google:username :returns: A user object. """ return cls.query(cls.auth_ids == auth_id).get() @classmethod def get_by_auth_token(cls, user_id, token): """Returns a user object based on a user ID and token. :param user_id: The user_id of the requesting user. :param token: The token string to be verified. :returns: A tuple ``(User, timestamp)``, with a user object and the token timestamp, or ``(None, None)`` if both were not found. """ token_key = cls.token_model.get_key(user_id, 'auth', token) user_key = model.Key(cls, user_id) # Use get_multi() to save a RPC call. valid_token, user = model.get_multi([token_key, user_key]) if valid_token and user: timestamp = int(time.mktime(valid_token.created.timetuple())) return user, timestamp return None, None @classmethod def get_by_auth_password(cls, auth_id, password): """Returns a user object, validating password. :param auth_id: Authentication id. :param password: Password to be checked. :returns: A user object, if found and password matches. :raises: ``auth.InvalidAuthIdError`` or ``auth.InvalidPasswordError``. """ user = cls.get_by_auth_id(auth_id) if not user: raise auth.InvalidAuthIdError() if not security.check_password_hash(password, user.password): raise auth.InvalidPasswordError() return user @classmethod def validate_token(cls, user_id, subject, token): """Checks for existence of a token, given user_id, subject and token. :param user_id: User unique ID. :param subject: The subject of the key. Examples: - 'auth' - 'signup' :param token: The token string to be validated. :returns: A :class:`UserToken` or None if the token does not exist. """ return cls.token_model.get(user=user_id, subject=subject, token=token) is not None @classmethod def create_auth_token(cls, user_id): """Creates a new authorization token for a given user ID. :param user_id: User unique ID. :returns: A string with the authorization token. """ return cls.token_model.create(user_id, 'auth').token @classmethod def validate_auth_token(cls, user_id, token): return cls.validate_token(user_id, 'auth', token) @classmethod def delete_auth_token(cls, user_id, token): """Deletes a given authorization token. :param user_id: User unique ID. :param token: A string with the authorization token. """ cls.token_model.get_key(user_id, 'auth', token).delete() @classmethod def create_signup_token(cls, user_id): entity = cls.token_model.create(user_id, 'signup') return entity.token @classmethod def validate_signup_token(cls, user_id, token): return cls.validate_token(user_id, 'signup', token) @classmethod def delete_signup_token(cls, user_id, token): cls.token_model.get_key(user_id, 'signup', token).delete() @classmethod def create_user(cls, auth_id, unique_properties=None, **user_values): """Creates a new user. :param auth_id: A string that is unique to the user. Users may have multiple auth ids. Example auth ids: - own:username - own:[email protected] - google:username - yahoo:username The value of `auth_id` must be unique. :param unique_properties: Sequence of extra property names that must be unique. :param user_values: Keyword arguments to create a new user entity. Since the model is an ``Expando``, any provided custom properties will be saved. To hash a plain password, pass a keyword ``password_raw``. :returns: A tuple (boolean, info). The boolean indicates if the user was created. If creation succeeds, ``info`` is the user entity; otherwise it is a list of duplicated unique properties that caused creation to fail. """ assert user_values.get('password') is None, \ 'Use password_raw instead of password to create new users.' assert not isinstance(auth_id, list), \ 'Creating a user with multiple auth_ids is not allowed, ' \ 'please provide a single auth_id.' if 'password_raw' in user_values: user_values['password'] = security.generate_password_hash( user_values.pop('password_raw'), length=12) user_values['auth_ids'] = [auth_id] user = cls(**user_values) # Set up unique properties. uniques = [('%s.auth_id:%s' % (cls.__name__, auth_id), 'auth_id')] if unique_properties: for name in unique_properties: key = '%s.%s:%s' % (cls.__name__, name, user_values[name]) uniques.append((key, name)) ok, existing = cls.unique_model.create_multi(k for k, v in uniques) if ok: user.put() return True, user else: properties = [v for k, v in uniques if k in existing] return False, properties
class UserToken(model.Model): """Stores validation tokens for users.""" created = model.DateTimeProperty(auto_now_add=True) updated = model.DateTimeProperty(auto_now=True) user = model.StringProperty(required=True, indexed=False) subject = model.StringProperty(required=True) token = model.StringProperty(required=True) @classmethod def get_key(cls, user, subject, token): """Returns a token key. :param user: User unique ID. :param subject: The subject of the key. Examples: - 'auth' - 'signup' :param token: Randomly generated token. :returns: ``model.Key`` containing a string id in the following format: ``{user_id}.{subject}.{token}.`` """ return model.Key(cls, '%s.%s.%s' % (str(user), subject, token)) @classmethod def create(cls, user, subject, token=None): """Creates a new token for the given user. :param user: User unique ID. :param subject: The subject of the key. Examples: - 'auth' - 'signup' :param token: Optionally an existing token may be provided. If None, a random token will be generated. :returns: The newly created :class:`UserToken`. """ user = str(user) token = token or security.generate_random_string(entropy=128) key = cls.get_key(user, subject, token) entity = cls(key=key, user=user, subject=subject, token=token) entity.put() return entity @classmethod def get(cls, user=None, subject=None, token=None): """Fetches a user token. :param user: User unique ID. :param subject: The subject of the key. Examples: - 'auth' - 'signup' :param token: The existing token needing verified. :returns: A :class:`UserToken` or None if the token does not exist. """ if user and subject and token: return cls.get_key(user, subject, token).get() assert subject and token, \ 'subject and token must be provided to UserToken.get().' return cls.query(cls.subject == subject, cls.token == token).get()
class CrashTestDummyModel(model.Model): name = model.StringProperty()
class User(model.Model): username = model.StringProperty(required=True) auth_id = model.StringProperty() email = model.StringProperty()
class Person(model.Model): na = model.StringProperty('name') ad = model.StructuredProperty(AddressPair, 'address')
class Employee(model.Model): name = model.StringProperty() rank = model.IntegerProperty()
class Bar(model.Model): name = model.StringProperty() foo = model.StructuredProperty(Foo)
class Address(model.Model): street = model.StringProperty() city = model.StringProperty()
class Node(model.Model): name = model.StringProperty(indexed=False)
class Person(model.Model): name = model.StringProperty() address = model.StringProperty(repeated=True)
class Message(model.Model): """Guestbook message.""" body = model.StringProperty() when = model.FloatProperty() userid = model.StringProperty()
class Foo(model.Model): name = model.StringProperty() rate = model.IntegerProperty() tags = model.StringProperty(repeated=True)
class Address(model.Model): label = model.StringProperty() line = model.StringProperty(repeated=True)
class Address(model.Model): st = model.StringProperty('street') ci = model.StringProperty('city')
class Mod(model.Model): data = model.StringProperty()
class Person(model.Model): name = model.StringProperty() address = model.StructuredProperty(Address)