Пример #1
0
 def test_feed_and_article_deletion(self):
     ccontr = CategoryController(2)
     cat = ccontr.read().first()
     ccontr.delete(cat.id)
     self.assertEqual(0,
                      ArticleController().read(category_id=cat.id).count())
     self.assertEqual(0, FeedController().read(category_id=cat.id).count())
Пример #2
0
 def test_cluster_same_feed(self):
     article = ArticleController().read(category_id__ne=None).first()
     cluster = article.cluster
     # all is enabled, article in cluster
     update_on_all_objs(articles=cluster.articles,
                        cluster_enabled=True,
                        cluster_same_feed=True)
     article = self.create_article_from(cluster, cluster.main_article.feed)
     self.assertInCluster(article, cluster)
     # feed's disabled, won't cluster
     FeedController().update(
         {'id__in': [a.feed_id for a in cluster.articles]},
         {'cluster_same_feed': False})
     article = self.create_article_from(cluster, cluster.main_article.feed)
     self.assertNotInCluster(article, cluster)
     # category's disabled, won't cluster
     FeedController().update(
         {'id__in': [a.feed_id for a in cluster.articles]},
         {'cluster_same_feed': None})
     CategoryController().update({'id': cluster.main_article.category.id},
                                 {'cluster_same_feed': False})
     article = self.create_article_from(cluster, cluster.main_article.feed)
     self.assertNotInCluster(article, cluster)
     # user's disable, won't cluster
     CategoryController().update({'id': cluster.main_article.category.id},
                                 {'cluster_same_feed': None})
     UserController().update({'id': cluster.user_id},
                             {'cluster_same_feed': False})
     article = self.create_article_from(cluster, cluster.main_article.feed)
     self.assertNotInCluster(article, cluster)
     # reenabling user, will cluster
     UserController().update({'id': cluster.user_id},
                             {'cluster_same_feed': True})
     article = self.create_article_from(cluster, cluster.main_article.feed)
     self.assertInCluster(article, cluster)
Пример #3
0
 def setUp(self):
     super().setUp()
     login = '******'
     self.user = UserController().get(login=login)
     self.user2 = UserController().get(login='******')
     self.fctrl = FeedController(self.user.id)
     self.cctrl = CategoryController(self.user.id)
     self.uctrl = UserController()
Пример #4
0
 def put(category_id):
     """Update an existing category."""
     cctrl = CategoryController(current_identity.id)
     attrs = parse_meaningful_params(parser_edit)
     if attrs:
         changed = cctrl.update({'id': category_id}, attrs)
         if not changed:
             cctrl.assert_right_ok(category_id)
     return None, 204
Пример #5
0
def populate_db():
    fcontr = FeedController()
    ccontr = CategoryController()
    UserController().create(
        **{
            'is_admin': True,
            'is_api': True,
            'cluster_enabled': False,
            'login': '******',
            'password': '******'
        })
    user1, user2 = [
        UserController().create(login=name,
                                cluster_enabled=False,
                                email="*****@*****.**" % name,
                                password=name) for name in ["user1", "user2"]
    ]

    for iteration in range(2):
        article_total = 0

        for user in (user1, user2):
            for iter_cat in range(3):
                cat_id = None
                if iter_cat:
                    cat_id = ccontr.create(user_id=user.id,
                                           name=to_name(
                                               user, iteration, iter_cat)).id
                feed_id = fcontr.create(
                    link="feed%d%d" % (iteration, iter_cat),
                    user_id=user.id,
                    category_id=cat_id,
                    title=to_name(user, iteration, iter_cat, iter_cat)).id
                for iter_art in range(3):
                    entry = to_name(user, iteration, iter_cat, iter_cat,
                                    iter_art)

                    tags = [
                        to_name(user, iteration, iter_cat, iter_cat, iter_art,
                                str(i)) for i in range(2)
                    ]
                    article_total += 1
                    ArticleController().create(
                        entry_id=entry,
                        link='http://test.te/%d' % article_total,
                        feed_id=feed_id,
                        user_id=user.id,
                        tags=tags,
                        category_id=cat_id,
                        title=entry,
                        date=utc_now() + timedelta(seconds=iteration),
                        content="content %d" % article_total)

    session.commit()
    session.flush()
    ClusterController().clusterize_pending_articles()
