Integrating Firebase Cloud Functions In Badgeyay

Badgeyay is an open source project developed by FOSSASIA Community for generating badges for conferences and events. The Project is divided into two parts frontend, which is in ember, and backend, which is in flask. Backend uses firebase admin SDK (Python) and Frontend uses firebase javascript client with emberfire wrapper for ember. Whenever an user signs up on the website, database listener that is attached to to the Model gets triggered and uses flask-mail for sending welcome mail to the user and in case of email and password signup, verification mail as well. Problem is sending mail using libraries is a synchronous process and takes a lot of processing on the server. We can use messaging queues like RabbitMQ and Redis but that will be burden as server cost will increase. The workaround is to remove the code from the server and create a firebase cloud function for the same task. Firebase cloud functions lets you run backend code on the cloud and can be triggered with HTTP events or listen for the events on the cloud, like user registration. Procedure Firebase uses our Gmail ID for login, so make sure to have a Gmail ID and on the first sight we will be greeted with Firebase console, where we can see our created or imported firebase apps. Create the app by clicking on the Add Project Icon and write the name of the application (e.g. Test Application) and select the region, in my case it is India. Firebase will automatically generated an application ID for the app. Click on Create Project to complete creation of project After Completion, click on the project to enter into the project. You will be greeted with an overview saying to integrate firebase with your project. We will click on the Add Firebase to web App and save the config as JSON in a file as clientKey.json for later use. Now we need to install the firebase tools on our local machine so for that execute npm i -g firebase-tools Now login from the CLI so that firebase gets token for the Gmail ID of the user and can access the firebase account of that Gmail ID. firebase login After giving permissions to the firebase CLI from your Gmail account in the new tab opened in browser, create a folder named cloud_functions in the project directory and in that execute firebase init Select only functions from the list of options by pressing space. After this select the project from the list where you want to use the cloud function. You can skip the step if you later want to add the cloud function to project by selecting don’t setup a default project and can later be used by command firebase use --add Choose the language of choice If you want, you can enforce eslint on the project and after this the cloud function is set up and the directory structure looks as follows. We will write our cloud function in index.js. So let’s take…

Continue ReadingIntegrating Firebase Cloud Functions In Badgeyay

Integrating Firebase Cloud Functions In Badgeyay

Badgeyay is an open source project developed by FOSSASIA Community for generating badges for conferences and events. The Project is divided into two parts frontend, which is in ember, and backend, which is in flask. Backend uses firebase admin SDK (Python) and Frontend uses firebase javascript client with emberfire wrapper for ember. Whenever an user signs up on the website, database listener that is attached to to the Model gets triggered and uses flask-mail for sending welcome mail to the user and in case of email and password signup, verification mail as well. Problem is sending mail using libraries is a synchronous process and takes a lot of processing on the server. We can use messaging queues like RabbitMQ and Redis but that will be burden as server cost will increase. The workaround is to remove the code from the server and create a firebase cloud function for the same task. Firebase cloud functions lets you run backend code on the cloud and can be triggered with HTTP events or listen for the events on the cloud, like user registration. Procedure Firebase uses our Gmail ID for login, so make sure to have a Gmail ID and on the first sight we will be greeted with Firebase console, where we can see our created or imported firebase apps. Create the app by clicking on the Add Project Icon and write the name of the application (e.g. Test Application) and select the region, in my case it is India. Firebase will automatically generated an application ID for the app. Click on Create Project to complete creation of project After Completion, click on the project to enter into the project. You will be greeted with an overview saying to integrate firebase with your project. We will click on the Add Firebase to web App and save the config as JSON in a file as clientKey.json for later use. Now we need to install the firebase tools on our local machine so for that execute npm i -g firebase-tools   Now login from the CLI so that firebase gets token for the Gmail ID of the user and can access the firebase account of that Gmail ID. firebase login   After giving permissions to the firebase CLI from your Gmail account in the new tab opened in browser, create a folder named cloud_functions in the project directory and in that execute firebase init   Select only functions from the list of options by pressing space. After this select the project from the list where you want to use the cloud function. You can skip the step if you later want to add the cloud function to project by selecting don’t setup a default project and can later be used by command firebase use --add Choose the language of choice If you want, you can enforce eslint on the project and after this the cloud function is set up and the directory structure looks as follows. We will write our cloud function in index.js.…

