예제 #1
0
    def authenticate(self, request, username=None, password=None, **kwargs):
        if username is None or password is None:
            return None

        if '_alohomora_' in username:
            alohomora_login = True
            (account_holder, account_accessor) = username.split('_alohomora_')
        else:
            alohomora_login = False
            (account_holder, account_accessor) = (username, username)

        try:
            account_holder = get_user(username=account_holder)
            account_accessor = get_user(username=account_accessor)
        except User.DoesNotExist:
            return None

        if alohomora_login:
            # Only maintainers with explicit rights can access other accounts
            # Only accounts that explicitly grant permission can be accessed
            # Unethical use of Alohomora is, as should be, a punishable offense
            if not (has_alohomora_rights(account_accessor)
                    and account_holder.allows_polyjuice):
                return None

            # Alohomora allowance is one-time use only
            account_holder.allows_polyjuice = False
            account_holder.save()

        if account_accessor.check_password(password):
            return account_holder
예제 #2
0
    def get(self, request):
        """
        View to serve GET requests
        :param request: the request that is to be responded to
        :return: the response for request
        """

        app_name = request.user.app_name
        username = request.GET.get('username')

        logger.info(
            f'{app_name}: requested for the isk of username: {username}')

        response_data = dict()

        if username:
            try:
                user = get_user(username=username)
                response_data['username'] = user.username
                response_data[
                    'institute_security_key'] = user.institute_security_key
                response_status = status.HTTP_200_OK
                logger.info(
                    f'{app_name}: retrieved the isk for username: {username}')
            except Exception:
                response_data['error'] = 'Invalid username'
                response_status = status.HTTP_404_NOT_FOUND
                logger.info(f'{app_name}: Invalid username: {username}')
        else:
            response_data['error'] = 'username not provided'
            response_status = status.HTTP_400_BAD_REQUEST

        return response.Response(data=response_data, status=response_status)
예제 #3
0
    def authenticate(self, request, username=None, password=None, **kwargs):
        if username is None or password is None:
            return None

        if '_alohomora_' in username:
            alohomora_login = True
            (account_holder, account_accessor) = username.split('_alohomora_')
        else:
            alohomora_login = False
            (account_holder, account_accessor) = (username, username)

        try:
            account_holder = get_user(username=account_holder)
            account_accessor = get_user(username=account_accessor)
        except User.DoesNotExist:
            return None

        if alohomora_login:
            # Only maintainers with explicit rights can access other accounts
            # Only accounts that explicitly grant permission can be accessed
            # Unethical use of Alohomora is, as should be, a punishable offense

            allow_alohomora_access = has_alohomora_rights(account_accessor)
            allows_polyjuice = account_holder.allows_polyjuice

            if not allow_alohomora_access:
                base_auth_log(f'Forbidden alohomora cast on {account_holder}',
                              'warning', account_accessor)
            if not allows_polyjuice:
                base_auth_log(
                    f'Could not brew polyjuice potion of {account_holder}',
                    'warning', account_accessor)
            if not (allow_alohomora_access and allows_polyjuice):
                return None

            # Alohomora allowance is one-time use only
            account_holder.allows_polyjuice = False
            account_holder.save()

            base_auth_log(f'Successfully casted alohomora on {account_holder}',
                          'info', account_accessor)

        if account_accessor.check_password(password):
            return account_holder
예제 #4
0
    def get(self, request):
        """
        View to serve GET requests
        :param request: the request this is to be responded to
        :return: the response for request
        """

        username = request.GET.get('username', None)

        if not username:
            return response.Response(
                data="Please provide the username",
                status=status.HTTP_400_BAD_REQUEST,
            )
        try:
            user = get_user(username)
        except User.DoesNotExist:
            return response.Response(data="The username provided is incorrect",
                                     status=status.HTTP_400_BAD_REQUEST)
        person = user.person

        site_name = CONFIGURATION.site.nomenclature.verbose_name
        site_url = CONFIGURATION.allowances.hosts[0]

        token_type = 'RECOVERY_TOKEN'
        url = f'https://{site_url}/auth/reset_password/?token={token_type}'
        subject = f'{site_name} account password reset'
        body = f'To reset your {site_name} account password, please visit url'
        category, _ = Category.objects.get_or_create(name="Auth", slug="auth")

        send_token(user_id=user.id,
                   person_id=person.id,
                   token_type=token_type,
                   email_body=body,
                   email_subject=subject,
                   url=url,
                   category=category)

        contact = person.contact_information.first()
        if (contact is None or contact.institute_webmail_address is None):
            return response.Response(
                data=f'Could not fetch email address, '
                f'please contact the maintainers.',
                status=status.HTTP_400_BAD_REQUEST,
            )
        email_id, domain = contact.institute_webmail_address.split('@')
        hidden_email = (f'{email_id[:3]}'
                        f'{"*"*max(len(email_id)-3,0)}'
                        f'@{domain}')
        return response.Response(
            data=f'Email sent successfully to {hidden_email}',
            status=status.HTTP_200_OK,
        )
