Exemplo n.º 1
0
 def test_unit__delete_revision__err__nominal_case(self, admin_user,
                                                   session,
                                                   content_type_list):
     # file creation
     workspace = Workspace(label="TEST_WORKSPACE_1", owner=admin_user)
     session.add(workspace)
     session.flush()
     content = Content(
         owner=admin_user,
         workspace=workspace,
         type=content_type_list.Page.slug,
         label="TEST_CONTENT_1",
         description="TEST_CONTENT_DESCRIPTION_1",
         revision_type=ActionDescription.CREATION,
         is_deleted=False,
         is_archived=False,
     )
     session.add(content)
     session.flush()
     with new_revision(session=session,
                       tm=transaction.manager,
                       content=content):
         content.description = "TEST_CONTENT_DESCRIPTION_1_UPDATED"
     session.add(content)
     session.flush()
     session.delete(content.revisions[0])
     # Raise ContentRevisionDeleteError because revision can't be deleted
     with pytest.raises(ContentRevisionDeleteError):
         session.flush()
Exemplo n.º 2
0
    def test_unit__content_depot_file__ok__nominal_case(
            self, admin_user, session, content_type_list):
        """ Depot file access thought content property methods. """
        workspace = Workspace(label="TEST_WORKSPACE_1", owner=admin_user)
        session.add(workspace)
        session.flush()
        content = Content(
            owner=admin_user,
            workspace=workspace,
            type=content_type_list.Page.slug,
            label="TEST_CONTENT_1",
            description="TEST_CONTENT_DESCRIPTION_1",
            revision_type=ActionDescription.CREATION,
            is_deleted=False,
            is_archived=False,
        )
        session.add(content)
        session.flush()

        # tests uninitialized depot file
        assert content.depot_file is None
        # initializes depot file
        # which is able to behave like a python file object
        content.depot_file = b"test"
        # tests initialized depot file
        assert content.depot_file
        # tests type of initialized depot file
        assert type(content.depot_file) == UploadedFile
        # tests content of initialized depot file
        # using depot_file.file of type StoredFile to fetch content back
        assert content.depot_file.file.read() == b"test"
Exemplo n.º 3
0
    def test_unit__delete_revision__ok__with_unsafe_context(
            self, admin_user, session, content_type_list):

        with unprotected_content_revision(session) as unsafe_session:
            workspace = Workspace(label="TEST_WORKSPACE_1", owner=admin_user)
            unsafe_session.add(workspace)
            unsafe_session.flush()
            content = Content(
                owner=admin_user,
                workspace=workspace,
                type=content_type_list.Page.slug,
                label="TEST_CONTENT_1",
                description="TEST_CONTENT_DESCRIPTION_1",
                revision_type=ActionDescription.CREATION,
                is_deleted=False,
                is_archived=False,
            )
            unsafe_session.add(content)
            unsafe_session.flush()
            with new_revision(session=unsafe_session,
                              tm=transaction.manager,
                              content=content):
                content.description = "TEST_CONTENT_DESCRIPTION_1_UPDATED"
            unsafe_session.add(content)
            unsafe_session.flush()
            unsafe_session.delete(content.revisions[0])
            unsafe_session.flush()
Exemplo n.º 4
0
def new_revision(
    session: Session,
    tm: TransactionManager,
    content: Content,
    force_create_new_revision: bool = False,
) -> Content:
    """
    Prepare context to update a Content. It will add a new updatable revision
    to the content.
    :param session: Database _session
    :param tm: TransactionManager
    :param content: Content instance to update
    :param force_create_new_revision: Decide if new_rev should or should not
    be forced.
    :return:
    """
    with session.no_autoflush:
        try:
            if force_create_new_revision \
                    or inspect(content.revision).has_identity:
                content.new_revision()
            RevisionsIntegrity.add_to_updatable(content.revision)
            yield content
        except Exception as e:
            # INFO - GM - 14-11-2018 - rollback session and renew
            # transaction when error happened
            # This avoid bad _session data like new "temporary" revision
            # to be add when problem happen.
            session.rollback()
            tm.abort()
            tm.begin()
            raise e
        finally:
            RevisionsIntegrity.remove_from_updatable(content.revision)
