root.py 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. # -*- coding: utf-8 -*-
  2. from tg import expose
  3. from tg import flash
  4. from tg import lurl
  5. from tg import predicates
  6. from tg import redirect
  7. from tg import request
  8. from tg import require
  9. from tg import tmpl_context
  10. from tg import url
  11. from tg.i18n import ugettext as _
  12. from tracim.controllers import StandardController
  13. from tracim.controllers.admin import AdminController
  14. from tracim.controllers.api import APIController
  15. from tracim.controllers.calendar import CalendarConfigController
  16. from tracim.controllers.calendar import CalendarController
  17. from tracim.controllers.content import ContentController
  18. from tracim.controllers.debug import DebugController
  19. from tracim.controllers.error import ErrorController
  20. from tracim.controllers.help import HelpController
  21. from tracim.controllers.previews import PreviewsController
  22. from tracim.controllers.user import UserRestController
  23. from tracim.controllers.workspace import UserWorkspaceRestController
  24. from tracim.controllers.events import EventRestController
  25. from tracim.lib import CST
  26. from tracim.lib.base import logger
  27. from tracim.lib.content import ContentApi
  28. from tracim.lib.user import CurrentUserGetterApi
  29. from tracim.lib.utils import replace_reset_password_templates
  30. from tracim.model.data import ContentType
  31. from tracim.model.serializers import Context
  32. from tracim.model.serializers import CTX
  33. from tracim.model.serializers import DictLikeClass
  34. class RootController(StandardController):
  35. """
  36. The root controller for the tracim application.
  37. All the other controllers and WSGI applications should be mounted on this
  38. controller. For example::
  39. panel = ControlPanelController()
  40. another_app = AnotherWSGIApplication()
  41. Keep in mind that WSGI applications shouldn't be mounted directly: They
  42. must be wrapped around with :class:`tg.controllers.WSGIAppController`.
  43. """
  44. admin = AdminController()
  45. help = HelpController()
  46. calendar = CalendarController()
  47. calendar_config = CalendarConfigController()
  48. debug = DebugController()
  49. error = ErrorController()
  50. # Rest controllers
  51. workspaces = UserWorkspaceRestController()
  52. user = UserRestController()
  53. previews = PreviewsController()
  54. content = ContentController()
  55. events = EventRestController()
  56. # api
  57. api = APIController()
  58. def _render_response(self, tgl, controller, response):
  59. replace_reset_password_templates(controller.decoration.engines)
  60. return super()._render_response(tgl, controller, response)
  61. def _before(self, *args, **kw):
  62. super(RootController, self)._before(args, kw)
  63. tmpl_context.project_name = "tracim"
  64. @expose('tracim.templates.index')
  65. def index(self, came_from='', *args, **kwargs):
  66. if request.identity:
  67. if came_from:
  68. logger.info(self, 'Will redirect to {}'.format(came_from))
  69. redirect(url(came_from))
  70. else:
  71. redirect(self.url(None, self.home.__name__))
  72. login_counter = request.environ.get('repoze.who.logins', 0)
  73. if login_counter > 0:
  74. flash(_('Wrong credentials'), CST.STATUS_ERROR)
  75. return dict(page='login', login_counter=str(login_counter),
  76. came_from=came_from)
  77. @require(predicates.is_anonymous())
  78. @expose('tracim.templates.index')
  79. def login(self, *args, **kwargs):
  80. """
  81. This method is there for backward compatibility only
  82. This is related to the default TG2 authentication behavior...
  83. Now the login form is included in home page
  84. :param args:
  85. :param kwargs:
  86. :return:
  87. """
  88. came_from = kwargs['came_from'] if 'came_from' in kwargs.keys() else ''
  89. logger.info(self, 'came_from: {}'.format(kwargs))
  90. return self.index(came_from, args, *kwargs)
  91. @expose()
  92. def post_login(self, came_from=lurl('/home')):
  93. """
  94. Redirect the user to the initially requested page on successful
  95. authentication or redirect her back to the login page if login failed.
  96. """
  97. if not request.identity:
  98. login_counter = request.environ.get('repoze.who.logins', 0) + 1
  99. redirect(url('/login'),
  100. params=dict(came_from=came_from, __logins=login_counter))
  101. user = CurrentUserGetterApi.get_current_user()
  102. flash(_('Welcome back, %s!') % user.get_display_name())
  103. redirect(came_from)
  104. @expose()
  105. def post_logout(self, came_from=lurl('/')):
  106. """
  107. Redirect the user to the initially requested page on logout and say
  108. goodbye as well.
  109. """
  110. flash(_('Successfully logged out. We hope to see you soon!'))
  111. redirect(came_from)
  112. @require(predicates.not_anonymous())
  113. @expose('tracim.templates.home')
  114. def home(self):
  115. user = tmpl_context.current_user
  116. current_user_content = Context(CTX.CURRENT_USER).toDict(user)
  117. fake_api = Context(CTX.CURRENT_USER).toDict({
  118. 'current_user': current_user_content})
  119. last_active_contents = ContentApi(user).get_last_active(None, ContentType.Any, None)
  120. fake_api.last_actives = Context(CTX.CONTENT_LIST).toDict(last_active_contents, 'contents', 'nb')
  121. unread_contents = ContentApi(user).get_last_unread(None, ContentType.Any, None)
  122. fake_api.last_unread = Context(CTX.CONTENT_LIST).toDict(unread_contents, 'contents', 'nb')
  123. # INFO - D.A. - 2015-05-20
  124. # For now, we do not have favorties and read/unread status
  125. # so we only show:
  126. # - workspaces
  127. # - last activity
  128. # - oldest open stuff
  129. items = ContentApi(user).get_all_without_exception(ContentType.Any, None)[:4]
  130. fake_api.favorites = Context(CTX.CONTENT_LIST).toDict(items, 'contents', 'nb')
  131. return DictLikeClass(fake_api=fake_api)
  132. @require(predicates.not_anonymous())
  133. @expose('tracim.templates.search.display')
  134. def search(self, keywords=''):
  135. from tracim.lib.content import ContentApi
  136. user = tmpl_context.current_user
  137. api = ContentApi(user)
  138. items = []
  139. keyword_list = api.get_keywords(keywords)
  140. result = api.search(keyword_list)
  141. if result:
  142. items = result.limit(ContentApi.SEARCH_DEFAULT_RESULT_NB).all()
  143. api.exclude_unavailable(items)
  144. current_user_content = Context(CTX.CURRENT_USER).toDict(user)
  145. fake_api = Context(CTX.CURRENT_USER).toDict({'current_user': current_user_content})
  146. search_results = Context(CTX.SEARCH).toDict(items, 'results', 'result_nb')
  147. search_results.keywords = keyword_list
  148. return DictLikeClass(fake_api=fake_api, search=search_results)