Skip to content

Commit ae060cd

Browse files
committed
Merge branch 'feature/pbs-26-9' into fix/ENG--10788
2 parents de26575 + 7d72518 commit ae060cd

107 files changed

Lines changed: 3748 additions & 683 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.docker-compose.env

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ INTERNAL_DOMAIN=http://192.168.168.167:5000/
77
API_DOMAIN=http://localhost:8000/
88
ELASTIC_URI=192.168.168.167:9200
99
ELASTIC6_URI=192.168.168.167:9201
10+
ELASTIC8_URI=http://192.168.168.167:9202
11+
ELASTIC8_USERNAME=elastic
1012
OSF_DB_HOST=192.168.168.167
1113
DB_HOST=192.168.168.167
1214
REDIS_HOST=redis://192.168.168.167:6379

.github/workflows/test-build.yml

Lines changed: 27 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,19 @@ jobs:
3737
permissions:
3838
checks: write
3939
services:
40-
postgres:
40+
elasticsearch8: &ES8_SERVICE
41+
image: elasticsearch:8.19.14
42+
ports:
43+
- 9202:9200
44+
env:
45+
discovery.type: single-node
46+
xpack.security.enabled: false
47+
options: >-
48+
--health-cmd "curl -sf http://localhost:9200/_cluster/health?wait_for_status=yellow&timeout=30s"
49+
--health-interval 10s
50+
--health-timeout 30s
51+
--health-retries 5
52+
postgres: &POSTGRES_SERVICE
4153
image: postgres
4254
env:
4355
POSTGRES_PASSWORD: ${{ env.OSF_DB_PASSWORD }}
@@ -54,6 +66,8 @@ jobs:
5466
- uses: ./.github/actions/start-build
5567
- name: Run tests
5668
run: poetry run python3 -m invoke test-ci-addons --junit
69+
env:
70+
ELASTIC8_URI: http://localhost:9202
5771
- name: Upload report
5872
if: (success() || failure()) # run this step even if previous step failed
5973
uses: ./.github/actions/gen-report
@@ -64,18 +78,7 @@ jobs:
6478
permissions:
6579
checks: write
6680
services:
67-
postgres:
68-
image: postgres
69-
env:
70-
POSTGRES_PASSWORD: ${{ env.OSF_DB_PASSWORD }}
71-
options: >-
72-
--health-cmd pg_isready
73-
--health-interval 10s
74-
--health-timeout 5s
75-
--health-retries 5
76-
ports:
77-
# Maps tcp port 5432 on service container to the host
78-
- 5432:5432
81+
postgres: *POSTGRES_SERVICE
7982
steps:
8083
- uses: actions/checkout@v6
8184
- uses: ./.github/actions/start-build
@@ -91,25 +94,17 @@ jobs:
9194
permissions:
9295
checks: write
9396
services:
94-
postgres:
95-
image: postgres
96-
env:
97-
POSTGRES_PASSWORD: ${{ env.OSF_DB_PASSWORD }}
98-
options: >-
99-
--health-cmd pg_isready
100-
--health-interval 10s
101-
--health-timeout 5s
102-
--health-retries 5
103-
ports:
104-
# Maps tcp port 5432 on service container to the host
105-
- 5432:5432
97+
elasticsearch8: *ES8_SERVICE
98+
postgres: *POSTGRES_SERVICE
10699
steps:
107100
- uses: actions/checkout@v6
108101
- uses: ./.github/actions/start-build
109102
- name: NVM & yarn install
110103
run: poetry run python3 -m invoke assets --dev
111104
- name: Run test
112105
run: poetry run python3 -m invoke test-ci-api1-and-js --junit
106+
env:
107+
ELASTIC8_URI: http://localhost:9202
113108
- name: Upload report
114109
if: (success() || failure()) # run this step even if previous step failed
115110
uses: ./.github/actions/gen-report
@@ -120,23 +115,15 @@ jobs:
120115
permissions:
121116
checks: write
122117
services:
123-
postgres:
124-
image: postgres
125-
env:
126-
POSTGRES_PASSWORD: ${{ env.OSF_DB_PASSWORD }}
127-
options: >-
128-
--health-cmd pg_isready
129-
--health-interval 10s
130-
--health-timeout 5s
131-
--health-retries 5
132-
ports:
133-
# Maps tcp port 5432 on service container to the host
134-
- 5432:5432
118+
elasticsearch8: *ES8_SERVICE
119+
postgres: *POSTGRES_SERVICE
135120
steps:
136121
- uses: actions/checkout@v6
137122
- uses: ./.github/actions/start-build
138123
- name: Run tests
139124
run: poetry run python3 -m invoke test-ci-api2 --junit
125+
env:
126+
ELASTIC8_URI: http://localhost:9202
140127
- name: Upload report
141128
if: (success() || failure()) # run this step even if previous step failed
142129
uses: ./.github/actions/gen-report
@@ -147,19 +134,7 @@ jobs:
147134
checks: write
148135
needs: build-cache
149136
services:
150-
postgres:
151-
image: postgres
152-
153-
env:
154-
POSTGRES_PASSWORD: ${{ env.OSF_DB_PASSWORD }}
155-
options: >-
156-
--health-cmd pg_isready
157-
--health-interval 10s
158-
--health-timeout 5s
159-
--health-retries 5
160-
ports:
161-
# Maps tcp port 5432 on service container to the host
162-
- 5432:5432
137+
postgres: *POSTGRES_SERVICE
163138
steps:
164139
- uses: actions/checkout@v6
165140
- uses: ./.github/actions/start-build
@@ -175,19 +150,7 @@ jobs:
175150
checks: write
176151
needs: build-cache
177152
services:
178-
postgres:
179-
image: postgres
180-
181-
env:
182-
POSTGRES_PASSWORD: ${{ env.OSF_DB_PASSWORD }}
183-
options: >-
184-
--health-cmd pg_isready
185-
--health-interval 10s
186-
--health-timeout 5s
187-
--health-retries 5
188-
ports:
189-
# Maps tcp port 5432 on service container to the host
190-
- 5432:5432
153+
postgres: *POSTGRES_SERVICE
191154
mailhog:
192155
image: mailhog/mailhog
193156
ports:
@@ -208,19 +171,7 @@ jobs:
208171
checks: write
209172
needs: build-cache
210173
services:
211-
postgres:
212-
image: postgres
213-
214-
env:
215-
POSTGRES_PASSWORD: ${{ env.OSF_DB_PASSWORD }}
216-
options: >-
217-
--health-cmd pg_isready
218-
--health-interval 10s
219-
--health-timeout 5s
220-
--health-retries 5
221-
ports:
222-
# Maps tcp port 5432 on service container to the host
223-
- 5432:5432
174+
postgres: *POSTGRES_SERVICE
224175
steps:
225176
- uses: actions/checkout@v6
226177
- uses: ./.github/actions/start-build