Exemplo n.º 5
0
    def test_children(self, admin_user, session, app_config,
                      content_api_factory, content_type_list):
        workspace = WorkspaceApi(current_user=admin_user,
                                 session=session,
                                 config=app_config).create_workspace(
                                     "workspace_1", save_now=True)
        folder = Content(type=content_type_list.Folder.slug, owner=admin_user)
        folder.label = "folder_1"
        folder.workspace = workspace
        session.add(folder)
        session.flush()

        thread = Content(type=content_type_list.Thread.slug,
                         owner=admin_user,
                         parent=folder)
        thread.label = "thread_1"
        thread.workspace = workspace
        session.add(folder)
        session.flush()
        workspace = session.query(Workspace).filter(
            Workspace.label == "workspace_1").one()
        content_api = content_api_factory.get()
        folder = content_api.get_canonical_query().filter(
            Content.label == "folder_1").one()
        assert [folder] == list(workspace.get_valid_children())
Exemplo n.º 6
0
 def test_unit__create_content__ok__nominal_case(self, admin_user, session,
                                                 content_type_list):
     assert session.query(Workspace).filter(
         Workspace.label == "TEST_WORKSPACE_1").count() == 0
     workspace = Workspace(label="TEST_WORKSPACE_1", owner=admin_user)
     session.add(workspace)
     session.flush()
     assert session.query(Workspace).filter(
         Workspace.label == "TEST_WORKSPACE_1").count() == 1
     assert (session.query(ContentRevisionRO).filter(
         ContentRevisionRO.label == "TEST_CONTENT_1").count() == 0)
     content = Content(
         owner=admin_user,
         workspace=workspace,
         type=content_type_list.Page.slug,
         label="TEST_CONTENT_1",
         description="TEST_CONTENT_DESCRIPTION_1",
         revision_type=ActionDescription.CREATION,
         is_deleted=False,
         is_archived=False,
     )
     session.add(content)
     session.flush()
     assert (session.query(ContentRevisionRO).filter(
         ContentRevisionRO.label == "TEST_CONTENT_1").count() == 1)
     searched_content = (session.query(ContentRevisionRO).filter(
         ContentRevisionRO.label == "TEST_CONTENT_1").one())
     assert searched_content.label == content.label
Exemplo n.º 7
0
 class FakeTracimContext(TracimContext):
     current_user = User(user_id=2, email="*****@*****.**")
     current_comment = Content(
         content_id=15,
         type=content_type_list.Comment.slug,
         owner=User(user_id=3, email="*****@*****.**"),
     )
Exemplo n.º 8
0
    def test_unit__crud_caller__ok__content(self, session):
        hook = ContentHookImpl()
        session.context.plugin_manager.register(hook)

        owner = User(email="john")
        session.add(owner)
        workspace = Workspace(label="Hello", owner=owner)
        session.add(workspace)
        session.flush()

        content = Content(
            label="Foo",
            owner=owner,
            workspace=workspace,
            revision_type=ActionDescription.CREATION,
            type="html-document",
        )
        session.add(content)
        session.flush()
        hook.mock_hooks.assert_called_with("created",
                                           content=content,
                                           context=session.context)

        with new_revision(
                session=session,
                tm=transaction.manager,
                content=content,
        ):
            content.label = "Bar"

        session.add(content)
        session.flush()
        hook.mock_hooks.assert_called_with("modified",
                                           content=content,
                                           context=session.context)

        # TODO SGD 2020/05/06: add this test when deleting a Content is possible
        session.delete(content)
        session.flush()
        hook.mock_hooks.assert_called_with("deleted",
                                           content=content,
                                           context=session.context)
Exemplo n.º 9
0
    def _create_content_and_test(self, name, workspace, *args,
                                 **kwargs) -> Content:
        """
        All extra parameters (*args, **kwargs) are for Content init
        :return: Created Content instance
        """
        content = Content(*args, **kwargs)
        content.label = name
        content.workspace = workspace
        self.session.add(content)
        self.session.flush()

        content_api = ContentApi(current_user=None,
                                 session=self.session,
                                 config=self.app_config)
        eq_(
            1,
            content_api.get_canonical_query().filter(
                Content.label == name).count())
        return content_api.get_canonical_query().filter(
            Content.label == name).one()