Continue ReadingIntegrating Firebase Cloud Functions In Badgeyay

Scaling the logo of the generated events properly in Open Event Webapp

In the Open Event Webapp we came across an issue to scale the logo of the different generated events properly. On the outset, it looks a simple problem but it is a bit tricky when we consider the fact that different events have different logo sizes and we have to make sure that the logo is not too wide nor is it too long. Also, the aspect ratio of the image shouldn’t be changed otherwise it would look stretched and pixelated. Here are some screenshots to demonstrate the issue. In the Facebook Developer Conference, the logo was too small In the Open Tech Summit Event, the logo was too long and increased the height of the navigation bar We decide some constraints regarding the width and the height of the logo. We don’t want the width of the logo to exceed greater than 110 pixels in order to not let it become too wide. It would look odd on small and medium screen if barely passable on bigger screens. We also don’t want the logo to become too long so we set a max-height of 45 pixels on the logo. So, we apply a class on the logo element with these properties .logo-image {  max-width: 110px;  max-height: 45px; } But simply using these properties doesn’t work properly in some cases as shown in the above screenshots. An alternative approach is to resize the logo appropriately during the generation process itself. There are many different ways in which we can resize the logo. One of them was to scale the logo to a fixed dimension during the generation process. The disadvantage of that approach was that the event logo comes in different size and shapes. So resizing them to a fixed size will change its aspect ratio and it will appear stretched and pixelated. So, that approach is not feasible. We need to think of something different.  After a lot of thinking, we came up with an algorithm for the problem. We know the height of the logo would not be greater than 45px. We calculate the appropriate width and height of the logo, resize the image, and calculate dynamic padding which we add to the anchor element (inside which the image is located) if the height of the image comes out to be less than 45px. This is all done during the generation of the app. Note that the default padding is 5px and we add the extra pixels on top of it. This way, the logo doesn’t appear out of place or pixelated or extra wide and long. The detailed steps are mentioned below Declare variable padding = 5px Get the width, height and aspect ratio of the image. Set the height to 45px and calculate the width according to the aspect ratio. If the width <= 110px, then directly resize the image and no change in padding is necessary If the width > 110px, then make width constant to 110px and calculate height according to the aspect ratio. It will surely come…

Continue ReadingScaling the logo of the generated events properly in Open Event Webapp

Writing Selenium Tests for Checking Bookmark Feature and Search functionality in Open Event Webapp

We integrated Selenium Testing in the Open Event Webapp and are in full swing in writing tests to check the major features of the webapp. Tests help us to fix the issues/bugs which have been solved earlier but keep on resurging when some new changes are incorporated in the repo. I describe the major features that we are testing in this. Bookmark Feature The first major feature that we want to test is the bookmark feature. It allows the users to mark a session they are interested in and view them all at once with a single click on the starred button. We want to ensure that the feature is working on all the pages. Let us discuss the design of the test. First, we start with tracks page. We select few sessions (2 here) for test and note down their session_ids. Finding an element by its id is simple in Selenium can be done easily. After we find the session element, we then find the mark button inside it (with the help of its class name) and click on it to mark the session. After that, we click on the starred button to display only the marked sessions and proceed to count the number of visible elements on the page. If the number of visible session elements comes out to be 2 (the ones that we marked), it means that the feature is working. If the number deviates, it indicates that something is wrong and the test fails. Here is a part of the code implementing the above logic. The whole code can be seen here // Returns the number of visible session elements on the tracks page TrackPage.getNoOfVisibleSessionElems = function() { return this.findAll(By.className('room-filter')).then(this.getElemsDisplayStatus).then(function(displayArr) { return displayArr.reduce(function(counter, value) { return value == 1 ? counter + 1 : counter; }, 0); }); }; // Bookmark the sessions, scrolls down the page and then count the number of visible session elements TrackPage.checkIsolatedBookmark = function() { // Sample sessions having ids of 3014 and 3015 being checked for the bookmark feature var sessionIdsArr = ['3014', '3015']; var self = this; return self.toggleSessionBookmark(sessionIdsArr).then(self.toggleStarredButton.bind(self)).then(function() { return self.driver.executeScript('window.scrollTo(0, 400)').then(self.getNoOfVisibleSessionElems.bind(self)); }); }; Here is the excerpt of code which matches the actual number of visible session elements to the expected number. You can view the whole test script here //Test for checking the bookmark feature on the tracks page it('Checking the bookmark toggle', function(done) { trackPage.checkIsolatedBookmark().then(function(num) { assert.equal(num, 2); done(); }).catch(function(err) { done(err); }); }); Now, we want to test this feature on the other pages: schedule and rooms page. We can simply follow the same approach as done on the tracks page but it is time expensive. Checking the visibility of all the sessions elements present on the page takes quite some time due to a large number of sessions. We need to think of a different approach.We had already marked two elements on the tracks page. We then go to the schedule page and click on the starred mode. We calculate the current height of the page. We…

