Rocket chat: Determine if the app is running in Desktop or browser - meteor

Is there anyway to determine if the Rocket.chat app is running in desktop or browser?
Thank you in advance. :)

You can look at server environment variables using a line like this:
console.log(process.env.TZ);
If you need to access that from the client, you can do this in your client code:
console.log("TZ = "+Meteor.call("getEnv","TZ"));
and in your meteor methods (in the server folder)
Meteor.methods({
getEnv: function(varname) {
return process.env[varname];
},
Obviously use this with care. It is a generic method that may present a security hole. If you want to make it more secure, just write a specific method where you don't pass the environment variable name, to prevent any kind of malicious attack.

Related

Is it possible to make rules for filenames to serve only to client or to server?

Meteor has special directories: server and client for serving files only to server or only to client.
Is it possible to make similar behaviour, but using not client and server folder names but file names which end with either .client.js or .server.js?
For example collections.client.js would be available only on client and collections.server.js would be available only on server?
UPD
Maybe it is possible to create smart package which will take control of files serving?
This is not possible, what you can do however, is the following :
lib/collections/collection.js
Declare the collection and common client/server behavior such as Meteor.methods.
client/collections/collection.js
Declare client specific helpers regarding the collection.
server/collections/collection.js
Declare publications and other server-side helpers.
You could alternatively declare everything in lib/collections/collection.js and use Meteor.isClient and Meteor.isServer blocks.
This might be OK for very small files but it can quickly become a mess for larger projects.
I'm not sure if the Meteor build tool is smart enough to strip Meteor.isServer from the bundle served to the client.
You can also use a modular approach and use packages instead, with the Package API you can control precisely the context where a file is supposed to be executed.
Package.describe({
name: "my-app-module",
description: "Handles some feature in My App",
version: "1.0.0"
});
Package.onUse(function(api){
api.addFiles({
"my-module/shared.js"
},["client","server"]);
//
api.addFiles({
"my-module/client.js"
},"client");
//
api.addFiles({
"my-module/server.js"
},"server");
//
api.export("MyModule",["client","server"]);
});
Hmmm, for now you can't do this, but you can put your code in
if (Meteor.isServer) {
// your server code
};
if (Meteor.isClient) {
// your client code
};

Possibility for only currently connected (not authenticated) and admin user to read and write on certain location

Is there any way to write a security rule or is there any other approach that would make possible only for currently connected (not authenticated) user to write/read certain location - admin should also be able to write/read?
Can a rule be written that disallows users to read of complete list of entries and let them read only entry that matches some identifier that was passed from client?
I'm trying to exchange some data between user and Node.js application through Firebase and that data shouldn't be able to read or write by anyone else other than user and/or admin.
I know that one solution would be that user requests auth token on my server and uses it to authenticate on Firebase and that would make it possible to write rule which prevents reads and writes. However, I'm trying to avoid user connecting to my server so this solution is not first option.
This is in a way session based scenario which is not available in Firebase but I have
some ideas that could solve this kind of problem - if implemented before session management:
maybe letting admin write into /.info/ location which is observed by client for every change and can be read only by active connection - if I understood correctly how .info works
maybe creating .temp location for that purpose
maybe letting admin and connected client could have more access to connection information which would contain some connection unique id, that can be used to create location with that name and use it inside rule to prevent reading and listing to other users
Thanks
This seems like a classic XY problem (i.e. trying to solve the attempted solution instead of the actual problem).
If I understand your constraints correctly, the underlying issue is that you do not wish to have direct connections to your server. This is currently the model we're using with Firebase and I can think of two simple patterns to accomplish this.
1) Store the data in an non-guessable path
Create a UUID or GID or, assuming we're not talking bank level security here, just a plain Firebase ID ( firebaseRef.push().name() ). Then have the server and client communicate via this path.
This avoids the need for security rules since the URLs are unguessable, or close enough to it, in the case of the Firebase ID, for normal uses.
Client example:
var fb = new Firebase(MY_INSTANCE_URL+'/connect');
var uniquePath = fb.push();
var myId = uniquePath.name();
// send a message to the server
uniquePath.push('hello world');
From the server, simply monitor connect, each one that connects is a new client:
var fb = new Firebase(MY_INSTANCE_URL+'/connect');
fb.on('child_added', newClientConnected);
function newClientConnected(snapshot) {
snapshot.ref().on('child_added', function(ss) {
// when the client sends me a message, log it and then return "goodbye"
console.log('new message', ss.val());
ss.ref().set('goodbye');
});
};
In your security rules:
{
"rules": {
// read/write are false by default
"connect": {
// contents cannot be listed, no way to find out ids other than guessing
"$client": {
".read": true,
".write": true
}
}
}
}
2) Use Firebase authentication
Instead of expending so much effort to avoid authentication, just use a third party service, like Firebase's built-in auth, or Singly (which supports Firebase). This is the best of both worlds, and the model I use for most cases.
Your client can authenticate directly with one of these services, never touching your server, and then authenticate to Firebase with the token, allowing security rules to take effect.

