예제 #1
0
    def mutate(root, args, context, info):
        RESOURCES_CENTER_HEADER_IMAGE = models.AttachmentPurpose.RESOURCES_CENTER_HEADER_IMAGE.value
        cls = models.Discussion
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        user_id = context.authenticated_userid or Everyone

        permissions = get_permissions(user_id, discussion_id)
        allowed = discussion.user_can(
            user_id, CrudPermissions.UPDATE, permissions)
        if not allowed:
            raise HTTPUnauthorized()

        with cls.default_db.no_autoflush:
            db = discussion.db
            title_entries = args.get('title_entries')
            if title_entries is not None and len(title_entries) == 0:
                raise Exception(
                    'Resources center title entries needs at least one entry')
                # Better to have this message than
                # 'NoneType' object has no attribute 'owner_object'
                # when creating the saobj below if title=None

            update_langstring_from_input_entries(
                discussion, 'resources_center_title', title_entries)

            # add uploaded image as an attachment to the discussion
            image = args.get('header_image')
            if image is not None:
                filename = os.path.basename(context.POST[image].filename)
                mime_type = context.POST[image].type
                document = models.File(
                    discussion=discussion,
                    mime_type=mime_type,
                    title=filename)
                document.add_file_data(context.POST[image].file)

                # if there is already an IMAGE, remove it with the
                # associated document
                header_images = [
                    att for att in discussion.attachments
                    if att.attachmentPurpose == RESOURCES_CENTER_HEADER_IMAGE
                ]
                if header_images:
                    header_image = header_images[0]
                    header_image.document.delete_file()
                    db.delete(header_image.document)
                    discussion.attachments.remove(header_image)

                db.add(models.DiscussionAttachment(
                    document=document,
                    discussion=discussion,
                    creator_id=context.authenticated_userid,
                    title=filename,
                    attachmentPurpose=RESOURCES_CENTER_HEADER_IMAGE
                ))

        db.flush()
        resources_center = ResourcesCenter()
        return UpdateResourcesCenter(resources_center=resources_center)
예제 #2
0
파일: post.py 프로젝트: shangxor/assembl
    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)
예제 #3
0
def create_document(value, context, discussion):
    filename = os.path.basename(context.POST[value].filename)
    mime_type = context.POST[value].type
    document = models.File(discussion=discussion,
                           mime_type=mime_type,
                           title=filename)
    document.add_file_data(context.POST[value].file)
    return document
예제 #4
0
def create_attachment(discussion, attachment_model, new_value,
                      attachment_purpose, context):
    filename = os.path.basename(context.POST[new_value].filename)
    mime_type = context.POST[new_value].type
    document = models.File(discussion=discussion,
                           mime_type=mime_type,
                           title=filename)
    document.add_file_data(context.POST[new_value].file)
    new_attachment = attachment_model(document=document,
                                      discussion=discussion,
                                      creator_id=context.authenticated_userid,
                                      title=filename,
                                      attachmentPurpose=attachment_purpose)

    return new_attachment
예제 #5
0
    def mutate(root, args, context, info):
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)

        cls = models.Document

        require_cls_permission(CrudPermissions.CREATE, cls, context)

        allowed_filetypes = aslist(
            get_config()['attachment_allowed_mime_types'])

        def is_matched_type(s):
            for mime in allowed_filetypes:
                if re.match(mime, s):
                    return True
            return False

        uploaded_file = args.get('file')
        if uploaded_file is not None:

            # Because the server is on GNU/Linux, os.path.basename will only work
            # with path using "/". Using ntpath works for both Linux and Windows path
            filename = ntpath.basename(context.POST[uploaded_file].filename)
            content = context.POST[uploaded_file].file.read()
            context.POST[uploaded_file].file.seek(0)
            filetype = magic.from_buffer(content, mime=True)

            if not is_matched_type(filetype):
                error = _('Sorry, this file type is not allowed.')
                log.warn(
                    "A MIME-TYPE of %s was uploaded. It was not found in allowed_filetypes."
                    % filetype)
                raise HTTPUnauthorized(context.localizer.translate(error))

            mime_type = context.POST[uploaded_file].type
            document = models.File(discussion=discussion,
                                   mime_type=mime_type,
                                   title=filename)
            document.add_file_data(context.POST[uploaded_file].file)
            discussion.db.add(document)
            document.db.flush()

        return UploadDocument(document=document)
