write_groups_reports.py 6.94 KB
Newer Older
Jonas Waeber's avatar
Jonas Waeber committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Import API Service
# Copyright (C) 2020-2021 Memobase Project
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
Jonas Waeber's avatar
Jonas Waeber committed
16
17
import requests
import json
18
19
from flask_restful import Resource, request
from flask_restful import current_app
20
from import_api_app.helpers.error import ImportApiError
Jonas Waeber's avatar
Jonas Waeber committed
21
22
from requests.auth import HTTPBasicAuth

23
24

class WriteTypeReportToDrupal(Resource):
25
26
27
28
29
30
31
32

    def __init__(self):
        self.base_url = current_app.config["drupal-api-url"]
        self.headers = {
            'Content-Type': 'application/vnd.api+json',
            'Accept': 'application/vnd.api+json',
            'X-API-Key': current_app.config['drupal-api-key']
        }
Jonas Waeber's avatar
Jonas Waeber committed
33
34
35
        user = current_app.config['drupal-user']
        password = current_app.config['drupal-password']
        self.auth = HTTPBasicAuth(user, password)
36

37
38
39
40
41
    def post(self):
        """
        Write a report for an recordset or institution Drupal
        ---
        tags:
Matthias's avatar
Matthias committed
42
          - reporting
43
        parameters:
Matthias's avatar
Matthias committed
44
45
46
47
48
49
50
51
52
            - in: body
              name: body
              required: true
              schema:
                  item:
                      type: object
                      properties:
                          node_type:
                              type: string
Jonas Waeber's avatar
Jonas Waeber committed
53
54
                              example: 'record_set'
                              description: Either 'record_set' or 'institution'.
Matthias's avatar
Matthias committed
55
56
57
58
59
60
                          id:
                              type: string
                              example: 'sag'
                              description: The memobase id of the record set or institution.
                          status:
                              type: boolean
Jonas Waeber's avatar
Jonas Waeber committed
61
                              example: true
Matthias's avatar
Matthias committed
62
63
64
65
66
                              description: The status
                          report:
                              type: string
                              example: "Failed to process record set."
                              description: Text message of the report.
67
        responses:
Matthias's avatar
Matthias committed
68
69
70
71
72
73
            200:
                description: It was successful
            404:
                description: No content with such a id found
            500:
                description: There was a problem
74
        """
Matthias's avatar
Matthias committed
75

76
        try:
Jonas Waeber's avatar
Jonas Waeber committed
77
78
79
80
            node_type = request.json['node_type']
            identifier = request.json['id']
            status = request.json['status']
            report = request.json['report']
81
82
83
84
85
        except KeyError as er:
            return {
                       'message': f'Missing a element in input body: {er}'
                   }, 400
        try:
Jonas Waeber's avatar
Jonas Waeber committed
86
87
            node_id, lang_code = self.get_drupal_uuid(identifier, node_type)
            return self.write_results(node_type, node_id, lang_code, status, report)
88
        except ImportApiError as e:
89
90
91
92
            current_app.logger.error(
                f"Could not write report to {node_type}/{identifier}: {e.message}")
            return {
                       'error': f"Could not write report to {node_type}/{identifier}: "
Jonas Waeber's avatar
Jonas Waeber committed
93
94
                                f"{e.message}"
                   }, 500
95

Jonas Waeber's avatar
Jonas Waeber committed
96
97
    def get_drupal_uuid(self, memobase_id: str, node_type: str):
        url = f'{self.base_url}/jsonapi/node/{node_type}?filter[field_memobase_id]={memobase_id}'
Jonas Waeber's avatar
Jonas Waeber committed
98
        response = requests.get(url, headers=self.headers, auth=self.auth)
99
100
        if response.ok:
            try:
Jonas Waeber's avatar
Jonas Waeber committed
101
102
                result = response.json()['data'][0]
                return result['id'], result['attributes']['langcode']
103
104
105
            except KeyError as er:
                current_app.logger.error(f"Could not find the key {er} in data: {response.text}.")
                raise ImportApiError(f"Could not find the key {er} in data (url={url}): "
Jonas Waeber's avatar
Jonas Waeber committed
106
                                     f"{response.text}.")
107
108
109
110
111
112
            except IndexError:
                current_app.logger.error(f"Data field does not contain a list (url={url}): "
                                         f"{response.text}.")
                raise ImportApiError(f"Data field does not contain a list (url={url}): "
                                     f"{response.text}.")
        else:
Jonas Waeber's avatar
Jonas Waeber committed
113
            current_app.logger.error("Could not find element: " + url)
114
            raise ImportApiError(f"Could not find element for report: {response.text}.")
115

Jonas Waeber's avatar
Jonas Waeber committed
116
117
118
    def write_results(self, node_type, identifier, lang_code, status, report):
        current_app.logger.debug(f"writing: {lang_code}/{node_type}/{str(identifier)}"
                                 f"/{str(status)}/{report}")
119

120
        drupal_type = ''
Jonas Waeber's avatar
Jonas Waeber committed
121
        url = f'{self.base_url}/{lang_code}/jsonapi/node/'
122
123
124
        if node_type == 'institution':
            drupal_type = 'node--institution'
            url += 'institution/'
Jonas Waeber's avatar
Jonas Waeber committed
125
            url = f'{url}{identifier}'
Jonas Waeber's avatar
Jonas Waeber committed
126
        elif node_type == 'record_set':
127
128
            drupal_type = 'node--record_set'
            url += 'record_set/'
Jonas Waeber's avatar
Jonas Waeber committed
129
            url = f'{url}{identifier}'
130

131
132
        data = {
            "data": {
Jonas Waeber's avatar
Jonas Waeber committed
133
                "id": identifier,
134
135
                "type": drupal_type,
                "attributes": {
Jonas Waeber's avatar
Jonas Waeber committed
136
137
                    "field_migrated": 1 if status == "true" or status is True
                    or status == "True" else 0,
138
139
                    "field_error": report
                }
140
141
142
            }
        }

143
        result = {'message': ''}
144

145
146
147
148
        try:
            response = requests.patch(
                url,
                headers=self.headers,
Jonas Waeber's avatar
Jonas Waeber committed
149
                auth=self.auth,
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
                data=json.dumps(data)
            )
        except requests.exceptions.RequestException:
            message = f'Request Error: {url}'
            current_app.logger.error(message)
            raise ImportApiError(message)
        if response.ok:
            current_app.logger.debug('Updated: ' + url)
            result['message'] += 'Updated: ' + url + '\n'
        elif response.status_code == 403:
            message = f"Authorization Failed: {url}"
            current_app.logger.error(message)
            raise ImportApiError(message)
        elif response.status_code == 404:
            message = 'Not Found: ' + url
            current_app.logger.error(message)
            raise ImportApiError(message)
        else:
            message = "Unknown response status code for drupal api for url " + url
Jonas Waeber's avatar
Jonas Waeber committed
169
            current_app.logger.error(json.dumps(data, ensure_ascii=False))
170
            current_app.logger.error(message)
171
            current_app.logger.error(response.text)
172
173
            raise ImportApiError(message)
        return result