Is it possible to have a common aurelia shell application that can load and navigate between separately hosted child applications?
So far I have only seen this question answered by having multiple divs with the 'aurelia-app' attribute in them. But this assumes that each app will be served from the same server instance and have files/routing co-located there.
What I am after is a way to have separate SPA's each possibly self-hosted on different machines (virtual or otherwise) that can act as stand-alone applications or be embedded in a parent SPA that can navigate between these SPA's and possibly coordinate passing data between them.
Is this possible in Aurelia or any other SPA framework?
You can use the Aurelia object's setRoot() method to change what is loaded for into the defined in index.html. I use this in my app to switch between the full-screen login mode and the application mode with full nav-bar.
private aurelia: Aurelia;
showLogin() : Promise<any> {
return this.setRoot(PLATFORM.moduleName('Login', 'login'));
}
showApplication() : Promise<any> {
return this.setRoot(PLATFORM.moduleName('Client', 'application'));
}
setRoot(root: string) {
// NOTE: Aurelia will call router.deactivate() & router.reset() if there is an existing root
// this.router.navigate('/', { replace: true, trigger: false });
return this.aurelia.setRoot(root);
}
Related
In the ConfigureServices() method of my ASP.NET 6.0 app, I have the following
// Code has been simplified for the purposes of this example.
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.All;
// Only trust "X-Forward*" headers from user-specified hosts.
foreach (var proxy in ApplicationSettings.GetKnownProxies())
{
options.KnownProxies.Add(proxy);
}
});
The ApplicationSettings.GetKnownProxies() method returns something according to what the end-user specified in the app's system configuration screen.
The problem is that the end user can change the settings during the lifetime of the application (either adding or removing proxies). However, since the "configure" code is only run on startup, any changes won't take effect until the web application is restarted.
Is there any way to avoid this? That is to say, is there any way to reconfigure the ForwardedHeaders feature without restarting the entire web application?
Set-up:
I have a web component (Angular 10) being used in an Angular 10 Application. The web component makes an Httpclient call to a web API to get some data to populate a menu dropdown. The web component was made using the standard methods to make a web component using Angular 10.
The web component is loaded through a script in the main client application. This is from the angular.json file for the parent application.
1."scripts":
[
"projects/web-component-test/src/assets/plugin.bundle.js"
]
and all works fine except we get a 401 error (unauthorized) since the end point requires the user to be logged in. By working fine, there are other controls that display as required just the the dropdown list, which gets it data from the API call does not get populated.
The flow:
User goes to website and then is prompted to log in (using keycloak Auth).
Application loads fine, except for the 401 error when the web component tries to load the menu items.
Http calls from the parent app work fine; the jwt token is added to the header for the call to the protected API. Calls from the child web component do not have the jwt token in the header, and thus fail with a 401 error.
httpinterceptor: we have an httpinterecptor on the main client application (the parent of the web control). Http calls that are made from the main app are routed through the interceptor where the token is attached to the header if needed.
Calls made from the child Web Component DO NOT hit the interceptor in the parent app?
Question:
How do I make call from the child web component route through the http interceptor in the parent so the token can be added.
Things I have tried:
I can get the web component to work fine if I do this:
When the parent loads I store the token in local storage
using an http interceptor on the web component, retrieve the token from local storage and use it.
** works, but I DO NOT want to store a secure token in local storage.
Pass the token in an attribute on the child component when the parent loads the child component
** again, I can get it to work, but not very secure.
A web component is an independent piece of code from your main codebase, so when you hit a request from the web component, your main app won't be able to catch those requests in the interceptor.
For me, one thing it worked was creating different Custom Events per every request:
doGetRequest
doPostRequest
doPutRequest
doDeleteRequest
Let me quickly guide you through one example of these events.
From the main app, I'm listening if any of these events are triggered:
this.popupEl.addEventListener('doPostRequest', (info: HTMLElementEventMap | any) => {
this.performHttpRequest(info.detail);
});
Notice that all the info sent from your web component, can be found in the property 'detail' your main app receives.
From the web component, I execute the following:
this.doPostRequest.emit({
url: 'the URL to hit',
endpointParams: {
user: 'my user',
password: '******',
}
});
Note: You can change the structure of the params to sent. It's totally up to you.
This will trigger the execution of the API in the main app, and as the request was executed from the main app, your interceptor will do its work and add whatever JWT you have there. Once the main app receives the response, you will need to set a new property in your web component to pass the response to it. Something like this:
this.popupEl.apiResponse = {
webComponentInfo: { ...infoReceivedFromYourWebComponent },
apiDetails: { ...ResponseFromYourBackend}
};
Finally, in your web component, add a new input that listen for the apiResponse attribute:
#Input()
set apiResponse(apiResponse: RequestParams) {
if (apiResponse.webComponentInfo.url === 'the URL to hit') {
// Do what you want in your web component, as you know exactly which URL just got executed.
}
}
This way, you let your main app continue doing its work with your interceptor and the web component won't need to handle the JWT or actually perform the requests.
One thing you may want to consider is not allowing the Delete request from your web component unless you and only you have full control over the web component. You wouldn't want anything that can perform a successful DELETE request to a very important API.
Hope this helps.
I have an APP using restful server. I want to store PDF's, images, etc. in folders on my server. How can I make the folders private on server, yet allow App to access only certain folders depending on their app access.
I have different users in app and security/tokens established, etc. But if they upload an image for their avatar (and now PDF's), they get stored in folders on the server, and I just display with image source=https://blahblah.com/org1/images/user232.jpg.
How can I make that not accessible to outside (like just going to browser), yet make accessible to app if they have correct login privilege's for that organization/user? And then further extend that logic to more sensative PDF's, and other docs uploaded through app. I didn't want to store in SQL since then harder to use simple image display tools and I already have upload and media managers using folders structures.
I can see how to secure if logging onto server through browser (credentials), but can't see how you connect App with that security level and maintain it for the session.
For future readers. Most of the work was done on the restful (ASP.NET) side. I first tried using authorization/Authentication in web.config and having Allow and deny. This allowed a redirect of a user to a login page; however, it didn't do it if they entered an image exactly correct on website.
Found HTTPHandlers (adding in webconfig ) where I could write code that would be executed once the user entered the specific Image address xyz/abc/image.png. I found this a bit feeling like a hack.
So lastly modified my
routes.MapRoute(
name: "staticFileRoute",
url: "publicstor/{*file}",
defaults: new { controller = "Home", action = "HandleStatic" }
And add a function like this to home controller.
[System.Web.Http.HttpGet]
public ActionResult HandleStatic(string file)
{
if (Session["OrgId"] == null) //todo need to add full security check.
{
return View("Login");
}
else //Either coming from app or coming from web interface
{
string mimeType = MimeInfo.GetMimeType(Path.GetExtension(file));
return File(file, mimeType);
}
}
The final bit is on the Xamarin side to now pass security when getting an image. Since just a simple Xamarin.Forms.Image doesn't have a way to pass login info or tokens/authentication I used
https://forums.xamarin.com/discussion/145575/image-from-url-needing-auth
And established an appwide webclient that logged in generally once forcing my restful to go through security validation, then just accessed the images/documents through out my app from that webclient. So far so good. Hopefully there are no holes.
This gives the gist to a future reader.
I have a code library I have written which can be utilized in both desktop applications and on a web server. That library sometimes needs to know which environment it's running in.
In the past I have relied on System.Web.Hosting.HostingEnvironment.IsHosted to tell if the code is running on a web server. Unfortunately asp.net core mvc does not have access to the System.Web namespace so I need another mechanism.
How can the code tell if it's running on a web server if one of those possibilities is asp.net core mvc?
Answering my own question in case it helps others.
It's been mentioned that one way to determine whether the code is running on a web server or desktop app is to look at the name of the process it's running in. This is definitely possible, but I have little control over what the process name is for a web application and the name is likely to change in the future if history is any indication.
So instead, I chose to make the determination based on the application's config file name. This file name is different for web apps and desktop apps and it's something that's more under my control as a developer.
The method I wrote to do this is:
public bool IsWebServer {
get {
string file = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile.ToLower();
//web.config used by asp.net 4.X,
//app.config used by MVC Core
//NameOfTheApp.exe.config used by desktop applications
if(file.Contains("web.config") || file.Contains("app.config")) {
return true;
}
return false;
}
}
Unfortunately, there is no currently equivalent API. When you look at how that property works, you can easily do something equivalent yourself--without making assumptions about which server is hosting your application.
You'll have to set up your API with a static public property:
namespace My.Project
{
public static HostingEnvironment
{
public static bool IsHosted { get; private set; }
public static void SetIsHosted(this IServicesCollection services)
{
// you can grab any other info from your services collection
// if you want. This is an extension method that you call
// from your Startup.ConfigureServices method
IsHosted = true;
}
}
}
So now you have something that works with both ASP.Net MVC 5 and 4.5. You would integrate it in your Startup.ConfigureServices() method.
public void ConfigureServices(IServiceCollection services)
{
// Set up whatever services you want here.
// Make sure you have your My.Project namespace
// in your using statements so you can use the IsHosted()
// extension method
services.SetIsHosted();
}
The only difference between this solution and the legacy System.Web.Hosting.HostingEnvironment.IsHosted solution is that the flag was set by the framework when the application was started by IIS automatically. This is probably as close of an equivalent solution as you are going to get, while still allowing the ability to host anywhere.
I have a working robolectric and want to test a component of my application that does HTTP request. Since I don't want these requests to go to my live server but instead to a local test server I want to override a string resources (that contains the servers hostname) during testing.
However, I'm not capable of finding anything in the robolectric documentation that goes remotely in the direction I want :(
I've faced a similar issue in Robolectric 3; you can override a resource at application level using Mockito partial mocks.
First, you tell Robolectric to used a partially mocked Application and to return that when the application context is used: (thanks to this answer: https://stackoverflow.com/a/31386831/327648)
RuntimeEnvironment.application = spy(RuntimeEnvironment.application);
when(RuntimeEnvironment.application.getApplicationContext())
.thenReturn(RuntimeEnvironment.application);
Then you partially mock the Resources object:
Resources spiedResources = spy(app.getResources());
when(app.getResources())
.thenReturn(spiedResources);
Then you can do the real override:
when(spiedResources.getString(R.string.server_address))
.thenReturn("local server address");
I hope this helps.
You can use the technique mentioned at http://robolectric.blogspot.com/2013/04/the-test-lifecycle-in-20.html
This will allow you to override getResources() and use spying to return a hardcoded String or (by default) the String loaded from res/values:
#Override
public Resources getResources() {
Resources resources = spy(super.getResources());
when(resources.getString(R.string.server_address)).thenReturn("local test server address");
return resources;
}