예제 #6
0
    def mutate(root, args, context, info):
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)

        cls = models.Document

        require_cls_permission(CrudPermissions.CREATE, cls, context)

        uploaded_file = args.get('file')
        if uploaded_file is not None:
            filename = os.path.basename(context.POST[uploaded_file].filename)
            mime_type = context.POST[uploaded_file].type
            document = models.File(discussion=discussion,
                                   mime_type=mime_type,
                                   title=filename)
            document.add_file_data(context.POST[uploaded_file].file)
            discussion.db.add(document)
            document.db.flush()

        return UploadDocument(document=document)
예제 #7
0
def update_attachment(discussion, attachment_model, new_value, attachments,
                      attachment_purpose, db, context):
    """Update or delete attachment."""
    current_attachment = None
    if attachments:
        purposes_attachments = [
            att for att in attachments
            if att.attachmentPurpose == attachment_purpose
        ]
        if purposes_attachments:
            current_attachment = purposes_attachments[0]

    if new_value == 'TO_DELETE' and current_attachment:
        # delete the new_value
        current_attachment.document.delete_file()
        db.delete(current_attachment.document)
        db.delete(current_attachment)
        attachments.remove(current_attachment)
    elif new_value == 'TO_DELETE':
        # When the entity is set to be deleted, but does not exist, do nothing (but avoid crashing the transaction)
        return
    else:
        filename = os.path.basename(context.POST[new_value].filename)
        mime_type = context.POST[new_value].type
        document = models.File(discussion=discussion,
                               mime_type=mime_type,
                               title=filename)
        document.add_file_data(context.POST[new_value].file)
        # if there is already an attachment, remove it with the
        # associated document (image)
        if current_attachment:
            current_attachment.document.delete_file()
            db.delete(current_attachment.document)
            attachments.remove(current_attachment)

        attachment = attachment_model(document=document,
                                      discussion=discussion,
                                      creator_id=context.authenticated_userid,
                                      title=filename,
                                      attachmentPurpose=attachment_purpose)
        attachments.append(attachment)
예제 #8
0
    def mutate(root, args, context, info):
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)

        user_id = context.authenticated_userid or Everyone
        cls = models.Document
        permissions = get_permissions(user_id, discussion_id)
        allowed = cls.user_can_cls(user_id, CrudPermissions.CREATE,
                                   permissions)
        if not allowed or (allowed == IF_OWNED and user_id == Everyone):
            raise HTTPUnauthorized()

        uploaded_file = args.get('file')
        if uploaded_file is not None:
            filename = os.path.basename(context.POST[uploaded_file].filename)
            mime_type = context.POST[uploaded_file].type
            document = models.File(discussion=discussion,
                                   mime_type=mime_type,
                                   title=filename)
            document.add_file_data(context.POST[uploaded_file].file)
            discussion.db.add(document)
            document.db.flush()

        return UploadDocument(document=document)
예제 #9
0
    def mutate(root, args, context, info):
        discussion_phase_id = args.get('discussion_phase_id')
        discussion_phase = models.DiscussionPhase.get(discussion_phase_id)
        discussion_id = context.matchdict["discussion_id"]
        discussion = models.Discussion.get(discussion_id)

        if discussion_phase is None:
            raise Exception(
                "A vote session requires a discussion phase, check discussionPhaseId value"
            )
        phase_identifier = "voteSession"
        if discussion_phase.identifier != phase_identifier:
            raise Exception(
                "A vote session can only be created or edited with a '{}' discussion phase, check discussionPhaseId value"
                .format(phase_identifier))

        vote_session = discussion_phase.vote_session
        if vote_session is None:
            require_cls_permission(CrudPermissions.CREATE, models.VoteSession,
                                   context)
            vote_session = models.VoteSession(
                discussion=discussion, discussion_phase=discussion_phase)
        else:
            require_instance_permission(CrudPermissions.UPDATE, vote_session,
                                        context)

        if args.get('see_current_votes', None) is not None:
            vote_session.see_current_votes = args['see_current_votes']

        db = vote_session.db

        update_langstrings(vote_session, langstrings_defs, args)

        image = args.get('header_image')
        if image is not None:
            filename = os.path.basename(context.POST[image].filename)
            mime_type = context.POST[image].type
            ATTACHMENT_PURPOSE_IMAGE = models.AttachmentPurpose.IMAGE.value
            document = models.File(discussion=discussion,
                                   mime_type=mime_type,
                                   title=filename)
            document.add_file_data(context.POST[image].file)
            images = [
                att for att in vote_session.attachments
                if att.attachmentPurpose == ATTACHMENT_PURPOSE_IMAGE
            ]
            if images:
                image = images[0]
                image.document.delete_file()
                db.delete(image.document)
                vote_session.attachments.remove(image)
            db.add(
                models.VoteSessionAttachment(
                    document=document,
                    vote_session=vote_session,
                    discussion=discussion,
                    creator_id=context.authenticated_userid,
                    title=filename,
                    attachmentPurpose=ATTACHMENT_PURPOSE_IMAGE))

        db.add(vote_session)

        # create the root thematic on which we will attach all proposals for this vote session
        root_thematic = get_root_thematic_for_phase(discussion_phase)
        if root_thematic is None:
            root_thematic = create_root_thematic(discussion_phase)

        db.flush()
        return UpdateVoteSession(vote_session=vote_session)
