Merge "Rationalise code for filtering private Boards and Worklists"

This commit is contained in:
Zuul 2019-06-09 14:46:13 +00:00 committed by Gerrit Code Review
commit 1919d5414a
2 changed files with 37 additions and 70 deletions

View File

@ -446,64 +446,35 @@ def filter_private_worklists(query, current_user, hide_lanes=True):
are lanes in a board.
"""
# Alias all the things we're joining, in case they've been
# joined already.
board_worklists = aliased(models.BoardWorklist,
name="worklist_boardworklists")
boards = aliased(models.Board, name="worklist_boards")
board_permissions = aliased(models.board_permissions,
name="worklist_boardpermissions")
worklist_permissions = aliased(models.worklist_permissions,
name="worklist_worklistpermissions")
permissions = aliased(models.Permission, name="worklist_permissions")
user_permissions = aliased(models.user_permissions,
name="worklist_userpermissions")
users = aliased(models.User, name="worklist_users")
# Worklists permissions must be inherited from the board which
# contains the list (if any). To handle this we split the query
# into the lists which are in boards (`lanes`) and those which
# aren't (`lists`). We then either hide the lanes entirely or
# unify the two queries.
lanes = query.join(
(board_worklists, models.Worklist.id == board_worklists.list_id))
lanes = (lanes
.outerjoin((boards, boards.id == board_worklists.board_id))
.outerjoin((board_permissions,
boards.id == board_permissions.c.board_id))
.outerjoin((permissions,
permissions.id == board_permissions.c.permission_id))
.outerjoin((user_permissions,
permissions.id == user_permissions.c.permission_id))
.outerjoin((users, user_permissions.c.user_id == users.id)))
lists = query.outerjoin(
(board_worklists, models.Worklist.id == board_worklists.list_id))
lists = (lists.filter(board_worklists.board_id.is_(None))
.outerjoin((worklist_permissions,
models.Worklist.id == worklist_permissions.c.worklist_id))
.outerjoin((permissions,
permissions.id == worklist_permissions.c.permission_id))
.outerjoin((user_permissions,
user_permissions.c.permission_id == permissions.id))
.outerjoin((users, user_permissions.c.user_id == users.id)))
# Lanes inherit board permissions and ignore their own, so need to be
# handled separately. If we're not hiding all lanes from the result,
# these two queries are combined at the end.
lanes = query.filter(models.Worklist.boards.any())
lists = query.filter(~models.Worklist.boards.any())
if current_user:
if not hide_lanes:
# This removes any worklists that are related only to boards
# that the user doesn't have permission to see.
lanes = lanes.filter(
or_(
and_(
users.id == current_user,
boards.private == true()
),
boards.private == false()
models.Worklist.boards.any(
or_(
models.Board.permissions.any(
models.Permission.users.any(
models.User.id == current_user
)
),
models.Board.private == false(),
models.Board.id.is_(None)
)
)
)
lists = lists.filter(
or_(
and_(
users.id == current_user,
models.Worklist.private == true()
models.Worklist.permissions.any(
models.Permission.users.any(
models.User.id == current_user
)
),
models.Worklist.private == false(),
models.Worklist.id.is_(None)
@ -511,7 +482,16 @@ def filter_private_worklists(query, current_user, hide_lanes=True):
)
else:
if not hide_lanes:
lanes = lanes.filter(boards.private == false())
# This removes any worklists that are related to only private
# boards
lanes = lanes.filter(
models.Worklist.boards.any(
or_(
models.Board.private == false(),
models.Board.id.is_(None)
)
)
)
lists = lists.filter(
or_(
models.Worklist.private == false(),
@ -531,28 +511,13 @@ def filter_private_boards(query, current_user):
:param current_user: The ID of the user requesting the result.
"""
board_permissions = aliased(models.board_permissions,
name="board_boardpermissions")
permissions = aliased(models.Permission, name="board_permissions")
user_permissions = aliased(models.user_permissions,
name="board_userpermissions")
users = aliased(models.User, name="board_users")
query = (query
.outerjoin((board_permissions,
models.Board.id == board_permissions.c.board_id))
.outerjoin((permissions,
board_permissions.c.permission_id == permissions.id))
.outerjoin((user_permissions,
permissions.id == user_permissions.c.permission_id))
.outerjoin((users, user_permissions.c.user_id == users.id)))
if current_user:
query = query.filter(
or_(
and_(
users.id == current_user,
models.Board.private == true()
models.Board.permissions.any(
models.Permission.users.any(
models.User.id == current_user
)
),
models.Board.private == false(),
models.Board.id.is_(None)

View File

@ -614,6 +614,8 @@ class Worklist(FullText, ModelBuilder, Base):
automatic = Column(Boolean, default=False)
filters = relationship(WorklistFilter)
permissions = relationship("Permission", secondary="worklist_permissions")
boards = relationship("Board", secondary="board_worklists",
backref="worklists")
_public_fields = ["id", "title", "creator_id", "project_id",
"permission_id", "private", "archived", "automatic"]