How to add a module to my application after its launch without using require.js?

My AngularJS application has an admin module that I want to make available only to those in the admin role. On the server, I placed the files for this module in one directory, and I have this web config in the same directory. This works, and if the user is not in the administrator role, they cannot load javascript files:

 <?xml version="1.0" encoding="utf-8"?> <configuration> <system.webServer> <security> <authorization> <remove users="*" roles="" verbs="" /> <add accessType="Allow" roles="Admin" /> </authorization> </security> </system.webServer> </configuration> 

So, the server side solution of my side is similar to the solution. However, I am completely stuck with what to do with the client, how to load scripts and add a module to my application after loading it . Here is what I have:

The files in the admin directory that I protected with web-config look like this:

admin.js

 angular.module('admin', []) 

homeController.js

 angular.module('admin') .controller('AdminHomeController', ['$http', '$q', '$resource', '$scope', '_o', adminHomeController]); function adminHomeController($http, $q, $resource, $scope, _o) { .... ... } 

My application level files are as follows:

app.js

 var app = angular .module('app', ['ui.router', 'admin', 'home',]) .run(['$rootScope', '$state', '$stateParams', '$http', '$angularCacheFactory', appRun]) function appRun($rootScope, $state, $stateParams, $http, $angularCacheFactory) { $rootScope.$state = $state; $rootScope.$stateParams = $stateParams; } 