예제 #10
0
    def mutate(root, args, context, info):
        EMBED_ATTACHMENT = models.AttachmentPurpose.EMBED_ATTACHMENT.value
        cls = models.Thematic
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        user_id = context.authenticated_userid or Everyone

        thematic_id = args.get('id')
        id_ = int(Node.from_global_id(thematic_id)[1])
        thematic = cls.get(id_)

        permissions = get_permissions(user_id, discussion_id)
        allowed = thematic.user_can(user_id, CrudPermissions.UPDATE,
                                    permissions)
        if not allowed:
            raise HTTPUnauthorized()

        with cls.default_db.no_autoflush:
            # introducing history at every step, including thematics + questions  # noqa: E501
            thematic.copy(tombstone=True)
            title_entries = args.get('title_entries')
            if title_entries is not None and len(title_entries) == 0:
                raise Exception(
                    'Thematic titleEntries needs at least one entry')
                # Better to have this message than
                # 'NoneType' object has no attribute 'owner_object'
                # when creating the saobj below if title=None

            update_langstring_from_input_entries(thematic, 'title',
                                                 title_entries)
            update_langstring_from_input_entries(
                thematic, 'description', args.get('description_entries'))
            kwargs = {}
            video = args.get('video', None)
            if video is not None:
                update_langstring_from_input_entries(
                    thematic, 'video_title', video.get('title_entries', []))
                update_langstring_from_input_entries(
                    thematic, 'video_description_top',
                    video.get('description_entries_top', []))
                update_langstring_from_input_entries(
                    thematic, 'video_description_bottom',
                    video.get('description_entries_bottom', []))
                update_langstring_from_input_entries(
                    thematic, 'video_description_side',
                    video.get('description_entries_side', []))
                kwargs['video_html_code'] = video.get('html_code', None)

            if args.get('identifier') is not None:
                kwargs['identifier'] = args.get('identifier')

            for attr, value in kwargs.items():
                setattr(thematic, attr, value)

            db = thematic.db

            # change order if needed
            order = args.get('order')
            if order:
                thematic.source_links[0].order = order

            # add uploaded image as an attachment to the idea
            image = args.get('image')
            if image is not None:
                if image == 'TO_DELETE' and thematic.attachments:
                    # delete the image
                    attachment = thematic.attachments[0]
                    attachment.document.delete_file()
                    db.delete(attachment.document)
                    db.delete(attachment)
                    thematic.attachments.remove(attachment)
                else:
                    filename = os.path.basename(context.POST[image].filename)
                    mime_type = context.POST[image].type
                    document = models.File(discussion=discussion,
                                           mime_type=mime_type,
                                           title=filename)
                    document.add_file_data(context.POST[image].file)
                    # if there is already an attachment, remove it with the
                    # associated document (image)
                    if thematic.attachments:
                        thematic.attachments[0].document.delete_file()
                        db.delete(thematic.attachments[0].document)
                        thematic.attachments.remove(thematic.attachments[0])

                    attachment = models.IdeaAttachment(
                        document=document,
                        discussion=discussion,
                        creator_id=context.authenticated_userid,
                        title=filename,
                        attachmentPurpose=EMBED_ATTACHMENT)
                    thematic.attachments.append(attachment)
            db.flush()

            questions_input = args.get('questions')
            existing_questions = {
                question.id: question
                for question in thematic.get_children()
            }
            updated_questions = set()
            if questions_input is not None:
                for idx, question_input in enumerate(questions_input):
                    if question_input.get('id', None) is not None:
                        id_ = int(Node.from_global_id(question_input['id'])[1])
                        updated_questions.add(id_)
                        question = models.Question.get(id_)
                        # archive the question
                        question.copy(tombstone=True)
                        update_langstring_from_input_entries(
                            question, 'title', question_input['title_entries'])
                        # modify question order
                        question.source_links[0].order = idx + 1.0
                    else:
                        title_ls = langstring_from_input_entries(
                            question_input['title_entries'])
                        question = models.Question(title=title_ls,
                                                   discussion_id=discussion_id)
                        db.add(
                            models.IdeaLink(source=thematic,
                                            target=question,
                                            order=idx + 1.0))

                # remove question (tombstone) that are not in questions_input
                for question_id in set(existing_questions.keys()).difference(
                        updated_questions):
                    existing_questions[question_id].is_tombstone = True

            db.flush()

        return UpdateThematic(thematic=thematic)
