Пример #1
0
 def _build(cls, target_class, *args, **kwargs):
     inst = ProjectFactory._build(target_class)
     for inst_attr, node_attr in Institution.attribute_map.items():
         default = cls.default_institution_attributes.get(inst_attr)
         if callable(default):
             default = default()
         setattr(inst, node_attr, kwargs.pop(inst_attr, default))
     for key, val in kwargs.items():
         setattr(inst, key, val)
     return Institution(inst)
Пример #2
0
def load_origins_whitelist():
    global ORIGINS_WHITELIST
    from osf.models import Institution, PreprintProvider

    institution_origins = tuple(domain.lower() for domain in itertools.chain(
        *[institution.domains for institution in Institution.find()]))

    preprintprovider_origins = tuple(
        preprintprovider.domain.lower()
        for preprintprovider in PreprintProvider.objects.exclude(domain=''))

    ORIGINS_WHITELIST = institution_origins + preprintprovider_origins
Пример #3
0
def load_origins_whitelist():
    global ORIGINS_WHITELIST
    from osf.models import Institution, PreprintProvider

    institution_origins = tuple(domain.lower() for domain in itertools.chain(*[
        institution.domains
        for institution in Institution.find()
    ]))

    preprintprovider_origins = tuple(preprintprovider.domain.lower() for preprintprovider in PreprintProvider.objects.exclude(domain=''))

    ORIGINS_WHITELIST = institution_origins + preprintprovider_origins
Пример #4
0
    def get_institutions_to_add_remove(self, institutions, new_institutions):
        diff = relationship_diff(
            current_items={inst._id: inst for inst in institutions.all()},
            new_items={inst['_id']: inst for inst in new_institutions}
        )

        insts_to_add = []
        for inst_id in diff['add']:
            inst = Institution.load(inst_id)
            if not inst:
                raise exceptions.NotFound(detail='Institution with id "{}" was not found'.format(inst_id))
            insts_to_add.append(inst)

        return insts_to_add, diff['remove'].values()
Пример #5
0
def load_origins_whitelist():
    global ORIGINS_WHITELIST
    from osf.models import Institution, PreprintProvider

    institution_origins = tuple(domain.lower() for domain in itertools.chain(
        *[institution.domains for institution in Institution.find()]))

    preprintprovider_origins = tuple(
        preprintprovider.domain.lower()
        for preprintprovider in PreprintProvider.objects.exclude(domain=''))

    ORIGINS_WHITELIST = tuple(
        urlparse(url).geturl().lower().split('{}://'.format(
            urlparse(url).scheme))[-1]
        for url in institution_origins + preprintprovider_origins)
Пример #6
0
    def get_institutions_to_add_remove(self, institutions, new_institutions):
        diff = relationship_diff(
            current_items={inst._id: inst
                           for inst in institutions.all()},
            new_items={inst['_id']: inst
                       for inst in new_institutions})

        insts_to_add = []
        for inst_id in diff['add']:
            inst = Institution.load(inst_id)
            if not inst:
                raise exceptions.NotFound(
                    detail='Institution with id "{}" was not found'.format(
                        inst_id))
            insts_to_add.append(inst)

        return insts_to_add, diff['remove'].values()
Пример #7
0
def migrate_institutions(index):
    for inst in Institution.find(Q('is_deleted', 'ne', True)):
        update_institution(inst, index)
Пример #8
0
 def get_queryset(self):
     return Institution.find(self.get_query_from_request())
Пример #9
0
 def get_institutions(self):
     institutions = Institution.find(Q('_id', 'ne', None))
     return institutions
Пример #10
0
 def get_institutions(self):
     institutions = Institution.find(Q('_id', 'ne', None))
     return institutions
Пример #11
0
def test_querying_on_domains():
    inst = InstitutionFactory(domains=['foo.test'])
    result = Institution.find(Q('domains', 'eq', 'foo.test'))
    assert inst in result
