aboutsummaryrefslogtreecommitdiffstats
path: root/mediagoblin/db
diff options
context:
space:
mode:
Diffstat (limited to 'mediagoblin/db')
-rw-r--r--mediagoblin/db/migrations.py29
-rw-r--r--mediagoblin/db/mixin.py60
-rw-r--r--mediagoblin/db/models.py4
3 files changed, 70 insertions, 23 deletions
diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py
index 36ad736a..2df06fc0 100644
--- a/mediagoblin/db/migrations.py
+++ b/mediagoblin/db/migrations.py
@@ -1693,6 +1693,15 @@ def federation_collection_schema(db):
# Add the fields onto the Collection model, we need to set these as
# not null to avoid DB integreity errors. We will add the not null
# constraint later.
+ public_id_column = Column(
+ "public_id",
+ Unicode,
+ unique=True
+ )
+ public_id_column.create(
+ collection_table,
+ unique_name="collection_public_id")
+
updated_column = Column(
"updated",
DateTime,
@@ -1846,3 +1855,23 @@ def federation_graveyard(db):
# Commit changes to the db
db.commit()
+
+@RegisterMigration(40, MIGRATIONS)
+def add_public_id(db):
+ metadata = MetaData(bind=db.bind)
+
+ # Get the table
+ activity_table = inspect_table(metadata, "core__activities")
+ activity_public_id = Column(
+ "public_id",
+ Unicode,
+ unique=True,
+ nullable=True
+ )
+ activity_public_id.create(
+ activity_table,
+ unique_name="activity_public_id"
+ )
+
+ # Commit this.
+ db.commit()
diff --git a/mediagoblin/db/mixin.py b/mediagoblin/db/mixin.py
index 7960061e..e6a2dc35 100644
--- a/mediagoblin/db/mixin.py
+++ b/mediagoblin/db/mixin.py
@@ -41,6 +41,40 @@ from mediagoblin.tools.text import cleaned_markdown_conversion
from mediagoblin.tools.url import slugify
from mediagoblin.tools.translate import pass_to_ugettext as _
+class GeneratePublicIDMixin(object):
+ """
+ Mixin that ensures that a the public_id field is populated.
+
+ The public_id is the ID that is used in the API, this must be globally
+ unique and dereferencable. This will be the URL for the API view of the
+ object. It's used in several places, not only is it used to give out via
+ the API but it's also vital information stored when a soft_deletion occurs
+ on the `Graveyard.public_id` field, this is needed to follow the spec which
+ says we have to be able to provide a shell of an object and return a 410
+ (rather than a 404) when a deleted object has been deleted.
+
+ This requires a the urlgen off the request object (`request.urlgen`) to be
+ provided as it's the ID is a URL.
+ """
+
+ def get_public_id(self, urlgen):
+ # Verify that the class this is on actually has a public_id field...
+ if "public_id" not in self.__table__.columns.keys():
+ raise Exception("Model has no public_id field")
+
+ # Great! the model has a public id, if it's None, let's create one!
+ if self.public_id is None:
+ # We need the internal ID for this so ensure we've been saved.
+ self.save(commit=False)
+
+ # Create the URL
+ self.public_id = urlgen(
+ "mediagoblin.api.object",
+ object_type=self.object_type,
+ id=self.id,
+ qualified=True
+ )
+ return self.public_id
class UserMixin(object):
object_type = "person"
@@ -52,6 +86,7 @@ class UserMixin(object):
def url_for_self(self, urlgen, **kwargs):
"""Generate a URL for this User's home page."""
return urlgen('mediagoblin.user_pages.user_home',
+
user=self.username, **kwargs)
@@ -128,7 +163,7 @@ class GenerateSlugMixin(object):
self.slug = slug
-class MediaEntryMixin(GenerateSlugMixin):
+class MediaEntryMixin(GenerateSlugMixin, GeneratePublicIDMixin):
def check_slug_used(self, slug):
# import this here due to a cyclic import issue
# (db.models -> db.mixin -> db.util -> db.models)
@@ -196,25 +231,6 @@ class MediaEntryMixin(GenerateSlugMixin):
media=self.slug_or_id,
**extra_args)
- def get_public_id(self, request):
- """ Returns the public_id of the MediaEntry
-
- If the MediaEntry has no public ID one will be produced from the
- current request.
- """
- if self.public_id is None:
- self.public_id = request.urlgen(
- "mediagoblin.api.object",
- object_type=self.object_type,
- id=self.id,
- qualified=True
- )
- # We need to ensure this ID is reused once we've given it out.
- self.save()
-
- return self.public_id
-
-
@property
def thumb_url(self):
"""Return the thumbnail URL (for usage in templates)
@@ -352,7 +368,7 @@ class MediaCommentMixin(object):
comment=self.content)
-class CollectionMixin(GenerateSlugMixin):
+class CollectionMixin(GenerateSlugMixin, GeneratePublicIDMixin):
object_type = "collection"
def check_slug_used(self, slug):
@@ -398,7 +414,7 @@ class CollectionItemMixin(object):
"""
return cleaned_markdown_conversion(self.note)
-class ActivityMixin(object):
+class ActivityMixin(GeneratePublicIDMixin):
object_type = "activity"
VALID_VERBS = ["add", "author", "create", "delete", "dislike", "favorite",
diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py
index 73f3c8ce..e52cab82 100644
--- a/mediagoblin/db/models.py
+++ b/mediagoblin/db/models.py
@@ -728,7 +728,7 @@ class MediaEntry(Base, MediaEntryMixin):
author = self.get_actor
published = UTC.localize(self.created)
updated = UTC.localize(self.updated)
- public_id = self.get_public_id(request)
+ public_id = self.get_public_id(request.urlgen)
context = {
"id": public_id,
"author": author.serialize(request),
@@ -1034,6 +1034,7 @@ class Collection(Base, CollectionMixin):
__tablename__ = "core__collections"
id = Column(Integer, primary_key=True)
+ public_id = Column(Unicode, unique=True)
title = Column(Unicode, nullable=False)
slug = Column(Unicode)
created = Column(DateTime, nullable=False, default=datetime.datetime.utcnow,
@@ -1492,6 +1493,7 @@ class Activity(Base, ActivityMixin):
__tablename__ = "core__activities"
id = Column(Integer, primary_key=True)
+ public_id = Column(Unicode, unique=True)
actor = Column(Integer,
ForeignKey("core__users.id"),
nullable=False)