Open Event Apk generator

So we made this apk generator currently hosted on a server (http://192.241.232.231) which let’s you generate an android app for your event in 10 minutes out of which the server takes about 8 minutes to build 😛 . So, essentially you just have to spare 2 minutes and just enter 3 things(email, Desired app’s name and Api link). Isn’t this cool?

So how exactly do we do this?

At the backend, we are running a python scripts with some shell scripts where the python script is basically creating directories, interacting with our firebase database to get the data entered by a user. So we made these scripts to first of all to clone the open event android repo, then customise and change the code in the repo according to the parameters entered by the organiser earlier(shown in the image).

Screen Shot 2016-06-14 at 12.13.12 AM
Generator Website

After the code has been changed by the scripts to customise the app according to the event the app will be used for, we move on to the script to build the apk, where we build and sign the apk in release mode using signing configs and release keys from the server because we don’t the organiser to generate keys and store it on the server to avoid the hassle and also the privacy concerns involving the keys. So this is when the apk is generated on the server. Now you have questions like the apk is generated but how do I get it? Do I have to wait on the same page for 10 minutes while the apk is being sent? The answer is no and yes. What I mean by this is that you can wait to download the apk if you want but we’ll anyways send it to your email you specified on the apk generator website. This is the sample Email we got when we were testing the system

Screen Shot 2016-06-14 at 12.08.59 AM.png

So it’s an end to end complete solution from which you can easily get an android app for your event in just 2 minutes. Would love to hear feedback and reviews. Please feel free to contact me @ manan13056@iiitd.ac.in or on social media’s(Twitter, Facebook). Adios!

P.S. : Here is the link to the scripts we’re using.

Continue ReadingOpen Event Apk generator

Sending a streaming zip file in node.js

The webapp generator that we set up is now up and running on a heroku instance and is working to generate zips of generated websites.

One of the requirements was that when the front-end presses, the “Generate” button, a request is created to the backend node app to start creating the html pages, and pack them into a zip file. Then the said zip file will be made available to download.

I intended for the zip file to become available to download immediately and the server to continuously pack data into the zip, as the user downloads it – a process known as streaming zip serving. (If you might have noticed, Google Drive uses this too. You do not know the final zip size before the download has completed.)

If the server takes time in creating the contents of the zip, this method can help, as it will allow the user to start downloading the file, before all the contents are finalised.

 

To achieve the mentioned goal, the idea Node.js module to use archiver.

If you look at the app.js code you’ll find on the /generate POST endpoint, we take the ‘req’ params and pass to a pipeToRes() function, which is defined in generator.js

app.post('/generate', uploadedFiles, function(req, res, next) {
console.log(req.files);
console.log(req.body);
res.setHeader('Content-Type', 'application/zip');
generator.pipeZipToRes(req, res);
});

And in the generator, you can find this block of code that pipes the streaming archive to the response.

 

      const zipfile = archiver('zip');

      zipfile.on('error', (err) => {
        throw err;
      });

      zipfile.pipe(res);

      zipfile.directory(distHelper.distPath, '/').finalize();

We zip the directory defined in distPath and the archiver API has a fluent call to .finalize() that finished the download for the user, when the zip is completed.

Continue ReadingSending a streaming zip file in node.js

Why should you use Heroku?

Last week I’ve dedicated most time to implement new heroku features to Open Event. Due to the fact that wasn’t easy tasks I can share my experience.

What is heroku?

Heroku is a cloud Platform-as-a-Service (PaaS) supporting several programming languages like Java, Node.js, Scala, Clojure, Python, PHP, and Go

Easy to deploy

what you need to do:

  1. Create account on heroku
  2. Download a heroku toolbelt to your enviroment.
  3. Go to your project directory(/open-event-orga-server)
  4. Sign in to heroku in your command line using your credentials
    $ heroku login
  5. Create app with name $
    heroku apps:create your_app_name

    after execution above command you will recive a link to your application

    http://your_app_name.herokuapp.com/
  6. Push latest changes to heroku
    $ git push heroku master
  7. If everythings is ok you can check results http://your_app_name.herokuapp.com/ (sometimes it does not work like we want 🙁 )

Easy to configure

To list/set/get config variables use:

$ heroku config
$ heroku config:set YOUR_VARIABLE=token123
$ heroku config:get YOUR_VARIABLE

or you can go to you application dashboard and make above operations

How you can get access to this variables using python langauges?

$ python

Python 2.7.10 (default, Oct 23 2015, 19:19:21) 

[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.5)] on darwin