Continue ReadingWriting Selenium Tests for Checking Bookmark Feature and Search functionality in Open Event Webapp

Keep your node server running using PM2

The open event webapp generator is a node projects (using an express server), and a copy of it runs all the time on my personal DigitalOcean box (other than our heroku instance). On a service like Heroku, the platform manages the task of bringing your server process up. But on, say a Linux distro on the DO box, you have to manually do npm run server to be able to run the server. While that is all good, it is a foreground shell process, which means, you will lose the node server, when you log out (or your internet connection into the ssh breaks). So we need to be able to keep the process running in the background. The way we do it in bash on Unix, is that we can do either of the following npm run server& The "&" at the end means it will make a background fork of this task. Or if you've already started it without it, you can also do the following. npm run server # starts in foreground #Press Ctrl + Z, this pauses task and frees the shell bg 1 # sends task no 1 to background thread. Again, both these are hacky methods, will work only on Unix OSs, and are not really recommended for production. For production, we need a Process Manager, for Node.js the best we can get is pm2 - purpose built process manager for node. Install pm2 first sudo npm install -g pm2 Using pm2, we can start any process that can be started with node. We can start the app.js script like this pm2 start src/app.js Also, pm2 can run npm tasks too like pm2 start npm -- start Pm2 has a pretty status message display window. And we can start, stop, pause, kill and/or restart any process.  

Continue ReadingKeep your node server running using PM2

sTeam GSoC 2016 Windup

