schemas.py 12KB

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