[Launchpad-reviewers] [Merge] ~pappacena/launchpad:comment-editing-model into launchpad:master
The proposal to merge ~pappacena/launchpad:comment-editing-model into launchpad:master has been updated. Status: Approved => Merged For more details, see: https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/401894 -- Your team Launchpad code reviewers is subscribed to branch ~pappacena/launchpad:comment-editing-model. ___ Mailing list: https://launchpad.net/~launchpad-reviewers Post to : launchpad-reviewers@lists.launchpad.net Unsubscribe : https://launchpad.net/~launchpad-reviewers More help : https://help.launchpad.net/ListHelp
[Launchpad-reviewers] [Merge] ~pappacena/launchpad:comment-editing-model into launchpad:master
The proposal to merge ~pappacena/launchpad:comment-editing-model into launchpad:master has been updated. Status: Needs review => Approved For more details, see: https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/401894 -- Your team Launchpad code reviewers is subscribed to branch ~pappacena/launchpad:comment-editing-model. ___ Mailing list: https://launchpad.net/~launchpad-reviewers Post to : launchpad-reviewers@lists.launchpad.net Unsubscribe : https://launchpad.net/~launchpad-reviewers More help : https://help.launchpad.net/ListHelp
Re: [Launchpad-reviewers] [Merge] ~pappacena/launchpad:comment-editing-model into launchpad:master
Pushed the requested changes. This should be good to go now. Diff comments: > diff --git a/lib/lp/services/messages/interfaces/messagerevision.py > b/lib/lp/services/messages/interfaces/messagerevision.py > new file mode 100644 > index 000..3b72673 > --- /dev/null > +++ b/lib/lp/services/messages/interfaces/messagerevision.py > @@ -0,0 +1,69 @@ > +# Copyright 2019-2021 Canonical Ltd. This software is licensed under the > +# GNU Affero General Public License version 3 (see the file LICENSE). > + > +"""Message revision history.""" > + > +from __future__ import absolute_import, print_function, unicode_literals > + > +__all__ = [ > +'IMessageRevision', > +'IMessageRevisionChunk', > +] > + > +from lazr.restful.fields import Reference > +from zope.interface import ( > +Attribute, > +Interface, > +) > +from zope.schema import ( > +Datetime, > +Int, > +Text, > +) > + > +from lp import _ > +from lp.services.messages.interfaces.message import IMessage > + > + > +class IMessageRevisionView(Interface): > +"""IMessageRevision readable attributes.""" > +id = Int(title=_("ID"), required=True, readonly=True) > + > +revision = Int(title=_("Revision number"), required=True, readonly=True) > + > +content = Text( > +title=_("The message at the given revision"), > +required=False, readonly=True) :facepalm: Fixing it. > + > +message = Reference( > +title=_('The current message of this revision.'), > +schema=IMessage, required=True, readonly=True) > + > +date_created = Datetime( > +title=_("The time when this message revision was created."), > +required=True, readonly=True) > + > +date_deleted = Datetime( > +title=_("The time when this message revision was created."), > +required=False, readonly=True) > + > +chunks = Attribute(_('Message pieces')) > + > + > +class IMessageRevisionEdit(Interface): > +"""IMessageRevision editable attributes.""" > + > +def deleteContent(): > +"""Logically deletes this MessageRevision.""" > + > + > +class IMessageRevision(IMessageRevisionView, IMessageRevisionEdit): > +"""A historical revision of a IMessage.""" > + > + > +class IMessageRevisionChunk(Interface): > +id = Int(title=_('ID'), required=True, readonly=True) > +messagerevision = Int( > +title=_('MessageRevision'), required=True, readonly=True) > +sequence = Int(title=_('Sequence order'), required=True, readonly=True) > +content = Text(title=_('Text content'), required=False, readonly=True) > diff --git a/lib/lp/services/messages/model/message.py > b/lib/lp/services/messages/model/message.py > index e592daa..b73e212 100644 > --- a/lib/lp/services/messages/model/message.py > +++ b/lib/lp/services/messages/model/message.py > @@ -164,6 +176,63 @@ class Message(SQLBase): > """See `IMessage`.""" > return None > > +@cachedproperty > +def revisions(self): > +"""See `IMessage`.""" > +return list(Store.of(self).find( > +MessageRevision, > +MessageRevision.message == self > +).order_by(Desc(MessageRevision.revision))) > + > +def editContent(self, new_content): > +"""See `IMessage`.""" > +store = Store.of(self) > + > +# Move the old content to a new revision. > +date_created = ( > +self.date_last_edited if self.date_last_edited is not None > +else self.datecreated) > +current_rev_num = store.find( > +Max(MessageRevision.revision), > +MessageRevision.message == self).one() > +rev_num = (current_rev_num or 0) + 1 > +rev = MessageRevision( > +message=self, revision=rev_num, date_created=date_created) > +self.date_last_edited = utc_now() > +store.add(rev) > + > +# Move the current text content to the recently created revision. > +for chunk in self._chunks: > +if chunk.blob is None: > +revision_chunk = MessageRevisionChunk( > +rev, chunk.sequence, chunk.content) > +store.add(revision_chunk) > +store.remove(chunk) > + > +# Create the new content. > +new_chunk = MessageChunk(message=self, sequence=1, > content=new_content) Ok! I'll try to fill eventual gaps instead of jumping directly into max_seq + 1. > +store.add(new_chunk) > + > +store.flush() > + > +# Clean up caches. > +del get_property_cache(self).text_contents > +del get_property_cache(self).chunks > +del get_property_cache(self).revisions > +return rev > + > +def deleteContent(self): > +"""See `IMessage`.""" > +store = Store.of(self) > +store.find(MessageChunk, MessageChunk.message == self).remove() > +for rev in self.revisions: > +store.find(MessageRevisionChunk,
Re: [Launchpad-reviewers] [Merge] ~pappacena/launchpad:comment-editing-model into launchpad:master
Review: Approve Diff comments: > diff --git a/lib/lp/services/messages/interfaces/messagerevision.py > b/lib/lp/services/messages/interfaces/messagerevision.py > new file mode 100644 > index 000..3b72673 > --- /dev/null > +++ b/lib/lp/services/messages/interfaces/messagerevision.py > @@ -0,0 +1,69 @@ > +# Copyright 2019-2021 Canonical Ltd. This software is licensed under the > +# GNU Affero General Public License version 3 (see the file LICENSE). > + > +"""Message revision history.""" > + > +from __future__ import absolute_import, print_function, unicode_literals > + > +__all__ = [ > +'IMessageRevision', > +'IMessageRevisionChunk', > +] > + > +from lazr.restful.fields import Reference > +from zope.interface import ( > +Attribute, > +Interface, > +) > +from zope.schema import ( > +Datetime, > +Int, > +Text, > +) > + > +from lp import _ > +from lp.services.messages.interfaces.message import IMessage > + > + > +class IMessageRevisionView(Interface): > +"""IMessageRevision readable attributes.""" > +id = Int(title=_("ID"), required=True, readonly=True) > + > +revision = Int(title=_("Revision number"), required=True, readonly=True) > + > +content = Text( > +title=_("The message at the given revision"), > +required=False, readonly=True) It looks like you changed `IMessageRevisionChunk.content` but forgot to change this one? > + > +message = Reference( > +title=_('The current message of this revision.'), > +schema=IMessage, required=True, readonly=True) > + > +date_created = Datetime( > +title=_("The time when this message revision was created."), > +required=True, readonly=True) > + > +date_deleted = Datetime( > +title=_("The time when this message revision was created."), > +required=False, readonly=True) > + > +chunks = Attribute(_('Message pieces')) > + > + > +class IMessageRevisionEdit(Interface): > +"""IMessageRevision editable attributes.""" > + > +def deleteContent(): > +"""Logically deletes this MessageRevision.""" > + > + > +class IMessageRevision(IMessageRevisionView, IMessageRevisionEdit): > +"""A historical revision of a IMessage.""" > + > + > +class IMessageRevisionChunk(Interface): > +id = Int(title=_('ID'), required=True, readonly=True) > +messagerevision = Int( > +title=_('MessageRevision'), required=True, readonly=True) > +sequence = Int(title=_('Sequence order'), required=True, readonly=True) > +content = Text(title=_('Text content'), required=False, readonly=True) > diff --git a/lib/lp/services/messages/model/message.py > b/lib/lp/services/messages/model/message.py > index e592daa..b73e212 100644 > --- a/lib/lp/services/messages/model/message.py > +++ b/lib/lp/services/messages/model/message.py > @@ -164,6 +176,63 @@ class Message(SQLBase): > """See `IMessage`.""" > return None > > +@cachedproperty > +def revisions(self): > +"""See `IMessage`.""" > +return list(Store.of(self).find( > +MessageRevision, > +MessageRevision.message == self > +).order_by(Desc(MessageRevision.revision))) > + > +def editContent(self, new_content): > +"""See `IMessage`.""" > +store = Store.of(self) > + > +# Move the old content to a new revision. > +date_created = ( > +self.date_last_edited if self.date_last_edited is not None > +else self.datecreated) > +current_rev_num = store.find( > +Max(MessageRevision.revision), > +MessageRevision.message == self).one() > +rev_num = (current_rev_num or 0) + 1 > +rev = MessageRevision( > +message=self, revision=rev_num, date_created=date_created) > +self.date_last_edited = utc_now() > +store.add(rev) > + > +# Move the current text content to the recently created revision. > +for chunk in self._chunks: > +if chunk.blob is None: > +revision_chunk = MessageRevisionChunk( > +rev, chunk.sequence, chunk.content) > +store.add(revision_chunk) > +store.remove(chunk) > + > +# Create the new content. > +new_chunk = MessageChunk(message=self, sequence=1, > content=new_content) It's probably not vital, but I think ideally the new chunk should occupy the smallest unused sequence number, rather than the largest + 1. (Consider [text comment, binary attachment], which if edited should probably turn into [new text comment, binary attachment] rather than [gap, binary attachment, new text comment].) > +store.add(new_chunk) > + > +store.flush() > + > +# Clean up caches. > +del get_property_cache(self).text_contents > +del get_property_cache(self).chunks > +del get_property_cache(self).revisions > +return rev > + > +def
Re: [Launchpad-reviewers] [Merge] ~pappacena/launchpad:comment-editing-model into launchpad:master
Addressed all the comments. Diff comments: > diff --git a/database/schema/security.cfg b/database/schema/security.cfg > index c3aba65..b712521 100644 > --- a/database/schema/security.cfg > +++ b/database/schema/security.cfg > @@ -232,7 +232,9 @@ public.logintoken = SELECT, INSERT, > UPDATE, DELETE > public.mailinglist = SELECT, INSERT, UPDATE, DELETE > public.mailinglistsubscription = SELECT, INSERT, UPDATE, DELETE > public.messageapproval = SELECT, INSERT, UPDATE, DELETE > -public.messagechunk = SELECT, INSERT > +public.messagechunk = SELECT, INSERT, DELETE > +public.messagerevision = SELECT, INSERT, UPDATE, DELETE > +public.messagerevisionchunk = SELECT, INSERT, UPDATE, DELETE You are right. Fixing it. > public.milestone= SELECT, INSERT, UPDATE, DELETE > public.milestonetag = SELECT, INSERT, UPDATE, DELETE > public.mirrorcdimagedistroseries= SELECT, INSERT, DELETE > diff --git a/lib/lp/security.py b/lib/lp/security.py > index 412f497..cd88d5c 100644 > --- a/lib/lp/security.py > +++ b/lib/lp/security.py > @@ -3182,6 +3182,15 @@ class SetMessageVisibility(AuthorizationBase): > return (user.in_admin or user.in_registry_experts) > > > +class EditMessage(AuthorizationBase): > +permission = 'launchpad.Edit' > +usedfor = IMessage > + > +def checkAuthenticated(self, user): > +"""Only message owner can edit it.""" > +return user.isOwner(self.obj) Right. Adding it. > + > + > class ViewPublisherConfig(AdminByAdminsTeam): > usedfor = IPublisherConfig > > diff --git a/lib/lp/services/messages/interfaces/messagerevision.py > b/lib/lp/services/messages/interfaces/messagerevision.py > new file mode 100644 > index 000..3b72673 > --- /dev/null > +++ b/lib/lp/services/messages/interfaces/messagerevision.py > @@ -0,0 +1,69 @@ > +# Copyright 2019-2021 Canonical Ltd. This software is licensed under the > +# GNU Affero General Public License version 3 (see the file LICENSE). > + > +"""Message revision history.""" > + > +from __future__ import absolute_import, print_function, unicode_literals > + > +__all__ = [ > +'IMessageRevision', > +'IMessageRevisionChunk', > +] > + > +from lazr.restful.fields import Reference > +from zope.interface import ( > +Attribute, > +Interface, > +) > +from zope.schema import ( > +Datetime, > +Int, > +Text, > +) > + > +from lp import _ > +from lp.services.messages.interfaces.message import IMessage > + > + > +class IMessageRevisionView(Interface): > +"""IMessageRevision readable attributes.""" > +id = Int(title=_("ID"), required=True, readonly=True) > + > +revision = Int(title=_("Revision number"), required=True, readonly=True) > + > +content = Text( > +title=_("The message at the given revision"), > +required=False, readonly=True) Ok! > + > +message = Reference( > +title=_('The current message of this revision.'), > +schema=IMessage, required=True, readonly=True) > + > +date_created = Datetime( > +title=_("The time when this message revision was created."), > +required=True, readonly=True) > + > +date_deleted = Datetime( > +title=_("The time when this message revision was created."), > +required=False, readonly=True) > + > +chunks = Attribute(_('Message pieces')) > + > + > +class IMessageRevisionEdit(Interface): > +"""IMessageRevision editable attributes.""" > + > +def deleteContent(): > +"""Logically deletes this MessageRevision.""" Fixing this description. > + > + > +class IMessageRevision(IMessageRevisionView, IMessageRevisionEdit): > +"""A historical revision of a IMessage.""" > + > + > +class IMessageRevisionChunk(Interface): > +id = Int(title=_('ID'), required=True, readonly=True) > +messagerevision = Int( > +title=_('MessageRevision'), required=True, readonly=True) > +sequence = Int(title=_('Sequence order'), required=True, readonly=True) > +content = Text(title=_('Text content'), required=False, readonly=True) Ok! > diff --git a/lib/lp/services/messages/model/message.py > b/lib/lp/services/messages/model/message.py > index e592daa..b73e212 100644 > --- a/lib/lp/services/messages/model/message.py > +++ b/lib/lp/services/messages/model/message.py > @@ -164,6 +176,63 @@ class Message(SQLBase): > """See `IMessage`.""" > return None > > +@cachedproperty > +def revisions(self): > +"""See `IMessage`.""" > +return list(Store.of(self).find( > +MessageRevision, > +MessageRevision.message == self > +).order_by(Desc(MessageRevision.revision))) > + > +def editContent(self, new_content): > +"""See `IMessage`.""" > +store = Store.of(self) > + > +# Move the old
Re: [Launchpad-reviewers] [Merge] ~pappacena/launchpad:comment-editing-model into launchpad:master
Review: Approve Diff comments: > diff --git a/database/schema/security.cfg b/database/schema/security.cfg > index c3aba65..b712521 100644 > --- a/database/schema/security.cfg > +++ b/database/schema/security.cfg > @@ -232,7 +232,9 @@ public.logintoken = SELECT, INSERT, > UPDATE, DELETE > public.mailinglist = SELECT, INSERT, UPDATE, DELETE > public.mailinglistsubscription = SELECT, INSERT, UPDATE, DELETE > public.messageapproval = SELECT, INSERT, UPDATE, DELETE > -public.messagechunk = SELECT, INSERT > +public.messagechunk = SELECT, INSERT, DELETE > +public.messagerevision = SELECT, INSERT, UPDATE, DELETE > +public.messagerevisionchunk = SELECT, INSERT, UPDATE, DELETE Are `MessageRevisionChunk` rows ever updated? I thought they were only inserted or deleted. > public.milestone= SELECT, INSERT, UPDATE, DELETE > public.milestonetag = SELECT, INSERT, UPDATE, DELETE > public.mirrorcdimagedistroseries= SELECT, INSERT, DELETE > diff --git a/lib/lp/security.py b/lib/lp/security.py > index 412f497..cd88d5c 100644 > --- a/lib/lp/security.py > +++ b/lib/lp/security.py > @@ -3182,6 +3182,15 @@ class SetMessageVisibility(AuthorizationBase): > return (user.in_admin or user.in_registry_experts) > > > +class EditMessage(AuthorizationBase): > +permission = 'launchpad.Edit' > +usedfor = IMessage > + > +def checkAuthenticated(self, user): > +"""Only message owner can edit it.""" > +return user.isOwner(self.obj) I guess there's some kind of default permission that applies to `IMessageRevision`, but it seems as though it might be a good idea for it to explicitly delegate to its parent `IMessage`. > + > + > class ViewPublisherConfig(AdminByAdminsTeam): > usedfor = IPublisherConfig > > diff --git a/lib/lp/services/messages/interfaces/messagerevision.py > b/lib/lp/services/messages/interfaces/messagerevision.py > new file mode 100644 > index 000..3b72673 > --- /dev/null > +++ b/lib/lp/services/messages/interfaces/messagerevision.py > @@ -0,0 +1,69 @@ > +# Copyright 2019-2021 Canonical Ltd. This software is licensed under the > +# GNU Affero General Public License version 3 (see the file LICENSE). > + > +"""Message revision history.""" > + > +from __future__ import absolute_import, print_function, unicode_literals > + > +__all__ = [ > +'IMessageRevision', > +'IMessageRevisionChunk', > +] > + > +from lazr.restful.fields import Reference > +from zope.interface import ( > +Attribute, > +Interface, > +) > +from zope.schema import ( > +Datetime, > +Int, > +Text, > +) > + > +from lp import _ > +from lp.services.messages.interfaces.message import IMessage > + > + > +class IMessageRevisionView(Interface): > +"""IMessageRevision readable attributes.""" > +id = Int(title=_("ID"), required=True, readonly=True) > + > +revision = Int(title=_("Revision number"), required=True, readonly=True) > + > +content = Text( > +title=_("The message at the given revision"), > +required=False, readonly=True) Maybe `required=True`, since the property can never return None? > + > +message = Reference( > +title=_('The current message of this revision.'), > +schema=IMessage, required=True, readonly=True) > + > +date_created = Datetime( > +title=_("The time when this message revision was created."), > +required=True, readonly=True) > + > +date_deleted = Datetime( > +title=_("The time when this message revision was created."), > +required=False, readonly=True) > + > +chunks = Attribute(_('Message pieces')) > + > + > +class IMessageRevisionEdit(Interface): > +"""IMessageRevision editable attributes.""" > + > +def deleteContent(): > +"""Logically deletes this MessageRevision.""" What does "Logically deletes" mean? > + > + > +class IMessageRevision(IMessageRevisionView, IMessageRevisionEdit): > +"""A historical revision of a IMessage.""" > + > + > +class IMessageRevisionChunk(Interface): > +id = Int(title=_('ID'), required=True, readonly=True) > +messagerevision = Int( > +title=_('MessageRevision'), required=True, readonly=True) > +sequence = Int(title=_('Sequence order'), required=True, readonly=True) > +content = Text(title=_('Text content'), required=False, readonly=True) Should be `required=True` to match the DB patch, I think. > diff --git a/lib/lp/services/messages/model/message.py > b/lib/lp/services/messages/model/message.py > index e592daa..b73e212 100644 > --- a/lib/lp/services/messages/model/message.py > +++ b/lib/lp/services/messages/model/message.py > @@ -164,6 +176,63 @@ class Message(SQLBase): > """See `IMessage`.""" > return None > > +@cachedproperty > +def revisions(self): > +
[Launchpad-reviewers] [Merge] ~pappacena/launchpad:comment-editing-model into launchpad:master
The proposal to merge ~pappacena/launchpad:comment-editing-model into launchpad:master has been updated. Description changed to: More changes will be added in a future MP in order to adjust BugComment, CodeReviewComment and QuestionMessage to use the new methods. These changes were splitted to make the review process easier. For more details, see: https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/401894 -- Your team Launchpad code reviewers is requested to review the proposed merge of ~pappacena/launchpad:comment-editing-model into launchpad:master. ___ Mailing list: https://launchpad.net/~launchpad-reviewers Post to : launchpad-reviewers@lists.launchpad.net Unsubscribe : https://launchpad.net/~launchpad-reviewers More help : https://help.launchpad.net/ListHelp
[Launchpad-reviewers] [Merge] ~pappacena/launchpad:comment-editing-model into launchpad:master
The proposal to merge ~pappacena/launchpad:comment-editing-model into launchpad:master has been updated. Description changed to: More changes will be added in a future MP in order to adjust BugComment, CodeReviewComment and QuestionMessage to use the new methods. Those changes were splitted to make the review process easier. For more details, see: https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/401894 -- Your team Launchpad code reviewers is requested to review the proposed merge of ~pappacena/launchpad:comment-editing-model into launchpad:master. ___ Mailing list: https://launchpad.net/~launchpad-reviewers Post to : launchpad-reviewers@lists.launchpad.net Unsubscribe : https://launchpad.net/~launchpad-reviewers More help : https://help.launchpad.net/ListHelp
[Launchpad-reviewers] [Merge] ~pappacena/launchpad:comment-editing-model into launchpad:master
Thiago F. Pappacena has proposed merging ~pappacena/launchpad:comment-editing-model into launchpad:master. Commit message: Mapping database initial structure for message editing Requested reviews: Launchpad code reviewers (launchpad-reviewers) For more details, see: https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/401894 -- Your team Launchpad code reviewers is requested to review the proposed merge of ~pappacena/launchpad:comment-editing-model into launchpad:master. diff --git a/database/schema/security.cfg b/database/schema/security.cfg index 1bbb845..c8b7d10 100644 --- a/database/schema/security.cfg +++ b/database/schema/security.cfg @@ -232,7 +232,8 @@ public.logintoken = SELECT, INSERT, UPDATE, DELETE public.mailinglist = SELECT, INSERT, UPDATE, DELETE public.mailinglistsubscription = SELECT, INSERT, UPDATE, DELETE public.messageapproval = SELECT, INSERT, UPDATE, DELETE -public.messagechunk = SELECT, INSERT +public.messagechunk = SELECT, INSERT, DELETE +public.messagerevision = SELECT, INSERT, UPDATE public.milestone= SELECT, INSERT, UPDATE, DELETE public.milestonetag = SELECT, INSERT, UPDATE, DELETE public.mirrorcdimagedistroseries= SELECT, INSERT, DELETE diff --git a/lib/lp/bugs/browser/tests/test_bugcomment.py b/lib/lp/bugs/browser/tests/test_bugcomment.py index c1877a5..e5baac1 100644 --- a/lib/lp/bugs/browser/tests/test_bugcomment.py +++ b/lib/lp/bugs/browser/tests/test_bugcomment.py @@ -1,4 +1,4 @@ -# Copyright 2010-2018 Canonical Ltd. This software is licensed under the +# Copyright 2010-2021 Canonical Ltd. This software is licensed under the # GNU Affero General Public License version 3 (see the file LICENSE). """Tests for the bugcomment module.""" @@ -35,6 +35,7 @@ from lp.testing import ( BrowserTestCase, celebrity_logged_in, login_person, +person_logged_in, TestCase, TestCaseWithFactory, verifyObject, @@ -300,7 +301,10 @@ class TestBugCommentImplementsInterface(TestCaseWithFactory): bug_message = self.factory.makeBugComment() bugtask = bug_message.bugs[0].bugtasks[0] bug_comment = BugComment(1, bug_message, bugtask) -verifyObject(IBugComment, bug_comment) +# Runs verifyObject logged in as the bug owner, so we don't fail on +# attributes that are not public to everyone. +with person_logged_in(bug_message.owner): +verifyObject(IBugComment, bug_comment) def test_download_url(self): """download_url is provided and works as expected.""" diff --git a/lib/lp/security.py b/lib/lp/security.py index 412f497..cd88d5c 100644 --- a/lib/lp/security.py +++ b/lib/lp/security.py @@ -3182,6 +3182,15 @@ class SetMessageVisibility(AuthorizationBase): return (user.in_admin or user.in_registry_experts) +class EditMessage(AuthorizationBase): +permission = 'launchpad.Edit' +usedfor = IMessage + +def checkAuthenticated(self, user): +"""Only message owner can edit it.""" +return user.isOwner(self.obj) + + class ViewPublisherConfig(AdminByAdminsTeam): usedfor = IPublisherConfig diff --git a/lib/lp/services/messages/configure.zcml b/lib/lp/services/messages/configure.zcml index e989fe2..fcaffab 100644 --- a/lib/lp/services/messages/configure.zcml +++ b/lib/lp/services/messages/configure.zcml @@ -1,4 +1,4 @@ - @@ -10,9 +10,9 @@ i18n_domain="launchpad"> - - + + @@ -22,6 +22,19 @@ + + + + + + + diff --git a/lib/lp/services/messages/interfaces/message.py b/lib/lp/services/messages/interfaces/message.py index 7e18e7d..0c54c84 100644 --- a/lib/lp/services/messages/interfaces/message.py +++ b/lib/lp/services/messages/interfaces/message.py @@ -1,4 +1,4 @@ -# Copyright 2009-2018 Canonical Ltd. This software is licensed under the +# Copyright 2009-2021 Canonical Ltd. This software is licensed under the # GNU Affero General Public License version 3 (see the file LICENSE). __metaclass__ = type @@ -49,9 +49,19 @@ from lp.services.librarian.interfaces import ILibraryFileAlias from lp.services.webservice.apihelpers import patch_reference_property -@exported_as_webservice_entry('message') -class IMessage(Interface): -"""A message. +class IMessageEdit(Interface): + +def edit_content(new_content): +"""Edit the content of this message, generating a new message +revision with the old content. +""" + +def delete_content(): +"""Deletes this message content.""" + + +class IMessageView(Interface): +"""Public attributes for message. This is like an email (RFC822) message, though it could be created through the web as well. @@ -61,6 +71,15 @@ class IMessage(Interface):