How do I authenticate access to assets folder in sails.js - static

I am already using passport to authenticate users. I added kibana 3 to the assets folder and want users to access it only if they are authenticated. how do i do this ?

The assets folder is intended for publicly-available files, like your images and Javascripts. If you want to protect those files, you can either override the default www middleware in Sails, which activates the Express static handler to servet those files (see details on overriding default middleware in this answer), or save the files you want to protect in a different location and use a controller action to serve them (probably the more reasonable option).
So, you could save the files in protected_files, and add a route like this to config/routes.js:
'/protected/:file': 'ProtectedFileController.download'
then in controllers/ProtectedFileController:
var fs = require('fs');
var path = require('path');
module.exports = {
download: function(req, res) {
// Get the URL of the file to download
var file = req.param('file');
// Get the file path of the file on disk
var filePath = path.resolve(sails.config.appPath, "protected_files", file);
// Should check that it exists here, but for demo purposes, assume it does
// and just pipe a read stream to the response.
fs.createReadStream(filePath).pipe(res);
}
};
Then protect that controller / action using a policy like you would with any other area that needs authentication.

Related

One CloudFront, one S3 bucket to serve many react apps using Lambda#Edge

The company I work at wants to serve multiple react websites using a single S3 bucket and Cloudfront distribution as there is a limit to the number of buckets AWS allows. The base file structure we want to have has three folders at the root of the bucket (i.e. dev, prod, and sandbox), and each has its corresponding react project.
From the Cloudfront distribution, I send the Host header to know which environment and bucket should be served. I catch that in a Lambda#Edge function and route to the corresponding bucket, which works up to that point. The Lambda#Edge function gets the index.html file correctly but cannot serve all the other files in the folder. This results in just getting a blank white screen with a couple of errors in the console: The stylesheet was not loaded because its MIME type, "text/html" is not "text/css and Loaded file has not a valid JavaScript MIME type.
The Lambda#Edge function I use is the following:
'use strict';
exports.handler = (event, context, callback) => {
// Extract the request from the CloudFront event that is sent to Lambda#Edge
var cf = event.Records[0].cf;
var request = event.Records[0].cf.request;
const origin = request.origin;
const domain = request.headers.host[0].value;
if (domain.includes("dev")) {
request.uri = "/dev-test/index.html"
} else if (domain.includes("sandbox") {
request.uri = "/sandbox-test/index.html";
} else {
request.uri = "/prod-test/index.html";
}
request.headers.host[0].value = origin.s3.domainName
// Return to CloudFront
return callback(null, request);
}
That function extracts the domain from the Host header, sets the URI accordingly, and changes the Host header to the S3 domain name to avoid getting a permissions error. I have also tried changing the S3 path as well as the URI, changing only the path instead of the URI but nothing seems to work. I do not know if I should be setting/changing something else in the request or I should change the settings/permissions in my S3 bucket and/or Cloudfront distribution.
By the way, I am testing this with a basic React JS app, I only ran npx create-react-app my-app then built it and uploaded everything in the build folder to the S3 bucket folders.
Thank you very much in advance for any help in this matter.
Are all of your requests coming back with a 200 OK status and the correct content — you just see a blank screen with that console error? If that's the case, then the issue is that you need to set the mime type on the CSS file in order for your browser to display it. Some browsers like Chrome won't serve a CSS file without the text/css Content-Type header.
You have three ways to set it:
Add it as metadata to each CSS file in your S3 bucket
Use a Lambda#Edge origin response function to dynamically set the Content-Type header based on the file extension.
Create a new cache behavior with a path pattern of *.css and attach a Response Header Policy that sets the Content-Type of text/css as a custom header with Origin Override checked (this is free to use, and will perform faster than Lambda#Edge as it's a native feature)
Option 1 is the simplest if you add it as part of your upload workflow. Otherwise would recommend option 3.

How to server a ".html" at certain URL in a Next.js app?

I have an ".html" file that I need to serve in a certain route in my Next.js app, like this ...
/pages/customr-route-name/my-html-file.html
So if I go to my website and type http://example.com/custom-route-name/my-html-file.html I can see it
How can I do that in Next.js?
This one requires an API route and a URL rewrite to get working. And the nice thing is, you'll be able to use this pattern for other things too (like if you want to generate an RSS feed or a sitemap.xml).
NOTE: You will need to be running Next 9.5 for this to work.
0. Move your HTML file (Optional)
Your file doesn't need to be located in the ./pages dir. Let's put it in ./static instead. Just replace your these route-file placeholders with your real filename later: ./static/<route>/<file>.html
1. Create the API route
Next lets you create API routes similar to how you would in an old-style host like Express. Any name is fine as long as it's in ./pages/api. We'll call it ./pages/api/static/<route>/<file>.js
// import
import fs from 'fs';
// vars
const filename = './static/<route>/<file>.html';
// export
export default async function api(req, res) {
res.setHeader('Content-Type', 'text/html; charset=utf-8');
res.write(await fs.readFileSync(filename, 'utf-8'));
res.end();
}
2. Add a rewrite to next.config.js
In Next, rewrites work similar to their apache counterparts. They map a url location to a Next ./page.
// export
module.exports = {
rewrites: async () => [
{source: '/<route>/<file>', destination: './pages/api/static/<route>/<file>'},
],
};
3. Run it!
You should be able to test this with a regular next dev. Of course, changes to next.config.js require you to manually reboot the dev server.
If you look at the Next docs, you'll see you can use wildcards in both the API routes and these redirects, which might help with the direction you're going.
Update for NextJS Version 11
In your public folder you can create a folder structure patterned after the URL you want.
For example:
public/custom-path-folder-name/file.html
will be served at:
http://localhost:3000/custom-path-folder-name/file.html
For more information see the nextjs docs for static file serving

Express Rewriting for Clean URLs in MEAN Stack Application with no index.html

Like many other clean angular URL rewrites, upon refreshing the page on a clean URL like localhost:3000/profile I get the GET /profile 404 error. I have been trying to use an Express Rewrite to send the index.html file, but as far as I know, I don't have an index.html to send, as it's not rendered until the index.js route.
I tried the following in my app.js:
app.all('/*', function(req, res, next) {
// Just send the index.html for other files to support HTML5Mode
res.sendFile('index.html', { root: __dirname });
});
and receive Error: ENOENT: no such file or directory, stat 'C:\xampp\htdocs\healthyu\healthyu\index.html'
My directory looks like this image here, and I can see there is no index.html file in the root directory. I have tried views/index.html, views/index.ejs, and views/index with no luck, and views/index.ejs actually prompted a download when I refreshed the page.
Is there a way to use Express to successfully rewrite the URLs, or will I be more successful with a mod-rewrite in an .htaccess file?
So what I needed to do was change all of my server requests that were API requests to use the /api prefix, so get /api/posts in order to reduce conflicts with get /posts which was the original API call and view name along with other conflicts.
My index.html is generated in my express routes/index.js file so I just needed to make sure I used that file whenever I tried to navigate to a different URL than the home entry point. The relevant parts of the code looked like the following:
var index = require('./routes/index');
var users = require('./routes/users');
app.use('/', index);
app.use('/api', index);
app.use('/users', users);
app.use("/*", index);

How to send an AngularJS file with ExpressJS?

I'm new with ExpressJS, I have a small example using EJS, but I want use AngularJS for manipulating the DOM. Both technologies offer me DOM manipulation, so why some people use it together? I don't understand.
I have no idea how to render HTML files. What is the correct way to use AngularJS with ExpressJS?
res.render('index.html');
As far as I know EJS is really for templating, none of the embedded js is executed on the client.
Personally I have found some cases where it is handy to use a templating language with AngularJS or any client side framework. For example, sometimes it is nice to be able to interpolate some csurf tokens, or session data required by the client app into your html on the server. Other times it is not necessary.
As for rendering html, use the express.static middleware. It comes with Express, you pass a file path, and it returns a handler that will serve the contents of a given directory. You could put express.static anywhere in your middleware chain, but I usually put it at the top to avoid naming issues. Read the documentation for more information.
Consider the following:
var express = require('express')
var app = express();
// Asssuming we have a directory
// `public` in the root of the application
app.use('/', express.static(__dirname + '/public'));
// now you're serving all the files in public directory off the root path
// Add middlewares and routes...
For a really simple app you could you use the fs module, and stream the contents of a file to the response. The following is naive example of how you could do this, in production you would want to listen for error events and implement some cache control.
app.get('/', function(req, res) {
res.set('Content-Type', 'text/html');
fs.createReadStream('./index.html').pipe(res);
});
Please use this :to render first time
and for more information please go her http://www.tutorialspoint.com/nodejs/nodejs_express_framework.htm
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.sendFile( __dirname + "/" + "index.html" );
})

ng-file-upload. How to configure the location where the file needs to be uploaded

Using ng-file-upload.js to upload files. Two questions: To which location the files get uploaded by default and how to change this location?
From github documentation (https://github.com/danialfarid/ng-file-upload)
var upload = Upload.upload({
url: 'server/upload/url', // upload.php script, node.js route, or servlet url
...
Alternative way of uploading, send the file binary with the file's content-type.
Could be used to upload files to CouchDB, imgur, etc... html5 FileReader is needed.
It could also be used to enable progress for regualr angular $http() post/put requests.
var uploadHttp = Upload.http({
url: '/server/upload/url',
...

Resources