diff --git a/admin/institutions/views.py b/admin/institutions/views.py index 46e6a0a7745..7ab8994e41f 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 diff --git a/admin/templates/institutions/detail.html b/admin/templates/institutions/detail.html index 2ce1ad20a03..c28ca7e7703 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 %} @@ -33,6 +59,18 @@ {% if perms.osf.change_institution %} Manage Admins {% endif %} + {% if cas_login_url %} + + + {% endif %} @@ -168,5 +206,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_tests/institutions/test_views.py b/admin_tests/institutions/test_views.py index 13cb1456ab9..c3c8a3c3fab 100644 --- a/admin_tests/institutions/test_views.py +++ b/admin_tests/institutions/test_views.py @@ -139,7 +139,8 @@ 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': 'Public', } form = InstitutionForm(data=new_data) assert form.is_valid() @@ -214,7 +215,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': 'Public', } form = InstitutionForm(data=data) assert form.is_valid() diff --git a/api/institutions/serializers.py b/api/institutions/serializers.py index 5beffe60348..3f60cfc65ac 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..b63b5efaa8d 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 diff --git a/api_tests/institutions/views/test_institution_list.py b/api_tests/institutions/views/test_institution_list.py index 74cb0b6bc8f..d203b2b9313 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,32 @@ 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 diff --git a/framework/auth/views.py b/framework/auth/views.py index aefb1b4f0e8..fe0c0ad201a 100644 --- a/framework/auth/views.py +++ b/framework/auth/views.py @@ -1203,6 +1203,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..4ebb8752217 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): @@ -79,6 +87,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 +209,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 +263,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 +282,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/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..3d0b832099a 100644 --- a/scripts/populate_institutions.py +++ b/scripts/populate_institutions.py @@ -101,6 +101,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['a2jlab.org'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'albion', @@ -113,6 +114,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'asu', @@ -125,6 +127,7 @@ def main(default_args=False): 'domains': ['osf.asu.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'brown', @@ -135,6 +138,7 @@ def main(default_args=False): 'domains': ['osf.brown.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'bt', @@ -145,6 +149,7 @@ def main(default_args=False): 'domains': ['osf.boystownhospital.org'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'bu', @@ -155,6 +160,7 @@ def main(default_args=False): 'domains': ['osf.bu.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'busara', @@ -165,6 +171,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['busaracenter.org'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'callutheran', @@ -175,6 +182,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'capolicylab', @@ -185,6 +193,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['capolicylab.org'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'cfa', @@ -195,6 +204,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['cfa.harvard.edu'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'clrn', @@ -205,6 +215,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['characterlab.org'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'cmu', @@ -219,6 +230,7 @@ def main(default_args=False): 'domains': ['osf.library.cmu.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'colorado', @@ -229,6 +241,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'cord', @@ -239,6 +252,7 @@ def main(default_args=False): 'domains': ['osf.cord.edu'], 'email_domains': [], 'delegation_protocol': 'cas-pac4j', + 'sso_availability': 'Public', }, { '_id': 'cornell', @@ -249,6 +263,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'cos', @@ -259,6 +274,7 @@ def main(default_args=False): 'domains': ['osf.cos.io'], 'email_domains': ['cos.io'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'csic', @@ -269,6 +285,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'cwru', @@ -279,6 +296,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'duke', @@ -289,6 +307,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'ecu', @@ -299,6 +318,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'esip', @@ -309,6 +329,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['esipfed.org'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'eur', @@ -324,6 +345,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'ferris', @@ -334,6 +356,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'fsu', @@ -344,6 +367,7 @@ def main(default_args=False): 'domains': ['osf.fsu.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'gatech', @@ -354,6 +378,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'gmu', @@ -364,6 +389,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'gwu', @@ -374,6 +400,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'harvard', @@ -384,6 +411,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'ibhri', @@ -394,6 +422,7 @@ def main(default_args=False): 'domains': ['osf.ibhri.org'], 'email_domains': ['ibhri.org'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'icarehb', @@ -404,6 +433,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['icarehb.com'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'icer', @@ -414,6 +444,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 +458,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['igdore.org'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'iit', @@ -437,6 +469,7 @@ def main(default_args=False): 'domains': ['osf.iit.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'itb', @@ -447,6 +480,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'jhu', @@ -457,6 +491,7 @@ def main(default_args=False): 'domains': ['osf.data.jhu.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'jmu', @@ -467,6 +502,7 @@ def main(default_args=False): 'domains': ['osf.jmu.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'jpal', @@ -477,6 +513,7 @@ def main(default_args=False): 'domains': ['osf.povertyactionlab.org'], 'email_domains': ['povertyactionlab.org'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'kuleuven', @@ -487,6 +524,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'ljaf', @@ -497,6 +535,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['arnoldfoundation.org'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'mit', @@ -507,6 +546,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'mq', @@ -517,6 +557,7 @@ def main(default_args=False): 'domains': ['osf.mq.edu.au'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'nationalmaglab', @@ -527,6 +568,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'nesta', @@ -537,6 +579,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'nd', @@ -547,6 +590,7 @@ def main(default_args=False): 'domains': ['osf.nd.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'nyu', @@ -557,6 +601,7 @@ def main(default_args=False): 'domains': ['osf.nyu.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'okstate', @@ -567,6 +612,7 @@ def main(default_args=False): 'domains': ['osf.library.okstate.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'ou', @@ -577,6 +623,7 @@ def main(default_args=False): 'domains': ['osf.ou.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'oxford', @@ -587,6 +634,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 +646,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'purdue', @@ -608,6 +657,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'sc', @@ -620,6 +670,7 @@ def main(default_args=False): 'domains': ['osf.sc.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'temple', @@ -630,6 +681,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'thepolicylab', @@ -640,6 +692,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'thelabatdc', @@ -650,6 +703,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['dc.gov'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'theworks', @@ -660,6 +714,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['theworks.info'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'tufts', @@ -670,6 +725,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'ua', @@ -680,6 +736,7 @@ def main(default_args=False): 'domains': ['osf.arizona.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'ubc', @@ -690,6 +747,7 @@ def main(default_args=False): 'domains': ['osf.openscience.ubc.ca'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'uc', @@ -700,6 +758,7 @@ def main(default_args=False): 'domains': ['osf.uc.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'ucla', @@ -710,6 +769,7 @@ def main(default_args=False): 'domains': ['osf.ucla.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'ucsd', @@ -720,6 +780,7 @@ def main(default_args=False): 'domains': ['osf.ucsd.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'ucr', @@ -730,6 +791,7 @@ def main(default_args=False): 'domains': ['osf.ucr.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'uct', @@ -740,6 +802,7 @@ def main(default_args=False): 'domains': ['osf.uct.ac.za'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'ugent', @@ -750,6 +813,7 @@ def main(default_args=False): 'domains': ['osf.ugent.be'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'ugoe', @@ -760,6 +824,7 @@ def main(default_args=False): 'domains': ['osf.uni-goettingen.de'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'umb', @@ -770,6 +835,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'umd', @@ -780,6 +846,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'unc', @@ -790,6 +857,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'universityofkent', @@ -800,6 +868,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'uol', @@ -810,6 +879,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'uom', @@ -820,6 +890,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'usc', @@ -830,6 +901,7 @@ def main(default_args=False): 'domains': ['osf.usc.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'ush', @@ -840,6 +912,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['uvers.ac.id'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'utdallas', @@ -850,6 +923,7 @@ def main(default_args=False): 'domains': ['osf.utdallas.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'uva', @@ -860,6 +934,7 @@ def main(default_args=False): 'domains': ['osf.virginia.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'uw', @@ -870,6 +945,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'uwstout', @@ -880,6 +956,7 @@ def main(default_args=False): 'domains': ['open.uwstout.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'vcu', @@ -890,6 +967,7 @@ def main(default_args=False): 'domains': ['osf.research.vcu.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'vt', @@ -900,6 +978,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'vua', @@ -910,6 +989,7 @@ def main(default_args=False): 'domains': ['osf.vu.nl'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'wustl', @@ -920,6 +1000,7 @@ def main(default_args=False): 'domains': ['osf.wustl.edu'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, ], 'stage': [ @@ -932,6 +1013,7 @@ def main(default_args=False): 'domains': ['staging-osf.cos.io'], 'email_domains': ['cos.io'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'nd', @@ -942,6 +1024,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 +1035,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['gmail.com'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'yahoo', @@ -961,6 +1045,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['yahoo.com'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'oxford', @@ -971,6 +1056,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 +1069,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'via-orcid', + 'sso_availability': 'Public', 'orcid_record_verified_source': 'OSF Integration', }, ], @@ -996,6 +1083,7 @@ def main(default_args=False): 'domains': ['staging2-osf.cos.io'], 'email_domains': ['cos.io'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, ], 'stage3': [ @@ -1008,6 +1096,7 @@ def main(default_args=False): 'domains': ['staging3-osf.cos.io'], 'email_domains': ['cos.io'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, ], 'test': [ @@ -1020,6 +1109,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'a2jlab', @@ -1030,6 +1120,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['a2jlab.org'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'albion', @@ -1042,6 +1133,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 +1146,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 +1157,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 +1168,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 +1179,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 +1190,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['busaracenter.org'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'callutheran', @@ -1104,6 +1201,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 +1212,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 +1223,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['capolicylab.org'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'cfa', @@ -1134,6 +1234,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['cfa.harvard.edu'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'clrn', @@ -1144,6 +1245,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['characterlab.org'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'cmu', @@ -1158,6 +1260,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 +1271,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'cornell', @@ -1178,6 +1282,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 +1293,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 +1304,7 @@ def main(default_args=False): 'domains': ['test-osf.cos.io'], 'email_domains': ['cos.io'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'csic', @@ -1208,6 +1315,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'cwru', @@ -1218,6 +1326,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 +1337,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'ecu', @@ -1238,6 +1348,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'esip', @@ -1248,6 +1359,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['esipfed.org'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'eur', @@ -1263,6 +1375,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'ferris', @@ -1273,6 +1386,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'fsu', @@ -1283,6 +1397,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 +1408,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'gmu', @@ -1303,6 +1419,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 +1430,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 +1441,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 +1452,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 +1463,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 +1474,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 +1488,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 +1499,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 +1510,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 +1521,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 +1532,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 +1543,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 +1554,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'ljaf', @@ -1436,6 +1565,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['arnoldfoundation.org'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'mit', @@ -1446,6 +1576,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 +1587,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 +1598,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 +1609,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'nd', @@ -1486,6 +1620,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 +1631,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 +1642,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 +1653,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 +1664,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 +1676,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 +1687,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'sc', @@ -1559,6 +1700,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 +1711,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 +1722,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 +1733,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['dc.gov'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'theworks', @@ -1599,6 +1744,7 @@ def main(default_args=False): 'domains': [], 'email_domains': ['theworks.info'], 'delegation_protocol': '', + 'sso_availability': 'Unavailable', }, { '_id': 'tufts', @@ -1609,6 +1755,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 +1766,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 +1777,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 +1788,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 +1799,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 +1810,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 +1821,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 +1832,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 +1843,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 +1854,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'ugent', @@ -1709,6 +1865,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 +1876,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 +1889,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 +1900,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 +1911,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 +1922,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'uom', @@ -1771,6 +1933,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'usc', @@ -1781,6 +1944,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 +1955,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 +1966,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 +1977,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 +1988,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'uwstout', @@ -1831,6 +1999,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 +2010,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 +2021,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'vua', @@ -1861,6 +2032,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 +2043,7 @@ def main(default_args=False): 'domains': ['test-osf-wustl.cos.io'], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, ], 'local': [ @@ -1884,6 +2057,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'cas-pac4j', + 'sso_availability': 'Public', }, { '_id': 'osftype1', @@ -1895,6 +2069,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'via-orcid', + 'sso_availability': 'Public', 'orcid_record_verified_source': 'OSF Integration', }, { @@ -1907,6 +2082,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', 'orcid_record_verified_source': '', }, { @@ -1920,6 +2096,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'osftype4', @@ -1932,6 +2109,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'osftype5', @@ -1944,6 +2122,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', 'orcid_record_verified_source': '', }, { @@ -1957,6 +2136,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'osftype7', @@ -1969,6 +2149,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'osftype8', @@ -1981,6 +2162,7 @@ def main(default_args=False): 'domains': [], 'email_domains': [], 'delegation_protocol': 'saml-shib', + 'sso_availability': 'Public', }, { '_id': 'osftype9', @@ -1993,6 +2175,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 608edc06519..f02bb48136f 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 2d3dcecba3b..914f549529d 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,