NestJs Guard : enable guard on resolverField without error - security

i have this ,
#Roles(ROLES.ADMIN)
#ResolveField('product', () => String)
async getProduct(#Parent() product: Product) {
return this.productService.getProduct(product);
}
i already add fieldResolverEnhancers: ['guards']
in appModule
my graphQl request gives me an error
"message": "Forbidden resource",
"path": [
"user",
"product"
],
witch is the expected behavior
, what i need is that the request succeed ,but return null as product value if Role !== ADMIN
any suggestions ? thanks

Related

How to configure custom validation error message in #hapi/joi when using validateAsync?

I am new trying to validate the incoming data i.e. request into my rest API and if correct then passing the control of the execution to controller folder where other logic executes. My request validates successfully and throws the error if req is incorrect in the format -> "error": "\"fname\" must only contain alpha-numeric characters".
But I want it in this format ->
"errors": [
{
"field": "firstname"
"msg": "Bad Request..whatever i want here"
"type": "Invalid"
}
]
This is my code -
const joi = require('#hapi/joi');
const sschema = joi.object({
servicename: joi.string().min(6).max(9).required(),
firstname: joi.string().min(4).max(255).required(),
lastname: joi.string().min(4).max(255).required(),
address: joi.string().min(20).max(256).required(),
countrycode: joi.string().length(2).valid('ca', 'us', 'uk', 'in').required()
});
const parametersValidation = async (req, res, next) => {
try {
await sschema.validateAsync(req.body, { abortEarly: true });
} catch (error) {
let var1 = error.details[0].message;
return res.status(400).send({
errors: [
{
type: 'Invalid',
field: var1,
message: 'Bad Request',
},
],
});
}
next(); // next will control the transfer to controller if all things are correct.
};
P.S. - I am using hapi/joi - 17.1.1 AND .messages() method is not working either I tried.

What is the correct JSON format for googles classroom.create?

Im trying to create a classroom using googles classroom API. Whenever run the classroom.create function I always receive the same error message. I'm using the JSON format from their docs but I just can't get it to work. I think I must be missing something.
This is the function:
async function listCourses(auth) {
const classroom = google.classroom({ version: 'v1', auth });
//Read data from JSON
let data = fs.readFileSync("class.json");
let course = JSON.parse(data);
//Try and create course
try {
const res = await classroom.courses.create(course);
console.log(res.data);
}
catch (error) {
console.log(error)
}
//List all current courses
classroom.courses.list({
pageSize: 10,
}, (err, res) => {
if (err) return console.error('The API returned an error: ' + err);
const courses = res.data.courses;
if (courses && courses.length) {
console.log('Courses:');
courses.forEach((course) => {
console.log(`${course.name} (${course.id})`);
});
} else {
console.log('No courses found.');
}
});
}
This is the JSON:
{
"id": "157942918368",
"name": "English - 9Y",
"section": "Period 2",
"ownerId": "me",
"courseState": "ACTIVE"
}
This is the error message:
code: 400,
errors: [
{
message: `Invalid JSON payload received. Unknown name "name": Cannot bind query parameter. Field 'name' could not be found in request message.\n` +
`Invalid JSON payload received. Unknown name "ownerId": Cannot bind query parameter. Field 'ownerId' could not be found in request message.\n` +
`Invalid JSON payload received. Unknown name "courseState": Cannot bind query parameter. Field 'courseState' could not be found in request message.\n` +
`Invalid JSON payload received. Unknown name "id": Cannot bind query parameter. Field 'id' could not be found in request message.\n` +
`Invalid JSON payload received. Unknown name "section": Cannot bind query parameter. Field 'section' could not be found in request message.`,
reason: 'invalid'
}
]
I believe your goal as follows.
You want to create new course using googleapis for Node.js.
Modification points:
At googleapis for Node.js, please put the request body to resource and/or requestBody.
I think that the reason of your error message is due to this.
When "id": "157942918368", is used, an error of Request contains an invalid argument. occurs.
When "courseState": "ACTIVE" is used, an error of "#CourseStateDenied This user cannot create or transition courses into the requested state." occurs.
"PROVISIONED" can be used in this case.
When above points are reflected to your script, it becomes as follows.
Modified script:
From:
const res = await classroom.courses.create(course);
To:
const res = await classroom.courses.create({ requestBody: course });
or
const res = await classroom.courses.create({ resource: course });
And also, please modify your request body as follows.
From:
{
"id": "157942918368",
"name": "English - 9Y",
"section": "Period 2",
"ownerId": "me",
"courseState": "ACTIVE"
}
To:
{
"name": "English - 9Y",
"section": "Period 2",
"ownerId": "me",
}
Note:
In this modification, it supposes that your const classroom = google.classroom({ version: 'v1', auth }); can be used for using the method of courses.create in Classroom API.
References:
Method: courses.create
googleapis for Node.js

