WIP: Response visibility calculation

This commit is contained in:
2018-07-17 09:30:11 +02:00
parent b9c037f914
commit 69a1efcd93
2 changed files with 295 additions and 0 deletions

View File

@@ -123,6 +123,39 @@ EVENT_VISIBILITY_TRANSLATIONS = {
}
class ResponseVisibility(Enum):
"""Enumeration for response visibility
"""
#: The response is only visible to the invitee
private = 0
#: The response is only visible to the event organisers
organisers = 1
#: The response is only visible to the event attendees
attendees = 2
#: The response is visible to the invitees friends (ie. mutual follows)
friends = 3
#: The response is visible to the invitees followers
followers = 4
#: The response is visible to anyone
public = 5
RESPONSE_VISIBILITY_TRANSLATIONS = {
ResponseVisibility.private: _('Visible only to myself'),
ResponseVisibility.organisers: _('Visible only to event organisers'),
ResponseVisibility.attendees: _('Visible only to event attendees'),
ResponseVisibility.friends: _('Visible only to my friends'),
ResponseVisibility.followers: _('Visible only to my followers'),
ResponseVisibility.public: _('Visible to anyone'),
}
class SettingsProxy:
"""Proxy object to get settings for a user
"""
@@ -404,6 +437,45 @@ class Profile(db.Model): # pylint: disable=too-few-public-methods
return notification
def is_following(self, profile):
"""Check if this profile is following ``profile``
"""
try:
UserFollow.query.filter(UserFollow.follower == self).filter(UserFollow.followed == profile).one()
except NoResultFound:
return False
return True
def is_friend_of(self, profile):
"""Check if this profile is friends with ``profile``
"""
reverse = db.aliased(UserFollow)
try:
UserFollow.query \
.filter(UserFollow.follower == self) \
.join(reverse, UserFollow.followed_id == reverse.follower_id) \
.filter(UserFollow.follower_id == reverse.followed_id) \
.one()
except NoResultFound:
return False
return True
def is_attending(self, event):
"""Check if this profile is attending ``event``
"""
try:
Response.query.filter(Response.profile == self).filter(Response.event == event).one()
except NoResultFound:
return False
return True
class Event(db.Model):
"""Database model for events
@@ -791,6 +863,54 @@ class Response(db.Model): # pylint: disable=too-few-public-methods
#: The response itself
response = db.Column(db.Enum(ResponseType), nullable=False)
#: The visibility of the response
visibility = db.Column(db.Enum(ResponseVisibility), nullable=False)
def visible_to(self, profile):
"""Checks if the response can be visible to ``profile``.
:param profile: the profile looking at the response. If None, it is viewed as anonymous
:type profile: Profile, None
:returns: ``True`` if the response should be visible, ``False`` otherwise
:rtype: bool
"""
if self.profile == profile:
return True
if self.visibility == ResponseVisibility.private:
return False
if self.visibility == ResponseVisibility.organisers:
return profile == self.event.profile
if self.visibility == ResponseVisibility.attendees:
return profile is not None and \
(profile.is_attending(self.event) or \
profile == self.event.profile)
# From this point on, if the event is not public, only attendees can see responses
if self.event.visibility != EventVisibility.public:
return profile is not None and \
(profile.is_attending(self.event) or
profile == self.event.profile)
if self.visibility == ResponseVisibility.friends:
return profile is not None and \
(profile.is_friend_of(self.profile) or \
profile.is_attending(self.event) or \
profile == self.event.profile or \
profile == self.profile)
if self.visibility == ResponseVisibility.followers:
return profile is not None and \
(profile.is_following(self.profile) or \
profile.is_attending(self.event) or \
profile == self.event.profile or \
profile == self.profile)
return self.visibility == ResponseVisibility.public
class AppState(app_state_base(db.Model)): # pylint: disable=too-few-public-methods
"""Database model for application state values