app.config.js

 app.config(['$controllerProvider', '$httpProvider', '$locationProvider', '$sceProvider', '$stateProvider', appConfig]); function appConfig($httpProvider, $locationProvider, $sceProvider, $stateProvider) { // I added this to help with loading the module after // the application has already loaded app.controllerProvider = $controllerProvider; // $sceProvider.enabled(false); $locationProvider.html5Mode(true); var admin = { name: 'admin', url: '/admin', views: { 'root': { templateUrl: '/Content/app/admin/partials/home.html', }, 'content': { templateUrl: '/Content/app/admin/partials/overview.html', }, } }; var adminContent = { name: 'admin.content', parent: 'admin', url: '/:content', views: { 'root': { templateUrl: '/Content/app/admin/partials/home.html', }, 'content': { templateUrl: function (stateParams) { return '/Content/app/admin/partials/' + stateParams.content + '.html'; }, } } }; var home = { name: 'home', url: '/home', views: { 'root': { templateUrl: '/Content/app/home/partials/home.html', }, 'content': { templateUrl: '/Content/app/home/partials/overview.html', }, } }; var homeContent = { name: 'home.content', parent: 'home', url: '/:content', views: { 'root': { templateUrl: '/Content/app/home/partials/home.html', }, 'content': { templateUrl: function (stateParams) { return '/Content/app/home/partials/' + stateParams.content + '.html'; }, } } }; $stateProvider .state(admin) .state(adminContent) .state(home) .state(homeContent); } 

When a user logs in, I know if this is a user of the admin role, since I have a security token that shows:

 { "access_token":"abcdefg", "token_type":"bearer", "expires_in":1209599, "userName":"xx", "roles":"Admin", ".issued":"Fri, 30 May 2014 12:23:53 GMT", ".expires":"Fri, 13 Jun 2014 12:23:53 GMT" } 

If the user of the admin role, then I want

  • Download the scripts of the admin module: /Content/app/admin/admin.js and /Content/app/admin/homeController.js from the server. I already set it up like this for calls to $ http: $http.defaults.headers.common.Authorization = 'Bearer ' + user.data.bearerToken; , so the Bearer token must be sent when receiving the scripts:

  • Add admin module to application

Can someone give me some tips on how I can do these two things. After reading about require.js, I feel like I would not want to use it as a solution. I would like as simple as possible.

From what I understand until AngularJS resolves this, I need to make it so that I can enter my controller. So I already added this in appConfig:

 app.controllerProvider = $controllerProvider; 

But how can I upload two javascript files and how to add them to AngularJS so that the user can start using the controller functions inside the admin module? I saw something about $ script.js that is used by the Angular team. Is this a good solution and how can I implement it to satisfy my rather simple need.

+6
source share
3 answers

You can add a permission property to your admin routes.

 var admin = { name: 'admin', url: '/admin', resolve: { isAdminAuth: function($q, User) { var defer = $q.defer(); if (User.isAdmin) { defer.resolve(); } else { defer.reject(); } return defer.promise; } }, views: { 'root': { templateUrl: '/Content/app/admin/partials/home.html', }, 'content': { templateUrl: '/Content/app/admin/partials/overview.html', }, } }; 

You can also link this.

  resolve: { adminPermissions: function($q, User) { var defer = $q.defer(); if (User.permissions.isAdmin) { defer.resolve(User.permissions.admin); } else { defer.reject(); } return defer.promise; }, hasAccessToHome: function($q, adminPermissions) { var defer = $q.defer(); if (adminPermissions.hasAccessToHome) { defer.resolve(true); } else { defer.reject(); } return defer.promise; }, }, 

The result of the resolve properties will also be passed to the controller if it is resolved. If rejected, the route will not be loaded. You can access it as follows.

 function adminHomeController($scope, adminPermissions, hasAccessToHome) { $scope.adminPermissions = adminPermissions; } 

You can also manually download the application:

 <!doctype html> <html> <body> <div ng-controller="WelcomeController"> {{greeting}} </div> <script src="angular.js"></script> <script> var isAdmin = true; <!-- injected variable from server here --> var app = angular.module('demo', []) .controller('WelcomeController', function($scope) { $scope.greeting = 'Welcome!'; }); angular.bootstrap(document, ['demo']); </script> </body> </html> 

[link] - https://docs.angularjs.org/api/ng/function/angular.bootstrap

Instead of introducing a variable or some other server-side template method, you can query using jQuery:

 $.getJSON('/my/url', function(data) { if (data.isAdmin) { // bootstrap app with admin module } else { // bootstrap app without admin module } }); 

Here is an example compatible with IE8 +, alternative to the one described above (not jQuery):

 request = new XMLHttpRequest(); request.open('GET', '/my/url', true); request.onreadystatechange = function() { if (this.readyState === 4){ if (this.status >= 200 && this.status < 400){ data = JSON.parse(this.responseText); if (data.isAdmin) { // bootstrap app with admin module } else { // bootstrap app without admin module } } } }; request.send(); request = null; 

[link] - http://youmightnotneedjquery.com/#json

+1
source

I would highly recommend using some module loader.

I understand that you want everything to be simple, but writing AMD (defining an asynchronous module) or CommonJS modules would help reduce some of the problems associated with dependency management (for example, loading things in the wrong order, redefining libraries, etc.) .

If you really insist, you can use jQuery.getScript() to load additional javascript sources (assuming you have jQuery as a dependency).

Pure javascript without jQuery will require you to do something like the loadScript example found in this.

In both cases, this will be done in the callback set for the controller; be careful, because the script will be executed in the global scope, so any variables, functions in the remote file MAY override those things that already exist if you are not careful.

If you are still interested in the module loader but you don't like require.js, take a quick look at curl.js.

0
source

Ido Sela talks about authorization in an Angularjs application and how they handle loading (or unloading) modules here: http://youtu.be/62RvRQuMVyg?t=2m35s

I would definitely look at this, as it will give you some of the best recommendations that I have seen on how to handle authorization and loading modules conditionally. (How I should have handled it in my prototype, and will be in future versions as soon as I have time to clean it.)

If you need to authorize after the initial loading of the application, and then you need to conditionally load the modules, you may consider making this a server problem. For example, using some kind of script loading mechanism, just visualize the logic based on the request authorization.

For example, in ASP.net MVC, I would consider the possibility of delivering my admin resources through the controller (and not as static content) and only visualizing real scripts if the user was logged in.

Update

Sorry for not taking your whole question into account. It looks like you have already provided the server side. So, now the problem of loading modules. I would still consider a controller that will filter your authorization requests (ie User.IsInRole("FooAdmin") or create an actual filter to scale your usage)

0
source

Source: https://habr.com/ru/post/970085/


All Articles