I have a Meteor game of heads or tails that keeps the stats of a user in their profile. The stats eg. wins and loses are changed using Meteor methods like incrementWins and incrementLoses.
Is there a way to prevent the users from calling these methods on the console?
I didn't find any precise answer to the question so I'll add one.
Is there a way to prevent the users from calling these methods on the console?
The short answer is no.
As long as you have the Meteor variable available on the client, it's not possible to restrict a user to use if from browser console. Meteor allows the client side to use Meteor.call function in any conditions, therefore even if you restrict its usage somehow, it will affect your whole application, not just browser console.
You can, however, make your methods more secure. As you know, you can make your code run either on client side, server side, or both. If you put your methods on the server side, the client side will never know what exactly happens as the methods are executed, nor would it be able to influence it or intercept control anyhow.
On the other hand, if you put your methods in the lib/ or both/ folder (or simply root folder of your app), the methods will run both on client and on server. Insecure part of the code (like bulk removing collection items or manipulating Meteor.users collection) won't be executed on the client side. But you may want to put something that would change UI state or show any messages, ironically, on the browser console. Think twice before applying this practice.
I personally think you exaggerate the meaning of ability to run something on the browser console. First, only a small group of users actually do that (but if they do, expect smallest holes in your app to be exploited). Second, Meteor is well secured in this part, it doesn't allow a user to run insecure code (unless insecure package is added, which is by default as you create a new app). And third, most of the time, as your methods get executed, the data will be updated reactively, this is what Meteor takes care of out of the box, so you don't need to worry about refreshing UI after app state change, etc.
Every newly created Meteor project has the insecure package added by default. This is the package that allows us to edit the database from the client. It's useful when prototyping, To remove this package, go to your app directory and run:
meteor remove insecure
Related
This seems like a really simple thing to do, yet I am having trouble finding the right architecture to do this.
Here's the scenario:
We have an API route api/templates that should, in theory, happen in every single route/page of the App. It fetches all the different templates and all the data in the app belongs to one of those templates. These are dynamic and can change over time, so they are not an 'importable JSON'
Every page should get these assets on load, but...
once it's loaded, and you start navigating through pages, the app should NOT re-fetch them on every single page navigation
We will implement a socket notification to alert an already-loaded client when templates change in the database
The problem is that, since this is needed on every page, SSR still needs to be able to access this on every page and our SEO policy requires server side rendering to send these pages fully rendered to client.
So, what we are looking for is:
to have a somewhat 'conditional' getServerSideProps that, if it is a full reload, it fetches that, but, if it is already in the client's memory, it skips that
we have looked into SWR, which, in theory, would work, but it still makes the API call as an after-thought, helping on the client side, but defeating the objective of not actually making the call, so that the backend is not 'burdened' with an unnecessary call
Honestly, this looks like a very 'common' pattern, yet I have completely failed to achieve a proper solution within the NextJS app environment. Maybe it's an "anti-pattern" and we shouldn't be doing this?
Meteor is supposed to pre-load a small part of Mongo client-side so that it can simulate changes to the DB. Thus making any changes to the page happen instantly while the real DB update happens in the background.
However, on my site I'm seeing a 1-2 second delay on simple actions that make changes to the DB, such as deleting a post.
Is there some extra coding that needs to be done to ensure the client-side simulation works?
As Michel Floyd Pointed out, if your meteor method is defined as server only code, there is no way to simulate the method call on the client.
Try moving Meteor method declarations into shared code, and see if that changes latency time.
also, without seeing some code and project structure the problem could be else where...
If you are using server-side method only, make sure your Mongodb has oplog tailing enabled, so that the change is picked up immediately and sent to the client. If you are using like a hosted db, like the free mlab, it's possible you have no oplog, the meteor falls back to querying the db periodically to check for changes.
But in any case, if the method is server side only, you will always have delays. Like mentioned in this thread, move the method definition outside the server folder (like /lib) só that the method becomes available on th client.
I'm learning Meteor and fundamentally enjoy how fast I can build data driven applications however as I went through the Creating Posts chapter in the Discover Meteor book I learned about using server side Methods. Specifically the primary reason (and there are a number of very valid reasons to use these) was because of the timestamp. You wouldn't want to rely on the client date/time, you'd want to use the server date/time.
Makes sense except that in almost every application I've ever built we store date/time of row create/update in a column. Effectively every single create or update to the database records date/time which in Meteor now looks like I would need to use server side Methods to ensure data integrity.
If I'm understanding correctly that pretty much eliminates the ease of use and real-time nature of a client side Collection because I'll need to use Methods for almost every single update and create to our databases.
Just wanted to check and see how everyone else is doing this in the real world. Are you just querying a server side Method that just returns the date/time and then using client side Collection or something else?
Thanks!
The short answer to this question is that yes, every operation that affects the server's database will go through a server-side method. The only difference is whether you are defining this method explicitly or not.
When you are just getting started with Meteor, you will probably do insert/update/remove operations directly on client collections using validators, which check for whether the operation is allowed. This usage is actually calling predefined methods on both the server and client: (for a collection named foo the you have /foo/insert, for example) which simply checks the specified validators before doing the operation. As you become more familiar with Meteor you will probably override these default methods, for reasons you described (among others.)
When using your own methods, you will typically want to define a method both on the server and the client, just as the default collection functions do for you. This is because of Meteor's latency compensation, which allows most client operations to be reflected immediately in the browser without any noticeable lag, as long as they are permitted. Meteor does this by first simulating the effect of a method call in the client, updating the client's cached data temporarily, then sending the actual method call to the server. If the server's method causes a different set of changes than the client's simulation, the client's cache will be updated to reflect this when the server method returns. This also means that if the client's method would have done the same as the server, we've basically allowed for an instant operation from the perspective of the client.
By defining your own methods on the server and client, you can extend this to fill your own needs. For example, if you want to insert timestamps on updates, have the client insert whatever timestamp in the simulation method. The server will insert an authoritative timestamp, which will replace the client's timestamp when the method returns. From the client's perspective, the insert operation will be instant, except for an update to the timestamp if the client's time happens to be way off. (By the way, you may want to check out my timesync package for displaying relative server time accurately on the client.)
A final note: it's good to understand what scope you are doing collection operations in, as this was one of the this that originally confused me about Meteor. For example, if you have a collection instance in the client Foo, Foo.insert() in normal client code will call the default pair of client/server methods. However, Foo.insert() in a client method will run only in a simulation and will never call server code - so you will need to define the same method on the server and make sure you do Foo.insert() there as well, for the method to work properly.
A good rule of thumb for moving forward is to replace groups of validated collection operations with your own methods that do the same operations, and then adding specific extra features on the server and client respectively.
In short— yes!
Publications exist to send out a 'live', and dynamic, subset of the database to the client, sending DDP added messages for existing records, followed by a ready, and then added, changed, and deleted messages to keep the client's cache consistent.
Methods exist to- directly, or indirectly— cause Mongo Updates, and like it was mentioned by Andrew, they are always in use.
But truly, because of Meteor's publication architecture, any edits to collections that are currently being published to at least one client, will be published via DDP - regardless of the source of the change to Mongo - even an outside process.
I'm the maintainer of the Meteor smart package zipzap and I would like to understand how a user of that package could possible specify if that package should be used on server, client or both. The package provides zip functionality, both on server and client. But if the user only needs server side zip functionality all files content still would be sent to the client and I don't see a way how to change that other than the user modifies the package.js.
A package.js looks like this:
Package.on_use(function (api) {
api.add_files('path/to/file.js', ['server', 'client']);
});
This is hardcoded so the user doesn't have any way to specify which files will be transferred to the client.
I see how my case might not be that common, as most packages either provide functionality for the server or client, or in some way interact with each other. But I see the same problem for client side packages which provide multiple features but the user only needs few of them and most of the code therefore never is required. Isn't there a way how the user could interact with the package and say:
I only need this on server
Activate feature X
Disable feature Y
I know the package system is not yet final and is the last big thing to be finished before Meteor 1.0. So it might be that any answer to that question might be obsolete next week. Thought I still ask.
I'm building a somewhat big application. When changing code the server restart and force refresh on the client.
The client keep his session data, but I seem to lose the Meteor.Collection previously sync data, forcing my user to re-sync everything.
I use 0.5.7(did not see anything in 0.5.8 about that)
Is that the expected behavior or I'm I missing something?
This can be tested by adding something like that at your client start (Assuming Components is your Meteor.Collection)
console.log("Length: ", Components.find().fetch().length);
No, you're not missing anything. The collection data should be re-synced on code pushes. However, if your collection data takes more than a second or two to load in, you should look into trying to send less data to the client by creating finer-grained subscriptions that only send data the client needs at the moment.