Show different routes to user than actual in angular - node.js

I am working on a full stack web development using Angular, Node(Express) and mySQL. I want to show user some different route than what it actually is. How can I do that?
For example, this is my dashboard page.
http://localhost:4200/#/dashboard
I want it to be viewed as something else to the user like:
http://localhost:4200/#/Welcome
OR
http://localhost:4200/#/Welcome/LandingPage
Meaning, this page can only be accessed if you enter the Url:
http://localhost:4200/#/dashboard
and, if the user tries to access this page by entering the Url that is being shown to him:
http://localhost:4200/#/Welcome
OR
http://localhost:4200/#/Welcome/LandingPage
then, he gets an error.
I have done this all in app.routing.ts. I just want to ask how can I do the above mentioned. To show that route to the user that actually doesn't exist.
For further clarification: When the user will open the page then it will be shown to him as "localhost:4200/#/Welcome". I want to just show the user this route. In my code, it actually should remain dashboard. In easy words, when the user enters the url: "localhost:4200/#/Welcome" it should throw an error because in code such route doesn't exist. It was just shown to the user as a kind of fake route. In actual, it should be "localhost:4200/#/dashboard" but, shows to user as "localhost:4200/#/Welcome"

I guess maybe using location will do the trick if I understood question right.
constructor(private location: Location){}
replaceState(){
this.location.replaceState("/Welcome");
}
You will have to import Location module:
import {Location} from '#angular/common';

Related

Prevent showing the UI5 app internal page without successful authentication

OpenUI5 version: 1.86
Browser/version (+device/version): Chrome Dev
Upon the authentication I validate the user session:
if (isUserSessionValid) {
const oRouter = UIComponent.getRouterFor(this);
oRouter.navTo("overview");
} else {
this.getOwnerComponent().openAuthDialog();
}
If isUserSessionValid is true, then I forward an user to the internal page, otherwise I show the login dialog.
The problem is, however, that an user can change the value of isUserSessionValid in DevTools and then getting forwarded to the UI5 app internal page. Of course, due to a lack of a valid session, no piece of the business data will be displayed, just an empty UI5 app template, but I would like to prevent even such screen.
If it would be a classical webapp, I would just send an appropriate server response with a redirect to the login page (e.g. res.redirect(403, "/login");). But, if I understand it correctly, since I'm sending am asynchronous request, a plain res.redirect won't work out and I'm required to implement a redirection logic on the UI5-client, which can be manipulated and bypassed by user.
How to prevent a manipulation of a view navigation in UI5 and ensure that unauthorized user can't get any piece of the UI5-app code?
The answer from SAP:
If you want to prevent an unauthorized user from accessing the client-side code (e.g. view/controller) you need to enforce
authorization on the server also for those static files. When bundling
the application code you also need to ensure that those files are
separate from the "public" files. One approach would be to have 2
separate components, one for the public page/auth dialog and one for
the actual application.

How can I protect the loopback explorer by username and password?

I've just started using loopback4 and I would like to protect the /explorer from being public. The user would initially see a page where username and password must be entered. If successful, the user is redirected to /explorer where he can see all API methods (and execute them). If user is not authenticated, accessing the path /explorer would give a response of "Unauthorized". Is there a way to easily implement this?
There is issue talking about a GLOBAL default strategy is enabled for all routes including explorer in https://github.com/strongloop/loopback-next/issues/5758
The way is to specify a global metadata through the options:
this.configure(AuthenticationBindings.COMPONENT).to({
defaultMetadata: {
strategy: 'JWTStrategy'
}
})
this.component(AuthenticationComponent);
registerAuthenticationStrategy(this, JWTAuthenticationStrategy)
But in terms of enabling a single endpoint added by route.get(), it's not supported yet, see code of how explorer is registered. #loopback/authentication retrieves auth strategy name from a controller class or its members, but if the route is not defined in the controller, it can only fall back to the default options, see implementation

How to fill login prompt with Webdriver IO?

