Converting Angular 4 App to PWA - javascript

I've set some routing rules in ngsw-manifest.json as shown below. Problem is when I'm running a http-server and directly hitting http://localhost:8080/home it's showing url not found.
{
"static.ignore": [
"^\/assets\/ignore.*$"
],
"routing": {
"index": "/index.html",
"routes": {
"/": {
"match": "exact"
},
"/home": {
"match": "exact"
},
"/listing/must_watch_videos": {
"match": "exact"
},
"^/regex/.*/route$": {
"match": "regex"
}
}
},
"external": {
"urls": [
{
"url": "https://fonts.googleapis.com/css?family=Material+Icons"
}
]
}
}

When someone requests /home your server can't find a file or folder with that name and returns error 404. You need your server to instead server your main app .html as though it resides at those locations.
For node http-server it looks like the option would be --spa. For example:
ws --spa index.html
Single Page Application
Serving a Single Page Application (an app with
client-side routing, e.g. a React or Angular app) is as trivial as
specifying the name of your single page:
$ ws --spa index.html Serving at http://mbp.local:8000,
http://127.0.0.1:8000, http://192.168.0.100:8000 By default, requests
for typical SPA paths (e.g. /user/1, /login) return 404 Not Found as a
file at that location does not exist. By marking index.html as the SPA
you create this rule:
If a static file is requested (e.g. /css/style.css) then serve it, if
not (e.g. /login) then serve the specified SPA and handle the route
client-side.
See: https://www.npmjs.com/package/local-web-server#single-page-application
See: https://github.com/lwsjs/local-web-server/wiki/How-to-serve-a-Single-Page-Application-(SPA)

Related

WebAuthn Relaying Party ID for various Setups

I have an Angular 11 Project, which implements a WebAuthn registration. The backend is SpringBoot 2.4
WebAuthn Login should work in two parts of the project, the "main" and the "viewer"
The domain setup is rather complicated:
Main Project
Urls
Local: https://localhost:4202
Staging: https://company.com (local Kubernetes Server)
Prod: https://company-project.com
Viewer Project
Urls
Local: https://localhost:4200
Staging: https://viewer.develop.plattform.intra.company.com (local Kubernetes Server)
Prod: https://viewer.company-project.com
Code
environment.ts
prodUrls: ['company-project.com'],
webauthn: {
name: "Company DEV",
rpId: "localhost"
}
environment.prod.ts (replace in build)
prodUrls: ['company-project.com'],
webauthn: {
name: "Company Prod",
rpId: "plattform.intra.company.com" // gets overridden by values in "prodUrls"
}
webauthn.service.ts
private _getRelyingPartyInfo(): RelyingParty {
let rpId = environment.webauthn.rpId;
/**
* Check if the Hostname matches one of our Prod Hostnames
* and use this instead
*/
environment.prodUrls.forEach((url, index) => {
if (location.hostname.indexOf(url) > -1) {
rpId = environment.prodUrls[index];
}
});
const rp = {
id: rpId,
name: environment.webauthn.name
};
return rp;
}
The Issues
It works locally, using the rpId localhost (both Backend and Frontend locally)
It does NOT work on staging --> Backend throws
WebAuthnException message: rpIdHash doesn't match the hash of preconfigured rpId.
It should work on Prod using company-project.com as rpId (scared to deploy as it does not work on staging)
What I tried
For staging, I changed the rpId to develop.plattform.intra.company.com and I can register and login in "main". Logging in on "viewer" throws an error as well
The spec is not very specific about what should work: https://www.w3.org/TR/webauthn/#relying-party-identifier, it only says what shouldn't work. I assume, that the multiple subdomains complicate things on staging?
What would be the correct rpId for staging and is the assumption that company-project.com as rpId should work on prod correct?
For staging, I changed the rpId to develop.plattform.intra.company.com and I can register and login in "main". Logging in on "viewer" throws an error as well
What's your code to get the assertion? You might also be running into this other question. You need to set the get assertion RP ID to the same RP ID used for registration. If you don't, it will default to the origin, which for your subdomain will be different.

How to setup serivce-worker.js properly using webpack in Laravel + ReactJS project? PWA

