Best way to load customer parameters in a multi-tenant angularJS application - angularjs

We have a multi-tenant Angular JS single page application. The routing for the application uses a customer identifier as part of the URL - #/home/<KEY> or #/search/<KEY>/<search term> for instance. In theory the first page served could be of any type. Each page calls an API using the customer key and other values picked up from the URL to get data for the page. So far so good.
We have some parameters - a logo, copyright statement, default language (for internationalization) - that can be loaded using a separate API call that also uses the customer KEY. These parameters need to be available as strings in partials, to drive the internationalization and perhaps in controllers.
The question is where to call the API to get these parameters and how to set them / make them available for the rest of the app. I have looked at a bunch of questions in this general area but can't find a concrete suggestion. Should we use a config in app.js? Call another script from index.html?
Appreciate people's advice.

The right place would be to make an API call immediately after authentication to get the various Customer specific configuration data like the Customer settings for logo, language and then put them in the session storage of the browser.
I have done an implementation using Microsoft ADAL js as per the documentation given here. https://github.com/AzureAD/azure-activedirectory-library-for-js/blob/dev/README.md.
You can do this Api call in the login success event handler or similar ones in angular.
Example:
$scope.$on("adal:loginSuccess", function () {
$scope.testMessage = "loginSuccess";
});
HTH

Related

Generate shareable link feature in Django?

I have a Django Rest Framework application that is fed in data from a csv. I then use React to create dashboards and Widgets from that data. I want to be able to generate a link to share a read-only version of any dashboard, much like in Google docs etc. Anyone clicking on that link will be able to see the dashboard with all the charts and analytics etc. The link can be shared much like how you share a Google Forms link. I'm not sure how to go about doing that. Any help / pointers would be appreciated. Thank you!
I think theoretically you need to use a router on your react app (e.g. https://reactrouter.com/ ).
If you're using create-react-app, you can also refer to https://create-react-app.dev/docs/adding-a-router/#:~:text=Create%20React%20App%20doesn't,is%20the%20most%20popular%20one.) .
With this you can directly read parameters on a certain page within your react app, that you can then use to build a concrete call to the backend, to retrieve the necessary data to build your dashboard.
The 'link builder' functionality most likely needs to be implemented on the backend, so you can have the necessary parameters you need to gather the necessary data, maybe by using query strings.
If you want to make it more complex, you would need to implement on the backend a kind of tokenized access, that could store the full call parameters on the backend side, and associate them with a token of some kind, that you could then provide to your clients.
e.g. : http://djangoappxpto.com/link/12345abcd points to a react page component that then executes a fetch to http://djangoappxpto.com/api/getStats/12345abcd which once received by python would internally mean something like http://djangoappxpto.com/api/generateStatsReport/?param1=a&param2=b&param3=w&param4=aa .

Rendering Just one module/state of Angular app

I've angular app with lots of states and modules etc. Now, I want to send a link to the user. When user'll hit this url, I want to redirect him to a new tab rendering only that particular state (specified in URL) i-e I don't want anything else to be visible to the user. Or you can say, I want to open a popup window rendering that particular state's html in popup window . This is the approach that comes to my mind to sort it out.
Ps. There are Rest APIs at the backend which I am calling through angular resource service to bind data with the model of the views
Option
I've rest APIs on backend, So, I was thinking to developing s separate Nodejs application, And I will send nodejs application url to the user and in the default/home route I'll call backend API and, the returned resultset will be rendered in html file within nodeJs application and this way, I'll render the corresponding data to user's browser window.
This is the flow for that
I don't know if that is right or clever approach. Please suggest me what will be the best approach to sort it out.
Thanks in advance.
This is what my app looks like
Everything in the left side-nav is a module and clicking on this I am routing to a different state. I am using angular-material and lots of other dependencies in this project.
And this is what I want.
I'll refer a link to the user for example www.myapp.com/specificpage.html. And hitting this url, a new tab/popup will be opened rendering state defined in the same app but with some non-editable url. And it should like.
There are multiple ways to achieve this and each approach has advantage and disadvantage. You have to choose depending on requirement and architecture. Details are below-
Create a separate app - You can do it through separate code base or use the module based build process and include this module only for new app.
Divide application is two part, public pages and private pages - Include this page and required APIs for this page in the public modules for your app.
Send token in the link - If you want to make secure page, send short lived token in the eMail and validate token on the server before displaying page to the user.