Пример #12
0
    def authenticate(self, request):
        """
        Handle CAS institution authentication request.

        The JWT `data` payload is expected in the following structure:
        {
            "provider": {
                "idp":  "",
                "id":   "",
                "user": {
                    "username":     "",
                    "fullname":     "",
                    "familyName":   "",
                    "givenName":    "",
                    "middleNames":  "",
                    "suffix":       "",
                }
            }
        }

        :param request: the POST request
        :return: user, None if authentication succeed
        :raises: AuthenticationFailed if authentication fails
        """

        # Verify / decrypt / decode the payload
        try:
            payload = jwt.decode(
                jwe.decrypt(request.body, settings.JWE_SECRET),
                settings.JWT_SECRET,
                options={'verify_exp': False},
                algorithm='HS256',
            )
        except (jwt.InvalidTokenError, TypeError, jwe.exceptions.MalformedData):
            raise AuthenticationFailed

        # Load institution and user data
        data = json.loads(payload['data'])
        provider = data['provider']
        institution = Institution.load(provider['id'])
        if not institution:
            raise AuthenticationFailed('Invalid institution id: "{}"'.format(provider['id']))
        username = provider['user'].get('username')
        fullname = provider['user'].get('fullname')
        given_name = provider['user'].get('givenName')
        family_name = provider['user'].get('familyName')
        middle_names = provider['user'].get('middleNames')
        suffix = provider['user'].get('suffix')
        department = provider['user'].get('department')

        # Use given name and family name to build full name if it is not provided
        if given_name and family_name and not fullname:
            fullname = given_name + ' ' + family_name

        # Non-empty full name is required. Fail the auth and inform sentry if not provided.
        if not fullname:
            message = 'Institution login failed: fullname required for ' \
                      'user "{}" from institution "{}"'.format(username, provider['id'])
            sentry.log_message(message)
            raise AuthenticationFailed(message)

        # Get an existing user or create a new one. If a new user is created, the user object is
        # confirmed but not registered,which is temporarily of an inactive status. If an existing
        # user is found, it is also possible that the user is inactive (e.g. unclaimed, disabled,
        # unconfirmed, etc.).
        user, created = get_or_create_user(fullname, username, reset_password=False)

        # Existing but inactive users need to be either "activated" or failed the auth
        activation_required = False
        new_password_required = False
        if not created:
            try:
                drf.check_user(user)
                logger.info('Institution SSO: active user "{}"'.format(username))
            except exceptions.UnclaimedAccountError:
                # Unclaimed user (i.e. a user that has been added as an unregistered contributor)
                user.unclaimed_records = {}
                activation_required = True
                # Unclaimed users have an unusable password when being added as an unregistered
                # contributor. Thus a random usable password must be assigned during activation.
                new_password_required = True
                logger.info('Institution SSO: unclaimed contributor "{}"'.format(username))
            except exceptions.UnconfirmedAccountError:
                if user.has_usable_password():
                    # Unconfirmed user from default username / password signup
                    user.email_verifications = {}
                    activation_required = True
                    # Unconfirmed users already have a usable password set by the creator during
                    # sign-up. However, it must be overwritten by a new random one so the creator
                    # (if he is not the real person) can not access the account after activation.
                    new_password_required = True
                    logger.info('Institution SSO: unconfirmed user "{}"'.format(username))
                else:
                    # Login take-over has not been implemented for unconfirmed user created via
                    # external IdP login (ORCiD).
                    message = 'Institution SSO is not eligible for an unconfirmed account ' \
                              'created via external IdP login: username = "******"'.format(username)
                    sentry.log_message(message)
                    logger.error(message)
                    return None, None
            except exceptions.DeactivatedAccountError:
                # Deactivated user: login is not allowed for deactivated users
                message = 'Institution SSO is not eligible for a deactivated account: ' \
                          'username = "******"'.format(username)
                sentry.log_message(message)
                logger.error(message)
                return None, None
            except exceptions.MergedAccountError:
                # Merged user: this shouldn't happen since merged users do not have an email
                message = 'Institution SSO is not eligible for a merged account: ' \
                          'username = "******"'.format(username)
                sentry.log_message(message)
                logger.error(message)
                return None, None
            except exceptions.InvalidAccountError:
                # Other invalid status: this shouldn't happen unless the user happens to be in a
                # temporary state. Such state requires more updates before the user can be saved
                # to the database. (e.g. `get_or_create_user()` creates a temporary-state user.)
                message = 'Institution SSO is not eligible for an inactive account with ' \
                          'an unknown or invalid status: username = "******"'.format(username)
                sentry.log_message(message)
                logger.error(message)
                return None, None
        else:
            logger.info('Institution SSO: new user "{}"'.format(username))

        # The `department` field is updated each login when it was changed.
        if department and user.department != department:
            user.department = department
            user.save()

        # Both created and activated accounts need to be updated and registered
        if created or activation_required:

            if given_name:
                user.given_name = given_name
            if family_name:
                user.family_name = family_name
            if middle_names:
                user.middle_names = middle_names
            if suffix:
                user.suffix = suffix

            # Users claimed or confirmed via institution SSO should have their full name updated
            if activation_required:
                user.fullname = fullname

            user.update_date_last_login()

            # Relying on front-end validation until `accepted_tos` is added to the JWT payload
            user.accepted_terms_of_service = timezone.now()

            # Register and save user
            password = str(uuid.uuid4()) if new_password_required else None
            user.register(username, password=password)
            user.save()

            # Send confirmation email for all three: created, confirmed and claimed
            send_mail(
                to_addr=user.username,
                mail=WELCOME_OSF4I,
                mimetype='html',
                user=user,
                domain=DOMAIN,
                osf_support_email=OSF_SUPPORT_EMAIL,
                storage_flag_is_active=waffle.flag_is_active(request, features.STORAGE_I18N),
            )

        # Affiliate the user if not previously affiliated
        if not user.is_affiliated_with_institution(institution):
            user.affiliated_institutions.add(institution)
            user.save()

        return user, None