예제 #11
0
    def mutate(root, args, context, info):
        EMBED_ATTACHMENT = models.AttachmentPurpose.EMBED_ATTACHMENT.value
        cls = models.Thematic
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        user_id = context.authenticated_userid or Everyone

        permissions = get_permissions(user_id, discussion_id)
        allowed = cls.user_can_cls(user_id, CrudPermissions.CREATE,
                                   permissions)
        if not allowed or (allowed == IF_OWNED and user_id == Everyone):
            raise HTTPUnauthorized()

        identifier = args.get('identifier')
        with cls.default_db.no_autoflush:
            title_entries = args.get('title_entries')
            if len(title_entries) == 0:
                raise Exception(
                    'Thematic titleEntries needs at least one entry')
                # Better to have this message than
                # 'NoneType' object has no attribute 'owner_object'
                # when creating the saobj below if title=None

            title_langstring = langstring_from_input_entries(title_entries)
            description_langstring = langstring_from_input_entries(
                args.get('description_entries'))
            kwargs = {}
            if description_langstring is not None:
                kwargs['description'] = description_langstring

            video = args.get('video')
            if video is not None:
                video_title = langstring_from_input_entries(
                    video.get('title_entries', None))
                if video_title is not None:
                    kwargs['video_title'] = video_title

                video_description_top = langstring_from_input_entries(
                    video.get('description_entries_top', None))
                if video_description_top is not None:
                    kwargs['video_description_top'] = video_description_top

                video_description_bottom = langstring_from_input_entries(
                    video.get('description_entries_bottom', None))
                if video_description_bottom is not None:
                    kwargs[
                        'video_description_bottom'] = video_description_bottom

                video_description_side = langstring_from_input_entries(
                    video.get('description_entries_side', None))
                if video_description_side is not None:
                    kwargs['video_description_side'] = video_description_side

                video_html_code = video.get('html_code', None)
                if video_html_code is not None:
                    kwargs['video_html_code'] = video_html_code

            # Our thematic, because it inherits from Idea, needs to be
            # associated to the root idea of the discussion.
            # We create a hidden root thematic, corresponding to the
            # `identifier` phase, child of the root idea,
            # and add our thematic as a child of this root thematic.
            root_thematic = get_root_thematic_for_phase(discussion, identifier)
            if root_thematic is None:
                root_thematic = create_root_thematic(discussion, identifier)

            saobj = cls(discussion_id=discussion_id,
                        title=title_langstring,
                        identifier=identifier,
                        **kwargs)
            db = saobj.db
            db.add(saobj)
            order = len(root_thematic.get_children()) + 1.0
            db.add(
                models.IdeaLink(source=root_thematic,
                                target=saobj,
                                order=args.get('order', order)))

            # add uploaded image as an attachment to the idea
            image = args.get('image')
            if image is not None:
                filename = os.path.basename(context.POST[image].filename)
                mime_type = context.POST[image].type
                document = models.File(discussion=discussion,
                                       mime_type=mime_type,
                                       title=filename)
                document.add_file_data(context.POST[image].file)
                db.add(
                    models.IdeaAttachment(
                        document=document,
                        idea=saobj,
                        discussion=discussion,
                        creator_id=context.authenticated_userid,
                        title=filename,
                        attachmentPurpose=EMBED_ATTACHMENT))

            db.flush()

            questions_input = args.get('questions')
            if questions_input is not None:
                for idx, question_input in enumerate(questions_input):
                    title_ls = langstring_from_input_entries(
                        question_input['title_entries'])
                    question = models.Question(title=title_ls,
                                               discussion_id=discussion_id)
                    db.add(
                        models.IdeaLink(source=saobj,
                                        target=question,
                                        order=idx + 1.0))
                db.flush()

        return CreateThematic(thematic=saobj)