Exemplo n.º 10
0
 def test_unit__get_allowed_content_type__ok(self, admin_user, session,
                                             content_type_list) -> None:
     workspace = Workspace(label="TEST_WORKSPACE", owner=admin_user)
     session.add(workspace)
     session.flush()
     content1 = Content(
         owner=admin_user,
         workspace=workspace,
         type=content_type_list.Page.slug,
         label="TEST_CONTENT_1",
         description="TEST_CONTENT_DESCRIPTION_1",
         revision_type=ActionDescription.CREATION,
         is_deleted=False,
         is_archived=False,
     )
     content1.properties = {"allowed_content": {"unknown_type": True}}
     try:
         assert content1.get_allowed_content_types() == []
     except ValueError:
         pytest.fail(
             "Unknown content type should not raise exception anymore "
             "when getting allowed content_type")
Exemplo n.º 11
0
    def test_unit__get_children__ok__nominal_case(sel, admin_user, session,
                                                  content_type_list):
        workspace = Workspace(label="TEST_WORKSPACE_1", owner=admin_user)
        session.add(workspace)
        session.flush()
        parent_folder = Content(
            owner=admin_user,
            workspace=workspace,
            type=content_type_list.Folder.slug,
            label="TEST_CONTENT_1",
            description="TEST_CONTENT_DESCRIPTION_1",
            revision_type=ActionDescription.CREATION,
            is_deleted=False,
            is_archived=False,
        )
        session.add(parent_folder)
        session.flush()
        assert parent_folder.children.all() == []
        children_folder = Content(
            owner=admin_user,
            workspace=workspace,
            type=content_type_list.Folder.slug,
            label="TEST_CONTENT_1",
            description="TEST_CONTENT_DESCRIPTION_1",
            revision_type=ActionDescription.CREATION,
            parent=parent_folder,
        )
        session.add(children_folder)
        session.flush()
        assert [type(child) == Content for child in parent_folder.children]
        assert [child.revision_id for child in parent_folder.children
                ] == [children_folder.cached_revision_id]

        with new_revision(session=session,
                          tm=transaction.manager,
                          content=children_folder):
            children_folder.parent = None
        session.flush()
        assert parent_folder.children.all() == []
Exemplo n.º 12
0
    def test_unit__update__err__without_prepare(self, admin_user, session,
                                                content_type_list):
        # file creation
        workspace = Workspace(label="TEST_WORKSPACE_1", owner=admin_user)
        session.add(workspace)
        session.flush()
        content = Content(
            owner=admin_user,
            workspace=workspace,
            type=content_type_list.Page.slug,
            label="TEST_CONTENT_1",
            description="TEST_CONTENT_DESCRIPTION_1",
            revision_type=ActionDescription.CREATION,
            is_deleted=False,
            is_archived=False,
        )
        session.add(content)
        session.flush()

        # file update
        with pytest.raises(ContentRevisionUpdateError):
            content.description = "FOO"
Exemplo n.º 13
0
    def delete_content(self,
                       content: Content,
                       recursively: bool = True) -> typing.List[str]:
        """
        Delete content and associated stuff:
        - all content revisions
        - all children content if recursively is True
        - all content share

        :param content: content_id to delete
        :param recursively: should we delete children content too ?
        :return: list of content_id of content(s) deleted
        """
        deleted_contents = []
        # INFO - G.M - 2019-12-11 - delete content_share
        shares = self.session.query(ContentShare).filter(
            ContentShare.content_id == content.content_id)
        for share in shares:
            logger.info(
                self, "delete share {} from content {}".format(
                    share.share_id, share.content_id))
            self.safe_delete(share)

        # INFO - G.M - 2019-12-11 - delete children of content
        if recursively:
            for children in content.get_children(recursively=recursively):
                self.delete_content(children)

        content.cached_revision_id = None
        for revision in content.revisions:
            deleted_contents.append(
                self.delete_revision(revision,
                                     do_update_content_last_revision=False))
        logger.info(self, "delete content {}".format(content.content_id))
        deleted_contents.append(content.content_id)
        self.safe_delete(content)
        return deleted_contents
