Merge remote-tracking branch 'refs/remotes/rodney757/reprocessing'
[mediagoblin.git] / mediagoblin / db / models.py
index 7448f5ce166c5e7b21b2141c79a98392e50b233e..809e47220dd6b6901b2361b8d563ca045ec7caac 100644 (file)
@@ -69,10 +69,13 @@ class User(Base, UserMixin):
     # Intented to be nullable=False, but migrations would not work for it
     # set to nullable=True implicitly.
     wants_comment_notification = Column(Boolean, default=True)
+    wants_notifications = Column(Boolean, default=True)
     license_preference = Column(Unicode)
     is_admin = Column(Boolean, default=False, nullable=False)
     url = Column(Unicode)
     bio = Column(UnicodeText)  # ??
+    uploaded = Column(Integer, default=0)
+    upload_limit = Column(Integer)
 
     ## TODO
     # plugin data would be in a separate model
@@ -105,6 +108,72 @@ class User(Base, UserMixin):
         _log.info('Deleted user "{0}" account'.format(self.username))
 
 
+class Client(Base):
+    """
+        Model representing a client - Used for API Auth
+    """
+    __tablename__ = "core__clients"
+
+    id = Column(Unicode, nullable=True, primary_key=True)
+    secret = Column(Unicode, nullable=False)
+    expirey = Column(DateTime, nullable=True)
+    application_type = Column(Unicode, nullable=False)
+    created = Column(DateTime, nullable=False, default=datetime.datetime.now)
+    updated = Column(DateTime, nullable=False, default=datetime.datetime.now)
+
+    # optional stuff
+    redirect_uri = Column(JSONEncoded, nullable=True)
+    logo_url = Column(Unicode, nullable=True)
+    application_name = Column(Unicode, nullable=True)
+    contacts = Column(JSONEncoded, nullable=True)
+
+    def __repr__(self):
+        if self.application_name:
+            return "<Client {0} - {1}>".format(self.application_name, self.id)
+        else:
+            return "<Client {0}>".format(self.id)
+
+class RequestToken(Base):
+    """
+        Model for representing the request tokens
+    """
+    __tablename__ = "core__request_tokens"
+
+    token = Column(Unicode, primary_key=True)
+    secret = Column(Unicode, nullable=False)
+    client = Column(Unicode, ForeignKey(Client.id))
+    user = Column(Integer, ForeignKey(User.id), nullable=True)
+    used = Column(Boolean, default=False)
+    authenticated = Column(Boolean, default=False)
+    verifier = Column(Unicode, nullable=True)
+    callback = Column(Unicode, nullable=False, default=u"oob")
+    created = Column(DateTime, nullable=False, default=datetime.datetime.now)
+    updated = Column(DateTime, nullable=False, default=datetime.datetime.now)
+
+class AccessToken(Base):
+    """
+        Model for representing the access tokens
+    """
+    __tablename__ = "core__access_tokens"
+
+    token = Column(Unicode, nullable=False, primary_key=True)
+    secret = Column(Unicode, nullable=False)
+    user = Column(Integer, ForeignKey(User.id))
+    request_token = Column(Unicode, ForeignKey(RequestToken.token))
+    created = Column(DateTime, nullable=False, default=datetime.datetime.now)
+    updated = Column(DateTime, nullable=False, default=datetime.datetime.now)
+
+
+class NonceTimestamp(Base):
+    """
+        A place the timestamp and nonce can be stored - this is for OAuth1
+    """
+    __tablename__ = "core__nonce_timestamps"
+
+    nonce = Column(Unicode, nullable=False, primary_key=True)
+    timestamp = Column(DateTime, nullable=False, primary_key=True)
+
+
 class MediaEntry(Base, MediaEntryMixin):
     """
     TODO: Consider fetching the media_files using join
@@ -123,6 +192,7 @@ class MediaEntry(Base, MediaEntryMixin):
         # or use sqlalchemy.types.Enum?
     license = Column(Unicode)
     collected = Column(Integer, default=0)
+    file_size = Column(Integer, default=0)
 
     fail_error = Column(Unicode)
     fail_metadata = Column(JSONEncoded)
@@ -197,6 +267,34 @@ class MediaEntry(Base, MediaEntryMixin):
         if media is not None:
             return media.url_for_self(urlgen)
 
+    def get_file_metadata(self, file_key, metadata_key=None):
+        """
+        Return the file_metadata dict of a MediaFile. If metadata_key is given,
+        return the value of the key.
+        """
+        media_file = MediaFile.query.filter_by(media_entry=self.id,
+                                               name=unicode(file_key)).first()
+
+        if media_file:
+            if metadata_key:
+                return media_file.file_metadata.get(metadata_key, None)
+
+            return media_file.file_metadata
+
+    def set_file_metadata(self, file_key, **kwargs):
+        """
+        Update the file_metadata of a MediaFile.
+        """
+        media_file = MediaFile.query.filter_by(media_entry=self.id,
+                                               name=unicode(file_key)).first()
+
+        file_metadata = media_file.file_metadata or {}
+
+        for key, value in kwargs.iteritems():
+            file_metadata[key] = value
+
+        media_file.file_metadata = file_metadata
+
     @property
     def media_data(self):
         return getattr(self, self.media_data_ref)
@@ -293,6 +391,7 @@ class MediaFile(Base):
         nullable=False)
     name_id = Column(SmallInteger, ForeignKey(FileKeynames.id), nullable=False)
     file_path = Column(PathTupleWithSlashes)
+    file_metadata = Column(JSONEncoded)
 
     __table_args__ = (
         PrimaryKeyConstraint('media_entry', 'name_id'),
@@ -580,13 +679,13 @@ with_polymorphic(
     [ProcessingNotification, CommentNotification])
 
 MODELS = [
-    User, MediaEntry, Tag, MediaTag, MediaComment, Collection, CollectionItem,
-    MediaFile, FileKeynames, MediaAttachmentFile, ProcessingMetaData,
-    Notification, CommentNotification, ProcessingNotification,
-    CommentSubscription]
+    User, Client, RequestToken, AccessToken, NonceTimestamp, MediaEntry, Tag,
+    MediaTag, MediaComment, Collection, CollectionItem, MediaFile, FileKeynames,
+    MediaAttachmentFile, ProcessingMetaData, Notification, CommentNotification,
+    ProcessingNotification, CommentSubscription]
 
 """
- Foundations are the default rows that are created immediately after the tables 
+ Foundations are the default rows that are created immediately after the tables
  are initialized. Each entry to  this dictionary should be in the format of:
                  ModelConstructorObject:List of Dictionaries
  (Each Dictionary represents a row on the Table to be created, containing each