The project I built is in ReactJS (frontend) with Laravel 5.8.27 (backend as REST API). I'm trying to setup PWA (Progressive Web App) for this project so I don't need to use mobile browser directly.
I prepared manifest.json and all the icons using generator from https://app-manifest.firebaseapp.com/:
{
"name": "TRT",
"short_name": "TRT",
"display": "fullscreen",
"orientation": "portrait",
"start_url": "/",
"scope": "/",
"icons": [
{
"src": "images/icons/icon-72x72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "images/icons/icon-96x96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "images/icons/icon-128x128.png",
"sizes": "128x128",
"type": "image/png"
},
{
"src": "images/icons/icon-144x144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "images/icons/icon-152x152.png",
"sizes": "152x152",
"type": "image/png"
},
{
"src": "images/icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "images/icons/icon-384x384.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "images/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"splash_pages": null
}
Then I needed to setup service-worker.js file in my "public" folder of my project. I used https://laravel-mix.com/extensions/workbox
I installed it and included this module in webpack.mix.js file which is in root folder of this project. I've just put a line to require 'laravel-mix-workbox' and in 'mix' object I added additional method '.generateSW()'. It looks like this:
const mix = require('laravel-mix');
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for the application as well as bundling up all the JS files.
|
*/
require('laravel-mix-react-css-modules');
require('laravel-mix-workbox');
mix.react('resources/js/app.js', 'public/js')
.reactCSSModules()
.generateSW();
Then I put the link to manifest.json file
<link rel="manifest" href="manifest.json">
and JS script in main index file:
<script>
// Check that service workers are supported
if ('serviceWorker' in navigator) {
// Use the window load event to keep the page load performant
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js');
});
}
</script>
to register the serive-worker.js which was created when I run
npm run dev
So, after that I went to my browser to check if it's ok. There is manifest.json file when I go to http://127.0.0.1:8000/manifest.json and there is also service-worker.js file in public folder of my project which looks like this:
/**
* Welcome to your Workbox-powered service worker!
*
* You'll need to register this file in your web app and you should
* disable HTTP caching for this file too.
*
* The rest of the code is auto-generated. Please don't update this file
* directly; instead, make changes to your Workbox build configuration
* and re-run your build process.
*/
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
importScripts(
"/precache-manifest.5e21538faef9d96ee3cc4d11ed2229cf.js"
);
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'SKIP_WAITING') {
self.skipWaiting();
}
});
/**
* The workboxSW.precacheAndRoute() method efficiently caches and responds to
* requests for URLs in the manifest.
*/
self.__precacheManifest = [].concat(self.__precacheManifest || []);
workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
So, when I went to the Google Dev Tools (Application tab) to see if everything is ok, it turned out that there's manifest.json file but there's problem with service-worker. The message is
"No matching service worker detected. You may need to reload the page, or check that the scope of the service worker for the current page encloses the scope and start URL from the manifest."
So I started to test scenarios of "start_url" and "scope" in manifest.json but I left it with "/" because it's my root folder.
I started to search stack and Google for solution. I found that there should be SSL set up for this project (Is it really needed in development environment?) so I used Laravel's Homestead to setup a project with SSL. No I have: https://project.test working. Then it turned out that in Google Dev Tools (Application tab) there is still "No matching service worker detected. You may need to reload the page, or check that the scope of the service worker for the current page encloses the scope and start URL from the manifest.".
I went to the Service Worker tab there and it shows service-worker.js file but with a problem. I went to console to see this:
Uncaught (in promise) TypeError: Failed to fetch in service-worker.js:1
Now I have no idea what causes the problem. When it comes to the fact that I shouldn't change the service-worker.js file which is autogenerated, what can I do to solve the problem. Can you help ?
Found a solution. There was problem with webpack configuration. I've just added to webpack.mix.js
const { GenerateSW } = require('workbox-webpack-plugin');
mix.webpackConfig({
plugins: [new GenerateSW()],
output: {
publicPath: ''
}
});
That solved the problem.

Error while running Paypal API using node js