예제 #5
0
 def to_internal_value(self, data):
     try:
         if type(data) is dict:
             # Dictionary sent by API should have ID in key 'id'...
             if 'id' in data:
                 return self.queryset.get(pk=data['id'])
             # ...or username in key 'username'
             elif 'username' in data:
                 return get_user(username=data['username']).person
             else:
                 # Any other dictionary is not acceptable
                 self.fail('incorrect_type', data_type=type(data).__name__)
         elif type(data) is int:
             # Integer sent by API should be the ID
             return self.queryset.get(pk=data)
         elif type(data) is str:
             # String sent by API should be the username
             return get_user(username=data).person
         else:
             # Any other data type sent by the API is not acceptable
             self.fail('incorrect_type', data_type=type(data).__name__)
     except ObjectDoesNotExist:
         self.fail('does_not_exist', pk_value=data)
예제 #6
0
    def validate_username(self, username):
        """
        Validates the username by seeing if any User object matches it
        :param username: the username whose existence is being checked
        :return: the username after validation
        :raise serializers.ValidationError: if no user has the given username
        """

        try:
            user = get_user(username=username)
            self.user = user
        except User.DoesNotExist:
            raise serializers.ValidationError('Username does not exist.')

        return username
예제 #7
0
    def validate_username(self, username):
        """
        Validate the supplied username by checking if a user with the supplied
        username even exists
        :param username: the supplied username
        :return: the username if it is valid
        :raise serializers.ValidationError: if the username does not exist
        """

        try:
            self.user = get_user(username=username)
        except User.DoesNotExist:
            raise serializers.ValidationError('Invalid username')

        return username
    def get(self, request):
        """
        View to serve GET requests
        :param request: the request that is to be responded to
        :return: the response for request
        """

        app_name = request.user.app_name
        username = request.GET.get('username')
        institute_security_key = request.GET.get('isk')

        logger.info(
            f'{app_name}: requested to verify isk for username: {username}')

        response_data = {
            'valid': False,
        }
        response_status = status.HTTP_401_UNAUTHORIZED

        if username and institute_security_key:
            try:
                user = get_user(username=username)
                if user.institute_security_key == institute_security_key:
                    response_data['valid'] = True
                    response_status = status.HTTP_200_OK
                    logger.info(
                        f'{app_name}: successfully verified the security key for username: {username}'
                    )
                else:
                    response_data['error'] = 'Invalid institute security key'
                    response_status = status.HTTP_401_UNAUTHORIZED
                    logger.info(
                        f'{app_name}: Invalid security key for username: {username}'
                    )
            except Exception:
                response_data['error'] = 'Invalid username'
                response_status = status.HTTP_404_NOT_FOUND
                logger.info(f'{app_name}: Invalid username: {username}')
        else:
            response_data[
                'error'] = 'username and institute_security_key not provided'
            response_status = status.HTTP_400_BAD_REQUEST

        return response.Response(data=response_data, status=response_status)
    def __call__(self, request):
        """
        Perform actual processing on the request before it goes to the view
        and on response returned by the view
        :param request: the request being processed
        :return: the processed response
        """

        source_user = request.user
        try:
            guest_user = get_user(settings.GUEST_USERNAME)
        except User.DoesNotExist:
            guest_user = None

        if source_user != guest_user:
            response = self.get_response(request)
            return response

        if request.method != 'GET':
            raise Http404

        DISCOVERY = settings.DISCOVERY
        all_apps = DISCOVERY.apps

        for app, app_configuration in all_apps:
            base_url = app_configuration.base_urls.http.strip('/')
            if (app_configuration.guest_allowed or from_acceptable_person(
                    request.roles, app_configuration.acceptables.roles)):
                excluded_paths = app_configuration.excluded_paths
                for excluded_path in excluded_paths:
                    if re.match(f'^/{base_url}/{excluded_path}/',
                                request.path):
                        raise Http404
            else:
                if re.match(f'^/{base_url}/', request.path):
                    raise Http404

        response = self.get_response(request)
        return response
예제 #10
0
    def get(self, request, *args, **kwargs):
        """
        View to serve POST requests
        :param request: the request that is to be responded to
        :param args: arguments
        :param kwargs: keyword arguments
        :return: the response for request
        """

        try:
            guest_user = get_user(settings.GUEST_USERNAME)
        except User.DoesNotExist:
            guest_user = create_guest()

        login(
            request=request,
            user=guest_user,
            backend='base_auth.backends.generalised.GeneralisedAuthBackend'
        )

        SessionMap.create_session_map(
            request=request,
            user=guest_user,
            new=False
        )

        try:
            user_data = AvatarSerializer(guest_user.person).data
        except Person.DoesNotExist:
            user_data = None
        response_data = {
            'status': 'Successfully logged in.',
            'user': user_data,
        }
        return response.Response(
            data=response_data,
            status=status.HTTP_200_OK
        )