Custom response Express Validator as JSON

I'm using Express Validator for validate user req. I'm trying to create custom response like this:
{
"code": 300,
"status": false,
"message": "Your email is not valid",
"param": "email",
"value": "kevin"
}
but what I got is
[
{
"code": 300,
"status": false,
"message": "Your email is not valid",
"param": "email",
"value": "kevin"
}
]
Here is my code:
controller.js:
const errors = validationResult(req).formatWith(utils.error);
if(!errors.isEmpty()){
res.status(300).json(errors.array());
}
ResUtils.js
error({msg, param, value, nestedErrors}) {
var code = 300;
var format = {code, status:false, message:msg, param:param, value:value, nestedErrors:nestedErrors};
return format;
}
How do I can get the response as Json, without [].
Thankyou.
Well, this state is good in my opinion, there is possibility of multiple errors so you should process all messages in a frontend app (or mobile or whatever) to give user informations about all invalid fields (or options or whatever). If you really need only a object, you can pick a first error message from an array for example.
if(!errors.isEmpty()){
const errorsArray = errors.array();
res.status(300).json(errorsArray[0]);
}
But as I said it is better approach to handle all error messages.

AWS cognito: getCredentials not working

Im in the process of learning to use AWS Cognito. I have set up a userpool and a identity pool.
Code (simplified):
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: (result) => {
let cognitoGetUser = userPool.getCurrentUser();
if (cognitoGetUser != null) {
cognitoGetUser.getSession((err, result) => {
if (result) {
console.log ("Authenticated to Cognito User and Identity Pools!");
let token = result.getIdToken().getJwtToken();
let cognitoParams = {
IdentityPoolId: this.identityPool,
Logins: {}
};
cognitoParams.Logins["cognito-idp.eu-west-1.amazonaws.com/"+this.poolData.UserPoolId] = token;
AWS.config.credentials = new AWS.CognitoIdentityCredentials(cognitoParams);
AWS.config.getCredentials(() => {
console.log(AWS.config.credentials.accessKeyId)
console.log(AWS.config.credentials.secretAccessKey)
console.log(AWS.config.credentials.sessionToken)
}
}
}
}
},
onFailure: function(err) {
console.log('error');
console.log(err)
}
}
}
Most of the code works as expected: The authenticateUser fires the onSuccess and I can see a jwt token ect
Problem: I cant get the AWS.config.getCredentials to work. It executed without any errors, but accessKeyId, secretAccessKey and SessionToken are all undefined.
Any suggestions to what I'm doing wrong?
I cant get the AWS.config.getCredentials to work. It executed without any errors but,
This may be a mistaken assumption. Your abbreviated code is missing a couple of closing parentheses, but ran fine for me without any meaningful adjustments.
When calling getCredentials, any errors are "silently" reported through an error object. I would think you'd see a 400 response somewhere (network tab or console or both), but getCredentials() doesn't really report errors in a visible fashion by itself.
To see what is going wrong, you should add a parameter to the callback you pass to getCredentials():
AWS.config.getCredentials((err) => {
if (err) {
console.log(err);
} else {
console.log(AWS.config.credentials.accessKeyId)
console.log(AWS.config.credentials.secretAccessKey)
console.log(AWS.config.credentials.sessionToken)
}
});
For reference, one commonly encountered error object looks like this. Note that the useful message is found in originalError.message:
{
"message": "Could not load credentials from CognitoIdentityCredentials",
"code": "CredentialsError",
"time": "2018-06-03T15:19:02.078Z",
"requestId": "71b03b4a-6741-11e8-98af-b70a114474f8",
"statusCode": 400,
"retryable": false,
"retryDelay": 94.28032122526344,
"originalError": {
"message": "Invalid login token. Issuer doesn't match providerName",
"code": "NotAuthorizedException",
"time": "2018-06-03T15:19:02.078Z",
"requestId": "71b03b4a-6741-11e8-98af-b70a114474f8",
"statusCode": 400,
"retryable": false,
"retryDelay": 94.28032122526344
}
}
The corresponding 400 in the Network tab contains this response:
{"__type":"NotAuthorizedException","message":"Invalid login token. Issuer doesn't match providerName"}