Exemplo n.º 14
0
    def test_unit__workspace_get_size(self, admin_user, session,
                                      content_type_list):
        """ Depot file access thought content property methods. """
        workspace = Workspace(label="TEST_WORKSPACE_1", owner=admin_user)
        session.add(workspace)
        session.flush()
        content = Content(
            owner=admin_user,
            workspace=workspace,
            type=content_type_list.Page.slug,
            label="TEST_CONTENT_1",
            description="TEST_CONTENT_DESCRIPTION_1",
            revision_type=ActionDescription.CREATION,
            is_deleted=False,
            is_archived=False,
        )
        content.depot_file = b"test"
        session.add(content)

        assert workspace.get_size() == 4
        assert workspace.get_size(include_deleted=True) == 4
        assert workspace.get_size(include_archived=True) == 4
        with new_revision(session=session,
                          tm=transaction.manager,
                          content=content):
            content.is_deleted = True
            content.is_archived = False
        session.flush()
        transaction.commit()
        assert workspace.get_size() == 0
        assert workspace.get_size(include_deleted=True) == 8
        assert workspace.get_size(include_archived=True) == 0
        with new_revision(session=session,
                          tm=transaction.manager,
                          content=content):
            content.is_deleted = False
            content.is_archived = True
        session.flush()
        transaction.commit()
        assert workspace.get_size() == 0
        assert workspace.get_size(include_deleted=True) == 0
        assert workspace.get_size(include_archived=True) == 12
Exemplo n.º 15
0
def designThread(content: data.Content,
                 content_revision: data.ContentRevisionRO, comments) -> str:
    hist = content.get_history(drop_empty_revision=False)

    allT = []
    allT += comments
    allT += hist
    allT.sort(key=lambda x: x.created, reverse=True)

    disc = ''
    participants = {}
    for t in allT:
        if t.type == content_type_list.Comment.slug:
            disc += '''
                    <div class="row comment comment-row">
                        <i class="fa fa-comment-o comment-icon"></i>
                            <div class="comment-content">
                            <h5>
                                <span class="comment-author"><b>%s</b> wrote :</span>
                                <div class="pull-right text-right">%s</div>
                            </h5>
                            %s
                        </div>
                    </div>
                    ''' % (t.owner.display_name, create_readable_date(
                t.created), t.description)

            if t.owner.display_name not in participants:
                participants[t.owner.display_name] = [1, t.created]
            else:
                participants[t.owner.display_name][0] += 1
        else:
            if isinstance(t, VirtualEvent) and t.type.id != 'comment':
                label = _LABELS[t.type.id]

                disc += '''
                    <div class="%s row comment comment-row to-hide">
                        <i class="fa %s comment-icon"></i>
                            <div class="comment-content">
                            <h5>
                                <span class="comment-author"><b>%s</b></span>
                                <div class="pull-right text-right">%s</div>
                            </h5>
                            %s %s
                        </div>
                    </div>
                    ''' % (
                    'warning' if t.id == content_revision.revision_id else '',
                    t.type.fa_icon,
                    t.owner.display_name,
                    t.create_readable_date(),
                    label,
                    # NOTE: (WABDAV_HIST_DEL_DISABLED) Disabled for beta 1.0
                    '<i class="fa fa-caret-left"></i> shown'
                    if t.id == content_revision.revision_id else
                    ''  # else '''<span><a class="revision-link" href="/.history/%s/%s-%s">(View revision)</a></span>''' % (
                    # content.label,
                    # t.id,
                    # t.ref_object.label) if t.type.id in ['revision', 'creation', 'edition'] else '')
                )

    thread = '''
<html>
<head>
	<meta charset="utf-8" />
	<title>%s</title>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css">
	<style>%s</style>
	<script type="text/javascript" src="/home/arnaud/Documents/css/script.js"></script>
</head>
<body>
    <div id="left" class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
        <div class="title thread">
            <div class="title-text">
                <i class="fa fa-comments-o title-icon thread"></i>
                <h1>%s</h1>
                <h6>thread created on <b>%s</b> by <b>%s</b></h6>
            </div>
            <div class="pull-right">
                <div class="btn-group btn-group-vertical">
                    <!-- NOTE: Not omplemented yet, don't display not working link
                    <a class="btn btn-default" onclick="hide_elements()">
                       <i id="hideshow" class="fa fa-eye-slash"></i> <span id="hideshowtxt" >Hide history</span></a>
                    </a>-->
                    <a class="btn btn-default">
                        <i class="fa fa-external-link"></i> View in tracim</a>
                    </a>
                </div>
            </div>
        </div>
        <div class="content col-xs-12 col-sm-12 col-md-12 col-lg-12">
            <div class="description">
                <span class="description-text">%s</span>
            </div>
            %s
        </div>
    </div>
    <script type="text/javascript">
        window.onload = function() {
            file_location = window.location.href
            file_location = file_location.replace(/\/[^/]*$/, '')
            file_location = file_location.replace(/\/.history\/[^/]*$/, '')

            // NOTE: (WABDAV_HIST_DEL_DISABLED) Disabled for beta 1.0
            // $('.revision-link').each(function() {
            //     $(this).attr('href', file_location + $(this).attr('href'))
            // });
        }

        function hide_elements() {
            elems = document.getElementsByClassName('to-hide');
            if (elems.length > 0) {
                for(var i = 0; i < elems.length; i++) {
                    $(elems[i]).addClass('to-show')
                    $(elems[i]).hide();
                }
                while (elems.length>0) {
                    $(elems[0]).removeClass('comment-row');
                    $(elems[0]).removeClass('to-hide');
                }
                $('#hideshow').addClass('fa-eye').removeClass('fa-eye-slash');
                $('#hideshowtxt').html('Show history');
            }
            else {
                elems = document.getElementsByClassName('to-show');
                for(var i = 0; i<elems.length; i++) {
                    $(elems[0]).addClass('comment-row');
                    $(elems[i]).addClass('to-hide');
                    $(elems[i]).show();
                }
                while (elems.length>0) {
                    $(elems[0]).removeClass('to-show');
                }
                $('#hideshow').removeClass('fa-eye').addClass('fa-eye-slash');
                $('#hideshowtxt').html('Hide history');
            }
        }
    </script>
</body>
</html>
        ''' % (content_revision.label, style, content_revision.label,
               content.created.strftime("%B %d, %Y at %H:%m"),
               content.owner.display_name, content_revision.description, disc)

    return thread
