schemas.py 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. # coding=utf-8
  2. import marshmallow
  3. from marshmallow import post_load
  4. from marshmallow.validate import OneOf
  5. from marshmallow.validate import Range
  6. from tracim.lib.utils.utils import DATETIME_FORMAT
  7. from tracim.models.auth import Profile
  8. from tracim.models.contents import GlobalStatus
  9. from tracim.models.contents import open_status
  10. from tracim.models.contents import ContentTypeLegacy as ContentType
  11. from tracim.models.contents import ContentStatusLegacy as ContentStatus
  12. from tracim.models.context_models import ActiveContentFilter
  13. from tracim.models.context_models import ContentIdsQuery
  14. from tracim.models.context_models import UserWorkspaceAndContentPath
  15. from tracim.models.context_models import ContentCreation
  16. from tracim.models.context_models import UserCreation
  17. from tracim.models.context_models import SetEmail
  18. from tracim.models.context_models import SetPassword
  19. from tracim.models.context_models import UserInfos
  20. from tracim.models.context_models import UserProfile
  21. from tracim.models.context_models import ContentPreviewSizedPath
  22. from tracim.models.context_models import RevisionPreviewSizedPath
  23. from tracim.models.context_models import PageQuery
  24. from tracim.models.context_models import WorkspaceAndContentRevisionPath
  25. from tracim.models.context_models import WorkspaceMemberInvitation
  26. from tracim.models.context_models import WorkspaceUpdate
  27. from tracim.models.context_models import RoleUpdate
  28. from tracim.models.context_models import CommentCreation
  29. from tracim.models.context_models import TextBasedContentUpdate
  30. from tracim.models.context_models import SetContentStatus
  31. from tracim.models.context_models import CommentPath
  32. from tracim.models.context_models import MoveParams
  33. from tracim.models.context_models import WorkspaceAndContentPath
  34. from tracim.models.context_models import WorkspaceAndUserPath
  35. from tracim.models.context_models import ContentFilter
  36. from tracim.models.context_models import LoginCredentials
  37. from tracim.models.data import UserRoleInWorkspace
  38. from tracim.models.data import ActionDescription
  39. class UserDigestSchema(marshmallow.Schema):
  40. """
  41. Simple user schema
  42. """
  43. user_id = marshmallow.fields.Int(dump_only=True, example=3)
  44. avatar_url = marshmallow.fields.Url(
  45. allow_none=True,
  46. example="/api/v2/assets/avatars/suri-cate.jpg",
  47. description="avatar_url is the url to the image file. "
  48. "If no avatar, then set it to null "
  49. "(and frontend will interpret this with a default avatar)",
  50. )
  51. public_name = marshmallow.fields.String(
  52. example='Suri Cate',
  53. )
  54. class UserSchema(UserDigestSchema):
  55. """
  56. Complete user schema
  57. """
  58. email = marshmallow.fields.Email(
  59. required=True,
  60. example='suri.cate@algoo.fr'
  61. )
  62. created = marshmallow.fields.DateTime(
  63. format=DATETIME_FORMAT,
  64. description='User account creation date',
  65. )
  66. is_active = marshmallow.fields.Bool(
  67. example=True,
  68. description='Is user account activated ?'
  69. )
  70. # TODO - G.M - 17-04-2018 - Restrict timezone values
  71. timezone = marshmallow.fields.String(
  72. example="Europe/Paris",
  73. )
  74. # TODO - G.M - 17-04-2018 - check this, relative url allowed ?
  75. caldav_url = marshmallow.fields.Url(
  76. allow_none=True,
  77. relative=True,
  78. attribute='calendar_url',
  79. example="/api/v2/calendar/user/3.ics/",
  80. description="The url for calendar CalDAV direct access",
  81. )
  82. profile = marshmallow.fields.String(
  83. attribute='profile',
  84. validate=OneOf(Profile._NAME),
  85. example='managers',
  86. )
  87. class Meta:
  88. description = 'User account of Tracim'
  89. class LoggedInUserPasswordSchema(marshmallow.Schema):
  90. loggedin_user_password = marshmallow.fields.String(
  91. required=True,
  92. )
  93. class SetEmailSchema(LoggedInUserPasswordSchema):
  94. email = marshmallow.fields.Email(
  95. required=True,
  96. example='suri.cate@algoo.fr'
  97. )
  98. @post_load
  99. def create_set_email_object(self, data):
  100. return SetEmail(**data)
  101. class SetPasswordSchema(LoggedInUserPasswordSchema):
  102. new_password = marshmallow.fields.String(
  103. example='8QLa$<w',
  104. required=True
  105. )
  106. new_password2 = marshmallow.fields.String(
  107. example='8QLa$<w',
  108. required=True
  109. )
  110. @post_load
  111. def create_set_password_object(self, data):
  112. return SetPassword(**data)
  113. class UserInfosSchema(marshmallow.Schema):
  114. timezone = marshmallow.fields.String(
  115. example="Europe/Paris",
  116. required=True,
  117. )
  118. public_name = marshmallow.fields.String(
  119. example='Suri Cate',
  120. required=True,
  121. )
  122. @post_load
  123. def create_user_info_object(self, data):
  124. return UserInfos(**data)
  125. class UserProfileSchema(marshmallow.Schema):
  126. profile = marshmallow.fields.String(
  127. attribute='profile',
  128. validate=OneOf(Profile._NAME),
  129. example='managers',
  130. )
  131. @post_load
  132. def create_user_profile(self, data):
  133. return UserProfile(**data)
  134. class UserCreationSchema(
  135. SetEmailSchema,
  136. SetPasswordSchema,
  137. UserInfosSchema,
  138. UserProfileSchema
  139. ):
  140. @post_load
  141. def create_user(self, data):
  142. return UserCreation(**data)
  143. # Path Schemas
  144. class UserIdPathSchema(marshmallow.Schema):
  145. user_id = marshmallow.fields.Int(
  146. example=3,
  147. required=True,
  148. description='id of a valid user',
  149. validate=Range(min=1, error="Value must be greater than 0"),
  150. )
  151. class WorkspaceIdPathSchema(marshmallow.Schema):
  152. workspace_id = marshmallow.fields.Int(
  153. example=4,
  154. required=True,
  155. description='id of a valid workspace',
  156. validate=Range(min=1, error="Value must be greater than 0"),
  157. )
  158. class ContentIdPathSchema(marshmallow.Schema):
  159. content_id = marshmallow.fields.Int(
  160. example=6,
  161. required=True,
  162. description='id of a valid content',
  163. validate=Range(min=1, error="Value must be greater than 0"),
  164. )
  165. class RevisionIdPathSchema(marshmallow.Schema):
  166. revision_id = marshmallow.fields.Int(example=6, required=True)
  167. class WorkspaceAndUserIdPathSchema(
  168. UserIdPathSchema,
  169. WorkspaceIdPathSchema
  170. ):
  171. @post_load
  172. def make_path_object(self, data):
  173. return WorkspaceAndUserPath(**data)
  174. class WorkspaceAndContentIdPathSchema(
  175. WorkspaceIdPathSchema,
  176. ContentIdPathSchema
  177. ):
  178. @post_load
  179. def make_path_object(self, data):
  180. return WorkspaceAndContentPath(**data)
  181. class WidthAndHeightPathSchema(marshmallow.Schema):
  182. width = marshmallow.fields.Int(example=256)
  183. height = marshmallow.fields.Int(example=256)
  184. class AllowedJpgPreviewSizesSchema(marshmallow.Schema):
  185. width = marshmallow.fields.Int(example=256)
  186. height = marshmallow.fields.Int(example=256)
  187. class AllowedJpgPreviewDimSchema(marshmallow.Schema):
  188. restricted = marshmallow.fields.Bool()
  189. dimensions = marshmallow.fields.Nested(
  190. AllowedJpgPreviewSizesSchema,
  191. many=True
  192. )
  193. class WorkspaceAndContentRevisionIdPathSchema(
  194. WorkspaceIdPathSchema,
  195. ContentIdPathSchema,
  196. RevisionIdPathSchema,
  197. ):
  198. @post_load
  199. def make_path_object(self, data):
  200. return WorkspaceAndContentRevisionPath(**data)
  201. class ContentPreviewSizedPathSchema(
  202. WorkspaceAndContentIdPathSchema,
  203. WidthAndHeightPathSchema
  204. ):
  205. @post_load
  206. def make_path_object(self, data):
  207. return ContentPreviewSizedPath(**data)
  208. class RevisionPreviewSizedPathSchema(
  209. WorkspaceAndContentRevisionIdPathSchema,
  210. WidthAndHeightPathSchema
  211. ):
  212. @post_load
  213. def make_path_object(self, data):
  214. return RevisionPreviewSizedPath(**data)
  215. class UserWorkspaceAndContentIdPathSchema(
  216. UserIdPathSchema,
  217. WorkspaceIdPathSchema,
  218. ContentIdPathSchema,
  219. ):
  220. @post_load
  221. def make_path_object(self, data):
  222. return UserWorkspaceAndContentPath(**data)
  223. class UserWorkspaceIdPathSchema(
  224. UserIdPathSchema,
  225. WorkspaceIdPathSchema,
  226. ):
  227. @post_load
  228. def make_path_object(self, data):
  229. return WorkspaceAndUserPath(**data)
  230. class CommentsPathSchema(WorkspaceAndContentIdPathSchema):
  231. comment_id = marshmallow.fields.Int(
  232. example=6,
  233. description='id of a valid comment related to content content_id',
  234. required=True,
  235. validate=Range(min=1, error="Value must be greater than 0"),
  236. )
  237. @post_load
  238. def make_path_object(self, data):
  239. return CommentPath(**data)
  240. class PageQuerySchema(marshmallow.Schema):
  241. page = marshmallow.fields.Int(
  242. example=2,
  243. default=0,
  244. description='allow to show a specific page of a pdf file',
  245. validate=Range(min=0, error="Value must be positive or 0"),
  246. )
  247. @post_load
  248. def make_page_query(self, data):
  249. return PageQuery(**data)
  250. class FilterContentQuerySchema(marshmallow.Schema):
  251. parent_id = marshmallow.fields.Int(
  252. example=2,
  253. default=0,
  254. description='allow to filter items in a folder.'
  255. ' If not set, then return all contents.'
  256. ' If set to 0, then return root contents.'
  257. ' If set to another value, return all contents'
  258. ' directly included in the folder parent_id',
  259. validate=Range(min=0, error="Value must be positive or 0"),
  260. )
  261. show_archived = marshmallow.fields.Int(
  262. example=0,
  263. default=0,
  264. description='if set to 1, then show archived contents.'
  265. ' Default is 0 - hide archived content',
  266. validate=Range(min=0, max=1, error="Value must be 0 or 1"),
  267. )
  268. show_deleted = marshmallow.fields.Int(
  269. example=0,
  270. default=0,
  271. description='if set to 1, then show deleted contents.'
  272. ' Default is 0 - hide deleted content',
  273. validate=Range(min=0, max=1, error="Value must be 0 or 1"),
  274. )
  275. show_active = marshmallow.fields.Int(
  276. example=1,
  277. default=1,
  278. description='f set to 1, then show active contents. '
  279. 'Default is 1 - show active content.'
  280. ' Note: active content are content '
  281. 'that is neither archived nor deleted. '
  282. 'The reason for this parameter to exist is for example '
  283. 'to allow to show only archived documents',
  284. validate=Range(min=0, max=1, error="Value must be 0 or 1"),
  285. )
  286. content_type = marshmallow.fields.String(
  287. example=ContentType.Any,
  288. default=ContentType.Any,
  289. validate=OneOf(ContentType.allowed_type_values())
  290. )
  291. @post_load
  292. def make_content_filter(self, data):
  293. return ContentFilter(**data)
  294. class ActiveContentFilterQuerySchema(marshmallow.Schema):
  295. limit = marshmallow.fields.Int(
  296. example=2,
  297. default=0,
  298. description='if 0 or not set, return all elements, else return only '
  299. 'the first limit elem (according to offset)',
  300. validate=Range(min=0, error="Value must be positive or 0"),
  301. )
  302. before_datetime = marshmallow.fields.DateTime(
  303. format=DATETIME_FORMAT,
  304. description='return only content lastly updated before this date',
  305. )
  306. @post_load
  307. def make_content_filter(self, data):
  308. return ActiveContentFilter(**data)
  309. class ContentIdsQuerySchema(marshmallow.Schema):
  310. contents_ids = marshmallow.fields.List(
  311. marshmallow.fields.Int(
  312. example=6,
  313. validate=Range(min=1, error="Value must be greater than 0"),
  314. )
  315. )
  316. @post_load
  317. def make_contents_ids(self, data):
  318. return ContentIdsQuery(**data)
  319. ###
  320. class RoleUpdateSchema(marshmallow.Schema):
  321. role = marshmallow.fields.String(
  322. example='contributor',
  323. validate=OneOf(UserRoleInWorkspace.get_all_role_slug())
  324. )
  325. @post_load
  326. def make_role(self, data):
  327. return RoleUpdate(**data)
  328. class WorkspaceMemberInviteSchema(RoleUpdateSchema):
  329. user_id = marshmallow.fields.Int(
  330. example=5,
  331. default=None,
  332. allow_none=True,
  333. )
  334. user_email_or_public_name = marshmallow.fields.String(
  335. example='suri@cate.fr',
  336. default=None,
  337. allow_none=True,
  338. )
  339. @post_load
  340. def make_role(self, data):
  341. return WorkspaceMemberInvitation(**data)
  342. class BasicAuthSchema(marshmallow.Schema):
  343. email = marshmallow.fields.Email(
  344. example='suri.cate@algoo.fr',
  345. required=True
  346. )
  347. password = marshmallow.fields.String(
  348. example='8QLa$<w',
  349. required=True,
  350. load_only=True,
  351. )
  352. class Meta:
  353. description = 'Entry for HTTP Basic Auth'
  354. @post_load
  355. def make_login(self, data):
  356. return LoginCredentials(**data)
  357. class LoginOutputHeaders(marshmallow.Schema):
  358. expire_after = marshmallow.fields.String()
  359. class WorkspaceModifySchema(marshmallow.Schema):
  360. label = marshmallow.fields.String(
  361. example='My Workspace',
  362. )
  363. description = marshmallow.fields.String(
  364. example='A super description of my workspace.',
  365. )
  366. @post_load
  367. def make_workspace_modifications(self, data):
  368. return WorkspaceUpdate(**data)
  369. class WorkspaceCreationSchema(WorkspaceModifySchema):
  370. pass
  371. class NoContentSchema(marshmallow.Schema):
  372. class Meta:
  373. description = 'Empty Schema'
  374. pass
  375. class WorkspaceMenuEntrySchema(marshmallow.Schema):
  376. slug = marshmallow.fields.String(example='markdown-pages')
  377. label = marshmallow.fields.String(example='Markdown Documents')
  378. route = marshmallow.fields.String(
  379. example='/#/workspace/{workspace_id}/contents/?type=mardown-page',
  380. description='the route is the frontend route. '
  381. 'It may include workspace_id '
  382. 'which must be replaced on backend size '
  383. '(the route must be ready-to-use)'
  384. )
  385. fa_icon = marshmallow.fields.String(
  386. example='file-text-o',
  387. description='CSS class of the icon. Example: file-o for using Fontawesome file-text-o icon', # nopep8
  388. )
  389. hexcolor = marshmallow.fields.String(
  390. example='#F0F9DC',
  391. description='Hexadecimal color of the entry.'
  392. )
  393. class Meta:
  394. description = 'Entry element of a workspace menu'
  395. class WorkspaceDigestSchema(marshmallow.Schema):
  396. workspace_id = marshmallow.fields.Int(
  397. example=4,
  398. validate=Range(min=1, error="Value must be greater than 0"),
  399. )
  400. slug = marshmallow.fields.String(example='intranet')
  401. label = marshmallow.fields.String(example='Intranet')
  402. sidebar_entries = marshmallow.fields.Nested(
  403. WorkspaceMenuEntrySchema,
  404. many=True,
  405. )
  406. class Meta:
  407. description = 'Digest of workspace informations'
  408. class WorkspaceSchema(WorkspaceDigestSchema):
  409. description = marshmallow.fields.String(example='All intranet data.')
  410. class Meta:
  411. description = 'Full workspace informations'
  412. class WorkspaceMemberSchema(marshmallow.Schema):
  413. role = marshmallow.fields.String(
  414. example='contributor',
  415. validate=OneOf(UserRoleInWorkspace.get_all_role_slug())
  416. )
  417. user_id = marshmallow.fields.Int(
  418. example=3,
  419. validate=Range(min=1, error="Value must be greater than 0"),
  420. )
  421. workspace_id = marshmallow.fields.Int(
  422. example=4,
  423. validate=Range(min=1, error="Value must be greater than 0"),
  424. )
  425. user = marshmallow.fields.Nested(
  426. UserDigestSchema()
  427. )
  428. workspace = marshmallow.fields.Nested(
  429. WorkspaceDigestSchema(exclude=('sidebar_entries',))
  430. )
  431. is_active = marshmallow.fields.Bool()
  432. class Meta:
  433. description = 'Workspace Member information'
  434. class WorkspaceMemberCreationSchema(WorkspaceMemberSchema):
  435. newly_created = marshmallow.fields.Bool(
  436. exemple=False,
  437. description='Is the user completely new '
  438. '(and account was just created) or not ?',
  439. )
  440. email_sent = marshmallow.fields.Bool(
  441. exemple=False,
  442. description='Has an email been sent to user to inform him about '
  443. 'this new workspace registration and eventually his account'
  444. 'creation'
  445. )
  446. class ApplicationConfigSchema(marshmallow.Schema):
  447. pass
  448. # TODO - G.M - 24-05-2018 - Set this
  449. class ApplicationSchema(marshmallow.Schema):
  450. label = marshmallow.fields.String(example='Calendar')
  451. slug = marshmallow.fields.String(example='calendar')
  452. fa_icon = marshmallow.fields.String(
  453. example='file-o',
  454. description='CSS class of the icon. Example: file-o for using Fontawesome file-o icon', # nopep8
  455. )
  456. hexcolor = marshmallow.fields.String(
  457. example='#FF0000',
  458. description='HTML encoded color associated to the application. Example:#FF0000 for red' # nopep8
  459. )
  460. is_active = marshmallow.fields.Boolean(
  461. example=True,
  462. description='if true, the application is in use in the context',
  463. )
  464. config = marshmallow.fields.Nested(
  465. ApplicationConfigSchema,
  466. )
  467. class Meta:
  468. description = 'Tracim Application informations'
  469. class StatusSchema(marshmallow.Schema):
  470. slug = marshmallow.fields.String(
  471. example='open',
  472. description='the slug represents the type of status. '
  473. 'Statuses are open, closed-validated, closed-invalidated, closed-deprecated' # nopep8
  474. )
  475. global_status = marshmallow.fields.String(
  476. example='open',
  477. description='global_status: open, closed',
  478. validate=OneOf([status.value for status in GlobalStatus]),
  479. )
  480. label = marshmallow.fields.String(example='Open')
  481. fa_icon = marshmallow.fields.String(example='fa-check')
  482. hexcolor = marshmallow.fields.String(example='#0000FF')
  483. class ContentTypeSchema(marshmallow.Schema):
  484. slug = marshmallow.fields.String(
  485. example='pagehtml',
  486. validate=OneOf(ContentType.allowed_types()),
  487. )
  488. fa_icon = marshmallow.fields.String(
  489. example='fa-file-text-o',
  490. description='CSS class of the icon. Example: file-o for using Fontawesome file-o icon', # nopep8
  491. )
  492. hexcolor = marshmallow.fields.String(
  493. example="#FF0000",
  494. description='HTML encoded color associated to the application. Example:#FF0000 for red' # nopep8
  495. )
  496. label = marshmallow.fields.String(
  497. example='Text Documents'
  498. )
  499. creation_label = marshmallow.fields.String(
  500. example='Write a document'
  501. )
  502. available_statuses = marshmallow.fields.Nested(
  503. StatusSchema,
  504. many=True
  505. )
  506. class ContentMoveSchema(marshmallow.Schema):
  507. # TODO - G.M - 30-05-2018 - Read and apply this note
  508. # Note:
  509. # if the new workspace is different, then the backend
  510. # must check if the user is allowed to move to this workspace
  511. # (the user must be content manager of both workspaces)
  512. new_parent_id = marshmallow.fields.Int(
  513. example=42,
  514. description='id of the new parent content id.',
  515. allow_none=True,
  516. required=True,
  517. validate=Range(min=0, error="Value must be positive or 0"),
  518. )
  519. new_workspace_id = marshmallow.fields.Int(
  520. example=2,
  521. description='id of the new workspace id.',
  522. required=True,
  523. validate=Range(min=1, error="Value must be greater than 0"),
  524. )
  525. @post_load
  526. def make_move_params(self, data):
  527. return MoveParams(**data)
  528. class ContentCreationSchema(marshmallow.Schema):
  529. label = marshmallow.fields.String(
  530. example='contract for client XXX',
  531. description='Title of the content to create'
  532. )
  533. content_type = marshmallow.fields.String(
  534. example='html-documents',
  535. validate=OneOf(ContentType.allowed_types_for_folding()), # nopep8
  536. )
  537. parent_id = marshmallow.fields.Integer(
  538. example=35,
  539. description='content_id of parent content, if content should be placed in a folder, this should be folder content_id.'
  540. )
  541. @post_load
  542. def make_content_filter(self, data):
  543. return ContentCreation(**data)
  544. class ContentDigestSchema(marshmallow.Schema):
  545. content_id = marshmallow.fields.Int(
  546. example=6,
  547. validate=Range(min=1, error="Value must be greater than 0"),
  548. )
  549. slug = marshmallow.fields.Str(example='intervention-report-12')
  550. parent_id = marshmallow.fields.Int(
  551. example=34,
  552. allow_none=True,
  553. default=None,
  554. validate=Range(min=0, error="Value must be positive or 0"),
  555. )
  556. workspace_id = marshmallow.fields.Int(
  557. example=19,
  558. validate=Range(min=1, error="Value must be greater than 0"),
  559. )
  560. label = marshmallow.fields.Str(example='Intervention Report 12')
  561. content_type = marshmallow.fields.Str(
  562. example='html-documents',
  563. validate=OneOf(ContentType.allowed_types()),
  564. )
  565. sub_content_types = marshmallow.fields.List(
  566. marshmallow.fields.String(
  567. example='html-content',
  568. validate=OneOf(ContentType.allowed_types())
  569. ),
  570. description='list of content types allowed as sub contents. '
  571. 'This field is required for folder contents, '
  572. 'set it to empty list in other cases'
  573. )
  574. status = marshmallow.fields.Str(
  575. example='closed-deprecated',
  576. validate=OneOf(ContentStatus.allowed_values()),
  577. description='this slug is found in content_type available statuses',
  578. default=open_status
  579. )
  580. is_archived = marshmallow.fields.Bool(example=False, default=False)
  581. is_deleted = marshmallow.fields.Bool(example=False, default=False)
  582. show_in_ui = marshmallow.fields.Bool(
  583. example=True,
  584. description='if false, then do not show content in the treeview. '
  585. 'This may his maybe used for specific contents or '
  586. 'for sub-contents. Default is True. '
  587. 'In first version of the API, this field is always True',
  588. )
  589. class ReadStatusSchema(marshmallow.Schema):
  590. content_id = marshmallow.fields.Int(
  591. example=6,
  592. validate=Range(min=1, error="Value must be greater than 0"),
  593. )
  594. read_by_user = marshmallow.fields.Bool(example=False, default=False)
  595. #####
  596. # Content
  597. #####
  598. class ContentSchema(ContentDigestSchema):
  599. current_revision_id = marshmallow.fields.Int(example=12)
  600. created = marshmallow.fields.DateTime(
  601. format=DATETIME_FORMAT,
  602. description='Content creation date',
  603. )
  604. author = marshmallow.fields.Nested(UserDigestSchema)
  605. modified = marshmallow.fields.DateTime(
  606. format=DATETIME_FORMAT,
  607. description='date of last modification of content',
  608. )
  609. last_modifier = marshmallow.fields.Nested(UserDigestSchema)
  610. class TextBasedDataAbstractSchema(marshmallow.Schema):
  611. raw_content = marshmallow.fields.String(
  612. description='Content of the object, may be raw text or <b>html</b> for example' # nopep8
  613. )
  614. class FileInfoAbstractSchema(marshmallow.Schema):
  615. raw_content = marshmallow.fields.String(
  616. description='raw text or html description of the file'
  617. )
  618. class TextBasedContentSchema(ContentSchema, TextBasedDataAbstractSchema):
  619. pass
  620. class FileContentSchema(ContentSchema, FileInfoAbstractSchema):
  621. pass
  622. #####
  623. # Revision
  624. #####
  625. class RevisionSchema(ContentDigestSchema):
  626. comment_ids = marshmallow.fields.List(
  627. marshmallow.fields.Int(
  628. example=4,
  629. validate=Range(min=1, error="Value must be greater than 0"),
  630. )
  631. )
  632. revision_id = marshmallow.fields.Int(
  633. example=12,
  634. validate=Range(min=1, error="Value must be greater than 0"),
  635. )
  636. revision_type = marshmallow.fields.String(
  637. example=ActionDescription.CREATION,
  638. validate=OneOf(ActionDescription.allowed_values()),
  639. )
  640. created = marshmallow.fields.DateTime(
  641. format=DATETIME_FORMAT,
  642. description='Content creation date',
  643. )
  644. author = marshmallow.fields.Nested(UserDigestSchema)
  645. class TextBasedRevisionSchema(RevisionSchema, TextBasedDataAbstractSchema):
  646. pass
  647. class FileRevisionSchema(RevisionSchema, FileInfoAbstractSchema):
  648. pass
  649. class CommentSchema(marshmallow.Schema):
  650. content_id = marshmallow.fields.Int(
  651. example=6,
  652. validate=Range(min=1, error="Value must be greater than 0"),
  653. )
  654. parent_id = marshmallow.fields.Int(
  655. example=34,
  656. validate=Range(min=0, error="Value must be positive or 0"),
  657. )
  658. raw_content = marshmallow.fields.String(
  659. example='<p>This is just an html comment !</p>'
  660. )
  661. author = marshmallow.fields.Nested(UserDigestSchema)
  662. created = marshmallow.fields.DateTime(
  663. format=DATETIME_FORMAT,
  664. description='comment creation date',
  665. )
  666. class SetCommentSchema(marshmallow.Schema):
  667. raw_content = marshmallow.fields.String(
  668. example='<p>This is just an html comment !</p>'
  669. )
  670. @post_load()
  671. def create_comment(self, data):
  672. return CommentCreation(**data)
  673. class ContentModifyAbstractSchema(marshmallow.Schema):
  674. label = marshmallow.fields.String(
  675. required=True,
  676. example='contract for client XXX',
  677. description='New title of the content'
  678. )
  679. class TextBasedContentModifySchema(ContentModifyAbstractSchema, TextBasedDataAbstractSchema): # nopep8
  680. @post_load
  681. def text_based_content_update(self, data):
  682. return TextBasedContentUpdate(**data)
  683. class FileContentModifySchema(TextBasedContentModifySchema):
  684. pass
  685. class SetContentStatusSchema(marshmallow.Schema):
  686. status = marshmallow.fields.Str(
  687. example='closed-deprecated',
  688. validate=OneOf(ContentStatus.allowed_values()),
  689. description='this slug is found in content_type available statuses',
  690. default=open_status,
  691. required=True,
  692. )
  693. @post_load
  694. def set_status(self, data):
  695. return SetContentStatus(**data)