test_calendar.py 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. import os
  2. import time
  3. import caldav
  4. import transaction
  5. from caldav.lib.error import AuthorizationError
  6. from collections import OrderedDict
  7. from nose.tools import eq_
  8. from nose.tools import ok_
  9. from nose.tools import raises
  10. import requests
  11. from requests.exceptions import ConnectionError
  12. from sqlalchemy.orm.exc import NoResultFound
  13. from tg import config
  14. from tracim.config.app_cfg import daemons
  15. from tracim.lib.calendar import CalendarManager
  16. from tracim.lib.workspace import WorkspaceApi
  17. from tracim.model import DBSession
  18. from tracim.tests import TestCalendar as BaseTestCalendar
  19. from tracim.tests import not_raises
  20. from tracim.model.auth import User
  21. from tracim.model.data import Content
  22. from tracim.model.data import Workspace
  23. class TestCalendar(BaseTestCalendar):
  24. def setUp(self):
  25. super().setUp()
  26. time.sleep(3) # TODO - 20160606 - Bastien: sleep to wait ...
  27. # ... radicale daemon started. We should lock something somewhere !
  28. def test_func__radicale_connectivity__ok__nominal_case(self):
  29. radicale_base_url = CalendarManager.get_base_url()
  30. try:
  31. response = requests.get(radicale_base_url)
  32. eq_(response.status_code, 401, 'Radicale http response should be '
  33. '401, its {0}'
  34. .format(response.status_code))
  35. except ConnectionError as exc:
  36. ok_(False, 'Unable to contact radicale on HTTP: {0}'.format(exc))
  37. @not_raises(AuthorizationError)
  38. def test_func__radicale_auth__ok__as_lawrence(self):
  39. radicale_base_url = CalendarManager.get_base_url()
  40. client = caldav.DAVClient(
  41. radicale_base_url,
  42. username='lawrence-not-real-email@fsf.local',
  43. password='foobarbaz'
  44. )
  45. client.propfind()
  46. @raises(AuthorizationError)
  47. def test_func__radicale_auth__fail__as_john_doe(self):
  48. radicale_base_url = CalendarManager.get_base_url()
  49. client = caldav.DAVClient(
  50. radicale_base_url,
  51. username='john.doe@foo.local',
  52. password='nopasswd'
  53. )
  54. client.propfind()
  55. @not_raises(AuthorizationError)
  56. def test_func__rights_read_user_calendar__ok__as_lawrence(self):
  57. radicale_base_url = CalendarManager.get_base_url()
  58. client = caldav.DAVClient(
  59. radicale_base_url,
  60. username='lawrence-not-real-email@fsf.local',
  61. password='foobarbaz'
  62. )
  63. user = DBSession.query(User).filter(
  64. User.email == 'lawrence-not-real-email@fsf.local'
  65. ).one()
  66. user_calendar_url = CalendarManager.get_user_calendar_url(user.user_id)
  67. caldav.Calendar(
  68. parent=client,
  69. client=client,
  70. url=user_calendar_url
  71. ).events()
  72. @raises(AuthorizationError)
  73. def test_func__rights_read_user_calendar__fail__as_john_doe(self):
  74. radicale_base_url = CalendarManager.get_base_url()
  75. client = caldav.DAVClient(
  76. radicale_base_url,
  77. username='john.doe@foo.local',
  78. password='nopasswd'
  79. )
  80. other_user = DBSession.query(User).filter(
  81. User.email == 'admin@admin.admin'
  82. ).one()
  83. user_calendar_url = CalendarManager.get_user_calendar_url(other_user.user_id)
  84. caldav.Calendar(
  85. parent=client,
  86. client=client,
  87. url=user_calendar_url
  88. ).events()
  89. @not_raises(AuthorizationError)
  90. def test_func__rights_read_workspace_calendar__ok__as_owner(self):
  91. lawrence = DBSession.query(User).filter(
  92. User.email == 'lawrence-not-real-email@fsf.local'
  93. ).one()
  94. workspace = WorkspaceApi(lawrence).create_workspace(
  95. 'workspace_1',
  96. save_now=False
  97. )
  98. workspace.calendar_enabled = True
  99. DBSession.flush()
  100. workspace_calendar_url = CalendarManager.get_workspace_calendar_url(
  101. workspace.workspace_id
  102. )
  103. transaction.commit()
  104. radicale_base_url = CalendarManager.get_base_url()
  105. client = caldav.DAVClient(
  106. radicale_base_url,
  107. username='lawrence-not-real-email@fsf.local',
  108. password='foobarbaz'
  109. )
  110. caldav.Calendar(
  111. parent=client,
  112. client=client,
  113. url=workspace_calendar_url
  114. ).events()
  115. @raises(AuthorizationError)
  116. def test_func__rights_read_workspace_calendar__fail__as_unauthorized(self):
  117. lawrence = DBSession.query(User).filter(
  118. User.email == 'lawrence-not-real-email@fsf.local'
  119. ).one()
  120. workspace = WorkspaceApi(lawrence).create_workspace(
  121. 'workspace_1',
  122. save_now=False
  123. )
  124. workspace.calendar_enabled = True
  125. DBSession.flush()
  126. workspace_calendar_url = CalendarManager.get_workspace_calendar_url(
  127. workspace.workspace_id
  128. )
  129. transaction.commit()
  130. radicale_base_url = CalendarManager.get_base_url()
  131. client = caldav.DAVClient(
  132. radicale_base_url,
  133. username='bob@fsf.local',
  134. password='foobarbaz'
  135. )
  136. caldav.Calendar(
  137. parent=client,
  138. client=client,
  139. url=workspace_calendar_url
  140. ).events()
  141. def test_func__event_create__ok__nominal_case(self):
  142. lawrence = DBSession.query(User).filter(
  143. User.email == 'lawrence-not-real-email@fsf.local'
  144. ).one()
  145. radicale_base_url = CalendarManager.get_base_url()
  146. client = caldav.DAVClient(
  147. radicale_base_url,
  148. username='lawrence-not-real-email@fsf.local',
  149. password='foobarbaz'
  150. )
  151. user_calendar_url = CalendarManager.get_user_calendar_url(
  152. lawrence.user_id
  153. )
  154. user_calendar = caldav.Calendar(
  155. parent=client,
  156. client=client,
  157. url=user_calendar_url
  158. )
  159. event_ics = """BEGIN:VCALENDAR
  160. VERSION:2.0
  161. PRODID:-//Example Corp.//CalDAV Client//EN
  162. BEGIN:VEVENT
  163. UID:1234567890
  164. DTSTAMP:20100510T182145Z
  165. DTSTART:20100512T170000Z
  166. DTEND:20100512T180000Z
  167. SUMMARY:This is an event
  168. LOCATION:Here
  169. END:VEVENT
  170. END:VCALENDAR
  171. """
  172. user_calendar.add_event(event_ics)
  173. user_calendar.save()
  174. daemons.execute_in_thread('radicale', lambda: transaction.commit())
  175. # TODO - 20160606 - Bastien: lock should be better here ?
  176. time.sleep(3) # Wait for be sure transaction commited in daemon
  177. transaction.commit()
  178. try:
  179. event = DBSession.query(Content).filter(
  180. Content.label == 'This is an event'
  181. ).one()
  182. except NoResultFound:
  183. ok_(False, 'Content record should exist for '
  184. '"This is an event" label')
  185. eq_(event.properties['location'], 'Here')
  186. eq_(event.properties['start'], '2010-05-12 18:00:00+0000')
  187. eq_(event.properties['end'], '2010-05-12 17:00:00+0000')
  188. def test_created_user_radicale_calendar(self):
  189. self._connect_user(
  190. 'admin@admin.admin',
  191. 'admin@admin.admin',
  192. )
  193. user_count = DBSession.query(User)\
  194. .filter(User.email == 'an-other-email@test.local').count()
  195. eq_(0, user_count, 'User should not exist yet')
  196. radicale_users_folder = '{0}/user'\
  197. .format(config.get('radicale.server.filesystem.folder'))
  198. eq_(
  199. False,
  200. os.path.isdir(radicale_users_folder),
  201. 'Radicale users folder should not exist yet',
  202. )
  203. # Create a new user, his calendar should be created to
  204. try_post_user = self.app.post(
  205. '/admin/users',
  206. OrderedDict([
  207. ('name', 'TEST'),
  208. ('email', 'an-other-email@test.local'),
  209. ('password', 'an-other-email@test.local'),
  210. ('is_tracim_manager', 'off'),
  211. ('is_tracim_admin', 'off'),
  212. ('send_email', 'off'),
  213. ])
  214. )
  215. eq_(try_post_user.status_code, 302,
  216. "Code should be 302, but is %d" % try_post_user.status_code)
  217. users_calendars = len([
  218. name for name in os.listdir(radicale_users_folder)
  219. if name.endswith('.ics')
  220. ])
  221. user = DBSession.query(User) \
  222. .filter(User.email == 'an-other-email@test.local').one()
  223. eq_(1, users_calendars, 'Radicale user path should list 1 calendar')
  224. user_calendar = '{0}/{1}.ics'.format(
  225. radicale_users_folder,
  226. user.user_id,
  227. )
  228. user_calendar_exist = os.path.isfile(user_calendar)
  229. eq_(True, user_calendar_exist, 'User calendar should be created')
  230. def test_created_workspace_radicale_calendar(self):
  231. self._connect_user(
  232. 'admin@admin.admin',
  233. 'admin@admin.admin',
  234. )
  235. workspaces_count = DBSession.query(Workspace)\
  236. .filter(Workspace.label == 'WTESTCAL').count()
  237. eq_(0, workspaces_count, 'Workspace should not exist yet !')
  238. radicale_workspaces_folder = '{0}/workspace'\
  239. .format(config.get('radicale.server.filesystem.folder'))
  240. eq_(
  241. False,
  242. os.path.isdir(radicale_workspaces_folder),
  243. 'Radicale workskpaces folder should not exist yet',
  244. )
  245. # Create a new workspace, his calendar should be created to
  246. try_post_workspace = self.app.post(
  247. '/admin/workspaces',
  248. OrderedDict([
  249. ('name', 'WTESTCAL'),
  250. ('description', 'WTESTCALDESCR'),
  251. ('calendar_enabled', 'on'),
  252. ])
  253. )
  254. eq_(try_post_workspace.status_code, 302,
  255. "Code should be 302, but is %d" % try_post_workspace.status_code)
  256. workspaces_calendars = len([
  257. name for name in os.listdir(radicale_workspaces_folder)
  258. if name.endswith('.ics')
  259. ])
  260. workspace = DBSession.query(Workspace) \
  261. .filter(Workspace.label == 'WTESTCAL').one()
  262. eq_(
  263. 1,
  264. workspaces_calendars,
  265. 'Radicale workspace path should list 1 calendar',
  266. )
  267. workspace_calendar = '{0}/{1}.ics'.format(
  268. radicale_workspaces_folder,
  269. workspace.workspace_id,
  270. )
  271. workspace_calendar_exist = os.path.isfile(workspace_calendar)
  272. eq_(
  273. True,
  274. workspace_calendar_exist,
  275. 'Workspace calendar should be created',
  276. )