Exemplo n.º 16
0
 def test_dummy_notifier__notify_content_update(self):
     c = Content()
     notifier = DummyNotifier(self.app_config, self.session)
     notifier.notify_content_update(c)
Exemplo n.º 17
0
 def _create_content(self, *args, **kwargs):
     content = Content(*args, **kwargs)
     self.session.add(content)
     self.session.flush()
     return content
Exemplo n.º 18
0
    def notify_content_update(self, content: Content):

        if content.get_last_action().id not \
                in self.config.EMAIL_NOTIFICATION_NOTIFIED_EVENTS:
            logger.info(
                self,
                'Skip email notification for update of content {}'
                'by user {} (the action is {})'.format(
                    content.content_id,
                    # below: 0 means "no user"
                    self._user.user_id if self._user else 0,
                    content.get_last_action().id
                )
            )
            return

        logger.info(self,
                    'About to email-notify update'
                    'of content {} by user {}'.format(
                        content.content_id,
                        # Below: 0 means "no user"
                        self._user.user_id if self._user else 0
                    )
        )

        if content.type not \
                in self.config.EMAIL_NOTIFICATION_NOTIFIED_CONTENTS:
            logger.info(
                self,
                'Skip email notification for update of content {}'
                'by user {} (the content type is {})'.format(
                    content.type,
                    # below: 0 means "no user"
                    self._user.user_id if self._user else 0,
                    content.get_last_action().id
                )
            )
            return

        logger.info(self,
                    'About to email-notify update'
                    'of content {} by user {}'.format(
                        content.content_id,
                        # Below: 0 means "no user"
                        self._user.user_id if self._user else 0
                    )
        )

        ####
        #
        # INFO - D.A. - 2014-11-05 - Emails are sent through asynchronous jobs.
        # For that reason, we do not give SQLAlchemy objects but ids only
        # (SQLA objects are related to a given thread/session)
        #
        try:
            if self.config.EMAIL_NOTIFICATION_PROCESSING_MODE.lower() == self.config.CST.ASYNC.lower():
                logger.info(self, 'Sending email in ASYNC mode')
                # TODO - D.A - 2014-11-06
                # This feature must be implemented in order to be able to scale to large communities
                raise NotImplementedError('Sending emails through ASYNC mode is not working yet')
            else:
                logger.info(self, 'Sending email in SYNC mode')
                EmailManager(
                    self._smtp_config,
                    self.config,
                    self.session,
                ).notify_content_update(self._user.user_id, content.content_id)
        except Exception as e:
            # TODO - G.M - 2018-08-27 - Do Better catching for exception here
            logger.error(self, 'Exception catched during email notification: {}'.format(e.__str__()))
            logger.exception(self, e)
Exemplo n.º 19
0
    def notify_content_update(self, content: Content):

        if content.get_last_action(
        ).id not in self.config.EMAIL__NOTIFICATION__NOTIFIED_EVENTS:
            logger.info(
                self,
                "Skip email notification for update of content {}"
                "by user {} (the action is {})".format(
                    content.content_id,
                    # below: 0 means "no user"
                    self._user.user_id if self._user else 0,
                    content.get_last_action().id,
                ),
            )
            return

        logger.info(
            self,
            "About to email-notify update"
            "of content {} by user {}".format(
                content.content_id,
                # Below: 0 means "no user"
                self._user.user_id if self._user else 0,
            ),
        )

        if content.type not in self.config.EMAIL__NOTIFICATION__NOTIFIED_CONTENTS:
            logger.info(
                self,
                "Skip email notification for update of content {}"
                "by user {} (the content type is {})".format(
                    content.type,
                    # below: 0 means "no user"
                    self._user.user_id if self._user else 0,
                    content.get_last_action().id,
                ),
            )
            return

        logger.info(
            self,
            "About to email-notify update"
            "of content {} by user {}".format(
                content.content_id,
                # Below: 0 means "no user"
                self._user.user_id if self._user else 0,
            ),
        )

        ####
        #
        # INFO - D.A. - 2014-11-05 - Emails are sent through asynchronous jobs.
        # For that reason, we do not give SQLAlchemy objects but ids only
        # (SQLA objects are related to a given thread/session)
        #
        try:
            if (self.config.EMAIL__NOTIFICATION__PROCESSING_MODE.lower() ==
                    self.config.CST.ASYNC.lower()):
                logger.info(self, "Sending email in ASYNC mode")
                # TODO - D.A - 2014-11-06
                # This feature must be implemented in order to be able to scale to large communities
                raise NotImplementedError(
                    "Sending emails through ASYNC mode is not working yet")
            else:
                logger.info(self, "Sending email in SYNC mode")
                EmailManager(self._smtp_config, self.config,
                             self.session).notify_content_update(
                                 self._user.user_id, content.content_id)
        except Exception:
            logger.exception(self,
                             "Exception catched during email notification")
