Adding property to the request using Node and Express - express

I have a MEAN application, and I'm handling authentication using passport. What I want to do is exactly what happens to the user on the passport, which can be accessed from the request like req.user. I have not found any solutions to reach that result. Can you give me any advice?

You can add properties to the request or response objects by creating a middleware and using it in your app. E.g.
// Defining middleware
function myMiddleware(req, res, next) {
req.myField = 12;
next();
}
// Using it in an app for all routes (you can replace * with any route you want)
app.use('*', myMiddleware)
Now all your request objects in your handlers will have myField property.

To add extra properties to the request and response object you need to extend the response and request interface.
index.d.ts files are used to provide typescript type information about a module that’s written in JavaScript.For express, the index.d.ts is present inside the #types/express folder inside the node_modules folder.
Use this link-
https://dev.to/kwabenberko/extend-express-s-request-object-with-typescript-declaration-merging-1nn5

Related

Is there a way to apply middlewares on all of specific request method?

I have been working on a typescript project. I have created a middleware to check users' subscription and do not want to let users access PUT and POST routes. But I still want them to be able to access GET and DELETE requests.
I know that the following line applies the checkSubscription middleware to all the requests on the route.
router.use(checkSubscription)
I only want the middleware to run if the request type is PUT or POST.
I could do the following, of course
router.get("/endpoint1", controller1);
router.put("/endpoint2", checkSubscription, controller2);
router.post("/endpoint3", checkSubscription, controller3);
router.delete("/endpoint4", controller4);
Notice that the above PUT and POST requests run the checkSubscription middleware.
But if I could declare on the top of the route file to run the middleware on all POST and PUT requests, that would save a lot of work and time.
Any kind of help would be highly appreciated. Thanks!
You can restrict the middleware to PUT and POST requests by evaluating the req.method inside:
function checkSubscription(req, res, next) {
if (req.method !== "PUT" && req.method !== "POST") return next();
// Rest of your middleware code
}
This keeps the rule "this middleware is only for PUT and POST" local to the middleware, no matter how often it is referenced in other statements like router.use and router.post.
But if I could declare on the top of the route file to run the middleware on all POST and PUT requests, that would save a lot of work and time.
You can just do something like this:
router.put("*", checkSubscription);
router.post("*", checkSubscription);
This will only call the checkSubscription() middleware for all PUT or POST requests that hit this router.
The "*" will match any path that goes through this router, but you could use any particular Express route pattern/regex there that you want if you want it to match more than one path, but not all paths.
As it sounds like you already know, you can also control route declaration ordering to give some routes a chance to handle the request before the middleware gets a shot to run.
Since Express runs middleware (including route handlers) in order, you can place the routes for which you don't want to run the middleware first, then the middleware, then the routes for which it does need to run:
router.get(...);
router.delete(...);
router.use(checkSubscription);
router.post(...);
router.put(...);
It does require some diligence with regards to app maintenance, because developers need to understand that the order in which the handlers are declared is relevant.

Authentication only for Admin prefix CakePHP 4

Hy guys!
I haven’t been using Cake from gen 2 so i am a bit stuck with all the new stuff. I added the Authentication Component to my project and it works fine (login/out/pass hash etc) but i can’t seem to find how to make only the “Admin” prefix to require Authentication.
In the old times was something “simple” like:
if($this->params[‘prefix’] == ‘admin’){
$this->Auth->deny(’*’);
}
While you could do something similar with the authentication plugin's authentication component, authentication is now performed at middleware level, that is before a controller is being invoked, hence it is probably best to avoid trying to authenticate a user in the first place when it's not actually needed.
Scope the middleware
With the authentication plugin there's a few way to handle this, the easiest way would probably be to apply the authentication middleware on routing level, so that it is scoped to your prefixed routes.
You'd just remove adding the middleware in your Application::middleware() method (src/Application.php), and instead add it in either your config/routes.php file, or your Application::routes() method, depending on where you're connecting your prefix route:
$routes->prefix('Admin', function (RouteBuilder $routes) {
$routes->registerMiddleware(
'auth',
new \Authentication\Middleware\AuthenticationMiddleware($this)
);
$routes->applyMiddleware('auth');
// ...
});
This way only the routes connected in that prefix are going have authentication applied.
Conditionally require an authenticated user
As a second step you'd still need to handle checking for the possibly authenticated user, so that your endpoints are actually protected. By default the authentication component will do automatically, so one way would be to load the authentication component only for the Admin prefix, for example in your AppController::initialize() method:
if ($this->request->getParam('prefix') === 'Admin') {
$this->loadComponent('Authentication.Authentication');
}
Note the capital A in Admin! In CakePHP 4.x prefixes on are now camel cased, while the generated URLs are lower cased and dash separated!
See also
Cookbook > Routing > Connecting Scoped Middleware
Cookbook > Routing > Prefix Routing
Cookbook > Request & Response Objects > Request > Request Parameters
I don't know if this is a conventional method, but it works.
In the callback method beforeFilter, in my global Appcontroller.php, I had this code:
public function beforeFilter(\Cake\Event\EventInterface $event)
{
if($this->request->getParam('prefix') == 'Api') {
$this->Authentication->allowUnauthenticated([$this->request->getParam('action')]);
}
}
}
It allows access to all methods of my prefix API.

