def mutate(root, args, context, info): EMBED_ATTACHMENT = models.AttachmentPurpose.EMBED_ATTACHMENT.value discussion_id = context.matchdict['discussion_id'] discussion = models.Discussion.get(discussion_id) post_id = args.get('post_id') post_id = int(Node.from_global_id(post_id)[1]) post = models.Post.get(post_id) cls = models.PostAttachment require_cls_permission(CrudPermissions.CREATE, cls, context) # add uploaded file as an attachment to the post attachment = args.get('file') if attachment is not None: filename = os.path.basename(context.POST[attachment].filename) mime_type = context.POST[attachment].type document = models.File( discussion=discussion, mime_type=mime_type, title=filename) document.add_file_data(context.POST[attachment].file) attachment = models.PostAttachment( document=document, discussion=discussion, creator_id=context.authenticated_userid, post=post, title=filename, attachmentPurpose=EMBED_ATTACHMENT ) post.db.add(attachment) post.db.flush() return AddPostAttachment(post=post)
def upgrade(pyramid_env): with context.begin_transaction(): pass # Do stuff with the app's models here. from assembl import models as m db = m.get_session_maker()() with transaction.manager: posts = db.query(m.WidgetPost).options( sa.orm.joinedload(m.WidgetPost.attachments)).filter( m.WidgetPost.metadata_raw.like('%://www.youtube.com/%')).all() for post in posts: url = post.metadata_json.get("inspiration_url", None) if not url: continue if not (url.startswith("https://www.youtube.com/") or url.startswith("http://www.youtube.com/")): # Should not happen, but elsewhere in metadata continue existing = {att.document.uri_id for att in post.attachments} if url in existing: continue document = db.query(m.Document).filter_by( uri_id=url, discussion_id=post.discussion_id).first() if not document: document = m.Document(uri_id=url, discussion_id=post.discussion_id) attachment = m.PostAttachment(discussion_id=post.discussion_id, creator_id=post.creator_id, document=document, attachmentPurpose='EMBED_ATTACHMENT', post=post) db.add(attachment) db.flush() # so document is available if repeated
def fulltext_synthesis_post_with_image(request, discussion, moderator_user, simple_file, test_session): from assembl import models synthesis_post = models.SynthesisPost( publication_state=models.PublicationStates.DRAFT, discussion=discussion, creator=moderator_user, publishes_synthesis=models.FullTextSynthesis( discussion=discussion, subject=models.LangString.create(u"a synthesis with image", "en"), body=models.LangString.create(u"Lorem ipsum dolor sit amet", "en"), )) synthesis_post.publishes_synthesis.subject.add_value( "une synthèse avec image", "fr") synthesis_post.publishes_synthesis.body.add_value( "Laurème ipsoume dolaure sitamette", "fr") test_session.flush() synthesis_image = models.PostAttachment(discussion=discussion, document=simple_file, post=synthesis_post, title=u"Synthesis image", creator=moderator_user, attachmentPurpose='IMAGE') test_session.add(synthesis_post) test_session.flush() def fin(): print("finalizer synthesis post with image") test_session.delete(synthesis_image) test_session.delete(synthesis_post) test_session.flush() request.addfinalizer(fin) return synthesis_post
def mutate(root, args, context, info): EMBED_ATTACHMENT = models.AttachmentPurpose.EMBED_ATTACHMENT.value discussion_id = context.matchdict['discussion_id'] user_id = context.authenticated_userid or Everyone discussion = models.Discussion.get(discussion_id) post_id = args.get('post_id') post_id = int(Node.from_global_id(post_id)[1]) post = models.Post.get(post_id) cls = models.Post permissions = get_permissions(user_id, discussion_id) allowed = post.user_can(user_id, CrudPermissions.UPDATE, permissions) if not allowed: raise HTTPUnauthorized() changed = False subject = args.get('subject') if subject: subject = sanitize_text(subject) body = args.get('body') if body: body = sanitize_html(body) # TODO: Here, an assumption that the modification uses the same # language as the original. May need revisiting. original_subject_entry = post.subject.first_original() # subject is not required, be careful to not remove it if not specified if subject and subject != original_subject_entry.value: changed = True post.subject.add_value(subject, original_subject_entry.locale_code) # Edit subject for all descendants children = post.children[:] new_subject = u'Re: ' + restrip_pat.sub('', subject).strip() while children: child = children.pop() children.extend(child.children) child.subject.add_value( new_subject, child.subject.first_original().locale_code) original_body_entry = post.body.first_original() if body != original_body_entry.value: post.body.add_value(body, original_body_entry.locale_code) changed = True original_attachments = post.attachments original_attachments_doc_ids = [] if original_attachments: original_attachments_doc_ids = [ str(a.document_id) for a in original_attachments ] attachments = args.get('attachments', []) for document_id in attachments: if document_id not in original_attachments_doc_ids: document = models.Document.get(document_id) models.PostAttachment( document=document, discussion=discussion, creator_id=context.authenticated_userid, post=post, title=document.title, attachmentPurpose=EMBED_ATTACHMENT) # delete attachments that has been removed documents_to_delete = set(original_attachments_doc_ids) - set( attachments) # noqa: E501 for document_id in documents_to_delete: with cls.default_db.no_autoflush: document = models.Document.get(document_id) post_attachment = post.db.query( models.PostAttachment).filter_by( discussion_id=discussion_id, post_id=post_id, document_id=document_id).first() document.delete_file() post.db.delete(document) post.attachments.remove(post_attachment) post.db.flush() publication_state = models.PublicationStates.from_string( args.get('publication_state')) if args.get( 'publication_state') in models.PublicationStates.values( ) else None if publication_state and publication_state != post.publication_state: post.publication_state = publication_state changed = True # Update the creation date when switching from draft to published if post.publication_state == models.PublicationStates.DRAFT and publication_state == models.PublicationStates.PUBLISHED: post.creation_date = datetime.utcnow() if changed: post.modification_date = datetime.utcnow() post.body_mime_type = u'text/html' post.db.flush() post.db.expire(post.subject, ["entries"]) post.db.expire(post.body, ["entries"]) return UpdatePost(post=post)
def mutate(root, args, context, info): EMBED_ATTACHMENT = models.AttachmentPurpose.EMBED_ATTACHMENT.value discussion_id = context.matchdict['discussion_id'] user_id = context.authenticated_userid or Everyone discussion = models.Discussion.get(discussion_id) idea_id = args.get('idea_id') idea_id = int(Node.from_global_id(idea_id)[1]) in_reply_to_idea = models.Idea.get(idea_id) if isinstance(in_reply_to_idea, models.Question): cls = models.PropositionPost else: cls = models.AssemblPost extract_id = args.get('extract_id') if extract_id: extract_id_global = int(Node.from_global_id(extract_id)[1]) extract = models.Extract.get(extract_id_global) cls = models.ExtractComment in_reply_to_post = None if (cls == models.AssemblPost) or (cls == models.ExtractComment): in_reply_to_post_id = args.get('parent_id') if in_reply_to_post_id: in_reply_to_post_id = int( Node.from_global_id(in_reply_to_post_id)[1]) if in_reply_to_post_id: in_reply_to_post = models.Post.get(in_reply_to_post_id) permissions = get_permissions(user_id, discussion_id) allowed = cls.user_can_cls(user_id, CrudPermissions.CREATE, permissions) if not allowed: raise HTTPUnauthorized() with cls.default_db.no_autoflush: subject = args.get('subject') body = args.get('body') classifier = args.get('message_classifier', None) body = sanitize_html(body) body_langstring = models.LangString.create(body) publication_state = models.PublicationStates.from_string( args.get('publication_state')) if args.get( 'publication_state') in models.PublicationStates.values( ) else models.PublicationStates.PUBLISHED if subject: subject = sanitize_text(subject) subject_langstring = models.LangString.create(subject) elif issubclass(cls, models.PropositionPost): # Specific case first. Respect inheritance. Since we are using # a specific value, construct it with localization machinery. subject_langstring = models.LangString.create_localized_langstring( # noqa: E501 _('Proposal'), discussion.discussion_locales, {'fr': 'Proposition'}) else: # We apply the same logic than in views/api/post.py::create_post # noqa: E501 locale = models.Locale.UNDEFINED if in_reply_to_post and in_reply_to_post.get_title(): original_subject = in_reply_to_post.get_title( ).first_original() locale = original_subject.locale_code subject = original_subject.value elif in_reply_to_idea: # TODO: some ideas have extra langstring titles # we try to guess the locale of the body to use the same locale for post's subject body_lang, data = discussion.translation_service( ).identify(body_langstring.entries[0].value, discussion.discussion_locales) closest_subject = in_reply_to_idea.title.closest_entry( body_lang) if closest_subject: subject = closest_subject.value locale = closest_subject.locale.code else: # rather no subject than one in a random locale subject = u'' locale = discussion.main_locale else: subject = discussion.topic if discussion.topic else '' locale = discussion.main_locale if subject is not None: if in_reply_to_idea and in_reply_to_idea.message_view_override == u'messageColumns': new_subject = subject else: new_subject = u'Re: ' + restrip_pat.sub( '', subject).strip() # noqa: E501 if (in_reply_to_post and new_subject == subject and in_reply_to_post.get_title()): # reuse subject and translations subject_langstring = in_reply_to_post.get_title( ).clone(discussion.db) else: subject_langstring = models.LangString.create( new_subject, locale) if cls == models.ExtractComment: new_post = cls(discussion=discussion, subject=subject_langstring, body=body_langstring, creator_id=user_id, body_mime_type=u'text/html', message_classifier=classifier, creation_date=datetime.utcnow(), publication_state=publication_state, parent_extract_id=extract.id) else: new_post = cls(discussion=discussion, subject=subject_langstring, body=body_langstring, creator_id=user_id, body_mime_type=u'text/html', message_classifier=classifier, creation_date=datetime.utcnow(), publication_state=publication_state) new_post.guess_languages() db = new_post.db db.add(new_post) db.flush() if in_reply_to_post: new_post.set_parent(in_reply_to_post) elif in_reply_to_idea and cls != models.ExtractComment: # don't create IdeaRelatedPostLink when we have both # in_reply_to_post and in_reply_to_idea or if it's a comment # for an extract idea_post_link = models.IdeaRelatedPostLink( creator_id=user_id, content=new_post, idea=in_reply_to_idea) db.add(idea_post_link) db.flush() attachments = args.get('attachments', []) for document_id in attachments: document = models.Document.get(document_id) models.PostAttachment(document=document, discussion=discussion, creator_id=context.authenticated_userid, post=new_post, title=document.title, attachmentPurpose=EMBED_ATTACHMENT) db.flush() return CreatePost(post=new_post)