integrity.py 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. # -*- coding: utf-8 -*-
  2. import os
  3. from sqlalchemy import func
  4. from tg import tmpl_context
  5. from tg.render import render
  6. from tracim.lib.content import ContentApi
  7. from tracim.lib.workspace import UnsafeWorkspaceApi
  8. from tracim.model.data import Workspace
  9. from tracim.model.data import Content
  10. from tracim.model.serializers import DictLikeClass, Context, CTX
  11. class PathValidationManager(object):
  12. def __init__(self, is_case_sensitive: bool=False):
  13. """
  14. :param is_case_sensitive: If True, consider name with different
  15. case as different.
  16. """
  17. self._is_case_sensitive = is_case_sensitive
  18. self._workspace_api = UnsafeWorkspaceApi(None)
  19. self._content_api = ContentApi(None)
  20. def workspace_label_is_free(self, workspace_name: str) -> bool:
  21. """
  22. :param workspace_name: Workspace name
  23. :return: True if workspace is available
  24. """
  25. query = self._workspace_api.get_base_query()
  26. label_filter = Workspace.label == workspace_name
  27. if not self._is_case_sensitive:
  28. label_filter = func.lower(Workspace.label) == \
  29. func.lower(workspace_name)
  30. return not bool(query.filter(label_filter).count())
  31. def content_label_is_free(
  32. self,
  33. content_label_as_file,
  34. workspace: Workspace,
  35. parent: Content=None,
  36. exclude_content_id: int=None,
  37. ) -> bool:
  38. """
  39. :param content_label_as_file:
  40. :param workspace:
  41. :param parent:
  42. :return: True if content label is available
  43. """
  44. query = self._content_api.get_base_query(workspace)
  45. if parent:
  46. query = query.filter(Content.parent_id == parent.content_id)
  47. if exclude_content_id:
  48. query = query.filter(Content.content_id != exclude_content_id)
  49. query = query.filter(Content.workspace_id == workspace.workspace_id)
  50. return not \
  51. bool(
  52. self._content_api.filter_query_for_content_label_as_path(
  53. query=query,
  54. content_label_as_file=content_label_as_file,
  55. is_case_sensitive=self._is_case_sensitive,
  56. ).count()
  57. )
  58. def validate_new_content(self, content: Content) -> bool:
  59. """
  60. :param content: Content with label to test
  61. :return: True if content label is not in conflict with existing
  62. resource
  63. """
  64. return self.content_label_is_free(
  65. content_label_as_file=content.get_label_as_file(),
  66. workspace=content.workspace,
  67. parent=content.parent,
  68. exclude_content_id=content.content_id,
  69. )
  70. def render_invalid_integrity_chosen_path(invalid_label: str) -> str:
  71. """
  72. Return html page code of error about invalid label choice.
  73. :param invalid_label: the invalid label
  74. :return: html page code
  75. """
  76. user = tmpl_context.current_user
  77. fake_api_content = DictLikeClass(
  78. current_user=user,
  79. )
  80. fake_api = Context(CTX.USER).toDict(fake_api_content)
  81. return render(
  82. template_vars=dict(
  83. invalid_label=invalid_label,
  84. fake_api=fake_api,
  85. ),
  86. template_engine='mako',
  87. template_name='tracim.templates.errors.label_invalid_path',
  88. )