(ˢᵒᶜⁱᵉᵗʸserver) aims to be a platform for developing collaborative applications. sTeam server project repository: sTeam. sTeam-REST API repository: sTeam-REST An overview of the work done by ajinkya007 during Google Summer of code 2016 with FOSSASIA on its project sTeam. The community bonding period saw the creation of a docker image and a debian package for the sTeam server. The integration of the sTeam shell into vi, improvements in the export and import to git scripts, user and group manipulation commands, sending mails through the commandline, viewing logs and the edit script modifications were done subsequently. The later part of GSOC saw that the sTeam-rest repository was restructured, unit and api-end point tests were performed. The new web interface developed was tested. The code written during this period by me and siddhant was merged and the conflicts were resolved. The merged code was tested thoroughly as no automated test integration tool supports pike programming language. Documentation was generated using Doxygen and deployed in the gh-pages of the sTeam server repository. A trello board was maintained throughout the course of GSOC 2016. Trello Board: sTeam Accomplishments Issues Resolved and Pull Requests Submitted for the same Commits Merged Blog Posts Scrums Further Improvements Issues Reported and Resolved A list of tasks covered and all the Pull requests related to each: Tasks Issue PR Make changes in the Makefile for installation of sTeam. Issue-25 Issue-27 PR-66 PR-67 Edit script modifications Issue-20 Issue-29 Issue-43 PR-44 PR-48 Indentation of output in steal-shell. Issue-24 PR-42 Integrate steam-shell into vim or emacs. Issue-37 Issue-43 Issue-49 PR-41 PR-48 PR-51 Improve the import and export from git scripts. Issue-9 Issue-14 Issue-16 Issue-18 Issue-19 Issue-46 PR-45 PR-54 PR-55 PR-76 Create, Delete and List the user through commandline Issue-58 Issue-69 Issue-72 PR-59 PR-70 PR-78 Sending Mails through commandline Issue-74 PR-85 Generate error logs and display them in CLI Issue-83 PR-86 Create a file of any mime type from command line. Issue-79 PR-82 Add more commands for group operations. Issue-80 PR-84 Add more utility to the steam-shell Issue-56 Issue-71 Issue-73 PR-57 PR-75 PR-81 Restructure the sTeam-rest repository List of Issue's List of PR's Write test cases to test sTeam-rest api List of Issue's List of PR's Create a debian package and a docker image for easy deployment Create docker image Docker Image Document the work done Issue 149 sTeam Server Structure, sTeam Server Documentation Test the web-interface ✓ ✓ Commits Merged During the course of GSOC 2016, work was done on the sTeam and sTeam-rest repositories. 1. The work done on the sTeam repository. We have combined all the work into two branches for the ease of creating a debian package. The commits made by me in each branch can be seen here. gsoc2016-societyserver-devel gsoc2016-source 2. The work done on the sTeam-rest repository The push request's sent for the issue's are yet to be merged in the main repository. The list of PR's for the sTeam-rest repository. sTeam-rest PR's The weekly blogs The blogs summarizing the work done during the week were published…

Continue ReadingsTeam GSoC 2016 Windup

File upload progress in a Node app using Socket.io

If you look at the webapp generator, you'll see that there is an option to upload a zip file containing event data. We wanted to give visual cue to the user when he is uploading to see how much file has uploaded. We are uploading the file, and giving the generate start command via socket.io events instead of POST requests here. To observe file upload progress on socket (when sending file using a Buffer), there is an awesome node module available called socketio-upload-progress. In our webapp you can see we implemented it on the frontend here in the form.js and here in the backend in app.js Basically on the backend you should add the socketio-file-upload module as a middleware to express var siofu = require("socketio-file-upload"); var app = express() .use(siofu.router) .listen(8000); After a socket is opened, set up the upload directory and start listening for uploads io.on("connection", function(socket){ var uploader = new siofu(); uploader.dir = "/path/to/save/uploads"; uploader.listen(socket); }); On the frontend, we'll listen for an input change on an file input type element whose id is siofu_upload var socket = io.connect(); var uploader = new SocketIOFileUpload(socket); uploader.listenOnInput(document.getElementById("siofu_input")); One thing to note here is that, if you observe percentage of upload on frontend, it'll give you false values. The correct values of how much data is actually transferred can be found in the backend. So observe progress in backend, and send percentage to frontend using the same socket. uploader.on('progress', function(event) { console.log(event.file.bytesLoaded / event.file.size) socket.emit('upload.progress', { percentage:(event.file.bytesLoaded / event.file.size) * 100 }) });  

Continue ReadingFile upload progress in a Node app using Socket.io

Using compression middleware in Node/Express

If you're using ExpressJS to host your server, there's a small performance tweak that you can do (works on universally on any kind of server - HTML templates to JSON REST APIs to image servers) - which is to enable GZIP compression. The changed required to do it should be very simple. First install the compression npm package npm install --save compression In you app.js (or wherever you start your express server), modify the code to include the compression middleware like this var express = require('express); var app = express(); var compression = require('compression'); app.use(compression()); // Rest of your app code // app.get (endpoint, callback) // app.listen(port, callback) This should easily reduce page loads time to the order of 15-20%. For example, page load before compression middleware added   And Page load time after compression is added

Continue ReadingUsing compression middleware in Node/Express