server/users: offer more stats in user entity
This commit is contained in:
parent
aa95afb989
commit
caecaee785
7 changed files with 164 additions and 8 deletions
28
API.md
28
API.md
|
@ -1391,13 +1391,18 @@ A single user.
|
||||||
|
|
||||||
```json5
|
```json5
|
||||||
{
|
{
|
||||||
"name": <name>,
|
"name": <name>,
|
||||||
"email": <email>,
|
"email": <email>,
|
||||||
"rank": <rank>,
|
"rank": <rank>,
|
||||||
"lastLoginTime": <last-login-time>,
|
"lastLoginTime": <last-login-time>,
|
||||||
"creationTime": <creation-time>,
|
"creationTime": <creation-time>,
|
||||||
"avatarStyle": <avatar-style>,
|
"avatarStyle": <avatar-style>,
|
||||||
"avatarUrl": <avatar-url>
|
"avatarUrl": <avatar-url>,
|
||||||
|
"commentCount": <comment-count>,
|
||||||
|
"uploadedPostCount": <uploaded-post-count>,
|
||||||
|
"likedPostCount": <liked-post-count>,
|
||||||
|
"dislikedPostCount": <disliked-post-count>,
|
||||||
|
"faoritevPostCount": <favorite-post-count>
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1427,6 +1432,15 @@ A single user.
|
||||||
- `"manual"`: the user has uploaded a picture manually.
|
- `"manual"`: the user has uploaded a picture manually.
|
||||||
|
|
||||||
- `<avatarUrl>`: the URL to the avatar.
|
- `<avatarUrl>`: the URL to the avatar.
|
||||||
|
- `<comment-count>`: number of comments.
|
||||||
|
- `<uploaded-post-count>`: number of uploaded posts.
|
||||||
|
- `<liked-post-count>`: 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`.
|
||||||
|
- `<disliked-post-count>`: 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`.
|
||||||
|
- `<favorite-post-count>`: number of favorited posts.
|
||||||
|
|
||||||
## Micro user
|
## Micro user
|
||||||
**Description**
|
**Description**
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
from sqlalchemy import Column, Integer, Unicode, DateTime
|
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.base import Base
|
||||||
|
from szurubooru.db.post import Post, PostScore, PostFavorite
|
||||||
|
from szurubooru.db.comment import Comment
|
||||||
|
|
||||||
class User(Base):
|
class User(Base):
|
||||||
__tablename__ = 'user'
|
__tablename__ = 'user'
|
||||||
|
@ -25,3 +29,30 @@ class User(Base):
|
||||||
last_login_time = Column('last_login_time', DateTime)
|
last_login_time = Column('last_login_time', DateTime)
|
||||||
avatar_style = Column(
|
avatar_style = Column(
|
||||||
'avatar_style', Unicode(32), nullable=False, default=AVATAR_GRAVATAR)
|
'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))
|
||||||
|
|
|
@ -28,6 +28,16 @@ def _get_email(user, authenticated_user, force_show_email):
|
||||||
return False
|
return False
|
||||||
return user.email
|
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):
|
def serialize_user(user, authenticated_user, options=None, force_show_email=False):
|
||||||
return util.serialize_entity(
|
return util.serialize_entity(
|
||||||
user,
|
user,
|
||||||
|
@ -38,7 +48,15 @@ def serialize_user(user, authenticated_user, options=None, force_show_email=Fals
|
||||||
'lastLoginTime': lambda: user.last_login_time,
|
'lastLoginTime': lambda: user.last_login_time,
|
||||||
'avatarStyle': lambda: user.avatar_style,
|
'avatarStyle': lambda: user.avatar_style,
|
||||||
'avatarUrl': lambda: _get_avatar_url(user),
|
'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)
|
options)
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,11 @@ def test_creating_user(test_ctx, fake_datetime):
|
||||||
'name': 'chewie1',
|
'name': 'chewie1',
|
||||||
'rank': 'administrator',
|
'rank': 'administrator',
|
||||||
'email': 'asd@asd.asd',
|
'email': 'asd@asd.asd',
|
||||||
|
'commentCount': 0,
|
||||||
|
'likedPostCount': 0,
|
||||||
|
'dislikedPostCount': 0,
|
||||||
|
'favoritePostCount': 0,
|
||||||
|
'uploadedPostCount': 0,
|
||||||
}
|
}
|
||||||
user = users.get_user_by_name('chewie1')
|
user = users.get_user_by_name('chewie1')
|
||||||
assert user.name == 'chewie1'
|
assert user.name == 'chewie1'
|
||||||
|
|
|
@ -56,7 +56,15 @@ def test_retrieving_single(test_ctx):
|
||||||
'avatarUrl': 'http://gravatar.com/avatar/' +
|
'avatarUrl': 'http://gravatar.com/avatar/' +
|
||||||
'275876e34cf609db118f3d84b799a790?d=retro&s=200',
|
'275876e34cf609db118f3d84b799a790?d=retro&s=200',
|
||||||
'email': False,
|
'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):
|
def test_trying_to_retrieve_single_non_existing(test_ctx):
|
||||||
with pytest.raises(users.UserNotFoundError):
|
with pytest.raises(users.UserNotFoundError):
|
||||||
|
|
|
@ -57,6 +57,11 @@ def test_updating_user(test_ctx):
|
||||||
'email': 'asd@asd.asd',
|
'email': 'asd@asd.asd',
|
||||||
'name': 'chewie',
|
'name': 'chewie',
|
||||||
'rank': 'moderator',
|
'rank': 'moderator',
|
||||||
|
'commentCount': 0,
|
||||||
|
'likedPostCount': 0,
|
||||||
|
'dislikedPostCount': 0,
|
||||||
|
'favoritePostCount': 0,
|
||||||
|
'uploadedPostCount': 0,
|
||||||
}
|
}
|
||||||
user = users.get_user_by_name('chewie')
|
user = users.get_user_by_name('chewie')
|
||||||
assert user.name == 'chewie'
|
assert user.name == 'chewie'
|
||||||
|
|
|
@ -21,3 +21,78 @@ def test_saving_user():
|
||||||
assert user.rank == 'rank'
|
assert user.rank == 'rank'
|
||||||
assert user.creation_time == datetime(1997, 1, 1)
|
assert user.creation_time == datetime(1997, 1, 1)
|
||||||
assert user.avatar_style == db.User.AVATAR_GRAVATAR
|
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
|
||||||
|
|
Loading…
Reference in a new issue