Type "help", "copyright", "credits" or "license" for more information.

>>> import os

>>> your_variable  = os.environ.get('YOUR_VARIABLE', None)

>>> print your_variable
token123

I’ve used this to display current release in my python application(You need to generate a special API token and add it to config variables)

os.popen('curl -n https://api.heroku.com/apps/open-event/releases -H 
"Authorization: Bearer ' + token + '" -H 
"Accept: application/vnd.heroku+json; version=3"').read()

Easy to monitor

If something is wrong with your APP you need to use this command

$ heroku logs

it shows all logs

To see 10 latest releases use:

$ heroku releases

How you can set up Open Event to deploy to heroku?

  1. Clone https://github.com/fossasia/open-event-orga-server
  2. Go to directory of open event orga server(/open-event-orga-server)
  3. Add git remote
     heroku git:remote -a open-event
  4. You can check if open event is added to git remote
    $ git remote -v
    heroku https://git.heroku.com/open-event.git (fetch)
    heroku https://git.heroku.com/open-event.git (push)
    origin https://github.com/fossasia/open-event-orga-server.git (fetch)
    origin https://github.com/fossasia/open-event-orga-server.git (push)
  5. Now you can deploy changes to open-event application(You need a permissions 🙂 )

Why should you use a Heroku?

It’s great to deploy apps because you are able to share content in short time what I’ve done. Besides it’s very well documented so you can find there answers for most of your questions. Finally most of things you can configure using Heroku dashboard so it’s the best advantages of this tool.

Continue ReadingWhy should you use Heroku?

Better fields and validation in Flask Restplus

We at Open Event Server project are using flask-restplus for API. Apart from auto-generating of Swagger specification, another great plus point of restplus is how easily we can set input and output models and the same is automatically shown in Swagger UI. We can also auto-validate the input in POST/PUT requests to make sure that we get what we want.

@api.expect(EVENT_POST, validate=True)
def put(self, id):
    """Modify object at id"""
    pass

As can be seen above, the validate param for namespace.expect decorator allows us to auto-validate the input payloads. This used to work well until one day I realized there were a few problems.

  1. When a field was defined as say for example field.Integer, then it will accept only Integer values, not even null.
  2. If there is a string field and it has required param set to True, then also it is possible to set empty string as its value and the in-built validator won’t catch it.
  3. Even if I somehow managed to hack my way to support null in field, it will also support null even if required=True.
  4. We had no control on what error message was returned.
EVENT = api.model('Event', {
    'id': fields.Integer,
    'name': fields.String(required=True)
})

Specially problem #1 was a huge one as it questioned the whole foundation of the API. So we realized it will be better if we don’t use namespace.expect and use a custom validator. For custom validator, we first had to create custom fields that this validator can benefit from. Luckily flask-restplus comes with a great API for creating custom fields. So we quickly created custom fields for all common fields (Integer, String) and more specific fields like Email, Uri and Color. Creating these specific fields were a huge advantage as now we can show proper example for each field types in the Swagger UI.

class Email(fields.String):
    """
    Email field
    """
    __schema_type__ = 'string'
    __schema_format__ = 'email'
    __schema_example__ = 'email@domain.com'

Consider the above code; now when we use Email as a field for a value, then the example shown for it in Swagger UI will be ‘email@domain.com’. Quite cool, right?

Now we needed a way to validate these fields. For that, what we did was to create a validate method in each of the field-classes. This validate method would get the value and check if it was valid. Consider the following code –

import re
EMAIL_REGEX = re.compile(r'S+@S+.S+')

class Email():
	def validate(self, value):
		if not value:
		    return False if self.required else True
		if not EMAIL_REGEX.match(value):
		    return False
		return True

Once each of the field had their validate methods, we created a validate_payload() function that uses the API model and compares it with the payload. It will first check if all required keys are present in the payload or not. When that is true, it finally validates each field’s value using their field’s classvalidate method.

from flask import abort
from flask_restplus import fields
from custom_fields import CustomField

def validate_payload(payload, api_model):
    # check if any reqd fields are missing in payload
    for key in api_model:
        if api_model[key].required and key not in payload:
            abort(400, 'Required field '%s' missing' % key)
    # check payload
    for key in payload:
        field = api_model[key]
        if isinstance(field, fields.List):
            field = field.container
            data = payload[key]
        else:
            data = [payload[key]]
        if isinstance(field, CustomField) and hasattr(field, 'validate'):
            for i in data:
                if not field.validate(i):
                    abort(400, 'Validation of '%s' field failed' % key)

The CustomField is the base class that each of the custom fields mentioned above inherit. So checking if field was an instance of CustomField is enough to know if it is a custom field or not. Other thing that may look weird in the above code is use of fields.List. If you look closely, I have added this to support custom fields inside lists. So if you have used a custom field in a list, it will also work too. But obviously, this only supports single level lists for now. The thing is we didn’t needed more than that so I let it go. :stuck_out_tongue_winking_eye:

This basically sums up how we are validating input payloads at Open Event. Of course this is very basic but we will keep on improving it as the project progresses. Stay tuned to opev blog if you want to be in touch with the progress of the project.

Links to full code at the time of writing this post are –

  1. Custom Fields
  2. Validate Payload

I hope you found this post useful. Thanks for reading.

 

{{ Repost from my personal blog http://aviaryan.in/blog/gsoc/restplus-validation-custom-fields.html }}

Continue ReadingBetter fields and validation in Flask Restplus

Export Timeline as iCal

iCal or iCalendar is the Internet standard for sharing event schedules or session timelines among each other. The filename extension for iCal is .ics . It is supported by a number of applications such as Google Calendar, Apple Calendar,] Yahoo! Calendar, Lightning extension for Mozilla Thunderbird and SeaMonkey, and partially by Microsoft Outlook . In Open Event Organizer’s Server we have added a feature to export the Schedule of a particular Event in iCal format.

Continue ReadingExport Timeline as iCal

Building interactive elements with HTML and javascript: Drag and Drop

{ Repost from my personal blog @ https://blog.codezero.xyz/building-interactive-elements-with-html-and-javascript-drag-and-drop }

Traditionally, all interactions in a website has been mostly via form inputs or clicking on links/button. The introduction of native Drag-and-drop as a part of the HTML5 spec, opened developers to a new way of Graphical input. So, how could this be implemented ?

Making any HTML element draggable is as simple as adding draggable="true" as an attribute.

<div id="a-draggable-div" draggable=true>  
    <h4>Drag me</h4>
</div>  

This will allow the user to drag div#a-draggable-div. Next, we need to designate a dropzone, into which the user can drop the div.

<div id="dropzone" ondragover="onDragOver(event)">  
</div>  
function onDragOver(e) {  
    // This function is called everytime 
    // an element is dragged over div#dropzone
    var dropzone = ev.target;

}

Now, the user will be able to drag the element. But, nothing will happen when the user drops it into the dropzone. We’ll need to define and handle that event. HTML5 provides ondrop attribute to bind to the drop event.

When the user drops the div into the drop zone, we’ll have to move the div from it’s original position into the drop zone. This has to be done in the drop event.

<div id="dropzone"  
ondrop="onDrop(event)"  
ondragover="onDragOver(event)"> </div>  
function onDrop(e) {  
    e.preventDefault();
    var draggableDiv = document.getElementById("a-draggable-div");
    draggableDiv.setAttribute("draggable", "false");
    e.target.appendChild(draggableDiv);
}

So, when the user drops the div into the drop zone, we’re disabling the draggable property of the div and appending it into the drop zone.

This is a very basic drag and drop implementation. It gets the job done. But, HTML5 provides us with more events to make the user’s experience even better 1.

Event Description
drag Fired when an element or text selection is being dragged.
dragend Fired when a drag operation is being ended (for example, by releasing a mouse button or hitting the escape key).
dragenter Fired when a dragged element or text selection enters a valid drop target.
dragexit Fired when an element is no longer the drag operation’s immediate selection target.
dragleave Fired when a dragged element or text selection leaves a valid drop target.
dragover Fired when an element or text selection is being dragged over a valid drop target
dragstart Fired when the user starts dragging an element or text selection.
drop Fired when an element or text selection is dropped on a valid drop target.

With these events a little bit of css magic a more user friendly experience can be created like highlighting the drop zones when the user starts to drag an element or changing the element’s text based on its state.

Demo:

https://jsfiddle.net/niranjan94/tkbcv3md/16/embedded/

External Resources:
Continue ReadingBuilding interactive elements with HTML and javascript: Drag and Drop

SASS for the theme based concept

Until yesterday, I was exploring all around the internet, to find the best possible way for the theme concept in the web app. The theme concept allows an organizer to choose the theme for the web app from the set of provided themes.

After some time, I realised that this awesomeness to the web app can be added by using Syntactically Awesome Stylesheets.

How SASS supports the theme concept?

 

In the web app, a folder name _scss is added which has the directory structure as shown

tree
_scss folder directory structure

There is a file _config.scss inside the _base folder that includes the SASS variables which are used in all the files after importing it.

Each of the SASS variables uses a flag !default at the end, which means it can be overwritten in any other file. This property of SASS leads to the theme concept.

//_.config.scss

@charset "UTF-8";
 
// Colors
$black: #000;
$white: #fff;
$red: #e2061c;
$gray-light: #c9c8c8;
$gray: #838282;
$gray-dark: #333333;
$blue: #253652;
 
// Corp-Colors
$corp-color: $white !default;
$corp-color-dark: darken($corp-color, 15%) !default;
$corp-color-second: $red !default;
$corp-color-second-dark: darken($corp-color-second, 15%) !default;
 
// Fontbasic
$base-font-size: 1.8 !default;
$base-font-family: Helvetica, Arial, Sans-Serif !default;
$base-font-color: $gray-dark !default;
 
// Border
$base-border-radius: 2px !default;
$rounded-border-radius: 50% !default;
$base-border-color: $gray !default;

The main file that includes all the required style is the application.scss. Here, $corp-color takes default value from  _config.scss. It can be overwritten by the themes.

//application.scss

@charset 'UTF-8';

// 1.Base
@import '_base/_config.scss';

/* Offsets for fixed navbar */
body {
 margin-top: 50px;
 background-color:$corp-color !important;
}

Making a light theme 

 

The light theme will overwrite the $corp-color value to $gray-light which is defined in _config.scss. This will change the background-color defined in application.scss to #c9c8c8. So, in this way a light theme is generated. The similar approach can be followed to generate the dark theme.

//_light.scss

@charset 'UTF-8';
@import '../../_base/config';
// 1.Overwrite stuff
$corp-color: $gray-light;

@import '../../application';

Making a dark theme 

 

//_dark.scss

@charset 'UTF-8';
@import '../../_base/config';
// 1.Overwrite stuff
$corp-color: $gray;

@import '../../application';

How to compile the CSS from SASS files ?

 

  1. We can easily compile these SASS files by using command
    sass /path/application.scss /path/schedule.css

    For generating light theme and dark theme:

    sass /path/_light.scss  /path/schedule.css
    sass /path/_dark.scss  /path/schedule.css

Optimization of Code

 

SASS is very powerful for optimizing the code. It allows the concepts such as nesting, mixins which reduce the line of code. I have rewritten schedule.css into application.scss to make it more optimized.

/* Adjustments for smaller screens */

@media (min-width: 450px) {
 body {
 font-size: 14px
 }
 .session {
   &-list{
     .label{
         font-size: 90%;
         padding: .2em .6em .3em;
           }
         }
    &-title {
         float:left;
         width: 75%;
         }
    &-location {
         float: right;
         width: 25%;
         text-align: right;
        }
  }
}

Further Exploration

 

This is one of the ways to deal with the SASS structure, but there are other resources that can be helpful in dealing with SASS projects.

Also, check out, Jeremy Hexon article here.

Continue ReadingSASS for the theme based concept

Swagger

Swagger is a specification for describing REST APIs. The main aim of Swagger is to provide a REST API definition format that is readable by both machines and humans.

You can think of two entities in a REST API: One the provider of API, and another the client using the API. Swagger essentially covers the gap between them by providing a format that is easy to use by the client and easy for the provider to define.

If not using Swagger, one would most certainly be creating the API first, writing the documentation (human-readable) with it. The client developer would read the documentation and use APIs as required. With Swagger, the specification can be considered as the document itself, helping both the client developer and the provider.

Here’s an example spec I wrote for our GET APIs at Organizer Server: https://gist.github.com/shivamMg/dacada0b45585bcd9cd0fbe4a722eddf

The format, although readable doesn’t really look what a client developer would be asking for.

Remember that the format is machine readable? What does it mean exactly?

Since the Swagger spec is a defined format, the provider can document it and people can write programs that understand the Swagger specification. Swagger itself comes with a set of tools (http://swagger.io/tools/) that use Swagger definitions created by the API provider to create SDKs for the clients to use.

Swagger-UI

One of our most used tools at our server is the Swagger UI (http://swagger.io/swagger-ui/).

It reads an API spec written in Swagger to generate corresponding UI that people can use to explore the APIs. Every API endpoint can have responses and parameters associated with it. For instance our Event endpoint at Server (“/events/:event_id”).

You can see how the UI displays the Model Schema, required parameters and possible response message.

Screenshot from 2016-06-07 19:08:21

Apart from documentation, Swagger UI provides the “Try it out!” tool that lets you make requests to the server for the corresponding API. This feature is incredibly useful for POST requests. No need for long curl commands in the terminal.

Here’s the Swagger config from our demo application: https://open-event.herokuapp.com/api/v2/swagger.json

The Swagger UI for this config can be found at https://open-event.herokuapp.com/api/v2

The UI for the example spec (gist) I linked before can be browsed here.

Swagger-js

https://github.com/swagger-api/swagger-js

Swagger-js is JS library that reads an API spec written in Swagger and provides an interface to the client developer to interact with the API. We will be using Swagger-js for Open Event Webapp.

Here’s an example to show you how it works. Let’s say the following endpoint returns (json) a list of events.

/events

The client developer can create a GET request and render the list with HTML.

$.getJSON("http://example.com/api/v2/events", function(data) {

  var events = "";
  $.each(data, function(i, event) {
    events += "<li id='event_" + i + "'>" + event.name + "</li>";
  });

  $("ul#events").html(events);
});

What if the provider moves the endpoint to “/event/all”? The client developer would need to change every instance of the URL to http://example.com/event/all.

Let’s now take the case of Swagger-js. With Swagger-js the client developer would essentially be writing programs to interact with the API Swagger spec defined by the provider, instead of directly consuming the API.

window.client = new SwaggerClient({
    url: "http://example.com/api/v2/swagger.json",
    success: function() {
      client.event.getEvents({
        responseContentType: 'application/json'
      }, function(data) {

        /* Create `events` string same as before */

        $("ul#events").html(events);
      });
    }
  });

 

The APIs at the Organizer server are getting more complex. Swagger helps in keeping the spec well defined.

That’s all for now. Hope you enjoyed the read.

Continue ReadingSwagger

REST API Authentication in Flask

Recently I had the challenge of restricting unauthorized personnel from accessing some views in Flask. Sure the naive way will be asking the username and password in the json itself and checking the records in the database. The request will be something like this-

{
	"username": "open_event_user",
	"password": "password"
}

But I wanted to do something better. So I looked up around the Internet and found that it is possible to accept Basic authorization credentials in Flask (sadly it isn’t documented). For those who don’t know what Basic authorization is a way to send plain username:password combo as header in a request after obscuring them with base64 encoding. So for the above username and password, the corresponding header will be –

{
	"Authorization": "Basic b3Blbl9ldmVudF91c2VyOnBhc3N3b3Jk"
}

where the hashed string is base64 encoded form of string “open_event_user:password”.

Now back to the topic, so the next job is to validate the views by checking the Basic auth credentials in header and call abort() if credentials are missing or wrong. For this, we can easily create a helper function that aborts a view if there is something wrong with the credentials.

from flask import request, Flask, abort
from models import UserModel

app = Flask(__name__)

def validate_auth():
	auth = request.authorization
	if not auth:  # no header set
		abort(401)
	user = UserModel.query.filter_by(username=auth.username).first()
	if user is None or user.password != auth.password:
		abort(401)

@app.route('/view')
def my_view():
	validate_auth()
	# stuff on success
	# more stuff

This works but wouldn’t it be nice if we could specify validate_auth function as a decorator. This will give us the advantage of only having to set it once in a model view with all auth-required methods. Right ? So here we go

def requires_auth(f):
	@wraps(f)
	def decorated(*args, **kwargs):
		auth = request.authorization
		if not auth:  # no header set
			abort(401)
		user = UserModel.query.filter_by(username=auth.username).first()
		if user is None or user.password != auth.password:
			abort(401)
		return f(*args, **kwargs)
	return decorated

@app.route('/view')
@requires_auth
def my_view():
	# stuff on success
	# more stuff

I renamed the function from validate_auth to requires_auth because it suits the context better.

At this point, the above code may look perfect but it doesn’t work when you are accessing the API through Swagger web UI. This is because it is not possible to set base64 encoded authorization header from the swagger UI. For those who are wondering “what the hell is swagger”, I will define Swagger as a tool for API based projects which creates a nice web UI to live-test the API and also exports a schema of the API that can be used to understand API definitions.

Now how do we get requires_auth to work when a request is sent through swagger UI ? It was a little tricky and took me a couple of hours but I finally got it. The trick therefore is to check for active sessions when there are no authorization headers set (as in the case of swagger UI). If an active session is found, it means that the user is authenticated. Here I would like to suggest using Flask-Login extension which makes session and login management a child’s play. Always use it if your flask project deals with login, user accounts and stuff.

Now back to the task in hand, here is how we can set the requires_auth function to check for existing sessions.

from flask import request, abort, g
from flask.ext import login

def requires_auth(f):
	@wraps(f)
	def decorated(*args, **kwargs):
		auth = request.authorization
		if not auth:  # no header set
			if login.current_user.is_authenticated:  # check active session
				g.user = login.current_user
				return f(*args, **kwargs)
			else:
				abort(401)
		user = UserModel.query.filter_by(username=auth.username).first()
		if user is None or user.password != auth.password:
			abort(401)
		g.user = user
		return f(*args, **kwargs)
	return decorated

Pretty easy right !! Also notice that I am saving the user who was currently authenticated in flask’s global variable g. Now the authenticated user can be accessed from views as g.user. Cool, isn’t it ? Now if there is a need to add a more secure form of authorization like ‘Token’ based, you can easily update therequires_auth decorator to get the same results.

I hope this article provided valuable insight into managing REST API authorizations in Flask. I will keep posting more awesome things I learn in my GSoC journey.

That’s it. Sayonara.

 

{{ Repost from my personal blog http://aviaryan.in/blog/gsoc/auth-flask-done-right.html }}

Continue ReadingREST API Authentication in Flask