CHANGELOG

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,29 @@
22

33
We follow the CalVer (https://calver.org/) versioning scheme: YY.MINOR.MICRO.
44

5+
26.10.0 (2026-05-19)
6+
===================
7+
8+
- osfmetrics data migration from elasticsearch6 to elasticsearch8
9+
- add configuration for osfmetrics with es8 (in parallel with es6)
10+
- save new osfmetrics event records and periodic reports in both es6 and es8
11+
- add migrate_osfmetrics_6to8 command to copy old data from es6 to es8
12+
13+
26.9.1 (2026-05-15)
14+
===================
15+
16+
- Hotfix for registrations stuck archiving
17+
18+
26.9.0 (2026-05-07)
19+
===================
20+
21+
- OSF4I In-progress SSO Project - BE Piece
22+
23+
26.8.2 (2026-05-06)
24+
===================
25+
26+
- Hotfix to avoid 502 on creating preprint version from rejected version
27+
528
26.8.1 (2026-04-30)
629
===================
730

addons/base/views.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import waffle
1515
from django.db import transaction
1616
from django.contrib.contenttypes.models import ContentType
17-
from elasticsearch import exceptions as es_exceptions
17+
from elasticsearch6 import exceptions as es_exceptions
1818
from rest_framework import status as http_status
1919

2020
from api.caching.tasks import update_storage_usage_with_size
@@ -34,6 +34,7 @@
3434
from framework.flask import redirect
3535
from framework.sentry import log_exception
3636
from framework.transactions.handlers import no_auto_transaction
37+
from osf.metrics.es8_metrics import OsfCountedUsageEvent
3738
from website import settings
3839
from addons.base import signals as file_signals
3940
from addons.base.utils import format_last_known_metadata, get_mfr_url
@@ -691,6 +692,18 @@ def osfstoragefile_viewed_update_metrics(self, auth, fileversion, file_node):
691692
version=fileversion.identifier,
692693
path=file_node.path,
693694
)
695+
OsfCountedUsageEvent.record(
696+
user_id=getattr(user, '_id', None),
697+
item_osfid=resource._id,
698+
action_labels=[
699+
OsfCountedUsageEvent.ActionLabel.VIEW.value,
700+
OsfCountedUsageEvent.ActionLabel.WEB.value,
701+
],
702+
# HACK: we don't have the user request, so fabricate a one-off session id
703+
# (this means no double-click filtering for anonymous users (same as before)
704+
# and potentially inflated "unique" sessionhour view counts)
705+
client_session_id=str(uuid.uuid4()),
706+
)
694707
except es_exceptions.ConnectionError:
695708
log_exception()
696709

