Angular Modified Bootstrap UI dialog in $ http interceptor hangs browser

I am trying to implement lazy authorization which will only bring up a login dialog when the user makes a call to an API that requires authentication. I am using bootstrap ui.bootstrap.modal (and ui.bootstrap. Warning within modal). The problem is that these directives explicitly state the following teamplateUrl

:

  • template / modal / backdrop.html (in modal.js

    here )
  • template / modal / window.html (in modal.js

    here )
  • template / alert / alert.html (in alert.js

    here )

like this:

.directive('modalBackdrop', ['$timeout', function ($timeout) {
  return {
    restrict: 'EA',
    replace: true,
    templateUrl: 'template/modal/backdrop.html',
    link: function (scope, element, attrs) {
      /* ... */
    }
  };
}])

      

And every time I call $modal.open()

and ui-bootstrap creates a DOM for a new modal, angular tries to resolve these urls through the service $http

even if the templates are already loaded either $templateCache.put

or by adding a tag <script>

. This is basically causing infinite recursion in my interceptor trying to enter the login dialog into the request

overload for the URLs above.

Here's a simplified version of my interceptor:

.config(['$provide', '$httpProvider', function($provide, $httpProvider) {
    $provide.factory('testInterceptor', ['$injector', function($injector) {
        return {
        'request': function(config) {

            var auth = $injector.get('authService');
            var modal = $injector.get('$modal');
            if (!auth.LoggedIn) {
              var loginModal = modal.open({
                  template: 'Login screen <alert type="warning">some message</alert>',
              });
              return loginModal.result;
            }
            return config;
          }
}}]);

      

Working demo here

Can anyone suggest an approach that doesn't involve hardcoding the templates used in ui.bootstrap.modal

and out ui.bootstrap.alert

?

I also reported this as an issue on github.

+3


source to share


2 answers


An easy workaround for this is to not force authentication on requests to any URL starting with template/

. For example:

      $provide.factory('testIntercepter', ['$q', '$injector',
        function($q, $injector) {
          return {
            'request': function(config) {
              if (config.url.indexOf('template/') == 0) {
                log('ignoring ' + config.url);
                return config;
              }

              log(config.method + ' ' + config.url);
              var auth = $injector.get('authService');
              if (!auth.LoggedIn) {
                return auth.Login();
              }
              return config;
            },
          }
        }
      ]);

      

Plunker example: http://plnkr.co/edit/kADmHkfHiyKW8kd7aNep?p=preview




A more complicated option might be to check $templateCache

if it contains the requested URL and skip authentication for these cases:

      $provide.factory('testIntercepter', ['$q', '$injector', '$templateCache',
        function($q, $injector, $templateCache) {
          return {
            'request': function(config) {
              if ($templateCache.get(config.url)) {
                log('in $templateCache ' + config.url);
                return config;
              }

              log(config.method + ' ' + config.url);
              var auth = $injector.get('authService');
              if (!auth.LoggedIn) {
                return auth.Login();
              }
              return config;
            },
          }
        }
      ]);

      

Plunker: http://plnkr.co/edit/RfkTmGinobxIWmg1BrMJ?p=preview

+5


source


You don't need to use templateUrl

. Check this code (also applies to authorization). I am using inline modal template. This is part of a larger script that opens a modal interface and allows routing in an open modal dialog, so you don't need to close the modal if you want to perform a series of actions in a modal dialog.



$modal.open({
     template: "<div data-ng-include='templateUrl'></div>",
     controller: function ($scope, $modalInstance) {

     $modalInstance.opened
         .then(function () {
             if (startRouteName != "unauthorized") {
                 var requiredAuthorizations = 
                        $scope.getRequiredPermissions(startRouteName);
                 if (requiredAuthorizations) {
                     $scope.hasAnyPermission(requiredAuthorizations)
                         .then(function (result) {
                             if (!result) {
                                 startRouteName = "unauthorized";
                             }
                             afterModalOpened($scope);
                     });
                 } else {
                     afterModalOpened($scope);
                 }
             } else {
                 afterModalOpened($scope);
             }
         });
     }
});

      

0


source







All Articles