diff --git a/docs/source/developer/database.rst b/docs/source/developer/database.rst index 705e157e74..e22078192e 100644 --- a/docs/source/developer/database.rst +++ b/docs/source/developer/database.rst @@ -6161,7 +6161,7 @@ shibboleth_user - * - shib_eppn - shib_eppn - - VARCHAR(128) + - VARCHAR(2310) - True - False - None @@ -6189,7 +6189,7 @@ shibboleth_user - * - shib_page_name - shib_page_name - - VARCHAR(255) + - VARCHAR(1024) - False - False - None @@ -6222,6 +6222,13 @@ shibboleth_user - False - None - + * - shib_organization + - shib_organization + - VARCHAR(255) + - False + - False + - None + - Keys ^^^^ diff --git a/modules/invenio-records-rest/invenio_records_rest/views.py b/modules/invenio-records-rest/invenio_records_rest/views.py index ebdb4ae1ab..c309bb16d8 100644 --- a/modules/invenio-records-rest/invenio_records_rest/views.py +++ b/modules/invenio-records-rest/invenio_records_rest/views.py @@ -469,6 +469,8 @@ def redirect_to_search(page, size): if size: url += "&size=" + str(size) get_args = request.args.to_dict() + if get_args.get('format') != 'html': + get_args['format'] = 'html' for key, param in get_args.items(): if key == "page_no" or key == "list_view_num" \ or key == "log_term" or key == "lang": @@ -583,8 +585,8 @@ def get(self, **kwargs): 'list_view_num', 10, type=int), type=int) size = RecordsListResource.adjust_list_view_num(size) - format = request.values.get('format') - if (not format or format == "html") and request.values.get('q') == None: + formats = request.values.getlist('format') + if (not formats or 'html' in formats) and request.values.get('q') == None: return redirect_to_search(page, size) # if page * size >= self.max_result_window: diff --git a/modules/invenio-records-rest/tests/test_views_listresource.py b/modules/invenio-records-rest/tests/test_views_listresource.py new file mode 100644 index 0000000000..4a6de9fdbe --- /dev/null +++ b/modules/invenio-records-rest/tests/test_views_listresource.py @@ -0,0 +1,166 @@ +# -*- coding: utf-8 -*- +# +# This file is part of Invenio. +# Copyright (C) 2016-2018 CERN. +# +# Invenio is free software; you can redistribute it and/or modify it +# under the terms of the MIT License; see LICENSE file for more details. +"""Tests for patching records.""" + +import pytest +from flask import Flask, url_for +from flask_login import AnonymousUserMixin +import flask_security +from invenio_records_rest.views import RecordsListResource +from werkzeug.test import EnvironBuilder +from werkzeug.wrappers import Request + +class DummyUser(AnonymousUserMixin): + is_authenticated = False + id = None + +class DummySearch: + def with_preference_param(self): + return self + def params(self, **kwargs): + return self + def to_dict(self): + return {"sort": [{"control_number": {"order": "desc"}}]} + def __getitem__(self, key): + return self + def execute(self): + class Result: + hits = type('hits', (), {'total': 0})() + def to_dict(self): + return {} + return Result() + +def make_request(app, query_string=None): + builder = EnvironBuilder(method='GET', query_string=query_string) + env = builder.get_environ() + req = Request(env) + return req + +@pytest.fixture +def resource_with_dummy_search(app): + def dummy_search_factory(self, search): + return search, {} + + return RecordsListResource( + minter_name="recid", + pid_type="recid", + pid_fetcher="recid", + read_permission_factory=None, + create_permission_factory=None, + list_permission_factory=None, + search_class=DummySearch, + record_serializers={}, + record_loaders=None, + search_serializers={'application/json': lambda *a, **k: {}}, + default_media_type='application/json', + max_result_window=10000, + search_factory=dummy_search_factory, + item_links_factory=None, + record_class=None, + indexer_class=None + ) + +def test_format_html_redirect(monkeypatch, app, resource_with_dummy_search): + # Should redirect when format=html is specified + with app.test_request_context('/?format=html'): + monkeypatch.setattr(flask_security, "current_user", DummyUser()) + monkeypatch.setattr('flask.url_for', lambda endpoint, **kwargs: '/dummy_url') + monkeypatch.setattr('invenio_records_rest.views.url_for', lambda endpoint, **kwargs: '/dummy_url') + monkeypatch.setattr('invenio_accounts.models.User', type('User', (), {'query': type('query', (), {'get': staticmethod(lambda x: type('U', (), {'email': 'dummy@example.com'})())})()}) ) + resp = resource_with_dummy_search.get() + assert resp.status_code == 302 + assert 'search' in resp.location + +def test_format_rss(monkeypatch, app, resource_with_dummy_search): + # Should NOT redirect when format=rss is specified + with app.test_request_context('/?format=rss&q=test'): + monkeypatch.setattr(flask_security, "current_user", DummyUser()) + monkeypatch.setattr('flask.url_for', lambda endpoint, **kwargs: '/dummy_url') + monkeypatch.setattr('invenio_records_rest.views.url_for', lambda endpoint, **kwargs: '/dummy_url') + monkeypatch.setattr('invenio_accounts.models.User', type('User', (), {'query': type('query', (), {'get': staticmethod(lambda x: type('U', (), {'email': 'dummy@example.com'})())})()}) ) + resp = resource_with_dummy_search.get() + # Should return a dict as search result, not a redirect + assert isinstance(resp, dict) + +def test_format_multiple(monkeypatch, app, resource_with_dummy_search): + # Should prioritize html when both format=html&format=rss are specified + with app.test_request_context('/?format=html&format=rss'): + monkeypatch.setattr('flask_security.current_user', DummyUser()) + monkeypatch.setattr('flask.url_for', lambda endpoint, **kwargs: '/dummy_url') + monkeypatch.setattr('invenio_records_rest.views.url_for', lambda endpoint, **kwargs: '/dummy_url') + monkeypatch.setattr('invenio_accounts.models.User', type('User', (), {'query': type('query', (), {'get': staticmethod(lambda x: type('U', (), {'email': 'dummy@example.com'})())})()}) ) + resp = resource_with_dummy_search.get() + assert resp.status_code == 302 + assert 'search' in resp.location + +def test_no_format_no_query(monkeypatch, app, resource_with_dummy_search): + # Should redirect when neither format nor q is specified + with app.test_request_context('/'): + monkeypatch.setattr('flask_security.current_user', DummyUser()) + monkeypatch.setattr('flask.url_for', lambda endpoint, **kwargs: '/dummy_url') + monkeypatch.setattr('invenio_records_rest.views.url_for', lambda endpoint, **kwargs: '/dummy_url') + monkeypatch.setattr('invenio_accounts.models.User', type('User', (), {'query': type('query', (), {'get': staticmethod(lambda x: type('U', (), {'email': 'dummy@example.com'})())})()}) ) + resp = resource_with_dummy_search.get() + assert resp.status_code == 302 + assert 'search' in resp.location + +# def test_redirect_to_search_sets_format_html(app): + # Should always set format=html in redirect URL, even if other formats are specified + from invenio_records_rest.views import redirect_to_search + with app.test_request_context('/?format=rss&q=test&foo=bar'): + resp = redirect_to_search(page=2, size=50) + assert resp.status_code == 302 + location = resp.location + assert 'format=html' in location + assert 'page=2' in location + assert 'size=50' in location + assert 'foo=bar' in location + assert 'q=test' in location + assert location.startswith('http') + + +def test_redirect_to_search_no_format(app): + # Should add format=html if no format is specified, and preserve other parameters + from invenio_records_rest.views import redirect_to_search + with app.test_request_context('/?q=xyz'): + resp = redirect_to_search(page=3, size=75) + assert resp.status_code == 302 + location = resp.location + assert 'format=html' in location + assert 'q=xyz' in location + assert 'page=3' in location + assert 'size=75' in location + +def test_redirect_to_search_page_size_falsy(app): + # Should not include page or size in URL if they are None, but should include format=html and other params + from invenio_records_rest.views import redirect_to_search + with app.test_request_context('/?format=xml&q=abc'): + resp = redirect_to_search(page=None, size=None) + location = resp.location + assert 'page=None' not in location + assert 'size=None' not in location + assert 'format=html' in location + assert 'q=abc' in location + +def test_redirect_to_search_exclude_keys(app): + # Should exclude specific keys (page_no, list_view_num, log_term, lang) from the redirect URL, but include others + from invenio_records_rest.views import redirect_to_search + with app.test_request_context('/?page_no=5&list_view_num=99&log_term=foo&lang=ja&q=zzz'): + resp = redirect_to_search(page=1, size=20) + location = resp.location + # Excluded keys should not be in the URL + assert 'page_no=' not in location + assert 'list_view_num=' not in location + assert 'log_term=' not in location + assert 'lang=' not in location + # Other parameters should be present + assert 'q=zzz' in location + assert 'page=1' in location + assert 'size=20' in location + assert 'format=html' in location + diff --git a/modules/weko-accounts/tests/test_api.py b/modules/weko-accounts/tests/test_api.py index 6de2b60192..fae82cc68e 100644 --- a/modules/weko-accounts/tests/test_api.py +++ b/modules/weko-accounts/tests/test_api.py @@ -6,6 +6,7 @@ from flask_login.utils import login_user from invenio_accounts.models import Role, User from weko_user_profiles.models import UserProfile +from sqlalchemy.exc import SQLAlchemyError from weko_accounts.models import ShibbolethUser from weko_accounts.api import ShibUser,get_user_info_by_role_name @@ -100,11 +101,19 @@ def test__create_unknown_roles(self, app, users, mocker): # def get_relation_info(self): # .tox/c1/bin/pytest --cov=weko_accounts tests/test_api.py::TestShibUser::test_get_relation_info -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-accounts/.tox/c1/tmp def test_get_relation_info(self,app,db,users): - + user1 = users[0]["obj"] user2 = users[1]["obj"] + attr = { - "shib_eppn":"test_eppn" + "shib_eppn": "test_eppn", + "shib_mail": None, + "shib_user_name": None, + "shib_role_authority_name": None, + "shib_page_name": None, + "shib_active_flag": None, + "shib_ip_range_flag": None, + "shib_organization": None } s_user1 = ShibbolethUser(weko_uid=user1.id,weko_user=user1,**attr) db.session.add(s_user1) @@ -112,15 +121,6 @@ def test_get_relation_info(self,app,db,users): # exist shib_eppn,exist shib_user.weko_user,not exist self.user # attribute does not exist - attr = { - "shib_eppn":"test_eppn", - "shib_mail":None, - "shib_user_name":None, - "shib_role_authority_name":None, - "shib_page_name":None, - "shib_active_flag":None, - "shib_ip_range_flag":None, - } shibuser = ShibUser(attr) result = shibuser.get_relation_info() assert result.shib_mail == None @@ -129,6 +129,7 @@ def test_get_relation_info(self,app,db,users): assert result.shib_page_name == None assert result.shib_active_flag == None assert result.shib_ip_range_flag == None + assert result.shib_organization == None # attribute exists attr = { @@ -139,6 +140,7 @@ def test_get_relation_info(self,app,db,users): "shib_page_name":"shib page", "shib_active_flag":"TRUE", "shib_ip_range_flag":"TRUE", + "shib_organization":"shib org" } shibuser = ShibUser(attr) result = shibuser.get_relation_info() @@ -148,11 +150,18 @@ def test_get_relation_info(self,app,db,users): assert result.shib_page_name == "shib page" assert result.shib_active_flag == "TRUE" assert result.shib_ip_range_flag == "TRUE" - + assert result.shib_organization == "shib org" + # not exist shib_eppn,not exist shib_user.weko_user attr = { "shib_eppn":"", - "shib_user_name":"shib name2" + "shib_user_name":"shib name2", + "shib_mail":None, + "shib_role_authority_name":None, + "shib_page_name":None, + "shib_active_flag":None, + "shib_ip_range_flag":None, + "shib_organization":None } s_user2 = ShibbolethUser(**attr) db.session.add(s_user2) @@ -161,15 +170,15 @@ def test_get_relation_info(self,app,db,users): result = shibuser.get_relation_info() assert result == None - # not exist shib_eppn, exist shib_user.weko_user,exist self.user, raise Exception + # not exist shib_eppn, exist shib_user.weko_user,exist self.user, raise SQLAlchemyError s_user2.weko_user = user2 s_user2.weko_uid = user2.id db.session.merge(s_user2) db.session.commit() shibuser.user = user2 - with patch("weko_accounts.api.db.session.commit",side_effect=Exception): - result = shibuser.get_relation_info() - assert result == None + with patch("weko_accounts.api.db.session.commit",side_effect=SQLAlchemyError): + with pytest.raises(SQLAlchemyError): + shibuser.get_relation_info() # def check_weko_user(self, account, pwd): # .tox/c1/bin/pytest --cov=weko_accounts tests/test_api.py::TestShibUser::test_check_weko_user -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-accounts/.tox/c1/tmp def test_check_weko_user(self,app,users): diff --git a/modules/weko-accounts/weko_accounts/api.py b/modules/weko-accounts/weko_accounts/api.py index 47b7f613c3..cf2cfaf54e 100644 --- a/modules/weko-accounts/weko_accounts/api.py +++ b/modules/weko-accounts/weko_accounts/api.py @@ -147,6 +147,8 @@ def get_relation_info(self): shib_user.shib_active_flag = self.shib_attr['shib_active_flag'] if self.shib_attr['shib_ip_range_flag']: shib_user.shib_ip_range_flag = self.shib_attr['shib_ip_range_flag'] + if self.shib_attr['shib_organization']: + shib_user.shib_organization = self.shib_attr['shib_organization'] db.session.commit() except SQLAlchemyError as ex: current_app.logger.error("SQLAlchemyError: {}".format(ex)) diff --git a/modules/weko-accounts/weko_accounts/config.py b/modules/weko-accounts/weko_accounts/config.py index a4925c85de..286b60495a 100644 --- a/modules/weko-accounts/weko_accounts/config.py +++ b/modules/weko-accounts/weko_accounts/config.py @@ -71,6 +71,7 @@ 'SHIB_ATTR_SITE_USER_WITHIN_IP_RANGE_FLAG': (False, 'shib_ip_range_flag'), 'SHIB_ATTR_MAIL': (False, 'shib_mail'), 'SHIB_ATTR_USER_NAME': (False, 'shib_user_name'), + 'SHIB_ATTR_ORGANIZATION': (False, 'shib_organization'), } """IdP attribute map.""" diff --git a/modules/weko-accounts/weko_accounts/models.py b/modules/weko-accounts/weko_accounts/models.py index fbcdb8292c..b53669fbfd 100644 --- a/modules/weko-accounts/weko_accounts/models.py +++ b/modules/weko-accounts/weko_accounts/models.py @@ -71,6 +71,9 @@ class ShibbolethUser(db.Model): shib_ip_range_flag = db.Column(db.String(255), nullable=True) """SHIB_ATTR_SITE_USER_WITHIN_IP_RANGE_FLAG""" + shib_organization = db.Column(db.String(255), nullable=True) + """SHIB_ATTR_ORGANIZATION""" + shib_roles = db.relationship( 'Role', secondary=shibuserrole, diff --git a/modules/weko-items-ui/tests/conftest.py b/modules/weko-items-ui/tests/conftest.py index ea314182d3..a08469fb32 100644 --- a/modules/weko-items-ui/tests/conftest.py +++ b/modules/weko-items-ui/tests/conftest.py @@ -345,26 +345,31 @@ def db(app): @pytest.fixture() def esindex(app,db_records): + current_search_client.indices.delete(index='test-*') with open("tests/data/mappings/item-v1.0.0.json","r") as f: mapping = json.load(f) + with open("tests/data/mappings/record-view-v1.json","r") as f: + mapping_record_view = json.load(f) search = LocalProxy(lambda: app.extensions["invenio-search"]) with app.test_request_context(): - search.client.indices.create(app.config["INDEXER_DEFAULT_INDEX"],body=mapping) - search.client.indices.put_alias(index=app.config["INDEXER_DEFAULT_INDEX"], name="test-weko") + current_search_client.indices.create(app.config["INDEXER_DEFAULT_INDEX"],body=mapping) + current_search_client.indices.put_alias(index=app.config["INDEXER_DEFAULT_INDEX"], name="test-weko") # print(current_search_client.indices.get_alias()) + current_search_client.indices.create("test-stats-record-view-000001",body=mapping_record_view) + current_search_client.indices.put_alias(index="test-stats-record-view-000001",name="test-stats-record-view") for depid, recid, parent, doi, record, item in db_records: - search.client.index(index='test-weko-item-v1.0.0', doc_type='item-v1.0.0', id=record.id, body=record,refresh='true') + current_search_client.index(index='test-weko-item-v1.0.0', doc_type='item-v1.0.0', id=record.id, body=record,refresh='true') - - yield search + yield current_search_client with app.test_request_context(): - search.client.indices.delete_alias(index=app.config["INDEXER_DEFAULT_INDEX"], name="test-weko") - search.client.indices.delete(index=app.config["INDEXER_DEFAULT_INDEX"], ignore=[400, 404]) - + current_search_client.indices.delete_alias(index=app.config["INDEXER_DEFAULT_INDEX"], name="test-weko") + current_search_client.indices.delete(index=app.config["INDEXER_DEFAULT_INDEX"], ignore=[400, 404]) + #current_search_client.indices.delete_alias(index="test-stats-record-view-000001",name="test-stats-record-view") + #current_search_client.indices.delete(index="test-stats-record-view-000001", ignore=[400,400]) @pytest.fixture() diff --git a/modules/weko-items-ui/tests/data/mappings/record-view-v1.json b/modules/weko-items-ui/tests/data/mappings/record-view-v1.json new file mode 100644 index 0000000000..297c5c3480 --- /dev/null +++ b/modules/weko-items-ui/tests/data/mappings/record-view-v1.json @@ -0,0 +1,89 @@ +{ + "index_patterns": ["__SEARCH_INDEX_PREFIX__stats-record-view-*"], + "settings": { + "index.mapper.dynamic": false, + "index": { + "refresh_interval": "1m", + "lifecycle.name": "weko_stats_policy", + "lifecycle.rollover_alias": "__SEARCH_INDEX_PREFIX__stats-record-view" + } + }, + "mappings": { + "record-view-day-aggregation": { + "date_detection": false, + "dynamic": false, + "numeric_detection": false, + "properties": { + "timestamp": { + "type": "date", + "format": "date_optional_time" + }, + "count": { + "type": "integer" + }, + "unique_count": { + "type": "integer" + }, + "record_id": { + "type": "keyword", + "index": true + }, + "record_name": { + "type": "keyword", + "index": true + }, + "country": { + "type": "keyword", + "index": true + }, + "hostname": { + "type": "keyword", + "index": true + }, + "remote_addr": { + "type": "keyword", + "index": true + }, + "pid_value": { + "type": "keyword", + "index": true + }, + "collection": { + "type": "keyword", + "index": true + }, + "cur_user_id": { + "type": "keyword", + "index": true + }, + "record_index_names": { + "type": "keyword", + "index": true + }, + "record_index_list": { + "type": "nested", + "properties": { + "index_id": { + "type": "keyword" + }, + "index_name_en": { + "type": "keyword", + "index": true + }, + "index_name": { + "type": "keyword", + "index": true + } + } + }, + "site_license_name": { + "type": "keyword", + "index": true + }, + "site_license_flag": { + "type": "boolean" + } + } + } + } +} diff --git a/modules/weko-items-ui/tests/test_utils.py b/modules/weko-items-ui/tests/test_utils.py index 83507216ca..aaaea510ca 100644 --- a/modules/weko-items-ui/tests/test_utils.py +++ b/modules/weko-items-ui/tests/test_utils.py @@ -2,7 +2,7 @@ import hashlib import json import os -from datetime import datetime +from datetime import datetime, timedelta from io import StringIO from collections import OrderedDict from unittest.mock import MagicMock @@ -10,6 +10,8 @@ import tempfile from uuid import UUID from dictdiffer import diff, patch, swap, revert +from elasticsearch import exceptions as es_exceptions +import uuid import pytest from flask_security.utils import login_user @@ -23,6 +25,7 @@ from weko_records.models import ItemType, ItemTypeMapping, ItemTypeName from weko_workflow.api import WorkActivity from weko_user_profiles.models import UserProfile +from weko_admin.models import SessionLifetime,RankingSettings from weko_workflow.models import ( Action, ActionStatus, @@ -68,6 +71,7 @@ get_new_items_by_date, get_options_and_order_list, get_options_list, + WekoQueryRankingHelper, get_ranking, get_title_in_request, get_user_info_by_email, @@ -7843,14 +7847,163 @@ def test_translate_schema_form(db_itemtype): _diff = diff(form_element_pre,form_element) assert list(_diff)==[] - +# .tox/c1/bin/pytest --cov=weko_items_ui tests/test_utils.py::test_WekoQueryRankingHelper_get -v -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-items-ui/.tox/c1/tmp +def test_WekoQueryRankingHelper_get(app, users, db_records,esindex,mocker): + user = users[2] + # add data to record_view + view_data = [ + {"rec_index":0,"count":1,"date":"2023-08-24"}, # recid:1 + {"rec_index":1,"count":3,"date": "2023-08-23"}, # recid:1.1 + {"rec_index":6,"count":2,"date": "2023-08-25"}, # recid: 4 + {"rec_index":4,"count":5,"date": "2023-08-25"}, # recid: 3 + {"rec_index":0,"count":5,"date": "2022-08-25"} # recid: 1 + ] + for data in view_data: + _record=db_records[data["rec_index"]] + pid = _record[1] + record=_record[4] + es_id = uuid.uuid4() + body = { + "timestamp":datetime.strptime(data["date"],"%Y-%m-%d"),"unique_id":str(es_id),"count":data["count"],"unique_count":data["count"],"country":None,"hostname":"None","remote_attr":"111.111.11.1","record_id":pid.object_uuid,"record_name":record["item_title"],"record_index_names":"test_index","pid_type":pid.pid_type,"pid_value":pid.pid_value,"cur_user_id":user["id"],"site_license_name":"","site_license_flag":False + } + esindex.index(index="test-stats-record-view",doc_type="record-view-day-aggregation",id=str(es_id),body=body) + esindex.indices.flush(index="test-*") + + result = WekoQueryRankingHelper.get( + start_date="2023-08-19", + end_date="2023-09-01", + agg_size=110, + event_type='record-view', + group_field='pid_value', + count_field='count', + ranking_type='most_view_ranking' + ) + assert result == [{'key': '3', 'count': 5}, {'key': '1', 'count': 4}, {'key': '4', 'count': 2}] + # raise Exception + with patch("weko_items_ui.utils.json.loads",side_effect=Exception("test_error")): + result = WekoQueryRankingHelper.get( + start_date="2023-08-19", + end_date="2023-09-01", + agg_size=110, + event_type='record-view', + group_field='pid_value', + count_field='count', + ranking_type='most_view_ranking' + ) + assert result == [] + + # raise NotFoundError + with patch("invenio_stats.queries.ESWekoRankingQuery.run",side_effect=es_exceptions.NotFoundError(404,"test_error")): + result = WekoQueryRankingHelper.get( + start_date="2023-08-19", + end_date="2023-09-01", + agg_size=110, + event_type='record-view', + group_field='pid_value', + count_field='count', + ranking_type='most_view_ranking' + ) + assert result == [] + # def get_ranking(settings): -# .tox/c1/bin/pytest --cov=weko_items_ui tests/test_utils.py::test_get_ranking -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-items-ui/.tox/c1/tmp -def test_get_ranking(app, db_records, db_ranking): - settings = db_ranking['settings'] +# .tox/c1/bin/pytest --cov=weko_items_ui tests/test_utils.py::test_get_ranking -v -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-items-ui/.tox/c1/tmp +def test_get_ranking(app, users, db_records, db_ranking, esindex, mocker): + import copy + user = users[2] + today = datetime.today() + view_data = [ + {"rec_index":0,"count":1,"date":today+timedelta(days=-2)}, + {"rec_index":1,"count":3,"date":today+timedelta(days=-2)}, + {"rec_index":6,"count":2,"date":today+timedelta(days=-2)}, + {"rec_index":4,"count":5,"date":today+timedelta(days=-2)}, + {"rec_index":0,"count":5,"date":today+timedelta(days=-370)} + ] + # Add data to record_view + for data in view_data: + _record=db_records[data["rec_index"]] + pid = _record[1] + record=_record[4] + es_id = uuid.uuid4() + body = { + "timestamp":data["date"],"unique_id":str(es_id),"count":data["count"],"unique_count":data["count"],"country":None,"hostname":"None","remote_attr":"111.111.11.1","record_id":pid.object_uuid,"record_name":record["item_title"],"record_index_names":"test_index","pid_type":pid.pid_type,"pid_value":pid.pid_value,"cur_user_id":user["id"],"site_license_name":"","site_license_flag":False + } + esindex.index(index="test-stats-record-view",doc_type="record-view-day-aggregation",id=str(es_id),body=body) + esindex.indices.flush(index="test-*") + + # Mocking the Indexes.get_browsing_tree_ignore_more and Mapping.get_record methods + index_json = [ + {"children": [ + {"children": [], "cid": 10, "pid": 1, "name": "ChildIndex", "id": "10"} + ], "cid": 1, "pid": 0, "name": "ParentIndex", "id": "1"}, + {"children":[],"cid":2,"pid":0,"name":"Index2","id":"2"} + ] + mocker.patch("weko_items_ui.utils.Indexes.get_browsing_tree_ignore_more", return_value=index_json) + title_mapping = {"item_1617186331708": {"jpcoar_mapping": {"title": {"@value": "subitem_1551255647225", "@attributes": {"xml:lang": "subitem_1551255648112"}}}}} + mocker.patch("weko_deposit.api.Mapping.get_record", return_value=title_mapping) + # Mocking the QueryRankingHelper and WekoQueryRankingHelper methods + mocker.patch("weko_items_ui.utils.QueryRankingHelper.get", return_value=[{"key": "test", "count": 1}]) + mocker.patch("weko_items_ui.utils.QueryRankingHelper.get_new_items", return_value=[{"key": "test", "count": 1}]) + mocker.patch("weko_items_ui.utils.WekoQueryRankingHelper.get", return_value=[{"key": "test", "count": 1}]) + + # new_item_start_date < start_date_original + settings = copy.deepcopy(db_ranking['settings']) + settings.new_item_period = 400 + settings.statistical_period = 365 + settings.rankings = { + "most_reviewed_items": True, + "most_downloaded_items": True, + "created_most_items_user": True, + "most_searched_keywords": True, + "new_items": True + } with app.test_request_context(): - assert get_ranking(settings)=={'most_reviewed_items': [], 'most_downloaded_items': [], 'created_most_items_user': [], 'most_searched_keywords': [], 'new_items': []} - + result = get_ranking(settings) + assert isinstance(result, dict) + assert "most_reviewed_items" in result + assert "most_downloaded_items" in result + assert "created_most_items_user" in result + assert "most_searched_keywords" in result + assert "new_items" in result + + for k in result: + assert isinstance(result[k], list) + + # new_item_start_date >= start_date_original + settings.new_item_period = 10 + settings.statistical_period = 365 + settings.rankings = { + "most_reviewed_items": False, + "most_downloaded_items": False, + "created_most_items_user": False, + "most_searched_keywords": False, + "new_items": True + } + with app.test_request_context(): + result = get_ranking(settings) + assert "new_items" in result + + # Test with no rankings enabled + settings.rankings = {k: False for k in settings.rankings} + with app.test_request_context(): + result = get_ranking(settings) + assert result == {} + + # Test with individual rankings enabled + for key in ["most_reviewed_items", "most_downloaded_items", "created_most_items_user", "most_searched_keywords", "new_items"]: + settings.rankings = {k: (k == key) for k in settings.rankings} + with app.test_request_context(): + result = get_ranking(settings) + assert list(result.keys()) == [key] + + # Test with all rankings enabled + mocker.patch("weko_items_ui.utils.QueryRankingHelper.get", return_value=[]) + mocker.patch("weko_items_ui.utils.QueryRankingHelper.get_new_items", return_value=[]) + mocker.patch("weko_items_ui.utils.WekoQueryRankingHelper.get", return_value=[]) + settings.rankings = {k: True for k in settings.rankings} + with app.test_request_context(): + result = get_ranking(settings) + for v in result.values(): + assert v == [] # def __sanitize_string(s: str): # .tox/c1/bin/pytest --cov=weko_items_ui tests/test_utils.py::test___sanitize_string -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-items-ui/.tox/c1/tmp def test___sanitize_string(): diff --git a/modules/weko-items-ui/weko_items_ui/config.py b/modules/weko-items-ui/weko_items_ui/config.py index 86d3c87fb4..71422596da 100644 --- a/modules/weko-items-ui/weko_items_ui/config.py +++ b/modules/weko-items-ui/weko_items_ui/config.py @@ -19,6 +19,7 @@ # MA 02111-1307, USA. """Configuration for weko-items-ui.""" +from invenio_stats.queries import ESWekoRankingQuery WEKO_WORKFLOW_BASE_TEMPLATE = 'weko_workflow/base.html' """Default base template for the demo page.""" @@ -204,4 +205,55 @@ WEKO_ITEMS_UI_RANKING_BUFFER = 100 -WEKO_ITEMS_UI_SEARCH_RANK_KEY_FILTER = [''] \ No newline at end of file +WEKO_ITEMS_UI_SEARCH_RANK_KEY_FILTER = [''] + +WEKO_ITEMS_UI_RANKING_QUERY = dict( + most_view_ranking = dict( + query_class = ESWekoRankingQuery, + query_config = dict( + index='{}-stats-{}', + doc_type='{}-day-aggregation', + main_fields=['start_date', 'end_date', 'group_field', 'agg_size', 'count_field'], + metric_fields=dict(), + main_query={ + "size": 0, + "query": { + "bool": { + "must": [ + { + "range": { + "timestamp": { + "gte": "@start_date", + "lte": "@end_date", + "time_zone": "@time_zone" + } + } + } + ], + "must_not": "@must_not" + } + }, + "aggs": { + "my_buckets": { + "terms": { + "size": "@agg_size", + "order": { + "my_sum": "desc" + }, + "script":{ + "source": "def @group_field = doc['@group_field'].value; return @group_field.contains('.') ? @group_field.substring(0, @group_field.indexOf('.')) : @group_field;" + } + }, + "aggs": { + "my_sum": { + "sum": { + "field": "@count_field" + } + } + } + } + } + } + ) + ) +) diff --git a/modules/weko-items-ui/weko_items_ui/utils.py b/modules/weko-items-ui/weko_items_ui/utils.py index bf305f9237..7d978921e1 100644 --- a/modules/weko-items-ui/weko_items_ui/utils.py +++ b/modules/weko-items-ui/weko_items_ui/utils.py @@ -38,6 +38,7 @@ import redis from redis import sentinel from elasticsearch.exceptions import NotFoundError +from elasticsearch import exceptions as es_exceptions from flask import abort, current_app, flash, redirect, request, send_file, \ url_for,jsonify from flask_babelex import gettext as _ @@ -54,7 +55,10 @@ from invenio_accounts.models import User from invenio_search import RecordsSearch from invenio_stats.utils import QueryRankingHelper, QuerySearchReportHelper -from invenio_stats.views import QueryRecordViewCount +from invenio_stats.views import QueryRecordViewCount as _QueryRecordViewCount +from invenio_stats.proxies import current_stats +from invenio_stats import config +#from invenio_stats.views import QueryRecordViewCount from jsonschema import SchemaError, ValidationError from simplekv.memory.redisstore import RedisStore from sqlalchemy import MetaData, Table @@ -2499,6 +2503,36 @@ def translate_schema_form(form_element, cur_lang): for sub_elem in form_element['items']: translate_schema_form(sub_elem, cur_lang) +class WekoQueryRankingHelper(QueryRankingHelper): + @classmethod + def get(cls, **kwargs): + result = [] + try: + start_date = kwargs.get('start_date') + end_date = kwargs.get('end_date') + params = { + 'start_date': start_date, + 'end_date': end_date + 'T23:59:59', + 'agg_size': str(kwargs.get('agg_size', 10)), + 'event_type': kwargs.get('event_type', ''), + 'group_field': kwargs.get('group_field', ''), + 'count_field': kwargs.get('count_field', ''), + 'must_not': kwargs.get('must_not', ''), + 'new_items': False + } + query_config = current_app.config["WEKO_ITEMS_UI_RANKING_QUERY"][kwargs.get("ranking_type")] + query_class = query_config["query_class"] + cfg =json.loads(json.dumps(query_config["query_config"])) + cfg.update(query_name=kwargs.get("ranking_type")) + all_query = query_class(**cfg) + all_res = all_query.run(**params) + cls.Calculation(all_res, result) + except es_exceptions.NotFoundError as e: + current_app.logger.debug(e) + except Exception as e: + current_app.logger.debug(e) + + return result def get_ranking(settings): """Get ranking. @@ -2533,23 +2567,17 @@ def _get_index_info(index_json, index_info): # most_reviewed_items current_app.logger.debug("get most_reviewed_items start") if settings.rankings['most_reviewed_items']: - result = QueryRankingHelper.get( + result = WekoQueryRankingHelper.get( start_date=start_date, end_date=end_date, agg_size=settings.display_rank + rank_buffer, event_type='record-view', group_field='pid_value', - count_field='count' + count_field='count', + ranking_type='most_view_ranking' ) - - current_app.logger.debug("finished getting most_reviewed_items data from ES") rankings['most_reviewed_items'] = get_permission_record('most_reviewed_items', result, settings.display_rank, has_permission_indexes) - q = QueryRecordViewCount() - for item in rankings['most_reviewed_items']: - ret = q.get_data_by_pid_value(pid_value=item['key']) - item['count'] = int(ret['total']) - # most_downloaded_items current_app.logger.debug("get most_downloaded_items start") if settings.rankings['most_downloaded_items']: @@ -2627,7 +2655,7 @@ def _get_index_info(index_json, index_info): ) ) if new_item_start_date < start_date_original: - new_item_start_date = start_date + new_item_start_date = start_date_original result = QueryRankingHelper.get_new_items( start_date=new_item_start_date.strftime('%Y-%m-%d'), end_date=end_date, diff --git a/modules/weko-records-ui/tests/conftest.py b/modules/weko-records-ui/tests/conftest.py index 4a58402056..419a2418af 100644 --- a/modules/weko-records-ui/tests/conftest.py +++ b/modules/weko-records-ui/tests/conftest.py @@ -5770,7 +5770,7 @@ def site_license_info(app, db): organization_name='test', domain_name='domain', mail_address='nii@nii.co.jp', - receive_mail_flag=False) + receive_mail_flag='Y',) with db.session.begin_nested(): db.session.add(record) return record diff --git a/modules/weko-records-ui/tests/test_ipaddr.py b/modules/weko-records-ui/tests/test_ipaddr.py index 7f52de6dce..90449597bc 100644 --- a/modules/weko-records-ui/tests/test_ipaddr.py +++ b/modules/weko-records-ui/tests/test_ipaddr.py @@ -29,7 +29,35 @@ def test_check_site_license_permission2(app,site_license_info,site_license_ipadd with app.test_request_context(headers={'X-Real-IP': '192.168.0.1','X-Forwarded-For': '192.168.254.1, 192.168.255.1'}): assert check_site_license_permission()==True +# .tox/c1/bin/pytest --cov=weko_records_ui tests/test_ipaddr.py::test_check_site_license_permission_shib_domain -vv -s --cov-branch --cov-report=term --basetemp=/code/modules/weko-records-ui/.tox/c1/tmp +def test_check_site_license_permission_shib_domain(app, site_license_info): + from flask_security import AnonymousUser + from types import SimpleNamespace + + class DummyShibUser: + def __init__(self, org): + self.shib_organization = org + + dummy_user = SimpleNamespace() + dummy_user.is_authenticated = True + dummy_user.shib_weko_user = [DummyShibUser('domain')] + + with app.test_request_context(): + import weko_records_ui.ipaddr as ipaddr_mod + with patch.object(ipaddr_mod, 'current_user', dummy_user): + assert ipaddr_mod.check_site_license_permission() is True + + dummy_user2 = SimpleNamespace() + dummy_user2.is_authenticated = True + dummy_user2.shib_weko_user = [DummyShibUser('otherdomain')] + with app.test_request_context(): + with patch.object(ipaddr_mod, 'current_user', dummy_user2): + assert ipaddr_mod.check_site_license_permission() is False + anon_user = AnonymousUser() + with app.test_request_context(): + with patch.object(ipaddr_mod, 'current_user', anon_user): + assert ipaddr_mod.check_site_license_permission() is False @@ -40,5 +68,4 @@ def test_match_ip_addr(): ip_addr = "192.168.0.100" assert match_ip_addr(addr,ip_addr) == True ip_addr = "192.168.1.100" - assert match_ip_addr(addr,ip_addr) == False - + assert match_ip_addr(addr,ip_addr) == False \ No newline at end of file diff --git a/modules/weko-records-ui/weko_records_ui/ipaddr.py b/modules/weko-records-ui/weko_records_ui/ipaddr.py index a8564dff3f..772e6b5236 100644 --- a/modules/weko-records-ui/weko_records_ui/ipaddr.py +++ b/modules/weko-records-ui/weko_records_ui/ipaddr.py @@ -47,6 +47,22 @@ def check_site_license_permission(): current_user.site_license_name = \ lst.get('organization_name') return True + + user_domain = None + if ( + getattr(current_user, "is_authenticated", False) + and getattr(current_user, "shib_weko_user", None) + ): + for shib_user in current_user.shib_weko_user: + user_domain = shib_user.shib_organization + for lst in sl_lst: + domain_name = lst.get('domain_name') + + if user_domain == domain_name: + current_user.site_license_flag = True + current_user.site_license_name = lst.get('organization_name') + return True + return False diff --git a/modules/weko-records/tests/test_serializers_utils.py b/modules/weko-records/tests/test_serializers_utils.py index 990add0484..1d3a7ee655 100644 --- a/modules/weko-records/tests/test_serializers_utils.py +++ b/modules/weko-records/tests/test_serializers_utils.py @@ -288,14 +288,124 @@ def fetcher(obj_uuid, data): # class OpenSearchDetailData: # def output_open_search_detail_data(self): +# .tox/c1/bin/pytest --cov=weko_records tests/test_serializers_utils.py::test_output_open_search_detail_data -v -s -vv --cov-branch --cov-report=term --cov-config=tox.ini --basetemp=/code/modules/weko-records/.tox/c1/tmp def test_output_open_search_detail_data(app): - with app.test_request_context(): - assert_str = 'WEKO OpenSearch : ' - res = sample.output_open_search_detail_data() - _tree = etree.fromstring(res) - _record = str(etree.tostring(_tree.findall('title', namespaces=_tree.nsmap)[0]),"utf-8").replace('\n ', '') - assert _record == str(etree.tostring(etree.fromstring(assert_str)),"utf-8") + item_map = { + 'volume.@value': 'item_1617186959569.subitem_1551256328147', + 'issue.@value': 'item_1617186981471.subitem_1551256294723', + 'pageStart.@value': 'item_1617187024783.subitem_1551256198917', + 'pageEnd.@value': 'item_1617187045071.subitem_1551256185532', + } + item_metadata = { + 'item_type_id': '1', + 'item_title': 'test', + 'control_number': '1', + 'path': ['1'], + 'item_1617186959569': {'attribute_name': 'Volume Number', 'attribute_value_mlt': [{'subitem_1551256328147': '21'}]}, + 'item_1617186981471': {'attribute_name': 'Issue Number', 'attribute_value_mlt': [{'subitem_1551256294723': '13'}]}, + 'item_1617187024783': {'attribute_name': 'Page Start', 'attribute_value_mlt': [{'subitem_1551256198917': '167'}]}, + 'item_1617187045071': {'attribute_name': 'Page End', 'attribute_value_mlt': [{'subitem_1551256185532': '223'}]}, + 'pubdate': {'attribute_name': 'PubDate', 'attribute_value': '2025-06-01'}, + } + hit = { + '_source': { + '_item_metadata': item_metadata, + '_oai': {'id': 'dummy_oai'}, + 'itemtype': 'dummy_itemtype', + '_created': None, + '_updated': None, + } + } + with patch("weko_records.api.Mapping.get_record", return_value={}), \ + patch("weko_records.serializers.utils.get_mapping", return_value=item_map), \ + patch("weko_records.serializers.utils.get_metadata_from_map", side_effect=[ + {'item_1617186959569.subitem_1551256328147': ['21']}, # volume + {'item_1617186981471.subitem_1551256294723': ['13']}, # issue + {'item_1617187024783.subitem_1551256198917': ['167']}, # pageStart + {'item_1617187045071.subitem_1551256185532': ['223']}, # pageEnd + ]), \ + patch("weko_records.serializers.utils.Index.query") as mock_index_query: + mock_index_query.filter_by.return_value.one_or_none.return_value = MagicMock(index_name='dummy_index', index_name_english='dummy_index_en') + sample_copy = copy.deepcopy(sample) + with app.test_request_context(): + sample_copy.search_result = {'hits': {'total': 1, 'hits': [hit]}} + sample_copy.output_type = "atom" + xml = sample_copy.output_open_search_detail_data() + assert b'21' in xml + assert b'13' in xml + assert b'167' in xml + assert b'223' in xml + +@pytest.mark.parametrize( + "item_map, item_metadata_key, xml_tag", + [ + ({'volume.@value': 'volume_key'}, 'volume_key', 'prism:volume'), + ({'issue.@value': 'issue_key'}, 'issue_key', 'prism:number'), + ({'pageStart.@value': 'page_start_key'}, 'page_start_key', 'prism:startingPage'), + ({'pageEnd.@value': 'page_end_key'}, 'page_end_key', 'prism:endingPage'), + ] +) +# .tox/c1/bin/pytest --cov=weko_records tests/test_serializers_utils.py::test_output_open_search_detail_data_field_false -v -s -vv --cov-branch --cov-report=term --cov-config=tox.ini --basetemp=/code/modules/weko-records/.tox/c1/tmp +def test_output_open_search_detail_data_field_false(app, item_map, item_metadata_key, xml_tag): + # item_id does not exist in item_metadata + item_metadata = { + 'item_type_id': '1', + 'item_title': 'test', + 'control_number': '1', + 'path': ['1'], + 'pubdate': {'attribute_name': 'PubDate', 'attribute_value': '2025-06-01'}, + } + hit = { + '_source': { + '_item_metadata': item_metadata, + '_oai': {'id': 'dummy_oai'}, + 'itemtype': 'dummy_itemtype', + '_created': None, + '_updated': None, + } + } + with patch("weko_records.api.Mapping.get_record", return_value={}), \ + patch("weko_records.serializers.utils.get_mapping", return_value=item_map), \ + patch("weko_records.serializers.utils.get_metadata_from_map", return_value={item_metadata_key: ['val']}), \ + patch("weko_records.serializers.utils.Index.query") as mock_index_query: + mock_index_query.filter_by.return_value.one_or_none.return_value = MagicMock(index_name='dummy_index', index_name_english='dummy_index_en') + sample_copy = copy.deepcopy(sample) + with app.test_request_context(): + sample_copy.search_result = {'hits': {'total': 1, 'hits': [hit]}} + sample_copy.output_type = "atom" + xml = sample_copy.output_open_search_detail_data() + assert f'<{xml_tag}>' not in xml.decode() + + # get_metadata_from_map returns a non-dict value + item_metadata2 = dict(item_metadata) + item_metadata2[item_metadata_key.split('.')[0]] = {'attribute_name': 'dummy', 'attribute_value_mlt': [{'dummy': 'val'}]} + hit2 = copy.deepcopy(hit) + hit2['_source']['_item_metadata'] = item_metadata2 + with patch("weko_records.api.Mapping.get_record", return_value={}), \ + patch("weko_records.serializers.utils.get_mapping", return_value=item_map), \ + patch("weko_records.serializers.utils.get_metadata_from_map", return_value=None), \ + patch("weko_records.serializers.utils.Index.query") as mock_index_query: + mock_index_query.filter_by.return_value.one_or_none.return_value = MagicMock(index_name='dummy_index', index_name_english='dummy_index_en') + sample_copy = copy.deepcopy(sample) + with app.test_request_context(): + sample_copy.search_result = {'hits': {'total': 1, 'hits': [hit2]}} + sample_copy.output_type = "atom" + xml = sample_copy.output_open_search_detail_data() + assert f'<{xml_tag}>' not in xml.decode() + + # get_metadata_from_map returns a string value + with patch("weko_records.api.Mapping.get_record", return_value={}), \ + patch("weko_records.serializers.utils.get_mapping", return_value=item_map), \ + patch("weko_records.serializers.utils.get_metadata_from_map", return_value={item_metadata_key: 'abc'}), \ + patch("weko_records.serializers.utils.Index.query") as mock_index_query: + mock_index_query.filter_by.return_value.one_or_none.return_value = MagicMock(index_name='dummy_index', index_name_english='dummy_index_en') + sample_copy = copy.deepcopy(sample) + with app.test_request_context(): + sample_copy.search_result = {'hits': {'total': 1, 'hits': [hit2]}} + sample_copy.output_type = "atom" + xml = sample_copy.output_open_search_detail_data() + assert f'<{xml_tag}>abc'.encode() in xml # def _set_publication_date(self, fe, item_map, item_metadata): def test__set_publication_date(app): @@ -479,5 +589,3 @@ def test__set_description(app): with patch("weko_records_ui.utils.get_pair_value", return_value=data1): assert sample_copy._set_description(fe=fe, item_map=item_map, item_metadata=item_metadata, request_lang=request_lang) == None - - diff --git a/modules/weko-records/weko_records/serializers/utils.py b/modules/weko-records/weko_records/serializers/utils.py index 36d8738b9d..4fe1d81504 100644 --- a/modules/weko-records/weko_records/serializers/utils.py +++ b/modules/weko-records/weko_records/serializers/utils.py @@ -565,7 +565,7 @@ def output_open_search_detail_data(self): self._set_source_identifier(fe, item_map, item_metadata) # Set volume - _volume = 'volume' + _volume = 'volume.@value' if _volume in item_map: volume_key = item_map[_volume] item_id = volume_key.split('.')[0] @@ -586,7 +586,7 @@ def output_open_search_detail_data(self): fe.prism.volume(volumes) # Set number - _issue = 'issue' + _issue = 'issue.@value' if _issue in item_map: issue_key = item_map[_issue] item_id = issue_key.split('.')[0] @@ -608,7 +608,7 @@ def output_open_search_detail_data(self): fe.prism.number(issues) # Set startingPage - _page_start = 'pageStart' + _page_start = 'pageStart.@value' if _page_start in item_map: page_start_key = item_map[_page_start] item_id = page_start_key.split('.')[0] @@ -630,7 +630,7 @@ def output_open_search_detail_data(self): fe.prism.startingPage(page_starts) # Set endingPage - _page_end = 'pageEnd' + _page_end = 'pageEnd.@value' if _page_end in item_map: page_end_key = item_map[_page_end] item_id = page_end_key.split('.')[0] diff --git a/nginx/attribute-map.xml b/nginx/attribute-map.xml index 54c14ecfad..e0a31f4f2f 100644 --- a/nginx/attribute-map.xml +++ b/nginx/attribute-map.xml @@ -59,17 +59,21 @@ + + + + diff --git a/nginx/login.php b/nginx/login.php index 32f086174c..497011bb29 100644 --- a/nginx/login.php +++ b/nginx/login.php @@ -26,6 +26,8 @@ $post_args["SHIB_ATTR_PAGE_NAME"]=$_SERVER['HTTP_WEKOSOCIETYSUBGROUP']; $post_args["SHIB_ATTR_ACTIVE_FLAG"]=$_SERVER['HTTP_WEKOACTIVEUSER']; $post_args["SHIB_ATTR_SITE_USER_WITHIN_IP_RANGE_FLAG"]=$_SERVER['HTTP_WEKOSITEUSERWITHINIPRANGE']; + $post_args["SHIB_ATTR_ORGANIZATION"] = $_SERVER['uidpDomainName']; + $options = array( //Method CURLOPT_POST => true,//POST diff --git a/postgresql/ddl/h2025-01-shib_organization.sql b/postgresql/ddl/h2025-01-shib_organization.sql new file mode 100644 index 0000000000..3c85ade663 --- /dev/null +++ b/postgresql/ddl/h2025-01-shib_organization.sql @@ -0,0 +1 @@ +ALTER TABLE shibboleth_user ADD COLUMN shib_organization VARCHAR(255); \ No newline at end of file diff --git a/scripts/instance.cfg b/scripts/instance.cfg index 138da81d7d..ed6ccedb91 100644 --- a/scripts/instance.cfg +++ b/scripts/instance.cfg @@ -452,6 +452,7 @@ WEKO_ACCOUNTS_SSO_ATTRIBUTE_MAP = { 'SHIB_ATTR_SITE_USER_WITHIN_IP_RANGE_FLAG': (False, 'shib_ip_range_flag'), 'SHIB_ATTR_MAIL': (False, 'shib_mail'), 'SHIB_ATTR_USER_NAME': (False, 'shib_user_name'), + 'SHIB_ATTR_ORGANIZATION': (False, 'shib_organization'), } # Shibboleth login pattern. (True: Shibboleth IdP(JairoCloud), False: Embedded DS-Pattern 1) diff --git a/scripts/provision-web.sh b/scripts/provision-web.sh index a018a7a35e..ec575ddef6 100755 --- a/scripts/provision-web.sh +++ b/scripts/provision-web.sh @@ -48,14 +48,15 @@ export DEBIAN_FRONTEND=noninteractive provision_web_common_ubuntu14 () { - # Update sources.list to use archive repositories - $sudo sed -i 's|http://deb.debian.org/debian|http://archive.debian.org/debian|g' /etc/apt/sources.list - $sudo sed -i 's|http://security.debian.org/debian-security|http://archive.debian.org/debian-security|g' /etc/apt/sources.list + # Point the main repository to the archive + sed -i 's/deb.debian.org/archive.debian.org/g' /etc/apt/sources.list + + # Point the security repository to the archive + sed -i 's/security.debian.org/archive.debian.org/g' /etc/apt/sources.list # sphinxdoc-install-useful-system-tools-ubuntu14-begin # update list of available packages: - # $sudo apt-get -y update --allow-releaseinfo-change - $sudo apt-get -y update -o Acquire::Check-Valid-Until=false --allow-releaseinfo-change + $sudo apt-get -y update --allow-releaseinfo-change # install useful system tools: $sudo apt-get -y install \