Пример #6
0
 def delete(category_id):
     """Delete an existing category."""
     try:
         CategoryController(current_identity.id).delete(category_id)
     except NotFound:
         user_id = CategoryController().get(id=category_id).user_id
         if user_id != current_identity.id:
             raise Forbidden()
         raise
     return None, 204
Пример #7
0
    def post():
        opml_file = request.files['opml_file']

        try:
            subscriptions = opml.from_string(opml_file.read())
        except Exception as error:
            raise UnprocessableEntity("Couldn't parse OPML file (%r)" % error)

        ccontr = CategoryController(current_identity.id)
        fcontr = FeedController(current_identity.id)
        counts = {'created': 0, 'existing': 0, 'failed': 0, 'exceptions': []}
        categories = {cat.name: cat.id for cat in ccontr.read()}
        for line in subscriptions:
            try:
                link = line.xmlUrl
            except Exception as error:
                counts['failed'] += 1
                counts['exceptions'].append(str(error))
                continue

            # don't import twice
            if fcontr.read(link=link).count():
                counts['existing'] += 1
                continue

            # handling categories
            cat_id = None
            category = getattr(line, 'category', '').lstrip('/')
            if category:
                if category not in categories:
                    new_category = ccontr.create(name=category)
                    categories[new_category.name] = new_category.id
                cat_id = categories[category]

            fcontr.create(title=getattr(line, 'text', None),
                          category_id=cat_id,
                          description=getattr(line, 'description', None),
                          link=link,
                          site_link=getattr(line, 'htmlUrl', None))
            counts['created'] += 1
        code = 200
        if counts.get('created'):
            code = 201
        elif counts.get('failed'):
            code = 400
        return counts, code
Пример #8
0
 def test_list_feeds(self):
     resp = self.jarr_client('get', 'list-feeds', user=self.user.login)
     fcount = FeedController(self.user.id).read().count()
     ccount = CategoryController(self.user.id).read().count()
     self.assertEqual(fcount + ccount + 1, len(resp.json))
     self.assertEqual(fcount,
                      len([r for r in resp.json if r['type'] == 'feed']))
     self.assertEqual(ccount,
                      len([r for r in resp.json if r['type'] == 'categ']))
Пример #9
0
 def update(self, filters, attrs, return_objs=False, commit=True):
     user_id = attrs.get('user_id', self.user_id)
     if 'feed_id' in attrs:
         feed = FeedController().get(id=attrs['feed_id'])
         if not (self.user_id is None or feed.user_id == user_id):
             raise Forbidden("no right on feed %r" % feed.id)
         attrs['category_id'] = feed.category_id
     if attrs.get('category_id'):
         cat = CategoryController().get(id=attrs['category_id'])
         if not (self.user_id is None or cat.user_id == user_id):
             raise Forbidden("no right on cat %r" % cat.id)
     return super().update(filters, attrs, return_objs, commit)
Пример #10
0
    def test_cluster_enabled(self):
        ccontr = ClusterController()
        cluster = ccontr.read().first()
        feed = FeedController(cluster.user_id).read(
            category_id__ne=None,
            id__nin=[art.feed_id for art in cluster.articles]).first()
        category = feed.category

        # clustering works when all is true
        update_on_all_objs(articles=cluster.articles,
                           feeds=[feed],
                           cluster_enabled=True)
        article = self.create_article_from(cluster, feed)
        self.assertInCluster(article, cluster)

        # disabling on user desactivate all clustering by default
        update_on_all_objs(articles=cluster.articles,
                           feeds=[feed],
                           cluster_enabled=None)
        UserController().update({'id': cluster.user_id},
                                {'cluster_enabled': False})
        article = self.create_article_from(cluster, feed)
        self.assertNotInCluster(article, cluster)

        # disabling on article's feed prevents from clustering
        update_on_all_objs(articles=cluster.articles,
                           feeds=[feed],
                           cluster_enabled=True)
        FeedController().update({'id': feed.id}, {'cluster_enabled': False})
        article = self.create_article_from(cluster, feed)
        self.assertNotInCluster(article, cluster)

        # disabling on feed from cluster's articles prevents from clustering
        update_on_all_objs(articles=cluster.articles,
                           feeds=[feed],
                           cluster_enabled=True)
        FeedController().update(
            {'id__in': [a.feed_id for a in cluster.articles]},
            {'cluster_enabled': False})
        article = self.create_article_from(cluster, feed)
        self.assertNotInCluster(article, cluster)

        # disabling on article's category prevents from clustering
        CategoryController(cluster.user_id).update({'id': category.id},
                                                   {'cluster_enabled': False})
        article = self.create_article_from(cluster, feed)
        self.assertNotInCluster(article, cluster)

        update_on_all_objs(articles=cluster.articles,
                           feeds=[feed],
                           cluster_enabled=True)
        article = self.create_article_from(cluster, feed)
        self.assertInCluster(article, cluster)
Пример #11
0
 def __clean_feed_fields(self, attrs):
     if attrs.get('category_id') == 0:
         attrs['category_id'] = None
     if self.user_id and attrs.get('category_id'):
         from jarr.controllers import CategoryController
         category = CategoryController().get(id=attrs['category_id'])
         if category.user_id != self.user_id:
             raise Forbidden()
     if 'filters' in attrs:
         attrs['filters'] = [
             filter_ for filter_ in (attrs['filters'] or [])
             if isinstance(filter_, dict)
         ]
Пример #12
0
 def get():
     user_id = current_identity.id
     user = UserController(user_id).get(id=user_id)
     categories = {
         cat.id: cat
         for cat in CategoryController(user_id).read()
     }
     response = make_response(
         render_template('opml.xml',
                         user=user,
                         categories=categories,
                         feeds=FeedController(user_id).read(),
                         now=utc_now()))
     for key, value in OK_GET_HEADERS.items():
         response.headers[key] = value
     return response
Пример #13
0
def update_on_all_objs(articles=None,
                       feeds=None,
                       categories=None,
                       users=None,
                       **kwargs):
    articles = articles or []
    feeds = feeds or []
    categories = categories or []
    users = users or []
    feed_ids = {a.feed_id for a in articles}.union({f.id for f in feeds})
    category_ids = {a.category_id for a in articles if a.category_id}\
            .union({f.category_id for f in feeds if f.category_id})\
            .union({c.id for c in categories})

    user_ids = {a.user_id for a in articles}\
            .union({f.user_id for f in feeds})\
            .union({c.user_id for c in categories})\
            .union({u.id for u in users})
    FeedController().update(
        {
            '__or__': [{
                'id__in': feed_ids
            }, {
                'category_id__in': category_ids
            }, {
                'user_id__in': user_ids
            }]
        }, kwargs)
    CategoryController().update(
        {'__or__': [{
            'id__in': category_ids
        }, {
            'user_id__in': user_ids
        }]}, kwargs)
    UserController().update(
        {'id__in': user_ids},
        # pushing default to user if not specifically false
        {k: v if v is not None else True
         for k, v in kwargs.items()})
Пример #14
0
 def test_no_cluster_same_category_on_original_category(self):
     article = ArticleController().read(category_id__ne=None).first()
     art_cat_id = article.category_id
     cat_ctrl = CategoryController(article.user_id)
     cluster = article.cluster
     feed = FeedController(cluster.user_id).create(title='new feed',
                                                   category_id=art_cat_id)
     update_on_all_objs(articles=cluster.articles,
                        feeds=[feed],
                        cluster_same_category=None,
                        cluster_enabled=True)
     cat_ctrl.update({'id': art_cat_id}, {'cluster_same_category': False})
     article = self.create_article_from(cluster, feed)
     self.assertNotInCluster(article, cluster)
     cat_ctrl.update({'id': art_cat_id}, {'cluster_same_category': True})
     article = self.create_article_from(cluster, feed)
     self.assertInCluster(article, cluster)
