Commit dd60471b authored by Markus Scheidgen's avatar Markus Scheidgen
Browse files

Merged v0.6.0.

parent 1f8bb5ae
Pipeline #62014 passed with stages
in 15 minutes and 23 seconds
...@@ -192,13 +192,8 @@ class Api { ...@@ -192,13 +192,8 @@ class Api {
this.onStartLoading = () => null this.onStartLoading = () => null
this.onFinishLoading = () => null this.onFinishLoading = () => null
this._swaggerClient = Swagger(`${apiBase}/swagger.json`)
this.keycloak = keycloak this.keycloak = keycloak
this.isLoggedIn = true && user
user = user || {}
this.auth_headers = {
'X-Token': user.token
}
this.swaggerPromise = Api.createSwaggerClient(user.token).catch(handleApiError)
// keep a list of localUploads, these are uploads that are currently uploaded through // keep a list of localUploads, these are uploads that are currently uploaded through
// the browser and that therefore not yet returned by the backend // the browser and that therefore not yet returned by the backend
......
...@@ -12,13 +12,12 @@ ...@@ -12,13 +12,12 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from flask import request from flask_restplus import abort, Resource
from flask_restplus import abort, Resource, fields
from nomad import infrastructure, config from nomad import infrastructure, config
from .api import api from .api import api
from .auth import admin_login_required from .auth import authenticate
ns = api.namespace('admin', description='Administrative operations') ns = api.namespace('admin', description='Administrative operations')
...@@ -29,7 +28,7 @@ class AdminResetResource(Resource): ...@@ -29,7 +28,7 @@ class AdminResetResource(Resource):
@api.doc('exec_reset_command') @api.doc('exec_reset_command')
@api.response(200, 'Reset performed') @api.response(200, 'Reset performed')
@api.response(400, 'Reset not available/disabled') @api.response(400, 'Reset not available/disabled')
@admin_login_required @authenticate(admin_only=True)
def post(self): def post(self):
""" """
The ``reset`` command will attempt to clear the contents of all databased and The ``reset`` command will attempt to clear the contents of all databased and
...@@ -40,7 +39,7 @@ class AdminResetResource(Resource): ...@@ -40,7 +39,7 @@ class AdminResetResource(Resource):
if config.services.disable_reset: if config.services.disable_reset:
abort(400, message='Operation is disabled') abort(400, message='Operation is disabled')
infrastructure.reset(repo_content_only=True) infrastructure.reset()
return dict(messager='Reset performed.'), 200 return dict(messager='Reset performed.'), 200
...@@ -50,7 +49,7 @@ class AdminRemoveResource(Resource): ...@@ -50,7 +49,7 @@ class AdminRemoveResource(Resource):
@api.doc('exec_remove_command') @api.doc('exec_remove_command')
@api.response(200, 'Remove performed') @api.response(200, 'Remove performed')
@api.response(400, 'Remove not available/disabled') @api.response(400, 'Remove not available/disabled')
@admin_login_required @authenticate(admin_only=True)
def post(self): def post(self):
""" """
The ``remove``command will attempt to remove all databases. Expect the The ``remove``command will attempt to remove all databases. Expect the
...@@ -65,28 +64,3 @@ class AdminRemoveResource(Resource): ...@@ -65,28 +64,3 @@ class AdminRemoveResource(Resource):
infrastructure.remove() infrastructure.remove()
return dict(messager='Remove performed.'), 200 return dict(messager='Remove performed.'), 200
pidprefix_model = api.model('PidPrefix', {
'prefix': fields.Integer(description='The prefix. All new calculations will get an id that is greater.', required=True)
})
# TODO remove after migration
@ns.route('/pidprefix')
class AdminPidPrefixResource(Resource):
@api.doc('exec_pidprefix_command')
@api.response(200, 'Pid prefix set')
@api.response(400, 'Bad pid prefix data')
@api.expect(pidprefix_model)
@admin_login_required
def post(self):
"""
The ``pidprefix``command will set the pid counter to the given value.
This might be useful while migrating data with old pids.
"""
infrastructure.set_pid_prefix(**request.get_json())
return dict(messager='PID prefix set.'), 200
...@@ -41,7 +41,7 @@ import uuid ...@@ -41,7 +41,7 @@ import uuid
from nomad import config, processing, utils, infrastructure, datamodel from nomad import config, processing, utils, infrastructure, datamodel
from .app import api from .api import api
# Authentication scheme definitions, for swagger # Authentication scheme definitions, for swagger
......
...@@ -26,7 +26,7 @@ from nomad import search, utils, datamodel ...@@ -26,7 +26,7 @@ from nomad import search, utils, datamodel
from nomad.app.utils import rfc3339DateTime from nomad.app.utils import rfc3339DateTime
from nomad.app.optimade import filterparser from nomad.app.optimade import filterparser
from .api import api, rfc3339DateTime from .api import api
from .auth import authenticate from .auth import authenticate
from .common import pagination_model, pagination_request_parser, calc_route from .common import pagination_model, pagination_request_parser, calc_route
...@@ -357,7 +357,7 @@ class RepoPidResource(Resource): ...@@ -357,7 +357,7 @@ class RepoPidResource(Resource):
@api.doc('resolve_pid') @api.doc('resolve_pid')
@api.response(404, 'Entry with PID does not exist') @api.response(404, 'Entry with PID does not exist')
@api.marshal_with(repo_calc_id_model, skip_none=True, code=200, description='Entry resolved') @api.marshal_with(repo_calc_id_model, skip_none=True, code=200, description='Entry resolved')
@login_if_available @authenticate()
def get(self, pid: int): def get(self, pid: int):
search_request = search.SearchRequest() search_request = search.SearchRequest()
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
import click import click
import datetime import datetime
import elasticsearch.helpers import elasticsearch.helpers
import json
from nomad import processing as proc, search, datamodel, infrastructure, utils, config from nomad import processing as proc, search, datamodel, infrastructure, utils, config
......
...@@ -278,10 +278,11 @@ class Keycloak(): ...@@ -278,10 +278,11 @@ class Keycloak():
user_id = user.user_id user_id = user.user_id
if email is not None and user_id is None: if email is not None and user_id is None:
try: with utils.lnr(logger, 'Could not use keycloak admin client'):
user_id = self._admin_client.get_user_id(email) user_id = self._admin_client.get_user_id(email)
except Exception:
raise KeyError('User does not exist') if user_id is None:
raise KeyError('User %s does not exist' % email)
assert user_id is not None, 'Could not determine user from given kwargs' assert user_id is not None, 'Could not determine user from given kwargs'
......
...@@ -286,7 +286,7 @@ class SearchRequest: ...@@ -286,7 +286,7 @@ class SearchRequest:
raise ValueError('Authentication required for owner value user') raise ValueError('Authentication required for owner value user')
q = Q('term', published=False) & Q('term', owners__user_id=user_id) q = Q('term', published=False) & Q('term', owners__user_id=user_id)
elif owner_type == 'admin': elif owner_type == 'admin':
if user_id is None or not coe_repo.User.from_user_id(user_id).is_admin: if user_id is None or not datamodel.User.get(user_id=user_id).is_admin:
raise ValueError('This can only be used by the admin user.') raise ValueError('This can only be used by the admin user.')
q = None q = None
else: else:
......
...@@ -25,7 +25,7 @@ from urllib.parse import urlencode ...@@ -25,7 +25,7 @@ from urllib.parse import urlencode
import base64 import base64
from nomad.app.utils import rfc3339DateTime from nomad.app.utils import rfc3339DateTime
from nomad.app.auth import generate_upload_token from nomad.app.api.auth import generate_upload_token
from nomad import search, parsing, files, config, utils, infrastructure from nomad import search, parsing, files, config, utils, infrastructure
from nomad.files import UploadFiles, PublicUploadFiles from nomad.files import UploadFiles, PublicUploadFiles
from nomad.processing import Upload, Calc, SUCCESS from nomad.processing import Upload, Calc, SUCCESS
...@@ -196,7 +196,7 @@ class TestUploads: ...@@ -196,7 +196,7 @@ class TestUploads:
assert upload['process_running'] assert upload['process_running']
additional_keys = ['with_embargo'] additional_keys = ['with_embargo']
if publish_with_metadata and 'external_id' in metadata: if 'external_id' in metadata:
additional_keys.append('external_id') additional_keys.append('external_id')
self.block_until_completed(api, upload_id, test_user_auth) self.block_until_completed(api, upload_id, test_user_auth)
...@@ -597,18 +597,21 @@ class TestRepo(): ...@@ -597,18 +597,21 @@ class TestRepo():
search.Entry.from_calc_with_metadata(calc_with_metadata).save(refresh=True) search.Entry.from_calc_with_metadata(calc_with_metadata).save(refresh=True)
calc_with_metadata.update( calc_with_metadata.update(
calc_id='2', uploader=other_test_user.user_id, published=True, with_embargo=False, calc_id='2', uploader=other_test_user.user_id, published=True,
upload_time=today - datetime.timedelta(days=5)) with_embargo=False, pid=2, upload_time=today - datetime.timedelta(days=5),
external_id='external_id')
calc_with_metadata.update( calc_with_metadata.update(
atoms=['Fe'], comment='this is a specific word', formula='AAA', basis_set='zzz') atoms=['Fe'], comment='this is a specific word', formula='AAA', basis_set='zzz')
search.Entry.from_calc_with_metadata(calc_with_metadata).save(refresh=True) search.Entry.from_calc_with_metadata(calc_with_metadata).save(refresh=True)
calc_with_metadata.update( calc_with_metadata.update(
calc_id='3', uploader=other_test_user.user_id, published=False, with_embargo=False) calc_id='3', uploader=other_test_user.user_id, published=False,
with_embargo=False, pid=3, external_id='external_id')
search.Entry.from_calc_with_metadata(calc_with_metadata).save(refresh=True) search.Entry.from_calc_with_metadata(calc_with_metadata).save(refresh=True)
calc_with_metadata.update( calc_with_metadata.update(
calc_id='4', uploader=other_test_user.user_id, published=True, with_embargo=True) calc_id='4', uploader=other_test_user.user_id, published=True,
with_embargo=True, pid=4, external_id='external_id')
search.Entry.from_calc_with_metadata(calc_with_metadata).save(refresh=True) search.Entry.from_calc_with_metadata(calc_with_metadata).save(refresh=True)
def assert_search(self, rv: Any, number_of_calcs: int) -> dict: def assert_search(self, rv: Any, number_of_calcs: int) -> dict:
......
...@@ -16,7 +16,7 @@ from typing import List ...@@ -16,7 +16,7 @@ from typing import List
from elasticsearch_dsl import Q from elasticsearch_dsl import Q
import pytest import pytest
from nomad import datamodel, search, processing, parsing, infrastructure, config, coe_repo from nomad import datamodel, search, processing, parsing, infrastructure, config
from nomad.search import Entry, SearchRequest from nomad.search import Entry, SearchRequest
...@@ -137,7 +137,7 @@ def test_search_totals(elastic, example_search_data): ...@@ -137,7 +137,7 @@ def test_search_totals(elastic, example_search_data):
assert 'quantities' not in results assert 'quantities' not in results
def test_search_quantity(elastic, normalized: parsing.LocalBackend, test_user: coe_repo.User, other_test_user: coe_repo.User): def test_search_quantity(elastic, normalized: parsing.LocalBackend, test_user: datamodel.User, other_test_user: datamodel.User):
calc_with_metadata = datamodel.CalcWithMetadata(upload_id='test upload id', calc_id='test id') calc_with_metadata = datamodel.CalcWithMetadata(upload_id='test upload id', calc_id='test id')
calc_with_metadata.apply_domain_metadata(normalized) calc_with_metadata.apply_domain_metadata(normalized)
calc_with_metadata.uploader = test_user.user_id calc_with_metadata.uploader = test_user.user_id
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment