Web.py Application – User Auth with token features

Visit Github Repository to view the code sample in full.

Introduction

User authentication is one of the most basic system that all web application will have. For many frameworks, there is already some sort of authentication system you could use, but for web.py, there is not such system available. But it shouldn’t stop you from using the framework, because creating one is not really that difficult.

In the past, I have written a tutorial on creating login systems for web application, but when I am working on a data API, I realized that having a token system makes work much much easier. You could integrate other authentication standards using this code, but this is just the very basic framework that you build upon for your application.

Differences from last version

In the last version of the tutorial, I used sessions to store the user’s session, but for this version, I will be designing it for a RESTful API, so, the bulk of the authentication will be done through the generation and usage of tokens.

Creating the database

This is pretty self explanatory, but this is just the most basic of the database structure, alter to fit your own needs.

app = web.application(urls, globals())
db = web.database(dbn='sqlite', db='database.db')
db.query('''
    CREATE TABLE IF NOT EXISTS users(
        uid INTEGER PRIMARY KEY,
        uusr TEXT NOT NULL,
        upwd TEXT NOT NULL,
        utme INTEGER,
        utkn TEXT
    );
''')

Additional functions

These are functions that are required for the user authentication system to work, accomplishing all the backend task such as accessing the database or generating tokens.

Generating tokens

This is a simple token generating scheme that you could use. For your application, you could use a much more sophisticated scheme.

def genToken():
    r = rand.random()
    return str(hashlib.sha1('%f%s'%(r, time.ctime())).hexdigest())

Encoding the password

It is never secure to save your password as plaintext. Instead use password hash scheme such as the one implemented here.

def getPwd(usr, pwd):
    return hashlib.sha1('%s:%s'%(usr, pwd)).hexdigest()

Signing up for a new account

The section of the code ensures that the request is in the correct format and if everything is all and well, it will serve to create an user account and store the user information into the database. The most crucial error that this process is the possibility that the user account might have already been created before, hence, we got to handle that error right there.

class SignUp:
    @json_response
    def POST(self):
        i = web.input()
        if not i.get('usr') or not i.get('pwd'):
            return web.badrequest()
        usr = i.get('usr');
        pwd = getPwd(usr, i.get('pwd'))

        if getUser(usr):
            return {'error': 'userExist - user already exist'}

        db.insert('users', uusr=usr, upwd=pwd, utkn=genToken(), utme=int(time.time()))

        return {'sucess': True}

Signing in and getting a token

Signing into the data API would return a access token, but if the token is not accessed within 4 hours of the last use, the token is regenerated and the new token will be returned. This is just a simple scheme that is implemented here, it should be changed to suit your application’s needs.

There are a few errors that might occur during the sign in process. For one, the user account might not already exist. The password could be wrong, authentication information might be missing.

class SignIn:
    @json_response
    def GET(self):
        i = web.input()
        if not i.get('usr') or not i.get('pwd'):
            return web.badrequest()
        usr = i.get('usr')
        pwd = getPwd(usr, i.get('pwd'))

        user = getUser(usr)
        if not user:
            return {'error': 'userNotExist - user does not exist'}

        if not user['upwd']==pwd:
            return {'error': 'invalidPass - invalid password, try again'}
        else:
            t = int(time.time())
            ### Token expires within 4 hours of inactivity
            if user['utkn'] && t-user['utme'] > 14400:
                token = genToken()
            else:
                token = user['utkn']

            res = db.update('users', where='uid=$id', utkn=token, utme=int(time.time()), vars={'id':user['uid']})

            return {'success':True, 'token':token}

        return {'error':'loginError - cannot login'}

Signing out

For a token access system, the signing out process will just be removing the token and resetting the sign in time. And by resetting the token, the previous token will be invalidated and it will be just like signing the user out of the system.

class SignOut:
    @json_response
    def GET(self):

        i = web.input()
        if not i.get('tkn'):
            return web.badrequest()
        tkn = i.get('tkn')

        user = getUser(None, tkn)
        if not user:
            return {'error':'Not logged in'}

        res = db.update('users', where='uid=$id', utkn=None, vars={'id':user['uid']})

        return web.seeother('/')

Things to note

  • For testing purposes, the functions corresponds to GET request, but for product do change them to POST queries that do not make plaintext information as available
  • User authentication system should always be done using some sort of security, namely with a SSL enabled connection
  • This set of of code is just a sample proof of concept. Always alter the code to suit your own needs.
  • If you have any questions or if anything is unclear, shoot me an email.

Explaining SIFT feature detection — Image Processing

Feature detection

Feature detection is one of the most important stage of any image processing task. The detecting of unique features in an image allows computer to recognize objects in the image, hence, giving way to more complex task from image stitching, object tracking or even 3D reconstruction.

SIFT (Scale Invariant Feature Transform)

The most basic of feature detectors focuses on finding basic features in the images, this can be in the form of corners (harris detector) or edges (canny detector), these are often features that are affected by scale transform.

SIFT on the other hand, aims to produce scale invariant (not affected by scale) features with descriptors that will perform well in the feature matching stage of the image processing pipeline.

Scaling affects feature detection

As seen above features might look different under different scale. In order to produce features that can be recognized under different scales means that we have to search for the features in different scale space.

Scale space for feature searching

Difference of Gaussian

As you can see from the above images of the cat, prominent features such as the unique shape of the nose and the eyes will remain prominent even after applying a gaussian filter.

By taking a difference of the gaussian filters, we will be able to extract prominent features that will perform well in more complex task such as keypoint matching.

Difference of Gaussian

Scale-space Local Extremas

The features in the images are basically the local extremas within the search window. To obtain the minima and maxima, the target pixel (colored yellow) is compared with a set of other pixels (colored blue). If it is larger or smaller than all the other pixels, those will be marked as the features.

Scale-space local extremas

Orientation detection

As of most feature detectors, SIFT uses the gradient of the image patch to distinguish different features. For each feature, the general direction of the gradient is computed. Keypoint orientation produces rotation invariant features, allowing features to remain distinguishable across different images.

Detecting orientation of a feature

SIFT Descriptors

Descriptors, as the name suggest, are used to describe the features such that in the further stages of the image processing pipeline, the feature matcher will be able to tell apart the different keypoints.

SIFT computes the gradient of small images patches that makes up the feature, generating a orientation in either of the 8 directions. The information in the 16×16 window is then encoded into a 4×4 keypoint descriptor, leading to a 128 (448) dimensional feature vector.

Feature descriptors

Try it out

If you are interesting in trying out SIFT. I would suggest you try out the OpenCV implementation of SIFT feature detection, where you can easily plot out the features. OpenCV is pretty easy to setup, and if you are feeling up to it, there are many tutorials out there that teaches you to use the library to accomplish more complex task such as image stitching and 3D reconstruction.

OpenCV SIFT detection

Simple Showcase for my design projects

Link

I plan to extend the design projects into a long term project where I will be working on different designs on and off. As such, I have created a landing page of sort, where I showcase my finished designs.

If you have any projects or know of anyone requiring such websites made, do feel free to contact at ongspxm@gmail.com

Do note: These are not actual workable websites, and are just simple implementation of the designs serve to showcase or hone my skill in frontend work. These mockups are not complete in anyway and act only as a gauge of what is possible. If you find any functions faulty in any of these mockups, it is not because I have no idea how to implement the feature, but rather, it is not essential to have them, because they are not a substantial part of the design.

CodeJam – 2014 Campus Test – Practice

bitbucket repository

Bad Horse

Problem description
Running through the list of conflicting members, we generate a list of dictionary with the key, name, and the value, the array of members, that can’t be in the same group as name.

The list is then iterated through, putting the members in different groups, either 0 or 1. For each member in the list, it is placed in group 0, and the conflicting members, group 1. Recursively, each conflicting member is passed the same function. If two conflicting members are found to be in the same group, then it is an impossible task to group them.

### Getting the list of members
names = {
    name: [list of enemies],
    ...
}

### Function to add to group
groupings = [NULL] * number of members
function putInGroup(member){
    if dun already have group{
        put in group 0
    }
    if have group and in same group as enemy{
        return False #impossible case
    }
    foreach enemy in names[member]{
        putInGroup(enemy)
    }
}

### Try to sort them into groups
putInGroup(first member of list)

Captain Hammer

Problem Description
This is really just a physics problem. Just pop in some physics equation (s**2 = ut + 0.5at**2) and then you just run the numbers and everything will just fit.

Moist

Problem Description
This is basically a simulation problem. Just check if the previous card is larger than the current card, and count the number of time this occurs and that will be all.

View code in the bitbucket repository