Shall I use SPA or traditional approach with AngularJS

I'm new to AngularJS, I have following scenario that I need to implement:
Assume index.html page only has an input field for enter a unique ID, when click submit button, the unique ID will be passed to backend for retrieving all information needed(for example, User object with current status, last name, first name etc ). Based on User.currentStatus, it should show different page with the same header and footer. There is no top menu bar on any of the page. Basically, all the pages are displaying different information about a user based on his status.
Honestly, it depends on your backend architecture, but if you're new to Angular I'd recommend a SPA, since most resources are geared towards building a SPA.
Angular can be used either "traditionally" or in a SPA environment. Given that Angular does specifically target use in SPA's, that's the path I suggest.
Here's is a reference to $route in the AngularJS documentation, which you'll need in order to build a SPA: $route
You'll also need to read up on ngView, which is referenced near the top of that page.
For a SPA, structuring the project well can make things a whole lot easier, so here's a reference to a good style guide for Angular as well.

URL handling in a Hypermedia (HATEOAS) driven AngularJS application

We are looking for some advice on handling URLs (and the state related to each URL) in a web application backed by a HATEOAS REST API, more specifically on
how to avoid having the web application URLs coupled with the REST API URLs
how to handle multiple resources in a single view
But let me first provide some more context:
We are building an Angular web application on top of a REST layer with Hypermedia constraint. (Note: I prefer simply using the term 'Hypermedia (constraint)' over HATEOAS).
As dictated by the Hypermedia constraint, the available actions and links in the application at any point in time are provided by the REST API. So the web application should not contain any hardcoded urls of the REST API, except for the 'root' (assuming that concept really exists in a REST API).
On the other hand, each page in the web application needs to be bookmarkable. So we cannot create a black-box application (with a single url and all state changes handled in the SPA without changing the URL). This means the web application also has its URL space, which needs somehow to be mapped to the REST API URL space. Which is already a conflict with the Hypermedia idea.
In the Angular application we use UI Router for handling application state. Here is how we got it working:
We only define states, no URLS
We defined a $urlRouterProvider.otherwise handler that will map the current web application URL to the corrsponding REST API URL, retrieve the representation of the resource that corresponds with that REST URL and pass it to the controller (in $stateParams).
The controller can then use the data (and links and actions) in the representation, just like it would if it would have made the REST call itself (or through a service)
So far so good (or not really) because there are some downsides on this approach:
The Web application URLs are mapped to the REST API URLs, so both URL spaces are coupled, which conflicts with one of the basic assumptions of using Hypermedia constraint: we cannot change the REST API URLs without having to change the web application.
In the $urlRouterProvider.otherwise handler we retrieve the representation of the current web app URL. But in some cases we have two resources in a single view (using UI Router nested states): for example a list of items and a detail of a single item. But there is only a single URL, so only the representation of the item detail is retrieved and the list of items remains empty.
So we would love to hear some suggestions on how we could improve on our approach in handling the two URL spaces. Is there a better way to make the REST API dictate the (available) behaviour of the web application and still have bookmarkable URLs in the webapplication? Because now we have some kind of hybrid approach that does not feel completely right.
Thanks in advance.
Regards,
Luc
that's a tough setup. Roughly you want bookmarks into your API, and RESTful systems somewhat discourage bookmarks.
One possible solution is a "bookmark service" that returns bookmark (bit.ly like) urls for the current resource being presents that are guaranteed to be fowards compatible because as you may change the canonical url structure, the bookmark service can always translate the bit.ly like url into the canonical url. Sounds complicated, but we see this all the time and we call them SEO urls eg: /product-name/ maps to products/ today, but may be /catalog/old-products/ tomorrow.
How you match that up to a UI that shows 2 resources the first being a list of summary like resources, and the second being a specific resource get's really tricky. I would expect such a page to know contain the state of what's it's displaying in it's url (probably in the fragment). As such since it's [likely] the controller that processing such commands it probably needs both (the list resource and the expanded resource) as input. I bet the url would look something like:
list=http://path/to/list/results&expand=http://self/link/of/path
So the last part you have is to make sure that works going forwards. Again this is the bookmark problem. What i may suggest if you don't want to build a bookmark service is that given you want to have such bookmarks you need to transition people to the new URLs. When a request is made to http://path/to/list/results and you want to switch that over you should be 301 redirecting them to the new canonical url and the app should be updating the bookmark. such a redirect can include the &flag=deprecate_message param to trigger the presentation in the UI that the client's bookmark is old and should be replaced. Alternatively the response can be internally forwarded and the deprecation flag & canonical (or latest) link included in the response to the old URL. This causes a phased transition.
In summary: I have yet to see HATEOAS be a cure all for backwards & forwards compatibility, but it's much better than the existing techniques. that said you must still make decisions in v1 of your API about how you want your users to move to v2.

