PageRenderTime 43ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/api/routes/Stories.py

https://gitlab.com/fdemian/Shelob
Python | 359 lines | 271 code | 80 blank | 8 comment | 24 complexity | e99ae73d4af3fc372b698abe9851c97b MD5 | raw file
  1. import json
  2. from api.model.models import Story, User, Category
  3. from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
  4. from api.authentication.AuthenticatedHandler import AuthenticatedHandler
  5. from tornado.web import RequestHandler
  6. from tornado.gen import coroutine
  7. from api.Utils import authenticated
  8. import datetime
  9. class StoriesHandler(AuthenticatedHandler):
  10. def data_received(self, chunk):
  11. pass
  12. # GET /stories
  13. @coroutine
  14. def get(self):
  15. session = self.settings['db']
  16. story_id = self.get_argument("id", default=None)
  17. if story_id is not None:
  18. story = session.query(Story).filter(Story.id == story_id and Story.is_draft == False).one()
  19. if story.category is None:
  20. category = {'id': -1, 'name': "uncatalogued"}
  21. else:
  22. category = {'id': story.category.id, 'name': story.category.name}
  23. comments = []
  24. for comment in story.comments:
  25. json_comment = {
  26. 'id': comment.id,
  27. 'author': comment.author,
  28. 'content': comment.content,
  29. 'avatar': comment.avatar,
  30. 'url': comment.url,
  31. 'date': str(comment.date)
  32. }
  33. comments.append(json_comment)
  34. json_author = {
  35. 'id': story.author.id,
  36. 'name': story.author.fullname,
  37. 'avatar': story.author.avatar,
  38. 'username': story.author.username,
  39. 'signature': story.author.signature
  40. }
  41. response = {
  42. 'id': story.id,
  43. 'title': story.title,
  44. 'category': category,
  45. 'content': story.content,
  46. 'comments': comments,
  47. 'tags': story.tags.split(','),
  48. 'author': json_author,
  49. 'date': str(story.date)
  50. }
  51. self.set_header("Content-Type", "application/jsonp;charset=UTF-8")
  52. self.set_header("Access-Control-Allow-Origin", "*")
  53. self.write(response)
  54. return
  55. else:
  56. # Hardcoded page page size. Move to configuration options.
  57. page_number = int(self.get_argument("page", default=0))
  58. PAGE_SIZE = 5
  59. OFFSET = PAGE_SIZE * page_number
  60. all_stories = session.query(Story).filter(Story.is_draft == False).order_by(Story.id.desc()).limit(PAGE_SIZE).offset(OFFSET)
  61. row_count = session.query(Story).count()
  62. data = []
  63. for story in all_stories:
  64. if story.category is None:
  65. category = {'id': -1, 'name': "Uncategorized"}
  66. else:
  67. category = {'id': story.category.id, 'name': story.category.name}
  68. json_story = {
  69. 'id': story.id,
  70. 'name': story.title,
  71. 'content': story.content,
  72. 'tags': story.tags.split(','),
  73. 'author': {
  74. 'id': story.user.id,
  75. 'name': story.user.username,
  76. 'avatar': story.user.avatar
  77. },
  78. 'comments': len(story.comments),
  79. 'date': str(story.date),
  80. 'category': category
  81. }
  82. data.append(json_story)
  83. response = {
  84. "page": page_number,
  85. "items": data,
  86. "pageSize": PAGE_SIZE,
  87. "totalItems": row_count
  88. }
  89. self.set_header("Content-Type", "application/jsonp;charset=UTF-8")
  90. self.set_header("Access-Control-Allow-Origin", "*")
  91. self.write(response)
  92. return
  93. # POST /stories/new
  94. @authenticated
  95. def post(self):
  96. request = self.request.body.decode("utf-8")
  97. json_request = json.loads(json.loads(request))
  98. title = json_request["title"]
  99. tags = ",".join(json_request["tags"])
  100. content = json.dumps(json_request["content"])
  101. author_id = json_request["author"]
  102. category_id = json_request["category"]
  103. is_draft = json_request['is_draft']
  104. session = self.settings['db']
  105. try:
  106. category = session.query(Category).filter(Category.id == category_id).one()
  107. except NoResultFound:
  108. category = None
  109. story = self.save_story(session, content, title, author_id, category, tags, is_draft)
  110. if story.category is not None:
  111. category = {'id': story.category.id, 'name': story.category.name}
  112. else:
  113. category = None
  114. json_story = {
  115. 'id': story.id,
  116. 'name': story.title,
  117. 'content': story.content,
  118. 'tags': story.tags.split(','),
  119. 'author': {
  120. 'id': story.user.id,
  121. 'name': story.user.username,
  122. 'avatar': story.user.avatar
  123. },
  124. 'comments': [],
  125. 'category': category,
  126. 'date': str(story.date),
  127. 'is_draft': str(is_draft)
  128. }
  129. self.set_status(200, 'Ok')
  130. self.set_header("Access-Control-Allow-Origin", "*")
  131. self.write(json.dumps(json_story))
  132. # PUT /stories/:story_id
  133. @authenticated
  134. def put(self, story_id):
  135. request = self.request.body.decode("utf-8")
  136. json_request = json.loads(json.loads(request))
  137. content = json.dumps(json_request["content"])
  138. session = self.settings['db']
  139. category_id = json_request["category"]
  140. is_draft = json_request["is_draft"]
  141. try:
  142. category = session.query(Category).filter(Category.id == category_id).one()
  143. except NoResultFound:
  144. category = None
  145. try:
  146. tags = ",".join(json_request["tags"])
  147. story = session.query(Story).filter(Story.id == story_id).one()
  148. story.title = json_request["title"]
  149. story.content = str(content)
  150. story.tags = tags
  151. story.category = category
  152. story.is_draft = is_draft
  153. session.commit()
  154. status = 200
  155. status_str = 'Ok'
  156. response = {'id': story_id}
  157. except NoResultFound:
  158. status = 500
  159. status_str = "error"
  160. response = {'message': 'No story found for the specified id.'}
  161. except MultipleResultsFound:
  162. status = 500
  163. status_str = "error"
  164. response = {'message': 'Multiple stories found for the specified id.'}
  165. json.dumps(response)
  166. self.set_header("Content-Type", "application/jsonp;charset=UTF-8")
  167. self.set_header("Access-Control-Allow-Origin", "*")
  168. self.set_status(status, status_str)
  169. self.write(response)
  170. return
  171. @authenticated
  172. def delete(self, story_id):
  173. session = self.settings['db']
  174. try:
  175. story = session.query(Story).filter(Story.id == story_id).one()
  176. session.delete(story)
  177. session.commit()
  178. status = 200
  179. status_str = 'Ok'
  180. response = {'id': story_id}
  181. except NoResultFound:
  182. status = 500
  183. status_str = "error"
  184. response = {'message': 'No stories found for the specified id.'}
  185. except MultipleResultsFound:
  186. status = 500
  187. status_str = "error"
  188. response = {'message': 'Multiple Stories found for the specified id.'}
  189. self.set_header("Content-Type", "application/jsonp;charset=UTF-8")
  190. self.set_header("Access-Control-Allow-Origin", "*")
  191. self.set_status(status, status_str)
  192. self.write(response)
  193. return
  194. @coroutine
  195. def trace(self):
  196. response = {"message": "This is not a valid method for this resource."}
  197. self.set_status(405, 'Error')
  198. self.set_header("Access-Control-Allow-Origin", "*")
  199. self.write(json.dumps(response))
  200. return
  201. @coroutine
  202. def connect(self):
  203. response = {"message": "This is not a valid method for this resource."}
  204. self.set_status(405, 'Error')
  205. self.set_header("Access-Control-Allow-Origin", "*")
  206. self.write(json.dumps(response))
  207. return
  208. @coroutine
  209. def options(self, *args):
  210. response = {}
  211. self.set_header("Content-Type", "test/plain;charset=UTF-8")
  212. self.set_header("Access-Control-Allow-Origin", "*")
  213. self.set_header("Access-Control-Allow-Headers", "Authorization")
  214. self.set_header("Access-Control-Allow-Methods ", "GET, POST, PUT, DELETE, OPTIONS")
  215. self.set_status(200, "Ok")
  216. self.write(response)
  217. return
  218. @coroutine
  219. def patch(self):
  220. response = {"message": "This is not a valid method for this resource."}
  221. self.set_status(405, 'Error')
  222. self.set_header("Access-Control-Allow-Origin", "*")
  223. self.write(json.dumps(response))
  224. return
  225. @coroutine
  226. def head(self):
  227. response = {"message": "This is not a valid method for this resource."}
  228. self.set_status(405, 'Error')
  229. self.set_header("Access-Control-Allow-Origin", "*")
  230. self.write(json.dumps(response))
  231. return
  232. @staticmethod
  233. def save_story(session, content, title, author_id, category, tags, is_draft):
  234. user = session.query(User).filter(User.id == author_id).one()
  235. current_date = datetime.datetime.now()
  236. story = Story()
  237. story.title = title
  238. story.content = str(content)
  239. story.category = category
  240. story.user_id = author_id
  241. story.tags = tags
  242. story.date = current_date
  243. story.is_draft = is_draft
  244. user.stories.append(story)
  245. session.commit()
  246. return story
  247. # TODO: integrate into stories handler.
  248. class StoriesByUserHandler(RequestHandler):
  249. # GET /user/stories
  250. def get(self, user_id):
  251. session = self.settings['db']
  252. data = []
  253. # TODO: esto no siempre es verdadero.
  254. # Asumimos que el usuario siempre existe.
  255. user = session.query(User).filter(User.id == user_id).one()
  256. all_stories = user.stories
  257. for story in all_stories:
  258. if story.category is None:
  259. category = {'id': -1, 'name': "Uncategorized"}
  260. else:
  261. category = {'id': story.category.id, 'name': story.category.name}
  262. json_story = {
  263. 'id': story.id,
  264. 'name': story.title,
  265. 'author': {
  266. 'id': user.id,
  267. 'name': user.username,
  268. 'avatar': user.avatar,
  269. 'signature': user.signature
  270. },
  271. 'date': str(story.date),
  272. 'comments': len(story.comments),
  273. 'category': category
  274. }
  275. data.append(json_story)
  276. response = {"page": 1, "stories": data}
  277. self.set_header("Content-Type", "application/jsonp;charset=UTF-8")
  278. self.set_header("Access-Control-Allow-Origin", "*")
  279. self.write(response)