aboutsummaryrefslogtreecommitdiffstats
path: root/mediagoblin/db
diff options
context:
space:
mode:
Diffstat (limited to 'mediagoblin/db')
-rw-r--r--mediagoblin/db/base.py12
-rw-r--r--mediagoblin/db/migration_tools.py22
-rw-r--r--mediagoblin/db/migrations.py81
-rw-r--r--mediagoblin/db/mixin.py17
-rw-r--r--mediagoblin/db/models.py89
-rw-r--r--mediagoblin/db/open.py4
-rw-r--r--mediagoblin/db/util.py2
7 files changed, 192 insertions, 35 deletions
diff --git a/mediagoblin/db/base.py b/mediagoblin/db/base.py
index 699a503a..c0cefdc2 100644
--- a/mediagoblin/db/base.py
+++ b/mediagoblin/db/base.py
@@ -24,18 +24,6 @@ Session = scoped_session(sessionmaker())
class GMGTableBase(object):
query = Session.query_property()
- @classmethod
- def find(cls, query_dict):
- return cls.query.filter_by(**query_dict)
-
- @classmethod
- def find_one(cls, query_dict):
- return cls.query.filter_by(**query_dict).first()
-
- @classmethod
- def one(cls, query_dict):
- return cls.find(query_dict).one()
-
def get(self, key):
return getattr(self, key)
diff --git a/mediagoblin/db/migration_tools.py b/mediagoblin/db/migration_tools.py
index c0c7e998..e75f3757 100644
--- a/mediagoblin/db/migration_tools.py
+++ b/mediagoblin/db/migration_tools.py
@@ -29,7 +29,7 @@ class MigrationManager(object):
to the latest migrations, etc.
"""
- def __init__(self, name, models, migration_registry, session,
+ def __init__(self, name, models, foundations, migration_registry, session,
printer=simple_printer):
"""
Args:
@@ -40,6 +40,7 @@ class MigrationManager(object):
"""
self.name = unicode(name)
self.models = models
+ self.foundations = foundations
self.session = session
self.migration_registry = migration_registry
self._sorted_migrations = None
@@ -140,6 +141,18 @@ class MigrationManager(object):
self.session.bind,
tables=[model.__table__ for model in self.models])
+ def populate_table_foundations(self):
+ """
+ Create the table foundations (default rows) as layed out in FOUNDATIONS
+ in mediagoblin.db.models
+ """
+ for Model, rows in self.foundations.items():
+ self.printer(u' + Laying foundations for %s table\n' %
+ (Model.__name__))
+ for parameters in rows:
+ new_row = Model(**parameters)
+ self.session.add(new_row)
+
def create_new_migration_record(self):
"""
Create a new migration record for this migration set
@@ -175,8 +188,7 @@ class MigrationManager(object):
if self.name == u'__main__':
return u"main mediagoblin tables"
else:
- # TODO: Use the friendlier media manager "human readable" name
- return u'media type "%s"' % self.name
+ return u'plugin "%s"' % self.name
def init_or_migrate(self):
"""
@@ -203,9 +215,9 @@ class MigrationManager(object):
self.init_tables()
# auto-set at latest migration number
- self.create_new_migration_record()
-
+ self.create_new_migration_record()
self.printer(u"done.\n")
+ self.populate_table_foundations()
self.set_current_migration()
return u'inited'
diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py
index fe4ffb3e..374ab4c8 100644
--- a/mediagoblin/db/migrations.py
+++ b/mediagoblin/db/migrations.py
@@ -25,6 +25,8 @@ 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
@@ -379,3 +381,82 @@ def pw_hash_nullable(db):
constraint.create()
db.commit()
+
+
+# oauth1 migrations
+class Client_v0(declarative_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_v0(declarative_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_v0.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_v0(declarative_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_v0.token))
+ created = Column(DateTime, nullable=False, default=datetime.datetime.now)
+ updated = Column(DateTime, nullable=False, default=datetime.datetime.now)
+
+
+class NonceTimestamp_v0(declarative_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)
+
+
+@RegisterMigration(14, MIGRATIONS)
+def create_oauth1_tables(db):
+ """ Creates the OAuth1 tables """
+
+ Client_v0.__table__.create(db.bind)
+ RequestToken_v0.__table__.create(db.bind)
+ AccessToken_v0.__table__.create(db.bind)
+ NonceTimestamp_v0.__table__.create(db.bind)
+
+ db.commit()
diff --git a/mediagoblin/db/mixin.py b/mediagoblin/db/mixin.py
index 1b32d838..57b27d83 100644
--- a/mediagoblin/db/mixin.py
+++ b/mediagoblin/db/mixin.py
@@ -29,15 +29,14 @@ real objects.
import uuid
import re
-import datetime
-
from datetime import datetime
from werkzeug.utils import cached_property
from mediagoblin import mg_globals
-from mediagoblin.media_types import get_media_managers, FileTypeNotSupported
+from mediagoblin.media_types import FileTypeNotSupported
from mediagoblin.tools import common, licenses
+from mediagoblin.tools.pluginapi import hook_handle
from mediagoblin.tools.text import cleaned_markdown_conversion
from mediagoblin.tools.url import slugify
@@ -204,14 +203,14 @@ class MediaEntryMixin(GenerateSlugMixin):
Raises FileTypeNotSupported in case no such manager is enabled
"""
- # TODO, we should be able to make this a simple lookup rather
- # than iterating through all media managers.
- for media_type, manager in get_media_managers():
- if media_type == self.media_type:
- return manager(self)
+ manager = hook_handle(('media_manager', self.media_type))
+ if manager:
+ return manager(self)
+
# Not found? Then raise an error
raise FileTypeNotSupported(
- "MediaManager not in enabled types. Check media_types in config?")
+ "MediaManager not in enabled types. Check media_type plugins are"
+ " enabled in config?")
def get_fail_exception(self):
"""
diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py
index 826d47ba..f0cbce2a 100644
--- a/mediagoblin/db/models.py
+++ b/mediagoblin/db/models.py
@@ -105,6 +105,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
@@ -580,11 +646,26 @@ 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
+ 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
+ of the columns' names as a key string, and each of the columns' values as a
+ value)
+
+ ex. [NOTE THIS IS NOT BASED OFF OF OUR USER TABLE]
+ user_foundations = [{'name':u'Joanna', 'age':24},
+ {'name':u'Andrea', 'age':41}]
+
+ FOUNDATIONS = {User:user_foundations}
+"""
+FOUNDATIONS = {}
######################################################
# Special, migrations-tracking table
diff --git a/mediagoblin/db/open.py b/mediagoblin/db/open.py
index 0b1679fb..4ff0945f 100644
--- a/mediagoblin/db/open.py
+++ b/mediagoblin/db/open.py
@@ -52,10 +52,6 @@ class DatabaseMaster(object):
def load_models(app_config):
import mediagoblin.db.models
- for media_type in app_config['media_types']:
- _log.debug("Loading %s.models", media_type)
- __import__(media_type + ".models")
-
for plugin in mg_globals.global_config.get('plugins', {}).keys():
_log.debug("Loading %s.models", plugin)
try:
diff --git a/mediagoblin/db/util.py b/mediagoblin/db/util.py
index 6ffec44d..8431361a 100644
--- a/mediagoblin/db/util.py
+++ b/mediagoblin/db/util.py
@@ -24,7 +24,7 @@ from mediagoblin.db.models import MediaEntry, Tag, MediaTag, Collection
def atomic_update(table, query_dict, update_values):
- table.find(query_dict).update(update_values,
+ table.query.filter_by(**query_dict).update(update_values,
synchronize_session=False)
Session.commit()