Cannot read the whole webview callback from Gupshup.io API inside my cloud function

I have a Google Cloud function written in Node-js that gets invoked each time somebody submits a Gupshup's serverless webview form
I expect to receive the following input in my web service:
{
"linkId": "f42414e2-ce1a-4bf5-b40a-e88e4d4d9aee",
"payload": [{
"fieldname": "name",
"fieldvalue": "Alice"
},{
"fieldname": "gender",
"fieldvalue": "Male"
},{
"fieldname": "account",
"fieldvalue": "savings"
},{
"fieldname": "interest",
"fieldvalue": "Cooking"
}],
"time": 1479904354249,
"userid": "UserID"
}
But i'm having trouble getting the objects inside "payload", time and userid objects.
This is my code:
exports.orderForm = (req, res) => {
const data = req.body;
const ref = data.userid;
var propValue;
console.log(req.method); // POST
console.log(req.get('content-type')); // application/x-www-form-urlencoded
console.log(req.body.linkid); // undefined
console.log(req.body.payload[0].fieldname); // cannot read property from undefined error
console.log(req.body.time); //undefined
console.log(req.body.userid); // undefined
// I attemp to print the properties, but they won't print
for(var propName in req.body.payload) {
propValue = req.body.payload[propName];
console.log(propName, propValue);
}
console.log('JSON.stringify: ' + JSON.stringify(req.body)); // This prints the following:
// JSON.stringify: {"{\"linkId\":\"f42414e2-ce1a-4bf5-b40a-e88e4d4d9aee\",\"payload\":":{"{\"fieldname\":\"account\",\"fieldvalue\":\"savings\"},{\"fieldname\":\"name\",\"fieldvalue\":\"Alice\"},{\"fieldname\":\"gender\",\"fieldvalue\":\"Male\"},{\"fieldname\":\"interest\",\"fieldvalue\":\"Cooking\"}":""}}
res.sendStatus(200);
};
As you can see stringify allows to see all payload properties, but before that i cannot access them in the js object.
The second problem is that event after stringify i can't see time and userid.
What i suspect is i must handle requests of content-type="application/x-www-form-urlencoded" differently from what i'm used to, but i couldn't find any examples for that.
The response you receive from Gupshup to your callback after submission of the serverless webview form is already a stringified object.
Hence you need to parse it using JSON.parse() to get the JSON object and then you will be able to get the values.
Sample code
exports.orderForm = (req, res) => {
const data = JSON.parse(req.body);
console.log(data.linkid); // undefined
console.log(data.payload[0].fieldname);
console.log(data.time);
console.log(data.userid);
};
This should resolve your issue.

Resources