Client and server side validation in Meteor JS - javascript

So I'm using Meteor's 'methods' to transmit data between the client and server. Is there a recommended pattern for validating data? I've seen SimpleSchema used on the server like this a bit
Lists.schema = new SimpleSchema({
name: {type: String},
incompleteCount: {type: Number, defaultValue: 0},
userId: {type: String, regEx: SimpleSchema.RegEx.Id, optional: true}
});
...
const list = {
name: 'My list',
incompleteCount: 3
};
Lists.schema.validate(list);
...which makes sense, is there something I similar I should be using on the client to validate forms? Any extra information would be appreciated as well.

You can use simple-schema to validate arguments in methods when you use Meteor's validated method package.
https://github.com/meteor/validated-method
One advantage to this is that you can validate the args on the client in the method simulation so if there is an error, the method is rejected before it even gets to the server.
You can also use the Meteor's check package (https://docs.meteor.com/api/check.html) as part of your validation.
In terms of validating forms, there are many solutions. An example would be jQuery validation

Client side validation requirement arises when you are not using autoforms. If wrong values are passed from UI then Simpleschema generates error on server side.
If you desire to keep no validations on client side without using autoform, then you can use check functionality to check data sent from UI. When any check fails, catch in asynchronous .Meteor.call and using bootstrap and jquery you can show user friendly message on UI.
Or else use normal JavaScript and gquery to.meet your needs. This procedure is very tedious to maintain later when the application is live on the server. Just to change simple validation or condition entire code will have to built and minified to suit server production ready code. But in case if you use simpleschema and autoforms, you will have to change app.js file and restart the application (may be using pm2 as I do) and your application will work fine.

I would like also to add that communication between server and client in Meteor are done through "publications" (serverside) and "subscriptions" (client side) to certain publications.
To my understanding, methods in Meteor are only for CRUD operations for example and they can be called remotely from the client.

Related

why validate both the post request and the database schema in the backend?

Abstract: should I use express-validator if I can validate data using mongoose schema?
I'm a front end developer, and I usually do some validation on the form before submitting. Now, I've started studying express.
One of the first things I did was receive a form and validate it using a library called express-validator, then the database operations were done. very simple, no big deal. However, after doing a project by myself I realized that mongoose itself could handle the errors, not only that, but it was quite easy to return these errors on the front, especially in the case of an api.
So that is my doubt, why validate this data so many times? I know that database schemas is not only to do that, but doing theses things once in front and twice in backend cause too many
repetition and may be a little hard to maintain.
Here goes a few lines of code only to illustrate the case. Don't judge me, I'm still learning.
import mongoose from "mongoose";
const TaskSchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true,
maxlength: 20,
},
description: {
type: String,
required: false,
},
completed: {
type: Boolean,
default: false,
},
date: {
type: Date,
default: Date.now,
},
});
export default mongoose.model("Task", TaskSchema);
import taskModel from "../models/tasksModel";
export function createTask(req: express.Request, res: express.Response) {
taskModel
.create(req.body)
.then((task) => res.status(201).send(task))
.catch((err) => res.status(400).send(err));
}
The thing is that you have both basic and business requirements. Meaning that by declaring database tables (collections), its properties, data types, constraints etc you setup, so to say, basic data structure. But you can also have extra business requirements, that probably won't be covered by the database syntax.
For example, you have in input as array of objects, that should be then saved to database. Probably you would like to prevent passing dublicate objects.
By different conditions (user roles, permissions etc) your data can be validated through different validation schemas.
Also it's a common case that you validate your input and transfer it to various layers, modules, components of your application as DTO.
At last but no least, SQL injection can be made by simple 'consuming' not validated data by database.
On the frontend each user works with their own copy of the application which runs on a single laptop and accepts input from local system or known web resources.
On the backend all users work with a single app which runs on the shared infrastructure and accepts inputs from the Internet.
Serverside validation is required to ensure data integrity and security as you have no control on where HTTP requests come from and what payload they deliver. Even legitimate clients may lack clientside validation if your api is called from a script. Invalid or malicious request can affect all users. Data loss may not be recoverable.
Client side validation is optional and is there to improve UX and provide instant feedback on invalid input - you save on HTTP roundtrip and can validate fields in isolation before whole form is completed and submitted to the server. Security-wise client side application affects only current user and can always be restored to the initial state by reloading the web page.

How to create parameters in dialogflow using node.js

I want to create a parameter in node js that stays in the same intent for a life spam of 2.
It should ask for the first value then validates it, then second value and so on
what I have done
function test(agent) {
var first = agent.parameters.first;
var second = agent.parameters.second;
agent.context.set({
name: 'test',
lifespan: 2,
parameters: {
'first': first,
'second': second
},
});
agent.add("first parameter then second parameter");
}
Should I create the parameters in dialogflow as follows and implement it in node js or it should be done all in node js. If so how can I do it?
appreciate your help
I would say that in general the best option is to set all the intent's parameters via Dialogflow and then interact via Node.js client library.
Actually it would be also possible to do everything with Node.js, but in case you are using (or may use in the future) one of the integration options using fulfillment to manage agent’s responses you should set a webhook service and manage responses via API.
Therefore, I think setting the parameters in Dialogflow before interacting with Node.js would be the simplest and straightforward approach for any use case.
The code works fine, incase anyone facing the same issue, the request being sent must have the same session id to avoid overriding the values.

Meteor Random package vs randomSeed

I'm trying to replicate the latency compensation done by Meteor and minimongo. For instance to create an id on the client and then the same id on the server after calling the method, so the client can update the UI without waiting for the server response.
For this I need to generate the same Id on both the client and the server.
So, in meteor if I do: Random.createWithSeeds('abc').id()
I always get:
WKrBPwCSbzNHmhacn
But if I connect from and external app, outside of metor using a ddp client:
self.send({msg: 'method', id:id, randomSeed: 'abc', method: name, params: params});
I get a different Id. It's repeatable, but not the same as the one generated by Random. Why?
I cannot understand. Are they using a different generationId algorithm?
Packages I'm using:
On Meteor: https://atmospherejs.com/meteor/random
On external Client (outside Meteor): https://github.com/eddflrs/meteor-ddp + source code of random.js
This may not be a complete answer (I'm still looking too), but the way you're using Random.createWithSeeds should read:
> let generator = Random.createWithSeeds('abc')
> generator.id()
'WKrBPwCSbzNHmhacn'
> generator.id()
'h6iLWkdEfZ7wXWpPQ'
Perhaps an edit might clarify that createWithSeeds('abc') is supposed to return an object you call .id() on multiple times. I've never tried passing the seed from another ddp client though, and I'll let you know when I do

Expose GraphQL schema from non-JS server to a JS client

I have a GraphQL server implemented in Java and a JavaScript client querying it. What I don't like is that the client has to just know the schema and can not get it from the server instead and dynamically build queries against it.
Now, I understand GraphiQL somehow does just that, but I'm guessing it's because its backend is also written in JavaScript so both the client and server can use it. My schema is defined in Java, but there might be a way to automatically generate a JavaScript representation that the client could use.
Does such a thing already exist?
Now, I understand GraphiQL somehow does just that, but I'm guessing it's because its backend is also written in JavaScript so both the client and server can use it.
Actually, (fortunately) this is not the case. It is written in Javascript, but it need not be to achieve this behavior.
I've got some great news for you...
Introspection!
One of the awesome things about GraphQL is that, in fact, the client doesn't have to know anything about the schema, because it can just query the server for it using introspection. In fact, GraphiQL will use this automatically if you don't provide a schema explicitly to automagically populate it.
From the Props section of the GraphiQL README:
schema: a GraphQLSchema instance or null if one is not to be used. If undefined is provided, GraphiQL will send an introspection query using the fetcher to produce a schema.
The official GraphQL Introspection docs will give you lot more information and sample queries. Their example of querying their Star Wars example schema:
{
__schema {
types {
name
}
}
}
This returns the names of all of the types. Introspection is part of the GraphQL spec, so every GraphQL server should be able to do it out of the box: you don't need to explicitly add any functionality.

Meteor: How can I get useraccounts package to write a new user doc into a remote collection?

I'm using the packages accounts-password and useraccounts:bootstrap and it all works fine, meaning the sign-on form creates a new doc in the Meteor.users collection. But I don't want any collection on the client facing app, hence I do have a second app running to which I successfully connect via DDP.connect() and I can exchange all necessary docs/collections via pub/sub and calling methods on the remote app.
The only thing that doesn't work is the useraccount doc. I've used (on the client app):
remote.subscribe('users', Meteor.userId(), function() {
});
and (on the remote app):
Meteor.publish('users', function() {
return Meteor.users.find({});
});
even though I'm not sure if there is a pub/sub already included in the package. Still, the doc is written to the local (client) app and not to the remote app.
How can I achieve this?
useraccounts:core simply makes use of Accounts.createUser on the server side (see this line) within a method called from the client-side (see this another line).
So the new user object is created from the server side and not from the client (though it flows all the way down to the client thanks to the DDP and default users subscriptions...).
If you're really looking to change the defaul behaviour provided by the Meteor core Accounts packages (accounts-base, accounts-password in this case...) you should try to override the Accounts.createUser method which is were all begins...
In any case be warned that the current user is published to the client by default: see these lines
Finally, to prevent useraccounts:core to use the Accounts API you could try to override the AtCreateUserServer method and deal with the creation of a new user on a remote application inside there.
Package accounts-base provide such functionality.
The accounts-base package exports two constructors, called AccountsClient and AccountsServer, which are used to create the Accounts object that is available on the client and the server, respectively.
Nevertheless, these two constructors can be instantiated more than once, to create multiple independent connections between different accounts servers and their clients, in more complicated authentication situations.
Documentation: Accounts (multi-server)

Categories

Resources