Пример #13
0
def migrate_institutions(index):
    for inst in Institution.find(Q('is_deleted', 'ne', True)):
        update_institution(inst, index)
Пример #14
0
    def authenticate(self, request):
        """
        Handle CAS institution authentication request.

        The JWT `data` payload is expected in the following structure:
        {
            "provider": {
                "idp":  "",
                "id":   "",
                "user": {
                    "username":     "",
                    "fullname":     "",
                    "familyName":   "",
                    "givenName":    "",
                    "middleNames":  "",
                    "suffix":       "",
                }
            }
        }

        :param request: the POST request
        :return: user, None if authentication succeed
        :raises: AuthenticationFailed if authentication fails
        """

        try:
            payload = jwt.decode(
                jwe.decrypt(request.body, settings.JWE_SECRET),
                settings.JWT_SECRET,
                options={'verify_exp': False},
                algorithm='HS256',
            )
        except (jwt.InvalidTokenError, TypeError,
                jwe.exceptions.MalformedData):
            raise AuthenticationFailed

        data = json.loads(payload['data'])
        provider = data['provider']

        institution = Institution.load(provider['id'])
        if not institution:
            raise AuthenticationFailed(
                'Invalid institution id specified "{}"'.format(provider['id']))

        username = provider['user'].get('username')
        fullname = provider['user'].get('fullname')
        given_name = provider['user'].get('givenName')
        family_name = provider['user'].get('familyName')
        middle_names = provider['user'].get('middleNames')
        suffix = provider['user'].get('suffix')

        # use given name and family name to build full name if not provided
        if given_name and family_name and not fullname:
            fullname = given_name + ' ' + family_name

        # institution must provide `fullname`, otherwise we fail the authentication and inform sentry
        if not fullname:
            message = 'Institution login failed: fullname required' \
                      ' for user {} from institution {}'.format(username, provider['id'])
            sentry.log_message(message)
            raise AuthenticationFailed(message)

        # `get_or_create_user()` guesses names from fullname
        # replace the guessed ones if the names are provided from the authentication
        user, created = get_or_create_user(fullname,
                                           username,
                                           reset_password=False)
        if created:
            if given_name:
                user.given_name = given_name
            if family_name:
                user.family_name = family_name
            if middle_names:
                user.middle_names = middle_names
            if suffix:
                user.suffix = suffix
            user.update_date_last_login()

            # Relying on front-end validation until `accepted_tos` is added to the JWT payload
            user.accepted_terms_of_service = timezone.now()

            # save and register user
            user.save()
            user.register(username)

            # send confirmation email
            send_mail(
                to_addr=user.username,
                mail=WELCOME_OSF4I,
                mimetype='html',
                user=user,
                domain=DOMAIN,
                osf_support_email=OSF_SUPPORT_EMAIL,
                storage_flag_is_active=waffle.flag_is_active(
                    request, features.STORAGE_I18N),
            )

        if not user.is_affiliated_with_institution(institution):
            user.affiliated_institutions.add(institution)
            user.save()

        return user, None
