From caecaee7856a818cc0ee45dc45a335a3b3a25af6 Mon Sep 17 00:00:00 2001 From: rr- Date: Fri, 3 Jun 2016 21:18:17 +0200 Subject: [PATCH] server/users: offer more stats in user entity --- API.md | 28 +++++-- server/szurubooru/db/user.py | 31 ++++++++ server/szurubooru/func/users.py | 20 ++++- .../tests/api/test_user_creating.py | 5 ++ .../tests/api/test_user_retrieving.py | 8 ++ .../tests/api/test_user_updating.py | 5 ++ server/szurubooru/tests/db/test_user.py | 75 +++++++++++++++++++ 7 files changed, 164 insertions(+), 8 deletions(-) diff --git a/API.md b/API.md index 1257c14..1a6a6d9 100644 --- a/API.md +++ b/API.md @@ -1391,13 +1391,18 @@ A single user. ```json5 { - "name": , - "email": , - "rank": , - "lastLoginTime": , - "creationTime": , - "avatarStyle": , - "avatarUrl": + "name": , + "email": , + "rank": , + "lastLoginTime": , + "creationTime": , + "avatarStyle": , + "avatarUrl": , + "commentCount": , + "uploadedPostCount": , + "likedPostCount": , + "dislikedPostCount": , + "faoritevPostCount": } ``` @@ -1427,6 +1432,15 @@ A single user. - `"manual"`: the user has uploaded a picture manually. - ``: the URL to the avatar. +- ``: number of comments. +- ``: number of uploaded posts. +- ``: nubmer of liked posts. It is available only if the + request is authenticated by the same user. If it's unavailable, the server + returns `false`. +- ``: number of disliked posts. It is available only if + the request is authenticated by the same user. If it's unavailable, the + server returns `false`. +- ``: number of favorited posts. ## Micro user **Description** diff --git a/server/szurubooru/db/user.py b/server/szurubooru/db/user.py index 502deb7..706f4df 100644 --- a/server/szurubooru/db/user.py +++ b/server/szurubooru/db/user.py @@ -1,5 +1,9 @@ from sqlalchemy import Column, Integer, Unicode, DateTime +from sqlalchemy.orm import column_property +from sqlalchemy.sql.expression import func, select from szurubooru.db.base import Base +from szurubooru.db.post import Post, PostScore, PostFavorite +from szurubooru.db.comment import Comment class User(Base): __tablename__ = 'user' @@ -25,3 +29,30 @@ class User(Base): last_login_time = Column('last_login_time', DateTime) avatar_style = Column( 'avatar_style', Unicode(32), nullable=False, default=AVATAR_GRAVATAR) + + post_count = column_property( + select([func.coalesce(func.count(1), 0)]) \ + .where(Post.user_id == user_id) \ + .correlate_except(Post)) + + comment_count = column_property( + select([func.coalesce(func.count(1), 0)]) \ + .where(Comment.user_id == user_id) \ + .correlate_except(Comment)) + + favorite_post_count = column_property( + select([func.coalesce(func.count(1), 0)]) \ + .where(PostFavorite.user_id == user_id) \ + .correlate_except(PostFavorite)) + + liked_post_count = column_property( + select([func.coalesce(func.count(1), 0)]) \ + .where(PostScore.user_id == user_id) \ + .where(PostScore.score == 1) \ + .correlate_except(PostScore)) + + disliked_post_count = column_property( + select([func.coalesce(func.count(1), 0)]) \ + .where(PostScore.user_id == user_id) \ + .where(PostScore.score == -1) \ + .correlate_except(PostScore)) diff --git a/server/szurubooru/func/users.py b/server/szurubooru/func/users.py index d5e7b11..a85adae 100644 --- a/server/szurubooru/func/users.py +++ b/server/szurubooru/func/users.py @@ -28,6 +28,16 @@ def _get_email(user, authenticated_user, force_show_email): return False return user.email +def _get_liked_post_count(user, authenticated_user): + if authenticated_user.user_id != user.user_id: + return False + return user.liked_post_count + +def _get_disliked_post_count(user, authenticated_user): + if authenticated_user.user_id != user.user_id: + return False + return user.disliked_post_count + def serialize_user(user, authenticated_user, options=None, force_show_email=False): return util.serialize_entity( user, @@ -38,7 +48,15 @@ def serialize_user(user, authenticated_user, options=None, force_show_email=Fals 'lastLoginTime': lambda: user.last_login_time, 'avatarStyle': lambda: user.avatar_style, 'avatarUrl': lambda: _get_avatar_url(user), - 'email': lambda: _get_email(user, authenticated_user, force_show_email), + 'commentCount': lambda: user.comment_count, + 'uploadedPostCount': lambda: user.post_count, + 'favoritePostCount': lambda: user.favorite_post_count, + 'likedPostCount': + lambda: _get_liked_post_count(user, authenticated_user), + 'dislikedPostCount': + lambda: _get_disliked_post_count(user, authenticated_user), + 'email': + lambda: _get_email(user, authenticated_user, force_show_email), }, options) diff --git a/server/szurubooru/tests/api/test_user_creating.py b/server/szurubooru/tests/api/test_user_creating.py index c512b8b..e70f660 100644 --- a/server/szurubooru/tests/api/test_user_creating.py +++ b/server/szurubooru/tests/api/test_user_creating.py @@ -43,6 +43,11 @@ def test_creating_user(test_ctx, fake_datetime): 'name': 'chewie1', 'rank': 'administrator', 'email': 'asd@asd.asd', + 'commentCount': 0, + 'likedPostCount': 0, + 'dislikedPostCount': 0, + 'favoritePostCount': 0, + 'uploadedPostCount': 0, } user = users.get_user_by_name('chewie1') assert user.name == 'chewie1' diff --git a/server/szurubooru/tests/api/test_user_retrieving.py b/server/szurubooru/tests/api/test_user_retrieving.py index 4058916..e2ddce7 100644 --- a/server/szurubooru/tests/api/test_user_retrieving.py +++ b/server/szurubooru/tests/api/test_user_retrieving.py @@ -56,7 +56,15 @@ def test_retrieving_single(test_ctx): 'avatarUrl': 'http://gravatar.com/avatar/' + '275876e34cf609db118f3d84b799a790?d=retro&s=200', 'email': False, + 'commentCount': 0, + 'likedPostCount': False, + 'dislikedPostCount': False, + 'favoritePostCount': 0, + 'uploadedPostCount': 0, } + assert result['email'] is False + assert result['likedPostCount'] is False + assert result['dislikedPostCount'] is False def test_trying_to_retrieve_single_non_existing(test_ctx): with pytest.raises(users.UserNotFoundError): diff --git a/server/szurubooru/tests/api/test_user_updating.py b/server/szurubooru/tests/api/test_user_updating.py index 1e8cafa..2cb449f 100644 --- a/server/szurubooru/tests/api/test_user_updating.py +++ b/server/szurubooru/tests/api/test_user_updating.py @@ -57,6 +57,11 @@ def test_updating_user(test_ctx): 'email': 'asd@asd.asd', 'name': 'chewie', 'rank': 'moderator', + 'commentCount': 0, + 'likedPostCount': 0, + 'dislikedPostCount': 0, + 'favoritePostCount': 0, + 'uploadedPostCount': 0, } user = users.get_user_by_name('chewie') assert user.name == 'chewie' diff --git a/server/szurubooru/tests/db/test_user.py b/server/szurubooru/tests/db/test_user.py index 1a38cd0..6168b74 100644 --- a/server/szurubooru/tests/db/test_user.py +++ b/server/szurubooru/tests/db/test_user.py @@ -21,3 +21,78 @@ def test_saving_user(): assert user.rank == 'rank' assert user.creation_time == datetime(1997, 1, 1) assert user.avatar_style == db.User.AVATAR_GRAVATAR + +def test_upload_count(user_factory, post_factory): + user = user_factory() + db.session.add(user) + db.session.flush() + assert user.post_count == 0 + post1 = post_factory() + post1.user = user + post2 = post_factory() + db.session.add_all([post1, post2]) + db.session.flush() + db.session.refresh(user) + assert user.post_count == 1 + +def test_comment_count(user_factory, comment_factory): + user = user_factory() + db.session.add(user) + db.session.flush() + assert user.comment_count == 0 + db.session.add_all([ + comment_factory(user=user), + comment_factory(), + ]) + db.session.flush() + db.session.refresh(user) + assert user.comment_count == 1 + +def test_favorite_count(user_factory, post_factory): + user = user_factory() + db.session.add(user) + db.session.flush() + assert user.comment_count == 0 + post1 = post_factory() + post2 = post_factory() + db.session.add_all([ + db.PostFavorite(post=post1, time=datetime.now(), user=user), + db.PostFavorite(post=post2, time=datetime.now(), user=user_factory()), + ]) + db.session.flush() + db.session.refresh(user) + assert user.favorite_post_count == 1 + +def test_liked_post_count(user_factory, post_factory): + user = user_factory() + db.session.add(user) + db.session.flush() + assert user.liked_post_count == 0 + assert user.disliked_post_count == 0 + post1 = post_factory() + post2 = post_factory() + db.session.add_all([ + db.PostScore(post=post1, time=datetime.now(), user=user, score=1), + db.PostScore(post=post2, time=datetime.now(), user=user_factory(), score=1), + ]) + db.session.flush() + db.session.refresh(user) + assert user.liked_post_count == 1 + assert user.disliked_post_count == 0 + +def test_disliked_post_count(user_factory, post_factory): + user = user_factory() + db.session.add(user) + db.session.flush() + assert user.liked_post_count == 0 + assert user.disliked_post_count == 0 + post1 = post_factory() + post2 = post_factory() + db.session.add_all([ + db.PostScore(post=post1, time=datetime.now(), user=user, score=-1), + db.PostScore(post=post2, time=datetime.now(), user=user_factory(), score=1), + ]) + db.session.flush() + db.session.refresh(user) + assert user.liked_post_count == 0 + assert user.disliked_post_count == 1