I am running the following code in a script called pp.js. And I am running this on my index.html on loading of the page for test. I am bundling every source files using the latest webpack module.
var paypal = require('paypal-rest-sdk');
var user_config ={
'mode': 'sandbox', //sandbox or live
'client_id': 'xxxxxxx',
'client_secret': 'xxxxxxx'
};
paypal.configure(user_config);
var create_payment_json = {
"intent": "sale",
"payer": {
"payment_method": "paypal"
},
"redirect_urls": {
"return_url": "http://return.url",
"cancel_url": "http://cancel.url"
},
"transactions": [{
"item_list": {
"items": [{
"name": "item",
"sku": "item",
"price": "1.00",
"currency": "USD",
"quantity": 1
}]
},
"amount": {
"currency": "USD",
"total": "1.00"
},
"description": "This is the payment description."
}]
};
// TILL HERE THERE IS NO ERROR
paypal.payment.create(create_payment_json, function (error, payment) {
if (error) {
console.log("There seems to be some error... I hope it can be corrected.");
throw error;
} else {
console.log("Create Payment Response");
console.log(payment);
}
});
When the last bit of the code is run i.e. paypal.payment.create(create_ ... I am getting the following error in the console of my browser.
How do I rectify this?
This code should be run server-side. The same issue in PayPal SDK tracker: https://github.com/paypal/PayPal-node-SDK/issues/220
Quote 1 (from the linked ticket)
Please see #149 (comment). It seems that you are trying to run this code in the browser which may be a security problem. If the user has access to your credentials or have an access token, they can do anything that you can do as a merchant (e.g. create more payments, refund people money, etc.).
Quote 2 (from the #149 ticket):
I did some more investigation. Apparently, this request.js:54 Uncaught Error: Invalid value for opts.mode. error comes from a version of stream-http/request.js. I'm guessing that you are trying to use browserify and using stream-http in the browser to simulate node.js's built-in http module.
Are you trying to run this SDK code in the browser (instead of in a server-side node.js process)?
This node.js SDK should only be used on a secured server. I have very limited experience using browserify. Unless I'm mistaken, you need to give this SDK access to your client ID and client secret to make this SDK work, and if your code runs in the browser, you will be exposing the credentials to any browser client. This will allow any customer to be able to do anything to your account (e.g. refund all of your payments).
If it's just that part of your code is intended to be run in the browser and another part is in the server but the code is all in one project, I recommend separating out the code into 2 different projects with different package.json files so you can have separate dependencies.

Uncaught SyntaxError: Identifier 'baseUrl' has already been declared

I have a Polymer webapp deployed using Firebase hosting.
The routing between views works but the error page handling is not.
I have succeeded to reproduce the issue on a minimal example using the official polymer-2-starter-kit example:
https://fir-polymer-404-issue.firebaseapp.com/
For instance, if you open the following URL, the error page is not displayed:
https://fir-polymer-404-issue.firebaseapp.com/not-existing
Instead, I get the error below:
my-not-existing.html:56 Uncaught SyntaxError: Identifier 'baseUrl' has already been declared
at my-not-existing.html:56
(anonymous) # my-not-existing.html:56
The configuration file firebase.json used for the previous example is here:
{
"hosting": {
"public": ".",
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}
I would like to have the error page handling made by Polymer.
Please note that the same app served by polymer serve works properly.
It seems the problem comes from the Firebase hosting configuration. All traffic is redirected to index.html so when Polymer load a not-existing page, the Firebase server returns an HTTP 200 response. Unfortunately, I have no idea how to fix the problem.
I have tried to create a redirection for non-404 responses only with the following configuration file:
{
"hosting": {
"public": ".",
"redirects": [
{
"source": "**",
"destination": "/index.html",
"type": 200
}
]
}
}
Unfortunately, the type property can be used for 3xx code only:
Error: HTTP Error: 400, hosting.redirects[0].type is not one of enum values: 301,302,303,304,305,307,308
Please also note that a custom 404.html file is placed at the root.
The only solution I see is to list all existing routes (per file) but it looks just crazy.
Any idea is welcome.
The reason neither firebase or polymer is going to handle your 404 page is that when you request a non-existing page, it's not only going to return with the status code 200 but it's also going to return with the HTML of the index page, so it will display something, although that something is really nothing.
Now the way polymer is set up it looks for views in the src folder, so you want a rewrite just on the root and not in the src folder. So change your firebase.json to be
{
"hosting": {
"public": ".",
"rewrites": [{
"source": "/*",
"destination": "/index.html"
}]
}
}
The single * will mean files but not subfolders, this will allow your routeing to work if you enter it in the address bar but if the page is not found the 404 will be handled by polymers routeing. I've set up a firebase application using the polymer starter pack to for an example.
https://testforsoissue.firebaseapp.com/view2
Will work and will take you to view2 as the initial request will be rewritten to return index.html but the request for /src/my-view2.html will not
Whereas a route that is not defined
https://testforsoissue.firebaseapp.com/not-existing
Will throw a 404 (in polymer) as the initial request will again be rewritten to return index.html but the request for /src/my-not-existing.html will not and will happily throw a 404!
P.S. the reason for the error 'baseUrl' has already been declared' is due to the fact the page was using the index.html twice which declares the baseUrl at the top
Edit
If you have subpaths seems like you can use the firebase.json like so
{
"hosting": {
"public": ".",
"rewrites": [{
"source": "!/src/*",
"destination": "/index.html"
}]
}
}
As per documentation, you do not need to do the handling; just create a 404.html:
You can specify a custom 404/Not Found error to be served when a user tries to access a page that does not exist. Simply add a 404.html page to the your project's public directory and the contents of this page will be displayed when Firebase Hosting needs to display a 404 Not Found error to the user.
To avoid the baseUrl error, if you have access to this line of code:
let baseUrl = document.querySelector('base').href;
Try changing it for:
baseUrl = baseUrl || document.querySelector('base').href;
It's not very neat, but it should not complain about the value being defined already.
Although I think this is unrelated to your problem and may stop showing this error once a proper 404 page is defined.

ng-lb command in StrongLoop fails when using local-storage-connector

Dear Strongloop community
I am following the example provided by loopback for evaluating local-storage data store.
It works fine and I can use the rest API to create and retrieve files from the local file system (used as a data source).
I had to used "$ npm install loopback-component-storage --save".
the datasource defined in datasource.json is:
{
"db": {
"name": "db",
"connector": "memory"
},
"localFileSystemStorage": {
"name": "localFileSystemStorage",
"connector": "loopback-component-storage",
"provider": "filesystem",
"root": "./property_data"
}
}
the ./property_data directory is where all the data is stored. (relative to the project directory) and I can access it through rest with no issues.
Next I was trying to generate Angular service component so I can connect to the loopback server using Angular application. So inside the client directory I executed:
../example-2.0/client$ lb-ng ../server/server.js js/lb-services.js
and it failed:
/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback-component-storage/lib/providers/filesystem/index.js:25
throw new Error('FileSystemProvider: Path does not exist: ' + this.root);
^
Error: FileSystemProvider: Path does not exist: ./server/storage
at new FileSystemProvider (/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback-component-storage/lib/providers/filesystem/index.js:25:11)
at Object.module.exports.createClient (/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback-component-storage/lib/providers/filesystem/index.js:17:10)
at Object.createClient (/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback-component-storage/lib/factory.js:86:18)
at new StorageService (/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback-component-storage/lib/storage-service.js:29:25)
at Object.exports.initialize (/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback-component-storage/lib/storage-connector.js:12:19)
at DataSource.setup (/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback-datasource-juggler/lib/datasource.js:332:17)
at new DataSource (/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback-datasource-juggler/lib/datasource.js:109:8)
at Registry.createDataSource (/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback/lib/registry.js:349:12)
at dataSourcesFromConfig (/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback/lib/application.js:415:19)
at EventEmitter.app.dataSource (/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback/lib/application.js:222:12)
Am I missing something?
I could really use some help here.
Thanks
In datasource.json file you have provided the relative path ./property_data with respect to /server folder.
Thus you need to call any method from that folder only.
Now when you are running it through the server then you are running it from /server folder thats why it runs without an issue but for angular Sdk generation you are doing it from client/ folder. Thus its genetating Path does not exist error.
Thus the correct syntax would be:
../example-2.0/server$ lb-ng server.js ../client/js/lb-services.js

Categories

Resources