workspace.py 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. # -*- coding: utf-8 -*-
  2. import typing
  3. from sqlalchemy.orm import Query
  4. from tg.i18n import ugettext as _
  5. import transaction
  6. from tracim.lib.userworkspace import RoleApi
  7. from tracim.model import DBSession
  8. from tracim.model.auth import Group
  9. from tracim.model.auth import User
  10. from tracim.model.data import UserRoleInWorkspace
  11. from tracim.model.data import Workspace
  12. __author__ = 'damien'
  13. class WorkspaceApi(object):
  14. def __init__(self, current_user: User, force_role: bool=False):
  15. """
  16. :param current_user: Current user of context
  17. :param force_role: If True, app role in queries even if admin
  18. """
  19. self._user = current_user
  20. self._force_role = force_role
  21. def _base_query_without_roles(self):
  22. return DBSession.query(Workspace).filter(Workspace.is_deleted==False)
  23. def _base_query(self):
  24. if not self._force_role and self._user.profile.id>=Group.TIM_ADMIN:
  25. return self._base_query_without_roles()
  26. return DBSession.query(Workspace).\
  27. join(Workspace.roles).\
  28. filter(UserRoleInWorkspace.user_id == self._user.user_id).\
  29. filter(Workspace.is_deleted == False)
  30. def create_workspace(
  31. self,
  32. label: str='',
  33. description: str='',
  34. calendar_enabled: bool=False,
  35. save_now: bool=False,
  36. ) -> Workspace:
  37. if not label:
  38. label = self.generate_label()
  39. workspace = Workspace()
  40. workspace.label = label
  41. workspace.description = description
  42. workspace.calendar_enabled = calendar_enabled
  43. # By default, we force the current user to be the workspace manager
  44. # And to receive email notifications
  45. role = RoleApi(self._user).create_one(self._user, workspace,
  46. UserRoleInWorkspace.WORKSPACE_MANAGER,
  47. with_notif=True)
  48. DBSession.add(workspace)
  49. DBSession.add(role)
  50. if save_now:
  51. DBSession.flush()
  52. if calendar_enabled:
  53. self.ensure_calendar_exist(workspace)
  54. else:
  55. self.disable_calendar(workspace)
  56. return workspace
  57. def get_one(self, id):
  58. return self._base_query().filter(Workspace.workspace_id==id).one()
  59. def get_one_by_label(self, label: str) -> Workspace:
  60. return self._base_query().filter(Workspace.label == label).one()
  61. """
  62. def get_one_for_current_user(self, id):
  63. return self._base_query().filter(Workspace.workspace_id==id).\
  64. session.query(ZKContact).filter(ZKContact.groups.any(ZKGroup.id.in_([1,2,3])))
  65. filter(sqla.).one()
  66. """
  67. def get_all(self):
  68. return self._base_query().all()
  69. def get_all_for_user(self, user: User, ignored_ids=None):
  70. workspaces = []
  71. for role in user.roles:
  72. if not role.workspace.is_deleted:
  73. if not ignored_ids:
  74. workspaces.append(role.workspace)
  75. elif role.workspace.workspace_id not in ignored_ids:
  76. workspaces.append(role.workspace)
  77. else:
  78. pass # do not return workspace
  79. workspaces.sort(key=lambda workspace: workspace.label.lower())
  80. return workspaces
  81. def get_all_manageable(self) -> typing.List[Workspace]:
  82. """Get all workspaces the current user has manager rights on."""
  83. workspaces = [] # type: typing.List[Workspace]
  84. if self._user.profile.id == Group.TIM_ADMIN:
  85. workspaces = self._base_query().order_by(Workspace.label).all()
  86. elif self._user.profile.id == Group.TIM_MANAGER:
  87. workspaces = self._base_query() \
  88. .filter(
  89. UserRoleInWorkspace.role ==
  90. UserRoleInWorkspace.WORKSPACE_MANAGER
  91. ) \
  92. .order_by(Workspace.label) \
  93. .all()
  94. return workspaces
  95. def disable_notifications(self, user: User, workspace: Workspace):
  96. for role in user.roles:
  97. if role.workspace==workspace:
  98. role.do_notify = False
  99. def enable_notifications(self, user: User, workspace: Workspace):
  100. for role in user.roles:
  101. if role.workspace==workspace:
  102. role.do_notify = True
  103. def get_notifiable_roles(self, workspace: Workspace) -> [UserRoleInWorkspace]:
  104. roles = []
  105. for role in workspace.roles:
  106. if role.do_notify==True \
  107. and role.user!=self._user \
  108. and role.user.is_active:
  109. roles.append(role)
  110. return roles
  111. def save(self, workspace: Workspace):
  112. DBSession.flush()
  113. def delete_one(self, workspace_id, flush=True):
  114. workspace = self.get_one(workspace_id)
  115. workspace.is_deleted = True
  116. if flush:
  117. DBSession.flush()
  118. def restore_one(self, workspace_id, flush=True):
  119. workspace = DBSession.query(Workspace).filter(Workspace.is_deleted==True).filter(Workspace.workspace_id==workspace_id).one()
  120. workspace.is_deleted = False
  121. if flush:
  122. DBSession.flush()
  123. return workspace
  124. def execute_created_workspace_actions(self, workspace: Workspace) -> None:
  125. self.ensure_calendar_exist(workspace)
  126. def ensure_calendar_exist(self, workspace: Workspace) -> None:
  127. # Note: Cyclic imports
  128. from tracim.lib.calendar import CalendarManager
  129. from tracim.model.organisational import WorkspaceCalendar
  130. calendar_manager = CalendarManager(self._user)
  131. try:
  132. calendar_manager.enable_calendar_file(
  133. calendar_class=WorkspaceCalendar,
  134. related_object_id=workspace.workspace_id,
  135. raise_=True,
  136. )
  137. # If previous calendar file no exist, calendar must be created
  138. except FileNotFoundError:
  139. self._user.ensure_auth_token()
  140. # Ensure database is up-to-date
  141. DBSession.flush()
  142. transaction.commit()
  143. calendar_manager.create_then_remove_fake_event(
  144. calendar_class=WorkspaceCalendar,
  145. related_object_id=workspace.workspace_id,
  146. )
  147. def disable_calendar(self, workspace: Workspace) -> None:
  148. # Note: Cyclic imports
  149. from tracim.lib.calendar import CalendarManager
  150. from tracim.model.organisational import WorkspaceCalendar
  151. calendar_manager = CalendarManager(self._user)
  152. calendar_manager.disable_calendar_file(
  153. calendar_class=WorkspaceCalendar,
  154. related_object_id=workspace.workspace_id,
  155. raise_=False,
  156. )
  157. def get_base_query(self) -> Query:
  158. return self._base_query()
  159. def generate_label(self) -> str:
  160. """
  161. :return: Generated workspace label
  162. """
  163. query = self._base_query_without_roles() \
  164. .filter(Workspace.label.ilike('{0}%'.format(
  165. _('Workspace'),
  166. )))
  167. return _('Workspace {}').format(
  168. query.count() + 1,
  169. )
  170. class UnsafeWorkspaceApi(WorkspaceApi):
  171. def _base_query(self):
  172. return DBSession.query(Workspace).filter(Workspace.is_deleted==False)