aboutsummaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorrr-2016-04-28 19:04:44 +0200
committerrr-2016-04-28 19:04:44 +0200
commit83cc7a568d387c80a301c4e22148089c95d18e9a (patch)
tree8eb9b631e925c5e5cafbf2b6ef9c41755f7280b2 /server
parent0b20132a2f4726023fb63e8aeec0830fd9c4e827 (diff)
server/posts: add post (un)favoriting
Diffstat (limited to 'server')
-rw-r--r--server/szurubooru/api/__init__.py3
-rw-r--r--server/szurubooru/api/post_api.py17
-rw-r--r--server/szurubooru/app.py1
-rw-r--r--server/szurubooru/db/post.py13
-rw-r--r--server/szurubooru/func/favorites.py36
-rw-r--r--server/szurubooru/func/posts.py2
-rw-r--r--server/szurubooru/tests/api/test_post_favoriting.py124
-rw-r--r--server/szurubooru/tests/api/test_post_rating.py1
8 files changed, 190 insertions, 7 deletions
diff --git a/server/szurubooru/api/__init__.py b/server/szurubooru/api/__init__.py
index 9479520..fb7324b 100644
--- a/server/szurubooru/api/__init__.py
+++ b/server/szurubooru/api/__init__.py
@@ -17,7 +17,8 @@ from szurubooru.api.comment_api import (
from szurubooru.api.post_api import (
PostDetailApi,
PostFeatureApi,
- PostScoreApi)
+ PostScoreApi,
+ PostFavoriteApi)
from szurubooru.api.snapshot_api import SnapshotListApi
from szurubooru.api.info_api import InfoApi
from szurubooru.api.context import Context, Request
diff --git a/server/szurubooru/api/post_api.py b/server/szurubooru/api/post_api.py
index 0c08e82..df1c32e 100644
--- a/server/szurubooru/api/post_api.py
+++ b/server/szurubooru/api/post_api.py
@@ -1,5 +1,5 @@
from szurubooru.api.base_api import BaseApi
-from szurubooru.func import auth, tags, posts, snapshots, scores
+from szurubooru.func import auth, tags, posts, snapshots, favorites, scores
class PostDetailApi(BaseApi):
def get(self, ctx, post_id):
@@ -51,3 +51,18 @@ class PostScoreApi(BaseApi):
scores.delete_score(post, ctx.user)
ctx.session.commit()
return posts.serialize_post_with_details(post, ctx.user)
+
+class PostFavoriteApi(BaseApi):
+ def post(self, ctx, post_id):
+ auth.verify_privilege(ctx.user, 'posts:favorite')
+ post = posts.get_post_by_id(post_id)
+ favorites.set_favorite(post, ctx.user)
+ ctx.session.commit()
+ return posts.serialize_post_with_details(post, ctx.user)
+
+ def delete(self, ctx, post_id):
+ auth.verify_privilege(ctx.user, 'posts:favorite')
+ post = posts.get_post_by_id(post_id)
+ favorites.unset_favorite(post, ctx.user)
+ ctx.session.commit()
+ return posts.serialize_post_with_details(post, ctx.user)
diff --git a/server/szurubooru/app.py b/server/szurubooru/app.py
index 6a459f6..85ccda8 100644
--- a/server/szurubooru/app.py
+++ b/server/szurubooru/app.py
@@ -67,6 +67,7 @@ def create_app():
app.add_route('/post/{post_id}', api.PostDetailApi())
app.add_route('/post/{post_id}/score', api.PostScoreApi())
+ app.add_route('/post/{post_id}/favorite', api.PostFavoriteApi())
app.add_route('/comments/', api.CommentListApi())
app.add_route('/comment/{comment_id}', api.CommentDetailApi())
diff --git a/server/szurubooru/db/post.py b/server/szurubooru/db/post.py
index 4d8deb0..8d6b496 100644
--- a/server/szurubooru/db/post.py
+++ b/server/szurubooru/db/post.py
@@ -128,6 +128,16 @@ class Post(Base):
.filter(PostScore.post_id == self.post_id) \
.one()[0] or 0
+ favorite_count = column_property(
+ select([func.count(PostFavorite.post_id)]) \
+ .where(PostFavorite.post_id == post_id) \
+ .correlate_except(PostFavorite))
+
+ last_favorite_time = column_property(
+ select([func.max(PostFavorite.time)]) \
+ .where(PostFavorite.post_id == post_id) \
+ .correlate_except(PostFavorite))
+
feature_count = column_property(
select([func.count(PostFeature.post_id)]) \
.where(PostFeature.post_id == post_id) \
@@ -139,11 +149,8 @@ class Post(Base):
.correlate_except(PostFeature))
# TODO: wire these
- #favorite_count = Column('auto_fav_count', Integer, nullable=False, default=0)
#comment_count = Column('auto_comment_count', Integer, nullable=False, default=0)
#note_count = Column('auto_note_count', Integer, nullable=False, default=0)
- #last_fav_time = Column(
- # 'auto_fav_time', Integer, nullable=False, default=0)
#last_comment_edit_time = Column(
# 'auto_comment_creation_time', Integer, nullable=False, default=0)
#last_comment_creation_time = Column(
diff --git a/server/szurubooru/func/favorites.py b/server/szurubooru/func/favorites.py
new file mode 100644
index 0000000..9c3dda7
--- /dev/null
+++ b/server/szurubooru/func/favorites.py
@@ -0,0 +1,36 @@
+import datetime
+from szurubooru import db
+from szurubooru.func import util
+
+def _get_table_info(entity):
+ resource_type, _, _ = util.get_resource_info(entity)
+ if resource_type == 'post':
+ return db.PostFavorite, lambda table: table.post_id
+ else:
+ assert False
+
+def _get_fav_entity(entity, user):
+ table, get_column = _get_table_info(entity)
+ return db.session \
+ .query(table) \
+ .filter(get_column(table) == get_column(entity)) \
+ .filter(table.user_id == user.user_id) \
+ .one_or_none()
+
+def has_favorited(entity, user):
+ return _get_fav_entity(entity, user) is not None
+
+def unset_favorite(entity, user):
+ fav_entity = _get_fav_entity(entity, user)
+ if fav_entity:
+ db.session.delete(fav_entity)
+
+def set_favorite(entity, user):
+ fav_entity = _get_fav_entity(entity, user)
+ if not fav_entity:
+ table, get_column = _get_table_info(entity)
+ fav_entity = table()
+ setattr(fav_entity, get_column(table).name, get_column(entity))
+ fav_entity.user = user
+ fav_entity.time = datetime.datetime.now()
+ db.session.add(fav_entity)
diff --git a/server/szurubooru/func/posts.py b/server/szurubooru/func/posts.py
index 3a3f7a3..7e1524a 100644
--- a/server/szurubooru/func/posts.py
+++ b/server/szurubooru/func/posts.py
@@ -32,7 +32,7 @@ def serialize_post(post, authenticated_user):
'score': post.score,
'featureCount': post.feature_count,
'lastFeatureTime': post.last_feature_time,
- 'favoritedBy': [users.serialize_user(rel, authenticated_user) \
+ 'favoritedBy': [users.serialize_user(rel.user, authenticated_user) \
for rel in post.favorited_by],
}
diff --git a/server/szurubooru/tests/api/test_post_favoriting.py b/server/szurubooru/tests/api/test_post_favoriting.py
new file mode 100644
index 0000000..53ed660
--- /dev/null
+++ b/server/szurubooru/tests/api/test_post_favoriting.py
@@ -0,0 +1,124 @@
+import datetime
+import pytest
+from szurubooru import api, db, errors
+from szurubooru.func import util, posts
+
+@pytest.fixture
+def test_ctx(config_injector, context_factory, user_factory, post_factory):
+ config_injector({
+ 'ranks': ['anonymous', 'regular_user'],
+ 'rank_names': {'anonymous': 'Peasant', 'regular_user': 'Lord'},
+ 'privileges': {'posts:favorite': 'regular_user'},
+ 'thumbnails': {'avatar_width': 200},
+ })
+ db.session.flush()
+ ret = util.dotdict()
+ ret.context_factory = context_factory
+ ret.user_factory = user_factory
+ ret.post_factory = post_factory
+ ret.api = api.PostFavoriteApi()
+ return ret
+
+def test_simple_rating(test_ctx, fake_datetime):
+ post = test_ctx.post_factory()
+ db.session.add(post)
+ db.session.commit()
+ with fake_datetime('1997-12-01'):
+ result = test_ctx.api.post(
+ test_ctx.context_factory(user=test_ctx.user_factory()),
+ post.post_id)
+ assert 'post' in result
+ assert 'id' in result['post']
+ post = db.session.query(db.Post).one()
+ assert db.session.query(db.PostFavorite).count() == 1
+ assert post is not None
+ assert post.favorite_count == 1
+
+def test_removing_from_favorites(test_ctx, fake_datetime):
+ user = test_ctx.user_factory()
+ post = test_ctx.post_factory()
+ db.session.add(post)
+ db.session.commit()
+ with fake_datetime('1997-12-01'):
+ result = test_ctx.api.post(
+ test_ctx.context_factory(user=user),
+ post.post_id)
+ with fake_datetime('1997-12-02'):
+ result = test_ctx.api.delete(
+ test_ctx.context_factory(user=user),
+ post.post_id)
+ post = db.session.query(db.Post).one()
+ assert db.session.query(db.PostFavorite).count() == 0
+ assert post.favorite_count == 0
+
+def test_favoriting_twice(test_ctx, fake_datetime):
+ user = test_ctx.user_factory()
+ post = test_ctx.post_factory()
+ db.session.add(post)
+ db.session.commit()
+ with fake_datetime('1997-12-01'):
+ result = test_ctx.api.post(
+ test_ctx.context_factory(user=user),
+ post.post_id)
+ with fake_datetime('1997-12-02'):
+ result = test_ctx.api.post(
+ test_ctx.context_factory(user=user),
+ post.post_id)
+ post = db.session.query(db.Post).one()
+ assert db.session.query(db.PostFavorite).count() == 1
+ assert post.favorite_count == 1
+
+def test_removing_twice(test_ctx, fake_datetime):
+ user = test_ctx.user_factory()
+ post = test_ctx.post_factory()
+ db.session.add(post)
+ db.session.commit()
+ with fake_datetime('1997-12-01'):
+ result = test_ctx.api.post(
+ test_ctx.context_factory(user=user),
+ post.post_id)
+ with fake_datetime('1997-12-02'):
+ result = test_ctx.api.delete(
+ test_ctx.context_factory(user=user),
+ post.post_id)
+ with fake_datetime('1997-12-02'):
+ result = test_ctx.api.delete(
+ test_ctx.context_factory(user=user),
+ post.post_id)
+ post = db.session.query(db.Post).one()
+ assert db.session.query(db.PostFavorite).count() == 0
+ assert post.favorite_count == 0
+
+def test_favorites_from_multiple_users(test_ctx, fake_datetime):
+ user1 = test_ctx.user_factory()
+ user2 = test_ctx.user_factory()
+ post = test_ctx.post_factory()
+ db.session.add_all([user1, user2, post])
+ db.session.commit()
+ with fake_datetime('1997-12-01'):
+ result = test_ctx.api.post(
+ test_ctx.context_factory(user=user1),
+ post.post_id)
+ with fake_datetime('1997-12-02'):
+ result = test_ctx.api.post(
+ test_ctx.context_factory(user=user2),
+ post.post_id)
+ post = db.session.query(db.Post).one()
+ assert db.session.query(db.PostFavorite).count() == 2
+ assert post.favorite_count == 2
+ assert post.last_favorite_time == datetime.datetime(1997, 12, 2)
+
+def test_trying_to_update_non_existing(test_ctx):
+ with pytest.raises(posts.PostNotFoundError):
+ test_ctx.api.post(
+ test_ctx.context_factory(user=test_ctx.user_factory()), 5)
+
+def test_trying_to_rate_without_privileges(test_ctx):
+ post = test_ctx.post_factory()
+ db.session.add(post)
+ db.session.commit()
+ with pytest.raises(errors.AuthError):
+ test_ctx.api.post(
+ test_ctx.context_factory(
+ user=test_ctx.user_factory(rank='anonymous')),
+ post.post_id)
diff --git a/server/szurubooru/tests/api/test_post_rating.py b/server/szurubooru/tests/api/test_post_rating.py
index 26e01db..65486e5 100644
--- a/server/szurubooru/tests/api/test_post_rating.py
+++ b/server/szurubooru/tests/api/test_post_rating.py
@@ -1,4 +1,3 @@
-import datetime
import pytest
from szurubooru import api, db, errors
from szurubooru.func import util, posts, scores

© 2015 - 2026 Jakob L. Kreuze