def get(self, id): row = database.query_db(PATCH_QUERY + ' where id = ?', (id,), one=True) if not row: abort(404) data = process_patch_row(row) data['mergeable'] = patching.is_mergeable(data['original_patch']) headers = {} comments = database.query_db( ''' SELECT author, message, posted_at FROM patch_request_comment WHERE patch_request_id=? ORDER BY posted_at ASC ''', (id,) ) data['comments'] = [dict(row) for row in comments] try: if auth.accept_patch_permission.can(): headers['Link'] = '<{}>;rel="merge"'.format( url_for('patchmerge', id=id)) except auth.AuthenticationFailed: pass return marshal(data, patch_fields), 200, headers
def get(self, id): row = database.query_db(PATCH_QUERY + ' where id = ?', (id,), one=True) if row['merged']: p = row['applied_patch'] else: p = row['original_patch'] return json.loads(p), 200
def test_comment_on_patch(self): with open(filepath('test-patch-adds-items.json')) as f: patch = f.read() with self.client as client: res = client.patch( '/d/', data=patch, content_type='application/json', headers={'Authorization': 'Bearer ' + 'NTAwNWViMTgtYmU2Yi00YWMwLWIwODQtMDQ0MzI4OWIzMzc4'}) patch_id = int(res.headers['Location'].split('/')[-2]) patch_url = urlparse(res.headers['Location']).path res = client.post( patch_url + 'messages', data=json.dumps({'message': 'This is a comment'}), content_type='application/json', headers={'Authorization': 'Bearer ' + 'NTAwNWViMTgtYmU2Yi00YWMwLWIwODQtMDQ0MzI4OWIzMzc4'} ) self.assertEqual(res.status_code, http.client.OK) self.assertEqual(patch_url, urlparse(res.headers['Location']).path) row = database.query_db( 'SELECT * FROM patch_request_comment WHERE patch_request_id=?', (patch_id,), one=True) self.assertEqual('https://orcid.org/1234-5678-9101-112X', row['author']) self.assertEqual(patch_id, row['patch_request_id']) self.assertEqual('This is a comment', row['message']) res = client.get(patch_url) comments = json.loads(res.get_data(as_text=True)).get('comments') self.assertEqual(1, len(comments))
def test_initial_patch(self): with self.client as client: client.patch( '/d/', data=self.patch, content_type='application/json', headers={'Authorization': 'Bearer ' + 'NTAwNWViMTgtYmU2Yi00YWMwLWIwODQtMDQ0MzI4OWIzMzc4'}) created_entities = database.query_db( 'SELECT created_entities FROM patch_request WHERE id = 1', one=True)['created_entities'] self.assertEqual(created_entities, '["p0trgkv", "p0trgkvwbjd"]') updated_entities = database.query_db( 'SELECT updated_entities FROM patch_request WHERE id = 1', one=True)['updated_entities'] self.assertEqual(updated_entities, '[]')
def test_admin_merge(self): with self.client as client: res = client.patch( '/d/', data=self.patch, content_type='application/json', headers={'Authorization': 'Bearer ' + 'NTAwNWViMTgtYmU2Yi00YWMwLWIwODQtMDQ0MzI4OWIzMzc4'}) patch_id = int(res.headers['Location'].split('/')[-2]) # Test that there's a link header patch_url = urlparse(res.headers['Location']).path res = self.client.get(patch_url, headers={ 'Authorization': 'Bearer ' + 'ZjdjNjQ1ODQtMDc1MC00Y2I2LThjODEtMjkzMmY1ZGFhYmI4'}) self.assertEqual(res.headers.get('Link'), '<{}>;rel="merge"'.format(patch_url + 'merge')) res = client.post( patch_url + 'merge', headers={'Authorization': 'Bearer ' + 'ZjdjNjQ1ODQtMDc1MC00Y2I2LThjODEtMjkzMmY1ZGFhYmI4'}) self.assertEqual(res.status_code, http.client.NO_CONTENT) merger = database.query_db( 'SELECT merged_by FROM patch_request WHERE id = ?', (patch_id,), one=True)['merged_by'] self.assertEqual(merger, 'http://orcid.org/1211-1098-7654-321X')
def add_new_version_of_dataset(data): now = database.query_db( "SELECT CAST(strftime('%s', 'now') AS INTEGER) AS now", one=True)['now'] cursor = database.get_db().cursor() cursor.execute( 'INSERT into DATASET (data, description, created_at) VALUES (?,?,?)', (json.dumps(data), void.describe_dataset(data, now), now)) return cursor.lastrowid
def test_add_admin_user(self): with app.app_context(): row = database.query_db( 'SELECT permissions FROM user WHERE id = ?', (self.admin_identity.id,), one=True) self.assertEqual( row['permissions'], '[["action", "submit-patch"], ["action", "accept-patch"]]')
def merge(patch_id, user_id): row = database.query_db( 'SELECT * FROM patch_request WHERE id = ?', (patch_id,), one=True) if not row: raise MergeError('No patch with ID {}.'.format(patch_id)) if row['merged']: raise MergeError('Patch is already merged.') if not row['open']: raise MergeError('Closed patches cannot be merged.') dataset = database.get_dataset() mergeable = is_mergeable(row['original_patch'], dataset) if not mergeable: raise UnmergeablePatchError('Patch is not mergeable.') data = json.loads(dataset['data']) original_patch = from_text(row['original_patch']) applied_patch, id_map = replace_skolem_ids( original_patch, data, database.get_removed_entity_keys()) created_entities = set(id_map.values()) # Should this be ordered? new_data = applied_patch.apply(data) db = database.get_db() curs = db.cursor() curs.execute( ''' UPDATE patch_request SET merged = 1, open = 0, merged_at = strftime('%s', 'now'), merged_by = ?, applied_to = ?, created_entities = ?, identifier_map = ?, applied_patch = ? WHERE id = ?; ''', (user_id, dataset['id'], json.dumps(sorted(created_entities)), json.dumps(id_map), applied_patch.to_string(), row['id']) ) version_id = add_new_version_of_dataset(new_data) curs.execute( ''' UPDATE patch_request SET resulted_in = ? WHERE id = ?; ''', (version_id, row['id']) )
def test_submit_patch(self): with self.client as client: res = client.patch( '/d/', data=self.patch, content_type='application/json', headers={'Authorization': 'Bearer ' + 'NTAwNWViMTgtYmU2Yi00YWMwLWIwODQtMDQ0MzI4OWIzMzc4'}) self.assertEqual(res.status_code, http.client.ACCEPTED) patch_id = int(res.headers['Location'].split('/')[-2]) updated_entities = database.query_db( 'SELECT updated_entities FROM patch_request WHERE id = ?', (patch_id,), one=True)['updated_entities'] self.assertEqual(updated_entities, '["p0trgkv", "p0trgkvwbjd"]') created_entities = database.query_db( 'SELECT created_entities FROM patch_request WHERE id = ?', (patch_id,), one=True)['created_entities'] self.assertEqual(created_entities, '[]')
def test_merge_patch(self): with open(filepath('test-patch-adds-items.json')) as f: patch = f.read() with self.client as client: res = client.patch( '/d/', data=patch, content_type='application/json', headers={'Authorization': 'Bearer ' + 'NTAwNWViMTgtYmU2Yi00YWMwLWIwODQtMDQ0MzI4OWIzMzc4'}) patch_id = int(res.headers['Location'].split('/')[-2]) updated_entities = database.query_db( 'SELECT updated_entities FROM patch_request WHERE id = ?', (patch_id,), one=True)['updated_entities'] self.assertEqual(updated_entities, '["p0trgkv"]') created_entities = database.query_db( 'SELECT created_entities FROM patch_request WHERE id = ?', (patch_id,), one=True)['created_entities'] self.assertEqual(created_entities, '[]') patch_url = urlparse(res.headers['Location']).path res = client.post( patch_url + 'merge', buffered=True, headers={'Authorization': 'Bearer ' + 'ZjdjNjQ1ODQtMDc1MC00Y2I2LThjODEtMjkzMmY1ZGFhYmI4'}) self.assertEqual(res.status_code, http.client.NO_CONTENT) row = database.query_db( 'SELECT applied_to, resulted_in FROM patch_request WHERE id=?', (patch_id,), one=True) self.assertEqual(1, row['applied_to']) self.assertEqual(2, row['resulted_in']) updated_entities = database.query_db( 'SELECT updated_entities FROM patch_request WHERE id = ?', (patch_id,), one=True)['updated_entities'] self.assertEqual(updated_entities, '["p0trgkv"]') created_entities = json.loads(database.query_db( 'SELECT created_entities FROM patch_request WHERE id = ?', (patch_id,), one=True)['created_entities']) self.assertEqual(4, len(created_entities)) for entity_id in created_entities: self.assertRegex(entity_id, identifier.IDENTIFIER_RE)
def test_authorized_user(self): with self.client as client: res = client.patch( '/d/', data=self.patch, content_type='application/json', headers={'Authorization': 'Bearer ' + 'NTAwNWViMTgtYmU2Yi00YWMwLWIwODQtMDQ0MzI4OWIzMzc4'}) self.assertEqual(res.status_code, http.client.ACCEPTED) patch_id = int(res.headers['Location'].split('/')[-2]) creator = database.query_db( 'SELECT created_by FROM patch_request WHERE id = ?', (patch_id,), one=True)['created_by'] self.assertEqual(creator, 'http://orcid.org/1234-5678-9101-112X')
def test_add_user(self): self.assertEqual( self.identity.id, 'http://orcid.org/1234-5678-9101-112X') self.assertEqual( self.identity.auth_type, 'bearer') with app.app_context(): row = database.query_db( 'SELECT name, permissions, b64token FROM user WHERE id = ?', (self.identity.id,), one=True) self.assertEqual(row['name'], 'Testy Testerson') self.assertEqual( row['permissions'], '[["action", "submit-patch"]]') self.assertEqual( row['b64token'], b'NTAwNWViMTgtYmU2Yi00YWMwLWIwODQtMDQ0MzI4OWIzMzc4')
def add_comment(patch_id, user_id, message): row = database.query_db( 'SELECT * FROM patch_request WHERE id = ?', (patch_id,), one=True) if not row: raise MergeError('No patch with ID {}.'.format(patch_id)) db = database.get_db() curs = db.cursor() curs.execute( ''' INSERT INTO patch_request_comment (patch_request_id, author, message) VALUES (?, ?, ?) ''', (patch_id, user_id, message) )
def get(self, id): row = database.query_db(PATCH_QUERY + ' where id = ?', (id,), one=True) if not row: abort(404) data = process_patch_row(row) data['mergeable'] = patching.is_mergeable(data['original_patch']) data['comments'] = [dict(c) for c in database.get_patch_request_comments(id)] headers = {} try: if auth.accept_patch_permission.can(): headers['Link'] = '<{}>;rel="merge"'.format( url_for('patchmerge', id=id)) except auth.AuthenticationFailed: pass return marshal(data, patch_fields), 200, headers
def test_reject_patch(self): with open(filepath('test-patch-adds-items.json')) as f: patch = f.read() with self.client as client: res = client.patch( '/d/', data=patch, content_type='application/json', headers={'Authorization': 'Bearer ' + 'NTAwNWViMTgtYmU2Yi00YWMwLWIwODQtMDQ0MzI4OWIzMzc4'}) patch_id = int(res.headers['Location'].split('/')[-2]) patch_url = urlparse(res.headers['Location']).path res = client.post( patch_url + 'reject', headers={'Authorization': 'Bearer ' + 'ZjdjNjQ1ODQtMDc1MC00Y2I2LThjODEtMjkzMmY1ZGFhYmI4'}) self.assertEqual(res.status_code, http.client.NO_CONTENT) row = database.query_db( 'SELECT open, merged FROM patch_request WHERE id=?', (patch_id,), one=True) self.assertEqual(0, row['open']) self.assertEqual(0, row['merged'])
def reject(patch_id, user_id): row = database.query_db( 'SELECT * FROM patch_request WHERE id = ?', (patch_id,), one=True) if not row: raise MergeError('No patch with ID {}.'.format(patch_id)) if row['merged']: raise MergeError('Patch is already merged.') if not row['open']: raise MergeError('Closed patches cannot be merged.') db = database.get_db() curs = db.cursor() curs.execute( ''' UPDATE patch_request SET merged = 0, open = 0, merged_at = strftime('%s', 'now'), merged_by = ? WHERE id = ?; ''', (user_id, row['id'],) )
def get(self): args = patch_list_parser.parse_args() query = PATCH_QUERY params = () where = [] if args['open'] is not None: where.append('open = ?') params += (True if args['open'] == 'true' else False,) if args['merged'] is not None: where.append('merged = ?') params += (True if args['merged'] == 'true' else False,) if where: query += ' where ' + ' AND '.join(where) query += ' order by ' + args['sort'] + ' ' + args['order'] limit = args['limit'] if limit < 0: limit = 25 if limit > 250: limit = 250 offset = args['from'] if offset < 0: offset = 0 query += ' limit ' + str(limit + 1) + ' offset ' + str(offset) rows = database.query_db(query, params) data = [process_patch_row(row) for row in rows][:limit] link_headers = [] if offset > 0: prev_url = url_for('patches', _external=True) prev_params = request.args.to_dict().copy() prev_params['from'] = offset - limit if (prev_params['from'] <= 0): prev_params.pop('from') prev_params = urlencode(prev_params) if (prev_params): prev_url += '?' + prev_params link_headers.append('<{}>; rel="prev"'.format(prev_url)) # We fetched 1 more than the limit. If there are limit+1 rows in the # retrieved query, then there are more rows to be fetched if len(rows) > limit: next_url = url_for('patches', _external=True) next_params = request.args.to_dict().copy() next_params['from'] = offset + limit link_headers.append( '<{}?{}>; rel="next"'.format(next_url, urlencode(next_params))) headers = {} if (link_headers): headers['Link'] = ', '.join(link_headers) return marshal(data, patch_list_fields), 200, headers