예제 #12
0
    def mutate(root, args, context, info):
        EMBED_ATTACHMENT = models.AttachmentPurpose.EMBED_ATTACHMENT.value
        cls = models.Idea
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        user_id = context.authenticated_userid or Everyone

        permissions = get_permissions(user_id, discussion_id)
        allowed = cls.user_can_cls(user_id, CrudPermissions.CREATE,
                                   permissions)
        if not allowed or (allowed == IF_OWNED and user_id == Everyone):
            raise HTTPUnauthorized()

        with cls.default_db.no_autoflush:
            title_entries = args.get('title_entries')
            if len(title_entries) == 0:
                raise Exception('Idea titleEntries needs at least one entry')
                # Better to have this message than
                # 'NoneType' object has no attribute 'owner_object'
                # when creating the saobj below if title=None

            title_langstring = langstring_from_input_entries(title_entries)
            description_langstring = langstring_from_input_entries(
                args.get('description_entries'))
            kwargs = {}
            if description_langstring is not None:
                kwargs['description'] = description_langstring

            parent_idea_id = args.get('parent_id')
            if parent_idea_id:
                parent_idea_id = int(Node.from_global_id(parent_idea_id)[1])
                if parent_idea_id:
                    parent_idea = models.Idea.get(parent_idea_id)
                    if not parent_idea:
                        raise Exception('Parent Idea not found')
                    if parent_idea.discussion != discussion:
                        # No cross-debate references are allowed,
                        # for security reasons
                        raise Exception(
                            'Parent Idea does not belong to this discussion'
                        )  # noqa: E501
                else:
                    raise Exception('Parent Idea not found')
            if not parent_idea_id:
                parent_idea = discussion.root_idea

            saobj = cls(discussion_id=discussion_id,
                        title=title_langstring,
                        **kwargs)
            db = saobj.db
            db.add(saobj)
            order = len(parent_idea.get_children()) + 1.0
            db.add(
                models.IdeaLink(source=parent_idea,
                                target=saobj,
                                order=args.get('order', order)))

            # add uploaded image as an attachment to the idea
            image = args.get('image')
            if image is not None:
                filename = os.path.basename(context.POST[image].filename)
                mime_type = context.POST[image].type
                document = models.File(discussion=discussion,
                                       mime_type=mime_type,
                                       title=filename)
                document.add_file_data(context.POST[image].file)
                db.add(
                    models.IdeaAttachment(
                        document=document,
                        idea=saobj,
                        discussion=discussion,
                        creator_id=context.authenticated_userid,
                        title=filename,
                        attachmentPurpose=EMBED_ATTACHMENT))

            db.flush()

        return CreateIdea(idea=saobj)
예제 #13
0
파일: user.py 프로젝트: driver4567/assembl
    def mutate(root, args, context, info):
        PROFILE_PICTURE = models.AttachmentPurpose.PROFILE_PICTURE.value
        cls = models.User
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        user_id = context.authenticated_userid or Everyone

        global_id = args.get('id')
        id_ = int(Node.from_global_id(global_id)[1])
        user = cls.get(id_)

        permissions = get_permissions(user_id, discussion_id)
        allowed = user.user_can(
            user_id, CrudPermissions.UPDATE, permissions)
        if not allowed:
            raise HTTPUnauthorized("You don't have the authorization to update this user. If you think it's an error, please reconnect to assembl.")

        with cls.default_db.no_autoflush as db:
            username = args.get('username')
            # only modify the username if it was given in parameter
            if username is not None:
                if username != user.username_p:
                    if db.query(models.Username).filter_by(
                        username=username
                    ).count():
                        raise Exception(u"001: We already have a user with this username.")

                user.username_p = username

            name = args.get('name')
            # only modify the name if it was given in parameter
            if name is not None:
                user.real_name_p = name

            old_password = args.get('old_password')
            new_password = args.get('new_password')
            new_password2 = args.get('new_password2')
            # only modify the password if it was given in parameter
            if old_password is not None and new_password is not None and new_password2 is not None:
                if not user.check_password(old_password):
                    raise Exception(u"002: The entered password doesn't match your current password.")

                if new_password != new_password2:
                    raise Exception(u"003: You entered two different passwords.")

                if old_password == new_password:
                    raise Exception(u"004: The new password has to be different than the current password.")

                try:
                    user.password_p = new_password
                except LocalizableError as e:
                    raise JSONError(e.localized_message(context.localizer))
                except Exception as e:
                    raise JSONError(str(e), code=409)

            # add uploaded image as an attachment to the user
            image = args.get('image')
            if image is not None:
                filename = os.path.basename(context.POST[image].filename)
                mime_type = context.POST[image].type
                document = models.File(
                    discussion=discussion,
                    mime_type=mime_type,
                    title=filename)
                document.add_file_data(context.POST[image].file)
                # if there is already an PROFILE_PICTURE, remove it with the
                # associated document
                images = [
                    att for att in user.profile_attachments
                    if att.attachmentPurpose == PROFILE_PICTURE]
                if images:
                    image = images[0]
                    allowed = image.user_can(
                        user_id, CrudPermissions.DELETE, permissions)
                    if not allowed:
                        raise HTTPUnauthorized("The authenticated user can't delete the existing AgentProfileAttachment")

                    image.document.delete_file()
                    db.delete(image.document)
                    user.profile_attachments.remove(image)

                allowed = models.AgentProfileAttachment.user_can_cls(
                    user_id, CrudPermissions.CREATE, permissions)
                if not allowed:
                    raise HTTPUnauthorized("The authenticated user can't create an AgentProfileAttachment")

                discussion.db.add(models.AgentProfileAttachment(
                    document=document,
                    discussion=discussion,
                    user=user,
                    creator_id=context.authenticated_userid,
                    title=filename,
                    attachmentPurpose=PROFILE_PICTURE
                ))

            db.flush()

        return UpdateUser(user=user)
