This is essentially a continuation of the question here: Nodejs Passport display username.
app.get('/hello', function(req, res) {
res.render('index.jade', { name: req.user.username });
});
So users log in via PassportJS, and goes to index.jade, which contains #{name} in the body, which will be replaced by the value of req.user.username.
Question: Is it possible to use the value of req.user.username in index.jade's JavaScript? I tried assigning its value to a variable but it doesn't work.
I have been using the trick of having a hidden input with #{name} as value:
input(type='hidden', id='variableName', value='#{name}')
Then JavaScript can access this value using:
$("#variableName").val()
This works. But does it have any potential downside like security issues? What is the right way to do this?
You have a few options. One of them is what you did and put the value inside you html. You can also solve it by doing:
script
window.name = #{name};
This will create an inline script that sets the variable. The other option you have is using ajax. That means you probably need to make an extra route to reply to that request.
Related
I have a question regarding Cypress assertions, just recently start playing with this testing platform, but got stuck when the URL returns a random number as shown below.
/Geocortex/Essentials/REST/sites/SITE?f=json&deep=true&token=SK42f-DZ_iCk2oWE8DVNnr6gAArG277W3X0kGJL1gTZ7W5oQAAV9iC4Zng4mf0BlulglN-10NK&dojo.preventCache=1575947662312
As you can see token is random and dojo.preventCache is also a random string. I want to detect this url and check if deep=true regardless the token number, but I don't know how to achieve this.
cy.location('origin', {timeout: 20000}).should('contain', '/Geocortex/Essentials/REST/sites/SITE?f=json&deep=true&token=**&dojo.preventCache=**');
Anyone any idea?
You can check both the path and query like this (note that cy.location('origin') doesn't yield neither pathname nor query from your original question, so I'm using cy.url()):
cy.url()
.should('contain', '/Geocortex/Essentials/REST/sites/SITE')
.should('contain', 'deep=true');
or check each separately:
cy.location('pathname').should('contain', '/Geocortex/Essentials/REST/sites/SITE');
cy.location('search').should('contain', 'deep=true');
or, use a custom callback in which you do and assert whatever you want:
cy.url().should( url => {
expect(/* do something with url, such as parse it, and access the `deep` prop */)
.to.be.true;
});
Is it a good idea to use function name property instead of constants for actions/mutations, like the code below?
Author of Vuex official documentation says that it is not required to use constants for actions/mutations. So I want to try to use type is based on function name.
Component:
this.$store.dispatch(authActions.login.name, {
email: this.email,
password: this.password
})
Action:
async login(context, { email, password }) {
// some code
}
I am waiting for the following answers:
1) Yes, you can use it, there are no potential problems with this
approach.
2) Yes, but these problems [problems] can happen.
3) No, there are a lot of problems: [problems].
I think it's option number 2).
The problem comes when you want to dispatch namespaced modules actions.
You can do this and it does work, but I noticed when I minify my code for production it stops working.
I suspect there's some code that maps the function names (ie login()) to their minified version (ie h()) during bundling, and that's breaking things.
I've been trying to figure this out for a while with no luck. I agree defining constants to use as function names, instead of grabbing the name after like myFunction.name, is stupid. I'll update my comment if I figure it out. I'll keep trying...
I want to access context variable to use the isMobile flag to select a different endpoint depending on the result. I could pass it on the dispatch from the component, but I know there should be one way to do it.
export const actions = {
...
signUpGoogle({ commit }) {
fireauth.useDeviceLanguage()
if (context.isMobile) {
fireauth.signInWithPopup(GoogleProvider).then ...
} else {
fireauth.signInWithRedirect(GoogleProvider)
}
}
I saw here that it can be obtained on server init, but I really don't want to rely on this as caching will mess things up
https://nuxtjs.org/guide/vuex-store/#the-nuxtserverinit-action
Thanks for the help
I'm not sure if you're talking about an environment variable here, but below is the answer if it is.
Looking on this GH issue, we can find out that you can use this.app.$config.isMobile (basically referencing env variables aka publicRuntimeConfig values in your nuxt.config.js).
You can do one thing in nuxtServerInit, set this variable in state using the context, and then use state.isMobile to do this type of API Calls. Hopefully, that should solve this.
If it's not very clear, I can edit to give some code examples
I want to implement a mechanism to obfuscate the id fields in my application . Right now all the id fields are integers. I want to use some sort of reversible hashing to create random strings corresponding to the id fields. Also, I am trying to accomplish this with minimal changes to the overall project.
One thing that came to my mind was to write a middleware to intercept every request and response object and check for the presence of id field. If the request contains id field and it is an obfuscated version, decode the string and replace the request parameter with the integer id.
If the response contains the integer id, run the encode function on it to send the obfuscated id to the client.
The problem I am facing is with modifying the req object. The id field can be present in req.body or req.params or res.query. However, in the middleware, I cannot see the id field when it is present in req.params.
I tried using policies. But the problem I am facing there is even after changing the req.params, the changes are lost when the control reaches the controller. What would be the recommended way of solving this problem ?
Here is the sample code:
In the policy:
module.exports = function (req, res, next) {
req.params.id = '12345';
req.query.pageSize = 30;
req.body = {};
sails.log.info('req.params', req.params);
sails.log.info('req.query', req.query);
sails.log.info('req.body', req.body);
return next();
};
I am just modifying values of req.params, req.query and req.body.
When I try to access these values in the controller, the values of req.query and req.body are the modified values as changed in the policy. However, req.params changes back to what was sent by the client and the changes made in the policy are lost
I think you are confusing policy and middleware? Is your code above in api/policies? If so, you still need to define which controller(s) this policy is applied to in config/policies.
So config/policies.js should look like:
modue.exports.policies = {
// If you really want this policy for every controller and action
'*': 'policyName.js',
// If you want it for a specific controller. '*' denotes every action in controller
specificController: {
'*': 'policyName.js'
},
// If you want it for a specific action on a specific controller
specificController: {
'specificAction': 'policyName.js'
}
};
Also I'd like to add. Policies are generally meant for authorization of controllers but this seems like a decent use case. Since every single request is not going to have these fields this should be a policy. Policies are great when applying something to a handful of controllers/actions. Middleware is great when you need to apply to every single action that comes into your app.
http://sailsjs.org/documentation/concepts/policies
http://sailsjs.org/documentation/concepts/middleware
Gitter response:
sgress454 #sgress454 10:45
#mandeepm91
In the policy, if I change req.body or req.query, the changes persist in the next policy or controller. However, changes made to req.params are lost.
This is one of the main use cases for req.options. This object is intended to be used to store request data that can be mutated by one handler before being passed on to the next. The req.params object is meant to provide each handler with a copy of the original request parameters.
How you approach this really depends on what your goal is. If you really need each request handler (that is, policies and controller actions) to see an encoded version of the ID, then a good approach would be to encode the ID in a policy as #S-Stephen suggested, store that value in req.options.id and refer to that in your other request handlers. If, on the other hand, you're really only concerned with the response having the encoded ID, the suggested practice is to use the res.ok() response in your handlers (rather than res.send() or res.json), and adjust the code for that response in api/responses/ok.js to encode the ID before sending. You can also use a custom response if this is only required for certain requests. See custom responses for more info.
Hi #sadlerw, you should be able to modify the code for res.ok() in your api/responses/ok.js file to have it always return JSON if that's what you want for every response. If it's something you only want for certain actions, you could create a custom response instead and use that where appropriate.
I'm writing a simple API, and building a simple web application on top of this API.
Because I want to "consume my own API" directly, I first Googled and found this answer on StackOverflow which answers my initial question perfectly: Consuming my own Laravel API
Now, this works great, I'm able to access my API by doing something like:
$request = Request::create('/api/cars/'.$id, 'GET');
$instance = json_decode(Route::dispatch($request)->getContent());
This is great! But, my API also allows you to add an optional fields parameter to the GET query string to specify specific attributes that should be returned, such as this:
http://cars.com/api/cars/1?fields=id,color
Now the way I actually handle this in the API is something along the lines of this:
public function show(Car $car)
{
if(Input::has('fields'))
{
//Here I do some logic and basically return only fields requested
....
...
}
I would assume that I could do something similar as I did with the query string parameter-less approach before, something like this:
$request = Request::create('/api/cars/' . $id . '?fields=id,color', 'GET');
$instance = json_decode(Route::dispatch($request)->getContent());
BUT, it doesn't seem so. Long story short, after stepping through the code it seems that the Request object is correctly created (and it correctly pulls out the fields parameter and assigns id,color to it), and the Route seems to be dispatched OK, but within my API controller itself I do not know how to access the field parameter. Using Input::get('fields') (which is what I use for "normal" requests) returns nothing, and I'm fairly certain that's because the static Input is referencing or scoping to the initial request the came in, NOT the new request I dispatched "manually" from within the app itself.
So, my question is really how should I be doing this? Am I doing something wrong? Ideally I'd like to avoid doing anything ugly or special in my API controller, I'd like to be able to use Input::get for the internally dispatched requests and not have to make a second check , etc.
You are correct in that using Input is actually referencing the current request and not your newly created request. Your input will be available on the request instance itself that you instantiate with Request::create().
If you were using (as you should be) Illuminate\Http\Request to instantiate your request then you can use $request->input('key') or $request->query('key') to get parameters from the query string.
Now, the problem here is that you might not have your Illuminate\Http\Request instance available to you in the route. A solution here (so that you can continue using the Input facade) is to physically replace the input on the current request, then switch it back.
// Store the original input of the request and then replace the input with your request instances input.
$originalInput = Request::input();
Request::replace($request->input());
// Dispatch your request instance with the router.
$response = Route::dispatch($request);
// Replace the input again with the original request input.
Request::replace($originalInput);
This should work (in theory) and you should still be able to use your original request input before and after your internal API request is made.
I was also just facing this issue and thanks to Jason's great answers I was able to make it work.
Just wanted to add that I found out that the Route also needs to be replaced. Otherwise Route::currentRouteName() will return the dispatched route later in the script.
More details to this can be found on my blog post.
I also did some tests for the stacking issue and called internal API methods repeatedly from within each other with this approach. It worked out just fine! All requests and routes have been set correctly.
If you want to invoke an internal API and pass parameters via an array (instead of query string), you can do like this:
$request = Request::create("/api/cars", "GET", array(
"id" => $id,
"fields" => array("id","color")
));
$originalInput = Request::input();//backup original input
Request::replace($request->input());
$car = json_decode(Route::dispatch($request)->getContent());//invoke API
Request::replace($originalInput);//restore orginal input
Ref: Laravel : calling your own API