file_controller.py 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. # coding=utf-8
  2. import typing
  3. import transaction
  4. from depot.manager import DepotManager
  5. from preview_generator.exception import UnavailablePreviewType
  6. from pyramid.config import Configurator
  7. from pyramid.response import FileResponse, FileIter
  8. try: # Python 3.5+
  9. from http import HTTPStatus
  10. except ImportError:
  11. from http import client as HTTPStatus
  12. from tracim_backend import TracimRequest
  13. from tracim_backend.extensions import hapic
  14. from tracim_backend.lib.core.content import ContentApi
  15. from tracim_backend.views.controllers import Controller
  16. from tracim_backend.views.core_api.schemas import FileContentSchema
  17. from tracim_backend.views.core_api.schemas import AllowedJpgPreviewDimSchema
  18. from tracim_backend.views.core_api.schemas import ContentPreviewSizedPathSchema
  19. from tracim_backend.views.core_api.schemas import RevisionPreviewSizedPathSchema
  20. from tracim_backend.views.core_api.schemas import PageQuerySchema
  21. from tracim_backend.views.core_api.schemas import WorkspaceAndContentRevisionIdPathSchema # nopep8
  22. from tracim_backend.views.core_api.schemas import FileRevisionSchema
  23. from tracim_backend.views.core_api.schemas import SetContentStatusSchema
  24. from tracim_backend.views.core_api.schemas import FileContentModifySchema
  25. from tracim_backend.views.core_api.schemas import WorkspaceAndContentIdPathSchema
  26. from tracim_backend.views.core_api.schemas import NoContentSchema
  27. from tracim_backend.lib.utils.authorization import require_content_types
  28. from tracim_backend.lib.utils.authorization import require_workspace_role
  29. from tracim_backend.models.data import UserRoleInWorkspace
  30. from tracim_backend.models.context_models import ContentInContext
  31. from tracim_backend.models.context_models import RevisionInContext
  32. from tracim_backend.models.contents import CONTENT_TYPES
  33. from tracim_backend.models.contents import file_type
  34. from tracim_backend.models.revision_protection import new_revision
  35. from tracim_backend.exceptions import EmptyLabelNotAllowed
  36. from tracim_backend.exceptions import PageOfPreviewNotFound
  37. from tracim_backend.exceptions import PreviewDimNotAllowed
  38. SWAGGER_TAG__FILE_ENDPOINTS = 'Files'
  39. class FileController(Controller):
  40. """
  41. Endpoints for File Content
  42. """
  43. # File data
  44. @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
  45. @require_workspace_role(UserRoleInWorkspace.CONTRIBUTOR)
  46. @require_content_types([file_type])
  47. @hapic.input_path(WorkspaceAndContentIdPathSchema())
  48. # TODO - G.M - 2018-07-24 - Use hapic for input file
  49. @hapic.output_body(NoContentSchema(), default_http_code=HTTPStatus.NO_CONTENT) # nopep8
  50. def upload_file(self, context, request: TracimRequest, hapic_data=None):
  51. """
  52. Upload a new version of raw file of content. This will create a new
  53. revision.
  54. """
  55. app_config = request.registry.settings['CFG']
  56. api = ContentApi(
  57. show_archived=True,
  58. show_deleted=True,
  59. current_user=request.current_user,
  60. session=request.dbsession,
  61. config=app_config,
  62. )
  63. content = api.get_one(
  64. hapic_data.path.content_id,
  65. content_type=CONTENT_TYPES.Any_SLUG
  66. )
  67. file = request.POST['files']
  68. with new_revision(
  69. session=request.dbsession,
  70. tm=transaction.manager,
  71. content=content
  72. ):
  73. api.update_file_data(
  74. content,
  75. new_filename=file.filename,
  76. new_mimetype=file.type,
  77. new_content=file.file,
  78. )
  79. return
  80. @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
  81. @require_workspace_role(UserRoleInWorkspace.READER)
  82. @require_content_types([file_type])
  83. @hapic.input_path(WorkspaceAndContentIdPathSchema())
  84. @hapic.output_file([])
  85. def download_file(self, context, request: TracimRequest, hapic_data=None):
  86. """
  87. Download raw file of last revision of content.
  88. """
  89. app_config = request.registry.settings['CFG']
  90. api = ContentApi(
  91. show_archived=True,
  92. show_deleted=True,
  93. current_user=request.current_user,
  94. session=request.dbsession,
  95. config=app_config,
  96. )
  97. content = api.get_one(
  98. hapic_data.path.content_id,
  99. content_type=CONTENT_TYPES.Any_SLUG
  100. )
  101. file = DepotManager.get().get(content.depot_file)
  102. response = request.response
  103. response.content_type = file.content_type
  104. response.app_iter = FileIter(file)
  105. return response
  106. @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
  107. @require_workspace_role(UserRoleInWorkspace.READER)
  108. @require_content_types([file_type])
  109. @hapic.input_path(WorkspaceAndContentRevisionIdPathSchema())
  110. @hapic.output_file([])
  111. def download_revisions_file(self, context, request: TracimRequest, hapic_data=None): # nopep8
  112. """
  113. Download raw file for specific revision of content.
  114. """
  115. app_config = request.registry.settings['CFG']
  116. api = ContentApi(
  117. show_archived=True,
  118. show_deleted=True,
  119. current_user=request.current_user,
  120. session=request.dbsession,
  121. config=app_config,
  122. )
  123. content = api.get_one(
  124. hapic_data.path.content_id,
  125. content_type=CONTENT_TYPES.Any_SLUG
  126. )
  127. revision = api.get_one_revision(
  128. revision_id=hapic_data.path.revision_id,
  129. content=content
  130. )
  131. file = DepotManager.get().get(revision.depot_file)
  132. response = request.response
  133. response.content_type = file.content_type
  134. response.app_iter = FileIter(file)
  135. return response
  136. # preview
  137. # pdf
  138. @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
  139. @require_workspace_role(UserRoleInWorkspace.READER)
  140. @require_content_types([file_type])
  141. @hapic.handle_exception(UnavailablePreviewType, HTTPStatus.BAD_REQUEST)
  142. @hapic.handle_exception(PageOfPreviewNotFound, HTTPStatus.BAD_REQUEST)
  143. @hapic.input_query(PageQuerySchema())
  144. @hapic.input_path(WorkspaceAndContentIdPathSchema())
  145. @hapic.output_file([])
  146. def preview_pdf(self, context, request: TracimRequest, hapic_data=None):
  147. """
  148. Obtain a specific page pdf preview of last revision of content.
  149. """
  150. app_config = request.registry.settings['CFG']
  151. api = ContentApi(
  152. show_archived=True,
  153. show_deleted=True,
  154. current_user=request.current_user,
  155. session=request.dbsession,
  156. config=app_config,
  157. )
  158. content = api.get_one(
  159. hapic_data.path.content_id,
  160. content_type=CONTENT_TYPES.Any_SLUG
  161. )
  162. pdf_preview_path = api.get_pdf_preview_path(
  163. content.content_id,
  164. content.revision_id,
  165. page=hapic_data.query.page
  166. )
  167. return FileResponse(pdf_preview_path)
  168. @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
  169. @require_workspace_role(UserRoleInWorkspace.READER)
  170. @require_content_types([file_type])
  171. @hapic.handle_exception(UnavailablePreviewType, HTTPStatus.BAD_REQUEST)
  172. @hapic.input_path(WorkspaceAndContentIdPathSchema())
  173. @hapic.output_file([])
  174. def preview_pdf_full(self, context, request: TracimRequest, hapic_data=None): # nopep8
  175. """
  176. Obtain a full pdf preview (all page) of last revision of content.
  177. """
  178. app_config = request.registry.settings['CFG']
  179. api = ContentApi(
  180. show_archived=True,
  181. show_deleted=True,
  182. current_user=request.current_user,
  183. session=request.dbsession,
  184. config=app_config,
  185. )
  186. content = api.get_one(
  187. hapic_data.path.content_id,
  188. content_type=CONTENT_TYPES.Any_SLUG
  189. )
  190. pdf_preview_path = api.get_full_pdf_preview_path(content.revision_id)
  191. return FileResponse(pdf_preview_path)
  192. @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
  193. @require_workspace_role(UserRoleInWorkspace.READER)
  194. @require_content_types([file_type])
  195. @hapic.handle_exception(UnavailablePreviewType, HTTPStatus.BAD_REQUEST)
  196. @hapic.input_path(WorkspaceAndContentRevisionIdPathSchema())
  197. @hapic.input_query(PageQuerySchema())
  198. @hapic.output_file([])
  199. def preview_pdf_revision(self, context, request: TracimRequest, hapic_data=None): # nopep8
  200. """
  201. Obtain a specific page pdf preview of a specific revision of content.
  202. """
  203. app_config = request.registry.settings['CFG']
  204. api = ContentApi(
  205. show_archived=True,
  206. show_deleted=True,
  207. current_user=request.current_user,
  208. session=request.dbsession,
  209. config=app_config,
  210. )
  211. content = api.get_one(
  212. hapic_data.path.content_id,
  213. content_type=CONTENT_TYPES.Any_SLUG
  214. )
  215. revision = api.get_one_revision(
  216. revision_id=hapic_data.path.revision_id,
  217. content=content
  218. )
  219. pdf_preview_path = api.get_pdf_preview_path(
  220. revision.content_id,
  221. revision.revision_id,
  222. page=hapic_data.query.page
  223. )
  224. return FileResponse(pdf_preview_path)
  225. # jpg
  226. @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
  227. @require_workspace_role(UserRoleInWorkspace.READER)
  228. @require_content_types([file_type])
  229. @hapic.handle_exception(PageOfPreviewNotFound, HTTPStatus.BAD_REQUEST)
  230. @hapic.input_path(WorkspaceAndContentIdPathSchema())
  231. @hapic.input_query(PageQuerySchema())
  232. @hapic.output_file([])
  233. def preview_jpg(self, context, request: TracimRequest, hapic_data=None):
  234. """
  235. Obtain normally sied jpg preview of last revision of content.
  236. """
  237. app_config = request.registry.settings['CFG']
  238. api = ContentApi(
  239. show_archived=True,
  240. show_deleted=True,
  241. current_user=request.current_user,
  242. session=request.dbsession,
  243. config=app_config,
  244. )
  245. content = api.get_one(
  246. hapic_data.path.content_id,
  247. content_type=CONTENT_TYPES.Any_SLUG
  248. )
  249. allowed_dim = api.get_jpg_preview_allowed_dim()
  250. jpg_preview_path = api.get_jpg_preview_path(
  251. content_id=content.content_id,
  252. revision_id=content.revision_id,
  253. page=hapic_data.query.page,
  254. width=allowed_dim.dimensions[0].width,
  255. height=allowed_dim.dimensions[0].height,
  256. )
  257. return FileResponse(jpg_preview_path)
  258. @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
  259. @require_workspace_role(UserRoleInWorkspace.READER)
  260. @require_content_types([file_type])
  261. @hapic.handle_exception(PageOfPreviewNotFound, HTTPStatus.BAD_REQUEST)
  262. @hapic.handle_exception(PreviewDimNotAllowed, HTTPStatus.BAD_REQUEST)
  263. @hapic.input_query(PageQuerySchema())
  264. @hapic.input_path(ContentPreviewSizedPathSchema())
  265. @hapic.output_file([])
  266. def sized_preview_jpg(self, context, request: TracimRequest, hapic_data=None): # nopep8
  267. """
  268. Obtain resized jpg preview of last revision of content.
  269. """
  270. app_config = request.registry.settings['CFG']
  271. api = ContentApi(
  272. show_archived=True,
  273. show_deleted=True,
  274. current_user=request.current_user,
  275. session=request.dbsession,
  276. config=app_config,
  277. )
  278. content = api.get_one(
  279. hapic_data.path.content_id,
  280. content_type=CONTENT_TYPES.Any_SLUG
  281. )
  282. jpg_preview_path = api.get_jpg_preview_path(
  283. content_id=content.content_id,
  284. revision_id=content.revision_id,
  285. page=hapic_data.query.page,
  286. height=hapic_data.path.height,
  287. width=hapic_data.path.width,
  288. )
  289. return FileResponse(jpg_preview_path)
  290. @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
  291. @require_workspace_role(UserRoleInWorkspace.READER)
  292. @require_content_types([file_type])
  293. @hapic.handle_exception(PageOfPreviewNotFound, HTTPStatus.BAD_REQUEST)
  294. @hapic.handle_exception(PreviewDimNotAllowed, HTTPStatus.BAD_REQUEST)
  295. @hapic.input_path(RevisionPreviewSizedPathSchema())
  296. @hapic.input_query(PageQuerySchema())
  297. @hapic.output_file([])
  298. def sized_preview_jpg_revision(self, context, request: TracimRequest, hapic_data=None): # nopep8
  299. """
  300. Obtain resized jpg preview of a specific revision of content.
  301. """
  302. app_config = request.registry.settings['CFG']
  303. api = ContentApi(
  304. show_archived=True,
  305. show_deleted=True,
  306. current_user=request.current_user,
  307. session=request.dbsession,
  308. config=app_config,
  309. )
  310. content = api.get_one(
  311. hapic_data.path.content_id,
  312. content_type=CONTENT_TYPES.Any_SLUG
  313. )
  314. revision = api.get_one_revision(
  315. revision_id=hapic_data.path.revision_id,
  316. content=content
  317. )
  318. jpg_preview_path = api.get_jpg_preview_path(
  319. content_id=content.content_id,
  320. revision_id=revision.revision_id,
  321. page=hapic_data.query.page,
  322. height=hapic_data.path.height,
  323. width=hapic_data.path.width,
  324. )
  325. return FileResponse(jpg_preview_path)
  326. @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
  327. @require_workspace_role(UserRoleInWorkspace.READER)
  328. @require_content_types([file_type])
  329. @hapic.input_path(WorkspaceAndContentIdPathSchema())
  330. @hapic.output_body(AllowedJpgPreviewDimSchema())
  331. def allowed_dim_preview_jpg(self, context, request: TracimRequest, hapic_data=None): # nopep8
  332. """
  333. Get allowed dimensions of jpg preview. If restricted is true,
  334. only those dimensions are strictly accepted.
  335. """
  336. app_config = request.registry.settings['CFG']
  337. api = ContentApi(
  338. show_archived=True,
  339. show_deleted=True,
  340. current_user=request.current_user,
  341. session=request.dbsession,
  342. config=app_config,
  343. )
  344. return api.get_jpg_preview_allowed_dim()
  345. # File infos
  346. @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
  347. @require_workspace_role(UserRoleInWorkspace.READER)
  348. @require_content_types([file_type])
  349. @hapic.input_path(WorkspaceAndContentIdPathSchema())
  350. @hapic.output_body(FileContentSchema())
  351. def get_file_infos(self, context, request: TracimRequest, hapic_data=None) -> ContentInContext: # nopep8
  352. """
  353. Get thread content
  354. """
  355. app_config = request.registry.settings['CFG']
  356. api = ContentApi(
  357. show_archived=True,
  358. show_deleted=True,
  359. current_user=request.current_user,
  360. session=request.dbsession,
  361. config=app_config,
  362. )
  363. content = api.get_one(
  364. hapic_data.path.content_id,
  365. content_type=CONTENT_TYPES.Any_SLUG
  366. )
  367. return api.get_content_in_context(content)
  368. @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
  369. @hapic.handle_exception(EmptyLabelNotAllowed, HTTPStatus.BAD_REQUEST)
  370. @require_workspace_role(UserRoleInWorkspace.CONTRIBUTOR)
  371. @require_content_types([file_type])
  372. @hapic.input_path(WorkspaceAndContentIdPathSchema())
  373. @hapic.input_body(FileContentModifySchema())
  374. @hapic.output_body(FileContentSchema())
  375. def update_file_info(self, context, request: TracimRequest, hapic_data=None) -> ContentInContext: # nopep8
  376. """
  377. update thread
  378. """
  379. app_config = request.registry.settings['CFG']
  380. api = ContentApi(
  381. show_archived=True,
  382. show_deleted=True,
  383. current_user=request.current_user,
  384. session=request.dbsession,
  385. config=app_config,
  386. )
  387. content = api.get_one(
  388. hapic_data.path.content_id,
  389. content_type=CONTENT_TYPES.Any_SLUG
  390. )
  391. with new_revision(
  392. session=request.dbsession,
  393. tm=transaction.manager,
  394. content=content
  395. ):
  396. api.update_content(
  397. item=content,
  398. new_label=hapic_data.body.label,
  399. new_content=hapic_data.body.raw_content,
  400. )
  401. api.save(content)
  402. return api.get_content_in_context(content)
  403. @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
  404. @require_workspace_role(UserRoleInWorkspace.READER)
  405. @require_content_types([file_type])
  406. @hapic.input_path(WorkspaceAndContentIdPathSchema())
  407. @hapic.output_body(FileRevisionSchema(many=True))
  408. def get_file_revisions(
  409. self,
  410. context,
  411. request: TracimRequest,
  412. hapic_data=None
  413. ) -> typing.List[RevisionInContext]:
  414. """
  415. get file revisions
  416. """
  417. app_config = request.registry.settings['CFG']
  418. api = ContentApi(
  419. show_archived=True,
  420. show_deleted=True,
  421. current_user=request.current_user,
  422. session=request.dbsession,
  423. config=app_config,
  424. )
  425. content = api.get_one(
  426. hapic_data.path.content_id,
  427. content_type=CONTENT_TYPES.Any_SLUG
  428. )
  429. revisions = content.revisions
  430. return [
  431. api.get_revision_in_context(revision)
  432. for revision in revisions
  433. ]
  434. @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
  435. @hapic.handle_exception(EmptyLabelNotAllowed, HTTPStatus.BAD_REQUEST)
  436. @require_workspace_role(UserRoleInWorkspace.CONTRIBUTOR)
  437. @require_content_types([file_type])
  438. @hapic.input_path(WorkspaceAndContentIdPathSchema())
  439. @hapic.input_body(SetContentStatusSchema())
  440. @hapic.output_body(NoContentSchema(), default_http_code=HTTPStatus.NO_CONTENT) # nopep8
  441. def set_file_status(self, context, request: TracimRequest, hapic_data=None) -> None: # nopep8
  442. """
  443. set file status
  444. """
  445. app_config = request.registry.settings['CFG']
  446. api = ContentApi(
  447. show_archived=True,
  448. show_deleted=True,
  449. current_user=request.current_user,
  450. session=request.dbsession,
  451. config=app_config,
  452. )
  453. content = api.get_one(
  454. hapic_data.path.content_id,
  455. content_type=CONTENT_TYPES.Any_SLUG
  456. )
  457. with new_revision(
  458. session=request.dbsession,
  459. tm=transaction.manager,
  460. content=content
  461. ):
  462. api.set_status(
  463. content,
  464. hapic_data.body.status,
  465. )
  466. api.save(content)
  467. return
  468. def bind(self, configurator: Configurator) -> None:
  469. """
  470. Add route to configurator.
  471. """
  472. # file info #
  473. # Get file info
  474. configurator.add_route(
  475. 'file_info',
  476. '/workspaces/{workspace_id}/files/{content_id}',
  477. request_method='GET'
  478. )
  479. configurator.add_view(self.get_file_infos, route_name='file_info') # nopep8
  480. # update file
  481. configurator.add_route(
  482. 'update_file_info',
  483. '/workspaces/{workspace_id}/files/{content_id}',
  484. request_method='PUT'
  485. ) # nopep8
  486. configurator.add_view(self.update_file_info, route_name='update_file_info') # nopep8
  487. # raw file #
  488. # upload raw file
  489. configurator.add_route(
  490. 'upload_file',
  491. '/workspaces/{workspace_id}/files/{content_id}/raw', # nopep8
  492. request_method='PUT'
  493. )
  494. configurator.add_view(self.upload_file, route_name='upload_file') # nopep8
  495. # download raw file
  496. configurator.add_route(
  497. 'download_file',
  498. '/workspaces/{workspace_id}/files/{content_id}/raw', # nopep8
  499. request_method='GET'
  500. )
  501. configurator.add_view(self.download_file, route_name='download_file') # nopep8
  502. # download raw file of revision
  503. configurator.add_route(
  504. 'download_revision',
  505. '/workspaces/{workspace_id}/files/{content_id}/revisions/{revision_id}/raw', # nopep8
  506. request_method='GET'
  507. )
  508. configurator.add_view(self.download_revisions_file, route_name='download_revision') # nopep8
  509. # previews #
  510. # get preview pdf full
  511. configurator.add_route(
  512. 'preview_pdf_full',
  513. '/workspaces/{workspace_id}/files/{content_id}/preview/pdf/full', # nopep8
  514. request_method='GET'
  515. )
  516. configurator.add_view(self.preview_pdf_full, route_name='preview_pdf_full') # nopep8
  517. # get preview pdf
  518. configurator.add_route(
  519. 'preview_pdf',
  520. '/workspaces/{workspace_id}/files/{content_id}/preview/pdf', # nopep8
  521. request_method='GET'
  522. )
  523. configurator.add_view(self.preview_pdf, route_name='preview_pdf') # nopep8
  524. # get preview jpg allowed dims
  525. configurator.add_route(
  526. 'allowed_dim_preview_jpg',
  527. '/workspaces/{workspace_id}/files/{content_id}/preview/jpg/allowed_dims', # nopep8
  528. request_method='GET'
  529. )
  530. configurator.add_view(self.allowed_dim_preview_jpg, route_name='allowed_dim_preview_jpg') # nopep8
  531. # get preview jpg
  532. configurator.add_route(
  533. 'preview_jpg',
  534. '/workspaces/{workspace_id}/files/{content_id}/preview/jpg', # nopep8
  535. request_method='GET'
  536. )
  537. configurator.add_view(self.preview_jpg, route_name='preview_jpg') # nopep8
  538. # get preview jpg with size
  539. configurator.add_route(
  540. 'sized_preview_jpg',
  541. '/workspaces/{workspace_id}/files/{content_id}/preview/jpg/{width}x{height}', # nopep8
  542. request_method='GET'
  543. )
  544. configurator.add_view(self.sized_preview_jpg, route_name='sized_preview_jpg') # nopep8
  545. # get jpg preview for revision
  546. configurator.add_route(
  547. 'sized_preview_jpg_revision',
  548. '/workspaces/{workspace_id}/files/{content_id}/revisions/{revision_id}/preview/jpg/{width}x{height}', # nopep8
  549. request_method='GET'
  550. )
  551. configurator.add_view(self.sized_preview_jpg_revision, route_name='sized_preview_jpg_revision') # nopep8
  552. # get jpg preview for revision
  553. configurator.add_route(
  554. 'preview_pdf_revision',
  555. '/workspaces/{workspace_id}/files/{content_id}/revisions/{revision_id}/preview/pdf', # nopep8
  556. request_method='GET'
  557. )
  558. configurator.add_view(self.preview_pdf_revision, route_name='preview_pdf_revision') # nopep8
  559. # others #
  560. # get file revisions
  561. configurator.add_route(
  562. 'file_revisions',
  563. '/workspaces/{workspace_id}/files/{content_id}/revisions', # nopep8
  564. request_method='GET'
  565. )
  566. configurator.add_view(self.get_file_revisions, route_name='file_revisions') # nopep8
  567. # get file status
  568. configurator.add_route(
  569. 'set_file_status',
  570. '/workspaces/{workspace_id}/files/{content_id}/status', # nopep8
  571. request_method='PUT'
  572. )
  573. configurator.add_view(self.set_file_status, route_name='set_file_status') # nopep8