Coverage for portality/api/current/bulk/articles.py: 61%
51 statements
« prev ^ index » next coverage.py v6.4.2, created at 2022-07-20 16:12 +0100
« prev ^ index » next coverage.py v6.4.2, created at 2022-07-20 16:12 +0100
1# ~~APIBulkArticles:Feature->APIBulk:Feature~~
2from portality.api.common import Api, Api404Error, Api400Error, Api403Error, Api401Error
3from portality.api.current.crud import ArticlesCrudApi
5from portality.bll import DOAJ
6from portality.bll import exceptions
8from copy import deepcopy
10from portality.bll.exceptions import DuplicateArticleException
13class ArticlesBulkApi(Api):
15 #~~->Swagger:Feature~~
16 # ~~->API:Documentation~~
17 SWAG_TAG = 'Bulk API'
19 @classmethod
20 def create_swag(cls):
21 template = deepcopy(cls.SWAG_TEMPLATE)
22 template['parameters'].append(
23 {
24 "description": "<div class=\"search-query-docs\">A list/array of article JSON objects that you would like to create or update. The contents should be a list, and each object in the list should comply with the schema displayed in the <a href=\"/api/docs#CRUD_Articles_get_api_articles_article_id\"> GET (Retrieve) an article route</a>. Partial updates are not allowed, you have to supply the full JSON.</div>",
25 "required": True,
26 "schema": {"type" : "string"},
27 "name": "article_json",
28 "in": "body"
29 }
30 )
31 template['parameters'].append(cls.SWAG_API_KEY_REQ_PARAM)
32 template['responses']['201'] = cls.R201_BULK
33 template['responses']['400'] = cls.R400
34 template['responses']['401'] = cls.R401
35 template['responses']['403'] = cls.R403
36 return cls._build_swag_response(template)
38 @classmethod
39 def create(cls, articles, account):
40 # We run through the articles once, validating in dry-run mode
41 # and deduplicating as we go. Then we .save() everything once
42 # we know all incoming articles are valid.
44 # as long as authentication (in the layer above) has been successful, and the account exists, then
45 # we are good to proceed
46 if account is None:
47 raise Api401Error()
49 # convert the data into a suitable article models
50 articles = [ArticlesCrudApi.prep_article(data, account) for data in articles]
52 # ~~->Article:Service~~
53 articleService = DOAJ.articleService()
54 try:
55 # ~~->BatchCreateArticles:Feature~~
56 result = articleService.batch_create_articles(articles, account, add_journal_info=True)
57 return [a.id for a in articles]
58 except DuplicateArticleException as e:
59 raise Api403Error(str(e))
60 except exceptions.IngestException as e:
61 raise Api400Error(str(e))
64 @classmethod
65 def delete_swag(cls):
66 template = deepcopy(cls.SWAG_TEMPLATE)
67 template['parameters'].append(
68 {
69 "description": "<div class=\"search-query-docs\">A list/array of DOAJ article IDs. E.g. [\"4cf8b72139a749c88d043129f00e1b07\", \"232b53726fb74cc4a8eb4717e5a43193\"].</div>",
70 "required": True,
71 "schema": {"type" : "string"},
72 "name": "article_ids",
73 "in": "body"
74 }
75 )
76 template['parameters'].append(cls.SWAG_API_KEY_REQ_PARAM)
77 template['responses']['204'] = cls.R204
78 template['responses']['400'] = cls.R400
79 template['responses']['401'] = cls.R401
80 return cls._build_swag_response(template)
82 @classmethod
83 def delete(cls, article_ids, account):
84 # we run through delete twice, once as a dry-run and the second time
85 # as the real deal
86 # ~~->APICrudArticles:Feature~~
87 for id in article_ids:
88 try:
89 ArticlesCrudApi.delete(id, account, dry_run=True)
90 except Api404Error as e:
91 raise Api400Error("Id {x} does not exist or does not belong to this user account".format(x=id))
92 except Api403Error as e:
93 raise Api400Error("Id {x} is not in a state which allows it to be deleted".format(x=id))
95 for id in article_ids:
96 ArticlesCrudApi.delete(id, account)