• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

rdmorganiser / rdmo / 20428555173

22 Dec 2025 10:02AM UTC coverage: 94.693% (-0.1%) from 94.814%
20428555173

Pull #1436

github

web-flow
Merge 0ffb48a5d into 57a75b09e
Pull Request #1436: Draft: add `rdmo.config` app for `Plugin` model (plugin managament)

2191 of 2304 branches covered (95.1%)

23411 of 24723 relevant lines covered (94.69%)

3.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.9
rdmo/core/views.py
1
import hashlib
4✔
2
import logging
4✔
3

4
from django.conf import settings
4✔
5
from django.contrib.auth.decorators import login_required
4✔
6
from django.contrib.auth.mixins import LoginRequiredMixin
4✔
7
from django.contrib.auth.mixins import PermissionRequiredMixin as DjangoPermissionRequiredMixin
4✔
8
from django.contrib.auth.views import redirect_to_login
4✔
9
from django.core.exceptions import PermissionDenied
4✔
10
from django.http import HttpResponseRedirect
4✔
11
from django.shortcuts import render
4✔
12
from django.urls import NoReverseMatch, reverse
4✔
13
from django.utils import translation
4✔
14
from django.utils.decorators import method_decorator
4✔
15
from django.views.decorators.csrf import ensure_csrf_cookie
4✔
16
from django.views.generic.base import View
4✔
17

18
from rest_framework import mixins, viewsets
4✔
19
from rest_framework.response import Response
4✔
20

21
from rules.contrib.views import PermissionRequiredMixin as RulesPermissionRequiredMixin
4✔
22

23
from .serializers import ChoicesSerializer
4✔
24
from .utils import get_next, get_referer, get_referer_path_info
4✔
25

26
logger = logging.getLogger(__name__)
4✔
27

28

29
def home(request):
4✔
30
    if request.user.is_authenticated:
4✔
31
        return HttpResponseRedirect(reverse('projects'))
4✔
32
    else:
33
        if settings.LOGIN_FORM:
4✔
34
            if settings.ACCOUNT or settings.SOCIALACCOUNT:
4✔
35
                from rdmo.accounts.account import LoginForm
4✔
36
                return render(request, 'core/home.html', {
4✔
37
                    'form': LoginForm(),
38
                    'signup_url': reverse("account_signup")
39
                })
40
            else:
41
                from django.contrib.auth.forms import AuthenticationForm
4✔
42
                return render(request, 'core/home.html', {'form': AuthenticationForm()})
4✔
43
        else:
44
            return render(request, 'core/home.html')
4✔
45

46

47
@login_required
4✔
48
def about(request):
4✔
49
    return render(request, 'core/about.html')
4✔
50

51

52
@login_required
4✔
53
def api(request):
4✔
54
    context = {}
4✔
55

56
    for name in ['schema', 'swagger', 'redoc']:
4✔
57
        try:
4✔
58
            context[f'{name}_url'] = request.build_absolute_uri(reverse(f'v1-openapi:{name}'))
4✔
59
        except NoReverseMatch:
×
60
            context[f'{name}_url'] = None
×
61

62
    context['module_urls'] = [
4✔
63
        request.build_absolute_uri(reverse(f'v1-{name}:api-root'))
64
            for name in [
65
                'accounts',
66
                'conditions',
67
                'core',
68
                'config',
69
                'domain',
70
                'management',
71
                'options',
72
                'overlays',
73
                'projects',
74
                'questions',
75
                'tasks',
76
                'views'
77
            ]
78
    ]
79

80
    return render(request, 'core/api.html', context)
4✔
81

82

83
def i18n_switcher(request, language):
4✔
84
    referer = get_referer(request, default='/')
4✔
85

86
    # set the new language
87
    translation.activate(language)
4✔
88

89
    # get the response, set the cookie and return
90
    response = HttpResponseRedirect(referer)
4✔
91
    response.set_cookie(settings.LANGUAGE_COOKIE_NAME, language)
4✔
92
    return response
4✔
93

94

95
def bad_request(request, exception):
4✔
96
    return render(request, 'core/400.html', status=400)
×
97

98

99
def forbidden(request, exception):
4✔
100
    return render(request, 'core/403.html', status=403)
×
101

102

103
def not_found(request, exception):
4✔
104
    return render(request, 'core/404.html', status=404)
×
105

106

107
def internal_server_error(request):
4✔
108
    return render(request, 'core/500.html', status=500)
×
109

110

111
class CSRFViewMixin(View):
4✔
112

113
    @method_decorator(ensure_csrf_cookie)
4✔
114
    def get(self, request, *args, **kwargs):
4✔
115
        return super().get(self, request, *args, **kwargs)
4✔
116

117

118
class StoreIdViewMixin(View):
4✔
119

120
    def render_to_response(self, context, **response_kwargs):
4✔
121
        response = super().render_to_response(context, **response_kwargs)
4✔
122
        response.set_cookie(
4✔
123
            'storeid',
124
            self.get_store_id(),
125
            path=settings.SESSION_COOKIE_PATH,
126
            domain=settings.SESSION_COOKIE_DOMAIN,
127
            secure=settings.SESSION_COOKIE_SECURE,
128
            httponly=False,
129
            samesite=settings.SESSION_COOKIE_SAMESITE,
130
        )
131
        return response
4✔
132

133
    def get_store_id(self):
4✔
134
        session_key = self.request.session.session_key or 'anonymous'
4✔
135
        return hashlib.sha256(session_key.encode()).hexdigest()
4✔
136

137

138
class RedirectViewMixin(View):
4✔
139

140
    def post(self, request, *args, **kwargs):
4✔
141
        if 'cancel' in request.POST:
4✔
142
            return HttpResponseRedirect(get_next(request))
×
143
        else:
144
            return super().post(request, *args, **kwargs)
4✔
145

146
    def get_context_data(self, **kwargs):
4✔
147
        context_data = super().get_context_data(**kwargs)
4✔
148
        if 'next' in self.request.GET:
4✔
149
            context_data['next'] = self.request.GET['next']
×
150
        else:
151
            context_data['next'] = get_referer_path_info(self.request)
4✔
152
        return context_data
4✔
153

154
    def get_success_url(self):
4✔
155
        if 'next' in self.request.GET:
4✔
156
            return self.request.GET['next']
×
157
        else:
158
            return super().get_success_url()
4✔
159

160

161
class PermissionRedirectMixin:
4✔
162

163
    def handle_no_permission(self):
4✔
164
        if self.request.user.is_authenticated:
4✔
165
            raise PermissionDenied(self.get_permission_denied_message())
4✔
166
        return redirect_to_login(self.request.get_full_path(), self.get_login_url(), self.get_redirect_field_name())
4✔
167

168

169
class ModelPermissionMixin(LoginRequiredMixin, PermissionRedirectMixin, DjangoPermissionRequiredMixin):
4✔
170
    pass
4✔
171

172

173
class ObjectPermissionMixin(PermissionRedirectMixin, RulesPermissionRequiredMixin):
4✔
174
    pass
4✔
175

176

177
class ChoicesViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
4✔
178
    serializer_class = ChoicesSerializer
4✔
179

180

181
class SettingsViewSet(viewsets.GenericViewSet):
4✔
182

183
    def list(self, request, *args, **kwargs):
4✔
184
        return Response({
×
185
            'default_uri_prefix': settings.DEFAULT_URI_PREFIX
186
        })
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc