예제 #1
0
    def test_get_active_app_none_none(self):
        # Get the active TethysApp object, with a request of None and url of None
        result = utilities.get_active_app(request=None, url=None)
        self.assertEqual(None, result)

        # Try again with the defaults, which are a request of None and url of None
        result = utilities.get_active_app()
        self.assertEqual(None, result)
예제 #2
0
    def test_get_active_app_none_none(self):
        # Get the active TethysApp object, with a request of None and url of None
        result = utilities.get_active_app(request=None, url=None)
        self.assertEqual(None, result)

        # Try again with the defaults, which are a request of None and url of None
        result = utilities.get_active_app()
        self.assertEqual(None, result)
예제 #3
0
    def wrapper(*args, **kwargs):
        from tethys_quotas.models import ResourceQuota
        from tethys_apps.utilities import get_active_app

        request = None
        for index, arg in enumerate(args):
            if isinstance(arg, HttpRequest):
                request = arg
                break

        if request is None:
            raise ValueError('No request given. The app_workspace decorator only works on controllers.')

        try:
            codename = 'app_workspace_quota'
            rq = ResourceQuota.objects.get(codename=codename)

        except ResourceQuota.DoesNotExist:
            log.warning('ResourceQuota with codename {} does not exist.'.format(codename))

        # Get the active app
        app = get_active_app(request, get_class=True)

        if not passes_quota(app, codename):
            raise PermissionDenied(rq.help)

        the_workspace = _get_app_workspace(app)

        return controller(*args, the_workspace, **kwargs)
예제 #4
0
def tethys_apps_context(request):
    """
    Add the current Tethys app metadata to the template context.

    Args:
        request: Django request object.
    """
    # Setup variables
    context = {'tethys_app': None}

    # Get the app
    app = get_active_app(request=request)

    if app is not None:
        context['tethys_app'] = {
            'id': app.id,
            'name': app.name,
            'index': app.index,
            'icon': app.icon,
            'color': app.color,
            'tags': app.tags,
            'description': app.description
        }

        if hasattr(app, 'feedback_emails') and len(app.feedback_emails) > 0:
            context['tethys_app']['feedback_emails'] = app.feedback_emails

            if hasattr(app, 'enable_feedback'):
                context['tethys_app']['enable_feedback'] = app.enable_feedback

    return context
예제 #5
0
    def test_get_active_app_url(self, mock_app):
        # Mock up for TethysApp
        mock_app.objects.get.return_value = mock.MagicMock()

        # Result should be mock for mock_app.objects.get.return_value
        result = utilities.get_active_app(url='/apps/foo/bar')
        self.assertEqual(mock_app.objects.get(), result)
예제 #6
0
    def test_get_active_app_url(self, mock_app):
        # Mock up for TethysApp
        mock_app.objects.get.return_value = mock.MagicMock()

        # Result should be mock for mock_app.objects.get.return_value
        result = utilities.get_active_app(url='/apps/foo/bar')
        self.assertEqual(mock_app.objects.get(), result)
예제 #7
0
    def test_get_active_app_request(self, mock_app):
        # Mock up for TethysApp, and request
        mock_app.objects.get.return_value = mock.MagicMock()
        mock_request = mock.MagicMock()
        mock_request.path = '/apps/foo/bar'

        # Result should be mock for mock_app.objects.get.return_value
        result = utilities.get_active_app(request=mock_request)
        self.assertEqual(mock_app.objects.get(), result)
예제 #8
0
    def test_get_active_app_request(self, mock_app):
        # Mock up for TethysApp, and request
        mock_app.objects.get.return_value = mock.MagicMock()
        mock_request = mock.MagicMock()
        mock_request.path = '/apps/foo/bar'

        # Result should be mock for mock_app.objects.get.return_value
        result = utilities.get_active_app(request=mock_request)
        self.assertEqual(mock_app.objects.get(), result)
예제 #9
0
    def test_get_active_app_class(self, mock_app, mock_harvester):
        # Mock up for TethysApp
        app = mock.MagicMock()
        mock_app.objects.get.return_value = app

        mock_harvester().apps = [app]

        # Result should be mock for mock_app.objects.get.return_value
        result = utilities.get_active_app(url='/apps/foo/bar', get_class=True)
        self.assertEqual(mock_app.objects.get(), result)
예제 #10
0
    def test_get_active_app_request_bad_path(self, mock_app):
        # Mock up for TethysApp
        mock_app.objects.get.return_value = mock.MagicMock()
        mock_request = mock.MagicMock()
        # Path does not contain apps
        mock_request.path = '/foo/bar'

        # Because 'app' not in request path, return None
        result = utilities.get_active_app(request=mock_request)
        self.assertEqual(None, result)
예제 #11
0
    def test_get_active_app_request_bad_path(self, mock_app):
        # Mock up for TethysApp
        mock_app.objects.get.return_value = mock.MagicMock()
        mock_request = mock.MagicMock()
        # Path does not contain apps
        mock_request.path = '/foo/bar'

        # Because 'app' not in request path, return None
        result = utilities.get_active_app(request=mock_request)
        self.assertEqual(None, result)
예제 #12
0
def send_beta_feedback_email(request):
    """
    Processes and send the beta form data submitted by beta testers
    """
    # Form parameters
    post = request.POST

    # Get url and parts
    url = post.get('betaFormUrl')

    # Get app
    app = get_active_app(url=url)

    if app is None or not hasattr(app, 'feedback_emails'):
        json = {
            'success': False,
            'error': 'App not found or feedback_emails not defined in app.py'
        }
        return JsonResponse(json)

    # Formulate email
    subject = 'User Feedback for {0}'.format(app.name.encode('utf-8'))

    message = 'User: {0}\n'\
              'User Local Time: {1}\n'\
              'UTC Offset in Hours: {2}\n'\
              'App URL: {3}\n'\
              'User Agent: {4}\n'\
              'Vendor: {5}\n'\
              'Comments:\n' \
              '{6}'.\
        format(
            post.get('betaUser'),
            post.get('betaSubmitLocalTime'),
            post.get('betaSubmitUTCOffset'),
            post.get('betaFormUrl'),
            post.get('betaFormUserAgent'),
            post.get('betaFormVendor'),
            post.get('betaUserComments')
        )

    try:
        send_mail(subject,
                  message,
                  from_email=None,
                  recipient_list=app.feedback_emails)
    except Exception as e:
        json = {
            'success': False,
            'error': 'Failed to send email: ' + e.message
        }
        return JsonResponse(json)

    json = {'success': True, 'result': 'Emails sent to specified developers'}
    return JsonResponse(json)
예제 #13
0
    def test_get_active_app_request_exception2(self, mock_app, mock_log_warning):
        from django.core.exceptions import MultipleObjectsReturned

        # Mock up for TethysApp to raise exception, and request
        mock_app.objects.get.side_effect = MultipleObjectsReturned
        mock_request = mock.MagicMock()
        mock_request.path = '/apps/foo/bar'

        # Result should be None due to the exception
        result = utilities.get_active_app(request=mock_request)
        self.assertEqual(None, result)
        mock_log_warning.assert_called_once_with('Multiple apps found with root url "foo".')
예제 #14
0
    def test_get_active_app_request_exception2(self, mock_app, mock_log_warning):
        from django.core.exceptions import MultipleObjectsReturned

        # Mock up for TethysApp to raise exception, and request
        mock_app.objects.get.side_effect = MultipleObjectsReturned
        mock_request = mock.MagicMock()
        mock_request.path = '/apps/foo/bar'

        # Result should be None due to the exception
        result = utilities.get_active_app(request=mock_request)
        self.assertEqual(None, result)
        mock_log_warning.assert_called_once_with('Multiple apps found with root url "foo".')
예제 #15
0
def tethys_apps_context(request):
    """
    Add the current Tethys app metadata to the template context.

    Args:
        request: Django request object.
    """
    # Setup variables
    context = {'tethys_app': None}

    # Get the app
    app = get_active_app(request=request)

    if app is not None:
        context['tethys_app'] = {
            'id': app.id,
            'name': app.name,
            'index': app.index,
            'icon': app.icon,
            'color': app.color,
            'tags': app.tags,
            'description': app.description,
            'namespace': app.namespace
        }

        if hasattr(app, 'feedback_emails') and len(app.feedback_emails) > 0:
            context['tethys_app']['feedback_emails'] = app.feedback_emails

            if hasattr(app, 'enable_feedback'):
                context['tethys_app']['enable_feedback'] = app.enable_feedback

    # Dependency Versions
    context.update({
        'tethys': {
            'jquery': {
                'version': '3.4.1',
                'integrity':
                'sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=',
            },
            'bootstrap': {
                'version':
                '3.4.1',
                'css_integrity':
                'sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu',
                'js_integrity':
                'sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd'
            },
        }
    })

    return context
예제 #16
0
def send_beta_feedback_email(request):
    """
    Processes and send the beta form data submitted by beta testers
    """
    # Form parameters
    post = request.POST

    # Get url and parts
    url = post.get('betaFormUrl')

    # Get app
    app = get_active_app(url=url)

    if app is None or not hasattr(app, 'feedback_emails'):
        json = {'success': False,
                'error': 'App not found or feedback_emails not defined in app.py'}
        return JsonResponse(json)

    # Formulate email
    subject = 'User Feedback for {0}'.format(app.name.encode('utf-8'))

    message = 'User: {0}\n'\
              'User Local Time: {1}\n'\
              'UTC Offset in Hours: {2}\n'\
              'App URL: {3}\n'\
              'User Agent: {4}\n'\
              'Vendor: {5}\n'\
              'Comments:\n' \
              '{6}'.\
        format(
            post.get('betaUser'),
            post.get('betaSubmitLocalTime'),
            post.get('betaSubmitUTCOffset'),
            post.get('betaFormUrl'),
            post.get('betaFormUserAgent'),
            post.get('betaFormVendor'),
            post.get('betaUserComments')
        )

    try:
        send_mail(subject, message, from_email=None, recipient_list=app.feedback_emails)
    except Exception as e:
        json = {'success': False,
                'error': 'Failed to send email: ' + str(e)}
        return JsonResponse(json)

    json = {'success': True,
            'result': 'Emails sent to specified developers'}
    return JsonResponse(json)
예제 #17
0
    def test_user_can_access_app(self, mock_settings):
        mock_settings.ENABLE_OPEN_PORTAL = False
        user = self.user
        app = utilities.get_active_app(url='/apps/test-app')

        # test no permission
        result1 = utilities.user_can_access_app(user, app)
        self.assertFalse(result1)

        # test permission
        assign_perm(f'{app.package}:access_app', user, app)

        result2 = utilities.user_can_access_app(user, app)
        self.assertTrue(result2)

        # test open portal mode case
        mock_settings.ENABLE_OPEN_PORTAL = True
        result3 = utilities.user_can_access_app(user, app)
        self.assertTrue(result3)
예제 #18
0
    def __call__(self, request):
        response = self.get_response(request)
        app = get_active_app(request)

        if app is None:
            return response
        else:
            if not app.enabled:
                if request.user.is_staff:
                    return handler_404(
                        request, PermissionDenied,
                        "This app is disabled. A user with admin permissions "
                        "can enable this app from the app settings page.")
                else:
                    return handler_404(request, PermissionDenied)
            elif user_can_access_app(request.user, app):
                return response
            else:
                return handler_404(request, PermissionDenied)
예제 #19
0
def has_permission(request, perm, user=None):
    """
    Returns True if the user of the given request has the given permission for the app. If a user object is provided, it is tested instead of the request user. The Request object is still required to derive the app context of the permission check.

    Args:
        request (Request): The current request object.
        perm (string): The name of the permission (e.g. 'create_things').
        user (django.contrib.auth.models.User): A user object to test instead of the user provided in the request.

    **Example:**

    ::

        from tethys_sdk.permissions import has_permission

        def my_controller(request):
            \"""
            Example controller
            \"""

            can_create_projects = has_permission(request, 'create_projects')

            if can_create_projects:
                ...

    """
    from tethys_apps.utilities import get_active_app

    app = get_active_app(request)

    if user is None:
        user = request.user

    namespaced_perm = 'tethys_apps.' + app.package + ':' + perm

    # Check permission
    if user.has_perm(namespaced_perm, app):
        return True
    return False
예제 #20
0
        def wrapper(*args, **kwargs):
            try:
                request = None
                for index, arg in enumerate(args):
                    if isinstance(arg, HttpRequest):
                        request = arg
                        break

                if request is None:
                    raise ValueError('Invalid request')

                rq = ResourceQuota.objects.get(codename=codename)

                if rq.applies_to == 'django.contrib.auth.models.User':
                    entity = request.user
                elif rq.applies_to == 'tethys_apps.models.TethysApp':
                    entity = get_active_app(request)
                    if not entity:
                        raise ValueError(
                            'Request could not be used to find app')
                else:
                    raise ValueError(
                        'ResourceQuota that applies_to {} is not supported'.
                        format(rq.applies_to))

                if not passes_quota(entity, codename):
                    raise PermissionDenied(rq.help)

            except ValueError as e:
                log.warning(str(e))

            except ResourceQuota.DoesNotExist:
                log.warning(
                    'ResourceQuota with codename {} does not exist.'.format(
                        codename))

            return controller(*args, **kwargs)