diff --git a/admin/institutions/forms.py b/admin/institutions/forms.py
index ccb7e9c4e77..1ccd3dc514f 100644
--- a/admin/institutions/forms.py
+++ b/admin/institutions/forms.py
@@ -1,5 +1,5 @@
from django import forms
-from osf.models import Institution
+from osf.models.institution import Institution, SSOAvailability
class InstitutionForm(forms.ModelForm):
@@ -10,6 +10,18 @@ class Meta:
'is_deleted', 'contributors', 'storage_regions',
]
+ def clean(self):
+ super().clean()
+
+ if hasattr(self, 'cleaned_data') and self.changed_data:
+ if not self.cleaned_data['delegation_protocol']:
+ if self.cleaned_data['sso_availability'] != SSOAvailability.UNAVAILABLE.value:
+ self.add_error('sso_availability', 'Must be UNAVAILABLE when no protocol')
+
+ elif self.cleaned_data['deactivated']:
+ if self.cleaned_data['sso_availability'] != SSOAvailability.HIDDEN.value:
+ self.add_error('sso_availability', 'Inactive must be HIDDEN')
+
class InstitutionalMetricsAdminRegisterForm(forms.Form):
""" A form that finds an existing OSF User, and grants permissions to that
diff --git a/admin/institutions/views.py b/admin/institutions/views.py
index 536d916d937..bd690747b48 100644
--- a/admin/institutions/views.py
+++ b/admin/institutions/views.py
@@ -56,6 +56,7 @@ def get_context_data(self, *args, **kwargs):
institution_dict = model_to_dict(institution)
kwargs.setdefault('page_number', self.request.GET.get('page', '1'))
kwargs['institution'] = institution_dict
+ kwargs['cas_login_url'] = institution.cas_login_url
kwargs['logo_path'] = institution.logo_path
kwargs['banner_path'] = institution.banner_path
fields = institution_dict
@@ -117,6 +118,16 @@ def get_context_data(self, *args, **kwargs):
def get_success_url(self, *args, **kwargs):
return reverse_lazy('institutions:detail', kwargs={'institution_id': self.kwargs.get('institution_id')})
+ def post(self, request, *args, **kwargs):
+ # Override `post` method in `django.views.generic.edit.ProcessFormView` due to custom behavior
+ self.object = self.get_object()
+ form = self.get_form()
+ if form.is_valid():
+ return self.form_valid(form)
+ else:
+ messages.error(request, form.errors)
+ return redirect('institutions:detail', institution_id=self.kwargs.get('institution_id'))
+
class InstitutionExport(PermissionRequiredMixin, View):
permission_required = 'osf.view_institution'
diff --git a/admin/templates/institutions/detail.html b/admin/templates/institutions/detail.html
index 8c4a9e79e15..38b3ba2813d 100644
--- a/admin/templates/institutions/detail.html
+++ b/admin/templates/institutions/detail.html
@@ -1,7 +1,33 @@
{% extends "base.html" %}
{% load static %}
{% block top_includes %}
-
+
+
{% endblock %}
{% load comment_extras %}
{% block title %}
@@ -34,6 +60,18 @@
{% if perms.osf.change_institution %}
Manage Admins
{% endif %}
+ {% if cas_login_url %}
+
+
+
+
×
+
Value copied. You can also copy manually:
+
+
+
+ {% endif %}
@@ -169,5 +207,27 @@ Are you sure you want to run monthly report for this institution?
});
});
});
+
+ window.openCopyPopup = function(text) {
+ const modal = document.getElementById("copy-modal");
+ const input = document.getElementById("copy-input");
+ input.value = text;
+ modal.classList.add("show_modal");
+ navigator.clipboard.writeText(text).catch(() => {});
+ input.focus();
+ input.select();
+ };
+
+ window.closeCopyPopup = function() {
+ document.getElementById("copy-modal").classList.remove("show_modal");
+ };
+
+ // Close on outside click
+ window.onclick = function(event) {
+ const modal = document.getElementById("copy-modal");
+ if (event.target === modal) {
+ modal.classList.remove("show_modal");
+ }
+ };
{% endblock %}
diff --git a/admin/templates/institutions/list.html b/admin/templates/institutions/list.html
index f990c778d25..47e6d09233f 100644
--- a/admin/templates/institutions/list.html
+++ b/admin/templates/institutions/list.html
@@ -20,6 +20,7 @@ List of Institutions
Name |
Description |
Status |
+ SSO Availability |
@@ -37,6 +38,7 @@ List of Institutions
{% else %}
DEACTIVATED |
{% endif %}
+ {{ institution.sso_availability }} |
{% endfor %}
diff --git a/admin_tests/institutions/test_views.py b/admin_tests/institutions/test_views.py
index 13cb1456ab9..1a8029ed088 100644
--- a/admin_tests/institutions/test_views.py
+++ b/admin_tests/institutions/test_views.py
@@ -139,11 +139,24 @@ def test_institution_form(self):
'name': 'New Name',
'logo_name': 'awesome_logo.png',
'domains': 'http://kris.biz/, http://www.little.biz/',
- '_id': 'newawesomeprov'
+ '_id': 'newawesomeprov',
+ 'sso_availability': 'Unavailable',
}
form = InstitutionForm(data=new_data)
assert form.is_valid()
+ def test_institution_form_invalid(self):
+ new_data = {
+ 'name': 'New Name',
+ 'logo_name': 'awesome_logo.png',
+ 'domains': 'http://kris.biz/, http://www.little.biz/',
+ '_id': 'newawesomeprov',
+ 'sso_availability': 'Public',
+ }
+ form = InstitutionForm(data=new_data)
+ assert not form.is_valid()
+ assert 'sso_availability' in form.errors
+
class TestInstitutionExport(AdminTestCase):
def setUp(self):
@@ -214,7 +227,8 @@ def test_monthly_reporter_called_on_create(self, mock_monthly_reporter_do):
'email_domains': FakeList('domain_name', n=1),
'orcid_record_verified_source': '',
'delegation_protocol': '',
- 'institutional_request_access_enabled': False
+ 'institutional_request_access_enabled': False,
+ 'sso_availability': 'Unavailable',
}
form = InstitutionForm(data=data)
assert form.is_valid()
diff --git a/api/institutions/serializers.py b/api/institutions/serializers.py
index 6f4bc4f9e15..fc1e48cefdf 100644
--- a/api/institutions/serializers.py
+++ b/api/institutions/serializers.py
@@ -29,10 +29,12 @@ class InstitutionSerializer(JSONAPISerializer):
'id',
'name',
'auth_url',
+ 'sso_availability',
])
name = ser.CharField(read_only=True)
id = ser.CharField(read_only=True, source='_id')
+ sso_availability = ser.CharField(read_only=True)
description = ser.CharField(read_only=True)
auth_url = ser.CharField(read_only=True)
iri = ser.CharField(read_only=True, source='identifier_domain')
diff --git a/api/institutions/views.py b/api/institutions/views.py
index a3c0f93d0c8..d653f5b4e77 100644
--- a/api/institutions/views.py
+++ b/api/institutions/views.py
@@ -73,6 +73,9 @@ class InstitutionList(JSONAPIBaseView, generics.ListAPIView, ListFilterMixin):
base_permissions.TokenHasScope,
)
+ # Adding sso_availability to MULTIPLE_VALUES_FIELDS to allow filtering institutions by multiple sso_availability values, e.g. ?filter[sso_availability]=[Unavailable,Hidden]
+ MULTIPLE_VALUES_FIELDS = ListFilterMixin.MULTIPLE_VALUES_FIELDS + ['sso_availability']
+
required_read_scopes = [CoreScopes.INSTITUTION_READ]
required_write_scopes = [CoreScopes.NULL]
model_class = Institution
@@ -85,7 +88,9 @@ class InstitutionList(JSONAPIBaseView, generics.ListAPIView, ListFilterMixin):
ordering = ('name',)
def get_default_queryset(self):
- return Institution.objects.filter(_id__isnull=False, is_deleted=False)
+ if 'filter[sso_availability]' in self.request.query_params:
+ return Institution.objects.filter(_id__isnull=False, is_deleted=False)
+ return Institution.objects.get_non_hidden_institutions().filter(_id__isnull=False, is_deleted=False)
# overrides ListAPIView
def get_queryset(self):
diff --git a/api_tests/institutions/views/test_institution_list.py b/api_tests/institutions/views/test_institution_list.py
index 74cb0b6bc8f..60e63056b7a 100644
--- a/api_tests/institutions/views/test_institution_list.py
+++ b/api_tests/institutions/views/test_institution_list.py
@@ -15,6 +15,10 @@ def institution_one(self):
def institution_two(self):
return InstitutionFactory()
+ @pytest.fixture()
+ def institution_three(self):
+ return InstitutionFactory()
+
@pytest.fixture()
def url_institution(self):
return f'/{API_BASE}institutions/'
@@ -47,3 +51,53 @@ def test_does_not_return_deleted_institution(
assert len(res.json['data']) == 1
assert institution_one._id not in ids
assert institution_two._id in ids
+
+ def test_sso_availability_filter(
+ self, app, institution_one, institution_two, institution_three, url_institution
+ ):
+ institution_one.sso_availability = 'Unavailable'
+ institution_one.save()
+
+ institution_two.sso_availability = 'Public'
+ institution_two.save()
+
+ institution_three.sso_availability = 'Hidden'
+ institution_three.save()
+
+ res = app.get(f'{url_institution}?filter[sso_availability]=[Unavailable]')
+ assert res.status_code == 200
+
+ ids = [each['id'] for each in res.json['data']]
+ assert len(res.json['data']) == 1
+ assert institution_one._id in ids
+ assert institution_two._id not in ids
+
+ res = app.get(f'{url_institution}?filter[sso_availability]=[Unavailable,Hidden]')
+ assert res.status_code == 200
+
+ ids = [each['id'] for each in res.json['data']]
+ assert len(res.json['data']) == 2
+ assert institution_one._id in ids
+ assert institution_three._id in ids
+ assert institution_two._id not in ids
+
+ def test_default_filter_excludes_institutions_with_sso_availability_hidden(
+ self, app, institution_one, institution_two, institution_three, url_institution
+ ):
+ institution_one.sso_availability = 'Unavailable'
+ institution_one.save()
+
+ institution_two.sso_availability = 'Public'
+ institution_two.save()
+
+ institution_three.sso_availability = 'Hidden'
+ institution_three.save()
+
+ res = app.get(url_institution)
+ assert res.status_code == 200
+
+ ids = [each['id'] for each in res.json['data']]
+ assert len(res.json['data']) == 2
+ assert institution_one._id in ids
+ assert institution_two._id in ids
+ assert institution_three._id not in ids
diff --git a/framework/auth/views.py b/framework/auth/views.py
index 2adeb00b3b6..59b2a207af4 100644
--- a/framework/auth/views.py
+++ b/framework/auth/views.py
@@ -1202,6 +1202,10 @@ def validate_next_url(next_url):
:return: True if valid, False otherwise
"""
+ # allow redirection to angular locally
+ if settings.LOCAL_ANGULAR_URL in next_url and settings.DEBUG_MODE:
+ return True
+
# disable external domain using `//`: the browser allows `//` as a shortcut for non-protocol specific requests
# like http:// or https:// depending on the use of SSL on the page already.
if next_url.startswith('//'):
diff --git a/osf/management/commands/backfill_sso_availability.py b/osf/management/commands/backfill_sso_availability.py
new file mode 100644
index 00000000000..d86e9362ff6
--- /dev/null
+++ b/osf/management/commands/backfill_sso_availability.py
@@ -0,0 +1,79 @@
+from django.core.management.base import BaseCommand
+from django.db import transaction
+from django.db.models import Q
+
+from osf.models.institution import Institution, SSOAvailability, IntegrationType
+
+
+class Command(BaseCommand):
+ help = 'Backfill sso_availability using fast DB-level updates'
+
+ def add_arguments(self, parser):
+ parser.add_argument(
+ '--dry-run',
+ action='store_true',
+ help='Show how many rows would be updated without applying changes',
+ )
+
+ def handle(self, *args, **options):
+ dry_run = options['dry_run']
+
+ # Build querysets
+ qs_no_protocol = Institution.objects.filter(
+ delegation_protocol=IntegrationType.NONE.value
+ ).exclude(
+ sso_availability=SSOAvailability.UNAVAILABLE.value
+ )
+
+ qs_inactive_with_protocol = Institution.objects.filter(
+ ~Q(delegation_protocol=IntegrationType.NONE.value),
+ deactivated__isnull=False
+ ).exclude(
+ sso_availability=SSOAvailability.HIDDEN.value
+ )
+
+ qs_active_with_protocol = Institution.objects.filter(
+ ~Q(delegation_protocol=IntegrationType.NONE.value),
+ deactivated__isnull=True
+ ).exclude(
+ sso_availability=SSOAvailability.PUBLIC.value
+ )
+
+ count_no_protocol = qs_no_protocol.count()
+ count_inactive = qs_inactive_with_protocol.count()
+ count_active = qs_active_with_protocol.count()
+
+ total = count_no_protocol + count_inactive + count_active
+
+ self.stdout.write('Planned updates:')
+ self.stdout.write(f" No protocol → UNAVAILABLE: {count_no_protocol}")
+ self.stdout.write(f" Inactive + protocol → HIDDEN: {count_inactive}")
+ self.stdout.write(f" Active + protocol → PUBLIC: {count_active}")
+ self.stdout.write(f" TOTAL: {total}")
+
+ if dry_run:
+ self.stdout.write(self.style.WARNING('Dry run, no changes applied.'))
+ return
+
+ with transaction.atomic():
+ updated_no_protocol = qs_no_protocol.update(
+ sso_availability=SSOAvailability.UNAVAILABLE.value
+ )
+
+ updated_inactive = qs_inactive_with_protocol.update(
+ sso_availability=SSOAvailability.HIDDEN.value
+ )
+
+ updated_active = qs_active_with_protocol.update(
+ sso_availability=SSOAvailability.PUBLIC.value
+ )
+
+ self.stdout.write(
+ self.style.SUCCESS(
+ 'Done:\n'
+ f" UNAVAILABLE: {updated_no_protocol}\n"
+ f" HIDDEN: {updated_inactive}\n"
+ f" PUBLIC: {updated_active}\n"
+ f" TOTAL: {updated_no_protocol + updated_inactive + updated_active}"
+ )
+ )
diff --git a/osf/migrations/0038_institution_sso_availability.py b/osf/migrations/0038_institution_sso_availability.py
new file mode 100644
index 00000000000..c4be5de4001
--- /dev/null
+++ b/osf/migrations/0038_institution_sso_availability.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.2.15 on 2026-03-13 11:11
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('osf', '0037_notification_refactor_post_release'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='institution',
+ name='sso_availability',
+ field=models.CharField(choices=[('Public', 'PUBLIC'), ('Unavailable', 'UNAVAILABLE'), ('Hidden', 'HIDDEN')], default='Hidden', max_length=15),
+ ),
+ ]
diff --git a/osf/models/institution.py b/osf/models/institution.py
index 3671e7bef1f..379f301a966 100644
--- a/osf/models/institution.py
+++ b/osf/models/institution.py
@@ -24,6 +24,7 @@
from .validators import validate_email
from osf.utils.fields import NonNaiveDateTimeField, LowercaseEmailField
from website import settings as website_settings
+from urllib.parse import quote
logger = logging.getLogger(__name__)
@@ -46,6 +47,13 @@ class SsoFilterCriteriaAction(Enum):
CONTAINS = 'contains' # Type 2: SSO releases a multi-value attribute, of which one value matches
IN = 'in' # Type 3: SSO releases a single-value attribute that have multiple valid values
+class SSOAvailability(Enum):
+ """Defines 3 SSO availability states for institutions.
+ """
+ PUBLIC = 'Public' # Active, has a delegation protocol and SSO setup has been verified
+ UNAVAILABLE = 'Unavailable' # Does not have a delegation protocol
+ HIDDEN = 'Hidden' # 1) Inactive and has a delegation protocol, or 2) active, has a delegation protocol and SSO setup is in-progress
+
class InstitutionManager(models.Manager):
@@ -55,6 +63,9 @@ def get_queryset(self):
def get_all_institutions(self):
return super().get_queryset()
+ def get_non_hidden_institutions(self):
+ return super().get_queryset().filter(deactivated__isnull=True, sso_availability__in=[SSOAvailability.PUBLIC.value, SSOAvailability.UNAVAILABLE.value])
+
class Institution(DirtyFieldsMixin, Loggable, ObjectIDMixin, BaseModel, GuardianMixin):
objects = InstitutionManager()
@@ -79,6 +90,13 @@ class Institution(DirtyFieldsMixin, Loggable, ObjectIDMixin, BaseModel, Guardian
default=''
)
+ # Institution SSO availability
+ sso_availability = models.CharField(
+ choices=[(choice.value, choice.name) for choice in SSOAvailability],
+ max_length=15,
+ default=SSOAvailability.HIDDEN.value
+ )
+
# Default Storage Region
storage_regions = models.ManyToManyField(
'addons_osfstorage.Region',
@@ -194,6 +212,17 @@ def banner_path(self):
except InstitutionAssetFile.DoesNotExist:
return '/static/img/institutions/banners/placeholder-banner.png'
+ @property
+ def cas_login_url(self):
+ if self.delegation_protocol == IntegrationType.NONE.value:
+ return None
+ if 'localhost' in website_settings.DOMAIN:
+ next_param = quote(website_settings.PROTOCOL + website_settings.LOCAL_ANGULAR_URL, safe='')
+ else:
+ next_param = quote(website_settings.DOMAIN, safe='')
+ service_url = quote(f'{website_settings.DOMAIN}login?next={next_param}', safe='')
+ return f'{website_settings.CAS_SERVER_URL}/login?campaign=institution&institutionId={self._id}&service={service_url}'
+
def update_search(self):
from website.search.search import update_institution
from website.search.exceptions import SearchUnavailableError
@@ -237,6 +266,11 @@ def deactivate(self):
"""
if not self.deactivated:
self.deactivated = timezone.now()
+ if not self.delegation_protocol:
+ self.sso_availability = SSOAvailability.UNAVAILABLE.value
+ else:
+ self.sso_availability = SSOAvailability.HIDDEN.value
+
self.save()
# Django mangers aren't used when querying on related models. Thus, we can query
# affiliated users and send notification emails after the institution has been deactivated.
@@ -251,6 +285,10 @@ def reactivate(self):
"""
if self.deactivated:
self.deactivated = None
+ if not self.delegation_protocol:
+ self.sso_availability = SSOAvailability.UNAVAILABLE.value
+ else:
+ self.sso_availability = SSOAvailability.HIDDEN.value
self.save()
else:
message = f'Action rejected - reactivating an active institution [{self._id}].'
diff --git a/osf_tests/factories.py b/osf_tests/factories.py
index 0b357aed1aa..0d5e5ad0c32 100644
--- a/osf_tests/factories.py
+++ b/osf_tests/factories.py
@@ -28,6 +28,7 @@
from osf import models
from osf.models.sanctions import Sanction
from osf.models.storage import PROVIDER_ASSET_NAME_CHOICES
+from osf.models.institution import SSOAvailability
from osf.utils.names import impute_names_model
from osf.utils.workflows import (
DefaultStates,
@@ -258,6 +259,7 @@ class InstitutionFactory(DjangoModelFactory):
orcid_record_verified_source = ''
delegation_protocol = ''
institutional_request_access_enabled = False
+ sso_availability = SSOAvailability.PUBLIC.value
class Meta:
model = models.Institution
diff --git a/osf_tests/test_institution.py b/osf_tests/test_institution.py
index 039b0ce04dd..867723cf291 100644
--- a/osf_tests/test_institution.py
+++ b/osf_tests/test_institution.py
@@ -128,6 +128,20 @@ def test_deactivated_institution_in_all_institutions(self):
institution.save()
assert institution in Institution.objects.get_all_institutions()
+ def test_deactivate_sso_institution(self):
+ institution = InstitutionFactory()
+ institution.delegation_protocol = 'saml-shib'
+ institution.save()
+ with mock.patch.object(
+ institution,
+ '_send_deactivation_email',
+ return_value=None
+ ) as mock__send_deactivation_email:
+ institution.deactivate()
+ assert institution.deactivated is not None
+ assert mock__send_deactivation_email.called
+ assert institution.sso_availability == 'Hidden'
+
def test_deactivate_institution(self):
institution = InstitutionFactory()
with mock.patch.object(
@@ -138,6 +152,16 @@ def test_deactivate_institution(self):
institution.deactivate()
assert institution.deactivated is not None
assert mock__send_deactivation_email.called
+ assert institution.sso_availability == 'Unavailable'
+
+ def test_reactivate_sso_institution(self):
+ institution = InstitutionFactory()
+ institution.delegation_protocol = 'saml-shib'
+ institution.deactivated = timezone.now()
+ institution.save()
+ institution.reactivate()
+ assert institution.deactivated is None
+ assert institution.sso_availability == 'Hidden'
def test_reactivate_institution(self):
institution = InstitutionFactory()
@@ -145,6 +169,7 @@ def test_reactivate_institution(self):
institution.save()
institution.reactivate()
assert institution.deactivated is None
+ assert institution.sso_availability == 'Unavailable'
def test_send_deactivation_email_call_count(self):
institution = InstitutionFactory()
diff --git a/scripts/populate_institutions.py b/scripts/populate_institutions.py
index f46f7c67113..64bf59bd2b9 100644
--- a/scripts/populate_institutions.py
+++ b/scripts/populate_institutions.py
@@ -12,13 +12,13 @@
from website import settings
from website.app import init_app
-from osf.models import Institution
+from osf.models.institution import Institution, SSOAvailability, IntegrationType
from website.search.search import update_institution
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
-ENVS = ['prod', 'stage', 'stage2', 'stage3', 'test', 'local']
+ENVS = ['prod', 'stage', 'stage2', 'stage3', 'test', 'local', 'auto_generated']
# TODO: Store only the Entity IDs in OSF DB and move the URL building process to CAS
SHIBBOLETH_SP_LOGIN = f'{settings.CAS_SERVER_URL}/Shibboleth.sso/Login?entityID={{}}'
@@ -37,7 +37,10 @@ def encode_uri_component(val):
def update_or_create(inst_data):
- inst = Institution.load(inst_data['_id'])
+ try:
+ inst = Institution.objects.get_all_institutions().get(_id=inst_data['_id'])
+ except Institution.DoesNotExist:
+ inst = None
if inst:
for key, val in inst_data.items():
setattr(inst, key, val)
@@ -53,6 +56,53 @@ def update_or_create(inst_data):
return inst, True
+PROTOCOL_MAP = {
+ IntegrationType.SAML_SHIBBOLETH.value: 'SAML',
+ IntegrationType.CAS_PAC4J.value: 'CAS',
+ IntegrationType.OAUTH_PAC4J.value: 'OAuth',
+ IntegrationType.AFFILIATION_VIA_ORCID.value: 'ORCiD',
+ IntegrationType.NONE.value: 'None',
+}
+
+
+DEACTIVATED_STATES = [
+ None,
+ '2026-01-01T00:00:00+00:00',
+]
+
+
+def get_valid_sso_states(protocol, deactivated):
+ is_active = deactivated is None
+ if not protocol:
+ return [SSOAvailability.UNAVAILABLE.value]
+ if not is_active:
+ return [SSOAvailability.HIDDEN.value]
+ return [SSOAvailability.PUBLIC.value, SSOAvailability.HIDDEN.value]
+
+
+def generate_test_institutions():
+ institutions = []
+
+ for protocol in PROTOCOL_MAP.keys():
+ for deactivated in DEACTIVATED_STATES:
+ for availability in get_valid_sso_states(protocol, deactivated):
+ _id = f"{PROTOCOL_MAP[protocol]}_{availability}_{'a' if deactivated is None else 'i'}".lower()
+ institutions.append({
+ '_id': _id,
+ 'name': f'Test Institution [{PROTOCOL_MAP[protocol] if protocol else "None"} {availability} {"Inactive" if deactivated else "Active"}]',
+ 'description': f'Description for {PROTOCOL_MAP[protocol] if protocol else "None"} {availability} {"Inactive" if deactivated else "Active"}',
+ 'login_url': SHIBBOLETH_SP_LOGIN.format(encode_uri_component(f'{_id}-entity-id')) if protocol == IntegrationType.SAML_SHIBBOLETH.value else None,
+ 'logout_url': SHIBBOLETH_SP_LOGOUT.format(encode_uri_component(f'{settings.DOMAIN}{_id}')) if protocol == IntegrationType.SAML_SHIBBOLETH.value else None,
+ 'domains': [],
+ 'email_domains': [f'{_id}.osf.io'] if not protocol else [],
+ 'delegation_protocol': protocol,
+ 'sso_availability': availability,
+ 'deactivated': deactivated,
+ })
+
+ return institutions
+
+
def main(default_args=False):
if default_args:
@@ -67,7 +117,12 @@ def main(default_args=False):
if not server_env or server_env not in ENVS:
logger.error(f'A valid environment must be specified: {ENVS}')
sys.exit(1)
- institutions = INSTITUTIONS[server_env]
+
+ if server_env == 'auto_generated':
+ logger.info('Generating institutions with all combinations of protocol, availability, and deactivated states for testing purposes.')
+ institutions = generate_test_institutions()
+ else:
+ institutions = INSTITUTIONS[server_env]
if not update_all and not update_ids:
logger.error('Nothing to update or create. Please either specify a list of institutions '
@@ -101,6 +156,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['a2jlab.org'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'albion',
@@ -113,6 +169,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'asu',
@@ -125,6 +182,7 @@ def main(default_args=False):
'domains': ['osf.asu.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'brown',
@@ -135,6 +193,7 @@ def main(default_args=False):
'domains': ['osf.brown.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'bt',
@@ -145,6 +204,7 @@ def main(default_args=False):
'domains': ['osf.boystownhospital.org'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'bu',
@@ -155,6 +215,7 @@ def main(default_args=False):
'domains': ['osf.bu.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'busara',
@@ -165,6 +226,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['busaracenter.org'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'callutheran',
@@ -175,6 +237,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'capolicylab',
@@ -185,6 +248,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['capolicylab.org'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'cfa',
@@ -195,6 +259,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['cfa.harvard.edu'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'clrn',
@@ -205,6 +270,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['characterlab.org'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'cmu',
@@ -219,6 +285,7 @@ def main(default_args=False):
'domains': ['osf.library.cmu.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'colorado',
@@ -229,6 +296,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'cord',
@@ -239,6 +307,7 @@ def main(default_args=False):
'domains': ['osf.cord.edu'],
'email_domains': [],
'delegation_protocol': 'cas-pac4j',
+ 'sso_availability': 'Public',
},
{
'_id': 'cornell',
@@ -249,6 +318,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'cos',
@@ -259,6 +329,7 @@ def main(default_args=False):
'domains': ['osf.cos.io'],
'email_domains': ['cos.io'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'csic',
@@ -269,6 +340,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'cwru',
@@ -279,6 +351,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'duke',
@@ -289,6 +362,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ecu',
@@ -299,6 +373,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'esip',
@@ -309,6 +384,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['esipfed.org'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'eur',
@@ -324,6 +400,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ferris',
@@ -334,6 +411,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'fsu',
@@ -344,6 +422,7 @@ def main(default_args=False):
'domains': ['osf.fsu.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'gatech',
@@ -354,6 +433,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'gmu',
@@ -364,6 +444,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'gwu',
@@ -374,6 +455,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'harvard',
@@ -384,6 +466,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ibhri',
@@ -394,6 +477,7 @@ def main(default_args=False):
'domains': ['osf.ibhri.org'],
'email_domains': ['ibhri.org'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'icarehb',
@@ -404,6 +488,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['icarehb.com'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'icer',
@@ -414,6 +499,7 @@ def main(default_args=False):
'domains': ['osf.icer-review.org'],
'email_domains': ['icer-review.org'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'igdore',
@@ -427,6 +513,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['igdore.org'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'iit',
@@ -437,6 +524,7 @@ def main(default_args=False):
'domains': ['osf.iit.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'itb',
@@ -447,6 +535,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'jhu',
@@ -457,6 +546,7 @@ def main(default_args=False):
'domains': ['osf.data.jhu.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'jmu',
@@ -467,6 +557,7 @@ def main(default_args=False):
'domains': ['osf.jmu.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'jpal',
@@ -477,6 +568,7 @@ def main(default_args=False):
'domains': ['osf.povertyactionlab.org'],
'email_domains': ['povertyactionlab.org'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'kuleuven',
@@ -487,6 +579,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ljaf',
@@ -497,6 +590,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['arnoldfoundation.org'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'mit',
@@ -507,6 +601,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'mq',
@@ -517,6 +612,7 @@ def main(default_args=False):
'domains': ['osf.mq.edu.au'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'nationalmaglab',
@@ -527,6 +623,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'nesta',
@@ -537,6 +634,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'nd',
@@ -547,6 +645,7 @@ def main(default_args=False):
'domains': ['osf.nd.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'nyu',
@@ -557,6 +656,7 @@ def main(default_args=False):
'domains': ['osf.nyu.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'okstate',
@@ -567,6 +667,7 @@ def main(default_args=False):
'domains': ['osf.library.okstate.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ou',
@@ -577,6 +678,7 @@ def main(default_args=False):
'domains': ['osf.ou.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'oxford',
@@ -587,6 +689,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'via-orcid',
+ 'sso_availability': 'Public',
'orcid_record_verified_source': 'ORCID Integration at the University of Oxford',
},
{
@@ -598,6 +701,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'purdue',
@@ -608,6 +712,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'sc',
@@ -620,6 +725,7 @@ def main(default_args=False):
'domains': ['osf.sc.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'temple',
@@ -630,6 +736,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'thepolicylab',
@@ -640,6 +747,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'thelabatdc',
@@ -650,6 +758,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['dc.gov'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'theworks',
@@ -660,6 +769,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['theworks.info'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'tufts',
@@ -670,6 +780,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ua',
@@ -680,6 +791,7 @@ def main(default_args=False):
'domains': ['osf.arizona.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ubc',
@@ -690,6 +802,7 @@ def main(default_args=False):
'domains': ['osf.openscience.ubc.ca'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'uc',
@@ -700,6 +813,7 @@ def main(default_args=False):
'domains': ['osf.uc.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ucla',
@@ -710,6 +824,7 @@ def main(default_args=False):
'domains': ['osf.ucla.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ucsd',
@@ -720,6 +835,7 @@ def main(default_args=False):
'domains': ['osf.ucsd.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ucr',
@@ -730,6 +846,7 @@ def main(default_args=False):
'domains': ['osf.ucr.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'uct',
@@ -740,6 +857,7 @@ def main(default_args=False):
'domains': ['osf.uct.ac.za'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ugent',
@@ -750,6 +868,7 @@ def main(default_args=False):
'domains': ['osf.ugent.be'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ugoe',
@@ -760,6 +879,7 @@ def main(default_args=False):
'domains': ['osf.uni-goettingen.de'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'umb',
@@ -770,6 +890,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'umd',
@@ -780,6 +901,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'unc',
@@ -790,6 +912,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'universityofkent',
@@ -800,6 +923,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'uol',
@@ -810,6 +934,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'uom',
@@ -820,6 +945,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'usc',
@@ -830,6 +956,7 @@ def main(default_args=False):
'domains': ['osf.usc.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ush',
@@ -840,6 +967,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['uvers.ac.id'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'utdallas',
@@ -850,6 +978,7 @@ def main(default_args=False):
'domains': ['osf.utdallas.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'uva',
@@ -860,6 +989,7 @@ def main(default_args=False):
'domains': ['osf.virginia.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'uw',
@@ -870,6 +1000,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'uwstout',
@@ -880,6 +1011,7 @@ def main(default_args=False):
'domains': ['open.uwstout.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'vcu',
@@ -890,6 +1022,7 @@ def main(default_args=False):
'domains': ['osf.research.vcu.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'vt',
@@ -900,6 +1033,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'vua',
@@ -910,6 +1044,7 @@ def main(default_args=False):
'domains': ['osf.vu.nl'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'wustl',
@@ -920,6 +1055,7 @@ def main(default_args=False):
'domains': ['osf.wustl.edu'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
],
'stage': [
@@ -932,6 +1068,7 @@ def main(default_args=False):
'domains': ['staging-osf.cos.io'],
'email_domains': ['cos.io'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'nd',
@@ -942,6 +1079,7 @@ def main(default_args=False):
'domains': ['staging-osf-nd.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'google',
@@ -952,6 +1090,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['gmail.com'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'yahoo',
@@ -961,6 +1100,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['yahoo.com'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'oxford',
@@ -971,6 +1111,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'via-orcid',
+ 'sso_availability': 'Public',
'orcid_record_verified_source': 'ORCID Integration at the University of Oxford',
},
{
@@ -983,6 +1124,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'via-orcid',
+ 'sso_availability': 'Public',
'orcid_record_verified_source': 'OSF Integration',
},
],
@@ -996,6 +1138,7 @@ def main(default_args=False):
'domains': ['staging2-osf.cos.io'],
'email_domains': ['cos.io'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
],
'stage3': [
@@ -1008,6 +1151,7 @@ def main(default_args=False):
'domains': ['staging3-osf.cos.io'],
'email_domains': ['cos.io'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
],
'test': [
@@ -1020,6 +1164,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'a2jlab',
@@ -1030,6 +1175,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['a2jlab.org'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'albion',
@@ -1042,6 +1188,7 @@ def main(default_args=False):
'domains': ['test-osf-ablbion.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'asu',
@@ -1054,6 +1201,7 @@ def main(default_args=False):
'domains': ['test-osf-asu.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'brown',
@@ -1064,6 +1212,7 @@ def main(default_args=False):
'domains': ['test-osf-brown.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'bt',
@@ -1074,6 +1223,7 @@ def main(default_args=False):
'domains': ['test-osf-bt.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'bu',
@@ -1084,6 +1234,7 @@ def main(default_args=False):
'domains': ['test-osf-bu.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'busara',
@@ -1094,6 +1245,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['busaracenter.org'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'callutheran',
@@ -1104,6 +1256,7 @@ def main(default_args=False):
'domains': ['test-osf-callutheran.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'callutheran2',
@@ -1114,6 +1267,7 @@ def main(default_args=False):
'domains': ['test-osf-callutheran2.cos.io'],
'email_domains': [],
'delegation_protocol': 'cas-pac4j',
+ 'sso_availability': 'Public',
},
{
'_id': 'capolicylab',
@@ -1124,6 +1278,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['capolicylab.org'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'cfa',
@@ -1134,6 +1289,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['cfa.harvard.edu'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'clrn',
@@ -1144,6 +1300,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['characterlab.org'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'cmu',
@@ -1158,6 +1315,7 @@ def main(default_args=False):
'domains': ['test-osf-cmu.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'colorado',
@@ -1168,6 +1326,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'cornell',
@@ -1178,6 +1337,7 @@ def main(default_args=False):
'domains': ['test-osf-cornell.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'cord',
@@ -1188,6 +1348,7 @@ def main(default_args=False):
'domains': ['test-osf-cord.cos.io'],
'email_domains': [],
'delegation_protocol': 'cas-pac4j',
+ 'sso_availability': 'Public',
},
{
'_id': 'cos',
@@ -1198,6 +1359,7 @@ def main(default_args=False):
'domains': ['test-osf.cos.io'],
'email_domains': ['cos.io'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'csic',
@@ -1208,6 +1370,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'cwru',
@@ -1218,6 +1381,7 @@ def main(default_args=False):
'domains': ['test-osf-cwru.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'duke',
@@ -1228,6 +1392,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ecu',
@@ -1238,6 +1403,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'esip',
@@ -1248,6 +1414,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['esipfed.org'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'eur',
@@ -1263,6 +1430,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ferris',
@@ -1273,6 +1441,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'fsu',
@@ -1283,6 +1452,7 @@ def main(default_args=False):
'domains': ['test-osf-fsu.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'gatech',
@@ -1293,6 +1463,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'gmu',
@@ -1303,6 +1474,7 @@ def main(default_args=False):
'domains': ['test-osf-gmu.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'gwu',
@@ -1313,6 +1485,7 @@ def main(default_args=False):
'domains': ['test-osf-gwu.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'harvard',
@@ -1323,6 +1496,7 @@ def main(default_args=False):
'domains': ['test-osf-harvard.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ibhri',
@@ -1333,6 +1507,7 @@ def main(default_args=False):
'domains': ['test-osf-ibhri.cos.io'],
'email_domains': ['ibhri.org'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'icarehb',
@@ -1343,6 +1518,7 @@ def main(default_args=False):
'domains': ['test-osf-icarehb.cos.io'],
'email_domains': ['icarehb.com'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'icer',
@@ -1353,6 +1529,7 @@ def main(default_args=False):
'domains': ['test-osf-icer.cos.io'],
'email_domains': ['icer-review.org'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'igdore',
@@ -1366,6 +1543,7 @@ def main(default_args=False):
'domains': ['test-osf-icer.igdore.io'],
'email_domains': ['igdore.org'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'iit',
@@ -1376,6 +1554,7 @@ def main(default_args=False):
'domains': ['test-osf-iit.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'itb',
@@ -1386,6 +1565,7 @@ def main(default_args=False):
'domains': ['test-osf-itb.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'jhu',
@@ -1396,6 +1576,7 @@ def main(default_args=False):
'domains': ['test-osf-jhu.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'jmu',
@@ -1406,6 +1587,7 @@ def main(default_args=False):
'domains': ['test-osf-jmu.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'jpal',
@@ -1416,6 +1598,7 @@ def main(default_args=False):
'domains': ['test-osf-jpal.cos.io'],
'email_domains': ['povertyactionlab.org'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'kuleuven',
@@ -1426,6 +1609,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ljaf',
@@ -1436,6 +1620,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['arnoldfoundation.org'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'mit',
@@ -1446,6 +1631,7 @@ def main(default_args=False):
'domains': ['test-osf-mit.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'mq',
@@ -1456,6 +1642,7 @@ def main(default_args=False):
'domains': ['test-osf-mq.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'nationalmaglab',
@@ -1466,6 +1653,7 @@ def main(default_args=False):
'domains': ['test-osf-nationalmaglab.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'nesta',
@@ -1476,6 +1664,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'nd',
@@ -1486,6 +1675,7 @@ def main(default_args=False):
'domains': ['test-osf-nd.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'nyu',
@@ -1496,6 +1686,7 @@ def main(default_args=False):
'domains': ['test-osf-nyu.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'okstate',
@@ -1506,6 +1697,7 @@ def main(default_args=False):
'domains': ['test-osf-library-okstate.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ou',
@@ -1516,6 +1708,7 @@ def main(default_args=False):
'domains': ['test-osf-ou.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'oxford',
@@ -1526,6 +1719,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'via-orcid',
+ 'sso_availability': 'Public',
'orcid_record_verified_source': 'ORCID Integration at the University of Oxford',
},
{
@@ -1537,6 +1731,7 @@ def main(default_args=False):
'domains': ['test-osf-pu.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'purdue',
@@ -1547,6 +1742,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'sc',
@@ -1559,6 +1755,7 @@ def main(default_args=False):
'domains': ['test-osf-sc.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'temple',
@@ -1569,6 +1766,7 @@ def main(default_args=False):
'domains': ['test-osf-temple.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'thepolicylab',
@@ -1579,6 +1777,7 @@ def main(default_args=False):
'domains': ['test-osf-thepolicylab.cos.io'],
'email_domains': ['policylab.io'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'thelabatdc',
@@ -1589,6 +1788,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['dc.gov'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'theworks',
@@ -1599,6 +1799,7 @@ def main(default_args=False):
'domains': [],
'email_domains': ['theworks.info'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'tufts',
@@ -1609,6 +1810,7 @@ def main(default_args=False):
'domains': ['test-osf-tufts.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ua',
@@ -1619,6 +1821,7 @@ def main(default_args=False):
'domains': ['test-osf-ua.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ubc',
@@ -1629,6 +1832,7 @@ def main(default_args=False):
'domains': ['test-osf-ubc.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'uc',
@@ -1639,6 +1843,7 @@ def main(default_args=False):
'domains': ['test-osf-uc.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ucla',
@@ -1649,6 +1854,7 @@ def main(default_args=False):
'domains': ['test-osf-ucla.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ucsd',
@@ -1659,6 +1865,7 @@ def main(default_args=False):
'domains': ['test-osf-ucsd.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ucr',
@@ -1669,6 +1876,7 @@ def main(default_args=False):
'domains': ['test-osf-ucr.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'uct',
@@ -1679,6 +1887,7 @@ def main(default_args=False):
'domains': ['test-osf-uct.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'umb',
@@ -1689,6 +1898,7 @@ def main(default_args=False):
'domains': ['test-osf-umb.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'umd',
@@ -1699,6 +1909,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ugent',
@@ -1709,6 +1920,7 @@ def main(default_args=False):
'domains': ['test-osf-ugent.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ugoe',
@@ -1719,6 +1931,7 @@ def main(default_args=False):
'domains': ['test-osf-ugoe.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'uit',
@@ -1731,6 +1944,7 @@ def main(default_args=False):
'domains': ['test-osf-uit.cos.io'],
'email_domains': ['uit.no'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'unc',
@@ -1741,6 +1955,7 @@ def main(default_args=False):
'domains': ['test-osf-unc.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'universityofkent',
@@ -1751,6 +1966,7 @@ def main(default_args=False):
'domains': ['test-osf-universityofkent.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'uol',
@@ -1761,6 +1977,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'uom',
@@ -1771,6 +1988,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'usc',
@@ -1781,6 +1999,7 @@ def main(default_args=False):
'domains': ['test-osf-usc.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'ush',
@@ -1791,6 +2010,7 @@ def main(default_args=False):
'domains': ['test-osf-ush.cos.io'],
'email_domains': ['uvers.ac.id'],
'delegation_protocol': '',
+ 'sso_availability': 'Unavailable',
},
{
'_id': 'utdallas',
@@ -1801,6 +2021,7 @@ def main(default_args=False):
'domains': ['test-osf-utdallas.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'uva',
@@ -1811,6 +2032,7 @@ def main(default_args=False):
'domains': ['test-osf-virginia.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'uw',
@@ -1821,6 +2043,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'uwstout',
@@ -1831,6 +2054,7 @@ def main(default_args=False):
'domains': ['test-osf-uwstout.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'vcu',
@@ -1841,6 +2065,7 @@ def main(default_args=False):
'domains': ['test-osf-research-vcu.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'vt',
@@ -1851,6 +2076,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'vua',
@@ -1861,6 +2087,7 @@ def main(default_args=False):
'domains': ['test-osf-vua.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'wustl',
@@ -1871,6 +2098,7 @@ def main(default_args=False):
'domains': ['test-osf-wustl.cos.io'],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
],
'local': [
@@ -1884,6 +2112,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'cas-pac4j',
+ 'sso_availability': 'Public',
},
{
'_id': 'osftype1',
@@ -1895,6 +2124,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'via-orcid',
+ 'sso_availability': 'Public',
'orcid_record_verified_source': 'OSF Integration',
},
{
@@ -1907,6 +2137,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
'orcid_record_verified_source': '',
},
{
@@ -1920,6 +2151,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'osftype4',
@@ -1932,6 +2164,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'osftype5',
@@ -1944,6 +2177,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
'orcid_record_verified_source': '',
},
{
@@ -1957,6 +2191,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'osftype7',
@@ -1969,6 +2204,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'osftype8',
@@ -1981,6 +2217,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
{
'_id': 'osftype9',
@@ -1993,6 +2230,7 @@ def main(default_args=False):
'domains': [],
'email_domains': [],
'delegation_protocol': 'saml-shib',
+ 'sso_availability': 'Public',
},
],
}
diff --git a/tests/test_auth_views.py b/tests/test_auth_views.py
index 7b24e286c15..75ef5de497a 100644
--- a/tests/test_auth_views.py
+++ b/tests/test_auth_views.py
@@ -584,6 +584,17 @@ def test_next_url_login_with_auth(self):
assert data.get('status_code') == http_status.HTTP_302_FOUND
assert data.get('next_url') == self.next_url
+ def test_next_url_angular_login_with_auth(self):
+ data = login_and_register_handler(self.auth, next_url=settings.LOCAL_ANGULAR_URL)
+ assert data.get('status_code') == http_status.HTTP_302_FOUND
+ assert data.get('next_url') == settings.LOCAL_ANGULAR_URL
+
+ def test_next_url_angular_login_without_auth(self):
+ request.url = web_url_for('auth_login', next=settings.LOCAL_ANGULAR_URL, _absolute=True)
+ data = login_and_register_handler(self.no_auth, next_url=settings.LOCAL_ANGULAR_URL)
+ assert data.get('status_code') == http_status.HTTP_302_FOUND
+ assert data.get('next_url') == cas.get_login_url(request.url)
+
def test_next_url_login_without_auth(self):
# login: user without auth
request.url = web_url_for('auth_login', next=self.next_url, _absolute=True)
@@ -827,6 +838,22 @@ def test_logout_with_no_parameter(self):
assert resp.status_code == http_status.HTTP_302_FOUND
assert cas.get_logout_url(self.goodbye_url) == resp.headers['Location']
+ @mock.patch('framework.auth.views.settings.LOCAL_ANGULAR_URL', 'http://localhost:4200')
+ def test_logout_with_angular_next_url_logged_in(self):
+ angular_url = 'http://localhost:4200/'
+ logout_url = web_url_for('auth_logout', _absolute=True, next=angular_url)
+ resp = self.app.get(logout_url, auth=self.auth_user.auth)
+ assert resp.status_code == http_status.HTTP_302_FOUND
+ assert cas.get_logout_url(logout_url) == resp.headers['Location']
+
+ @mock.patch('framework.auth.views.settings.LOCAL_ANGULAR_URL', 'http://localhost:4200')
+ def test_logout_with_angular_next_url_logged_out(self):
+ angular_url = 'http://localhost:4200/'
+ logout_url = web_url_for('auth_logout', _absolute=True, next=angular_url)
+ resp = self.app.get(logout_url, auth=None)
+ assert resp.status_code == http_status.HTTP_302_FOUND
+ assert angular_url == resp.headers['Location']
+
class TestResetPassword(OsfTestCase):
diff --git a/website/settings/defaults.py b/website/settings/defaults.py
index fbe9b939ae1..75edc0bd5a6 100644
--- a/website/settings/defaults.py
+++ b/website/settings/defaults.py
@@ -90,6 +90,7 @@ def parent_dir(path):
INTERNAL_DOMAIN = DOMAIN
API_DOMAIN = PROTOCOL + 'localhost:8000/'
RESET_PASSWORD_URL = PROTOCOL + 'localhost:5000/resetpassword/' # TODO set angular reset password url
+LOCAL_ANGULAR_URL = 'localhost:4200'
PREPRINT_PROVIDER_DOMAINS = {
'enabled': False,