How do you secure the client side MongoDB API?

I don't want just all of my users being able to insert/destroy data.
While there is no documented way to do this yet, here's some code that should do what you want:
Foo = new Meteor.Collection("foo");
...
if (Meteor.is_server) {
Meteor.startup(function () {
Meteor.default_server.method_handlers['/foo/insert'] = function () {};
Meteor.default_server.method_handlers['/foo/update'] = function () {};
Meteor.default_server.method_handlers['/foo/remove'] = function () {};
});
}
This will disable the default insert/update/remove methods. Clients can try to insert into the database, but the server will do nothing, and the client will notice and remove the locally created item when the server responds.
insert/update/remove will still work on the server. You'll need to make methods with Meteor.methods that run on the server to accomplish any database writes.
All of this will change when the authentication branch lands. Once that happens, you'll be able to provide validators to inspect and authorize database writes on the server. Here's a little more detail: http://news.ycombinator.com/item?id=3825063
[UPDATE] There is now an official and documented Auth Package which provides different solutions to secure a collection.
On a CRUD level :
[Server] collection.allow(options) and collection.deny(options). Restricts default write methods on this collection. Once either of these are called on a collection, all write methods on that collection are restricted regardless of the insecure package.
And there is also insecureto remove full write access from the client.
source : Getting Started with Auth (thanks to #dan-dascalescu)
[OLD ANSWER]
Apparently there are working on Auth Package(?) that should avoid any users taking full control on the db as it is now. There is also someone suggesting that there is an existing solution (workaround) by defining your own mutations (methods) and make them failed if they attempts to perform an unauthorized action. I didn't get it much better but I think this will often be necessary since I doubt the Auth Package will let you implement the usual auth logic on a row level but probably only on the CRUD methods. Will have to see what the devs have to say.
[EDIT]
Found something that seems to confirm my thoughts :
Currently the client is given full write access to the collection. They can execute arbitrary Mongo update commands. Once we build authentication, you will be able to limit the client's direct access to insert, update, and remove. We are also considering validators and other ORM-like functionality.
Sources of this answer :
Accessing to DB at client side as in server side with meteor
https://stackoverflow.com/questions/10100813/data-validation-and-security-in-meteor/10101516#10101516
A more succinct way:
_.each(['collection1', 'collection2'], function(collection){
_.each(['insert','update', 'remove'], function(method){
Meteor.default_server.method_handlers['/' + collection + '/' + method] = function(){}
});
});
or to make it more idiomatic:
extend meteor:
_.extend(Meteor.Collection.prototype, {
remove_client_access: function(methods){
var self = this;
if(!methods) methods = ['insert','update','remove'];
if(typeof methods === 'String') methods = [methods];
_.each(methods, function(method){
Meteor.default_server.method_handlers[self._prefix + method] = function(){}
});
}
});
Calls are simpler:
List.remove_client_access() // restrict all
List.remove_client_access('remove') //restrict one
List.remove_client_access(['remove','update']) //restrict more than one
I am new to Meteor, but what I have come across so far are these two points
You can limit what a client can access in the database by adding parameters to the find command in the server-side publish command. Then when the client calls Collection.find({}), the results that are returned correspond to what on the server side would be, for example, Collection.find({user: this.userId}) (see also Publish certain information for Meteor.users and more information for Meteor.user and http://docs.meteor.com/#meteor_publish)
One thing that is built in (I have meteor 0.5.9) is that the client can only update items by id, not using selectors. An error is logged to console on the client if there is an attempt that doesn't comply. 403: "Not permitted. Untrusted code may only update documents by ID." (see Understanding "Not permitted. Untrusted code may only update documents by ID." Meteor error).
In view of number 2, you need to use Meteor.methods on the server side to make remote procedure calls available to the client with Meteor.call.

Return values from exe in javascript

i have to call an executable in the client machine in asp.net and get the return parameters, i been looking for an example but i couldn't find it.
it this possible to recover the output parameters from one exe in JavaScript?
i know that can i write:
var WshShell = new ActiveXObject("WScript.Shell");
var oExec = WshShell.Exec("My.exe");
but the clients executable returns 0 or 1 that values are the ones i need to collect
Thanks in advance
Browser-based JavaScript can't call executable files on client machines; to do so would be a catastrophic security problem. If you have to run an executable on the client machine, consider asking the user to install a .NET application, an ActiveX control, or something like Java if you want to be platform-independent.
Depending on what you're trying to do, you may not need to run an EXE on the client machine; you can do a LOT with standard cloud-type scenarios (JS or SilverLight on the client, Web services or WCF on the server). Without more information about your situation, however, it's impossible to tell.
EDIT: Based on your comments that you're using the ActiveXObject.Exec method, you can use the StdOut property of the WshScriptExec object that method returns. From MSDN's article on the StdOut property:
if (!oExec.StdOut.AtEndOfStream)
{
input += oExec.StdOut.Read(1);
//...
}

Test to identify your development environment?

The code has a runtime dependency which is not available in our development environment (and is available in test and prod). It's expensive to actually test for the dependency, and I want to test for the environment instead.
if (isDevEnvironment) {
// fake it
}
else {
// actually do it
}
Without using appSettings, what code/technique/test would you use to set isDevEnvironment?
Example answers:
check machine name (partial or full)
check for running instance of Visual Studio
check for environment variable
I'm hoping for a test I hadn't considered.
You should try to not test your environment in the code! That's why dependency inversion (and then injection) has been invented for.
Draw some inspiration from NewSpeak, where where the complete platform is abstracted in an object and passed as parameter down the chain of method calls.
The code you provided (if (isDevEnvironment) ..) smells with test code in production.
Without using appSettings, what code/technique/test would you use to set isDevEnvironment?
Generally, Dependency Injection.
But also the the possible Solution in the link provided.
You should not check the environment, instead you need to provide the environment.
You've hit upon the major techniques. At my current job, we use the Enviroment variable technique.
At a previous job, all servers had three NIC's, there was the public front end, the middle tier for server to server traffic, and the back end Network Operations would connect to.
There were on different IP subnets. It made it easy to detect where something was coming from, but also who where was it.
Example:
10.100.x.xxx - Production Subnet
10.100.1.xxx - Back
10.100.2.xxx - Middle
10.100.3.xxx - Front
10.0.1.x - Development Subnet
This required nothing to be installed special on the servers, just code detection and then caching.
I prefer to do this:
if(Properties.Settings.Default.TestEnvironment || HttpContext.Current.Request.ServerVariables["Server_Name"] == "localhost")
{
// do something
}

Resources