schemas.py 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. # coding=utf-8
  2. import marshmallow
  3. from marshmallow import post_load
  4. from marshmallow.validate import OneOf
  5. from tracim.models.auth import Profile
  6. from tracim.models.contents import CONTENT_DEFAULT_TYPE, GlobalStatus, CONTENT_DEFAULT_STATUS
  7. from tracim.models.context_models import LoginCredentials, ContentFilter
  8. from tracim.models.data import UserRoleInWorkspace
  9. class ProfileSchema(marshmallow.Schema):
  10. slug = marshmallow.fields.String(
  11. attribute='name',
  12. validate=OneOf(Profile._NAME),
  13. example='managers',
  14. )
  15. class Meta:
  16. description = 'User Profile, give user right on whole Tracim instance.'
  17. class UserSchema(marshmallow.Schema):
  18. user_id = marshmallow.fields.Int(dump_only=True, example=3)
  19. email = marshmallow.fields.Email(
  20. required=True,
  21. example='suri.cate@algoo.fr'
  22. )
  23. display_name = marshmallow.fields.String(
  24. example='Suri Cate',
  25. )
  26. created = marshmallow.fields.DateTime(
  27. format='iso8601',
  28. description='User account creation date (iso8601 format).',
  29. )
  30. is_active = marshmallow.fields.Bool(
  31. example=True,
  32. # TODO - G.M - Explains this value.
  33. )
  34. # TODO - G.M - 17-04-2018 - Restrict timezone values
  35. timezone = marshmallow.fields.String(
  36. example="Paris/Europe",
  37. )
  38. # TODO - G.M - 17-04-2018 - check this, relative url allowed ?
  39. caldav_url = marshmallow.fields.Url(
  40. allow_none=True,
  41. relative=True,
  42. attribute='calendar_url',
  43. example="/api/v2/calendar/user/3.ics/",
  44. description="The url for calendar CalDAV direct access",
  45. )
  46. avatar_url = marshmallow.fields.Url(
  47. allow_none=True,
  48. example="/api/v2/assets/avatars/suri-cate.jpg",
  49. description="avatar_url is the url to the image file. "
  50. "If no avatar, then set it to null "
  51. "(and frontend will interpret this with a default avatar)",
  52. )
  53. profile = marshmallow.fields.Nested(
  54. ProfileSchema,
  55. many=False,
  56. )
  57. class Meta:
  58. description = 'User account of Tracim'
  59. # Path Schemas
  60. class UserIdPathSchema(marshmallow.Schema):
  61. user_id = marshmallow.fields.Int(example=3, required=True)
  62. class WorkspaceIdPathSchema(marshmallow.Schema):
  63. workspace_id = marshmallow.fields.Int(example=4, required=True)
  64. class ContentIdPathSchema(marshmallow.Schema):
  65. content_id = marshmallow.fields.Int(example=6, required=True)
  66. class WorkspaceAndContentIdPathSchema(WorkspaceIdPathSchema, ContentIdPathSchema):
  67. pass
  68. class FilterContentQuerySchema(marshmallow.Schema):
  69. parent_id = workspace_id = marshmallow.fields.Int(
  70. example=2,
  71. default=None,
  72. description='allow to filter items in a folder.'
  73. ' If not set, then return all contents.'
  74. ' If set to 0, then return root contents.'
  75. ' If set to another value, return all contents'
  76. ' directly included in the folder parent_id'
  77. )
  78. show_archived = marshmallow.fields.Int(
  79. example=0,
  80. default=0,
  81. description='if set to 1, then show archived contents.'
  82. ' Default is 0 - hide archived content'
  83. )
  84. show_deleted = marshmallow.fields.Int(
  85. example=0,
  86. default=0,
  87. description='if set to 1, then show deleted contents.'
  88. ' Default is 0 - hide deleted content'
  89. )
  90. show_active = marshmallow.fields.Int(
  91. example=1,
  92. default=1,
  93. description='f set to 1, then show active contents. '
  94. 'Default is 1 - show active content.'
  95. ' Note: active content are content '
  96. 'that is neither archived nor deleted. '
  97. 'The reason for this parameter to exist is for example '
  98. 'to allow to show only archived documents'
  99. )
  100. @post_load
  101. def make_content_filter(self, data):
  102. return ContentFilter(**data)
  103. ###
  104. class BasicAuthSchema(marshmallow.Schema):
  105. email = marshmallow.fields.Email(
  106. example='suri.cate@algoo.fr',
  107. required=True
  108. )
  109. password = marshmallow.fields.String(
  110. example='8QLa$<w',
  111. required=True,
  112. load_only=True,
  113. )
  114. class Meta:
  115. description = 'Entry for HTTP Basic Auth'
  116. @post_load
  117. def make_login(self, data):
  118. return LoginCredentials(**data)
  119. class LoginOutputHeaders(marshmallow.Schema):
  120. expire_after = marshmallow.fields.String()
  121. class NoContentSchema(marshmallow.Schema):
  122. class Meta:
  123. description = 'Empty Schema'
  124. pass
  125. class WorkspaceMenuEntrySchema(marshmallow.Schema):
  126. slug = marshmallow.fields.String(example='markdown-pages')
  127. label = marshmallow.fields.String(example='Markdown Documents')
  128. route = marshmallow.fields.String(
  129. example='/#/workspace/{workspace_id}/contents/?type=mardown-page',
  130. description='the route is the frontend route. '
  131. 'It may include workspace_id '
  132. 'which must be replaced on backend size '
  133. '(the route must be ready-to-use)'
  134. )
  135. icon = marshmallow.fields.String(
  136. example='file-text-o',
  137. description='CSS class of the icon. Example: file-o for using Fontawesome file-text-o icon', # nopep8
  138. )
  139. hexcolor = marshmallow.fields.String(
  140. example='#F0F9DC',
  141. description='Hexadecimal color of the entry.'
  142. )
  143. class Meta:
  144. description = 'Entry element of a workspace menu'
  145. class WorkspaceSchema(marshmallow.Schema):
  146. id = marshmallow.fields.Int(example=4)
  147. slug = marshmallow.fields.String(example='intranet')
  148. label = marshmallow.fields.String(example='Intranet')
  149. description = marshmallow.fields.String(example='All intranet data.')
  150. sidebar_entries = marshmallow.fields.Nested(
  151. WorkspaceMenuEntrySchema,
  152. many=True,
  153. )
  154. class Meta:
  155. description = 'Full workspace informations'
  156. class WorkspaceDigestSchema(marshmallow.Schema):
  157. id = marshmallow.fields.Int(example=4)
  158. label = marshmallow.fields.String(example='Intranet')
  159. sidebar_entries = marshmallow.fields.Nested(
  160. WorkspaceMenuEntrySchema,
  161. many=True,
  162. )
  163. class Meta:
  164. description = 'Digest of workspace informations'
  165. class WorkspaceMemberSchema(marshmallow.Schema):
  166. role_slug = marshmallow.fields.String(
  167. example='contributor',
  168. validate=OneOf(UserRoleInWorkspace.get_all_role_slug())
  169. )
  170. user_id = marshmallow.fields.Int(example=3)
  171. workspace_id = marshmallow.fields.Int(example=4)
  172. user = marshmallow.fields.Nested(
  173. UserSchema(only=('display_name', 'avatar_url'))
  174. )
  175. class Meta:
  176. description = 'Workspace Member information'
  177. class ApplicationConfigSchema(marshmallow.Schema):
  178. pass
  179. # TODO - G.M - 24-05-2018 - Set this
  180. class ApplicationSchema(marshmallow.Schema):
  181. label = marshmallow.fields.String(example='Calendar')
  182. slug = marshmallow.fields.String(example='calendar')
  183. icon = marshmallow.fields.String(
  184. example='file-o',
  185. description='CSS class of the icon. Example: file-o for using Fontawesome file-o icon', # nopep8
  186. )
  187. hexcolor = marshmallow.fields.String(
  188. example='#FF0000',
  189. description='HTML encoded color associated to the application. Example:#FF0000 for red' # nopep8
  190. )
  191. is_active = marshmallow.fields.Boolean(
  192. example=True,
  193. description='if true, the application is in use in the context',
  194. )
  195. config = marshmallow.fields.Nested(
  196. ApplicationConfigSchema,
  197. )
  198. class Meta:
  199. description = 'Tracim Application informations'
  200. class StatusSchema(marshmallow.Schema):
  201. slug = marshmallow.fields.String(
  202. example='open',
  203. description='the slug represents the type of status. '
  204. 'Statuses are open, closed-validated, closed-invalidated, closed-deprecated' # nopep8
  205. )
  206. global_status = marshmallow.fields.String(
  207. example='Open',
  208. description='global_status: open, closed',
  209. validate=OneOf([status.value for status in GlobalStatus]),
  210. )
  211. label = marshmallow.fields.String(example='Open')
  212. icon = marshmallow.fields.String(example='fa-check')
  213. hexcolor = marshmallow.fields.String(example='#0000FF')
  214. class ContentTypeSchema(marshmallow.Schema):
  215. slug = marshmallow.fields.String(
  216. example='pagehtml',
  217. validate=OneOf([content.slug for content in CONTENT_DEFAULT_TYPE]),
  218. )
  219. icon = marshmallow.fields.String(
  220. example='fa-file-text-o',
  221. description='CSS class of the icon. Example: file-o for using Fontawesome file-o icon', # nopep8
  222. )
  223. hexcolor = marshmallow.fields.String(
  224. example="#FF0000",
  225. description='HTML encoded color associated to the application. Example:#FF0000 for red' # nopep8
  226. )
  227. label = marshmallow.fields.String(
  228. example='Text Documents'
  229. )
  230. creation_label = marshmallow.fields.String(
  231. example='Write a document'
  232. )
  233. available_statuses = marshmallow.fields.Nested(
  234. StatusSchema,
  235. many=True
  236. )
  237. class ContentMoveSchema(marshmallow.Schema):
  238. # TODO - G.M - 30-05-2018 - Read and apply this note
  239. # Note:
  240. # if the new workspace is different, then the backend
  241. # must check if the user is allowed to move to this workspace
  242. # (the user must be content manager of both workspaces)
  243. new_parent_id = marshmallow.fields.Int(
  244. example=42,
  245. description='id of the new parent content id.'
  246. )
  247. class ContentCreationSchema(marshmallow.Schema):
  248. label = marshmallow.fields.String(
  249. example='contract for client XXX',
  250. description='Title of the content to create'
  251. )
  252. content_type_slug = marshmallow.fields.String(
  253. example='htmlpage',
  254. validate=OneOf(CONTENT_DEFAULT_TYPE),
  255. )
  256. class ContentDigestSchema(marshmallow.Schema):
  257. id = marshmallow.fields.Int(example=6)
  258. slug = marshmallow.fields.Str(example='intervention-report-12')
  259. parent_id = marshmallow.fields.Int(
  260. example=34,
  261. allow_none=True,
  262. default=None
  263. )
  264. workspace_id = marshmallow.fields.Int(
  265. example=19,
  266. )
  267. label = marshmallow.fields.Str(example='Intervention Report 12')
  268. content_type_slug = marshmallow.fields.Str(
  269. example='htmlpage',
  270. validate=OneOf([content.slug for content in CONTENT_DEFAULT_TYPE]),
  271. )
  272. sub_content_type_slug = marshmallow.fields.List(
  273. marshmallow.fields.Str,
  274. description='list of content types allowed as sub contents. '
  275. 'This field is required for folder contents, '
  276. 'set it to empty list in other cases'
  277. )
  278. status_slug = marshmallow.fields.Str(
  279. example='closed-deprecated',
  280. validate=OneOf([status.slug for status in CONTENT_DEFAULT_STATUS]),
  281. description='this slug is found in content_type available statuses',
  282. )
  283. is_archived = marshmallow.fields.Bool(example=False)
  284. is_deleted = marshmallow.fields.Bool(example=False)
  285. show_in_ui = marshmallow.fields.Bool(
  286. example=True,
  287. description='if false, then do not show content in the treeview. '
  288. 'This may his maybe used for specific contents or '
  289. 'for sub-contents. Default is True. '
  290. 'In first version of the API, this field is always True',
  291. )