def saml_details(request): redirect_to = reverse('saml_details') saml_session = saml.is_saml_session(request) if request.method == 'POST': if 'login' in request.POST: if request.user.is_authenticated(): person = request.user institute = person.institute if institute.saml_entityid: redirect_to = reverse("saml_details") url = saml.build_shib_url(request, redirect_to, institute.saml_entityid) return HttpResponseRedirect(url) else: return HttpResponseBadRequest("<h1>Bad Request</h1>") else: return HttpResponseBadRequest("<h1>Bad Request</h1>") elif 'register' in request.POST: if request.user.is_authenticated() and saml_session: person = request.user person = saml.add_saml_data( person, request) person.save() url = reverse("saml_details") return HttpResponseRedirect(url) else: return HttpResponseBadRequest("<h1>Bad Request</h1>") elif 'logout' in request.POST: if saml_session: url = saml.logout_url(request) return HttpResponseRedirect(url) else: return HttpResponseBadRequest("<h1>Bad Request</h1>") else: return HttpResponseBadRequest("<h1>Bad Request</h1>") attrs = {} if saml_session: attrs, _ = saml.parse_attributes(request) saml_session = True person = None if request.user.is_authenticated(): person = request.user return render_to_response('people/saml_detail.html', {'attrs': attrs, 'saml_session': saml_session, 'person': person, }, context_instance=RequestContext(request))
def new_application(request): """ A new application by a user to start a new project. """ # Note default kgapplications/index.html will display error if user logged # in. if not settings.ALLOW_REGISTRATIONS: return render( template_name='kgapplications/project_common_disabled.html', context={}, request=request) roles = {'is_applicant', 'is_authorised'} if not request.user.is_authenticated(): attrs, _ = saml.parse_attributes(request) defaults = {'email': attrs['email']} form = forms.UnauthenticatedInviteUserApplicationForm( request.POST or None, initial=defaults) if request.method == 'POST': if form.is_valid(): email = form.cleaned_data['email'] applicant, existing_person = get_applicant_from_email(email) assert not existing_person application = ProjectApplication() application.applicant = applicant application.save() state_machine = get_application_state_machine() state_machine.start(request, application, roles) # we do not show unauthenticated users the application at this # stage. url = reverse('index') return HttpResponseRedirect(url) return render( template_name='kgapplications/' 'project_common_invite_unauthenticated.html', context={'form': form, }, request=request) else: if request.method == 'POST': person = request.user application = ProjectApplication() application.applicant = person application.save() state_machine = get_application_state_machine() response = state_machine.start(request, application, roles) return response return render( template_name='kgapplications/' 'project_common_invite_authenticated.html', context={}, request=request)
def saml_details(request): redirect_to = reverse('kg_profile_saml') saml_session = saml.is_saml_session(request) if request.method == 'POST': if 'login' in request.POST: if request.user.is_authenticated: person = request.user institute = person.institute if institute.saml_entityid: url = saml.build_shib_url( request, redirect_to, institute.saml_entityid) return HttpResponseRedirect(url) else: return HttpResponseBadRequest("<h1>Bad Request</h1>") else: return HttpResponseBadRequest("<h1>Bad Request</h1>") elif 'register' in request.POST: if request.user.is_authenticated and saml_session: person = request.user person = saml.add_saml_data( person, request) person.save() return HttpResponseRedirect(redirect_to) else: return HttpResponseBadRequest("<h1>Bad Request</h1>") elif 'logout' in request.POST: if saml_session: url = saml.logout_url(request) return HttpResponseRedirect(url) else: return HttpResponseBadRequest("<h1>Bad Request</h1>") else: return HttpResponseBadRequest("<h1>Bad Request</h1>") attrs = {} if saml_session: attrs, _ = saml.parse_attributes(request) saml_session = True person = None if request.user.is_authenticated: person = request.user return render( template_name='karaage/people/profile_saml.html', context={ 'attrs': attrs, 'saml_session': saml_session, 'person': person, }, request=request)
def saml_login(request): redirect_to = reverse('index') if 'next' in request.GET: redirect_to = request.GET['next'] error = None saml_session = saml.is_saml_session(request) form = saml.SAMLInstituteForm(request.POST or None) if request.method == 'POST': if 'login' in request.POST and form.is_valid(): institute = form.cleaned_data['institute'] url = saml.build_shib_url( request, redirect_to, institute.saml_entityid) return HttpResponseRedirect(url) elif 'logout' in request.POST: if saml_session: url = saml.logout_url(request) return HttpResponseRedirect(url) else: return HttpResponseBadRequest("<h1>Bad Request</h1>") else: return HttpResponseBadRequest("<h1>Bad Request</h1>") elif request.user.is_authenticated(): error = "You are already logged in." elif saml_session: attrs, error = saml.parse_attributes(request) saml_id = attrs['persistent_id'] try: Person.objects.get(saml_id=saml_id) # This should not happen, suggests a fault in the saml middleware error = "Shibboleth session established " \ "but you did not get logged in. " except Person.DoesNotExist: email = attrs['email'] try: Person.objects.get(email=email) error = "Cannot log in with this shibboleth account. " \ "Please try using the Karaage login instead." except Person.DoesNotExist: if apps.is_installed("karaage.plugins.kgapplications"): app_url = reverse('kg_application_new') return HttpResponseRedirect(app_url) else: error = "Cannot log in with shibboleth as " \ "we do not recognise your shibboleth id." return render( template_name='karaage/people/profile_login_saml.html', context={'form': form, 'error': error, 'saml_session': saml_session, }, request=request)
def _get_applicant_from_saml(request): attrs, _ = saml.parse_attributes(request) saml_id = attrs['persistent_id'] try: return Person.objects.get(saml_id=saml_id) except Person.DoesNotExist: pass try: return Applicant.objects.get(saml_id=saml_id) except Applicant.DoesNotExist: pass return None
def process_request(self, request): # AuthenticationMiddleware is required so that request.user exists. if not hasattr(request, 'user'): raise ImproperlyConfigured( "The Django SAML user auth middleware requires the" " authentication middleware to be installed. Edit your" " MIDDLEWARE_CLASSES setting to insert" " 'django.contrib.auth.middleware.AuthenticationMiddleware'" " before the SamlUserMiddleware class.") # If the user is already authenticated and that user is the user we are # getting passed in the headers, then the correct user is already # persisted in the session and we don't need to continue. if request.user.is_authenticated: return # Is this a shib session? if not saml.is_saml_session(request): return # Can we get the shib attributes we need? attrs, error = saml.parse_attributes(request) if error: return render(template_name='saml_error.html', context={'shib_attrs': attrs}, request=request) # What is our persistent_id? saml_id = attrs['persistent_id'] assert saml_id # We are seeing this user for the first time in this session, attempt # to authenticate the user. try: person = Person.objects.get(saml_id=saml_id) except Person.DoesNotExist: return # User is valid. Set request.user and persist user in the session # by logging the user in. request.user = person # We must set the model backend here manually as we skip # the call to auth.authenticate(). request.user.backend = 'django.contrib.auth.backends.ModelBackend' auth.login(request, person)
def saml_login(request): redirect_to = reverse('kg_profile_login_saml') if 'next' in request.REQUEST: redirect_to = request.REQUEST['next'] error = None saml_session = saml.is_saml_session(request) form = saml.SAMLInstituteForm(request.POST or None) if request.method == 'POST': if 'login' in request.POST and form.is_valid(): institute = form.cleaned_data['institute'] url = saml.build_shib_url( request, redirect_to, institute.saml_entityid) return HttpResponseRedirect(url) elif 'logout' in request.POST: if saml_session: url = saml.logout_url(request) return HttpResponseRedirect(url) else: return HttpResponseBadRequest("<h1>Bad Request</h1>") else: return HttpResponseBadRequest("<h1>Bad Request</h1>") elif request.user.is_authenticated(): # JH fix the bug return HttpResponseRedirect(redirect_to) # error = "You are already logged in." elif saml_session: attrs, error = saml.parse_attributes(request) saml_id = attrs['persistent_id'] try: Person.objects.get(saml_id=saml_id) error = "Shibboleth session established " \ "but you did not get logged in." except Person.DoesNotExist: error = "Cannot log in with shibboleth as " \ "we do not know your shibboleth id." return render_to_response( 'karaage/people/profile_login_saml.html', {'form': form, 'error': error, 'saml_session': saml_session, }, context_instance=RequestContext(request))
def view(self, request, application, label, auth, actions): """ Process the view request at the current step. """ # if user is logged and and not applicant, steal the # application if auth['is_applicant']: # if we got this far, then we either we are logged in as applicant, or # we know the secret for this application. new_person = None attrs, _ = saml.parse_attributes(request) saml_id = attrs['persistent_id'] if saml_id is not None: query = Person.objects.filter(saml_id=saml_id) if query.content_type.model == "person": query = query.exclude(pk=application.applicant.pk) if query.count() > 0: new_person = Person.objects.get(saml_id=saml_id) reason = "SAML id is already in use by existing person." details = ("It is not possible to continue this application " + "as is because the saml identity already exists " + "as a registered user.") del query if request.user.is_authenticated(): new_person = request.user reason = "%s was logged in and accessed the secret URL." % new_person details = ("If you want to access this application "+ "as %s " % application.applicant + "without %s stealing it, " % new_person + "you will have to ensure %s is " % new_person + "logged out first.") if new_person is not None: if application.applicant != new_person: if 'steal' in request.POST: old_applicant = application.applicant application.applicant = new_person application.save() log(request.user, application.application_ptr, 1, "Stolen application from %s", old_applicant) messages.success( request, "Stolen application from %s", old_applicant) url = base.get_url(request, application, auth, label) return HttpResponseRedirect(url) else: return render_to_response( 'applications/project_aed_steal.html', {'application': application, 'person': new_person, 'reason': reason, 'details': details, }, context_instance=RequestContext(request)) # if the user is the leader, show him the leader specific page. if (auth['is_leader'] or auth['is_delegate']) and not auth['is_admin'] and not auth['is_applicant']: actions = ['reopen'] if 'reopen' in request.POST: return 'reopen' return render_to_response( 'applications/project_aed_for_leader.html', {'application': application, 'actions': actions, 'auth': auth, }, context_instance=RequestContext(request)) # otherwise do the default behaviour for StateWithSteps return super(StateApplicantEnteringDetails, self).view(request, application, label, auth, actions)
def view(self, request, application, label, auth, actions): """ Django view method. """ status = None applicant = application.applicant attrs = [] saml_session = saml.is_saml_session(request) # certain actions are supported regardless of what else happens if 'cancel' in request.POST: return "cancel" if 'prev' in request.POST: return 'prev' # test for conditions where shibboleth registration not required if applicant.saml_id is not None: status = "You have already registered a shibboleth id." form = None done = True elif application.content_type.model != 'applicant': status = "You are already registered in the system." form = None done = True elif (applicant.institute is not None and applicant.institute.saml_entityid is None): status = "Your institute does not have shibboleth registered." form = None done = True elif Institute.objects.filter(saml_entityid__isnull=False).count() == 0: status = "No institutes support shibboleth here." form = None done = True else: # shibboleth registration is required # Do construct the form form = saml.SAMLInstituteForm(request.POST or None, initial = {'institute': applicant.institute}) done = False status = None # Was it a POST request? if request.method == 'POST': # Did the login form get posted? if 'login' in request.POST and form.is_valid(): institute = form.cleaned_data['institute'] applicant.institute = institute applicant.save() # We do not set application.insitute here, that happens # when application, if it is a ProjectApplication, is # submitted # if institute supports shibboleth, redirect back here via # shibboleth, otherwise redirect directly back he. url = base.get_url(request, application, auth, label) if institute.saml_entityid is not None: url = saml.build_shib_url( request, url, institute.saml_entityid) return HttpResponseRedirect(url) # Did we get a register request? elif 'register' in request.POST: if saml_session: applicant = _get_applicant_from_saml(request) if applicant is not None: application.applicant = applicant application.save() else: applicant = application.applicant applicant = saml.add_saml_data( applicant, request) applicant.save() url = base.get_url(request, application, auth, label) return HttpResponseRedirect(url) else: return HttpResponseBadRequest("<h1>Bad Request</h1>") # Did we get a logout request? elif 'logout' in request.POST: if saml_session: url = saml.logout_url(request) return HttpResponseRedirect(url) else: return HttpResponseBadRequest("<h1>Bad Request</h1>") # did we get a shib session yet? if saml_session: attrs, _ = saml.parse_attributes(request) saml_session = True # if we are done, we can proceed to next state if request.method == 'POST': if done: for action in actions: if action in request.POST: return action return HttpResponseBadRequest("<h1>Bad Request</h1>") else: status = "Please register with Shibboleth before proceeding." # render the page return render_to_response( 'applications/project_aed_shibboleth.html', {'form': form, 'done': done, 'status': status, 'actions': actions, 'auth': auth, 'application': application, 'attrs': attrs, 'saml_session': saml_session,}, context_instance=RequestContext(request))
def view(self, request, application, label, roles, actions): """ Process the view request at the current step. """ # if user is logged and and not applicant, steal the # application if 'is_applicant' in roles: # if we got this far, then we either we are logged in as applicant, # or we know the secret for this application. new_person = None attrs, _ = saml.parse_attributes(request) saml_id = attrs['persistent_id'] if saml_id is not None: query = Person.objects.filter(saml_id=saml_id) if application.content_type.model == "person": query = query.exclude(pk=application.applicant.pk) if query.count() > 0: new_person = Person.objects.get(saml_id=saml_id) reason = "SAML id is already in use by existing person." details = ( "It is not possible to continue this application " + "as is because the saml identity already exists " + "as a registered user.") del query if request.user.is_authenticated(): new_person = request.user reason = "%s was logged in " \ "and accessed the secret URL." % new_person details = ("If you want to access this application " + "as %s " % application.applicant + "without %s stealing it, " % new_person + "you will have to ensure %s is " % new_person + "logged out first.") if new_person is not None: if application.applicant != new_person: if 'steal' in request.POST: old_applicant = application.applicant application.applicant = new_person application.save() log.change( application.application_ptr, "Stolen application from %s" % old_applicant) messages.success( request, "Stolen application from %s" % old_applicant) url = base.get_url(request, application, roles, label) return HttpResponseRedirect(url) else: return render_to_response( 'kgapplications/project_aed_steal.html', { 'application': application, 'person': new_person, 'reason': reason, 'details': details, }, context_instance=RequestContext(request)) # if the user is the leader, show him the leader specific page. if ('is_leader' in roles or 'is_delegate' in roles) \ and 'is_admin' not in roles \ and 'is_applicant' not in roles: actions = ['reopen'] if 'reopen' in request.POST: return 'reopen' return render_to_response( 'kgapplications/project_aed_for_leader.html', { 'application': application, 'actions': actions, 'roles': roles, }, context_instance=RequestContext(request)) # otherwise do the default behaviour for StateWithSteps return super(StateApplicantEnteringDetails, self) \ .view(request, application, label, roles, actions)
def view(self, request, application, label, roles, actions): """ Django view method. """ status = None applicant = application.applicant attrs = [] saml_session = saml.is_saml_session(request) # certain actions are supported regardless of what else happens if 'cancel' in request.POST: return "cancel" if 'prev' in request.POST: return 'prev' # test for conditions where shibboleth registration not required if applicant.saml_id is not None: status = "You have already registered a shibboleth id." form = None done = True elif application.content_type.model != 'applicant': status = "You are already registered in the system." form = None done = True elif (applicant.institute is not None and applicant.institute.saml_entityid is None): status = "Your institute does not have shibboleth registered." form = None done = True elif Institute.objects.filter( saml_entityid__isnull=False).count() == 0: status = "No institutes support shibboleth here." form = None done = True else: # shibboleth registration is required # Do construct the form form = saml.SAMLInstituteForm( request.POST or None, initial={'institute': applicant.institute}) done = False status = None # Was it a POST request? if request.method == 'POST': # Did the login form get posted? if 'login' in request.POST and form.is_valid(): institute = form.cleaned_data['institute'] applicant.institute = institute applicant.save() # We do not set application.insitute here, that happens # when application, if it is a ProjectApplication, is # submitted # if institute supports shibboleth, redirect back here via # shibboleth, otherwise redirect directly back he. url = base.get_url(request, application, roles, label) if institute.saml_entityid is not None: url = saml.build_shib_url(request, url, institute.saml_entityid) return HttpResponseRedirect(url) # Did we get a register request? elif 'register' in request.POST: if saml_session: applicant = _get_applicant_from_saml(request) if applicant is not None: application.applicant = applicant application.save() else: applicant = application.applicant applicant = saml.add_saml_data(applicant, request) applicant.save() url = base.get_url(request, application, roles, label) return HttpResponseRedirect(url) else: return HttpResponseBadRequest("<h1>Bad Request</h1>") # Did we get a logout request? elif 'logout' in request.POST: if saml_session: url = saml.logout_url(request) return HttpResponseRedirect(url) else: return HttpResponseBadRequest("<h1>Bad Request</h1>") # did we get a shib session yet? if saml_session: attrs, _ = saml.parse_attributes(request) saml_session = True # if we are done, we can proceed to next state if request.method == 'POST': if done: for action in actions: if action in request.POST: return action return HttpResponseBadRequest("<h1>Bad Request</h1>") else: status = "Please register with Shibboleth before proceeding." # render the page return render_to_response('kgapplications/project_aed_shibboleth.html', { 'form': form, 'done': done, 'status': status, 'actions': actions, 'roles': roles, 'application': application, 'attrs': attrs, 'saml_session': saml_session, }, context_instance=RequestContext(request))
def view(self, request, application, label, roles, actions): """ Process the view request at the current step. """ # if user is logged and and not applicant, steal the # application if "is_applicant" in roles: # if we got this far, then we either we are logged in as applicant, # or we know the secret for this application. new_person = None attrs, _ = saml.parse_attributes(request) saml_id = attrs["persistent_id"] if saml_id is not None: query = Person.objects.filter(saml_id=saml_id) if application.content_type.model == "person": query = query.exclude(pk=application.applicant.pk) if query.count() > 0: new_person = Person.objects.get(saml_id=saml_id) reason = "SAML id is already in use by existing person." details = ( "It is not possible to continue this application " + "as is because the saml identity already exists " + "as a registered user." ) del query if request.user.is_authenticated(): new_person = request.user reason = "%s was logged in " "and accessed the secret URL." % new_person details = ( "If you want to access this application " + "as %s " % application.applicant + "without %s stealing it, " % new_person + "you will have to ensure %s is " % new_person + "logged out first." ) if new_person is not None: if application.applicant != new_person: if "steal" in request.POST: old_applicant = application.applicant application.applicant = new_person application.save() log.change(application.application_ptr, "Stolen application from %s" % old_applicant) messages.success(request, "Stolen application from %s" % old_applicant) url = base.get_url(request, application, roles, label) return HttpResponseRedirect(url) else: return render_to_response( "kgapplications/project_aed_steal.html", {"application": application, "person": new_person, "reason": reason, "details": details}, context_instance=RequestContext(request), ) # if the user is the leader, show him the leader specific page. if ("is_leader" in roles or "is_delegate" in roles) and "is_admin" not in roles and "is_applicant" not in roles: actions = ["reopen"] if "reopen" in request.POST: return "reopen" return render_to_response( "kgapplications/project_aed_for_leader.html", {"application": application, "actions": actions, "roles": roles}, context_instance=RequestContext(request), ) # otherwise do the default behaviour for StateWithSteps return super(StateApplicantEnteringDetails, self).view(request, application, label, roles, actions)
def new_application(request): """ A new application by a user to start a new project. """ # Note default kgapplications/index.html will display error if user logged # in. if not settings.ALLOW_REGISTRATIONS: return render( template_name='kgapplications/project_common_disabled.html', context={}, request=request) roles = {'is_applicant', 'is_authorised'} if not request.user.is_authenticated: attrs, _ = saml.parse_attributes(request) defaults = {'email': attrs['email']} form = forms.UnauthenticatedInviteUserApplicationForm(request.POST or None, initial=defaults) if request.method == 'POST': if form.is_valid(): email = form.cleaned_data['email'] applicant, existing_person = get_applicant_from_email(email) # If applicant is None then there were multiple persons found. # This should never happen as the # UnauthenticatedInviteUserApplicationForm form disallows # existing users applying unauthenticated. assert applicant is not None # Similarly existing_person should always be False here. assert not existing_person application = ProjectApplication() application.applicant = applicant application.save() state_machine = get_application_state_machine() state_machine.start(request, application, roles) # we do not show unauthenticated users the application at this # stage. url = reverse('index') return HttpResponseRedirect(url) return render(template_name='kgapplications/' 'project_common_invite_unauthenticated.html', context={ 'form': form, }, request=request) else: if request.method == 'POST': person = request.user application = ProjectApplication() application.applicant = person application.save() state_machine = get_application_state_machine() response = state_machine.start(request, application, roles) return response return render(template_name='kgapplications/' 'project_common_invite_authenticated.html', context={}, request=request)