Exemplo n.º 20
0
    def test_unit__update__ok__nominal_case(self, admin_user, session,
                                            content_type_list):
        workspace = Workspace(label="TEST_WORKSPACE_1", owner=admin_user)
        session.add(workspace)
        session.flush()
        with freeze_time("1999-12-31 23:59:59"):
            content = Content(
                owner=admin_user,
                workspace=workspace,
                type=content_type_list.Page.slug,
                label="TEST_CONTENT_1",
                description="TEST_CONTENT_DESCRIPTION_1",
                revision_type=ActionDescription.CREATION,
                is_deleted=False,
                is_archived=False,
            )
            # TODO - G.M - 2019-07-05 - for unknown reason freeze-time doesn't work implicitly at
            # content creation, we do override date here to have correct behaviour.
            content.updated = content.created = datetime.utcnow()
            session.add(content)
            session.flush()
            transaction.commit()
        searched_content = session.query(Content).filter(
            Content.id == content.id).one()
        assert (session.query(ContentRevisionRO).filter(
            ContentRevisionRO.label == "TEST_CONTENT_1").count() == 1)
        assert session.query(Content).filter(
            Content.id == searched_content.id).count() == 1
        with freeze_time("2000-01-01 00:00:05"):
            with new_revision(session=session,
                              tm=transaction.manager,
                              content=content):
                content.description = "TEST_CONTENT_DESCRIPTION_1_UPDATED"
            session.flush()
        assert (session.query(ContentRevisionRO).filter(
            ContentRevisionRO.label == "TEST_CONTENT_1").count() == 2)
        assert session.query(Content).filter(
            Content.id == searched_content.id).count() == 1
        with freeze_time("2003-12-31 23:59:59"):
            with new_revision(session=session,
                              tm=transaction.manager,
                              content=content):
                content.description = "TEST_CONTENT_DESCRIPTION_1_UPDATED_2"
            session.flush()
        assert (session.query(ContentRevisionRO).filter(
            ContentRevisionRO.label == "TEST_CONTENT_1").count() == 3)
        assert session.query(Content).filter(
            Content.id == searched_content.id).count() == 1

        revision_1 = (session.query(ContentRevisionRO).filter(
            ContentRevisionRO.description ==
            "TEST_CONTENT_DESCRIPTION_1").one())
        revision_2 = (session.query(ContentRevisionRO).filter(
            ContentRevisionRO.description ==
            "TEST_CONTENT_DESCRIPTION_1_UPDATED").one())
        revision_3 = (session.query(ContentRevisionRO).filter(
            ContentRevisionRO.description ==
            "TEST_CONTENT_DESCRIPTION_1_UPDATED_2").one())

        # Updated dates must be different
        assert revision_1.updated < revision_2.updated < revision_3.updated
        # Created dates must be equal
        assert revision_1.created == revision_2.created == revision_3.created
Exemplo n.º 21
0
    def test_unit__query_content__ok__nominal_case(self, admin_user, session,
                                                   content_type_list):
        workspace = Workspace(label="TEST_WORKSPACE_1", owner=admin_user)
        session.add(workspace)
        session.flush()
        workspace2 = Workspace(label="TEST_WORKSPACE_2", owner=admin_user)
        session.add(workspace2)
        session.flush()
        content1 = Content(
            owner=admin_user,
            workspace=workspace,
            type=content_type_list.Page.slug,
            label="TEST_CONTENT_1",
            description="TEST_CONTENT_DESCRIPTION_1",
            revision_type=ActionDescription.CREATION,
            is_deleted=False,
            is_archived=False,
        )
        with new_revision(session=session,
                          tm=transaction.manager,
                          content=content1):
            content1.description = "TEST_CONTENT_DESCRIPTION_1_UPDATED"
            session.add(content1)
        session.flush()
        content2 = Content(
            owner=admin_user,
            workspace=workspace2,
            type=content_type_list.Page.slug,
            label="TEST_CONTENT_2",
            description="TEST_CONTENT_DESCRIPTION_2",
            revision_type=ActionDescription.CREATION,
            is_deleted=False,
            is_archived=False,
        )
        with new_revision(session=session,
                          tm=transaction.manager,
                          content=content2):
            content2.description = "TEST_CONTENT_DESCRIPTION_2_UPDATED"
            session.add(content2)
            session.flush()

        workspace1 = session.query(Workspace).filter(
            Workspace.label == "TEST_WORKSPACE_1").one()
        workspace2 = session.query(Workspace).filter(
            Workspace.label == "TEST_WORKSPACE_2").one()

        # To get Content in database
        # we have to join Content and ContentRevisionRO
        # with particular condition:
        # Join have to be on most recent revision
        join_sub_query = (session.query(ContentRevisionRO.revision_id).filter(
            ContentRevisionRO.content_id == Content.id).order_by(
                ContentRevisionRO.revision_id.desc()).limit(1).correlate(
                    Content))

        base_query = session.query(Content).join(
            ContentRevisionRO,
            and_(
                Content.id == ContentRevisionRO.content_id,
                ContentRevisionRO.revision_id == join_sub_query,
            ),
        )

        pattern = "TEST_CONTENT_DESCRIPTION_%_UPDATED"
        assert base_query.filter(
            Content.description.like(pattern)).count() == 2

        assert base_query.filter(Content.workspace == workspace1).count() == 1
        assert base_query.filter(Content.workspace == workspace2).count() == 1

        content1_from_query = base_query.filter(
            Content.workspace == workspace1).one()
        assert content1.id == content1_from_query.id
        assert "TEST_CONTENT_DESCRIPTION_1_UPDATED" == content1_from_query.description