Possible to add an `app` method through middleware in Express?

I am trying to write a middleware that creates a new method on app created with express(). For example, I would like to achieve the following:
app.use(myMiddleware())
// ...
app.newMethod() // added through the previous middleware
Is there a way to achieve this? A way I have thought of, as referenced in some other questions, is to pass in app itself as a param to my middleware so that I could tweak it:
app.use(myMiddleware(app))
// ...
app.newMethod() // ok, definitely doable
However, this does not seem elegant enough.
Also, req.app and res.app references won't work for me in this case, since the (req, res, next) => {} function returned by myMiddleware() only executes when receiving requests, while I possibly want to access the method before even app.listen() is called.
Is there a way I can achieve this?
It really doesn't make sense to add an app method in middleware. The purpose of middleware is to process an incoming request, either in preparation for later middleware or later request handlers or to just handle the request itself in the middleware.
Middleware gets called over and over during incoming requests. It should never be used for something that should just happen once and it should only be used for processing related to an incoming request.
while I possibly want to access the method before even app.listen() is called
So, that definitely has nothing to do with an incoming request then so using middleware is just not the right design choice.
If all you're trying to do is to add your own method to the app object, you can do that when you are initializing your server:
const app = require('express')();
// add my own method to the app object
app.myMethod = function(myArg1, myArg2) {
// put the implementation here
}
app.use(...);
app.get(...);
app.get(...);
app.listen(...);
Then, anywhere you want, you can call app.myMethod(...).

Handling laravel api resource store and create endpoints

I have the following in my controller
class WrittersController extends Controller
{
public function index()
{
return view('backend.writters.dashboard');
}
public function store(Request $request){
//confused on when to use this
}
public function create(Request $request){
//add new user functionality
}
Now in my routes i would like to use the resource routes
Route::resource('writters','WrittersController');
Now the confusion comes in my vue axios http endpoints. I uderstand that i index is a get request but axios doesnt have a store or create point.
When should i use the store and create endpoints in the vuejs
UPDATE ON MY AXIOS. Am using axios via
axios.post("url") //how do i go about create and store here
The store function is called when you want to create i.e you will create and then store. So I usually call the create method from inside the store. I do this just to seperate the code and make it more readable. There is no store or create http requests. The store uses post request. So you will need to use post request with axios. Just use Route::resource in your web.php and then go to the terminal and check your routes with
php artisan routes (laravel 4)
php artisan route:list (laravel 5)
This will list all your registered routes and tell you which functions they use.
You use the other resources in the same way you used it for the get request.
Assuming your resource route looks like the following.
Route::resource('/mydata', 'MyDataController');
You would construct your requests in the following manner.
As you observed already, if you use axios.get('/mydata') you are routed to the index method. However if you use axios.post('/mydata'), Laravel will automatically route you to the store method.
If you want to use the create action you change the url to use axios.get('/mydata/create') and you are routed to the create method. Please note that the create action is not used for creating the record but rather for fetching the view where the user will create the record, e.g. a form. Then you will store the data entered in that form with a POST request.
If you want to use PUT (or PATCH) you use axios.put(/mydata/{some_id}) and you are routed to the update method.
So Laravel handles all the routing automatically for you depending on the type of request that is made (GET, POST, PUT/PATCH, DELETE). You only need to supply a parameter in the URL for those "Verbs" that require it.
Look at the documentation here link Look for the chart or table labeled "Actions Handled By Resource Controller" and you will see the various actions what verbs to access them with, and their respective URLs and Routes.
Also note that you can add custom methods to the resource controller if needed, but you will have to define the route. You do this by declaring the route in your routes file e.g. web.php before you declare the actual resource.
Say you want to add an new post method 'archived' to mark some record as being no longer active. You would do something like the following in your routes.
Route::post('/mydata/archived/{some_id}', 'MyDataController#archive');
Route::resource('/mydata', 'MyDataController');
As demonstrated above you can use axios.put() or axios.patch() and they will both be routed to the update method. There are times when you need to handle those requests differently. For example when using a autosave feature and I want to validate some form data when only one field has changed, I would use patch to validate just that single field as follows.
public function update(Request $request, $id)
{
if($request->isMethod('patch')){
$this->validateSingle($request);
}else{
$this->validateAll($request);
}
//....
}

ExpressJs Routing: Could not find official documentation for '_startTime' property in request object

I need to check the time at which request is send to the server. For this I explored the 'req' object. It has a property of '_startTime' which gives me the System time of the Client machine from which request was sent.
I am not able to find the official documentation for this property.
From what I can see, _startTime is not something that Express sets on the request object.
The logger module morgan adds it, but it's convention that properties whose name starts with an underscore are "private": they are for internal use only, and should not be relied upon.
However, it's not very difficult to add such a property yourself. In Express, the most logical method would be to use a middleware function for that:
app.use((req, res, next) => {
req._requestStarted = new Date();
next();
});
Because it's your own application code that sets this property, you can always rely on it existing (as opposed to _startTime which, because it's for internal use by morgan, may be removed or renamed in the future).
To nitpick: this value does not reflect the system time of the client from which the request was sent, it's the time on the server at which the server received the request. In HTTP, clients generally don't send their own local time along with a request.