예제 #14
0
    def mutate(root, args, context, info):
        ATTACHMENT_PURPOSE_IMAGE = models.AttachmentPurpose.IMAGE.value
        ATTACHMENT_PURPOSE_DOCUMENT = models.AttachmentPurpose.DOCUMENT.value
        cls = models.Resource
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        user_id = context.authenticated_userid or Everyone

        permissions = get_permissions(user_id, discussion_id)
        allowed = cls.user_can_cls(
            user_id, CrudPermissions.CREATE, permissions)
        if not allowed or (allowed == IF_OWNED and user_id == Everyone):
            raise HTTPUnauthorized()

        with cls.default_db.no_autoflush:
            title_entries = args.get('title_entries')
            if len(title_entries) == 0:
                raise Exception(
                    'Resource titleEntries needs at least one entry')
                # Better to have this message than
                # 'NoneType' object has no attribute 'owner_object'
                # when creating the saobj below if title=None

            title_langstring = langstring_from_input_entries(title_entries)
            text_langstring = langstring_from_input_entries(
                args.get('text_entries'))
            kwargs = {}
            if text_langstring is not None:
                kwargs['text'] = text_langstring

            kwargs['embed_code'] = args.get('embed_code')
            saobj = cls(
                discussion_id=discussion_id,
                title=title_langstring,
                **kwargs)
            db = saobj.db
            db.add(saobj)

            image = args.get('image')
            if image is not None:
                filename = os.path.basename(context.POST[image].filename)
                mime_type = context.POST[image].type
                document = models.File(
                    discussion=discussion,
                    mime_type=mime_type,
                    title=filename)
                document.add_file_data(context.POST[image].file)
                db.add(models.ResourceAttachment(
                    document=document,
                    resource=saobj,
                    discussion=discussion,
                    creator_id=context.authenticated_userid,
                    title=filename,
                    attachmentPurpose=ATTACHMENT_PURPOSE_IMAGE
                ))

            doc = args.get('doc')
            if doc is not None:
                filename = os.path.basename(context.POST[doc].filename)
                mime_type = context.POST[doc].type
                document = models.File(
                    discussion=discussion,
                    mime_type=mime_type,
                    title=filename)
                document.add_file_data(context.POST[doc].file)
                db.add(models.ResourceAttachment(
                    document=document,
                    resource=saobj,
                    discussion=discussion,
                    creator_id=context.authenticated_userid,
                    title=filename,
                    attachmentPurpose=ATTACHMENT_PURPOSE_DOCUMENT
                ))

            db.flush()

        return CreateResource(resource=saobj)
