aboutsummaryrefslogtreecommitdiffstats
path: root/mediagoblin/db
diff options
context:
space:
mode:
Diffstat (limited to 'mediagoblin/db')
-rw-r--r--mediagoblin/db/extratypes.py30
-rw-r--r--mediagoblin/db/migrations.py60
-rw-r--r--mediagoblin/db/models.py38
3 files changed, 118 insertions, 10 deletions
diff --git a/mediagoblin/db/extratypes.py b/mediagoblin/db/extratypes.py
index f2304af0..8e04d58d 100644
--- a/mediagoblin/db/extratypes.py
+++ b/mediagoblin/db/extratypes.py
@@ -15,6 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+from sqlalchemy.ext.mutable import Mutable
from sqlalchemy.types import TypeDecorator, Unicode, TEXT
import json
@@ -38,7 +39,7 @@ class PathTupleWithSlashes(TypeDecorator):
return value
-# The following class and only this one class is in very
+# The following two classes and only these two classes is in very
# large parts based on example code from sqlalchemy.
#
# The original copyright notice and license follows:
@@ -61,3 +62,30 @@ class JSONEncoded(TypeDecorator):
if value is not None:
value = json.loads(value)
return value
+
+
+class MutationDict(Mutable, dict):
+ @classmethod
+ def coerce(cls, key, value):
+ "Convert plain dictionaries to MutationDict."
+
+ if not isinstance(value, MutationDict):
+ if isinstance(value, dict):
+ return MutationDict(value)
+
+ # this call will raise ValueError
+ return Mutable.coerce(key, value)
+ else:
+ return value
+
+ def __setitem__(self, key, value):
+ "Detect dictionary set events and emit change events."
+
+ dict.__setitem__(self, key, value)
+ self.changed()
+
+ def __delitem__(self, key):
+ "Detect dictionary del events and emit change events."
+
+ dict.__delitem__(self, key)
+ self.changed()
diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py
index 6616b657..0356c672 100644
--- a/mediagoblin/db/migrations.py
+++ b/mediagoblin/db/migrations.py
@@ -26,7 +26,7 @@ from sqlalchemy.sql import and_
from migrate.changeset.constraint import UniqueConstraint
-from mediagoblin.db.extratypes import JSONEncoded
+from mediagoblin.db.extratypes import JSONEncoded, MutationDict
from mediagoblin.db.migration_tools import RegisterMigration, inspect_table
from mediagoblin.db.models import (MediaEntry, Collection, MediaComment, User,
Privilege)
@@ -474,6 +474,43 @@ def wants_notifications(db):
col.create(user_table)
db.commit()
+
+
+@RegisterMigration(16, MIGRATIONS)
+def upload_limits(db):
+ """Add user upload limit columns"""
+ metadata = MetaData(bind=db.bind)
+
+ user_table = inspect_table(metadata, 'core__users')
+ media_entry_table = inspect_table(metadata, 'core__media_entries')
+
+ col = Column('uploaded', Integer, default=0)
+ col.create(user_table)
+
+ col = Column('upload_limit', Integer)
+ col.create(user_table)
+
+ col = Column('file_size', Integer, default=0)
+ col.create(media_entry_table)
+
+ db.commit()
+
+
+@RegisterMigration(17, MIGRATIONS)
+def add_file_metadata(db):
+ """Add file_metadata to MediaFile"""
+ metadata = MetaData(bind=db.bind)
+ media_file_table = inspect_table(metadata, "core__mediafiles")
+
+ col = Column('file_metadata', MutationDict.as_mutable(JSONEncoded))
+ col.create(media_file_table)
+
+ db.commit()
+
+###################
+# Moderation tables
+###################
+
class ReportBase_v0(declarative_base()):
__tablename__ = 'core__reports'
id = Column(Integer, primary_key=True)
@@ -487,6 +524,7 @@ class ReportBase_v0(declarative_base()):
result = Column(UnicodeText)
__mapper_args__ = {'polymorphic_on': discriminator}
+
class CommentReport_v0(ReportBase_v0):
__tablename__ = 'core__reports_on_comments'
__mapper_args__ = {'polymorphic_identity': 'comment_report'}
@@ -496,7 +534,6 @@ class CommentReport_v0(ReportBase_v0):
comment_id = Column(Integer, ForeignKey(MediaComment.id), nullable=True)
-
class MediaReport_v0(ReportBase_v0):
__tablename__ = 'core__reports_on_media'
__mapper_args__ = {'polymorphic_identity': 'media_report'}
@@ -504,6 +541,7 @@ class MediaReport_v0(ReportBase_v0):
id = Column('id',Integer, ForeignKey('core__reports.id'), primary_key=True)
media_entry_id = Column(Integer, ForeignKey(MediaEntry.id), nullable=True)
+
class UserBan_v0(declarative_base()):
__tablename__ = 'core__user_bans'
user_id = Column(Integer, ForeignKey(User.id), nullable=False,
@@ -511,11 +549,13 @@ class UserBan_v0(declarative_base()):
expiration_date = Column(Date)
reason = Column(UnicodeText, nullable=False)
+
class Privilege_v0(declarative_base()):
__tablename__ = 'core__privileges'
id = Column(Integer, nullable=False, primary_key=True, unique=True)
privilege_name = Column(Unicode, nullable=False, unique=True)
+
class PrivilegeUserAssociation_v0(declarative_base()):
__tablename__ = 'core__privileges_users'
privilege_id = Column(
@@ -529,13 +569,18 @@ class PrivilegeUserAssociation_v0(declarative_base()):
ForeignKey(Privilege.id),
primary_key=True)
+
PRIVILEGE_FOUNDATIONS_v0 = [{'privilege_name':u'admin'},
- {'privilege_name':u'moderator'},
- {'privilege_name':u'uploader'},
- {'privilege_name':u'reporter'},
- {'privilege_name':u'commenter'},
- {'privilege_name':u'active'}]
+ {'privilege_name':u'moderator'},
+ {'privilege_name':u'uploader'},
+ {'privilege_name':u'reporter'},
+ {'privilege_name':u'commenter'},
+ {'privilege_name':u'active'}]
+
+# vR1 stands for "version Rename 1". This only exists because we need
+# to deal with dropping some booleans and it's otherwise impossible
+# with sqlite.
class User_vR1(declarative_base()):
__tablename__ = 'rename__users'
@@ -550,6 +595,7 @@ class User_vR1(declarative_base()):
url = Column(Unicode)
bio = Column(UnicodeText) # ??
+
@RegisterMigration(18, MIGRATIONS)
def create_moderation_tables(db):
diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py
index 5173be9e..1514a3aa 100644
--- a/mediagoblin/db/models.py
+++ b/mediagoblin/db/models.py
@@ -30,8 +30,8 @@ from sqlalchemy.sql.expression import desc
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.util import memoized_property
-
-from mediagoblin.db.extratypes import PathTupleWithSlashes, JSONEncoded
+from mediagoblin.db.extratypes import (PathTupleWithSlashes, JSONEncoded,
+ MutationDict)
from mediagoblin.db.base import Base, DictReadAttrProxy
from mediagoblin.db.mixin import UserMixin, MediaEntryMixin, \
MediaCommentMixin, CollectionMixin, CollectionItemMixin
@@ -48,6 +48,7 @@ from migrate import changeset
_log = logging.getLogger(__name__)
+
class User(Base, UserMixin):
"""
TODO: We should consider moving some rarely used fields
@@ -71,6 +72,8 @@ class User(Base, UserMixin):
license_preference = Column(Unicode)
url = Column(Unicode)
bio = Column(UnicodeText) # ??
+ uploaded = Column(Integer, default=0)
+ upload_limit = Column(Integer)
## TODO
# plugin data would be in a separate model
@@ -217,6 +220,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)
@@ -291,6 +295,35 @@ 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
+ media_file.save()
+
@property
def media_data(self):
return getattr(self, self.media_data_ref)
@@ -387,6 +420,7 @@ class MediaFile(Base):
nullable=False)
name_id = Column(SmallInteger, ForeignKey(FileKeynames.id), nullable=False)
file_path = Column(PathTupleWithSlashes)
+ file_metadata = Column(MutationDict.as_mutable(JSONEncoded))
__table_args__ = (
PrimaryKeyConstraint('media_entry', 'name_id'),