I'm working on a CLI with OCLIF. In one of the commands, I need to simulate a couple of clicks on a web page (using the WebdriverIO framework for that). Before you're able to reach the desired page, there is a redirect to a page with a login prompt. When I use WebdriverIO methods related to alerts such as browser.getAlertText(), browser.sendAlertText() or browser.acceptAlert, I always get the error no such alert.
As an alternative, I tried to get the URL when I am on the page that shows the login prompt. With the URL, I wanted to do something like browser.url(https://<username>:<password>#<url>) to circumvent the prompt. However, browser.url() returns chrome-error://chromewebdata/ as URL when I'm on that page. I guess because the focus is on the prompt and that doesn't have an URL. I also don't know the URL before I land on that page. When being redirected, a query string parameter containing a token is added to the URL that I need.
A screenshot of the prompt:
Is it possible to handle this scenario with WebdriverIO? And if so, how?
You are on the right track, probably there are some fine-tunings that you need to address to get it working.
First off, regarding the chrome-error://chromewebdata errors, quoting Chrome DOCs:
If you see errors with a location like chrome-error://chromewebdata/
in the error stack, these errors are not from the extension or from
your app - they are usually a sign that Chrome was not able to load
your app.
When you see these errors, first check whether Chrome was able to load
your app. Does Chrome say "This site can't be reached" or something
similar? You must start your own server to run your app. Double-check
that your server is running, and that the url and port are configured
correctly.
A lot of words that sum up to: Chrome couldn't load the URL you used inside the browser.url() command.
I tried myself on The Internet - Basic Auth page. It worked like a charm.
URL without basic auth credentials:
URL WITH basic auth credentials:
Code used:
it('Bypass HTTP basic auth', () => {
browser.url('https://admin:admin#the-internet.herokuapp.com/basic_auth');
browser.waitForReadyState('complete');
const banner = $('div.example p').getText().trim();
expect(banner).to.equal('Congratulations! You must have the proper credentials.');
});
What I'd do is manually go through each step, trying to emulate the same flow in the script you're using. From history I can tell you, I dealt with some HTTP web-apps that required a refresh after issuing the basic auth browser.url() call.
Another way to tackle this is to make use of some custom browser profiles (Firefox | Chrome) . I know I wrote a tutorial on it somewhere on SO, but I'm too lazy to find it. I reference a similar post here.
Short story, manually complete the basic auth flow (logging in with credentials) in an incognito window (as to isolate the configurations). Open chrome://version/ in another tab of that session and store the contents of the Profile Path. That folder in going to keep all your sessions & preserve cookies and other browser data.
Lastly, in your currentCapabilities, update the browser-specific options to start the sessions with a custom profile, via the '--user-data-dir=/path/to/your/custom/profile. It should look something like this:
'goog:chromeOptions': {
args: [
'--user-data-dir=/Users/iamdanchiv/Desktop/scoped_dir18256_17319',
],
}
Good luck!

How can I get a token for the Drive API?

I want to implement the Google Drive API to my web application using NodeJS and I'm struggling when I try to get a token via OAuth.
I've copied the code from this guide and run the script using Node and it returns an error in this line:
var redirectUrl = credentials.installed.redirect_uris[0];
Googling around I found that I can set that variable as http://localhost:8080 and set the same value in the Authorized redirect URIs configuration in the Google Developers Console and that error goes away, fine, it works. Now it asks for a code that I should get by using an URL.
https://accounts.google.com/o/oauth2/auth?access_type=offline&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.metadata.readonly&response_type=code&client_id=CLIENT_ID&redirect_uri=http%3A%2F%2Flocalhost%3A8080
Then I've added the client id and enter to that URL with Chrome and then returns a connection refused error. No clue what to do in here, I searched about my problem and I can't found an answer. By looking at the direction bar in Chrome I see that there's a parameter called code and after it, there's random numbers and letters. Like this:
http://localhost:8080/?code=#/r6ntY87F8DAfhsdfadf78F7D765lJu_Vk-5qhc#
If I add any of these values it returns this error...
Error while trying to retrieve access token { [Error: invalid_request] code: 400 }
Any ideas on what should I do? Thanks.
Did you follow all the directions on the page you indicated, including all of those in Step 1 where you create the credentials in the console and download the JSON for it? There are a few things to note about creating those credentials and the JSON that you get from it:
The steps they give are a little different from what I went through. They're essentially correct, but the "Go to credentials" didn't put me on the page that has the "OAuth Consent Screen" and "Credentials" tabs on the top. I had to click on the "Credentials" left navigation for the project first.
Similarly, on the "Credentials" page, my button was labeled "Create Credentials", not "Add Credentials". But it was a blue button on the top of the page either way.
It is very important that you select "OAuth Client ID" and then Application Type of "Other". This will let you create an OAuth token that runs through an application and not through a server.
Take a look at the client_secret.json file it tells you to download. In there, you should see an entry that looks something like "redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"] which is the JSON entry that the line you reported having problems with was looking for.
That "urn:ietf:wg:oauth:2.0:oob" is a magic string that says that you're not going to redirect anywhere as part of the auth stage in your browser, but instead you're going to get back a code on the page that you will enter into the application.
I suspect that the "connection refused" error you're talking about is that you used "http://localhost:8080/" for that value, so it was trying to redirect your browser to an application running on localhost... and I suspect you didn't have anything running there.
The application will prompt you to enter the code, will convert the code into the tokens it needs, and then save the tokens for future use. See the getNewToken() function in the sample code for where and how it does all this.
You need to use this code to exchange for a token. I'm not sure with nodejs how to go about this but in PHP I would post the details to the token exchange url. In javascript you post array would look similar to this ....
var query = {'code': 'the code sent',
'client_id': 'your client id',
'client_secret': 'your client secret',
'redirect_uri': 'your redirect',
'grant_type': 'code' };
Hope this helps
Change redirect uri from http://localhost:8080 to https://localhost:8080.
For this add SSL certificates to your server.

how to create ACL with mongoose-acl node.js

I found this library for creating an ACL (access control list) for mongoose:
https://github.com/scttnlsn/mongoose-acl
It looks like a good module, but I'm a little confused on how to use it for my purpose.
I have a site where anybody (logged in or not) can visit a profile page, like example.com/users/chovy
However if the user 'chovy' is logged into this page, I want to give them admin privileges for editing the details of the account.
If the user is not 'chovy' or is not logged in, they would just see the read-only profile page for 'chovy'.
Can someone give me a concrete example of how I would do this?
That sounds so common, that I don't think you need an ACL. You will need to have sessions, and then you can change how the view looks based upon the current logged in user. An incomplete example would like like this:
// Assumes:
// - You set req.session.user when user logs in
// - The url route has a :name so you can do req.param() to get the name of the page being viewed
db.users.getCurrentUser(req.session.user, gotLoggedInUser)
db.users.getUserByName({name: req.param('name')}, gotUser)
And then pass this to the view, when you do a res.render():
var is_viewing_own_page = currentUser._id.toString() === loggedInUser._id.toString()
And then the view can do something like this (assuming jade):
- if (is_viewing_own_page)
div You are looking at your own page
- else
div You are viewing someone else's page

Resources