예제 #15
0
    def mutate(root, args, context, info):
        ATTACHMENT_PURPOSE_IMAGE = models.AttachmentPurpose.IMAGE.value
        ATTACHMENT_PURPOSE_DOCUMENT = models.AttachmentPurpose.DOCUMENT.value
        cls = models.Resource
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        user_id = context.authenticated_userid or Everyone

        resource_id = args.get('id')
        resource_id = int(Node.from_global_id(resource_id)[1])
        resource = cls.get(resource_id)

        permissions = get_permissions(user_id, discussion_id)
        allowed = resource.user_can(
            user_id, CrudPermissions.UPDATE, permissions)
        if not allowed:
            raise HTTPUnauthorized()

        with cls.default_db.no_autoflush:
            title_entries = args.get('title_entries')
            if title_entries is not None and len(title_entries) == 0:
                raise Exception(
                    'Resource titleEntries needs at least one entry')
                # Better to have this message than
                # 'NoneType' object has no attribute 'owner_object'
                # when creating the saobj below if title=None

            update_langstring_from_input_entries(
                resource, 'title', title_entries)
            update_langstring_from_input_entries(
                resource, 'text', args.get('text_entries'))
            kwargs = {}
            kwargs['embed_code'] = args.get('embed_code', None)
            for attr, value in kwargs.items():
                setattr(resource, attr, value)

            db = resource.db

            # add uploaded image as an attachment to the resource
            image = args.get('image')
            if image is not None:
                filename = os.path.basename(context.POST[image].filename)
                mime_type = context.POST[image].type
                document = models.File(
                    discussion=discussion,
                    mime_type=mime_type,
                    title=filename)
                document.add_file_data(context.POST[image].file)
                # if there is already an IMAGE, remove it with the
                # associated document
                images = [
                    att for att in resource.attachments
                    if att.attachmentPurpose == ATTACHMENT_PURPOSE_IMAGE]
                if images:
                    image = images[0]
                    image.document.delete_file()
                    db.delete(image.document)
                    resource.attachments.remove(image)

                db.add(models.ResourceAttachment(
                    document=document,
                    discussion=discussion,
                    resource=resource,
                    creator_id=context.authenticated_userid,
                    title=filename,
                    attachmentPurpose=ATTACHMENT_PURPOSE_IMAGE
                ))

        # add uploaded doc as an attachment to the resource
        doc = args.get('doc')
        if doc is not None:
            filename = os.path.basename(context.POST[doc].filename)
            mime_type = context.POST[doc].type
            document = models.File(
                discussion=discussion,
                mime_type=mime_type,
                title=filename)
            document.add_file_data(context.POST[doc].file)
            # if there is already a DOCUMENT, remove it with the
            # associated document
            docs = [
                att for att in resource.attachments
                if att.attachmentPurpose == ATTACHMENT_PURPOSE_DOCUMENT]
            if docs:
                doc = docs[0]
                doc.document.delete_file()
                db.delete(doc.document)
                resource.attachments.remove(doc)

            resource.db.add(models.ResourceAttachment(
                document=document,
                discussion=discussion,
                resource=resource,
                creator_id=context.authenticated_userid,
                title=filename,
                attachmentPurpose=ATTACHMENT_PURPOSE_DOCUMENT
            ))

            db.flush()

        return UpdateResource(resource=resource)