Пример #15
0
 def test_cluster_disabled_on_original_category(self):
     article = ArticleController().read(category_id__ne=None).first()
     art_cat_id = article.category_id
     cat_ctrl = CategoryController(article.user_id)
     cluster = article.cluster
     fctrl = FeedController(cluster.user_id)
     feed = fctrl.create(title='new feed', category_id=art_cat_id)
     fno_cat = fctrl.create(title='category-less')
     update_on_all_objs(users=[cluster.user], cluster_enabled=None)
     cat_ctrl.update({}, {'cluster_enabled': False})
     article = self.create_article_from(cluster, feed)
     self.assertEqual(1, len(article.cluster.articles))
     self.assertNotInCluster(article, cluster)
     article = self.create_article_from(cluster, fno_cat)
     self.assertEqual(1, len(article.cluster.articles))
     self.assertNotInCluster(article, cluster)
     cat_ctrl.update({'id': art_cat_id}, {'cluster_enabled': True})
     article = self.create_article_from(cluster, fno_cat)
     self.assertEqual(2, len(article.cluster.articles))
     self.assertInCluster(article, cluster)
     article = self.create_article_from(cluster, feed)
     self.assertEqual(3, len(article.cluster.articles))
     self.assertInCluster(article, cluster)
Пример #16
0
class OPMLTest(JarrFlaskCommon):
    def setUp(self):
        super().setUp()
        login = '******'
        self.user = UserController().get(login=login)
        self.user2 = UserController().get(login='******')
        self.fctrl = FeedController(self.user.id)
        self.cctrl = CategoryController(self.user.id)
        self.uctrl = UserController()

    def test_opml_dump_and_restore(self):
        # downloading OPML export file
        resp = self.jarr_client('get', '/opml', user=self.user.login)
        self.assertStatusCode(200, resp)
        opml_dump = resp.data.decode()
        self.assertTrue(
            opml_dump.startswith('<?xml version="1.0" encoding="utf-8"'))
        self.assertTrue(opml_dump.endswith('</opml>'))
        # cleaning db
        actrl = ArticleController(self.user.id)
        for item in actrl.read():
            actrl.delete(item.id)
        self.assertEqual(0, ClusterController(self.user.id).read().count())
        self.assertEqual(0, ArticleController(self.user.id).read().count())
        no_category_feed = []
        existing_feeds = {}
        for feed in self.fctrl.read():
            if feed.category:
                if feed.category.name in existing_feeds:
                    existing_feeds[feed.category.name].append(feed.title)
                else:
                    existing_feeds[feed.category.name] = [feed.title]
            else:
                no_category_feed.append(feed.title)

            self.fctrl.delete(feed.id)
        for category in self.cctrl.read():
            self.cctrl.delete(category.id)
        # re-importing OPML
        import_resp = self.jarr_client(
            'post',
            'opml',
            to_json=False,
            data={'opml_file': (BytesIO(resp.data), 'opml.xml')},
            headers=None,
            user=self.user.login)
        self.assertStatusCode(201, import_resp)
        self.assertEqual(0, import_resp.json['existing'])
        self.assertEqual(0, import_resp.json['failed'])
        self._check_opml_imported(existing_feeds, no_category_feed)

        import_resp = self.jarr_client(
            'post',
            'opml',
            to_json=False,
            data={'opml_file': (BytesIO(resp.data), 'opml.xml')},
            headers=None,
            user=self.user.login)
        self.assertStatusCode(200, import_resp)
        self.assertEqual(0, import_resp.json['created'])
        self.assertEqual(0, import_resp.json['failed'])

    def _check_opml_imported(self, existing_feeds, no_category_feed):
        self.assertEqual(
            sum(map(len, existing_feeds.values())) + len(no_category_feed),
            self.fctrl.read().count())
        self.assertEqual(len(existing_feeds), self.cctrl.read().count())
        for feed in self.fctrl.read():
            if feed.category:
                self.assertIn(feed.category.name, existing_feeds)
                self.assertIn(feed.title, existing_feeds[feed.category.name])
            else:
                self.assertIn(feed.title, no_category_feed)
Пример #17
0
 def post():
     """Create a new category."""
     attrs = parse_meaningful_params(parser)
     return CategoryController(current_identity.id).create(**attrs), 201
Пример #18
0
 def get():
     """List all categories with their unread counts."""
     return list(CategoryController(current_identity.id).read()), 200
Пример #19
0
 def test_feed_rights(self):
     cat = CategoryController(2).read().first()
     self.assertEqual(3,
                      ArticleController().read(category_id=cat.id).count())
     self.assertEqual(1, FeedController().read(category_id=cat.id).count())
     self._test_controller_rights(cat, UserController().get(id=cat.user_id))
Пример #20
0
 def get(category_id):
     """Read an existing category."""
     return CategoryController(current_identity.id).get(id=category_id), \
             200