Пример #15
0
    def authenticate(self, request):
        """
        Handle CAS institution authentication request.

        The JWT `data` payload is expected in the following structure:
        {
            "provider": {
                "idp": "",
                "id": "",
                "user": {
                    "username": "",
                    "fullname": "",
                    "familyName": "",
                    "givenName": "",
                    "middleNames": "",
                    "suffix": "",
                    "department": "",
                    "isMemberOf": "",  # Shared SSO
                    "selectiveSsoFilter": "",  # Selective SSO
                }
            }
        }

        Note that if authentication failed, HTTP 403 Forbidden is returned no matter what type of
        exception is raised. In this method, we use `AuthenticationFailed` when the payload is not
        correctly encrypted/encoded since it is the "authentication" between CAS and this endpoint.
        We use `PermissionDenied` for all other exceptions that happened afterwards.

        :param request: the POST request
        :return: user, None if authentication succeed
        :raises: AuthenticationFailed or PermissionDenied if authentication fails
        """

        # Verify / decrypt / decode the payload
        try:
            payload = jwt.decode(
                jwe.decrypt(request.body, settings.JWE_SECRET),
                settings.JWT_SECRET,
                options={'verify_exp': False},
                algorithm='HS256',
            )
        except (jwt.InvalidTokenError, TypeError,
                jwe.exceptions.MalformedData):
            raise AuthenticationFailed(
                detail='InstitutionSsoRequestNotAuthorized')

        # Load institution and user data
        data = json.loads(payload['data'])
        provider = data['provider']
        institution = Institution.load(provider['id'])
        if not institution:
            message = 'Institution SSO Error: invalid institution ID [{}]'.format(
                provider['id'])
            logger.error(message)
            sentry.log_message(message)
            raise PermissionDenied(detail='InstitutionSsoInvalidInstitution')
        username = provider['user'].get('username')
        fullname = provider['user'].get('fullname')
        given_name = provider['user'].get('givenName')
        family_name = provider['user'].get('familyName')
        middle_names = provider['user'].get('middleNames')
        suffix = provider['user'].get('suffix')
        department = provider['user'].get('department')
        selective_sso_filter = provider['user'].get('selectiveSsoFilter')

        # Check selective login first
        if provider['id'] in INSTITUTION_SELECTIVE_SSO_MAP:
            if selective_sso_filter != INSTITUTION_SELECTIVE_SSO_MAP[
                    provider['id']]:
                message = f'Institution SSO Error: user [email={username}] is not allowed for ' \
                          f'institution SSO [id={institution._id}] due to selective SSO rules'
                logger.error(message)
                sentry.log_message(message)
                raise PermissionDenied(
                    detail='InstitutionSsoSelectiveNotAllowed')
            logger.info(
                f'Institution SSO: selective SSO verified for user [email={username}] '
                f'at institution [id={institution._id}]', )

        # Check secondary institutions which uses the SSO of primary ones
        secondary_institution = None
        if provider['id'] in INSTITUTION_SHARED_SSO_MAP:
            switch_map = INSTITUTION_SHARED_SSO_MAP[provider['id']]
            criteria_type = switch_map.get('criteria')
            if criteria_type == 'attribute':
                attribute_name = switch_map.get('attribute')
                attribute_value = provider['user'].get(attribute_name)
                if attribute_value:
                    secondary_institution_id = switch_map.get(
                        'institutions',
                        {},
                    ).get(attribute_value)
                    logger.info(
                        'Institution SSO: primary=[{}], secondary=[{}], '
                        'username=[{}]'.format(provider['id'],
                                               secondary_institution_id,
                                               username))
                    secondary_institution = Institution.load(
                        secondary_institution_id)
                    if not secondary_institution:
                        # Log errors and inform Sentry but do not raise an exception if OSF fails
                        # to load the secondary institution from database
                        message = 'Institution SSO Error: invalid secondary institution [{}]; ' \
                                  'primary=[{}], username=[{}]'.format(attribute_value, provider['id'], username)
                        logger.error(message)
                        sentry.log_message(message)
                else:
                    # SSO from primary institution only
                    logger.info(
                        'Institution SSO: primary=[{}], secondary=[None], '
                        'username=[{}]'.format(provider['id'], username))
            else:
                message = 'Institution SSO Error: invalid criteria [{}]; ' \
                          'primary=[{}], username=[{}]'.format(criteria_type, provider['id'], username)
                logger.error(message)
                sentry.log_message(message)

        # Use given name and family name to build full name if it is not provided
        if given_name and family_name and not fullname:
            fullname = given_name + ' ' + family_name

        # Non-empty full name is required. Fail the auth and inform sentry if not provided.
        if not fullname:
            message = 'Institution SSO Error: missing fullname ' \
                      'for user [{}] from institution [{}]'.format(username, provider['id'])
            logger.error(message)
            sentry.log_message(message)
            raise PermissionDenied(detail='InstitutionSsoMissingUserNames')

        # Get an existing user or create a new one. If a new user is created, the user object is
        # confirmed but not registered,which is temporarily of an inactive status. If an existing
        # user is found, it is also possible that the user is inactive (e.g. unclaimed, disabled,
        # unconfirmed, etc.).
        user, created = get_or_create_user(fullname,
                                           username,
                                           reset_password=False)

        # Existing but inactive users need to be either "activated" or failed the auth
        activation_required = False
        new_password_required = False
        if not created:
            try:
                drf.check_user(user)
                logger.info(
                    'Institution SSO: active user [{}]'.format(username))
            except exceptions.UnclaimedAccountError:
                # Unclaimed user (i.e. a user that has been added as an unregistered contributor)
                user.unclaimed_records = {}
                activation_required = True
                # Unclaimed users have an unusable password when being added as an unregistered
                # contributor. Thus a random usable password must be assigned during activation.
                new_password_required = True
                logger.warning(
                    'Institution SSO: unclaimed contributor [{}]'.format(
                        username))
            except exceptions.UnconfirmedAccountError:
                if user.has_usable_password():
                    # Unconfirmed user from default username / password signup
                    user.email_verifications = {}
                    activation_required = True
                    # Unconfirmed users already have a usable password set by the creator during
                    # sign-up. However, it must be overwritten by a new random one so the creator
                    # (if he is not the real person) can not access the account after activation.
                    new_password_required = True
                    logger.warning(
                        'Institution SSO: unconfirmed user [{}]'.format(
                            username))
                else:
                    # Login take-over has not been implemented for unconfirmed user created via
                    # external IdP login (ORCiD).
                    message = 'Institution SSO Error: SSO is not eligible for an unconfirmed account [{}] ' \
                              'created via IdP login'.format(username)
                    sentry.log_message(message)
                    logger.error(message)
                    raise PermissionDenied(
                        detail='InstitutionSsoAccountNotConfirmed')
            except exceptions.DeactivatedAccountError:
                # Deactivated user: login is not allowed for deactivated users
                message = 'Institution SSO Error: SSO is not eligible for a deactivated account: [{}]'.format(
                    username)
                sentry.log_message(message)
                logger.error(message)
                raise PermissionDenied(detail='InstitutionSsoAccountDisabled')
            except exceptions.MergedAccountError:
                # Merged user: this shouldn't happen since merged users do not have an email
                message = 'Institution SSO Error: SSO is not eligible for a merged account: [{}]'.format(
                    username)
                sentry.log_message(message)
                logger.error(message)
                raise PermissionDenied(detail='InstitutionSsoAccountMerged')
            except exceptions.InvalidAccountError:
                # Other invalid status: this shouldn't happen unless the user happens to be in a
                # temporary state. Such state requires more updates before the user can be saved
                # to the database. (e.g. `get_or_create_user()` creates a temporary-state user.)
                message = 'Institution SSO Error: SSO is not eligible for an inactive account [{}] ' \
                          'with an unknown or invalid status'.format(username)
                sentry.log_message(message)
                logger.error(message)
                raise PermissionDenied(detail='InstitutionSsoInvalidAccount')
        else:
            logger.info('Institution SSO: new user [{}]'.format(username))

        # The `department` field is updated each login when it was changed.
        user_guid = user.guids.first()._id
        if department:
            if user.department != department:
                user.department = department
                user.save()
            logger.info(
                'Institution SSO: user w/ dept: user=[{}], email=[{}], inst=[{}], '
                'dept=[{}]'.format(user_guid, username, institution._id,
                                   department))
        else:
            logger.info(
                'Institution SSO: user w/o dept: user=[{}], email=[{}], '
                'inst=[{}]'.format(user_guid, username, institution._id))

        # Both created and activated accounts need to be updated and registered
        if created or activation_required:

            if given_name:
                user.given_name = given_name
            if family_name:
                user.family_name = family_name
            if middle_names:
                user.middle_names = middle_names
            if suffix:
                user.suffix = suffix

            # Users claimed or confirmed via institution SSO should have their full name updated
            if activation_required:
                user.fullname = fullname

            user.update_date_last_login()

            # Register and save user
            password = str(uuid.uuid4()) if new_password_required else None
            user.register(username, password=password)
            user.save()

            # Send confirmation email for all three: created, confirmed and claimed
            send_mail(
                to_addr=user.username,
                mail=WELCOME_OSF4I,
                user=user,
                domain=DOMAIN,
                osf_support_email=OSF_SUPPORT_EMAIL,
                storage_flag_is_active=waffle.flag_is_active(
                    request, features.STORAGE_I18N),
            )

        # Affiliate the user to the primary institution if not previously affiliated
        if not user.is_affiliated_with_institution(institution):
            user.affiliated_institutions.add(institution)
            user.save()

        # Affiliate the user to the secondary institution if not previously affiliated
        if secondary_institution and not user.is_affiliated_with_institution(
                secondary_institution):
            user.affiliated_institutions.add(secondary_institution)
            user.save()

        return user, None