예제 #16
0
    def mutate(root, args, context, info):
        cls = models.Discussion
        discussion_id = context.matchdict['discussion_id']
        discussion = cls.get(discussion_id)
        user_id = context.authenticated_userid or Everyone

        permissions = get_permissions(user_id, discussion_id)
        allowed = discussion.user_can(
            user_id, CrudPermissions.UPDATE, permissions)
        if not allowed:
            raise HTTPUnauthorized()

        with cls.default_db.no_autoflush as db:
            title_entries = args.get('title_entries')
            if title_entries is not None and len(title_entries) == 0:
                raise Exception(
                    'Title entries needs at least one entry')
                # Better to have this message than
                # 'NoneType' object has no attribute 'owner_object'
                # when creating the saobj below if title=None

            update_langstring_from_input_entries(
                discussion, 'title', title_entries)

            subtitle_entries = args.get('subtitle_entries')
            update_langstring_from_input_entries(
                discussion, 'subtitle', subtitle_entries)

            button_label_entries = args.get('button_label_entries')
            update_langstring_from_input_entries(
                discussion, 'button_label', button_label_entries)

            # add uploaded header image as an attachment to the discussion
            LANDING_PAGE_HEADER_IMAGE = models.AttachmentPurpose.LANDING_PAGE_HEADER_IMAGE.value
            image = args.get('header_image')
            if image is not None:
                header_images = [
                    att for att in discussion.attachments
                    if att.attachmentPurpose == LANDING_PAGE_HEADER_IMAGE
                ]

                if image == 'TO_DELETE' and header_images:
                    header_image = header_images[0]
                    header_image.document.delete_file()
                    db.delete(header_image.document)
                    discussion.attachments.remove(header_image)
                else:
                    filename = os.path.basename(context.POST[image].filename)
                    mime_type = context.POST[image].type
                    document = models.File(
                        discussion=discussion,
                        mime_type=mime_type,
                        title=filename)
                    document.add_file_data(context.POST[image].file)

                    # if there is already an IMAGE, remove it with the
                    # associated document
                    if header_images:
                        header_image = header_images[0]
                        header_image.document.delete_file()
                        db.delete(header_image.document)
                        discussion.attachments.remove(header_image)

                    db.add(models.DiscussionAttachment(
                        document=document,
                        discussion=discussion,
                        creator_id=context.authenticated_userid,
                        title=filename,
                        attachmentPurpose=LANDING_PAGE_HEADER_IMAGE
                    ))

            # add uploaded logo image as an attachment to the discussion
            LANDING_PAGE_LOGO_IMAGE = models.AttachmentPurpose.LANDING_PAGE_LOGO_IMAGE.value
            image = args.get('logo_image')
            if image is not None:
                logo_images = [
                    att for att in discussion.attachments
                    if att.attachmentPurpose == LANDING_PAGE_LOGO_IMAGE
                ]

                if image == 'TO_DELETE' and logo_images:
                    logo_image = logo_images[0]
                    logo_image.document.delete_file()
                    db.delete(logo_image.document)
                    discussion.attachments.remove(logo_image)
                else:
                    filename = os.path.basename(context.POST[image].filename)
                    mime_type = context.POST[image].type
                    document = models.File(
                        discussion=discussion,
                        mime_type=mime_type,
                        title=filename)
                    document.add_file_data(context.POST[image].file)

                    # if there is already an IMAGE, remove it with the
                    # associated document
                    if logo_images:
                        logo_image = logo_images[0]
                        logo_image.document.delete_file()
                        db.delete(logo_image.document)
                        discussion.attachments.remove(logo_image)

                    db.add(models.DiscussionAttachment(
                        document=document,
                        discussion=discussion,
                        creator_id=context.authenticated_userid,
                        title=filename,
                        attachmentPurpose=LANDING_PAGE_LOGO_IMAGE
                    ))

        db.flush()
        discussion = cls.get(discussion_id)
        return UpdateDiscussion(discussion=discussion)
예제 #17
0
    def mutate(root, args, context, info):
        cls = models.DiscussionPhase
        phase_id = args.get('id')
        phase_id = int(Node.from_global_id(phase_id)[1])
        phase = cls.get(phase_id)
        require_instance_permission(CrudPermissions.UPDATE, phase, context)
        with cls.default_db.no_autoflush as db:
            title_entries = args.get('title_entries')
            if len(title_entries) == 0:
                raise Exception(
                    'DiscussionPhase titleEntries needs at least one entry')

            update_langstring_from_input_entries(phase, 'title', title_entries)
            description_entries = args.get('description_entries')
            if description_entries is not None:
                update_langstring_from_input_entries(phase, 'description',
                                                     description_entries)

            phase.identifier = args.get('identifier')
            phase.is_thematics_table = args.get('is_thematics_table')
            # SQLAlchemy wants naive datetimes
            phase.start = args.get('start').replace(tzinfo=None)
            phase.end = args.get('end').replace(tzinfo=None)
            phase.order = args.get('order')
            image = args.get('image')
            discussion_id = context.matchdict['discussion_id']
            discussion = models.Discussion.get(discussion_id)
            if image is not None:
                if image == 'TO_DELETE' and phase.attachments:
                    # delete the image
                    attachment = phase.attachments[0]
                    attachment.document.delete_file()
                    db.delete(attachment.document)
                    db.delete(attachment)
                    phase.attachments.remove(attachment)
                else:
                    filename = os.path.basename(context.POST[image].filename)
                    mime_type = context.POST[image].type
                    document = models.File(discussion=discussion,
                                           mime_type=mime_type,
                                           title=filename)
                    document.add_file_data(context.POST[image].file)
                    # if there is already an attachment, remove it with the
                    # associated document (image)
                    if phase.attachments:
                        for attachment in phase.attachments[:]:
                            attachment.document.delete_file()
                            db.delete(attachment.document)
                            phase.attachments.remove(attachment)

                    attachment = models.TimelineEventAttachment(
                        document=document,
                        discussion=discussion,
                        creator_id=context.authenticated_userid,
                        title=filename,
                        attachmentPurpose=models.AttachmentPurpose.IMAGE.value)
                    phase.attachments.append(attachment)

            db.flush()

        return UpdateDiscussionPhase(discussion_phase=phase)