AngularJs authorization layout

I am building a large application with Web API and AngularJs. I built the secure web api with authentication and claim-based authorizations. One requirement is that different users can view different modules on the same template.
I am new to AngularJs. I did the authentication in client side with the tokens. Also, in web api, I created a service to get all the permission given a user id. The response is a list of resource(contoller)/action(method) pairs. How do I implement the correct layout based on authorization rules on client side? Does that solely rely on web api permissions response and show/hide (ng-hide/ng-show) content based on the permissions?
Is this a good approach? What other modules/directives do I need to look into? Such as the loader for not loading the nested route until user request the parent route.
To add complexity, this site also need to work in bi-lingual. I think ng-translate. I mentioned this because it may open up another discussion on whether this may favor MVC instead of AngularJs. But the preference is Angular if the above two problem can be resolved.
All the authentication & authorisation & validation should be done server-side. You can adjust the user interface based on the roles/claims the server tells the browser the current user has.
One way to do this is to create something like a roles/userprofile controller, which will respond with a list of roles the current user has. On the client side you’ll probably want something you can inject everywhere, so you’re able to determine user interface behaviour.
myApp.factory(‘myUser’, function(Roles, $q) {
// Create a promise to inform other folks when we’re done.
var defer = $q.defer();
// For this example I’m using ngResource
Role.query({
/*
No params — let the server figure out who you ‘really’ are.
Depending on WebApi configuration this might just be
as simple as this.User (in context of the controller).
*/
}, function(roles) {
var user = {
roles: roles,
isInRole: function(role) {
return user.roles.indexOf(role) !== -1;
}
};
defer.resolve(user);
});
return defer;
});
Because the factory above is returning a promise we can enforce that myUser is resolved before a certain route/controller instance is created. One little trick I use is to gather all my route definitions in one object, loop through them with an angular.forEach and add a resolve.myUser property to each of them. You can use this to pre-load/initialize other stuff too.
Now inject the myUser anywhere you like:
myApp.controller(‘MyController’, function($scope, myUser) {
// Expose it on the current scope
$scope.myUser = myUser;
});
… and in your markup …
<div class=“my-content-thingy”>
<p>Lorem del ipsum …</p>
<button class=“btn” ng-if=“myUser.isInRole(‘content-editor’)”></button>
</div>
Note: You’ll probably want to use ng-if and not ng-show; the latter keeps the element in the DOM.
Just keep in mind that you don’t authenticate anything on the client side; that all done server side. A simple way is to place Authorize attributes on the appropriate controller actions.
Hope this helps.
A proper approach is to build AngularJS routing configuration as per Authorization on the server. This should be build just after the user is authorized and before the AngularJS app is initialized. That way the authorized user sees a "complete" app based on his roles etc. Using ng-show/ng-hide is not a good way to do it. Also each view should be doing only one thing. So load separate views based on the task that needs to be completed.
Regarding multi language support, this is independent of Authorization. Some time ago, I wrote a custom AngularJS filter that used the jQuery i18next plugin. It was a pretty simple implementation.
However you can now use https://github.com/i18next/ng-i18next
(Sorry for misunderstanding the problem).
I think that using ng-hide/show is not much of a problem. At the end of the day, the user does not have access to the data. I think it should rely on the api permissions + show/hide of presentation. Depends on the complexity you want... You can use MVC with angularjs since it's a large application.

Resources