Fix migrations and refactor object_type
- Make changes to objectType to be more pythonic "object_type" - Move object_type to mixins rather than be on the models - Convert migrations to sqlalchemy core rather than ORM (fix) - Change TYPES to use descriptive strings rather than numbers
This commit is contained in:
parent
23bf7f3b02
commit
0421fc5ee8
@ -905,15 +905,21 @@ class Activity_R0(declarative_base()):
|
||||
published = Column(DateTime, nullable=False, default=datetime.datetime.now)
|
||||
updated = Column(DateTime, nullable=False, default=datetime.datetime.now)
|
||||
verb = Column(Unicode, nullable=False)
|
||||
content = Column(Unicode, nullable=False)
|
||||
content = Column(Unicode, nullable=True)
|
||||
title = Column(Unicode, nullable=True)
|
||||
target = Column(Integer, ForeignKey(User.id), nullable=True)
|
||||
generator = Column(Integer, ForeignKey(Generator.id), nullable=True)
|
||||
object = Column(Integer,
|
||||
ForeignKey("core__activity_intermediators.id"),
|
||||
nullable=False)
|
||||
target = Column(Integer,
|
||||
ForeignKey("core__activity_intermediators.id"),
|
||||
nullable=True)
|
||||
|
||||
class ActivityIntermediator_R0(declarative_base()):
|
||||
__tablename__ = "core__acitivity_intermediators"
|
||||
__tablename__ = "core__activity_intermediators"
|
||||
id = Column(Integer, primary_key=True)
|
||||
type = Column(Integer, nullable=False)
|
||||
type = Column(Unicode, nullable=False)
|
||||
|
||||
@RegisterMigration(24, MIGRATIONS)
|
||||
def activity_migration(db):
|
||||
@ -925,32 +931,40 @@ def activity_migration(db):
|
||||
- Retroactively adds activities for what we can acurately work out
|
||||
"""
|
||||
# Set constants we'll use later
|
||||
FOREIGN_KEY = "core__acitivity_intermediators.id"
|
||||
FOREIGN_KEY = "core__activity_intermediators.id"
|
||||
|
||||
|
||||
# Create the new tables.
|
||||
Activity_R0.__table__.create(db.bind)
|
||||
Generator_R0.__table__.create(db.bind)
|
||||
ActivityIntermediator_R0.__table__.create(db.bind)
|
||||
Generator_R0.__table__.create(db.bind)
|
||||
Activity_R0.__table__.create(db.bind)
|
||||
db.commit()
|
||||
|
||||
|
||||
# Initiate the tables we want to use later
|
||||
metadata = MetaData(bind=db.bind)
|
||||
user_table = inspect_table(metadata, "core__users")
|
||||
activity_table = inspect_table(metadata, "core__activities")
|
||||
generator_table = inspect_table(metadata, "core__generators")
|
||||
collection_table = inspect_table(metadata, "core__collections")
|
||||
media_entry_table = inspect_table(metadata, "core__media_entries")
|
||||
media_comments_table = inspect_table(metadata, "core__media_comments")
|
||||
ai_table = inspect_table(metadata, "core__activity_intermediators")
|
||||
|
||||
|
||||
# Create the foundations for Generator
|
||||
db.execute(generator_table.insert().values(
|
||||
name="GNU Mediagoblin",
|
||||
object_type="service"
|
||||
object_type="service",
|
||||
published=datetime.datetime.now(),
|
||||
updated=datetime.datetime.now()
|
||||
))
|
||||
db.commit()
|
||||
|
||||
# Get the ID of that generator
|
||||
gmg_generator = db.execute(generator_table.select(
|
||||
generator_table.c.name==u"GNU Mediagoblin")).first()
|
||||
|
||||
|
||||
# Now we want to modify the tables which MAY have an activity at some point
|
||||
as_object = Column("activity_as_object", Integer, ForeignKey(FOREIGN_KEY))
|
||||
@ -977,45 +991,93 @@ def activity_migration(db):
|
||||
|
||||
# Now we want to retroactively add what activities we can
|
||||
# first we'll add activities when people uploaded media.
|
||||
for media in MediaEntry.query.all():
|
||||
activity = Activity_R0(
|
||||
verb="create",
|
||||
actor=media.uploader,
|
||||
published=media.created,
|
||||
updated=media.created,
|
||||
generator=gmg_generator.id
|
||||
)
|
||||
activity.generate_content()
|
||||
activity.save(set_updated=False)
|
||||
activity.set_object(media)
|
||||
media.save()
|
||||
# these can't have content as it's not fesible to get the
|
||||
# correct content strings.
|
||||
for media in db.execute(media_entry_table.select()):
|
||||
# Now we want to create the intermedaitory
|
||||
db_ai = db.execute(ai_table.insert().values(
|
||||
type="media",
|
||||
))
|
||||
db_ai = db.execute(ai_table.select(
|
||||
ai_table.c.id==db_ai.inserted_primary_key[0]
|
||||
)).first()
|
||||
|
||||
# Add the activity
|
||||
activity = {
|
||||
"verb": "create",
|
||||
"actor": media.uploader,
|
||||
"published": media.created,
|
||||
"updated": media.created,
|
||||
"generator": gmg_generator.id,
|
||||
"object": db_ai.id
|
||||
}
|
||||
db.execute(activity_table.insert().values(**activity))
|
||||
|
||||
# Add the AI to the media.
|
||||
db.execute(media_entry_table.update().values(
|
||||
activity_as_object=db_ai.id
|
||||
).where(id=media.id))
|
||||
|
||||
# Now we want to add all the comments people made
|
||||
for comment in MediaComment.query.all():
|
||||
activity = Activity_R0(
|
||||
verb="comment",
|
||||
actor=comment.author,
|
||||
published=comment.created,
|
||||
updated=comment.created,
|
||||
generator=gmg_generator.id
|
||||
)
|
||||
activity.generate_content()
|
||||
activity.save(set_updated=False)
|
||||
activity.set_object(comment)
|
||||
comment.save()
|
||||
for comment in db.execute(media_comments_table.select()):
|
||||
# Get the MediaEntry for the comment
|
||||
media_entry = db.execute(
|
||||
media_entry_table.select(id=comment.media_entry_id))
|
||||
|
||||
# Create an AI for target
|
||||
db_ai_media = db.execute(ai_table.insert().values(
|
||||
type="media"
|
||||
))
|
||||
db_ai_media = db.execute(ai_table.select(
|
||||
ai_table.c.id==db_ai_media.inserted_primary_key[0]
|
||||
))
|
||||
|
||||
db.execute(
|
||||
media_entry_table.update().values(
|
||||
activity_as_target=db_ai_media.id
|
||||
).where(id=media_entry.id))
|
||||
|
||||
# Now create the AI for the comment
|
||||
db_ai_comment = db.execute(ai_table.insert().values(
|
||||
type="comment"
|
||||
))
|
||||
|
||||
activity = {
|
||||
"verb": "comment",
|
||||
"actor": comment.author,
|
||||
"published": comment.created,
|
||||
"updated": comment.created,
|
||||
"generator": gmg_generator.id,
|
||||
"object": db_ai_comment.id,
|
||||
"target": db_ai_media.id,
|
||||
}
|
||||
|
||||
# Now add the comment object
|
||||
db.execute(media_comments_table.insert().values(**activity))
|
||||
|
||||
# Create 'create' activities for all collections
|
||||
for collection in Collection.query.all():
|
||||
activity = Activity_R0(
|
||||
verb="create",
|
||||
actor=collection.creator,
|
||||
published=collection.created,
|
||||
updated=collection.created,
|
||||
generator=gmg_generator.id
|
||||
)
|
||||
activity.generate_content()
|
||||
activity.save(set_updated=False)
|
||||
activity.set_object(collection)
|
||||
collection.save()
|
||||
for collection in db.execute(collection_table.select()):
|
||||
# create AI
|
||||
db_ai = db.execute(ai_table.insert().values(
|
||||
type="collection"
|
||||
))
|
||||
|
||||
# Now add link the collection to the AI
|
||||
db.execute(collection_table.update().values(
|
||||
activity_as_object=db_ai.id
|
||||
).where(id=collection.id))
|
||||
|
||||
activity = {
|
||||
"verb": "create",
|
||||
"actor": collection.creator,
|
||||
"published": collection.created,
|
||||
"updated": collection.created,
|
||||
"generator": gmg_generator.id,
|
||||
"object": db_ai.id,
|
||||
}
|
||||
|
||||
db.execute(activity_table.insert().values(**activity))
|
||||
|
||||
|
||||
|
||||
db.commit()
|
||||
|
@ -43,6 +43,8 @@ from mediagoblin.tools.translate import pass_to_ugettext as _
|
||||
|
||||
|
||||
class UserMixin(object):
|
||||
object_type = "person"
|
||||
|
||||
@property
|
||||
def bio_html(self):
|
||||
return cleaned_markdown_conversion(self.bio)
|
||||
@ -131,6 +133,11 @@ class MediaEntryMixin(GenerateSlugMixin):
|
||||
|
||||
return check_media_slug_used(self.uploader, slug, self.id)
|
||||
|
||||
@property
|
||||
def object_type(self):
|
||||
""" Converts media_type to pump-like type - don't use internally """
|
||||
return self.media_type.split(".")[-1]
|
||||
|
||||
@property
|
||||
def description_html(self):
|
||||
"""
|
||||
@ -298,6 +305,8 @@ class MediaEntryMixin(GenerateSlugMixin):
|
||||
|
||||
|
||||
class MediaCommentMixin(object):
|
||||
object_type = "comment"
|
||||
|
||||
@property
|
||||
def content_html(self):
|
||||
"""
|
||||
@ -322,6 +331,8 @@ class MediaCommentMixin(object):
|
||||
|
||||
|
||||
class CollectionMixin(GenerateSlugMixin):
|
||||
object_type = "collection"
|
||||
|
||||
def check_slug_used(self, slug):
|
||||
# import this here due to a cyclic import issue
|
||||
# (db.models -> db.mixin -> db.util -> db.models)
|
||||
@ -366,6 +377,7 @@ class CollectionItemMixin(object):
|
||||
return cleaned_markdown_conversion(self.note)
|
||||
|
||||
class ActivityMixin(object):
|
||||
object_type = "activity"
|
||||
|
||||
VALID_VERBS = ["add", "author", "create", "delete", "dislike", "favorite",
|
||||
"follow", "like", "post", "share", "unfavorite", "unfollow",
|
||||
@ -440,7 +452,8 @@ class ActivityMixin(object):
|
||||
"updated": self.updated.isoformat(),
|
||||
"content": self.content,
|
||||
"url": self.get_url(request),
|
||||
"object": self.get_object().serialize(request)
|
||||
"object": self.get_object().serialize(request),
|
||||
"objectType": self.object_type,
|
||||
}
|
||||
|
||||
if self.generator:
|
||||
|
@ -78,15 +78,13 @@ class User(Base, UserMixin):
|
||||
upload_limit = Column(Integer)
|
||||
|
||||
activity_as_object = Column(Integer,
|
||||
ForeignKey("core__acitivity_intermediators.id"))
|
||||
ForeignKey("core__activity_intermediators.id"))
|
||||
activity_as_target = Column(Integer,
|
||||
ForeignKey("core__acitivity_intermediators.id"))
|
||||
ForeignKey("core__activity_intermediators.id"))
|
||||
|
||||
## TODO
|
||||
# plugin data would be in a separate model
|
||||
|
||||
objectType = "person"
|
||||
|
||||
def __repr__(self):
|
||||
return '<{0} #{1} {2} {3} "{4}">'.format(
|
||||
self.__class__.__name__,
|
||||
@ -151,7 +149,7 @@ class User(Base, UserMixin):
|
||||
"id": "acct:{0}@{1}".format(self.username, request.host),
|
||||
"preferredUsername": self.username,
|
||||
"displayName": "{0}@{1}".format(self.username, request.host),
|
||||
"objectType": self.objectType,
|
||||
"objectType": self.object_type,
|
||||
"pump_io": {
|
||||
"shared": False,
|
||||
"followed": False,
|
||||
@ -319,9 +317,9 @@ class MediaEntry(Base, MediaEntryMixin):
|
||||
default=MutationDict())
|
||||
|
||||
activity_as_object = Column(Integer,
|
||||
ForeignKey("core__acitivity_intermediators.id"))
|
||||
ForeignKey("core__activity_intermediators.id"))
|
||||
activity_as_target = Column(Integer,
|
||||
ForeignKey("core__acitivity_intermediators.id"))
|
||||
ForeignKey("core__activity_intermediators.id"))
|
||||
|
||||
## TODO
|
||||
# fail_error
|
||||
@ -444,18 +442,13 @@ class MediaEntry(Base, MediaEntryMixin):
|
||||
# pass through commit=False/True in kwargs
|
||||
super(MediaEntry, self).delete(**kwargs)
|
||||
|
||||
@property
|
||||
def objectType(self):
|
||||
""" Converts media_type to pump-like type - don't use internally """
|
||||
return self.media_type.split(".")[-1]
|
||||
|
||||
def serialize(self, request, show_comments=True):
|
||||
""" Unserialize MediaEntry to object """
|
||||
author = self.get_uploader
|
||||
context = {
|
||||
"id": self.id,
|
||||
"author": author.serialize(request),
|
||||
"objectType": self.objectType,
|
||||
"objectType": self.object_type,
|
||||
"url": self.url_for_self(request.urlgen),
|
||||
"image": {
|
||||
"url": request.host_url + self.thumb_url[1:],
|
||||
@ -472,7 +465,7 @@ class MediaEntry(Base, MediaEntryMixin):
|
||||
"self": {
|
||||
"href": request.urlgen(
|
||||
"mediagoblin.federation.object",
|
||||
objectType=self.objectType,
|
||||
object_type=self.objectType,
|
||||
id=self.id,
|
||||
qualified=True
|
||||
),
|
||||
@ -491,14 +484,15 @@ class MediaEntry(Base, MediaEntryMixin):
|
||||
context["license"] = self.license
|
||||
|
||||
if show_comments:
|
||||
comments = [comment.serialize(request) for comment in self.get_comments()]
|
||||
comments = [
|
||||
comment.serialize(request) for comment in self.get_comments()]
|
||||
total = len(comments)
|
||||
context["replies"] = {
|
||||
"totalItems": total,
|
||||
"items": comments,
|
||||
"url": request.urlgen(
|
||||
"mediagoblin.federation.object.comments",
|
||||
objectType=self.objectType,
|
||||
object_type=self.object_type,
|
||||
id=self.id,
|
||||
qualified=True
|
||||
),
|
||||
@ -620,8 +614,6 @@ class MediaTag(Base):
|
||||
creator=Tag.find_or_new
|
||||
)
|
||||
|
||||
objectType = "tag"
|
||||
|
||||
def __init__(self, name=None, slug=None):
|
||||
Base.__init__(self)
|
||||
if name is not None:
|
||||
@ -668,11 +660,9 @@ class MediaComment(Base, MediaCommentMixin):
|
||||
|
||||
|
||||
activity_as_object = Column(Integer,
|
||||
ForeignKey("core__acitivity_intermediators.id"))
|
||||
ForeignKey("core__activity_intermediators.id"))
|
||||
activity_as_target = Column(Integer,
|
||||
ForeignKey("core__acitivity_intermediators.id"))
|
||||
|
||||
objectType = "comment"
|
||||
ForeignKey("core__activity_intermediators.id"))
|
||||
|
||||
def serialize(self, request):
|
||||
""" Unserialize to python dictionary for API """
|
||||
@ -680,7 +670,7 @@ class MediaComment(Base, MediaCommentMixin):
|
||||
author = self.get_author
|
||||
context = {
|
||||
"id": self.id,
|
||||
"objectType": self.objectType,
|
||||
"objectType": self.object_type,
|
||||
"content": self.content,
|
||||
"inReplyTo": media.serialize(request, show_comments=False),
|
||||
"author": author.serialize(request)
|
||||
@ -739,16 +729,14 @@ class Collection(Base, CollectionMixin):
|
||||
cascade="all, delete-orphan"))
|
||||
|
||||
activity_as_object = Column(Integer,
|
||||
ForeignKey("core__acitivity_intermediators.id"))
|
||||
ForeignKey("core__activity_intermediators.id"))
|
||||
activity_as_target = Column(Integer,
|
||||
ForeignKey("core__acitivity_intermediators.id"))
|
||||
ForeignKey("core__activity_intermediators.id"))
|
||||
|
||||
__table_args__ = (
|
||||
UniqueConstraint('creator', 'slug'),
|
||||
{})
|
||||
|
||||
objectType = "collection"
|
||||
|
||||
def get_collection_items(self, ascending=False):
|
||||
#TODO, is this still needed with self.collection_items being available?
|
||||
order_col = CollectionItem.position
|
||||
@ -1085,10 +1073,7 @@ class PrivilegeUserAssociation(Base):
|
||||
primary_key=True)
|
||||
|
||||
class Generator(Base):
|
||||
"""
|
||||
This holds the information about the software used to create
|
||||
objects for the pump.io APIs.
|
||||
"""
|
||||
""" Information about what created an activity """
|
||||
__tablename__ = "core__generators"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
@ -1118,16 +1103,16 @@ class ActivityIntermediator(Base):
|
||||
used multiple times for the activity object or target and also allows for
|
||||
different types of objects to be used as an Activity.
|
||||
"""
|
||||
__tablename__ = "core__acitivity_intermediators"
|
||||
__tablename__ = "core__activity_intermediators"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
type = Column(Integer, nullable=False)
|
||||
type = Column(Unicode, nullable=False)
|
||||
|
||||
TYPES = {
|
||||
0: User,
|
||||
1: MediaEntry,
|
||||
2: MediaComment,
|
||||
3: Collection,
|
||||
"user": User,
|
||||
"media": MediaEntry,
|
||||
"comment": MediaComment,
|
||||
"collection": Collection,
|
||||
}
|
||||
|
||||
def _find_model(self, obj):
|
||||
@ -1189,18 +1174,22 @@ class Activity(Base, ActivityMixin):
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
actor = Column(Integer,
|
||||
ForeignKey(User.id, use_alter=True, name="actor"),
|
||||
ForeignKey("core__users.id"),
|
||||
nullable=False)
|
||||
published = Column(DateTime, nullable=False, default=datetime.datetime.now)
|
||||
updated = Column(DateTime, nullable=False, default=datetime.datetime.now)
|
||||
verb = Column(Unicode, nullable=False)
|
||||
content = Column(Unicode, nullable=True)
|
||||
title = Column(Unicode, nullable=True)
|
||||
generator = Column(Integer, ForeignKey(Generator.id), nullable=True)
|
||||
generator = Column(Integer,
|
||||
ForeignKey("core__generators.id"),
|
||||
nullable=True)
|
||||
object = Column(Integer,
|
||||
ForeignKey(ActivityIntermediator.id), nullable=False)
|
||||
ForeignKey("core__activity_intermediators.id"),
|
||||
nullable=False)
|
||||
target = Column(Integer,
|
||||
ForeignKey(ActivityIntermediator.id), nullable=True)
|
||||
ForeignKey("core__activity_intermediators.id"),
|
||||
nullable=True)
|
||||
|
||||
get_actor = relationship(User,
|
||||
foreign_keys="Activity.actor", post_update=True)
|
||||
@ -1214,8 +1203,9 @@ class Activity(Base, ActivityMixin):
|
||||
self.object = ai.id
|
||||
return
|
||||
|
||||
self.object.set_object(*args, **kwargs)
|
||||
self.object.save()
|
||||
ai = ActivityIntermediator.query.filter_by(id=self.object).first()
|
||||
ai.set_object(*args, **kwargs)
|
||||
ai.save()
|
||||
|
||||
@property
|
||||
def get_object(self):
|
||||
@ -1229,8 +1219,9 @@ class Activity(Base, ActivityMixin):
|
||||
self.object = ai.id
|
||||
return
|
||||
|
||||
self.target.set_object(*args, **kwargs)
|
||||
self.targt.save()
|
||||
ai = ActivityIntermediator.query.filter_by(id=self.target).first()
|
||||
ai.set_object(*args, **kwargs)
|
||||
ai.save()
|
||||
|
||||
@property
|
||||
def get_target(self):
|
||||
|
@ -51,12 +51,12 @@ add_route(
|
||||
# object endpoints
|
||||
add_route(
|
||||
"mediagoblin.federation.object",
|
||||
"/api/<string:objectType>/<string:id>",
|
||||
"/api/<string:object_type>/<string:id>",
|
||||
"mediagoblin.federation.views:object_endpoint"
|
||||
)
|
||||
add_route(
|
||||
"mediagoblin.federation.object.comments",
|
||||
"/api/<string:objectType>/<string:id>/comments",
|
||||
"/api/<string:object_type>/<string:id>/comments",
|
||||
"mediagoblin.federation.views:object_comments"
|
||||
)
|
||||
|
||||
|
@ -71,14 +71,14 @@ def profile_endpoint(request):
|
||||
def user_endpoint(request):
|
||||
""" This is /api/user/<username> - This will get the user """
|
||||
user, user_profile = get_profile(request)
|
||||
|
||||
|
||||
if user is None:
|
||||
username = request.matchdict["username"]
|
||||
return json_error(
|
||||
"No such 'user' with username '{0}'".format(username),
|
||||
status=404
|
||||
)
|
||||
|
||||
|
||||
return json_response({
|
||||
"nickname": user.username,
|
||||
"updated": user.created.isoformat(),
|
||||
@ -350,7 +350,7 @@ def feed_endpoint(request):
|
||||
@oauth_required
|
||||
def object_endpoint(request):
|
||||
""" Lookup for a object type """
|
||||
object_type = request.matchdict["objectType"]
|
||||
object_type = request.matchdict["object_type"]
|
||||
try:
|
||||
object_id = int(request.matchdict["id"])
|
||||
except ValueError:
|
||||
@ -382,17 +382,17 @@ def object_comments(request):
|
||||
media = MediaEntry.query.filter_by(id=request.matchdict["id"]).first()
|
||||
if media is None:
|
||||
return json_error("Can't find '{0}' with ID '{1}'".format(
|
||||
request.matchdict["objectType"],
|
||||
request.matchdict["object_type"],
|
||||
request.matchdict["id"]
|
||||
), 404)
|
||||
|
||||
comments = response.serialize(request)
|
||||
comments = media.serialize(request)
|
||||
comments = comments.get("replies", {
|
||||
"totalItems": 0,
|
||||
"items": [],
|
||||
"url": request.urlgen(
|
||||
"mediagoblin.federation.object.comments",
|
||||
objectType=media.objectType,
|
||||
object_type=media.object_type,
|
||||
id=media.id,
|
||||
qualified=True
|
||||
)
|
||||
@ -459,27 +459,30 @@ def whoami(request):
|
||||
@require_active_login
|
||||
def activity_view(request):
|
||||
""" /<username>/activity/<id> - Display activity
|
||||
|
||||
|
||||
This should display a HTML presentation of the activity
|
||||
this is NOT an API endpoint.
|
||||
"""
|
||||
# Get the user object.
|
||||
username = request.matchdict["username"]
|
||||
user = User.query.filter_by(username=username).first()
|
||||
|
||||
|
||||
activity_id = request.matchdict["id"]
|
||||
|
||||
|
||||
if request.user is None:
|
||||
return render_404(request)
|
||||
|
||||
activity = Activity.query.filter_by(id=activity_id).first()
|
||||
|
||||
activity = Activity.query.filter_by(
|
||||
id=activity_id,
|
||||
author=user.id
|
||||
).first()
|
||||
if activity is None:
|
||||
return render_404(request)
|
||||
|
||||
|
||||
return render_to_response(
|
||||
request,
|
||||
"mediagoblin/federation/activity.html",
|
||||
{"activity": activity}
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user