@@ -718,6 +731,17 @@ def osfstoragefile_downloaded_update_metrics(self, auth, fileversion, file_node)
718731
version=fileversion.identifier,
719732
path=file_node.path,
720733
)
734+
OsfCountedUsageEvent.record(
735+
user_id=getattr(user, '_id', None),
736+
item_osfid=resource._id,
737+
action_labels=[
738+
OsfCountedUsageEvent.ActionLabel.DOWNLOAD.value,
739+
],
740+
# HACK: we don't have the user request, so fabricate a one-off session id
741+
# (this means no double-click filtering for anonymous users (same as before)
742+
# and potentially inflated "unique" sessionhour view counts)
743+
client_session_id=str(uuid.uuid4()),
744+
)
721745
except es_exceptions.ConnectionError:
722746
log_exception()
723747

admin/institutions/forms.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from django import forms
2-
from osf.models import Institution
2+
from osf.models.institution import Institution, SSOAvailability
33

44

55
class InstitutionForm(forms.ModelForm):
@@ -10,6 +10,25 @@ class Meta:
1010
'is_deleted', 'contributors', 'storage_regions',
1111
]
1212

13+
def clean(self):
14+
super().clean()
15+
16+
if hasattr(self, 'cleaned_data') and self.changed_data:
17+
if not self.cleaned_data['delegation_protocol']:
18+
if self.cleaned_data['sso_availability'] != SSOAvailability.UNAVAILABLE.value:
19+
self.add_error(None, 'SSO availability must be set to "Unavailable" when no delegation protocol is configured.')
20+
21+
elif self.cleaned_data['deactivated']:
22+
if self.cleaned_data['sso_availability'] != SSOAvailability.HIDDEN.value:
23+
self.add_error(None, 'SSO availability must be set to "Hidden" when the institution is deactivated.')
24+
25+
else:
26+
if self.cleaned_data['sso_availability'] not in [
27+
SSOAvailability.PUBLIC.value,
28+
SSOAvailability.HIDDEN.value
29+
]:
30+
self.add_error(None, 'SSO availability must be set to "Public" or "Hidden" when delegation protocol is configured.')
31+
1332

1433
class InstitutionalMetricsAdminRegisterForm(forms.Form):
1534
""" A form that finds an existing OSF User, and grants permissions to that

admin/institutions/views.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ def get_context_data(self, *args, **kwargs):
5656
institution_dict = model_to_dict(institution)
5757
kwargs.setdefault('page_number', self.request.GET.get('page', '1'))
5858
kwargs['institution'] = institution_dict
59+
kwargs['cas_login_url'] = institution.cas_login_url
5960
kwargs['logo_path'] = institution.logo_path
6061
kwargs['banner_path'] = institution.banner_path
6162
fields = institution_dict
@@ -117,6 +118,17 @@ def get_context_data(self, *args, **kwargs):
117118
def get_success_url(self, *args, **kwargs):
118119
return reverse_lazy('institutions:detail', kwargs={'institution_id': self.kwargs.get('institution_id')})
119120

121+
def post(self, request, *args, **kwargs):
122+
# Override `post` method in `django.views.generic.edit.ProcessFormView` due to custom behavior
123+
self.object = self.get_object()
124+
form = self.get_form()
125+
if form.is_valid():
126+
return self.form_valid(form)
127+
else:
128+
for error in form.non_field_errors():
129+
messages.error(request, error)
130+
return redirect('institutions:detail', institution_id=self.kwargs.get('institution_id'))
131+
120132

121133
class InstitutionExport(PermissionRequiredMixin, View):
122134
permission_required = 'osf.view_institution'

admin/management/urls.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from django.urls import re_path
1+
from django.urls import re_path, path
22

33
from admin.management import views
44

@@ -21,5 +21,6 @@
2121
re_path(r'^sync_notification_templates', views.SyncNotificationTemplates.as_view(),
2222
name='sync_notification_templates'),
2323
re_path(r'^remove_orcid_from_user_social', views.RemoveOrcidFromUserSocial.as_view(),
24-
name='remove_orcid_from_user_social')
24+
name='remove_orcid_from_user_social'),
25+
path('migrate_osfmetrics_6to8', views.MigrateOsfmetrics6to8.as_view(), name='migrate_osfmetrics_6to8'),
2526
]

0 commit comments

Comments
 (0)