text: import requests
  import json
  import os
  import os.path
  import urllib
  import xmltodict
  
  from django.apps import apps
  from django.conf import settings
  from django.http import (HttpResponse, HttpResponseRedirect, HttpResponseServerError)
  from django.shortcuts import redirect, render
  from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie
  from onelogin.saml2.auth import OneLogin_Saml2_Auth
  from onelogin.saml2.idp_metadata_parser import OneLogin_Saml2_IdPMetadataParser
  from onelogin.saml2.settings import OneLogin_Saml2_Settings
  from onelogin.saml2.utils import OneLogin_Saml2_Utils
  
  from catalog.models import *
  from opal.settings import USER_APPS
  from ssp.models import *
  from .functions import search_for_uuid, convert_xml_to_json
  
  # Create your views here.
  
  logger = logging.getLogger('django')
  
  # Override the method in OneLogin_Saml2_Auth to disable compresion
  from onelogin.saml2.authn_request import OneLogin_Saml2_Authn_Request
  
  
  class MAXLogin_Saml2_Authn_Request(OneLogin_Saml2_Authn_Request):
      def get_request(self, deflate=False):
          """
          Returns unsigned AuthnRequest.
          :param deflate: It makes the deflate process optional
          :type: bool
          :return: AuthnRequest maybe deflated and base64 encoded
          :rtype: str object
          """
          logger.info("Checkin to see if compresion is required...")
          if deflate:
              logger.info("compresion required")
              request = OneLogin_Saml2_Utils.deflate_and_base64_encode(self._authn_request)
          else:
              logger.info("nope, it isn't")
              request = OneLogin_Saml2_Utils.b64encode(self._authn_request)
          return request
  
  
  class MaxLogin_SAML2_Auth(OneLogin_Saml2_Auth):
      authn_request_class = MAXLogin_Saml2_Authn_Request
  
      def login(self,
                return_to=None,
                force_authn=False,
                is_passive=False,
                set_nameid_policy=True,
                name_id_value_req=None):
          """
          Initiates the SSO process.
          :param return_to: Optional argument. The target URL the user should be redirected to after login.
          :type return_to: string
          :param force_authn: Optional argument. When true the AuthNRequest will set the ForceAuthn='true'.
          :type force_authn: bool
          :param is_passive: Optional argument. When true the AuthNRequest will set the Ispassive='true'.
          :type is_passive: bool
          :param set_nameid_policy: Optional argument. When true the AuthNRequest will set a nameIdPolicy element.
          :type set_nameid_policy: bool
          :param name_id_value_req: Optional argument. Indicates to the IdP the subject that should be authenticated
          :type name_id_value_req: string
          :returns: Redirection URL
          :rtype: string
          """
          authn_request = self.authn_request_class(self._settings, force_authn, is_passive, set_nameid_policy,
                                                   name_id_value_req)
          self._last_request = authn_request.get_xml()
          self._last_request_id = authn_request.get_id()
  
          saml_request = authn_request.get_request(deflate=False)
          parameters = {'SAMLRequest': saml_request}
  
          if return_to is not None:
              parameters['RelayState'] = return_to
          else:
              parameters['RelayState'] = OneLogin_Saml2_Utils.get_self_url_no_query(self._request_data)
  
          security = self._settings.get_security_data()
          if security.get('authnRequestsSigned', False):
              self.add_request_signature(parameters, security['signatureAlgorithm'])
          requests.post(self.get_sso_url(), data=parameters)
          return self.redirect_to(self.get_sso_url(), parameters)
  
  
  available_catalog_list = [{
      "uuid": "6643738e-4b28-436d-899f-704d88c91f5e", "slug": "nist_sp_800_53_rev_5_high_baseline",
      "name": "NIST SP-800 53 rev5 HIGH baseline",
      "link": "https://raw.githubusercontent.com/usnistgov/oscal-content/main/nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_HIGH-baseline-resolved-profile_catalog-min.json"
  }, {
      "uuid": "36ade4b6-3e50-4899-b955-9d4a95407c38", "slug": "nist_sp_800_53_rev_5_moderate_baseline",
      "name": "NIST SP-800 53 rev5 MODERATE baseline",
      "link": "https://raw.githubusercontent.com/usnistgov/oscal-content/main/nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_MODERATE-baseline-resolved-profile_catalog-min.json"
  }, {
      "uuid": "0186ce03-126b-49dd-959f-2fa94059ddd2", "slug": "nist_sp_800_53_rev_5_low_baseline",
      "name": "NIST SP-800 53 rev5 LOW baseline",
      "link": "https://raw.githubusercontent.com/usnistgov/oscal-content/main/nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_LOW-baseline-resolved-profile_catalog-min.json"
  }, {
      "uuid": "7401e6d3-dec9-4a5b-86dc-309df4519e36", "slug": "nist_sp_800_53_rev_5_privacy_baseline",
      "name": "NIST SP-800 53 rev5 PRIVACY baseline",
      "link": "https://raw.githubusercontent.com/usnistgov/oscal-content/main/nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_PRIVACY-baseline-resolved-profile_catalog-min.json"
  }, {
      "uuid": "61787e85-adaf-4951-8d16-91f6e0b331bb", "slug": "fed_ramp_rev_4_high_baseline_resolved_profile_catalog",
      "name": "FedRAMP Rev 4 HIGH Baseline",
      "link": "https://raw.githubusercontent.com/GSA/fedramp-automation/master/dist/content/baselines/rev4/json/FedRAMP_rev4_HIGH-baseline-resolved-profile_catalog-min.json"
  }, {
      "uuid": "0f9fcab5-995f-412f-8954-49526e1cc80a", "slug": "fed_ramp_rev_4_low_baseline_resolved_profile_catalog_min",
      "name": "FedRAMP Rev 4 LOW Baseline",
      "link": "https://raw.githubusercontent.com/GSA/fedramp-automation/master/dist/content/baselines/rev4/json/FedRAMP_rev4_LOW-baseline-resolved-profile_catalog-min.json"
  }, {
      "uuid": "8bf9a86c-66e9-4757-830c-87c0df2fb821",
      "slug": "fed_ramp_rev_4_moderate_baseline_resolved_profile_catalog_min", "name": "FedRAMP Rev 4 MODERATE Baseline",
      "link": "https://raw.githubusercontent.com/GSA/fedramp-automation/master/dist/content/baselines/rev4/json/FedRAMP_rev4_MODERATE-baseline-resolved-profile_catalog-min.json"
  }, {
      "uuid": "9a740e35-422f-48e2-baca-0b0c515997d1", "slug": "nist_sp_800_53_rev_4_low",
      "name": "Nist SP 800 53 Rev 4 LOW",
      "link": "https://raw.githubusercontent.com/usnistgov/oscal-content/main/nist.gov/SP800-53/rev4/json/NIST_SP-800-53_rev4_LOW-baseline-resolved-profile_catalog-min.json"
  }, {
      "uuid": "be314319-466e-459b-b736-631bd84e3cd7", "slug": "nist_sp_800_53_rev_4_moderate",
      "name": "Nist SP 800 53 Rev 4 MODERATE",
      "link": "https://raw.githubusercontent.com/usnistgov/oscal-content/main/nist.gov/SP800-53/rev4/json/NIST_SP-800-53_rev4_MODERATE-baseline-resolved-profile_catalog-min.json"
  }, {
      "uuid": "8f1b188b-5315-4c4d-a95a-1917f3cd5a62", "slug": "nist_sp_800_53_rev_4_high",
      "name": "Nist SP 800 53 Rev 4 High",
      "link": "https://raw.githubusercontent.com/usnistgov/oscal-content/main/nist.gov/SP800-53/rev4/json/NIST_SP-800-53_rev4_HIGH-baseline-resolved-profile_catalog-min.json"
  }, ]
  
  
  @ensure_csrf_cookie
  def index_view(request):
      catalog_list_html_str = ""
  
      for item in available_catalog_list:
          catalog_list_html_str += "<li><a href='"
          catalog_list_html_str += reverse('catalog:import_catalog_view', kwargs={'catalog_link': item['slug']})
          catalog_list_html_str += "'>" + item['name'] + "</a>"
          if catalogs.objects.filter(uuid=item['uuid']).exists():
              catalog_list_html_str += "&#9989;"
          catalog_list_html_str += "</li>"
  
      ssp_file_str = urllib.parse.quote_plus('ssp-example.json')
      ssp_sample_import_link = reverse('ssp:import_ssp_view', kwargs={'ssp_file': ssp_file_str})
  
      context = {
          "catalog_list": catalog_list_html_str, "ssp_sample_import_link": ssp_sample_import_link
      }
      # And so on for more models
      return render(request, "index.html", context)
  
  
  @ensure_csrf_cookie
  def authentication_view(request):
      from opal.settings import ENABLE_OIDC, ENABLE_SAML
  
      html_str = ""
      form_list = []
  
      if request.user.is_authenticated:
          html_str += "<h2>Welcome %s</h2>" % request.user.get_full_name()
      else:
          if ENABLE_OIDC:
              html_str += "<h2>OIDC Enabled</h2>"
              html_str += "<a href='%s'>Login using OIDC</a>" % settings.OIDC_OP_LOGIN_REDIRECT_URL
  
          if ENABLE_SAML:
              html_str += "<h2>SAML Enabled</h2>"
              html_str += "<a href='%s'>Login using SAML</a>" % reverse('common:saml_authentication')
  
      context = {
          "content": html_str, "title": "OPAL Authentication Options"
      }
  
      return render(request, "generic_template.html", context)
  
  
  from django import forms
  
  
  def saml_login_button(self,
                        return_to=None,
                        force_authn=False,
                        is_passive=False,
                        set_nameid_policy=True,
                        name_id_value_req=None):
      authn_request = self.authn_request_class(self._settings, force_authn, is_passive, set_nameid_policy,
                                                   name_id_value_req)
      self._last_request = authn_request.get_xml()
      self._last_request_id = authn_request.get_id()
  
      saml_request = authn_request.get_request(deflate=False)
      parameters = {'SAMLRequest': saml_request}
  
      if return_to is not None:
          parameters['RelayState'] = return_to
      else:
          parameters['RelayState'] = OneLogin_Saml2_Utils.get_self_url_no_query(self._request_data)
  
      security = self._settings.get_security_data()
      if security.get('authnRequestsSigned', False):
          self.add_request_signature(parameters, security['signatureAlgorithm'])
  
      f = forms.Form
      for key, value in parameters:
          f.fields
  
  
      return self.redirect_to(self.get_sso_url(), parameters)
  
  
  def init_saml_auth(request):
      settings_dict = get_saml_metadata(request)
      # saml_settings = OneLogin_Saml2_Settings(settings_dict)
      auth = MaxLogin_SAML2_Auth(request, old_settings=settings_dict)
      return auth
  
  
  def prepare_django_request(request):
      # If server is behind proxys or balancers use the HTTP_X_FORWARDED fields
      if 'HTTP_HOST' in request.META:
          http_host = request.META['HTTP_HOST']
      else:
          http_host = get_host_name(request)
      result = {
          'https': 'on' if request.is_secure() else 'off',
          'http_host': http_host,
          'script_name': request.META['PATH_INFO'],
          'get_data': request.GET.copy(),
          # Uncomment if using ADFS as IdP, https://github.com/onelogin/python-saml/pull/144
          # 'lowercase_urlencoding': True,
          'post_data': request.POST.copy()
      }
      logger.info(result)
      return result
  
  
  def attrs(request):
      paint_logout = False
      attributes = False
  
      if 'samlUserdata' in request.session:
          paint_logout = True
          if len(request.session['samlUserdata']) > 0:
              attributes = request.session['samlUserdata'].items()
      return render(
          request, 'saml/attrs.html', {
              'paint_logout': paint_logout, 'attributes': attributes
          }
      )
  
  
  @csrf_exempt
  def saml_authentication(request):
      req = prepare_django_request(request)
      auth = init_saml_auth(request)
      errors = []
      error_reason = None
      not_auth_warn = False
      success_slo = False
      attributes = False
      paint_logout = False
  
      if 'sso' in req['get_data']:
          return HttpResponseRedirect(auth.login(return_to=get_host_name(request)))
          # If AuthNRequest ID need to be stored in order to later validate it, do instead  # sso_built_url = auth.login()
          # request.session['AuthNRequestID'] = auth.get_last_request_id()  # return HttpResponseRedirect(sso_built_url)
      elif 'sso2' in req['get_data']:
          return_to = OneLogin_Saml2_Utils.get_self_url(req) + reverse('common:attrs')
          return HttpResponseRedirect(auth.login(return_to))
      elif 'slo' in req['get_data']:
          name_id = session_index = name_id_format = name_id_nq = name_id_spnq = None
          if 'samlNameId' in request.session:
              name_id = request.session['samlNameId']
          if 'samlSessionIndex' in request.session:
              session_index = request.session['samlSessionIndex']
          if 'samlNameIdFormat' in request.session:
              name_id_format = request.session['samlNameIdFormat']
          if 'samlNameIdNameQualifier' in request.session:
              name_id_nq = request.session['samlNameIdNameQualifier']
          if 'samlNameIdSPNameQualifier' in request.session:
              name_id_spnq = request.session['samlNameIdSPNameQualifier']
  
          return HttpResponseRedirect(
              auth.logout(
                  name_id=name_id, session_index=session_index, nq=name_id_nq, name_id_format=name_id_format,
                  spnq=name_id_spnq
              )
          )
          # If LogoutRequest ID need to be stored in order to later validate it, do instead
          # slo_built_url = auth.logout(name_id=name_id, session_index=session_index)
          # request.session['LogoutRequestID'] = auth.get_last_request_id()
          # return HttpResponseRedirect(slo_built_url)
      elif 'acs' in req['get_data']:
          request_id = None
          if 'AuthNRequestID' in request.session:
              request_id = request.session['AuthNRequestID']
  
          auth.process_response(request_id=request_id)
          errors = auth.get_errors()
          not_auth_warn = not auth.is_authenticated()
  
          if not errors:
              if 'AuthNRequestID' in request.session:
                  del request.session['AuthNRequestID']
              request.session['samlUserdata'] = auth.get_attributes()
              request.session['samlNameId'] = auth.get_nameid()
              request.session['samlNameIdFormat'] = auth.get_nameid_format()
              request.session['samlNameIdNameQualifier'] = auth.get_nameid_nq()
              request.session['samlNameIdSPNameQualifier'] = auth.get_nameid_spnq()
              request.session['samlSessionIndex'] = auth.get_session_index()
              if 'RelayState' in req['post_data'] and OneLogin_Saml2_Utils.get_self_url(req) != req['post_data'][
                  'RelayState']:
                  # To avoid 'Open Redirect' attacks, before execute the redirection confirm
                  # the value of the req['post_data']['RelayState'] is a trusted URL.
                  return HttpResponseRedirect(auth.redirect_to(req['post_data']['RelayState']))
          elif auth.get_settings().is_debug_active():
              error_reason = auth.get_last_error_reason()
      elif 'sls' in req['get_data']:
          request_id = None
          if 'LogoutRequestID' in request.session:
              request_id = request.session['LogoutRequestID']
          dscb = lambda: request.session.flush()
          url = auth.process_slo(request_id=request_id, delete_session_cb=dscb)
          errors = auth.get_errors()
          if len(errors) == 0:
              if url is not None:
                  # To avoid 'Open Redirect' attacks, before execute the redirection confirm
                  # the value of the url is a trusted URL
                  return HttpResponseRedirect(url)
              else:
                  success_slo = True
          elif auth.get_settings().is_debug_active():
              error_reason = auth.get_last_error_reason()
  
      if 'samlUserdata' in request.session:
          paint_logout = True
          if len(request.session['samlUserdata']) > 0:
              attributes = request.session['samlUserdata'].items()
  
      return render(
          request, 'saml/saml_authentication.html', {
              'errors': errors, 'error_reason': error_reason, 'not_auth_warn': not_auth_warn, 'success_slo': success_slo,
              'attributes': attributes, 'paint_logout': paint_logout
          }
      )
  
  
  def metadata(request):
      # req = prepare_django_request(request)
      # auth = init_saml_auth(req)
      # saml_settings = auth.get_settings()
  
      settings_dict = get_saml_metadata(request)
  
      saml_settings = OneLogin_Saml2_Settings(
          settings=settings_dict, sp_validation_only=True
      )
      metadata_xml = saml_settings.get_sp_metadata()
      errors = saml_settings.validate_metadata(metadata_xml)
  
      if len(errors) == 0:
          resp = HttpResponse(content=metadata_xml, content_type='text/xml')
      else:
          resp = HttpResponseServerError(content=', '.join(errors))
      return resp
  
  
  def get_saml_metadata(request):
      filename = os.path.join(settings.SAML_FOLDER, settings.SAML_SETTINGS_JSON)
      host_name = get_host_name(request)
      with open(filename, 'r') as json_data:
          sp_settings_dict = json.loads(json_data.read())
      sp_settings_dict['sp']['entityId'] = host_name + '/common/saml/metadata'
      sp_settings_dict['sp']['assertionConsumerService']['url'] = host_name + '/common/saml/?acs'
      sp_settings_dict['sp']['singleLogoutService']['url'] = host_name + '/common/saml/?sls'
      if settings.SAML_TECHNICAL_POC:
          sp_settings_dict['contactPerson'] = {
              'technical': {'givenName': settings.SAML_TECHNICAL_POC, 'emailAddress': settings.SAML_TECHNICAL_POC_EMAIL}
          }
      if settings.SAML_TECHNICAL_POC:
          sp_settings_dict['contactPerson'] = {
              'support': {'givenName': settings.SAML_SUPPORT_POC, 'emailAddress': settings.SAML_SUPPORT_POC_EMAIL}
          }
      sp_settings_dict['organization']['en-US']['url'] = host_name
  
      # Add IDP sections
      proxies = {}
      if settings.HTTP_PROXY:
          proxies['http'] = settings.HTTP_PROXY
      if settings.HTTPS_PROXY:
          proxies['https'] = settings.HTTPS_PROXY
  
      # from onelogin.saml2.idp_metadata_parser import OneLogin_Saml2_IdPMetadataParser
      metadata_parser = OneLogin_Saml2_IdPMetadataParser()
      max_idp_metadata_dict = metadata_parser.parse_remote('https://login.max.gov/idp/shibboleth')
      settings_dict = metadata_parser.merge_settings(sp_settings_dict, max_idp_metadata_dict)
  
      # max_idp_metadata = requests.get('https://login.max.gov/idp/shibboleth', proxies=proxies).text
      #
      # import xml.etree.ElementTree as ET
      #
      # root = ET.fromstring(max_idp_metadata)
      #
      # ns = {
      #     "": "urn:oasis:names:tc:SAML:2.0:metadata",
      #     "ds": "http://www.w3.org/2000/09/xmldsig#",
      #     "shibmd": "urn:mace:shibboleth:metadata:1.0",
      #     "xsi": "http://www.w3.org/2001/XMLSchema-instance"
      #     }
      #
      # settings_dict['idp'] = {
      #     "entityId": root.attrib['entityID'],
      #     "x509cert": root.find(".//ds:X509Certificate", ns).text
      #     }
      #
      # service_list = []
      # for e in root[0].findall("{urn:oasis:names:tc:SAML:2.0:metadata}SingleSignOnService"):
      #     # if e.attrib['Binding'] == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect':
      #     service_list.append({"binding": e.attrib['Binding'], "url": e.attrib['Location']})
      # settings_dict['idp']["singleSignOnService"] = service_list
  
      return settings_dict
  
  
  def get_host_name(request):
      if request.is_secure():
          host_name = "https://"
      else:
          host_name = "http://"
      host_name += request.get_host()
      logger.info("Got host: " + host_name)
      return host_name
  
  
  def database_status_view(request):
      model_list = []
      for a in USER_APPS:
          app_models = apps.get_app_config(a).get_models()
          for m in app_models:
              if m.objects.count() > 0:
                  s = m.__name__ + ":" + str(m.objects.count())
                  model_list.append(s)
      model_list.sort()
      context = {"model_list": model_list}
      return render(request, "db_status.html", context)
  
  
  def permalink(request, p_uuid):
      redirect_url = "error_404_view"
      obj = search_for_uuid(p_uuid)
      try:
          redirect_url = obj.get_absolute_url()
      except AttributeError as e:
          err_msg = e
      return redirect(to=redirect_url)
  
  
  def error_404_view(request, exception):
      template_name = "404.html"
      context_object_name = "obj"
  