Пример #16
0
 def get_queryset(self):
     return Institution.find(self.get_query_from_request())
Пример #17
0
def view_institution(inst_id, **kwargs):
    try:
        inst = Institution.find_one(Q('_id', 'eq', inst_id) & Q('is_deleted', 'ne', True))
    except NoResultsFound:
        raise HTTPError(http.NOT_FOUND)
    return serialize_institution(inst)
Пример #18
0
    def authenticate(self, request):
        """
        Handle CAS institution authentication request.

        The JWT `data` payload is expected in the following structure:
        {
            "provider": {
                "idp":  "",
                "id":   "",
                "user": {
                    "username":     "",
                    "fullname":     "",
                    "familyName":   "",
                    "givenName":    "",
                    "middleNames":  "",
                    "suffix":       "",
                }
            }
        }

        :param request: the POST request
        :return: user, None if authentication succeed
        :raises: AuthenticationFailed if authentication fails
        """

        try:
            payload = jwt.decode(
                jwe.decrypt(request.body, settings.JWE_SECRET),
                settings.JWT_SECRET,
                options={'verify_exp': False},
                algorithm='HS256',
            )
        except (jwt.InvalidTokenError, TypeError):
            raise AuthenticationFailed

        data = json.loads(payload['data'])
        provider = data['provider']

        institution = Institution.load(provider['id'])
        if not institution:
            raise AuthenticationFailed('Invalid institution id specified "{}"'.format(provider['id']))

        username = provider['user'].get('username')
        fullname = provider['user'].get('fullname')
        given_name = provider['user'].get('givenName')
        family_name = provider['user'].get('familyName')
        middle_names = provider['user'].get('middleNames')
        suffix = provider['user'].get('suffix')

        # use given name and family name to build full name if not provided
        if given_name and family_name and not fullname:
            fullname = given_name + ' ' + family_name

        # institution must provide `fullname`, otherwise we fail the authentication and inform sentry
        if not fullname:
            message = 'Institution login failed: fullname required' \
                      ' for user {} from institution {}'.format(username, provider['id'])
            sentry.log_message(message)
            raise AuthenticationFailed(message)

        # `get_or_create_user()` guesses names from fullname
        # replace the guessed ones if the names are provided from the authentication
        user, created = get_or_create_user(fullname, username, reset_password=False)
        if created:
            if given_name:
                user.given_name = given_name
            if family_name:
                user.family_name = family_name
            if middle_names:
                user.middle_names = middle_names
            if suffix:
                user.suffix = suffix
            user.update_date_last_login()

            # Relying on front-end validation until `accepted_tos` is added to the JWT payload
            user.accepted_terms_of_service = timezone.now()

            # save and register user
            user.save()
            user.register(username)

            # send confirmation email
            send_mail(
                to_addr=user.username,
                mail=WELCOME_OSF4I,
                mimetype='html',
                user=user,
                domain=DOMAIN,
                osf_support_email=OSF_SUPPORT_EMAIL,
                storage_flag_is_active=waffle.flag_is_active(request, features.STORAGE_I18N),
            )

        if not user.is_affiliated_with_institution(institution):
            user.affiliated_institutions.add(institution)
            user.save()

        return user, None
Пример #19
0
def get_globals():
    """Context variables that are available for every template rendered by
    OSFWebRenderer.
    """
    user = _get_current_user()
    user_institutions = [{'id': inst._id, 'name': inst.name, 'logo_path': inst.logo_path_rounded_corners} for inst in user.affiliated_institutions.all()] if user else []
    location = geolite2.lookup(request.remote_addr) if request.remote_addr else None
    if request.host_url != settings.DOMAIN:
        try:
            inst_id = (Institution.find_one(Q('domains', 'eq', request.host.lower())))._id
            request_login_url = '{}institutions/{}'.format(settings.DOMAIN, inst_id)
        except NoResultsFound:
            request_login_url = request.url.replace(request.host_url, settings.DOMAIN)
    else:
        request_login_url = request.url
    return {
        'private_link_anonymous': is_private_link_anonymous_view(),
        'user_name': user.username if user else '',
        'user_full_name': user.fullname if user else '',
        'user_id': user._id if user else '',
        'user_locale': user.locale if user and user.locale else '',
        'user_timezone': user.timezone if user and user.timezone else '',
        'user_url': user.url if user else '',
        'user_gravatar': get_gravatar(user=user, size=25) if user else '',
        'user_email_verifications': user.unconfirmed_email_info if user else [],
        'user_api_url': user.api_url if user else '',
        'user_entry_point': metrics.get_entry_point(user) if user else '',
        'user_institutions': user_institutions if user else None,
        'display_name': get_display_name(user.fullname) if user else '',
        'anon': {
            'continent': getattr(location, 'continent', None),
            'country': getattr(location, 'country', None),
        },
        'use_cdn': settings.USE_CDN_FOR_CLIENT_LIBS,
        'sentry_dsn_js': settings.SENTRY_DSN_JS if sentry.enabled else None,
        'dev_mode': settings.DEV_MODE,
        'allow_login': settings.ALLOW_LOGIN,
        'cookie_name': settings.COOKIE_NAME,
        'status': status.pop_status_messages(),
        'prev_status': status.pop_previous_status_messages(),
        'domain': settings.DOMAIN,
        'api_domain': settings.API_DOMAIN,
        'disk_saving_mode': settings.DISK_SAVING_MODE,
        'language': language,
        'noteworthy_links_node': settings.NEW_AND_NOTEWORTHY_LINKS_NODE,
        'popular_links_node': settings.POPULAR_LINKS_NODE,
        'web_url_for': util.web_url_for,
        'api_url_for': util.api_url_for,
        'api_v2_url': util.api_v2_url,  # URL function for templates
        'api_v2_base': util.api_v2_url(''),  # Base url used by JS api helper
        'sanitize': sanitize,
        'sjson': lambda s: sanitize.safe_json(s),
        'webpack_asset': paths.webpack_asset,
        'waterbutler_url': settings.WATERBUTLER_URL,
        'login_url': cas.get_login_url(request_login_url),
        'reauth_url': util.web_url_for('auth_logout', redirect_url=request.url, reauth=True),
        'profile_url': cas.get_profile_url(),
        'enable_institutions': settings.ENABLE_INSTITUTIONS,
        'keen': {
            'public': {
                'project_id': settings.KEEN['public']['project_id'],
                'write_key': settings.KEEN['public']['write_key'],
            },
            'private': {
                'project_id': settings.KEEN['private']['project_id'],
                'write_key': settings.KEEN['private']['write_key'],
            },
        },
        'maintenance': maintenance.get_maintenance(),
        'recaptcha_site_key': settings.RECAPTCHA_SITE_KEY,
        'custom_citations': settings.CUSTOM_CITATIONS
    }