workspace.py 8.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. # -*- coding: utf-8 -*-
  2. import typing
  3. from sqlalchemy.orm import Query
  4. from sqlalchemy.orm import Session
  5. from tracim import CFG
  6. from tracim.lib.utils.translation import fake_translator as _
  7. from tracim.lib.core.userworkspace import RoleApi
  8. from tracim.models.auth import Group
  9. from tracim.models.auth import User
  10. from tracim.models.context_models import WorkspaceInContext
  11. from tracim.models.data import UserRoleInWorkspace
  12. from tracim.models.data import Workspace
  13. __author__ = 'damien'
  14. class WorkspaceApi(object):
  15. def __init__(
  16. self,
  17. session: Session,
  18. current_user: User,
  19. config: CFG,
  20. force_role: bool=False
  21. ):
  22. """
  23. :param current_user: Current user of context
  24. :param force_role: If True, app role in queries even if admin
  25. """
  26. self._session = session
  27. self._user = current_user
  28. self._config = config
  29. self._force_role = force_role
  30. def _base_query_without_roles(self):
  31. return self._session.query(Workspace).filter(Workspace.is_deleted == False)
  32. def _base_query(self):
  33. if not self._force_role and self._user.profile.id>=Group.TIM_ADMIN:
  34. return self._base_query_without_roles()
  35. return self._session.query(Workspace).\
  36. join(Workspace.roles).\
  37. filter(UserRoleInWorkspace.user_id == self._user.user_id).\
  38. filter(Workspace.is_deleted == False)
  39. def get_workspace_with_context(
  40. self,
  41. workspace: Workspace
  42. ) -> WorkspaceInContext:
  43. """
  44. Return WorkspaceInContext object from Workspace
  45. """
  46. workspace = WorkspaceInContext(
  47. workspace=workspace,
  48. dbsession=self._session,
  49. config=self._config,
  50. )
  51. return workspace
  52. def create_workspace(
  53. self,
  54. label: str='',
  55. description: str='',
  56. calendar_enabled: bool=False,
  57. save_now: bool=False,
  58. ) -> Workspace:
  59. if not label:
  60. label = self.generate_label()
  61. workspace = Workspace()
  62. workspace.label = label
  63. workspace.description = description
  64. workspace.calendar_enabled = calendar_enabled
  65. # By default, we force the current user to be the workspace manager
  66. # And to receive email notifications
  67. role_api = RoleApi(
  68. session=self._session,
  69. current_user=self._user,
  70. config=self._config
  71. )
  72. role = role_api.create_one(
  73. self._user,
  74. workspace,
  75. UserRoleInWorkspace.WORKSPACE_MANAGER,
  76. with_notif=True,
  77. )
  78. self._session.add(workspace)
  79. self._session.add(role)
  80. if save_now:
  81. self._session.flush()
  82. # TODO - G.M - 28-03-2018 - [Calendar] Reenable calendar stuff
  83. # if calendar_enabled:
  84. # self._ensure_calendar_exist(workspace)
  85. # else:
  86. # self._disable_calendar(workspace)
  87. return workspace
  88. def update_workspace(
  89. self,
  90. workspace: Workspace,
  91. label: str,
  92. description: str,
  93. save_now: bool=False,
  94. ) -> Workspace:
  95. """
  96. Update workspace
  97. :param workspace: workspace to update
  98. :param label: new label of workspace
  99. :param description: new description
  100. :param save_now: database flush
  101. :return: updated workspace
  102. """
  103. workspace.label = label
  104. workspace.description = description
  105. if save_now:
  106. self.save(workspace)
  107. return workspace
  108. def get_one(self, id):
  109. return self._base_query().filter(Workspace.workspace_id == id).one()
  110. def get_one_by_label(self, label: str) -> Workspace:
  111. return self._base_query().filter(Workspace.label == label).one()
  112. """
  113. def get_one_for_current_user(self, id):
  114. return self._base_query().filter(Workspace.workspace_id==id).\
  115. session.query(ZKContact).filter(ZKContact.groups.any(ZKGroup.id.in_([1,2,3])))
  116. filter(sqla.).one()
  117. """
  118. def get_all(self):
  119. return self._base_query().all()
  120. def get_all_for_user(self, user: User, ignored_ids=None):
  121. workspaces = []
  122. for role in user.roles:
  123. if not role.workspace.is_deleted:
  124. if not ignored_ids:
  125. workspaces.append(role.workspace)
  126. elif role.workspace.workspace_id not in ignored_ids:
  127. workspaces.append(role.workspace)
  128. else:
  129. pass # do not return workspace
  130. workspaces.sort(key=lambda workspace: workspace.label.lower())
  131. return workspaces
  132. def get_all_manageable(self) -> typing.List[Workspace]:
  133. """Get all workspaces the current user has manager rights on."""
  134. workspaces = [] # type: typing.List[Workspace]
  135. if self._user.profile.id == Group.TIM_ADMIN:
  136. workspaces = self._base_query().order_by(Workspace.label).all()
  137. elif self._user.profile.id == Group.TIM_MANAGER:
  138. workspaces = self._base_query() \
  139. .filter(
  140. UserRoleInWorkspace.role ==
  141. UserRoleInWorkspace.WORKSPACE_MANAGER
  142. ) \
  143. .order_by(Workspace.label) \
  144. .all()
  145. return workspaces
  146. def disable_notifications(self, user: User, workspace: Workspace):
  147. for role in user.roles:
  148. if role.workspace==workspace:
  149. role.do_notify = False
  150. def enable_notifications(self, user: User, workspace: Workspace):
  151. for role in user.roles:
  152. if role.workspace==workspace:
  153. role.do_notify = True
  154. def get_notifiable_roles(self, workspace: Workspace) -> [UserRoleInWorkspace]:
  155. roles = []
  156. for role in workspace.roles:
  157. if role.do_notify==True \
  158. and role.user!=self._user \
  159. and role.user.is_active:
  160. roles.append(role)
  161. return roles
  162. def save(self, workspace: Workspace):
  163. self._session.flush()
  164. def delete_one(self, workspace_id, flush=True):
  165. workspace = self.get_one(workspace_id)
  166. workspace.is_deleted = True
  167. if flush:
  168. self._session.flush()
  169. def restore_one(self, workspace_id, flush=True):
  170. workspace = self._session.query(Workspace)\
  171. .filter(Workspace.is_deleted==True)\
  172. .filter(Workspace.workspace_id==workspace_id).one()
  173. workspace.is_deleted = False
  174. if flush:
  175. self._session.flush()
  176. return workspace
  177. def execute_created_workspace_actions(self, workspace: Workspace) -> None:
  178. pass
  179. # TODO - G.M - 28-03-2018 - [Calendar] Re-enable this calendar stuff
  180. # self.ensure_calendar_exist(workspace)
  181. # TODO - G.M - 28-03-2018 - [Calendar] Re-enable this calendar stuff
  182. # def ensure_calendar_exist(self, workspace: Workspace) -> None:
  183. # # Note: Cyclic imports
  184. # from tracim.lib.calendar import CalendarManager
  185. # from tracim.model.organisational import WorkspaceCalendar
  186. #
  187. # calendar_manager = CalendarManager(self._user)
  188. #
  189. # try:
  190. # calendar_manager.enable_calendar_file(
  191. # calendar_class=WorkspaceCalendar,
  192. # related_object_id=workspace.workspace_id,
  193. # raise_=True,
  194. # )
  195. # # If previous calendar file no exist, calendar must be created
  196. # except FileNotFoundError:
  197. # self._user.ensure_auth_token()
  198. #
  199. # # Ensure database is up-to-date
  200. # self.session.flush()
  201. # transaction.commit()
  202. #
  203. # calendar_manager.create_then_remove_fake_event(
  204. # calendar_class=WorkspaceCalendar,
  205. # related_object_id=workspace.workspace_id,
  206. # )
  207. #
  208. # def disable_calendar(self, workspace: Workspace) -> None:
  209. # # Note: Cyclic imports
  210. # from tracim.lib.calendar import CalendarManager
  211. # from tracim.model.organisational import WorkspaceCalendar
  212. #
  213. # calendar_manager = CalendarManager(self._user)
  214. # calendar_manager.disable_calendar_file(
  215. # calendar_class=WorkspaceCalendar,
  216. # related_object_id=workspace.workspace_id,
  217. # raise_=False,
  218. # )
  219. def get_base_query(self) -> Query:
  220. return self._base_query()
  221. def generate_label(self) -> str:
  222. """
  223. :return: Generated workspace label
  224. """
  225. query = self._base_query_without_roles() \
  226. .filter(Workspace.label.ilike('{0}%'.format(
  227. _('Workspace'),
  228. )))
  229. return _('Workspace {}').format(
  230. query.count() + 1,
  231. )
  232. class UnsafeWorkspaceApi(WorkspaceApi):
  233. def _base_query(self):
  234. return self.session.query(Workspace).filter(Workspace.is_deleted==False)