Communicating with a web widget-Meteor, React, Node - javascript

I'm building a chat dashboard and widget with which a customer should be able to put the widget into their page. Some similar examples would be Intercom or Drift.
Currently, the "main" application is written in Meteor.js (it's front end is in React). I've written a <Widget /> component and thrown it inside a /widget directory. Inside this directory, I also have an index.jsx file, which simply contains the following:
import React from 'react';
import ......
ReactDOM.render(
<Widget/>,
document.getElementById('widget-target')
);
I then setup a webpack configuration with an entry point at index.jsx and when webpack is run spits out a bundle.js in a public directory.
This can then be included on another page by simply including a script and div:
<script src="http://localhost:3000/bundle.js" type="text/javascript"></script>
<div id="widget-target"></div>
A few questions:
What is wrong with this implementation? Are their any security issues to be aware of? Both the examples linked earlier seem make use of an iframe in one form or another.
What is the best way to communicate with my main meteor application? A REST API? Emit events with Socket.io? The widget is a chat widget, so I need to send messages back and forth.
How can I implement some sort of unique identifier/user auth for the user and the widget? Currently, the widget is precompiled.

1 What is wrong with this implementation? Are their any security issues to be aware of? Both the examples linked earlier seem make use of an iframe in one form or another.
As #JeremyK mentioned, you're safer within an iFrame. That being said, there's a middle route that many third parties (Facebook, GA, ...) are using, including Intercom:
ask users to integrate your bundled code within their webpage. It's then up to you to ensure you're not introducing a security vulnerability on their site. This code will do two things:
take care of setting up an iframe, where the main part of your service is going to happen. You can position it, style it etc. This ensure that all the logic happening in the iframe is safe and you're not exposed.
expose some API between your customer webpage and your iframe, using window messaging.
the main code (the iframe code) is then loaded by this first script asynchronously, and not included in it.
For instance Intercom ask customers to include some script on their page: https://developers.intercom.com/docs/single-page-app#section-step-1-include-intercom-js-library that's pretty small (https://js.intercomcdn.com/shim.d97a38b5.js). This loads extra code that sets the iFrame and expose their API that will make it easy to interact with the iFrame, like closing it, setting user properties etc.
2 What is the best way to communicate with my main meteor application? A REST API? Emit events with Socket.io? The widget is a chat widget, so I need to send messages back and forth.
You've three options:
Build your widget as an entire Meteor app. This will increase the size of the code that needs to be loaded. In exchange for the extra code, you can communicate with your backend through the Meteor API, like Meteor.call, get the reactivity of all data (for instance if you send a response to a user through your main Meteor application, the response would pop up on the client with no work to do as long as they are on the same database (no need to be on the same server)), and the optimistic UI. In short you've all what Meteor offers here, and it's probably going to be easier to integrate with your existing backend that I assume is Meteor.
Don't include Meteor. Since you're building a chat app, you'll probably need socket.io over a traditional REST API. For sure you can do a mix of both
Use Meteor DDP. (it's kind of like socket.io, but for Meteor. Meteor app use that for all requests to the server) This will include less things that the full Meteor and probably be easier to integrate to your Meteor backend than a REST API / socket.io, and will be some extra work over the full Meteor.
3 How can I implement some sort of unique identifier/user auth for the user and the widget?
This part should probably do some work on the customer website (vs in your iframe) so that you can set cookies on his page, and send that data to your iframe that's gonna talk to your server and identify the user. Wether you use artwells:accounts-guest (that's based on meteor:accounts-base) is going to depend on wether you decide to include Meteor in your iframe.
If you don't have Meteor in your iframe, you can do something like:
handle user creation yourself, by simply doing on your server
.
const token = createToken();
Users.insert({ tokens: [token] });
// send the token back to your iframe
// and set is as a cookie on your customer website
then for each call to your server, on your iframe:
.
let token;
const makeRequest = async (request) => {
token = token || getCookieFromCustomerWebsite();
// pass the token to your HTTP / socket.io / ... request.
// in the header of whatever
return await callServer(token, request);
};
in the server have a middleware that sets the user. Mine looks like:
.
const loginAs = (userId, cb) => {
DDP._CurrentInvocation.withValue(new DDPCommon.MethodInvocation({
isSimulation: false,
userId,
}), cb);
};
// my middleware that run on all API requests for a non Meteor client
export const identifyUserIfPossible = (req, res, next) => {
const token = req.headers.authorization;
if (!token) {
return next();
}
const user = Users.findOne({ tokens: token });
if (!user) {
return next();
}
loginAs(user._id, () => {
next();
// Now Meteor.userId() === user._id from all calls made on that request
// So you can do Meteor.call('someMethod') as you'd do on a full Meteor stack
});
};

Asking your customers to embed your code like this doesn't follow the principles of Security by Design.
From their point of view, you are asking them to embed your prebundled code into their website, exposing their site up to any hidden security risks (inadvertent or deliberately malicious) that exist in your code which would have unrestricted access to their website's DOM, localstorage, etc.
This is why using an iframe is the prefered method to embed third party content in a website, as that content is sandboxed from the rest of it's host site.
Further, following the security principle of 'Least Privilege' they (with your guidance/examples) can set the sandbox attribute on the iframe, and explicitly lockdown via a whitelist the privileges the widget will have.
Loading your widget in an iframe will also give you more flexibility in how it communicates with your servers. This could now be a normal meteor client, using meteor's ddp to communicate with your servers. Your other suggestions are also possible.
User auth/identification depends on the details of your system. This could range from using Meteor Accounts which would give you either password or social auth solutions. Or you could try an anonymous accounts solution such as artwells:accounts-guest.
html5rocks article on sandboxed-iframes

Related

Is CASL React library safe for authorization?

I came CASL JavaScript library, which restricts what resources a given client is allowed to access.
My question is whether it can be used for role based access in a React app in a secure way?
And whether user can temper with the permission and gain unauthorized access if used only in front end to display/hide components as shown in following react code?
import React, { useContext } from 'react';
import { AbilityContext } from './Can'
export default () => {
const createTodo = () => { /* logic to show new todo form */ };
const ability = useContext(AbilityContext);
return (
<div>
{ability.can('create', 'Todo') &&
<button onClick={createTodo}>Create Todo</button>}
</div>
);
}
Reference: https://casl.js.org/v5/en/package/casl-react
Tbh, users always can gain access from the frontend side by modifying some javascript code and that is why you must handle the authorization from the backend
about your question for CASL, it only checks if you have the ability to see this page or button or do specific actions ... so the place where you save user abilities is your responsibility, not CASL responsibility
Any code for the client (especially browsers) is publicly available to the user/guest and it can be easily tempered with. Any view/front-end library/framework is used to make user-interface dynamic has to be used only for making it dynamic, not for adding security measures or critical logic. Just like your client code can communicate with an API, any other client may also communicate with it as well (If not, the client code can easily be tempered).
CASL library for React is used only to make the UI dynamic, to be able to hide unnecessary functionality. It has zero effect on securing the application. Anyone who inspects the code can see the "hidden" UI and with changing a few variables, they can access any functionality. So no, CASL or similar libraries cannot make your application secure, it may even give you the false sense of security.
You should secure your application on the API level. Anything unnecessary should be hidden from the currently authenticated user or non-authenticated user (guests). As long as your API endpoints are secure, the fact of anyone can temper with the client code does not create any security risk (as long as security risks like XSS, CSRF are eliminated and the client code does not give much information about the intricacies of the critical logic at the API level).
Libraries like CASL should be only used to improve the user-interface, thus improving the user-experience. If not used, let's say the admin dashboard is visible to any user, but they wouldn't be able to see any data or do any action because the API endpoint won't allow them (authorization on the API level); that would create a confusion in user as they may think this functionality is necessary for them to use your application but somehow there is a problem, or it may signal that their account/data may not be safe as well.

How does Express and React Routes work on initial GET request from browser?

I'm new to the react world and to the fullstack world as a whole but I've searched endlessly for an answer to the following and some guidance would be really appreciated.
I'm creating an app using React and Express. It requires authentication so I was planning on using Passport to help. The client side JS uses React Routers to navigate through the website. That's all fine but my issue is with the initial GET request made by the browser.
I'll first describe my specific app requirements and then generalize what I don't understand.
As I said, my application requires OAuth2 authentication. If you try to GET a path on my website and you're not logged in, it should just load the login page. If you are logged in, then load as normal and find your path. Similar to facebook, I'd like the login URL to be the same as the "feed" page. So similar to how facebook.com '/' route is either the login page or your new feed depending on whether you are signed in, I want the same thing.
From what I understand, Passport authenticates on the back end by checking the request header. So I understand that I should have some kind of middleware that says "if user is signed in, continue down the routes otherwise render sign in page" ... How is this done? What would the code look like? My only experience with Express was from an intro class which used res.render to send back an HTML file and pass it through some template engine like handlebars. But I have no idea how it'd work with react routes. Would i still use res.render()? Something else?
Let's say my index.html has the root div to inject the react into. If I had to guess, I'd send back that index.html page with the .js file with the routes and somehow on the backend send back the route I want it to match on my react routes (either the login one or the user requested)??
More generally, I guess I'm just confused how the initial request to a website using react routes is done. 1) How does the server interact with everything to render what I asked for? 2) What would the code look like for that. My only experience with React is from a basic Udemy course that just used "react-scripts start" to render the page.
After spending the entire day Googling this question it led me to SSR which is a rabbit-hole of its own and I'm not even sure if its what I need to help me. Is it?
I'm clearly missing some fundamental knowledge as this is really tripping me up so if you have any resources to learn more just post them. Thanks!
I understand your struggle as I've had to go through it myself when combining front-end with back-end, specifically React and Node. So first things first, we know that the browser/client will always initiate a request to the server, so how does React Router take control of the routes? Well its plain simple actually, all you have to do is return the entire react app from any route from your express server. The code will look something like this:
const express = require('express');
const app = express();
app.get('/*', (req, res, next) => {
// Return React App index.html
});
app.listen(3000);
Once the react app renders on the user browser (don't worry about paths, as react will automatically render according to the URL based on the code you wrote in the client side, it will also take care of authentication vs feed page when it will scan for your local storage, cookies, etc), it will take control of routing, instead of a request going to the express server. But what happens when we request data from our server, well it returns react app on each route so we need to setup an api route to handle any data requests.
app.get('/api/v1/*', (req, res, next) {
// Return some data in json format
});
Hopefully, this gives you insight about what you were looking for.
I think the fundamental gap you're struggling with stems from that lot of those 'intro courses' shove the entire browser client into the application server to get things up and running quickly, as in, the Node server renders the entire React app AND operates as an API...
// Ajax request from React app to: http://example.com/api
app.use('/api/*'),()=> {
res.send({ <!-- some JSON object -->})
})
// User visits in browser: http://example.com/**/*
app.use('/*',()=>{
res.render(<!-- entire React App sent to browser -->)
})
The first request (assuming the user doesn't visit /api/* ) will just send down the React bundle. Further user navigation within the client would generally send XHR requests (or open WebSockets) from the React app to Express routes running on the same node program.
In many situations it makes sense to have these parts of your program separated, as by having react delivered from a completely different location than where it requests data. There's many reasons for this, but optimizing computing resources to their differing demands of CPU, memory, network .etc and manageability of code/deployment are the big reasons for me.
For example...
User visits: http://example.com *
Nginx, Apache, a 'cloud proxy' .etc direct the traffic to a static React bundle, which has no authentication and never makes contact with your Node server.
If the user has Authenticate previously they will have token in local storage (if you're using JWTs for Authentication) and your React app will be configured to always check for these tokens when you first it is initially loaded.
If the user has a token it will send an Ajax request in the background with the token as a Header Bearer and will send back user data, then redirect them to an 'Authenticated page' like the FB feed you mention.
If they don't have a token or the token Authentication fails then React will redirect them to the Login or Registration page
React
React basically high jacks the browser's native 'location' functionality (whats displayed after you domain name). So any events after the initial page load (buttons clicks and such) are handled entirely by React internally and uses those routes to determine what to display or what data to fetch from the API through Ajax (XHR).
If the user performs a hard page reload then that request will go back to the server and it will perform the whole cycle over again
React Router
Allows you to do 2 things simultaneously...
Manipulate the browser Location and History objects.
Use that History and Location information elsewhere by detecting changes and sending off events.
SSR
I've only toyed around with SSR so I can speak to it, but its provides extremely low latency for initial renders, doing it in 1 network request, so you want to use it areas of your program where thats important.
Not sure if this answers you question, but let me know if you would like me to elaborate on anything or provide some more detailed resources.
SSR is a little bit confuses for developer that has less experience, let forget it for now.
It will be more easier for you to assume that frontend JavaScript (React) and backend Javascript (NodeJS) are two separate apps, and they communicate to each other via API.
here the code that show Login component and Feed component depending on whether you are signed in
import React, { Component } from "react";
import axios from "axios";
class Home extends Component {
constructor() {
const accessToken = localStorage.getItem("accessToken");
this.state = {
accessToken,
feeds: []
};
}
componentDidMount() {
if (this.state.accessToken) {
axios(`api/feeds?accessToken=${this.state.accessToken}`).then(({ data }) => {
this.setState({
feeds: data
});
});
}
}
render() {
if (this.state.accessToken) {
return <FeedsComponent feeds={this.state.feeds} />;
}
return <LoginComponent />;
}
}
and this is your backend
const express = require("express");
const app = express();
app.get('/api/feeds', (req, res, ) => {
const feeds = [
{},
{}
]
res.status(200).json(feeds);
});
app.listen(3001);
just keep in mind that they are two separate apps, the can be in two different folder, different server, different port.
Simply point Express to the folder containing your React files or build files.
app.use(express.static(__dirname + '/dist'));
where 'dist' contains the build files
See docs for more details

.php is getting downloaded instead of loading it on firebase web hosting [duplicate]

I'm trying to test out if PHP works from my Firebase hosting using the following:
(index.html)
<form action="welcome.php" method="post">
<input type="submit">
</form>
(welcome.php)
<?php
$to = "my#email.com";
$subject = "My subject";
$txt = "Hello world!";
$headers = "From: dummy#email.com";
mail($to,$subject,$txt,$headers);
?>
Every time I try this the browser keeps on attempting to open the PHP file rather than processing it. Is simple PHP enabled on the Firebase server hosting to process a simple form like this? If I can get it to work this way, I will be building the form out correctly including validation etc.
Thanks,
From the Firebase Hosting site (emphasis mine):
We deliver all of your static content (html, js, images, etc.) over a secure SSL connection and serve it on a CDN.
Firebase Hosting is for hosting static assets. Firebase currently doesn't offer any way to execute your code on Firebase's servers.
Update (2018-08-08): You can now run Node.js/JavaScript code but connecting your Firebase Hosting project to Cloud Functions + Firebase Hosting. But that still won't allow you to run PHP code.
As per the latest update firebase has started using Cloud Functions
Cloud Functions for Firebase lets you run mobile backend code that automatically responds to events triggered by Firebase features and HTTPS requests. Your code is stored in Google’s cloud and runs in a managed environment. There's no need to manage and scale your own servers.
For more : https://firebase.google.com/docs/functions/
There is no PHP but nodeJS available for server-side scripting ...
Google Cloud Functions are written in JavaScript, and execute in
a Node.js runtime.
Mandrill also supports nodeJS and it features a Webhooks API.
Therefore, one can require that node module within these "cloud functions" and "web hooks" ...and then post with a HTML form onto them.
There would need to be a few HTTP cloud functions defined on the Firebase Console, in order to let them subscribe, unsubscribe and manage their subscriptions. One could even generate the HTML markup for the input form with cloud functions and then attach it. As an example, not tested and no guarantee included:
const functions = require('firebase-functions');
const mandrill = require('mandrill-api/mandrill');
var client = new mandrill.Mandrill('YOUR_API_KEY');
/* TODO: add the user on Firebase, respond through the API */
exports.user_add = functions.https.onRequest((req, res) => {
});
/* TODO: change subscription settings on Firebase, respond through the API */
exports.user_edit = functions.https.onRequest((req, res) => {
});
/* TODO: remove the user on Firebase, respond through the API */
exports.user_remove = functions.https.onRequest((req, res) => {
});
/* optional: generate the HTML markup of the form, send HTTP response */
exports.markup = functions.https.onRequest((req, res) => {
});
One can bind the events of Firebase Auth, to keep two user databases in in-sync (this is not required for Mandrill, but required for MailChimp - no matter whether using the PHP or nodeJS wrapper):
exports.on_user_create = functions.auth.user().onCreate(event => {
const user = event.data;
});
exports.on_user_delete = functions.auth.user().onDelete(event => {
const user = event.data;
});
Firebase on Websites explains it, while there is a Local Emulator for Cloud Functions.
You can play around with any of these: Angular, Ember, Knockout, React,
Node JS. The same thing you PHP code does you can make happen with pretty much any Javascript technologies - just no dynamic language. Also another way to do it is to used an online form providers like Jot Forms or others. You can create and style the form withing you online form account then simply add it to you site. Then when user post it will post to the form. As a result you have a centralized environment not only for you current site but for any others down the road. You can create a web service and post values there - then do whatever you want with them: save them to the database... Otherwords have another server that handles all those things so you can just call it from Firebase hosted sites. Hope that helps
PS: I am currently building a product that is a simplified version of Online Forms to be used on Firebase websites. I am planning to have a few people using for now so if you would like you can email me and I will create an account for you to use it. As long as there is no abuse like sending a bunch of emails - you will be fine!

How a fully scalable SPA with a solid backend is built

the past few weeks I've been hard at work with Angular, Node, TDD, Heroku, Amazon S3 etc. Trying to get a better picture of how a fully scalable SPA with a solid backend is built, working with grunt, bower, haven't dipped my toes in TDD using Jasmine yet, though I understand how the tests are being made through Karma, this is supposedly my next step.
One thing is sure: IT IS A LOT OF INFORMATION
On to the Questions/Rationale on working with all these technologies.
First things first, I played with
Angular App https://github.com/angular-app/angular-app
NG Boilerplate https://github.com/joshdmiller/ng-boilerplate
and read many dozens of posts etc.
I found NG Boilerplate to be most logical structured (as far as my understanding of these things go).
As a demo project (which evolved from something really small) I want to make a Single Page CRUD Application using:
NodeJS as backend
Express as a web app framework
NG Boilerplate as the Client
The app deployed to Heroku
MongoDB for DB
Amazon S3 for dynamic storage
Now I want to use Angular-Apps's (https://github.com/angular-app/angular-app) server as a backend to my NGBoilerplate kickstarter
I want to know how:
from what I see the client connects directly to MongoDB?
how does the angular client communicate back and forth to express ?
I read an interesting article http://www.espeo.pl/2012/02/26/authentication-in-angularjs-application related to how the authentication works.
Long Story Short, without me asking a ton of questions, could someone please describe in detail the workflow of such an app? Getting the session, login, access to editing the content, tying express routes to angular routes (e.g. X route can be accessed by the admin only) etc. ##
there'a big blur in my head :).
In the last months I played a lot with these issues and questions and I got to the following conclusion:
For my purposes, I needed an app that relies almost entirely on Angular, without a separate backend, and the present backend should be from Angular.
Why? Because I want all of my eggs in one basket, I don’t want to configure a ton of stuff on a lot of different parts.
As a basis for my project I ended up using ng-boilerplate, as a boilerplate :), with some changes to the development process, Grunt tasks etc, this is for everybody to figure out, depending on each particular project.
Well, the main issue I’m gonna touch here is that, for a true backend, made in Angular, we need secure routes and a secure persistence method, a database.
For the app, I took advantage of the ng-boilerplate's modular and dependency aware structure, I think it’s perfect for a Angular app.
Anyhow, I’m gonna take things top to bottom (final product wise, the build env as I said above, it’s up to you, but ng-boilerplate is awesome), here we go.
On the upper layer we have the actual Angular app, made just the way we want
The server container, is a NodeJS server with express and other modules to take PARTIAL care of the routing on different browsers and devices (In my app, I made HTML5 routing that is augmented by express, .htaccess like settings whenever there’s a partial URL it should redirect to index where Angular will read the path requested and zapp you to that location)
For my case, the whole things runs on Heroku, on a Node.JS application, you can install several other things there if you want to.
Now, for the persistency, to have authentication and security, and NOT to rely on backend for that, I am using firebase (https://www.firebase.com/), there’s some great tutorials there to help you going and have true persistence in your Angular APP, with routes when you are logged in, access to custom tables/objects in DB when you are logged in etc. It’s the real deal.
If you don’t want to rely OAuth’s possible sites to log in with (Facebook, github, persona or twitter) and want custom emails and addresses you can do that directly with Firebase, to create accounts and delete them etc.
FIREBASE Angular Backend.
So, Firebase, just like they say on the site is a powerful API to store and sync data in realtime.
I don’t know exactly how to approach this, so I’m gonna start it with creating a Firebase database. Once we create it, in the backend we have several options, one of which is security.
{
"rules": {
".read": true,
".write": "auth != null"
}
}
Here, if we read the documentation on https://www.firebase.com/docs/security/security-rules.html we’ll learn that we can add rules for each ‘table' in our database, so we can have like 3 protected ’table’ objects and some that are not protected.
We can protect tables per user basis, per different rules, if logged in or not, we also have inheritance for rules etc, pleas read the documentation there, it really is a good read.
Now, for these rules to take effect we need to enable the Firebase Simple Login and select the desired login method, from Facebook, Twitter, Github, Persona, Email&Password and Anonymous.
For a real app, we need to write info to DB also as anonymous (user sessions etc) and also as logged (with either of the options above) to store and read information.
Me, I wanted to go the quick easy way and made a Facebook authentication, reading the docs there I made a quick Facebook app, and in the settings of the application on Facebook I’m putting Firebase’s backend https://www.dropbox.com/s/xcd4b8tty1nlbm5/Screenshot%202014-01-22%2013.51.26.png
This gives a interim link to login to Facebook and have access to ’tables’ that are otherwise locked if the rule is auth !=null.
NOW, onto the Angular backend.
Firebase provides a library for us to put in our app, and a SimpleLogin lib, also, for Angular, a factory service called AngularFire.
In my case, I made local firebaseService with use methods that connects to my DB:
angular.module('firebaseService', ['firebase'])
.service('firebaseService', function ($firebase, $rootScope) {
//Input data in Firebase
var URL = "https://glowing-fire-xxxx.firebaseio.com";
var tellFirebase = function(ID, JSON) {
users = $firebase(new Firebase(URL + '/' + ID));
users.details = JSON;
users.$save('details');
};
return {
addUser: function(ID, JSON) {
tellFirebase(ID, JSON);
if ($rootScope.debugStatus === true) {
console.log('Firebase Service .addUSer Called');
}
},
getUser: function(ID) {
if ($rootScope.debugStatus === true) {
console.log('Firebase Service .getUser Called');
}
}
};
})
From here we do our READ/WRITE, on the controller’s page I have this:
It’s worth noticing that I have a middleware service (storageManagement) where I switch between Firebase and MongoDB, to avoid confusion.
.controller( 'SomeCtrl', function SomeController( $scope, storageManagement, $firebase, $firebaseSimpleLogin ) {
/*===========================
* ==== FIREBASE LOGIN
* ===========================*/
var URL = "https://glowing-fire-XXXXX.firebaseio.com";
var users = new Firebase(URL);
$scope.auth = $firebaseSimpleLogin(users, function(error, user){});
if ($scope.auth.user == null) {
//$scope.auth.$login('facebook');
}
console.log($scope.auth);
//$scope.auth.$logout('facebook');
$scope.doLogin = function() {
console.log($scope.facebookemail);
console.log($scope.facebookpassword);
$scope.auth.$login('facebook');
$scope.$on("$firebaseSimpleLogin:login", function(evt, user) {
storageManagement.runFirebase();
});
/* example of logging in while asking access to permissions like email, user_list, friends_list etc.
* auth.$login('facebook', {
rememberMe: true,
scope: 'email,user_likes'
});*/
};
$scope.doLogout = function() {
$scope.auth.$logout();
};
});
I’m adding the $firebase service to my controller, and the $firebaseSimpleLogin one.
This here exposes to scope two buttons, login/logout, that popup the OAuth window from Facebook, with email/password setting you won't need to to go through this I think, for a full understanding please read the full docs at firebase.
SO, once we are logged, we can access tables described in the rules, if we choose email/password, actually even for Facebook or other methods, we can assign certain rules for certain IDENTITIES, so you could have a ADMIN table where you could save settings that get READ on page load to apply whatever you want.
Now, with routes, we can check for the $scope.auth status, if WE PUT IT IN $rootScope, and check for the status when going to a route, if the status checks, we get to that route and it gets populated with stuff from the DB, otherwise, even if someone hacks it’s way to that route it won’t see anything because there are no permissions to read that table for unauthorized/wrong email users.
This is loosely based on this article, http://www.ng-newsletter.com/posts/back-end-with-firebase.html … I had a hard time changing the mindset from what the guy wrote there, but, after ONE WHOLE day, of reading the docs (and setting up middleware, mind you) from Firebase I figured it out, and it works.
The connection to the DB is exposed like one BIG object where you can do whatever operations you want.
This isn't the most complete explanation, but it should get you well on your way to making some awesome things:D
The best example of this that I've come across is called angular-app.
It's very comprehensive and addresses all your needs. It's written by one of the authors of the fantastic book "Mastering Web Application Development with AngularJS".
https://github.com/angular-app/angular-app
From the github repo:
AngularJS CRUD application demo
Purpose
The idea is to demonstrate how to write a typical, non-trivial CRUD application using AngularJS. To showcase AngularJS in its most advantageous environment we've set out to write a simplified project management tool supporting teams using the SCRUM methodology. The sample application tries to show best practices when it comes to: folders structure, using modules, testing, communicating with a REST back-end, organizing navigation, addressing security concerns (authentication / authorization).
We've learned a lot while using and supporting AngularJS on the mailing list and would like to share our experience.
Stack
Persistence store: MongoDB hosted on MongoLab
Backend: Node.js
Awesome AngularJS on the client
CSS based on Twitter's bootstrap
Build
It is a complete project with a build system focused on AngularJS apps and tightly integrated with other tools commonly used in the AngularJS community:
powered by Grunt.js
test written using Jasmine syntax
test are executed by Karma Test Runner (integrated with the Grunt.js build)
build supporting JS, CSS and AngularJS templates minification
Twitter's bootstrap with LESS templates processing integrated into the build
Travis-CI integration

Publish data from browser app without writing my own server

I need users to be able to post data from a single page browser application (SPA) to me, but I can't put server-side code on the host.
Is there a web service that I can use for this? I looked at Amazon SQS (simple queue service) but I can't call their REST APIs from within the browser due to cross origin policy.
I favour ease of development over robustness right now, so even just receiving an email would be fine. I'm not sure that the site is even going to catch on. If it does, then I'll develop a server-side component and move hosts.
Not only there are Web Services, but nowadays there are robust systems that provide a way to server-side some logic on your applications. They are called BaaS or Backend as a Service providers, usually to provide some backbone to your front end applications.
Although they have multiple uses, I'm going to list the most common in my opinion:
For mobile applications - Instead of having to learn an API for each device you code to, you can use an standard platform to store logic and data for your application.
For prototyping - If you want to create a slick application, but you don't want to code all the backend logic for the data -less dealing with all the operations and system administration that represents-, through a BaaS provider you only need good Front End skills to code the simplest CRUD applications you can imagine. Some BaaS even allow you to bind some Reduce algorithms to calls your perform to their API.
For web applications - When PaaS (Platform as a Service) came to town to ease the job for Backend End developers in order to avoid the hassle of System Administration and Operations, it was just logic that the same was going to happen to the Backend. There are many clones that showcase the real power of this strategy.
All of this is amazing, but I have yet to mention any of them. I'm going to list the ones that I know the most and have actually used in projects. There are probably many, but as far as I know, this one have satisfied most of my news, whether it's any of the previously ones mentioned.
Parse.com
Parse's most outstanding features target mobile devices; however, nowadays Parse contains an incredible amount of API's that allows you to use it as full feature backend service for Javascript, Android and even Windows 8 applications (Windows 8 SDK was introduced a few months ago this year).
How does a Parse code looks in Javascript?
Parse works through classes and objects (ain't that beautiful?), so you first create a specific class (can be done through Javascript, REST or even the Data Browser manager) and then you add objects to specific classes.
First, add up Parse as a script tag in javascript:
<script type="text/javascript" src="http://www.parsecdn.com/js/parse-1.1.15.min.js"></script>
Then, through a given Application ID and a Javascript Key, initialize Parse.
Parse.initialize("APPLICATION_ID", "JAVASCRIPT_KEY");
From there, it's all object manipulation
var Person = Parse.Object.extend("Person"); //Person is a class *cof* uppercase *cof*
var personObject = new Person();
personObject.save({name: "John"}, {
success: function(object) {
console.log("The object with the data "+ JSON.stringify(object) + " was saved successfully.");
},
error: function(model, error) {
console.log("There was an error! The following model and error object were provided by the Server");
console.log(model);
console.log(error);
}
});
What about authentication and security?
Parse has a User based authentication system, which pretty much allows you to store a base of users that can manipulate the data. If map the data with User information, you can ensure that only a given user can manipulate specific data. Plus, in the settings of your Parse application, you can specify that no clients are allowed to create classes, to ensure innecesary calls are performed.
Did you REALLY used in a web application?
Yes, it was my tool of choice for a medium fidelity prototype.
Firebase.com
Firebase's main feature is the ability to provide Real Time to your application without all the hassle. You don't need a MeteorJS server in order to bring Push Notifications to your software. If you know Javascript, you are half way through to bring Real Time magic to your users.
How does a Firebase looks in Javascript?
Firebase works in a REST fashion, and I think they do an amazing job structuring the Glory of REST. As a good example, look at the following Resource structure in Firebase:
https://SampleChat.firebaseIO-demo.com/users/fred/name/first
You don't need to be a rocket scientist to know that you are retrieve the first name of the user "Fred", giving there's at least one -usually there should be a UUID instead of a name, but hey, it's an example, give me a break-.
In order to start using Firebase, as with Parse, add up their CDN Javascript
<script type='text/javascript' src='https://cdn.firebase.com/v0/firebase.js'></script>
Now, create a reference object that will allow you to consume the Firebase API
var myRootRef = new Firebase('https://myprojectname.firebaseIO-demo.com/');
From there, you can create a bunch of neat applications.
var USERS_LOCATION = 'https://SampleChat.firebaseIO-demo.com/users';
var userId = "Fred"; // Username
var usersRef = new Firebase(USERS_LOCATION);
usersRef.child(userId).once('value', function(snapshot) {
var exists = (snapshot.val() !== null);
if (exists) {
console.log("Username "+userId+" is part of our database");
} else {
console.log("We have no register of the username "+userId);
}
});
What about authentication and security?
You are in luck! Firebase released their Security API about two weeks ago! I have yet to explore it, but I'm sure it fills most of the gaps that allowed random people to use your reference to their own purpose.
Did you REALLY used in a web application?
Eeehm... ok, no. I used it in a Chrome Extension! It's still in process but it's going to be a Real Time chat inside a Chrome Extension. Ain't that cool? Fine. I find it cool. Anyway, you can browse more awesome examples for Firebase in their examples page.
What's the magic of these services? If you read your Dependency Injection and Mock Object Testing, at some point you can completely replace all of those services for your own through a REST Web Service provider.
Since these services were created to be used inside any application, they are CORS ready. As stated before, I have successfully used both of them from multiple domains without any issue (I'm even trying to use Firebase in a Chrome Extension, and I'm sure I will succeed soon).
Both Parse and Firebase have Data Browser managers, which means that you can see the data you are manipulating through a simple web browser. As a final disclaimer, I have no relationship with any of those services other than the face that James Taplin (Firebase Co-founder) was amazing enough to lend me some Beta access to Firebase.
You actually CAN use SQS from the browser, even without CORS, as long as you only need the browser to send messages, not receive them. Warning: this is a kludge that would make my CS professors cry.
When you perform a GET request via javascript, the browser will always perform the request, however, you'll only get access to the response if it was from the same origin (protocol, host, port). This is your ticket to ride, since messages can be posted to an SQS queue with just a GET, and who really cares about the response anyways?
Assuming you're using jquery, your queue is https://sqs.us-east-1.amazonaws.com/71717171/myqueue, and allows anyone to post a message, the following will post a message with the body "HITHERE" to the queue:
$.ajax({
url: 'https://sqs.us-east-1.amazonaws.com/71717171/myqueue' +
'?Action=SendMessage' +
'&Version=2012-11-05' +
'&MessageBody=HITHERE'
})
The'll be an error in the console saying that the request failed, but the message will show up in the queue anyways.
Have you considered JSONP? That is one way of calling cross-domain scripts from javascript without running into the same origin policy. You're going to have to set up some script somewhere to send you the data, though. Javascript just isn't up to the task.
Depending in what kind of data you want to send, and what you're going to do with it, one way of solving it would be to post the data to a Google Spreadsheet using Ajax. It's a bit tricky to accomplish though.Here is another stackoverflow question about it.
If presentation isn't that important you can just have an embedded Google Spreadsheet Form.
What about mailto:youremail#goeshere.com ? ihihi
Meantime, you can turn on some free hostings like Altervista or Heroku or somenthing else like them .. so you can connect to their server , if i remember these free services allows servers p2p, so you can create a sort of personal web services and push ajax requests as well, obviously their servers are slow for free accounts, but i think it's enought if you do not have so much users traffic, else you should turn on some better VPS or Hosting or Cloud solution.
Maybe CouchDB can provide what you're after. IrisCouch provides free CouchDB instances. Lock it down so that users can't view documents and have a sensible validation function and you've got yourself an easy RESTful place to stick your data in.

Categories

Resources