Exemplo n.º 22
0
 class FakeTracimContext(TracimContext):
     current_user = User(user_id=2, email='*****@*****.**')
     current_comment = Content(content_id=15,
                               type=content_type_list.Comment.slug,
                               owner=current_user)
Exemplo n.º 23
0
 class FakeTracimContext(TracimContext):
     current_content = Content(
         content_id=15,
         type='unexistent_type',
     )
Exemplo n.º 24
0
 class FakeTracimContext(TracimContext):
     current_content = Content(content_id=15,
                               type=content_type_list.Thread.slug)
Exemplo n.º 25
0
 class FakeBaseFakeTracimContext(BaseFakeTracimContext):
     current_content = Content(content_id=15, type="unexistent_type")
Exemplo n.º 26
0
def designPage(content: data.Content,
               content_revision: data.ContentRevisionRO) -> str:
    hist = content.get_history(drop_empty_revision=False)
    histHTML = '<table class="table table-striped table-hover">'
    for event in hist:
        if isinstance(event, VirtualEvent):
            date = event.create_readable_date()
            label = _LABELS[event.type.id]

            histHTML += '''
                <tr class="%s">
                    <td class="my-align"><span class="label label-default"><i class="fa %s"></i> %s</span></td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                </tr>
                ''' % (
                'warning' if event.id == content_revision.revision_id else '',
                event.type.fa_icon,
                label,
                date,
                event.owner.display_name,
                # NOTE: (WABDAV_HIST_DEL_DISABLED) Disabled for beta 1.0
                '<i class="fa fa-caret-left"></i> shown'
                if event.id == content_revision.revision_id else
                ''  # '''<span><a class="revision-link" href="/.history/%s/(%s - %s) %s.html">(View revision)</a></span>''' % (
                # content.label, event.id, event.type.id, event.ref_object.label) if event.type.id in ['revision', 'creation', 'edition'] else '')
            )
    histHTML += '</table>'

    page = '''
<html>
<head>
	<meta charset="utf-8" />
	<title>%s</title>
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css">
	<style>%s</style>
	<script type="text/javascript" src="/home/arnaud/Documents/css/script.js"></script>
	<script
			  src="https://code.jquery.com/jquery-3.1.0.min.js"
			  integrity="sha256-cCueBR6CsyA4/9szpPfrX3s49M9vUU5BgtiJj06wt/s="
			  crossorigin="anonymous"></script>
</head>
<body>
    <div id="left" class="col-lg-8 col-md-12 col-sm-12 col-xs-12">
        <div class="title page">
            <div class="title-text">
                <i class="fa fa-file-text-o title-icon page"></i>
                <h1>%s</h1>
                <h6>page created on <b>%s</b> by <b>%s</b></h6>
            </div>
            <div class="pull-right">
                <div class="btn-group btn-group-vertical">
                    <!-- NOTE: Not omplemented yet, don't display not working link
                     <a class="btn btn-default">
                         <i class="fa fa-external-link"></i> View in tracim</a>
                     </a>-->
                </div>
            </div>
        </div>
        <div class="content col-xs-12 col-sm-12 col-md-12 col-lg-12">
            %s
        </div>
    </div>
    <div id="right" class="col-lg-4 col-md-12 col-sm-12 col-xs-12">
        <h4>History</h4>
        %s
    </div>
    <script type="text/javascript">
        window.onload = function() {
            file_location = window.location.href
            file_location = file_location.replace(/\/[^/]*$/, '')
            file_location = file_location.replace(/\/.history\/[^/]*$/, '')

            // NOTE: (WABDAV_HIST_DEL_DISABLED) Disabled for beta 1.0
            // $('.revision-link').each(function() {
            //    $(this).attr('href', file_location + $(this).attr('href'))
            // });
        }
    </script>
</body>
</html>
        ''' % (content_revision.label, style, content_revision.label,
               content.created.strftime("%B %d, %Y at %H:%m"),
               content.owner.display_name, content_revision.description,
               histHTML)

    return page