diff options
Diffstat (limited to 'mediagoblin/db/migrations.py')
-rw-r--r-- | mediagoblin/db/migrations.py | 256 |
1 files changed, 251 insertions, 5 deletions
diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py index 62fb7e8d..426080a2 100644 --- a/mediagoblin/db/migrations.py +++ b/mediagoblin/db/migrations.py @@ -19,16 +19,18 @@ import uuid from sqlalchemy import (MetaData, Table, Column, Boolean, SmallInteger, Integer, Unicode, UnicodeText, DateTime, - ForeignKey) + ForeignKey, Date) from sqlalchemy.exc import ProgrammingError from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.sql import and_ from migrate.changeset.constraint import UniqueConstraint -from mediagoblin.db.extratypes import JSONEncoded -from mediagoblin.db.migration_tools import RegisterMigration, inspect_table -from mediagoblin.db.models import MediaEntry, Collection, User, MediaComment +from mediagoblin.db.extratypes import JSONEncoded, MutationDict +from mediagoblin.db.migration_tools import ( + RegisterMigration, inspect_table, replace_table_hack) +from mediagoblin.db.models import (MediaEntry, Collection, MediaComment, User, + Privilege) MIGRATIONS = {} @@ -469,8 +471,252 @@ def wants_notifications(db): """Add a wants_notifications field to User model""" metadata = MetaData(bind=db.bind) user_table = inspect_table(metadata, "core__users") - col = Column('wants_notifications', Boolean, default=True) 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) + reporter_id = Column(Integer, ForeignKey(User.id), nullable=False) + report_content = Column(UnicodeText) + reported_user_id = Column(Integer, ForeignKey(User.id), nullable=False) + created = Column(DateTime, nullable=False, default=datetime.datetime.now) + discriminator = Column('type', Unicode(50)) + resolver_id = Column(Integer, ForeignKey(User.id)) + resolved = Column(DateTime) + result = Column(UnicodeText) + __mapper_args__ = {'polymorphic_on': discriminator} + + +class CommentReport_v0(ReportBase_v0): + __tablename__ = 'core__reports_on_comments' + __mapper_args__ = {'polymorphic_identity': 'comment_report'} + + id = Column('id',Integer, ForeignKey('core__reports.id'), + primary_key=True) + 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'} + + 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, + primary_key=True) + 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( + 'core__privilege_id', + Integer, + ForeignKey(User.id), + primary_key=True) + user_id = Column( + 'core__user_id', + Integer, + 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'}] + + +# 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' + id = Column(Integer, primary_key=True) + username = Column(Unicode, nullable=False, unique=True) + email = Column(Unicode, nullable=False) + pw_hash = Column(Unicode) + created = Column(DateTime, nullable=False, default=datetime.datetime.now) + wants_comment_notification = Column(Boolean, default=True) + wants_notifications = Column(Boolean, default=True) + license_preference = Column(Unicode) + url = Column(Unicode) + bio = Column(UnicodeText) # ?? + uploaded = Column(Integer, default=0) + upload_limit = Column(Integer) + + +@RegisterMigration(18, MIGRATIONS) +def create_moderation_tables(db): + + # First, we will create the new tables in the database. + #-------------------------------------------------------------------------- + ReportBase_v0.__table__.create(db.bind) + CommentReport_v0.__table__.create(db.bind) + MediaReport_v0.__table__.create(db.bind) + UserBan_v0.__table__.create(db.bind) + Privilege_v0.__table__.create(db.bind) + PrivilegeUserAssociation_v0.__table__.create(db.bind) + + db.commit() + + # Then initialize the tables that we will later use + #-------------------------------------------------------------------------- + metadata = MetaData(bind=db.bind) + privileges_table= inspect_table(metadata, "core__privileges") + user_table = inspect_table(metadata, 'core__users') + user_privilege_assoc = inspect_table( + metadata, 'core__privileges_users') + + # This section initializes the default Privilege foundations, that + # would be created through the FOUNDATIONS system in a new instance + #-------------------------------------------------------------------------- + for parameters in PRIVILEGE_FOUNDATIONS_v0: + db.execute(privileges_table.insert().values(**parameters)) + + db.commit() + + # This next section takes the information from the old is_admin and status + # columns and converts those to the new privilege system + #-------------------------------------------------------------------------- + admin_users_ids, active_users_ids, inactive_users_ids = ( + db.execute( + user_table.select().where( + user_table.c.is_admin==True)).fetchall(), + db.execute( + user_table.select().where( + user_table.c.is_admin==False).where( + user_table.c.status==u"active")).fetchall(), + db.execute( + user_table.select().where( + user_table.c.is_admin==False).where( + user_table.c.status!=u"active")).fetchall()) + + # Get the ids for each of the privileges so we can reference them ~~~~~~~~~ + (admin_privilege_id, uploader_privilege_id, + reporter_privilege_id, commenter_privilege_id, + active_privilege_id) = [ + db.execute(privileges_table.select().where( + privileges_table.c.privilege_name==privilege_name)).first()['id'] + for privilege_name in + [u"admin",u"uploader",u"reporter",u"commenter",u"active"] + ] + + # Give each user the appopriate privileges depending whether they are an + # admin, an active user or an inactive user ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + for admin_user in admin_users_ids: + admin_user_id = admin_user['id'] + for privilege_id in [admin_privilege_id, uploader_privilege_id, + reporter_privilege_id, commenter_privilege_id, + active_privilege_id]: + db.execute(user_privilege_assoc.insert().values( + core__privilege_id=admin_user_id, + core__user_id=privilege_id)) + + for active_user in active_users_ids: + active_user_id = active_user['id'] + for privilege_id in [uploader_privilege_id, reporter_privilege_id, + commenter_privilege_id, active_privilege_id]: + db.execute(user_privilege_assoc.insert().values( + core__privilege_id=active_user_id, + core__user_id=privilege_id)) + + for inactive_user in inactive_users_ids: + inactive_user_id = inactive_user['id'] + for privilege_id in [uploader_privilege_id, reporter_privilege_id, + commenter_privilege_id]: + db.execute(user_privilege_assoc.insert().values( + core__privilege_id=inactive_user_id, + core__user_id=privilege_id)) + + db.commit() + + # And then, once the information is taken from is_admin & status columns + # we drop all of the vestigial columns from the User table. + #-------------------------------------------------------------------------- + if db.bind.url.drivername == 'sqlite': + # SQLite has some issues that make it *impossible* to drop boolean + # columns. So, the following code is a very hacky workaround which + # makes it possible. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + User_vR1.__table__.create(db.bind) + db.commit() + new_user_table = inspect_table(metadata, 'rename__users') + replace_table_hack(db, user_table, new_user_table) + else: + # If the db is not run using SQLite, this process is much simpler ~~~~~ + + status = user_table.columns['status'] + email_verified = user_table.columns['email_verified'] + is_admin = user_table.columns['is_admin'] + status.drop() + email_verified.drop() + is_admin.drop() + + db.commit() +@RegisterMigration(19, MIGRATIONS) +def drop_MediaEntry_collected(db): + """ + Drop unused MediaEntry.collected column + """ + metadata = MetaData(bind=db.bind) + + media_collected= inspect_table(metadata, 'core__media_entries') + media_collected = media_collected.columns['collected'] + + media_collected.drop() db.commit() |