Repository: HTTP-APIs/hydrus
Pull request #194 (2018-05-18 05:42:58)

Develop
<!-- Please create/claim an issue before sending a PR -->
<!-- Add issue number (Eg: fixes #123) -->

Fixes #

### Checklist
- [ ] My branch is up-to-date with upstream/develop branch.
- [ ] Everything works and tested for Python 3.5.2 and above.

### Description
<!-- Describe about what this PR does, previous state and new state of the output -->

### Test Logs
<!-- Please submit test logs to confirm everything is working. -->



Patch:
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
new file mode 100644
index 0000000..f37889c
--- /dev/null
+++ b/.github/CONTRIBUTING.md
@@ -0,0 +1,21 @@
+### Contribution Best Practices
+
+* Read this [how-to about Github workflow here](https://guides.github.com/introduction/flow/) if you are not familiar with.
+
+* Read all the texts related to [contributing for an OS community](https://github.com/HTTP-APIs/hydrus/tree/master/.github).
+
+* Read this [how-to about writing a PR](https://github.com/blog/1943-how-to-write-the-perfect-pull-request) and this [other how-to about writing a issue](https://wiredcraft.com/blog/how-we-write-our-github-issues/)
+
+* **first ask in chat**: if you find a problem, first ask for [help in the chat](https://gitter.im/HTTP-APIs/Lobby), then consider opening a issue.
+    
+* **read history**: before opening a PR be sure that all the tests pass successfully. If any is failing for non-related reasons, annotate the test failure in the PR comment.
+
+* **PRs on develop**: any change should be PRed first in `develop`, `master` can only receive merge from develop.
+
+* **testing**:  everything should work and be tested for Python 3.5.2 and above.
+    
+* **free PR**: no permission is needed to work on the code. Fork `master`, submit a PR and ask for reviewing. PR is the natural place for code comparison and corrections. If many contributors have something ready in a PR, we can consider opening a branch in which different people working on the same part of the application can collaborate.
+
+* **pylint**: code in PRs should be accurately compliant with [PEP-8](https://www.python.org/dev/peps/pep-0008/), checking code with `pylint` is fine.
+
+* **mypy**: every module is and should in future provide type annotations using `mypy`.
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index d5d65c6..8fd052c 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -12,3 +12,23 @@ Fixes #
 
 ### Test Logs
 <!-- Please submit test logs to confirm everything is working. -->
+
+### Changes log
+
+#### Added
+<!-- Edit these points below to describe the new features added with this PR -->
+- Feature 1
+- Feature 2
+
+#### Changed
+<!-- Edit these points below to describe the changes made in existing functionality with this PR -->
+- Change 1
+- Change 2
+
+#### Fixed
+<!-- Edit these points below to describe the bug fixes made with this PR -->
+- Bug 1
+
+#### Removed
+<!-- Edit these points below to describe the removed features with this PR -->
+- Deprecated feature 1
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index e7218ac..b5403b8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,7 @@
 # Byte-compiled / optimized / DLL files
+
+.idea/**
+
 __pycache__/
 *.py[cod]
 *$py.class
diff --git a/LICENSE b/LICENSE
index b784f34..a6497ae 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,21 +1,8 @@
-MIT License
+Copyright 2017 HYDRA W3C Group
 
-Copyright (c) 2018 HYDRA W3C Group, Github.com/HTTP-APIs contributors
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
 
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/README.md b/README.md
index fbff772..530957c 100644
--- a/README.md
+++ b/README.md
@@ -16,18 +16,18 @@ Features
 Hydrus supports the following features:
 - A client that can understand Hydra vocabulary and interacts with a Hydra supporting server to basic [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) operations on data.
 - A generic server that can serve required data and metadata(in the form of API documentation) to a client over HTTP.
-- A middleware that allows users to use the client to interact with the server using Natural Language which is processed machine consumable language. **(under developement)**
+- A middleware that allows users to use the client to interact with the server using Natural Language which is processed machine consumable language. **(under development)**
 
 <a name="req"></a>
 Requirements
 -------------
 The system is built over the following standards and tools:
 - [Flask](http://flask.pocoo.org/) a Python based micro-framework for handling server requests and responses.
-- [JSON-LD](http://json-ld.org/spec/latest/json-ld/) as the prefered data format.
+- [JSON-LD](http://json-ld.org/spec/latest/json-ld/) as the preferred data format.
 - [Hydra](http://www.hydra-cg.com/) as the API standard.
 - [SQLAlchemy](http://www.sqlalchemy.org/) as the backend database connector for storage and related operations.
 
-Apart from this, there are also various Python packages that Hydrus uses. A list of all these packages can be found in the [requirements.txt](https://github.com/HTTP-APIs/hydrus/blob/master/requirements.txt) file. It would be advisable to run **`pip install -r requirements.txt`** before setting up other things.
+Apart from this, there are also various Python packages that Hydrus uses. Using `python setup.py install` installs all the required dependencies.
 
 **NOTE:** You'll need to use `python3` not `python2`.
 
@@ -47,16 +47,24 @@ cd hydrus
 git checkout -b develop origin/develop
 ```
 
-Install requirements and run the `main.py` script:
+Install hydrus using:
 ```bash
-pip install -r requirements.txt
+pip install .
+```
+or
+```bash
+python setup.py install
+```
 
-python main.py
+and run the server using:
+
+```bash
+hydrus serve
 ```
 
-The demo should be up and running on `http://localhost:8080/serverapi/`
+The demo should be up and running on `http://localhost:8080/serverapi/`.
 
 <a name="usage"></a>
 Usage
 -------------
-For more info, head to the [Usage](https://github.com/HTTP-APIs/hydrus/wiki/Usage) section of the [wiki](https://github.com/HTTP-APIs/hydrus/wiki/)
+For more info, head to the [Usage](https://github.com/HTTP-APIs/hydrus/wiki/Usage) section of the [wiki](https://github.com/HTTP-APIs/hydrus/wiki/).
diff --git a/cli.py b/cli.py
new file mode 100644
index 0000000..648637d
--- /dev/null
+++ b/cli.py
@@ -0,0 +1,126 @@
+from sqlalchemy import create_engine
+from sqlalchemy.orm import sessionmaker, scoped_session
+
+from hydrus.app import app_factory
+from hydrus.utils import (set_session, set_doc, set_hydrus_server_url,
+                            set_token, set_api_name, set_authentication)
+from hydrus.data import doc_parse
+from hydrus.hydraspec import doc_maker
+from hydrus.data.db_models import Base
+from hydrus.data.user import add_user
+from gevent.wsgi import WSGIServer
+from typing import Tuple
+import json
+import click
+
+@click.command()
+@click.option("--adduser", "-u", default=tuple([1, "test"]),
+                help="Adds a new user to the API.", nargs=2, type=(int, str))
+@click.option("--api", "-a", default="serverapi",
+                help="The API name.", type=str)
+@click.option("--auth/--no-auth", default=True,
+                help="Set authentication to True or False.")
+@click.option("--dburl", default="sqlite:///:memory:",
+                help="Set database url", type=str)
+@click.option("--hydradoc", "-d", default="doc.jsonld",
+                help="Location to HydraDocumentation (JSON-LD) of server.",
+                type=click.File('r'))
+@click.option("--port", "-p", default=8080,
+                help="The port the app is hosted at.", type=int)
+@click.option("--token/--no-token", default=True,
+                help="Toggle token based user authentication.")
+@click.option("--serverurl", default= "http://localhost",
+                help="Set server url", type=str)
+@click.argument("serve", required=True)
+def startserver(adduser: Tuple, api: str, auth: bool, dburl: str,
+                hydradoc: str, port: int, serverurl: str, token: bool,
+                serve: None) -> None:
+    """
+    Python Hydrus CLI
+
+    :param adduser <tuple>  : Contains the user credentials.
+    :param api <str>                    : Sets the API name for the server.
+    :param auth <bool>                  : Toggles the authentication.
+    :param dburl <str>                  : Sets the database URL.
+    :param hydradoc <str>               : Sets the link to the HydraDoc file.
+    :param port <int>                   : Sets the API server port.
+    :param serverurl <str>              : Sets the API server url.
+    :param token <bool>                 : Toggle token based user auth.
+    :param serve                        : Starts up the server.
+
+    :return                             : None.
+    """
+    # The database connection URL
+    # See http://docs.sqlalchemy.org/en/rel_1_0/core/engines.html#sqlalchemy.create_engine for more info
+    # DB_URL = 'sqlite:///database.db'
+    DB_URL = dburl
+
+    # Define the server URL, this is what will be displayed on the Doc
+    HYDRUS_SERVER_URL = "{}:{}/".format(serverurl, str(port))
+
+    # The name of the API or the EntryPoint, the api will be at http://localhost/<API_NAME>
+    API_NAME = api
+
+    click.echo("Setting up the database")
+    # Create a connection to the database you want to use
+    engine = create_engine(DB_URL)
+
+    click.echo("Creating models")
+    # Add the required Models to the database
+    Base.metadata.create_all(engine)
+
+    # Define the Hydra API Documentation
+    # NOTE: You can use your own API Documentation and create a HydraDoc object using doc_maker
+    #       Or you may create your own HydraDoc Documentation using doc_writer [see hydrus/hydraspec/doc_writer_sample]
+    click.echo("Creating the API Documentation")
+    apidoc = doc_maker.create_doc(json.loads(hydradoc.read()),
+                                    HYDRUS_SERVER_URL, API_NAME)
+
+    # Start a session with the DB and create all classes needed by the APIDoc
+    session = scoped_session(sessionmaker(bind=engine))
+
+    click.echo("Adding Classes and Properties")
+    # Get all the classes from the doc
+    classes = doc_parse.get_classes(apidoc.generate())     # You can also pass dictionary defined in hydrus/hydraspec/doc_writer_sample_output.py
+
+    # Get all the properties from the classes
+    properties = doc_parse.get_all_properties(classes)
+
+    # Insert them into the database
+    doc_parse.insert_classes(classes, session)
+    doc_parse.insert_properties(properties, session)
+
+    click.echo("Adding authorized users")
+    add_user(id_=adduser[0], paraphrase=adduser[1], session=session)
+
+    # Insert them into the database
+    doc_parse.insert_classes(classes, session)
+    doc_parse.insert_properties(properties, session)
+
+    click.echo("Creating the application")
+    # Create a Hydrus app with the API name you want, default will be "api"
+    app = app_factory(API_NAME)
+    # Set the name of the API
+    click.echo("Starting the application")
+    with set_authentication(app, auth):
+        # Use authentication for all requests
+        with set_token(app, token):
+            with set_api_name(app, api):
+                # Set the API Documentation
+                with set_doc(app, apidoc):
+                    # Set HYDRUS_SERVER_URL
+                    with set_hydrus_server_url(app, HYDRUS_SERVER_URL):
+                        # Set the Database session
+                        with set_session(app, session):
+                            # Start the Hydrus app
+                            http_server = WSGIServer(('', port), app)
+                            click.echo("Server running at:")
+                            click.echo(HYDRUS_SERVER_URL + API_NAME)
+                            try:
+                                http_server.serve_forever()
+                            except KeyboardInterrupt:
+                                pass
+
+
+if __name__ == "__main__":
+    startserver()
diff --git a/doc.jsonld b/doc.jsonld
new file mode 100644
index 0000000..1daac63
--- /dev/null
+++ b/doc.jsonld
@@ -0,0 +1,1059 @@
+{
+    "@context": {
+        "ApiDocumentation": "hydra:ApiDocumentation",
+        "description": "hydra:description",
+        "domain": {
+            "@id": "rdfs:domain",
+            "@type": "@id"
+        },
+        "expects": {
+            "@id": "hydra:expects",
+            "@type": "@id"
+        },
+        "hydra": "http://www.w3.org/ns/hydra/core#",
+        "label": "rdfs:label",
+        "method": "hydra:method",
+        "possibleStatus": "hydra:possibleStatus",
+        "property": {
+            "@id": "hydra:property",
+            "@type": "@id"
+        },
+        "range": {
+            "@id": "rdfs:range",
+            "@type": "@id"
+        },
+        "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
+        "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
+        "readonly": "hydra:readonly",
+        "required": "hydra:required",
+        "returns": {
+            "@id": "hydra:returns",
+            "@type": "@id"
+        },
+        "statusCode": "hydra:statusCode",
+        "statusCodes": "hydra:statusCodes",
+        "subClassOf": {
+            "@id": "rdfs:subClassOf",
+            "@type": "@id"
+        },
+        "supportedClass": "hydra:supportedClass",
+        "supportedOperation": "hydra:supportedOperation",
+        "supportedProperty": "hydra:supportedProperty",
+        "title": "hydra:title",
+        "vocab": "http://localhost:8080/api/vocab#",
+        "writeonly": "hydra:writeonly"
+    },
+    "@id": "http://localhost:8080/api/vocab",
+    "@type": "ApiDocumentation",
+    "description": "API Documentation for the server side system",
+    "possibleStatus": [],
+    "supportedClass": [
+        {
+            "@id": "vocab:Datastream",
+            "@type": "hydra:Class",
+            "description": "Class for a datastream entry",
+            "supportedOperation": [
+                {
+                    "@type": "hydra:Operation",
+                    "expects": "null",
+                    "method": "GET",
+                    "possibleStatus": [
+                        {
+                            "description": "Data not found",
+                            "statusCode": 404
+                        },
+                        {
+                            "description": "Data returned",
+                            "statusCode": 200
+                        }
+                    ],
+                    "returns": "vocab:Datastream",
+                    "title": "ReadDatastream"
+                },
+                {
+                    "@type": "http://schema.org/UpdateAction",
+                    "expects": "vocab:Datastream",
+                    "method": "POST",
+                    "possibleStatus": [
+                        {
+                            "description": "Data updated",
+                            "statusCode": 200
+                        }
+                    ],
+                    "returns": "null",
+                    "title": "UpdateDatastream"
+                },
+                {
+                    "@type": "http://schema.org/DeleteAction",
+                    "expects": "null",
+                    "method": "DELETE",
+                    "possibleStatus": [
+                        {
+                            "description": "Data deleted",
+                            "statusCode": 200
+                        }
+                    ],
+                    "returns": "null",
+                    "title": "DeleteDatastream"
+                }
+            ],
+            "supportedProperty": [
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://schema.org/QuantitativeValue",
+                    "readonly": "false",
+                    "required": "true",
+                    "title": "Temperature",
+                    "writeonly": "false"
+                },
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://schema.org/identifier",
+                    "readonly": "false",
+                    "required": "true",
+                    "title": "DroneID",
+                    "writeonly": "false"
+                },
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://schema.org/geo",
+                    "readonly": "false",
+                    "required": "true",
+                    "title": "Position",
+                    "writeonly": "false"
+                }
+            ],
+            "title": "Datastream"
+        },
+        {
+            "@id": "vocab:Area",
+            "@type": "hydra:Class",
+            "description": "Class for Area of Interest of the server",
+            "supportedOperation": [
+                {
+                    "@type": "http://schema.org/UpdateAction",
+                    "expects": "vocab:Area",
+                    "method": "POST",
+                    "possibleStatus": [
+                        {
+                            "description": "Area of interest changed",
+                            "statusCode": 200
+                        }
+                    ],
+                    "returns": "null",
+                    "title": "UpdateArea"
+                },
+                {
+                    "@type": "hydra:Operation",
+                    "expects": "null",
+                    "method": "GET",
+                    "possibleStatus": [
+                        {
+                            "description": "Area of interest not found",
+                            "statusCode": 404
+                        },
+                        {
+                            "description": "Area of interest returned",
+                            "statusCode": 200
+                        }
+                    ],
+                    "returns": "vocab:Area",
+                    "title": "GetArea"
+                }
+            ],
+            "supportedProperty": [
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://schema.org/geo",
+                    "readonly": "false",
+                    "required": "true",
+                    "title": "TopLeft",
+                    "writeonly": "false"
+                },
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://schema.org/geo",
+                    "readonly": "false",
+                    "required": "true",
+                    "title": "BottomRight",
+                    "writeonly": "false"
+                }
+            ],
+            "title": "Area"
+        },
+        {
+            "@id": "vocab:State",
+            "@type": "hydra:Class",
+            "description": "Class for drone state objects",
+            "supportedOperation": [],
+            "supportedProperty": [
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://auto.schema.org/speed",
+                    "readonly": "false",
+                    "required": "true",
+                    "title": "Speed",
+                    "writeonly": "false"
+                },
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://schema.org/geo",
+                    "readonly": "false",
+                    "required": "true",
+                    "title": "Position",
+                    "writeonly": "false"
+                },
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://schema.org/Property",
+                    "readonly": "false",
+                    "required": "true",
+                    "title": "Direction",
+                    "writeonly": "false"
+                },
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://schema.org/fuelCapacity",
+                    "readonly": "false",
+                    "required": "true",
+                    "title": "Battery",
+                    "writeonly": "false"
+                },
+                {
+                    "@type": "SupportedProperty",
+                    "property": "https://schema.org/status",
+                    "readonly": "false",
+                    "required": "true",
+                    "title": "SensorStatus",
+                    "writeonly": "false"
+                },
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://schema.org/identifier",
+                    "readonly": "false",
+                    "required": "true",
+                    "title": "DroneID",
+                    "writeonly": "false"
+                }
+            ],
+            "title": "State"
+        },
+        {
+            "@id": "vocab:Drone",
+            "@type": "hydra:Class",
+            "description": "Class for a drone",
+            "supportedOperation": [
+                {
+                    "@type": "http://schema.org/UpdateAction",
+                    "expects": "vocab:Drone",
+                    "method": "POST",
+                    "possibleStatus": [
+                        {
+                            "description": "Drone updated",
+                            "statusCode": 200
+                        }
+                    ],
+                    "returns": "null",
+                    "title": "SubmitDrone"
+                },
+                {
+                    "@type": "http://schema.org/AddAction",
+                    "expects": "vocab:Drone",
+                    "method": "PUT",
+                    "possibleStatus": [
+                        {
+                            "description": "Drone added",
+                            "statusCode": 200
+                        }
+                    ],
+                    "returns": "null",
+                    "title": "CreateDrone"
+                },
+                {
+                    "@type": "hydra:Operation",
+                    "expects": "null",
+                    "method": "GET",
+                    "possibleStatus": [
+                        {
+                            "description": "Drone not found",
+                            "statusCode": 404
+                        },
+                        {
+                            "description": "Drone Returned",
+                            "statusCode": 200
+                        }
+                    ],
+                    "returns": "vocab:Drone",
+                    "title": "GetDrone"
+                }
+            ],
+            "supportedProperty": [
+                {
+                    "@type": "SupportedProperty",
+                    "property": "vocab:State",
+                    "readonly": "false",
+                    "required": "true",
+                    "title": "DroneState",
+                    "writeonly": "false"
+                },
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://schema.org/name",
+                    "readonly": "false",
+                    "required": "true",
+                    "title": "name",
+                    "writeonly": "false"
+                },
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://schema.org/model",
+                    "readonly": "false",
+                    "required": "true",
+                    "title": "model",
+                    "writeonly": "false"
+                },
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://auto.schema.org/speed",
+                    "readonly": "false",
+                    "required": "true",
+                    "title": "MaxSpeed",
+                    "writeonly": "false"
+                },
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://schema.org/device",
+                    "readonly": "false",
+                    "required": "true",
+                    "title": "Sensor",
+                    "writeonly": "false"
+                }
+            ],
+            "title": "Drone"
+        },
+        {
+            "@id": "vocab:Command",
+            "@type": "hydra:Class",
+            "description": "Class for drone commands",
+            "supportedOperation": [
+                {
+                    "@type": "hydra:Operation",
+                    "expects": "null",
+                    "method": "GET",
+                    "possibleStatus": [
+                        {
+                            "description": "Command not found",
+                            "statusCode": 404
+                        },
+                        {
+                            "description": "Command Returned",
+                            "statusCode": 200
+                        }
+                    ],
+                    "returns": "vocab:Command",
+                    "title": "GetCommand"
+                },
+                {
+                    "@type": "http://schema.org/AddAction",
+                    "expects": "vocab:Command",
+                    "method": "PUT",
+                    "possibleStatus": [
+                        {
+                            "description": "Command added",
+                            "statusCode": 201
+                        }
+                    ],
+                    "returns": "null",
+                    "title": "AddCommand"
+                },
+                {
+                    "@type": "http://schema.org/DeleteAction",
+                    "expects": "null",
+                    "method": "DELETE",
+                    "possibleStatus": [
+                        {
+                            "description": "Command deleted",
+                            "statusCode": 201
+                        }
+                    ],
+                    "returns": "null",
+                    "title": "DeleteCommand"
+                }
+            ],
+            "supportedProperty": [
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://schema.org/identifier",
+                    "readonly": "false",
+                    "required": "true",
+                    "title": "DroneID",
+                    "writeonly": "false"
+                },
+                {
+                    "@type": "SupportedProperty",
+                    "property": "vocab:State",
+                    "readonly": "false",
+                    "required": "true",
+                    "title": "State",
+                    "writeonly": "false"
+                }
+            ],
+            "title": "Command"
+        },
+        {
+            "@id": "vocab:LogEntry",
+            "@type": "hydra:Class",
+            "description": "Class for a log entry",
+            "supportedOperation": [
+                {
+                    "@type": "hydra:Operation",
+                    "expects": "null",
+                    "method": "GET",
+                    "possibleStatus": [
+                        {
+                            "description": "Log entry not found",
+                            "statusCode": 404
+                        },
+                        {
+                            "description": "Log entry returned",
+                            "statusCode": 200
+                        }
+                    ],
+                    "returns": "vocab:LogEntry",
+                    "title": "GetLog"
+                },
+                {
+                    "@type": "http://schema.org/AddAction",
+                    "expects": "vocab:LogEntry",
+                    "method": "PUT",
+                    "possibleStatus": [
+                        {
+                            "description": "Log entry created",
+                            "statusCode": 201
+                        }
+                    ],
+                    "returns": "null",
+                    "title": "AddLog"
+                }
+            ],
+            "supportedProperty": [
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://schema.org/identifier",
+                    "readonly": "true",
+                    "required": "false",
+                    "title": "DroneID",
+                    "writeonly": "true"
+                },
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://schema.org/UpdateAction",
+                    "readonly": "false",
+                    "required": "false",
+                    "title": "Update",
+                    "writeonly": "true"
+                },
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://schema.org/ReplyAction",
+                    "readonly": "false",
+                    "required": "false",
+                    "title": "Get",
+                    "writeonly": "true"
+                },
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://schema.org/SendAction",
+                    "readonly": "false",
+                    "required": "false",
+                    "title": "Send",
+                    "writeonly": "true"
+                },
+                {
+                    "@type": "SupportedProperty",
+                    "property": "vocab:State",
+                    "readonly": "false",
+                    "required": "false",
+                    "title": "State",
+                    "writeonly": "true"
+                },
+                {
+                    "@type": "SupportedProperty",
+                    "property": "vocab:Datastream",
+                    "readonly": "false",
+                    "required": "false",
+                    "title": "Data",
+                    "writeonly": "true"
+                },
+                {
+                    "@type": "SupportedProperty",
+                    "property": "vocab:Command",
+                    "readonly": "false",
+                    "required": "false",
+                    "title": "Command",
+                    "writeonly": "true"
+                }
+            ],
+            "title": "LogEntry"
+        },
+        {
+            "@id": "vocab:Message",
+            "@type": "hydra:Class",
+            "description": "Class for messages received by the GUI interface",
+            "supportedOperation": [
+                {
+                    "@type": "hydra:Operation",
+                    "expects": "null",
+                    "method": "GET",
+                    "possibleStatus": [
+                        {
+                            "description": "Message not found",
+                            "statusCode": 404
+                        },
+                        {
+                            "description": "Message returned",
+                            "statusCode": 200
+                        }
+                    ],
+                    "returns": "vocab:Message",
+                    "title": "GetMessage"
+                },
+                {
+                    "@type": "http://schema.org/DeleteAction",
+                    "expects": "null",
+                    "method": "DELETE",
+                    "possibleStatus": [
+                        {
+                            "description": "Message deleted",
+                            "statusCode": 200
+                        }
+                    ],
+                    "returns": "null",
+                    "title": "DeleteMessage"
+                }
+            ],
+            "supportedProperty": [
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://schema.org/Text",
+                    "readonly": "false",
+                    "required": "true",
+                    "title": "MessageString",
+                    "writeonly": "false"
+                }
+            ],
+            "title": "Message"
+        },
+        {
+            "@id": "http://www.w3.org/ns/hydra/core#Resource",
+            "@type": "hydra:Class",
+            "description": "null",
+            "supportedOperation": [],
+            "supportedProperty": [],
+            "title": "Resource"
+        },
+        {
+            "@id": "http://www.w3.org/ns/hydra/core#Collection",
+            "@type": "hydra:Class",
+            "description": "null",
+            "supportedOperation": [],
+            "supportedProperty": [
+                {
+                    "@type": "SupportedProperty",
+                    "property": "http://www.w3.org/ns/hydra/core#member",
+                    "readonly": "false",
+                    "required": "null",
+                    "title": "members",
+                    "writeonly": "false"
+                }
+            ],
+            "title": "Collection"
+        },
+        {
+            "@id": "vocab:DatastreamCollection",
+            "@type": "hydra:Class",
+            "description": "A collection of datastream",
+            "subClassOf": "http://www.w3.org/ns/hydra/core#Collection",
+            "supportedOperation": [
+                {
+                    "@id": "_:datastream_collection_retrieve",
+                    "@type": "hydra:Operation",
+                    "description": "Retrieves all Datastream entities",
+                    "expects": "null",
+                    "method": "GET",
+                    "returns": "vocab:DatastreamCollection",
+                    "statusCodes": []
+                },
+                {
+                    "@id": "_:datastream_create",
+                    "@type": "http://schema.org/AddAction",
+                    "description": "Create new Datastream entitity",
+                    "expects": "vocab:Datastream",
+                    "method": "PUT",
+                    "returns": "vocab:Datastream",
+                    "statusCodes": [
+                        {
+                            "description": "If the Datastream entity was created successfully.",
+                            "statusCode": 201
+                        }
+                    ]
+                }
+            ],
+            "supportedProperty": [
+                {
+                    "@type": "SupportedProperty",
+                    "description": "The datastream",
+                    "property": "http://www.w3.org/ns/hydra/core#member",
+                    "readonly": "false",
+                    "required": "false",
+                    "title": "members",
+                    "writeonly": "false"
+                }
+            ],
+            "title": "DatastreamCollection"
+        },
+        {
+            "@id": "vocab:DroneCollection",
+            "@type": "hydra:Class",
+            "description": "A collection of drone",
+            "subClassOf": "http://www.w3.org/ns/hydra/core#Collection",
+            "supportedOperation": [
+                {
+                    "@id": "_:drone_collection_retrieve",
+                    "@type": "hydra:Operation",
+                    "description": "Retrieves all Drone entities",
+                    "expects": "null",
+                    "method": "GET",
+                    "returns": "vocab:DroneCollection",
+                    "statusCodes": []
+                },
+                {
+                    "@id": "_:drone_create",
+                    "@type": "http://schema.org/AddAction",
+                    "description": "Create new Drone entitity",
+                    "expects": "vocab:Drone",
+                    "method": "PUT",
+                    "returns": "vocab:Drone",
+                    "statusCodes": [
+                        {
+                            "description": "If the Drone entity was created successfully.",
+                            "statusCode": 201
+                        }
+                    ]
+                }
+            ],
+            "supportedProperty": [
+                {
+                    "@type": "SupportedProperty",
+                    "description": "The drone",
+                    "property": "http://www.w3.org/ns/hydra/core#member",
+                    "readonly": "false",
+                    "required": "false",
+                    "title": "members",
+                    "writeonly": "false"
+                }
+            ],
+            "title": "DroneCollection"
+        },
+        {
+            "@id": "vocab:MessageCollection",
+            "@type": "hydra:Class",
+            "description": "A collection of message",
+            "subClassOf": "http://www.w3.org/ns/hydra/core#Collection",
+            "supportedOperation": [
+                {
+                    "@id": "_:message_collection_retrieve",
+                    "@type": "hydra:Operation",
+                    "description": "Retrieves all Message entities",
+                    "expects": "null",
+                    "method": "GET",
+                    "returns": "vocab:MessageCollection",
+                    "statusCodes": []
+                },
+                {
+                    "@id": "_:message_create",
+                    "@type": "http://schema.org/AddAction",
+                    "description": "Create new Message entitity",
+                    "expects": "vocab:Message",
+                    "method": "PUT",
+                    "returns": "vocab:Message",
+                    "statusCodes": [
+                        {
+                            "description": "If the Message entity was created successfully.",
+                            "statusCode": 201
+                        }
+                    ]
+                }
+            ],
+            "supportedProperty": [
+                {
+                    "@type": "SupportedProperty",
+                    "description": "The message",
+                    "property": "http://www.w3.org/ns/hydra/core#member",
+                    "readonly": "false",
+                    "required": "false",
+                    "title": "members",
+                    "writeonly": "false"
+                }
+            ],
+            "title": "MessageCollection"
+        },
+        {
+            "@id": "vocab:LogEntryCollection",
+            "@type": "hydra:Class",
+            "description": "A collection of logentry",
+            "subClassOf": "http://www.w3.org/ns/hydra/core#Collection",
+            "supportedOperation": [
+                {
+                    "@id": "_:logentry_collection_retrieve",
+                    "@type": "hydra:Operation",
+                    "description": "Retrieves all LogEntry entities",
+                    "expects": "null",
+                    "method": "GET",
+                    "returns": "vocab:LogEntryCollection",
+                    "statusCodes": []
+                },
+                {
+                    "@id": "_:logentry_create",
+                    "@type": "http://schema.org/AddAction",
+                    "description": "Create new LogEntry entitity",
+                    "expects": "vocab:LogEntry",
+                    "method": "PUT",
+                    "returns": "vocab:LogEntry",
+                    "statusCodes": [
+                        {
+                            "description": "If the LogEntry entity was created successfully.",
+                            "statusCode": 201
+                        }
+                    ]
+                }
+            ],
+            "supportedProperty": [
+                {
+                    "@type": "SupportedProperty",
+                    "description": "The logentry",
+                    "property": "http://www.w3.org/ns/hydra/core#member",
+                    "readonly": "false",
+                    "required": "false",
+                    "title": "members",
+                    "writeonly": "false"
+                }
+            ],
+            "title": "LogEntryCollection"
+        },
+        {
+            "@id": "vocab:CommandCollection",
+            "@type": "hydra:Class",
+            "description": "A collection of command",
+            "subClassOf": "http://www.w3.org/ns/hydra/core#Collection",
+            "supportedOperation": [
+                {
+                    "@id": "_:command_collection_retrieve",
+                    "@type": "hydra:Operation",
+                    "description": "Retrieves all Command entities",
+                    "expects": "null",
+                    "method": "GET",
+                    "returns": "vocab:CommandCollection",
+                    "statusCodes": []
+                },
+                {
+                    "@id": "_:command_create",
+                    "@type": "http://schema.org/AddAction",
+                    "description": "Create new Command entitity",
+                    "expects": "vocab:Command",
+                    "method": "PUT",
+                    "returns": "vocab:Command",
+                    "statusCodes": [
+                        {
+                            "description": "If the Command entity was created successfully.",
+                            "statusCode": 201
+                        }
+                    ]
+                }
+            ],
+            "supportedProperty": [
+                {
+                    "@type": "SupportedProperty",
+                    "description": "The command",
+                    "property": "http://www.w3.org/ns/hydra/core#member",
+                    "readonly": "false",
+                    "required": "false",
+                    "title": "members",
+                    "writeonly": "false"
+                }
+            ],
+            "title": "CommandCollection"
+        },
+        {
+            "@id": "vocab:EntryPoint",
+            "@type": "hydra:Class",
+            "description": "The main entry point or homepage of the API.",
+            "supportedOperation": [
+                {
+                    "@id": "_:entry_point",
+                    "@type": "hydra:Operation",
+                    "description": "The APIs main entry point.",
+                    "expects": "null",
+                    "method": "GET",
+                    "returns": "null",
+                    "statusCodes": "vocab:EntryPoint"
+                }
+            ],
+            "supportedProperty": [
+                {
+                    "hydra:description": "The Area Class",
+                    "hydra:title": "area",
+                    "property": {
+                        "@id": "vocab:EntryPoint/Area",
+                        "@type": "hydra:Link",
+                        "description": "Class for Area of Interest of the server",
+                        "domain": "vocab:EntryPoint",
+                        "label": "Area",
+                        "range": "vocab:Area",
+                        "supportedOperation": [
+                            {
+                                "@id": "_:updatearea",
+                                "@type": "hydra:Operation",
+                                "description": "null",
+                                "expects": "vocab:Area",
+                                "label": "UpdateArea",
+                                "method": "POST",
+                                "returns": "null",
+                                "statusCodes": [
+                                    {
+                                        "description": "Area of interest changed",
+                                        "statusCode": 200
+                                    }
+                                ]
+                            },
+                            {
+                                "@id": "_:getarea",
+                                "@type": "hydra:Operation",
+                                "description": "null",
+                                "expects": "null",
+                                "label": "GetArea",
+                                "method": "GET",
+                                "returns": "vocab:Area",
+                                "statusCodes": [
+                                    {
+                                        "description": "Area of interest not found",
+                                        "statusCode": 404
+                                    },
+                                    {
+                                        "description": "Area of interest returned",
+                                        "statusCode": 200
+                                    }
+                                ]
+                            }
+                        ]
+                    },
+                    "readonly": "true",
+                    "required": "null",
+                    "writeonly": "false"
+                },
+                {
+                    "hydra:description": "The DatastreamCollection collection",
+                    "hydra:title": "datastreamcollection",
+                    "property": {
+                        "@id": "vocab:EntryPoint/DatastreamCollection",
+                        "@type": "hydra:Link",
+                        "description": "The DatastreamCollection collection",
+                        "domain": "vocab:EntryPoint",
+                        "label": "DatastreamCollection",
+                        "range": "vocab:DatastreamCollection",
+                        "supportedOperation": [
+                            {
+                                "@id": "_:_:datastream_collection_retrieve",
+                                "@type": "hydra:Operation",
+                                "description": "Retrieves all Datastream entities",
+                                "expects": "null",
+                                "method": "GET",
+                                "returns": "vocab:DatastreamCollection",
+                                "statusCodes": []
+                            },
+                            {
+                                "@id": "_:_:datastream_create",
+                                "@type": "http://schema.org/AddAction",
+                                "description": "Create new Datastream entitity",
+                                "expects": "vocab:Datastream",
+                                "method": "PUT",
+                                "returns": "vocab:Datastream",
+                                "statusCodes": [
+                                    {
+                                        "description": "If the Datastream entity was created successfully.",
+                                        "statusCode": 201
+                                    }
+                                ]
+                            }
+                        ]
+                    },
+                    "readonly": "true",
+                    "required": "null",
+                    "writeonly": "false"
+                },
+                {
+                    "hydra:description": "The DroneCollection collection",
+                    "hydra:title": "dronecollection",
+                    "property": {
+                        "@id": "vocab:EntryPoint/DroneCollection",
+                        "@type": "hydra:Link",
+                        "description": "The DroneCollection collection",
+                        "domain": "vocab:EntryPoint",
+                        "label": "DroneCollection",
+                        "range": "vocab:DroneCollection",
+                        "supportedOperation": [
+                            {
+                                "@id": "_:_:drone_collection_retrieve",
+                                "@type": "hydra:Operation",
+                                "description": "Retrieves all Drone entities",
+                                "expects": "null",
+                                "method": "GET",
+                                "returns": "vocab:DroneCollection",
+                                "statusCodes": []
+                            },
+                            {
+                                "@id": "_:_:drone_create",
+                                "@type": "http://schema.org/AddAction",
+                                "description": "Create new Drone entitity",
+                                "expects": "vocab:Drone",
+                                "method": "PUT",
+                                "returns": "vocab:Drone",
+                                "statusCodes": [
+                                    {
+                                        "description": "If the Drone entity was created successfully.",
+                                        "statusCode": 201
+                                    }
+                                ]
+                            }
+                        ]
+                    },
+                    "readonly": "true",
+                    "required": "null",
+                    "writeonly": "false"
+                },
+                {
+                    "hydra:description": "The MessageCollection collection",
+                    "hydra:title": "messagecollection",
+                    "property": {
+                        "@id": "vocab:EntryPoint/MessageCollection",
+                        "@type": "hydra:Link",
+                        "description": "The MessageCollection collection",
+                        "domain": "vocab:EntryPoint",
+                        "label": "MessageCollection",
+                        "range": "vocab:MessageCollection",
+                        "supportedOperation": [
+                            {
+                                "@id": "_:_:message_collection_retrieve",
+                                "@type": "hydra:Operation",
+                                "description": "Retrieves all Message entities",
+                                "expects": "null",
+                                "method": "GET",
+                                "returns": "vocab:MessageCollection",
+                                "statusCodes": []
+                            },
+                            {
+                                "@id": "_:_:message_create",
+                                "@type": "http://schema.org/AddAction",
+                                "description": "Create new Message entitity",
+                                "expects": "vocab:Message",
+                                "method": "PUT",
+                                "returns": "vocab:Message",
+                                "statusCodes": [
+                                    {
+                                        "description": "If the Message entity was created successfully.",
+                                        "statusCode": 201
+                                    }
+                                ]
+                            }
+                        ]
+                    },
+                    "readonly": "true",
+                    "required": "null",
+                    "writeonly": "false"
+                },
+                {
+                    "hydra:description": "The LogEntryCollection collection",
+                    "hydra:title": "logentrycollection",
+                    "property": {
+                        "@id": "vocab:EntryPoint/LogEntryCollection",
+                        "@type": "hydra:Link",
+                        "description": "The LogEntryCollection collection",
+                        "domain": "vocab:EntryPoint",
+                        "label": "LogEntryCollection",
+                        "range": "vocab:LogEntryCollection",
+                        "supportedOperation": [
+                            {
+                                "@id": "_:_:logentry_collection_retrieve",
+                                "@type": "hydra:Operation",
+                                "description": "Retrieves all LogEntry entities",
+                                "expects": "null",
+                                "method": "GET",
+                                "returns": "vocab:LogEntryCollection",
+                                "statusCodes": []
+                            },
+                            {
+                                "@id": "_:_:logentry_create",
+                                "@type": "http://schema.org/AddAction",
+                                "description": "Create new LogEntry entitity",
+                                "expects": "vocab:LogEntry",
+                                "method": "PUT",
+                                "returns": "vocab:LogEntry",
+                                "statusCodes": [
+                                    {
+                                        "description": "If the LogEntry entity was created successfully.",
+                                        "statusCode": 201
+                                    }
+                                ]
+                            }
+                        ]
+                    },
+                    "readonly": "true",
+                    "required": "null",
+                    "writeonly": "false"
+                },
+                {
+                    "hydra:description": "The CommandCollection collection",
+                    "hydra:title": "commandcollection",
+                    "property": {
+                        "@id": "vocab:EntryPoint/CommandCollection",
+                        "@type": "hydra:Link",
+                        "description": "The CommandCollection collection",
+                        "domain": "vocab:EntryPoint",
+                        "label": "CommandCollection",
+                        "range": "vocab:CommandCollection",
+                        "supportedOperation": [
+                            {
+                                "@id": "_:_:command_collection_retrieve",
+                                "@type": "hydra:Operation",
+                                "description": "Retrieves all Command entities",
+                                "expects": "null",
+                                "method": "GET",
+                                "returns": "vocab:CommandCollection",
+                                "statusCodes": []
+                            },
+                            {
+                                "@id": "_:_:command_create",
+                                "@type": "http://schema.org/AddAction",
+                                "description": "Create new Command entitity",
+                                "expects": "vocab:Command",
+                                "method": "PUT",
+                                "returns": "vocab:Command",
+                                "statusCodes": [
+                                    {
+                                        "description": "If the Command entity was created successfully.",
+                                        "statusCode": 201
+                                    }
+                                ]
+                            }
+                        ]
+                    },
+                    "readonly": "true",
+                    "required": "null",
+                    "writeonly": "false"
+                }
+            ],
+            "title": "EntryPoint"
+        }
+    ],
+    "title": "API Doc for the server side API"
+}
diff --git a/examples/drones/doc_gen.py b/examples/drones/doc_gen.py
index b378d51..b1bbf0c 100644
--- a/examples/drones/doc_gen.py
+++ b/examples/drones/doc_gen.py
@@ -3,8 +3,7 @@
 from hydrus.hydraspec.doc_writer import HydraDoc, HydraClass, HydraClassProp, HydraClassOp
 import json
 
-
-def doc_gen(API, BASE_URL):
+def doc_gen(API: str, BASE_URL: str) -> HydraDoc:
     """Generate API Doc for server."""
     # Main API Doc
     api_doc = HydraDoc(API,
@@ -176,4 +175,4 @@ if __name__ == "__main__":
     doc = doc.replace('null', '"null"')
     f = open("doc.py", "w")
     f.write(doc)
-    f.close()
+    f.close()
\ No newline at end of file
diff --git a/main.py b/examples/hydrus-demo-server/demo.py
similarity index 69%
rename from main.py
rename to examples/hydrus-demo-server/demo.py
index 149a344..13af2a8 100644
--- a/main.py
+++ b/examples/hydrus-demo-server/demo.py
@@ -1,10 +1,10 @@
 """Demo script for setting up Hydrus with any db and any API Doc."""
 
 from sqlalchemy import create_engine
-from sqlalchemy.orm import sessionmaker
+from sqlalchemy.orm import sessionmaker, scoped_session
 
 from hydrus.app import app_factory
-from hydrus.utils import set_session, set_doc, set_hydrus_server_url, set_api_name, set_authentication
+from hydrus.utils import set_session, set_doc, set_hydrus_server_url, set_api_name, set_authentication, set_token
 from hydrus.data import doc_parse
 from hydrus.hydraspec import doc_maker
 from hydrus.data.db_models import Base
@@ -37,10 +37,10 @@ if __name__ == "__main__":
     # NOTE: You can use your own API Documentation and create a HydraDoc object using doc_maker
     #       Or you may create your own HydraDoc Documentation using doc_writer [see hydrus/hydraspec/doc_writer_sample]
     print("Creating the API Documentation")
-    apidoc = doc_maker.createDoc(doc, HYDRUS_SERVER_URL, API_NAME)
+    apidoc = doc_maker.create_doc(doc, HYDRUS_SERVER_URL, API_NAME)
 
     # Start a session with the DB and create all classes needed by the APIDoc
-    session = sessionmaker(bind=engine)()
+    session = scoped_session(sessionmaker(bind=engine))
 
     print("Adding Classes and Properties")
     # Get all the classes from the doc
@@ -49,10 +49,6 @@ if __name__ == "__main__":
     # Get all the properties from the classes
     properties = doc_parse.get_all_properties(classes)
 
-    # Insert them into the database
-    doc_parse.insert_classes(classes, session)
-    doc_parse.insert_properties(properties, session)
-
     print("Adding authorized users")
     add_user(id_=1, paraphrase="test", session=session)
 
@@ -67,17 +63,19 @@ if __name__ == "__main__":
     print("Starting the application")
     with set_authentication(app, True):
         # Use authentication for all requests
-        with set_api_name(app, "serverapi"):
-            # Set the API Documentation
-            with set_doc(app, apidoc):
-                # Set HYDRUS_SERVER_URL
-                with set_hydrus_server_url(app, HYDRUS_SERVER_URL):
-                    # Set the Database session
-                    with set_session(app, session):
-                        # Start the Hydrus app
-                        http_server = WSGIServer(('', 8080), app)
-                        print("Server running")
-                        try:
-                            http_server.serve_forever()
-                        except KeyboardInterrupt:
-                            pass
+        with set_token(app, True): 
+            with set_api_name(app, "serverapi"):
+                # Set the API Documentation
+                with set_doc(app, apidoc):
+                    # Set HYDRUS_SERVER_URL
+                    with set_hydrus_server_url(app, HYDRUS_SERVER_URL):
+                        # Set the Database session
+                        with set_session(app, session):
+                            # Start the Hydrus app
+                            http_server = WSGIServer(('', 8080), app)
+                            print("Server running at:")
+                            print(HYDRUS_SERVER_URL + API_NAME)
+                            try:
+                                http_server.serve_forever()
+                            except KeyboardInterrupt:
+                                pass
diff --git a/doc.py b/examples/hydrus-demo-server/doc.py
similarity index 100%
rename from doc.py
rename to examples/hydrus-demo-server/doc.py
diff --git a/hydrus/app.py b/hydrus/app.py
index 417623b..997c592 100644
--- a/hydrus/app.py
+++ b/hydrus/app.py
@@ -1,4 +1,29 @@
-"""Main route for the applciation."""
+"""Main route for the applciation.
+    ===============================
+    Imports :
+
+    flask.json.jsonify : Turns the JSON output into a Response object with the application/json mimetype
+    Ref- http://flask.pocoo.org/docs/0.12/api
+
+    flask.request : The request object used by default in Flask. Remembers the matched endpoint and view arguments.
+    Ref - http://flask.pocoo.org/docs/0.12/api
+
+    flask.abort : Raises an HTTPException for the given status code or WSGI application:
+    Ref - http://flask.pocoo.org/docs/0.12/api
+
+    flask_restful.Resource : Represents an abstract RESTful resource.
+    Ref - http://flask-restful.readthedocs.io/en/latest/api.html
+
+
+    hydrus.data.crud : Function/Class to perform basic CRUD operations for the server
+    hydrus.data.user.check_authorization : Funcion checks if the request object has the correct authorization
+    hydrus.utils.get_session : Gets the database session for the server
+    hydrus.utils.get_doc : Function which gets the server API documentation
+    hydrus.utils.get_api_name : Function which gets the server API name
+    hydrus.utils.get_hydrus_server_url : Function the gets the server URL
+    hydrus.utils.get_authentication : Function that checks whether API needs to be authenticated or not
+
+"""
 
 import json
 from flask import Flask, jsonify, request, abort
@@ -6,55 +31,87 @@ from flask_restful import Api, Resource
 from flask_cors import CORS
 
 from hydrus.data import crud
-from hydrus.data.user import check_authorization
-from hydrus.utils import get_session, get_doc, get_api_name, get_hydrus_server_url, get_authentication
+from hydrus.data.user import check_authorization, add_token, check_token, create_nonce
+from hydrus.data.exceptions import (ClassNotFound, InstanceExists, PropertyNotFound,
+                                    NotInstanceProperty, NotAbstractProperty,
+                                    InstanceNotFound)
+from hydrus.utils import get_session, get_doc, get_api_name, get_hydrus_server_url, get_authentication,get_token
+
+from flask.wrappers import Response
+from typing import Dict, List, Any, Union
 
-import pdb
 
+def validObject(object_: Dict[str, Any]) -> bool:
+    """
+        Check if the Dict passed in POST is of valid format or not.
+        (if there's an "@type" key in the dict)
 
-def validObject(object_):
-    """Check if the data passed in POST is of valid format or not."""
+        :param object_ - Object to be checked
+    """
     if "@type" in object_:
         return True
     return False
 
+def token_response(token: str) -> Response:
+    """
+    Return succesful token generation object
+    """
+    message = {200: "User token generated"}
+    response = set_response_headers(jsonify(message), status_code=200,
+                                    headers=[{'X-Authorization': token}])
+    return response
 
-def failed_authentication():
-    """Return failed authentication object."""
-    message = {401: "Need credentials to authenticate"}
+def failed_authentication(incorrect: bool) -> Response:
+    """
+    Return failed authentication object.
+    """
+    if not incorrect:
+        message = {401: "Need credentials to authenticate"}
+        realm = 'Basic realm="Login required"'
+    else:
+        message = {401: "Incorrect credentials"}
+        realm = 'Basic realm="Incorrect credentials"'        
+    nonce = create_nonce(get_session())
     response = set_response_headers(jsonify(message), status_code=401,
-                                    headers=[{'WWW-Authenticate': 'Basic realm="Login Required"'}])
+                                    headers=[{'WWW-Authenticate': realm},{'X-Authentication': nonce}])
     return response
 
 
-def set_response_headers(resp, ct="application/ld+json", headers=[], status_code=200):
+def set_response_headers(resp: Response, ct: str="application/ld+json", headers: List[Dict[str, Any]]=[], status_code: int=200) -> Response:
     """Set the response headers."""
     resp.status_code = status_code
     for header in headers:
         resp.headers[list(header.keys())[0]] = header[list(header.keys())[0]]
     resp.headers['Content-type'] = ct
     resp.headers['Link'] = '<' + get_hydrus_server_url() + \
-        get_api_name()+'/vocab>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"'
+        get_api_name() + '/vocab>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"'
     return resp
 
 
-def hydrafy(object_):
+def hydrafy(object_: Dict[str, Any]) -> Dict[str, Any]:
     """Add hydra context to objects."""
-    object_["@context"] = "/"+get_api_name()+"/contexts/" + object_["@type"] + ".jsonld"
+    object_["@context"] = "/" + get_api_name() + "/contexts/" + \
+        object_["@type"] + ".jsonld"
     return object_
 
 
-def checkEndpoint(method, type_):
+def checkEndpoint(method: str, type_: str) -> Dict[str, Union[bool, int]]:
     """Check if endpoint and method is supported in the API."""
+    status_val = 404
+    if type_ == 'vocab':
+        return {'method': False, 'status': 405}
+
     for endpoint in get_doc().entrypoint.entrypoint.supportedProperty:
         if type_ == endpoint.name:
+            status_val = 405
             for operation in endpoint.supportedOperation:
                 if operation.method == method:
-                    return True
-    return False
+                    status_val = 200
+                    return {'method': True, 'status': status_val}
+    return {'method': False, 'status': status_val}
 
 
-def getType(class_type, method):
+def getType(class_type: str, method: str) -> Any:
     """Return the @type of object allowed for POST/PUT."""
     for supportedOp in get_doc().parsed_classes[class_type]["class"].supportedOperation:
         if supportedOp.method == method:
@@ -62,18 +119,52 @@ def getType(class_type, method):
     # NOTE: Don't use split, if there are more than one substrings with 'vocab:' not everything will be returned.
 
 
-def checkClassOp(class_type, method):
+def checkClassOp(class_type: str, method: str) -> bool:
     """Check if the Class supports the operation."""
     for supportedOp in get_doc().parsed_classes[class_type]["class"].supportedOperation:
         if supportedOp.method == method:
             return True
     return False
 
+def verify_user() -> Union[Response, None]:
+    """ 
+    Verify the credentials of the user and assign token.
+    """
+    try:
+        auth = check_authorization(request, get_session())
+        if auth is False:
+            return failed_authentication(True)
+        else:
+            if get_token():
+                token = add_token(request, get_session())
+                return token_response(token)
+    except Exception as e:
+        status_code, message = e.get_HTTP()  # type: ignore
+        return set_response_headers(jsonify(message), status_code=status_code)
+    return None  
+
+def check_authentication_response() -> Union[Response,None]:
+    """ 
+    Return the response as per the authentication requirements.
+    """
+    if get_authentication():
+        if get_token():
+            token = check_token(request, get_session())
+            if not token:
+                if request.authorization is None:
+                    return failed_authentication(False)
+                else:
+                    return verify_user()
+        elif request.authorization is None:
+            return failed_authentication(False)
+        else:
+            return verify_user()
+    return None
 
 class Index(Resource):
     """Class for the EntryPoint."""
 
-    def get(self):
+    def get(self) -> Response:
         """Return main entrypoint for the api."""
         return set_response_headers(jsonify(get_doc().entrypoint.get()))
 
@@ -81,7 +172,7 @@ class Index(Resource):
 class Vocab(Resource):
     """Vocabulary for Hydra."""
 
-    def get(self):
+    def get(self) -> Response:
         """Return the main hydra vocab."""
         return set_response_headers(jsonify(get_doc().generate()))
 
@@ -89,7 +180,7 @@ class Vocab(Resource):
 class Entrypoint(Resource):
     """Hydra EntryPoint."""
 
-    def get(self):
+    def get(self) -> Response:
         """Return application main Entrypoint."""
         response = {"@context": get_doc().entrypoint.context.generate()}
         return set_response_headers(jsonify(response))
@@ -98,65 +189,63 @@ class Entrypoint(Resource):
 class Item(Resource):
     """Handles all operations(GET, POST, PATCH, DELETE) on Items (item can be anything depending upon the vocabulary)."""
 
-    def get(self, id_, type_):
-        """GET object with id = id_ from the database."""
-        if get_authentication():
-            if request.authorization is None:
-                return failed_authentication()
-            else:
-                try:
-                    auth = check_authorization(request, get_session())
-                    if auth is False:
-                        return failed_authentication()
-                except Exception as e:
-                    status_code, message = e.get_HTTP()
-                    return set_response_headers(jsonify(message), status_code=status_code)
+    def get(self, id_: int, type_: str) -> Response:
+        """
+        GET object with id = id_ from the database.
+
+        :param id : Item ID
+        :param type_ : Item type
+        """
+        auth_response = check_authentication_response()
+        if type(auth_response) == Response:
+            return auth_response
 
         class_type = get_doc().collections[type_]["collection"].class_.title
 
         if checkClassOp(class_type, "GET"):
-
+            # Check if class_type supports GET operation
             try:
-                response = crud.get(id_, class_type, api_name=get_api_name(), session=get_session())
+                # Try getting the Item based on ID and Class type
+                response = crud.get(
+                    id_, class_type, api_name=get_api_name(), session=get_session())
                 return set_response_headers(jsonify(hydrafy(response)))
 
-            except Exception as e:
+            except (ClassNotFound, InstanceNotFound) as e:
                 status_code, message = e.get_HTTP()
                 return set_response_headers(jsonify(message), status_code=status_code)
-
         abort(405)
 
-    def post(self, id_, type_):
-        """Update object of type<type_> at ID<id_> with new object_ using HTTP POST."""
-        if get_authentication():
-            if request.authorization is None:
-                return failed_authentication()
-            else:
-                try:
-                    auth = check_authorization(request, get_session())
-                    if auth is False:
-                        return failed_authentication()
-                except Exception as e:
-                    status_code, message = e.get_HTTP()
-                    return set_response_headers(jsonify(message), status_code=status_code)
+    def post(self, id_: int, type_: str) -> Response:
+        """Update object of type<type_> at ID<id_> with new object_ using HTTP POST.
+
+        :param id_ - ID of Item to be updated
+        :param type_ - Type(Class name) of Item to be updated
+        """
+        auth_response = check_authentication_response()
+        if type(auth_response) == Response:
+            return auth_response
 
         class_type = get_doc().collections[type_]["collection"].class_.title
 
         if checkClassOp(class_type, "POST"):
-
+            # Check if class_type supports POST operation
             object_ = json.loads(request.data.decode('utf-8'))
             obj_type = getType(class_type, "POST")
-
+            # Load new object and type
             if validObject(object_):
-
                 if object_["@type"] == obj_type:
                     try:
-                        object_id = crud.update(object_=object_, id_=id_, type_=object_["@type"], session=get_session(), api_name=get_api_name())
-                        headers_ = [{"Location": get_hydrus_server_url()+get_api_name()+"/"+type_+"/"+str(object_id)}]
-                        response = {"message": "Object with ID %s successfully updated" % (object_id)}
+                        # Update the right ID if the object is valid and matches
+                        # type of Item
+                        object_id = crud.update(object_=object_, id_=id_, type_=object_[
+                                                "@type"], session=get_session(), api_name=get_api_name())
+                        headers_ = [{"Location": get_hydrus_server_url(
+                        ) + get_api_name() + "/" + type_ + "/" + str(object_id)}]
+                        response = {
+                            "message": "Object with ID %s successfully updated" % (object_id)}
                         return set_response_headers(jsonify(response), headers=headers_)
 
-                    except Exception as e:
+                    except (ClassNotFound, InstanceNotFound, InstanceExists, PropertyNotFound) as e:
                         status_code, message = e.get_HTTP()
                         return set_response_headers(jsonify(message), status_code=status_code)
 
@@ -164,37 +253,35 @@ class Item(Resource):
 
         abort(405)
 
-    def put(self, id_, type_):
-        """Add new object_ optional <id_> parameter using HTTP PUT."""
-        if get_authentication():
-            if request.authorization is None:
-                return failed_authentication()
-            else:
-                try:
-                    auth = check_authorization(request, get_session())
-                    if auth is False:
-                        return failed_authentication()
-                except Exception as e:
-                    status_code, message = e.get_HTTP()
-                    return set_response_headers(jsonify(message), status_code=status_code)
+    def put(self, id_: int, type_: str) -> Response:
+        """Add new object_ optional <id_> parameter using HTTP PUT.
+
+        :param id_ - ID of Item to be updated
+        :param type_ - Type(Class name) of Item to be updated
+        """
+        auth_response = check_authentication_response()
+        if type(auth_response) == Response:
+            return auth_response
 
         class_type = get_doc().collections[type_]["collection"].class_.title
 
         if checkClassOp(class_type, "PUT"):
-
+            # Check if class_type supports PUT operation
             object_ = json.loads(request.data.decode('utf-8'))
             obj_type = getType(class_type, "PUT")
-
+            # Load new object and type
             if validObject(object_):
-
                 if object_["@type"] == obj_type:
                     try:
-                        object_id = crud.insert(object_=object_, id_=id_, session=get_session())
-                        headers_ = [{"Location": get_hydrus_server_url()+get_api_name()+"/"+type_+"/"+str(object_id)}]
-                        response = {"message": "Object with ID %s successfully added" % (object_id)}
+                        # Add the object with given ID
+                        object_id = crud.insert(
+                            object_=object_, id_=id_, session=get_session())
+                        headers_ = [{"Location": get_hydrus_server_url(
+                        ) + get_api_name() + "/" + type_ + "/" + str(object_id)}]
+                        response = {
+                            "message": "Object with ID %s successfully added" % (object_id)}
                         return set_response_headers(jsonify(response), headers=headers_, status_code=201)
-
-                    except Exception as e:
+                    except (ClassNotFound, InstanceExists, PropertyNotFound) as e:
                         status_code, message = e.get_HTTP()
                         return set_response_headers(jsonify(message), status_code=status_code)
 
@@ -202,29 +289,24 @@ class Item(Resource):
 
         abort(405)
 
-    def delete(self, id_, type_):
+    def delete(self, id_: int, type_: str) -> Response:
         """Delete object with id=id_ from database."""
-        if get_authentication():
-            if request.authorization is None:
-                return failed_authentication()
-            else:
-                try:
-                    auth = check_authorization(request, get_session())
-                    if auth is False:
-                        return failed_authentication()
-                except Exception as e:
-                    status_code, message = e.get_HTTP()
-                    return set_response_headers(jsonify(message), status_code=status_code)
+        auth_response = check_authentication_response()
+        if type(auth_response) == Response:
+            return auth_response
 
         class_type = get_doc().collections[type_]["collection"].class_.title
 
         if checkClassOp(class_type, "DELETE"):
+            # Check if class_type supports PUT operation
             try:
+                # Delete the Item with ID == id_
                 crud.delete(id_, class_type, session=get_session())
-                response = {"message": "Object with ID %s successfully deleted" % (id_)}
+                response = {
+                    "message": "Object with ID %s successfully deleted" % (id_)}
                 return set_response_headers(jsonify(response))
 
-            except Exception as e:
+            except (ClassNotFound, InstanceNotFound) as e:
                 status_code, message = e.get_HTTP()
                 return set_response_headers(jsonify(message), status_code=status_code)
 
@@ -234,174 +316,174 @@ class Item(Resource):
 class ItemCollection(Resource):
     """Handle operation related to ItemCollection (a collection of items)."""
 
-    def get(self, type_):
-        """Retrieve a collection of items from the database."""
-        if get_authentication():
-            if request.authorization is None:
-                return failed_authentication()
-            else:
-                try:
-                    auth = check_authorization(request, get_session())
-                    if auth is False:
-                        return failed_authentication()
-                except Exception as e:
-                    status_code, message = e.get_HTTP()
-                    return set_response_headers(jsonify(message), status_code=status_code)
-
-        if checkEndpoint("GET", type_):
-            # Collections
+    def get(self, type_: str) -> Response:
+        """
+        Retrieve a collection of items from the database.
+        """
+        auth_response = check_authentication_response()
+        if type(auth_response) == Response:
+            return auth_response
+        endpoint_ = checkEndpoint("GET",type_)
+        if endpoint_['method']:
+            # If endpoint and GET method is supported in the API
             if type_ in get_doc().collections:
-
+                # If collection name in document's collections
                 collection = get_doc().collections[type_]["collection"]
                 try:
-                    response = crud.get_collection(get_api_name(), collection.class_.title, session=get_session())
+                    # Get collection details from the database
+                    response = crud.get_collection(
+                        get_api_name(), collection.class_.title, session=get_session())
                     return set_response_headers(jsonify(hydrafy(response)))
 
-                except Exception as e:
+                except ClassNotFound as e:
                     status_code, message = e.get_HTTP()
                     return set_response_headers(jsonify(message), status_code=status_code)
 
-            # Non Collection classes
-            elif type_ in get_doc().parsed_classes and type_+"Collection" not in get_doc().collections:
+            # If class is supported
+            elif type_ in get_doc().parsed_classes and type_ + "Collection" not in get_doc().collections:
                 try:
-                    response = crud.get_single(type_, api_name=get_api_name(), session=get_session())
+                    response = crud.get_single(
+                        type_, api_name=get_api_name(), session=get_session())
                     return set_response_headers(jsonify(hydrafy(response)))
 
-                except Exception as e:
-                    status_code, message = e.get_HTTP()
-                    return set_response_headers(jsonify(message), status_code=status_code)
-
-        abort(405)
-
-    def put(self, type_):
-        """Add item to ItemCollection."""
-        if get_authentication():
-            if request.authorization is None:
-                return failed_authentication()
-            else:
-                try:
-                    auth = check_authorization(request, get_session())
-                    if auth is False:
-                        return failed_authentication()
-                except Exception as e:
+                except (ClassNotFound, InstanceNotFound) as e:
                     status_code, message = e.get_HTTP()
                     return set_response_headers(jsonify(message), status_code=status_code)
 
-        if checkEndpoint("PUT", type_):
+        abort(endpoint_['status'])
+
+    def put(self, type_: str) -> Response:
+        """
+        Method executed for PUT requests.
+        Used to add an item to a collection
+
+        :param type_ - Item type
+        """
+        auth_response = check_authentication_response()
+        if type(auth_response) == Response:
+            return auth_response
+        
+        endpoint_ = checkEndpoint("PUT", type_)
+        if endpoint_['method']:
+            # If endpoint and PUT method is supported in the API
             object_ = json.loads(request.data.decode('utf-8'))
 
-            # Collections
             if type_ in get_doc().collections:
-
+                # If collection name in document's collections
                 collection = get_doc().collections[type_]["collection"]
+
+                # title of HydraClass object corresponding to collection
                 obj_type = collection.class_.title
 
                 if validObject(object_):
-
+                    # If Item in request's JSON is a valid object
+                    # ie. @type is one of the keys in object_
                     if object_["@type"] == obj_type:
+                        # If the right Item type is being added to the collection
                         try:
-                            object_id = crud.insert(object_=object_, session=get_session())
-                            headers_ = [{"Location": get_hydrus_server_url()+get_api_name()+"/"+type_+"/"+str(object_id)}]
-                            response = {"message": "Object with ID %s successfully deleted" % (object_id)}
+                            # Insert object and return location in Header
+                            object_id = crud.insert(
+                                object_=object_, session=get_session())
+                            headers_ = [{"Location": get_hydrus_server_url(
+                            ) + get_api_name() + "/" + type_ + "/" + str(object_id)}]
+                            response = {
+                                "message": "Object with ID %s successfully added" % (object_id)}
                             return set_response_headers(jsonify(response), headers=headers_, status_code=201)
-                        except Exception as e:
+                        except (ClassNotFound, InstanceExists, PropertyNotFound) as e:
                             status_code, message = e.get_HTTP()
                             return set_response_headers(jsonify(message), status_code=status_code)
 
                 return set_response_headers(jsonify({400: "Data is not valid"}), status_code=400)
 
-            # Non Collection classes
-            elif type_ in get_doc().parsed_classes and type_+"Collection" not in get_doc().collections:
+            elif type_ in get_doc().parsed_classes and type_ + "Collection" not in get_doc().collections:
+                # If type_ is in parsed_classes but is not a collection
                 obj_type = getType(type_, "PUT")
-
                 if object_["@type"] == obj_type:
-
                     if validObject(object_):
                         try:
-                            object_id = crud.insert(object_=object_, session=get_session())
-                            headers_ = [{"Location": get_hydrus_server_url()+get_api_name()+"/"+type_+"/"}]
+                            object_id = crud.insert(
+                                object_=object_, session=get_session())
+                            headers_ = [{"Location": get_hydrus_server_url(
+                            ) + get_api_name() + "/" + type_ + "/"}]
                             response = {"message": "Object successfully added"}
                             return set_response_headers(jsonify(response), headers=headers_, status_code=201)
-                        except Exception as e:
+                        except (ClassNotFound, InstanceExists, PropertyNotFound) as e:
                             status_code, message = e.get_HTTP()
                             return set_response_headers(jsonify(message), status_code=status_code)
 
                 return set_response_headers(jsonify({400: "Data is not valid"}), status_code=400)
 
-        abort(405)
+        abort(endpoint_['status'])
 
-    def post(self, type_):
-        """Update Non Collection class item."""
-        if get_authentication():
-            if request.authorization is None:
-                return failed_authentication()
-            else:
-                try:
-                    auth = check_authorization(request, get_session())
-                    if auth is False:
-                        return failed_authentication()
-                except Exception as e:
-                    status_code, message = e.get_HTTP()
-                    return set_response_headers(jsonify(message), status_code=status_code)
+    def post(self, type_: str) -> Response:
+        """
+        Method executed for POST requests.
+        Used to update a non-collection class.
 
-        if checkEndpoint("POST", type_):
-            object_ = json.loads(request.data.decode('utf-8'))
+        :param type_ - Item type
+        """
+        auth_response = check_authentication_response()
+        if type(auth_response) == Response:
+            return auth_response
 
-            if type_ in get_doc().parsed_classes and type_+"Collection" not in get_doc().collections:
+        endpoint_ = checkEndpoint("POST", type_)
+        if endpoint_['method']:
+            object_ = json.loads(request.data.decode('utf-8'))
+            if type_ in get_doc().parsed_classes and type_ + "Collection" not in get_doc().collections:
                 obj_type = getType(type_, "POST")
-
                 if validObject(object_):
-
                     if object_["@type"] == obj_type:
-                        # try:
-                            crud.update_single(object_=object_, session=get_session(), api_name=get_api_name())
-                            headers_ = [{"Location": get_hydrus_server_url()+get_api_name()+"/"+type_+"/"}]
+                        try:
+                            crud.update_single(
+                                object_=object_, session=get_session(), api_name=get_api_name())
+                            headers_ = [{"Location": get_hydrus_server_url(
+                            ) + get_api_name() + "/" + type_ + "/"}]
                             response = {"message": "Object successfully updated"}
                             return set_response_headers(jsonify(response), headers=headers_)
-                        # except Exception as e:
-                        #     status_code, message = e.get_HTTP()
-                        #     return set_response_headers(jsonify(message), status_code=status_code)
+                        except (ClassNotFound, InstanceNotFound, InstanceExists, PropertyNotFound) as e:
+                             status_code, message = e.get_HTTP()
+                             return set_response_headers(jsonify(message), status_code=status_code)
 
                 return set_response_headers(jsonify({400: "Data is not valid"}), status_code=400)
 
-        abort(405)
-
-    def delete(self, type_):
-        """Delete a non Collection class item."""
-        if get_authentication():
-            if request.authorization is None:
-                return failed_authentication()
-            else:
-                try:
-                    auth = check_authorization(request, get_session())
-                    if auth is False:
-                        return failed_authentication()
-                except Exception as e:
-                    status_code, message = e.get_HTTP()
-                    return set_response_headers(jsonify(message), status_code=status_code)
-
-        if checkEndpoint("DELETE", type_):
+        abort(endpoint_['status'])
+
+    def delete(self, type_: str) -> Response:
+        """
+        Method executed for DELETE requests.
+        Used to delete a non-collection class.
+
+        :param type_ - Item type
+        """
+        auth_response = check_authentication_response()
+        if type(auth_response) == Response:
+            return auth_response
+          
+        endpoint_ = checkEndpoint("DELETE", type_)
+        if endpoint_['method']:
             # No Delete Operation for collections
-            if type_ in get_doc().parsed_classes and type_+"Collection" not in get_doc().collections:
+            if type_ in get_doc().parsed_classes and type_ + "Collection" not in get_doc().collections:
                 try:
                     crud.delete_single(type_, session=get_session())
                     response = {"message": "Object successfully deleted"}
                     return set_response_headers(jsonify(response))
-                except Exception as e:
+                except (ClassNotFound, InstanceNotFound) as e:
                     status_code, message = e.get_HTTP()
                     return set_response_headers(jsonify(message), status_code=status_code)
-        abort(405)
+        abort(endpoint_['status'])
 
 
 class Contexts(Resource):
     """Dynamically genereated contexts."""
 
-    def get(self, category):
+    def get(self, category: str) -> Response:
         """Return the context for the specified class."""
         if "Collection" in category:
 
             if category in get_doc().collections:
-                response = {"@context": get_doc().collections[category]["context"].generate()}
+                # type: Union[Dict[str,Any],Dict[int,str]]
+                response = {
+                    "@context": get_doc().collections[category]["context"].generate()}
                 return set_response_headers(jsonify(response))
 
             else:
@@ -411,7 +493,8 @@ class Contexts(Resource):
         else:
 
             if category in get_doc().parsed_classes:
-                response = {"@context": get_doc().parsed_classes[category]["context"].generate()}
+                response = {
+                    "@context": get_doc().parsed_classes[category]["context"].generate()}
                 return set_response_headers(jsonify(response))
 
             else:
@@ -419,20 +502,24 @@ class Contexts(Resource):
                 return set_response_headers(jsonify(response), status_code=404)
 
 
-def app_factory(API_NAME="api"):
+def app_factory(API_NAME: str="api") -> Flask:
     """Create an app object."""
     app = Flask(__name__)
-
+    app.config['SECRET_KEY'] = 'secret key'
     CORS(app)
     app.url_map.strict_slashes = False
     api = Api(app)
 
-    api.add_resource(Index, "/"+API_NAME+"/", endpoint="api")
-    api.add_resource(Vocab, "/"+API_NAME+"/vocab", endpoint="vocab")
-    api.add_resource(Contexts, "/"+API_NAME+"/contexts/<string:category>.jsonld", endpoint="contexts")
-    api.add_resource(Entrypoint, "/"+API_NAME+"/contexts/EntryPoint.jsonld", endpoint="main_entrypoint")
-    api.add_resource(ItemCollection, "/"+API_NAME+"/<string:type_>", endpoint="item_collection")
-    api.add_resource(Item, "/"+API_NAME+"/<string:type_>/<int:id_>", endpoint="item")
+    api.add_resource(Index, "/" + API_NAME + "/", endpoint="api")
+    api.add_resource(Vocab, "/" + API_NAME + "/vocab", endpoint="vocab")
+    api.add_resource(Contexts, "/" + API_NAME +
+                     "/contexts/<string:category>.jsonld", endpoint="contexts")
+    api.add_resource(Entrypoint, "/" + API_NAME +
+                     "/contexts/EntryPoint.jsonld", endpoint="main_entrypoint")
+    api.add_resource(ItemCollection, "/" + API_NAME +
+                     "/<string:type_>", endpoint="item_collection")
+    api.add_resource(Item, "/" + API_NAME +
+                     "/<string:type_>/<int:id_>", endpoint="item")
 
     return app
 
diff --git a/hydrus/data/crud.py b/hydrus/data/crud.py
index 11c94ee..82163c3 100644
--- a/hydrus/data/crud.py
+++ b/hydrus/data/crud.py
@@ -1,4 +1,35 @@
-"""Basic CRUD operations for the server."""
+"""Basic CRUD operations for the server.
+
+    ===============================
+    Imports :
+
+    sqlalchemy.orm.with_polymorphic : Load columns for inheriting classes.
+    Ref : http://docs.sqlalchemy.org/en/latest/orm/query.html
+
+    sqlalchemy.exists : A convenience method that turns a query into an EXISTS subquery of the form EXISTS (SELECT 1 FROM … WHERE …).
+    Ref : http://docs.sqlalchemy.org/en/latest/orm/query.html
+
+    sqlalchemy.orm.exc.NoResultFound : A database result was required but none was found.
+    Ref : http://docs.sqlalchemy.org/en/latest/orm/exceptions.html?highlight=result%20found#sqlalchemy.orm.exc.NoResultFound
+
+    sqlalchemy.orm.session.Session : Manages persistence operations for ORM-mapped objects.
+    Ref : http://docs.sqlalchemy.org/en/latest/orm/session_api.html?highlight=session#module-sqlalchemy.orm.session
+
+    hydrus.data.db_models.Graph : Model for a graph that store triples of instance from the other models to map relationships.
+    hydrus.data.db_models.BaseProperty : Model for Basic Property.
+    hydrus.data.db_models.RDFClass : Model for Classes specifically RDF-OWL or RDF-HYDRA classes.
+    hydrus.data.db_models.Instance : Model for Object/Resource. Instances are instances of some kind/classes that are served through the API.
+    hydrus.data.db_models.Terminal : Model for Terminals which are numbers or string that can be referenced by a Property. 
+    hydrus.data.db_models.GraphIAC : Graph model for Instance >> AbstractProperty >> Class.
+    hydrus.data.db_models.GraphIIT : Graph model for Instance >> InstanceProperty >> Terminal.
+    hydrus.data.db_models.GraphIII : Graph model for Instance >> InstanceProperty >> Instance.
+    
+    Ref : ./db_models.py
+
+    hydrus.data.exceptions : Contains all exceptions .
+    typing : Module which provides support for type hints .
+
+"""
 
 from sqlalchemy.orm import with_polymorphic
 from sqlalchemy import exists
@@ -9,16 +40,19 @@ from hydrus.data.db_models import (Graph, BaseProperty, RDFClass, Instance,
 from hydrus.data.exceptions import (ClassNotFound, InstanceExists, PropertyNotFound,
                                     NotInstanceProperty, NotAbstractProperty,
                                     InstanceNotFound)
+# from sqlalchemy.orm.session import Session
+from sqlalchemy.orm.scoping import scoped_session
+from typing import Dict, Optional, Any, List
 
 triples = with_polymorphic(Graph, '*')
 properties = with_polymorphic(BaseProperty, "*")
 
 
-def get(id_, type_, api_name, session, recursive=False):
+def get(id_: int, type_: str, api_name: str, session: scoped_session, recursive: bool = False) -> Dict[str, str]:
     """Retrieve an Instance with given ID from the database [GET]."""
     object_template = {
         "@type": "",
-    }
+    } # type: Dict[str, Any]
     try:
         rdf_class = session.query(RDFClass).filter(
             RDFClass.name == type_).one()
@@ -66,7 +100,7 @@ def get(id_, type_, api_name, session, recursive=False):
     return object_template
 
 
-def insert(object_, session, id_=None):
+def insert(object_: Dict[str, Any], session: scoped_session , id_: Optional[int] =None) -> int:
     """Insert an object to database [POST] and returns the inserted object."""
     rdf_class = None
     instance = None
@@ -144,7 +178,7 @@ def insert(object_, session, id_=None):
     return instance.id
 
 
-def delete(id_, type_, session):
+def delete(id_:int, type_:str, session:scoped_session) -> None:
     """Delete an Instance and all its relations from DB given id [DELETE]."""
     try:
         rdf_class = session.query(RDFClass).filter(RDFClass.name == type_).one()
@@ -179,7 +213,7 @@ def delete(id_, type_, session):
     session.commit()
 
 
-def update(id_, type_, object_, session, api_name):
+def update(id_: int, type_: str, object_: Dict[str,str], session: scoped_session, api_name:str) -> int:
     """Update an object properties based on the given object [PUT]."""
     # Keep the object as fail safe
     instance = get(id_=id_, type_=type_, session=session, api_name=api_name)
@@ -190,7 +224,7 @@ def update(id_, type_, object_, session, api_name):
     # Try inserting new object
     try:
         insert(object_=object_, id_=id_, session=session)
-    except Exception as e:
+    except (ClassNotFound, InstanceExists, PropertyNotFound) as e:
         # Put old object back
         insert(object_=instance, id_=id_, session=session)
         raise e
@@ -199,14 +233,14 @@ def update(id_, type_, object_, session, api_name):
     return id_
 
 
-def get_collection(API_NAME, type_, session):
+def get_collection(API_NAME: str, type_: str, session: scoped_session) -> Dict[str, Any]:
     """Retrieve a type of collection from the database."""
     collection_template = {
         "@id": "/"+API_NAME+"/" + type_ + "Collection/",
         "@context": None,
         "@type": type_ + "Collection",
         "members": list()
-    }
+    } # type: Dict[str, Any]
     try:
         rdf_class = session.query(RDFClass).filter(
             RDFClass.name == type_).one()
@@ -227,7 +261,7 @@ def get_collection(API_NAME, type_, session):
     return collection_template
 
 
-def get_single(type_, api_name, session):
+def get_single(type_: str, api_name: str, session: scoped_session) -> Dict[str, Any]:
     """Get instance of classes with single objects."""
     try:
         rdf_class = session.query(RDFClass).filter(RDFClass.name == type_).one()
@@ -245,7 +279,7 @@ def get_single(type_, api_name, session):
     return object_
 
 
-def insert_single(object_, session):
+def insert_single(object_: Dict[str, Any], session: scoped_session) -> Any:
     """Insert instance of classes with single objects."""
     try:
         rdf_class = session.query(RDFClass).filter(RDFClass.name == object_["@type"]).one()
@@ -260,7 +294,7 @@ def insert_single(object_, session):
     raise InstanceExists(type_=rdf_class.name)
 
 
-def update_single(object_, session, api_name):
+def update_single(object_: Dict[str, Any], session: scoped_session, api_name: str) -> int:
     """Update instance of classes with single objects."""
     try:
         rdf_class = session.query(RDFClass).filter(RDFClass.name == object_["@type"]).one()
@@ -276,7 +310,7 @@ def update_single(object_, session, api_name):
     return update(id_=instance.id, type_=object_["@type"], object_=object_, session=session, api_name=api_name)
 
 
-def delete_single(type_, session):
+def delete_single(type_: str, session: scoped_session) -> None:
     """Delete instance of classes with single objects."""
     try:
         rdf_class = session.query(RDFClass).filter(RDFClass.name == type_).one()
@@ -288,4 +322,4 @@ def delete_single(type_, session):
     except (NoResultFound, IndexError, ValueError):
         raise InstanceNotFound(type_=rdf_class.name)
 
-    return delete(instance.id, type_, session=session)
+    return delete(instance.id, type_, session=session)
\ No newline at end of file
diff --git a/hydrus/data/db_models.py b/hydrus/data/db_models.py
index b84a750..c5f6b9c 100644
--- a/hydrus/data/db_models.py
+++ b/hydrus/data/db_models.py
@@ -2,17 +2,17 @@
 
 from sqlalchemy import create_engine, ForeignKey
 from sqlalchemy.ext.declarative import declarative_base
-from sqlalchemy import Column, Integer, String
+from sqlalchemy import Column, Integer, String, DateTime
+from typing import Any
 # from hydrus.settings import DB_URL
 
 engine = create_engine('sqlite:///database.db')
 
-Base = declarative_base()
+Base = declarative_base() # type: Any
 
 
 class RDFClass(Base):
     """Model for Classes.
-
     Classes are RDF-OWL or RDF-HYDRA classes.
     """
 
@@ -21,14 +21,13 @@ class RDFClass(Base):
     id = Column(Integer, primary_key=True)
     name = Column(String, unique=True)
 
-    def __repr__(self):
+    def __repr__(self) -> str:
         """Verbose object name."""
         return "<id='%s', name='%s'>" % (self.id, self.name)
 
 
 class Instance(Base):
     """Model for Object/Resource.
-
     Instances are instances of some kind/classes that are served through the API.
     """
 
@@ -55,7 +54,6 @@ class BaseProperty(Base):
 
 class InstanceProperty(BaseProperty):
     """Model for Instance Properties.
-
     Instance Properties are properties that are used as predicate when the subject is an Instance.
     >>> prop1 = BaseProperty('hasWeight')
     >>> prop2 = BaseProperty('hasCost')
@@ -65,14 +63,13 @@ class InstanceProperty(BaseProperty):
         'polymorphic_identity': 'INSTANCE'
     }
 
-    def __repr__(self):
+    def __repr__(self) -> str:
         """Verbose object name."""
         return "<id='%s', name='%s', type='%s'>" % (self.id, self.name, self.type_)
 
 
 class AbstractProperty(BaseProperty):
     """Model for Abstract Properties.
-
     Abstract Properties are properties that are used as predicate between two RDF-OWL classes.
     >>> prop1 = BaseProperty('hasWeight')
     >>> prop2 = BaseProperty('hasCost')
@@ -84,14 +81,13 @@ class AbstractProperty(BaseProperty):
         'polymorphic_identity': 'ABSTRACT'
     }
 
-    def __repr__(self):
+    def __repr__(self) -> str:
         """Verbose object name."""
         return "<id='%s', name='%s', type='%s'>" % (self.id, self.name, self.type_)
 
 
 class Terminal(Base):
     """Model for Terminals.
-
     Terminals are numbers or string that can be referenced by a Property. They can be only
      objects in a triple.
     >>> t = Terminal(value=85, unit='cubic centimeters')
@@ -104,7 +100,7 @@ class Terminal(Base):
     value = Column(String)
     unit = Column(String)
 
-    def __repr__(self):
+    def __repr__(self) -> str:
         """Verbose object name."""
         return "<id='%s', value='%s', unit='%s'>" % (self.id, self.value, self.unit)
 
@@ -136,7 +132,7 @@ class GraphCAC(Graph):
         'polymorphic_identity': 'graphcac',
     }
 
-    def __repr__(self):
+    def __repr__(self) -> str:
         """Verbose object name."""
         return "<subject='%s', predicate='%s', object_='%s'>" % (self.subject, self.predicate, self.object_)
 
@@ -154,7 +150,7 @@ class GraphIAC(Graph):
         'polymorphic_identity': 'graphiac',
     }
 
-    def __repr__(self):
+    def __repr__(self) -> str:
         """Verbose object name."""
         return "<subject='%s', predicate='%s', object_='%s'>" % (self.subject, self.predicate, self.object_)
 
@@ -172,7 +168,7 @@ class GraphIII(Graph):
         'polymorphic_identity': 'graphiii',
     }
 
-    def __repr__(self):
+    def __repr__(self) -> str:
         """Verbose object name."""
         return "<subject='%s', predicate='%s', object_='%s'>" % (self.subject, self.predicate, self.object_)
 
@@ -190,7 +186,7 @@ class GraphIIT(Graph):
         'polymorphic_identity': 'graphiit',
     }
 
-    def __repr__(self):
+    def __repr__(self) -> str:
         """Verbose object name."""
         return "<subject='%s', predicate='%s', object_='%s'>" % (self.subject, self.predicate, self.object_)
 
@@ -203,8 +199,22 @@ class User(Base):
     id = Column(Integer, primary_key=True)
     paraphrase = Column(String)
 
+class Token(Base):
+    """Model for storing tokens for the users."""
+
+    __tablename__ = "tokens"
+    id = Column(String, primary_key = True)
+    user_id = Column(Integer, ForeignKey('user.id'))
+    timestamp = Column(DateTime) 
+
+class Nonce(Base):
+    """Model for storing nonce for the users."""
+
+    __tablename__  = "nonce"
+    id = Column(String, primary_key = True)
+    timestamp = Column(DateTime)
 
 if __name__ == "__main__":
     print("Creating models....")
     Base.metadata.create_all(engine)
-    print("Done")
+    print("Done")
\ No newline at end of file
diff --git a/hydrus/data/doc_parse.py b/hydrus/data/doc_parse.py
index 709d594..0886086 100644
--- a/hydrus/data/doc_parse.py
+++ b/hydrus/data/doc_parse.py
@@ -3,10 +3,13 @@
 from sqlalchemy import exists
 
 from hydrus.data.db_models import RDFClass, BaseProperty
+from typing import Any, Dict, List, Set, Optional
+from sqlalchemy.orm.session import Session
+from sqlalchemy.orm import scoped_session
 # from hydrus.tests.example_doc import doc_gen
 
 
-def get_classes(apidoc):
+def get_classes(apidoc: Dict[str, Any]) -> List[Dict[str, Any]]:
     """Get all the classes in the APIDocumentation."""
     classes = list()
     for class_ in apidoc["supportedClass"]:
@@ -16,10 +19,10 @@ def get_classes(apidoc):
     return classes
 
 
-def get_all_properties(classes):
+def get_all_properties(classes: List[Dict[str, Any]]) -> Set[str]:
     """Get all the classes in the APIDocumentation."""
     # properties = list()
-    prop_names = set()
+    prop_names = set() # type: Set[str]
     for class_ in classes:
         for prop in class_["supportedProperty"]:
             if prop["title"] not in prop_names:
@@ -28,9 +31,13 @@ def get_all_properties(classes):
     return set(prop_names)
 
 
-def insert_classes(classes, session):
+def insert_classes(classes: List[Dict[str, Any]], session: scoped_session) -> Optional[Any]:
     """Insert all the classes as defined in the APIDocumentation into DB."""
     # print(session.query(exists().where(RDFClass.name == "Datastream")).scalar())
+    if not isinstance(session, scoped_session) and not isinstance(session, Session):
+        raise TypeError(
+            "session is not of type <sqlalchemy.orm.scoping.scoped_session> or <sqlalchemy.orm.session.Session>"
+        )
     class_list = [RDFClass(name=class_["label"].strip('.')) for class_ in classes
                   if "label" in class_ and
                   not session.query(exists().where(RDFClass.name == class_["label"].strip('.'))).scalar()]
@@ -44,7 +51,7 @@ def insert_classes(classes, session):
     return None
 
 
-def insert_properties(properties, session):
+def insert_properties(properties: Set[str], session: scoped_session) -> Optional[Any]:
     """Insert all the properties as defined in the APIDocumentation into DB."""
     prop_list = [BaseProperty(name=prop) for prop in properties
                  if not session.query(exists().where(BaseProperty.name == prop)).scalar()]
@@ -69,4 +76,4 @@ def insert_properties(properties, session):
 #     print("Classes inserted successfully")
 #     # Add all the properties
 #     insert_properties(properties, session)
-#     print("Properties inserted successfully")
+#     print("Properties inserted successfully")
\ No newline at end of file
diff --git a/hydrus/data/exceptions.py b/hydrus/data/exceptions.py
index d67142d..8432ca7 100644
--- a/hydrus/data/exceptions.py
+++ b/hydrus/data/exceptions.py
@@ -1,14 +1,15 @@
 """Exceptions for the crud operations."""
+from typing import Dict, Tuple, Union
 
 
 class ClassNotFound(Exception):
     """Error when the RDFClass is not found."""
 
-    def __init__(self, type_):
+    def __init__(self, type_: str) -> None:
         """Constructor."""
         self.type_ = type_
 
-    def get_HTTP(self):
+    def get_HTTP(self) -> Tuple[int, Dict[str, str]]:
         """Return the HTTP response for the Exception."""
         return 400, {"message": "The class %s is not a valid/defined RDFClass" % self.type_}
 
@@ -16,12 +17,12 @@ class ClassNotFound(Exception):
 class InstanceNotFound(Exception):
     """Error when the Instance is not found."""
 
-    def __init__(self, type_, id_=None):
+    def __init__(self, type_: str, id_: Union[int, None] =None) -> None:
         """Constructor."""
         self.type_ = type_
         self.id_ = id_
 
-    def get_HTTP(self):
+    def get_HTTP(self) -> Tuple[int, Dict[str, str]]:
         """Return the HTTP response for the Exception."""
         if str(self.id_) is None:
             return 404, {"message": "Instance of type %s not found" % (self.type_)}
@@ -32,11 +33,11 @@ class InstanceNotFound(Exception):
 class PropertyNotFound(Exception):
     """Error when the Property is not found."""
 
-    def __init__(self, type_):
+    def __init__(self, type_: str) -> None:
         """Constructor."""
         self.type_ = type_
 
-    def get_HTTP(self):
+    def get_HTTP(self) -> Tuple[int, Dict[str, str]]:
         """Return the HTTP response for the Exception."""
         return 400, {"message": "The property %s is not a valid/defined Property" % self.type_}
 
@@ -44,12 +45,12 @@ class PropertyNotFound(Exception):
 class InstanceExists(Exception):
     """Error when the Instance already exists."""
 
-    def __init__(self, type_, id_=None):
+    def __init__(self, type_: str, id_: Union[int, None]=None) -> None:
         """Constructor."""
         self.type_ = type_
         self.id_ = id_
 
-    def get_HTTP(self):
+    def get_HTTP(self) -> Tuple[int, Dict[str, str]]:
         """Return the HTTP response for the Exception."""
         if str(self.id_) is None:
             return 400, {"message": "Instance of type %salready exists" % (self.type_)}
@@ -60,11 +61,11 @@ class InstanceExists(Exception):
 class NotInstanceProperty(Exception):
     """Error when the property is not an Instance property."""
 
-    def __init__(self, type_):
+    def __init__(self, type_: str) -> None:
         """Constructor."""
         self.type_ = type_
 
-    def get_HTTP(self):
+    def get_HTTP(self) -> Tuple[int, Dict[str, str]]:
         """Return the HTTP response for the Exception."""
         return 400, {"message": "The property %s is not an Instance property" % self.type_}
 
@@ -72,11 +73,11 @@ class NotInstanceProperty(Exception):
 class NotAbstractProperty(Exception):
     """Error when the property is not an Abstract property."""
 
-    def __init__(self, type_):
+    def __init__(self, type_: str) -> None:
         """Constructor."""
         self.type_ = type_
 
-    def get_HTTP(self):
+    def get_HTTP(self) -> Tuple[int, Dict[str, str]]:
         """Return the HTTP response for the Exception."""
         return 400, {"message": "The property %s is not an Abstract property" % self.type_}
 
@@ -84,11 +85,11 @@ class NotAbstractProperty(Exception):
 class UserExists(Exception):
     """Error when the User already exitst."""
 
-    def __init__(self, id_):
+    def __init__(self, id_: int) -> None:
         """Constructor."""
         self.id_ = id_
 
-    def get_HTTP(self):
+    def get_HTTP(self) -> Tuple[int, Dict[str, str]]:
         """Return the HTTP response for the Exception."""
         return 400, {"message": "The user with ID %s already exists" % str(self.id_)}
 
@@ -96,10 +97,10 @@ class UserExists(Exception):
 class UserNotFound(Exception):
     """Error when the User is not found."""
 
-    def __init__(self, id_):
+    def __init__(self, id_: int) -> None:
         """Constructor."""
         self.id_ = id_
 
-    def get_HTTP(self):
+    def get_HTTP(self) -> Tuple[int, Dict[str, str]]:
         """Return the HTTP response for the Exception."""
-        return 400, {"message": "The User with ID %s is not a valid/defined User" % str(self.id_)}
+        return 400, {"message": "The User with ID %s is not a valid/defined User" % str(self.id_)}
\ No newline at end of file
diff --git a/hydrus/data/legacy/generator.py b/hydrus/data/legacy/generator.py
index f535cf6..0f57e47 100644
--- a/hydrus/data/legacy/generator.py
+++ b/hydrus/data/legacy/generator.py
@@ -1,6 +1,7 @@
 """Generate random objects for SubSystem classes."""
 
 import random
+from typing import Any, Dict, List, Optional
 
 classes_keymap = {
     "communication": "Spacecraft_Communication",
@@ -102,16 +103,16 @@ subsystems = {
 }
 
 
-def randomValue(interval):
+def randomValue(interval: Dict[str, int]) -> int:
     """Generate a random integer value from a given interval."""
     if not isinstance(interval, dict):
         raise ValueError('value has to be dict')
     return random.randrange(interval['min'], interval['max'], 1) // 1
 
 
-def generateObject(name, subsystem):
+def generateObject(name: str, subsystem: Dict[str, Any]) -> Optional[Dict[str, Any]]: # type: ignore
     """Generate random components from given input dictionary."""
-    result = {}
+    result = {} # type: Dict
     result['hasMass'] = randomValue(subsystem['hasMass'])
     if 'minWorkingTemperature' in subsystem.keys():
         if not name == 'structure':
@@ -192,27 +193,28 @@ def generateObject(name, subsystem):
 
 # First we will generate data for COTS (spacecraft parts).
 # gen_cots will generate n number of spacecraft parts with random properties
-def gen_random_object():
+def gen_random_object() -> Dict[str, Any]:
     """Generate a random object."""
     index = random.randint(0, len(subsystems.keys())-1)
     k, v = list(subsystems.items())[index]
     name = str(random.randrange(0, 50)) + \
         str(random.choice(['T', 'W', 'KV', 'JFG'])) + ' ' + k
-    obj = {}
+    obj = {} # type: Dict[str, Any]
     obj['name'] = name
     obj['@type'] = classes_keymap[k]
-    obj['object'] = generateObject(k, v)
+    obj['object'] = generateObject(k, v) #type: ignore
     return obj
 
 
-def gen_cots(n):
+def gen_cots(n: int) -> List[Dict[str, Any]]:
     """Generate n number of spacecraft parts with random properties."""
-    output = []
+    output = [] # type: List[Dict[str, Any]]
     for num in range(n):
         obj = gen_random_object()
         output.append(obj)
     return output
 
 import json
+
 if __name__ == "__main__":
-    print(json.dumps(gen_cots(1), indent=4, sort_keys=True))
+    print(json.dumps(gen_cots(1), indent=4, sort_keys=True))
\ No newline at end of file
diff --git a/hydrus/data/user.py b/hydrus/data/user.py
index b3aff5f..46aad48 100644
--- a/hydrus/data/user.py
+++ b/hydrus/data/user.py
@@ -3,14 +3,18 @@
 from sqlalchemy import exists
 from sqlalchemy.orm.exc import NoResultFound
 from hydrus.data.exceptions import UserExists, UserNotFound
-from hydrus.data.db_models import User
+from hydrus.data.db_models import User, Token, Nonce
 from hashlib import sha224
 import base64
 # import random
-import pdb
+from sqlalchemy.orm.session import Session
+from werkzeug.local import LocalProxy
+from random import randrange
+from datetime import datetime,timedelta
+from uuid import uuid4
 
 
-def add_user(id_, paraphrase, session):
+def add_user(id_: int, paraphrase: str, session: Session) -> None:
     """Add new users to the database."""
     if session.query(exists().where(User.id == id_)).scalar():
         raise UserExists(id_=id_)
@@ -19,21 +23,75 @@ def add_user(id_, paraphrase, session):
         session.add(new_user)
         session.commit()
 
-# TODO: Implement handhasking for better security
-# def create_nonce(id_, session):
-#     """Assign a random nonce to the user."""
-#     user = None
-#     try:
-#         user = session.query(User).filter(User.id == id_).one()
-#     except NoResultFound:
-#         raise UserNotFound(id_=id_)
-#     user.nonce = random.randint(1, 1000000)
-#     session.commit()
-#
-#     return user.nonce
-
-
-def generate_basic_digest(id_, paraphrase):
+def check_nonce(request: LocalProxy, session: Session) -> bool:
+    """check validity of nonce passed by the user."""
+    try:
+        id_ = request.headers['X-Authentication']
+        nonce = session.query(Nonce).filter(Nonce.id == id_).one()
+        present = datetime.now()
+        present = present - nonce.timestamp
+        session.delete(nonce)
+        session.commit()
+        if present > timedelta(0,0,0,0,1,0,0):
+            return False
+    except:
+        return False
+    return True        
+
+def create_nonce(session: Session) -> str:
+    """
+    Create a one time use nonce valid for a short time 
+    for user authentication.
+    """
+    nonce = str(uuid4())
+    time = datetime.now()
+    new_nonce = Nonce(id=nonce, timestamp=time)
+    session.add(new_nonce)
+    session.commit()
+    return nonce
+
+def add_token(request: LocalProxy, session: Session) -> str:
+    """
+    Create a new token for the user or return a 
+    valid existing token to the user.
+    """
+    token = None
+    id_ = int(request.authorization['username'])
+    try:
+        token = session.query(Token).filter(Token.user_id == id_).one()
+        present = datetime.now()
+        present = present - token.timestamp
+        if present > timedelta(0,0,0,0,45,0,0):
+            update_token = '%030x' % randrange(16**30)
+            token.id = update_token
+            token.timestamp = datetime.now()
+            session.commit()
+    except NoResultFound:
+        token = '%030x' % randrange(16**30)
+        time = datetime.now()
+        new_token = Token(user_id=id_, id=token, timestamp=time)
+        session.add(new_token)
+        session.commit()
+        return token
+    return token.id
+
+def check_token(request: LocalProxy, session: Session) -> bool:
+    """
+    check validity of the token passed by the user.
+    """
+    token = None
+    try:
+        id_ = request.headers['X-Authorization']
+        token = session.query(Token).filter(Token.id == id_).one()
+        present = datetime.now()
+        present = present - token.timestamp
+        if present > timedelta(0,0,0,0,45,0,0):
+            return False
+    except:
+        return False
+    return True
+
+def generate_basic_digest(id_: int, paraphrase: str) -> str:
     """Create the digest to be added to the HTTP Authorization header."""
     paraphrase_digest = sha224(paraphrase.encode('utf-8')).hexdigest()
     credentials = str(id_) + ':' + paraphrase_digest
@@ -41,7 +99,7 @@ def generate_basic_digest(id_, paraphrase):
     return digest
 
 
-def authenticate_user(id_, paraphrase, session):
+def authenticate_user(id_: int, paraphrase: str, session: Session) -> bool:
     """Authenticate a user based on the ID and his paraphrase."""
     user = None
     try:
@@ -54,7 +112,9 @@ def authenticate_user(id_, paraphrase, session):
     return generated_hash == hashvalue
 
 
-def check_authorization(request, session):
+def check_authorization(request: LocalProxy, session: Session) -> bool:
     """Check if the request object has the correct authorization."""
     auth = request.authorization
-    return authenticate_user(auth.username, auth.password, session)
+    if check_nonce(request, session):
+        return authenticate_user(auth.username, auth.password, session)
+    return False
\ No newline at end of file
diff --git a/hydrus/hydraspec/doc_maker.py b/hydrus/hydraspec/doc_maker.py
index 66fb668..0729023 100644
--- a/hydrus/hydraspec/doc_maker.py
+++ b/hydrus/hydraspec/doc_maker.py
@@ -1,12 +1,48 @@
-"""Contsructor to take a Python dict containing an API Documentation and create a HydraDoc object for it."""
-
-from hydrus.hydraspec.doc_writer_sample import api_doc as sample_document
-from hydrus.hydraspec.doc_writer import HydraDoc, HydraClass, HydraClassProp, HydraClassOp, HydraStatus
+'''Contsructor to take a Python dict containing an API Documentation and
+create a HydraDoc object for it'''
 import re
 import json
+from hydrus.hydraspec.doc_writer_sample import api_doc as sample_document
+from hydrus.hydraspec.doc_writer import HydraDoc, HydraClass, HydraClassProp, HydraClassOp
+from hydrus.hydraspec.doc_writer import HydraStatus
+from typing import Any, Dict, Match, Optional, Tuple, Union
+
+
+def error_mapping(body: str=None) -> str :
+    """Function returns starting error message based on its body type.
+    :param body: Params type for error message
+    :return string: Error message for input key
+    """
+    error_map = {
+        "doc" : "The API Documentation must have",
+        "class_dict" : "Class must have",
+        "supported_prop" : "Property must have",
+        "supported_op": "Operation must have",
+        "possible_status": "Status must have"
+    }
+    return error_map[body]
+
+
+
+
+def input_key_check(body: Dict[str, Any], key: str=None, body_type: str=None, literal: bool=False) -> dict :
+    """Function to validate key inside the dictonary payload  
+    :param body: JSON body in which we have to check the key
+    :param key: To check if its value exit in the body
+    :param body_type: Name of JSON body
+    :param literal: To check whether we need to convert the value
+    :return string: Value of the body
+    """
+    try:
+        if literal:
+            return convert_literal(body[key])
+        return body[key]
+    except KeyError:
+        raise SyntaxError("{0} [{1}]".format(error_mapping(body_type), key))
 
 
-def createDoc(doc, HYDRUS_SERVER_URL=None, API_NAME=None):
+
+def create_doc(doc: Dict[str, Any], HYDRUS_SERVER_URL: str=None, API_NAME: str=None) -> HydraDoc:
     """Create the HydraDoc object from the API Documentation."""
     # Check @id
     try:
@@ -15,57 +51,47 @@ def createDoc(doc, HYDRUS_SERVER_URL=None, API_NAME=None):
         raise SyntaxError("The API Documentation must have [@id]")
 
     # Extract base_url, entrypoint and API name
-    matchObj = re.match(r'(.*)://(.*)/(.*)/vocab#?', id_, re.M | re.I)
-    if matchObj:
-        base_url = matchObj.group(1) + '://' + matchObj.group(2) + '/'
-        entrypoint = matchObj.group(3)
+    match_obj = re.match(r'(.*)://(.*)/(.*)/vocab#?', id_, re.M | re.I)
+    if match_obj:
+        base_url = "{0}://{1}/".format(match_obj.group(1),match_obj.group(2))
+        entrypoint = match_obj.group(3)
 
     # Syntax checks
     else:
         raise SyntaxError("The '@id' of the Documentation must be of the form:\n'[protocol] :// [base url] / [entrypoint] / vocab'")
-    try:
-        desc = doc["description"]
-    except KeyError:
-        raise SyntaxError("The API Documentation must have [description]")
-    try:
-        title = doc["title"]
-    except KeyError:
-        raise SyntaxError("The API Documentation must have [title]")
-    try:
-        supportedClass = doc["supportedClass"]
-    except KeyError:
-        raise SyntaxError("The API Documentation must have [supportedClass]")
-    try:
-        context = doc["@context"]
-    except KeyError:
-        raise SyntaxError("The API Documentation must have [@context]")
-    try:
-        possibleStatus = doc["possibleStatus"]
-    except KeyError:
-        raise SyntaxError("The API Documentation must have [possibleStatus]")
+    doc_keys = {
+        "description" : False,
+        "title" : False,
+        "supportedClass" : False,
+        "@context" : False,
+        "possibleStatus" : False
+    }
+    result = {}
+    for k, literal in doc_keys.items():
+        result[k] = input_key_check(doc, k, "doc", literal)
 
     # EntryPoint object
-    entrypoint_obj = getEntrypoint(doc)     # getEntrypoint checks if all classes have @id
+    entrypoint_obj = get_entrypoint(doc)     # getEntrypoint checks if all classes have @id
 
     # Main doc object
     if HYDRUS_SERVER_URL is not None and API_NAME is not None:
-        apidoc = HydraDoc(API_NAME, title, desc, API_NAME, HYDRUS_SERVER_URL)
+        apidoc = HydraDoc(API_NAME, result["title"], result["description"], API_NAME, HYDRUS_SERVER_URL)
     else:
-        apidoc = HydraDoc(entrypoint, title, desc, entrypoint, base_url)
+        apidoc = HydraDoc(entrypoint, result["title"], result["description"], entrypoint, base_url)
 
     # additional context entries
-    for entry in context:
-        apidoc.add_to_context(entry, context[entry])
+    for entry in result["@context"]:
+        apidoc.add_to_context(entry, result["@context"][entry])
 
     # add all parsed_classes
-    for class_ in supportedClass:
-        class_obj, collection = createClass(entrypoint_obj, class_)
+    for class_ in result["supportedClass"]:
+        class_obj, collection = create_class(entrypoint_obj, class_)
         if class_obj:
             apidoc.add_supported_class(class_obj, collection=collection)
 
     # add possibleStatus
-    for status in possibleStatus:
-        status_obj = createStatus(status)
+    for status in result["possibleStatus"]:
+        status_obj = create_status(status)
         apidoc.add_possible_status(status_obj)
 
     apidoc.add_baseResource()
@@ -74,7 +100,7 @@ def createDoc(doc, HYDRUS_SERVER_URL=None, API_NAME=None):
     return apidoc
 
 
-def createClass(entrypoint, class_dict):
+def create_class(entrypoint: Dict[str, Any], class_dict: Dict[str, Any]) -> Tuple[HydraClass, bool]:
     """Create HydraClass objects for classes in the API Documentation."""
     # Base classes not used
     exclude_list = ['http://www.w3.org/ns/hydra/core#Resource',
@@ -83,30 +109,23 @@ def createClass(entrypoint, class_dict):
     id_ = class_dict["@id"]
     if id_ in exclude_list:
         return None, None
-    matchObj = re.match(r'vocab:(.*)', id_, re.M | re.I)
-    if matchObj:
-        id_ = matchObj.group(1)
+    match_obj = re.match(r'vocab:(.*)', id_, re.M | re.I)
+    if match_obj:
+        id_ = match_obj.group(1)
+
+    doc_keys = {
+        "supportedProperty" : False,
+        "title" : False,
+        "description" : False,
+        "supportedOperation" : False
+    }
 
-    # Syntax checks
-    try:
-        supportedProperty = class_dict["supportedProperty"]
-    except KeyError:
-        raise SyntaxError("Class must have [supportedProperty]")
-    try:
-        title = class_dict["title"]
-    except KeyError:
-        raise SyntaxError("Class must have [title]")
-    try:
-        desc = class_dict["description"]
-    except KeyError:
-        raise SyntaxError("Class must have [description]")
-    try:
-        supportedOperation = class_dict["supportedOperation"]
-    except KeyError:
-        raise SyntaxError("Class must have [supportedOperation]")
+    result = {}
+    for k, literal in doc_keys.items():
+        result[k] = input_key_check(class_dict, k, "class_dict", literal)
 
     # See if class_dict is a Collection Class
-    collection = re.match(r'(.*)Collection(.*)', title, re.M | re.I)
+    collection = re.match(r'(.*)Collection(.*)', result["title"], re.M | re.I) #type: Union[Match[Any], bool]
     if collection:
         return None, None
 
@@ -117,22 +136,22 @@ def createClass(entrypoint, class_dict):
     collection = collection_in_endpoint(class_dict, entrypoint)
 
     # Create the HydraClass object
-    class_ = HydraClass(id_, title, desc, endpoint=endpoint)
+    class_ = HydraClass(id_, result["title"], result["description"], endpoint=endpoint)
 
     # Add supportedProperty for the Class
-    for prop in supportedProperty:
-        prop_obj = createProperty(prop)
+    for prop in result["supportedProperty"]:
+        prop_obj = create_property(prop)
         class_.add_supported_prop(prop_obj)
 
     # Add supportedOperation for the Class
-    for op in supportedOperation:
-        op_obj = createOperation(op)
+    for op in result["supportedOperation"]:
+        op_obj = create_operation(op)
         class_.add_supported_op(op_obj)
 
     return class_, collection
 
 
-def getEntrypoint(doc):
+def get_entrypoint(doc: Dict[str, Any]) -> Dict[str, Any]:
     """Find and return the entrypoint object in the doc."""
     # Search supportedClass
     for class_ in doc["supportedClass"]:
@@ -142,15 +161,15 @@ def getEntrypoint(doc):
         except KeyError:
             raise SyntaxError("Each supportedClass must have [@id]")
         # Match with regular expression
-        matchObj = re.match(r'vocab:(.*)EntryPoint', class_id)
+        match_obj = re.match(r'vocab:(.*)EntryPoint', class_id)
         # Return the entrypoint object
-        if matchObj:
+        if match_obj:
             return class_
     # If not found, raise error
     raise SyntaxError("No EntryPoint class found")
 
 
-def convert_literal(literal):
+def convert_literal(literal: Any) -> Optional[Union[bool, str]]:
     """Convert JSON literals to Python ones."""
     # Map for the literals
     map_ = {
@@ -163,8 +182,7 @@ def convert_literal(literal):
         # Check if the literal is valid
         if literal in map_:
             return map_[literal]
-        else:
-            return literal
+        return literal
     elif isinstance(literal, (bool,)) or literal is None:
         return literal
     else:
@@ -172,45 +190,36 @@ def convert_literal(literal):
         raise TypeError("Literal not recognised")
 
 
-def createProperty(supported_prop):
+def create_property(supported_prop: Dict[str, Any]) -> HydraClassProp:
     """Create a HydraClassProp object from the supportedProperty."""
     # Syntax checks
-    try:
-        uri = supported_prop["property"]
-    except KeyError:
-        raise SyntaxError("Property must have [property]")
-    try:
-        title = supported_prop["title"]
-    except KeyError:
-        raise SyntaxError("Property must have [title]")
-    try:
-        read = convert_literal(supported_prop["readonly"])
-    except KeyError:
-        raise SyntaxError("Property must have [readonly]")
-    try:
-        write = convert_literal(supported_prop["writeonly"])
-    except KeyError:
-        raise SyntaxError("Property must have [writeonly]")
-    try:
-        required = convert_literal(supported_prop["required"])
-    except KeyError:
-        raise SyntaxError("Property must have [required]")
+
+    doc_keys = {
+        "property" : False,
+        "title": False,
+        "readonly": True,
+        "writeonly": True,
+        "required": True
+    }
+    result = {}
+    for k, literal in doc_keys.items():
+        result[k] = input_key_check(supported_prop, k, "supported_prop", literal)
     # Create the HydraClassProp object
-    prop = HydraClassProp(uri, title, required=required, read=read, write=write)
+    prop = HydraClassProp(result["property"], result["title"], required=result["required"], read=result["readonly"], write=result["writeonly"])
     return prop
 
 
-def class_in_endpoint(class_, entrypoint):
+def class_in_endpoint(class_: Dict[str, Any], entrypoint: Dict[str, Any]) -> bool:
     """Check if a given class is in the EntryPoint object as a class."""
     regex = r'(vocab:)?(.*)EntryPoint/(.*/)?' + re.escape(class_["title"]) + r'$'
     # Check supportedProperty for the EntryPoint
     try:
-        supportedProperty = entrypoint["supportedProperty"]
+        supported_property = entrypoint["supportedProperty"]
     except KeyError:
         raise SyntaxError("EntryPoint must have [supportedProperty]")
 
     # Check all endpoints in supportedProperty
-    for prop in supportedProperty:
+    for prop in supported_property:
         # Syntax checks
         try:
             property_ = prop["property"]
@@ -221,23 +230,23 @@ def class_in_endpoint(class_, entrypoint):
         except KeyError:
             raise SyntaxError("property must have [@id]")
         # Match the title with regular expression
-        matchObj = re.match(regex, id_)
-        if matchObj:
+        match_obj = re.match(regex, id_)
+        if match_obj:
             return True
     return False
 
 
-def collection_in_endpoint(class_, entrypoint):
+def collection_in_endpoint(class_: Dict[str, Any], entrypoint: Dict[str, Any]) -> bool:
     """Check if a given class is in the EntryPoint object as a collection."""
     regex = r'(vocab:)?(.*)EntryPoint/(.*/)?' + class_["title"] + "Collection"
     # Check supportedProperty for the EntryPoint
     try:
-        supportedProperty = entrypoint["supportedProperty"]
+        supported_property = entrypoint["supportedProperty"]
     except KeyError:
         raise SyntaxError("EntryPoint must have [supportedProperty]")
 
     # Check all endpoints in supportedProperty
-    for prop in supportedProperty:
+    for prop in supported_property:
         # Syntax checks
         try:
             property_ = prop["property"]
@@ -248,60 +257,47 @@ def collection_in_endpoint(class_, entrypoint):
         except KeyError:
             raise SyntaxError("property must have [@id]")
         # Match the title with regular expression
-        matchObj = re.match(regex, id_)
-        if matchObj:
+        match_obj = re.match(regex, id_)
+        if match_obj:
             return True
     return False
 
 
-def createOperation(supported_op):
+def create_operation(supported_op: Dict[str, Any]) -> HydraClassOp:
     """Create a HyraClassOp object from the supportedOperation."""
     # Syntax checks
-    try:
-        name = supported_op["title"]
-    except KeyError:
-        raise SyntaxError("Operation must have [title]")
-    try:
-        method = supported_op["method"]
-    except KeyError:
-        raise SyntaxError("Operation must have [method]")
-    try:
-        expects = convert_literal(supported_op["expects"])
-    except KeyError:
-        raise SyntaxError("Operation must have [expects]")
-    try:
-        returns = convert_literal(supported_op["returns"])
-    except KeyError:
-        raise SyntaxError("Operation must have [returns]")
-    try:
-        status = supported_op["possibleStatus"]
-    except KeyError:
-        raise SyntaxError("Operation must have [possibleStatus]")
+    doc_keys = {
+        "title": False,
+        "method" : False,
+        "expects": True,
+        "returns": True,
+        "possibleStatus": False
+    }
+    result = {}
+    for k, literal in doc_keys.items():
+        result[k] = input_key_check(supported_op, k, "supported_op", literal)
+
     # Create the HydraClassOp object
-    op = HydraClassOp(name, method, expects, returns, status)
-    return op
+    op_ = HydraClassOp(result["title"], result["method"], result["expects"], result["returns"], result["possibleStatus"])
+    return op_
 
 
-def createStatus(possible_status):
+def create_status(possible_status: Dict[str, Any]) -> HydraStatus:
     """Create a HydraStatus object from the possibleStatus."""
     # Syntax checks
-    try:
-        title = possible_status["title"]
-    except KeyError:
-        raise SyntaxError("Status must have [title]")
-    try:
-        code = possible_status["statusCode"]
-    except KeyError:
-        raise SyntaxError("Status must have [statusCode]")
-    try:
-        description = convert_literal(possible_status["description"])
-    except KeyError:
-        raise SyntaxError("Status must have [description]")
+    doc_keys = {
+        "title": False,
+        "statusCode": False,
+        "description": True
+    }
+    result = {}
+    for k, literal in doc_keys.items():
+        result[k] = input_key_check(possible_status, k, "possible_status", literal)
     # Create the HydraStatus object
-    status = HydraStatus(code, title, description)
+    status = HydraStatus(result["statusCode"], result["title"], result["description"])
     return status
 
 
 if __name__ == "__main__":
-    api_doc = createDoc(sample_document.generate())
+    api_doc = create_doc(sample_document.generate())
     print(json.dumps(api_doc.generate(), indent=4, sort_keys=True))
diff --git a/hydrus/hydraspec/doc_writer.py b/hydrus/hydraspec/doc_writer.py
index 532c42d..0562196 100644
--- a/hydrus/hydraspec/doc_writer.py
+++ b/hydrus/hydraspec/doc_writer.py
@@ -1,23 +1,24 @@
 """API Doc templates generator."""
+from typing import Any, Dict, List, Optional, Union
 
 
 class HydraDoc():
     """Class for an API Doc."""
 
-    def __init__(self, API, title, desc, entrypoint, base_url):
+    def __init__(self, API: str, title: str, desc: str, entrypoint: str, base_url: str) -> None:
         """Initialize the APIDoc."""
         self.API = API
         self.title = title
         self.base_url = base_url
         self.context = Context(base_url + API)
-        self.parsed_classes = dict()
-        self.other_classes = list()
-        self.collections = dict()
-        self.status = list()
+        self.parsed_classes = dict() # type: Dict[str, Any]
+        self.other_classes = list() # type: List[HydraClass]
+        self.collections = dict() # type: Dict[str, Any]
+        self.status = list() # type: List[HydraStatus]
         self.entrypoint = HydraEntryPoint(base_url, entrypoint)
         self.desc = desc
 
-    def add_supported_class(self, class_, collection=False, collectionGet=True, collectionPost=True):
+    def add_supported_class(self, class_: 'HydraClass', collection: Union[bool, 'HydraCollection']=False, collectionGet: bool=True, collectionPost: bool=True) -> None:
         """Add a new supportedClass."""
         # self.doc["supportedClass"].append(class_.get())
         if not isinstance(class_, HydraClass):
@@ -34,29 +35,29 @@ class HydraDoc():
                 "collection": collection
             }
 
-    def add_possible_status(self, status):
+    def add_possible_status(self, status: 'HydraStatus') -> None:
         """Add a new possibleStatus."""
         if not isinstance(status, HydraStatus):
             raise TypeError("Type is not <HydraStatus>")
         self.status.append(status)
 
-    def add_baseCollection(self):
+    def add_baseCollection(self) -> None:
         """Add Collection class to the API Doc."""
         collection = HydraClass("http://www.w3.org/ns/hydra/core#Collection", "Collection", None)
         member = HydraClassProp("http://www.w3.org/ns/hydra/core#member", "members", False, False, None)
         collection.add_supported_prop(member)
         self.other_classes.append(collection)
 
-    def add_baseResource(self):
+    def add_baseResource(self) -> None:
         """Add Resource class to the API Doc."""
         resource = HydraClass("http://www.w3.org/ns/hydra/core#Resource", "Resource", None)
         self.other_classes.append(resource)
 
-    def add_to_context(self, key, value):
+    def add_to_context(self, key: str, value: Union[Dict[str, str], str]) -> None:
         """Add entries to the vocabs context."""
         self.context.add(key, value)
 
-    def gen_EntryPoint(self):
+    def gen_EntryPoint(self) -> None:
         """Generate the EntryPoint for the Hydra Doc."""
         # pdb.set_trace()
         for class_ in self.parsed_classes:
@@ -65,7 +66,7 @@ class HydraDoc():
         for collection in self.collections:
             self.entrypoint.add_Collection(self.collections[collection]["collection"])
 
-    def generate(self):
+    def generate(self) -> Dict[str, Any]:
         """Get the Hydra API Doc as a python dict."""
         parsed_classes = [self.parsed_classes[key]["class"] for key in self.parsed_classes]
         collections = [self.collections[key]["collection"] for key in self.collections]
@@ -84,31 +85,31 @@ class HydraDoc():
 class HydraClass():
     """Template for a new class."""
 
-    def __init__(self, id_, title, desc,  endpoint=False, sub_classof=None):
+    def __init__(self, id_: str, title: str, desc: str,  endpoint: bool=False, sub_classof: None=None) -> None:
         """Initialize the Hydra_Class."""
         self.id_ = id_ if "http" in id_ else "vocab:"+id_
         self.title = title
         self.desc = desc
         self.parents = None
         self.endpoint = endpoint
-        self.supportedProperty = list()
-        self.supportedOperation = list()
+        self.supportedProperty = list() # type: List
+        self.supportedOperation = list() # type: List
         if sub_classof is not None:
             self.parents = sub_classof
 
-    def add_supported_prop(self, prop):
+    def add_supported_prop(self, prop: Union['HydraClassProp', 'EntryPointClass', 'EntryPointCollection']) -> None:
         """Add a new supportedProperty."""
         if not isinstance(prop, (HydraClassProp, EntryPointClass, EntryPointCollection)):
             raise TypeError("Type is not <HydraClassProp>")
         self.supportedProperty.append(prop)
 
-    def add_supported_op(self, op):
+    def add_supported_op(self, op: Union['EntryPointOp', 'HydraClassOp']) -> None:
         """Add a new supportedOperation."""
         if not isinstance(op, (HydraClassOp, EntryPointOp)):
             raise TypeError("Type is not <HydraClassOp>")
         self.supportedOperation.append(op)
 
-    def generate(self):
+    def generate(self) -> Dict[str, Any]:
         """Get the Hydra class as a python dict."""
         class_ = {
             "@id": self.id_,
@@ -126,7 +127,14 @@ class HydraClass():
 class HydraClassProp():
     """Template for a new property."""
 
-    def __init__(self, prop, title, read, write, required, desc=""):
+    def __init__(self,
+                 prop: str,
+                 title: str,
+                 read: bool,
+                 write: bool,
+                 required: bool,
+                 desc: str="",
+                 ) -> None:
         """Initialize the Hydra_Prop."""
         self.prop = prop
         self.title = title
@@ -135,7 +143,7 @@ class HydraClassProp():
         self.required = required
         self.desc = desc
 
-    def generate(self):
+    def generate(self) -> Dict[str, Any]:
         """Get the Hydra prop as a python dict."""
         prop = {
           "@type": "SupportedProperty",
@@ -153,7 +161,13 @@ class HydraClassProp():
 class HydraClassOp():
     """Template for a new supportedOperation."""
 
-    def __init__(self, title, method, expects, returns, status):
+    def __init__(self,
+                 title: str,
+                 method: str,
+                 expects: Optional[str],
+                 returns: Optional[str],
+                 status: List[Dict[str, Any]],
+                 ) -> None:
         """Initialize the Hydra_Prop."""
         self.title = title
         self.method = method
@@ -161,7 +175,7 @@ class HydraClassOp():
         self.returns = returns
         self.status = status
 
-    def get_type(self, method):
+    def get_type(self, method: str) -> str:
         """Return @type for op based on method type."""
         if method == "POST":
             return "http://schema.org/UpdateAction"
@@ -172,7 +186,7 @@ class HydraClassOp():
         else:
             return "http://schema.org/FindAction"
 
-    def generate(self):
+    def generate(self) -> Dict[str, Any]:
         """Get the Hydra op as a python dict."""
         op = {
                 "@type": self.get_type(self.method),
@@ -188,11 +202,11 @@ class HydraClassOp():
 class HydraCollection():
     """Class for Hydra Collection."""
 
-    def __init__(self, class_, get=True, post=True):
+    def __init__(self, class_: HydraClass, get: bool=True, post: bool=True) -> None:
         """Generate Collection for a given class."""
         self.class_ = class_
         self.name = class_.title + "Collection"
-        self.supportedOperation = list()
+        self.supportedOperation = list() # type: List
         self.supportedProperty = [HydraClassProp("http://www.w3.org/ns/hydra/core#member",
                                                  "members",
                                                  False, False, False,
@@ -215,7 +229,7 @@ class HydraCollection():
                                         )
             self.supportedOperation.append(post_op)
 
-    def generate(self):
+    def generate(self) -> Dict[str, Any]:
         """Get as a python dict."""
         collection = {
             "@id": "vocab:%s" % (self.name,),
@@ -232,7 +246,15 @@ class HydraCollection():
 class HydraCollectionOp():
     """Operation class for Collection operations."""
 
-    def __init__(self, id_, type_, method, desc, expects, returns, status=[]):
+    def __init__(self,
+                 id_: str,
+                 type_: str,
+                 method: str,
+                 desc: str,
+                 expects: Optional[str],
+                 returns: str,
+                 status: List[Dict[str, Any]] =[],
+                 ) -> None:
         """Create method."""
         self.id_ = id_
         self.type_ = type_
@@ -242,7 +264,7 @@ class HydraCollectionOp():
         self.expects = expects
         self.status = status
 
-    def generate(self):
+    def generate(self) -> Dict[str, Any]:
         """Get as a Python dict."""
         object_ = {
             "@id": self.id_,
@@ -259,7 +281,7 @@ class HydraCollectionOp():
 class HydraEntryPoint():
     """Template for a new entrypoint."""
 
-    def __init__(self, base_url, entrypoint):
+    def __init__(self, base_url: str, entrypoint: str) -> None:
         """Initialize the Entrypoint."""
         self.url = base_url
         self.api = entrypoint
@@ -267,7 +289,7 @@ class HydraEntryPoint():
         self.entrypoint.add_supported_op(EntryPointOp("_:entry_point", "GET", "The APIs main entry point.", None, None, "vocab:EntryPoint"))
         self.context = Context(base_url+entrypoint, entrypoint=self)
 
-    def add_Class(self, class_):
+    def add_Class(self, class_: HydraClass) -> None:
         """Add supportedProperty to the EntryPoint."""
         if not isinstance(class_, HydraClass):
             raise TypeError("Type is not <HydraClass>")
@@ -275,7 +297,7 @@ class HydraEntryPoint():
         self.entrypoint.add_supported_prop(entrypoint_class)
         self.context.add(entrypoint_class.name, {"@id": entrypoint_class.id_, "@type": "@id"})
 
-    def add_Collection(self, collection):
+    def add_Collection(self, collection: HydraCollection) -> None:
         """Add supportedProperty to the EntryPoint."""
         if not isinstance(collection, HydraCollection):
             raise TypeError("Type is not <HydraCollection>")
@@ -283,11 +305,11 @@ class HydraEntryPoint():
         self.entrypoint.add_supported_prop(entrypoint_collection)
         self.context.add(entrypoint_collection.name, {"@id": entrypoint_collection.id_, "@type": "@id"})
 
-    def generate(self):
+    def generate(self) -> Dict[str, Any]:
         """Get as a Python dict."""
         return self.entrypoint.generate()
 
-    def get(self):
+    def get(self) -> Dict[str, str]:
         """Create the EntryPoint object to be returnd for the get function."""
         object_ = {
             "@context": "/"+self.api+"/"+"contexts/EntryPoint.jsonld",
@@ -303,13 +325,13 @@ class HydraEntryPoint():
 class EntryPointCollection():
     """Class for a Collection Entry to the EntryPoint object."""
 
-    def __init__(self, collection):
+    def __init__(self, collection: HydraCollection) -> None:
         """Create method."""
         self.name = collection.name
         self.supportedOperation = collection.supportedOperation
         self.id_ = "vocab:EntryPoint/" + self.name
 
-    def generate(self):
+    def generate(self) -> Dict[str, Any]:
         """Get as a python dict."""
         object_ = {
             "property": {
@@ -326,7 +348,7 @@ class EntryPointCollection():
             "required": None,
             "readonly": True,
             "writeonly": False
-        }
+        } # type: Dict[str, Any]
         for op in self.supportedOperation:
             operation = EntryPointOp("_:"+op.id_.lower(), op.method, op.desc, op.expects, op.returns, op.status, type_=op.type_)
             object_["property"]["supportedOperation"].append(operation.generate())
@@ -336,14 +358,14 @@ class EntryPointCollection():
 class EntryPointClass():
     """Class for a Operation Entry to the EntryPoint object."""
 
-    def __init__(self, class_):
+    def __init__(self, class_: HydraClass) -> None:
         """Create method."""
         self.name = class_.title
         self.desc = class_.desc
         self.supportedOperation = class_.supportedOperation
         self.id_ = "vocab:EntryPoint/" + self.name
 
-    def generate(self):
+    def generate(self) -> Dict[str, Any]:
         """Get as Python Dict."""
         object_ = {
             "property": {
@@ -360,7 +382,7 @@ class EntryPointClass():
             "required": None,
             "readonly": True,
             "writeonly": False
-        }
+        } # type: Dict[str, Any]
         for op in self.supportedOperation:
             operation = EntryPointOp("_:"+op.title.lower(), op.method, None, op.expects, op.returns, op.status, label=op.title)
             object_["property"]["supportedOperation"].append(operation.generate())
@@ -370,7 +392,16 @@ class EntryPointClass():
 class EntryPointOp():
     """supportedOperation for EntryPoint."""
 
-    def __init__(self, id_, method, desc, expects, returns, statusCodes=[], type_=None, label=""):
+    def __init__(self,
+                 id_: str,
+                 method: str,
+                 desc: str,
+                 expects: Optional[str],
+                 returns: str,
+                 statusCodes: Union[str, List[Dict[str, Any]]]=[],
+                 type_: Optional[str]=None,
+                 label: str="",
+                 ) -> None:
         """Create method."""
         self.id_ = id_
         self.method = method
@@ -381,7 +412,7 @@ class EntryPointOp():
         self.label = label
         self.type_ = type_
 
-    def get_type(self, method):
+    def get_type(self, method: str) -> str:
         """Return @type for op based on method type."""
         if method == "POST":
             return "http://schema.org/UpdateAction"
@@ -392,7 +423,7 @@ class EntryPointOp():
         else:
             return "http://schema.org/FindAction"
 
-    def generate(self):
+    def generate(self) -> Dict[str, Any]:
         """Get as Python Dict."""
         prop = {
             "@id": self.id_,
@@ -413,13 +444,13 @@ class EntryPointOp():
 class HydraStatus():
     """Class for possibleStatus in Hydra Doc."""
 
-    def __init__(self, code, title, desc):
+    def __init__(self, code: str, title: str, desc: str) -> None:
         """Create method."""
         self.code = code
         self.title = title
         self.desc = desc
 
-    def generate(self):
+    def generate(self) -> Dict[str, Any]:
         """Get as Python dict."""
         status = {
           "@context": "http://www.w3.org/ns/hydra/context.jsonld",
@@ -434,7 +465,13 @@ class HydraStatus():
 class Context():
     """Class for JSON-LD context."""
 
-    def __init__(self, address, adders={}, class_=None, collection=None, entrypoint=None):
+    def __init__(self,
+                 address: str,
+                 adders: Dict={},
+                 class_: Optional[HydraClass]=None,
+                 collection: Optional[HydraCollection]=None,
+                 entrypoint: Optional[HydraEntryPoint]=None,
+                 ) -> None:
         """Initialize context."""
         # NOTE: adders is a dictionary containing additional context elements to the base Hydra context
         if class_ is not None:
@@ -443,7 +480,7 @@ class Context():
                 "hydra": "http://www.w3.org/ns/hydra/core#",
                 "members": "http://www.w3.org/ns/hydra/core#member",
                 "object": "http://schema.org/object",
-            }
+            } # type: Dict[str, Any]
             self.context[class_.title] = class_.id_
             for prop in class_.supportedProperty:
                 self.context[prop.title] = prop.prop
@@ -510,7 +547,7 @@ class Context():
                 }
             }
 
-    def createContext(self, object_):
+    def createContext(self, object_: Dict[str, Any]) -> None:
         """Create the context for the given object."""
         if isinstance(object_, HydraClass):
             self.add(object_.title, object_.id)
@@ -520,10 +557,10 @@ class Context():
             self.add(object_.name, "vocab:"+object_.name)
             self.add(object_.class_.title, object_.class_.id)
 
-    def generate(self):
+    def generate(self) -> Dict[str, Any]:
         """Get as a python dict."""
         return self.context
 
-    def add(self, key, value):
+    def add(self, key: str, value: Union[Dict[str, str], str]) -> None:
         """Add entry to context."""
         self.context[key] = value
diff --git a/hydrus/hydraspec/doc_writer_sample.py b/hydrus/hydraspec/doc_writer_sample.py
index 721247a..f32593f 100644
--- a/hydrus/hydraspec/doc_writer_sample.py
+++ b/hydrus/hydraspec/doc_writer_sample.py
@@ -1,22 +1,22 @@
 """Sample to create Hydra APIDocumentation using doc_writer."""
 
 from hydrus.hydraspec.doc_writer import HydraDoc, HydraClass, HydraClassProp, HydraClassOp
+from typing import Any, Dict, Union
 
 """Creating the HydraDoc object, this is the primary class for the Doc"""
-API_NAME = "demoapi"                # Name of the API
+API_NAME = "api"                # Name of the API, will serve as EntryPoint
 BASE_URL = "https://hydrus.com/"    # The base url at which the API is hosted
-ENTRY_POINT = "api"                 # The entrypoint where the API will  be accessed
 # NOTE: The API will be accessible at BASE_URL + ENTRY_POINT (http://hydrus.com/api/)
 
 api_doc = HydraDoc(API_NAME,
                    "Title for the API Documentation",
                    "Description for the API Documentation",
-                   ENTRY_POINT,
+                   API_NAME,
                    BASE_URL)
 
 
 """Creating classes for the API"""
-class_uri = "http://hydrus.com/dummyClass"      # URI of class for the HydraClass
+class_uri = "dummyClass"      # URI of class for the HydraClass
 class_title = "dummyClass"                      # Title of the Class
 class_description = "A dummyClass for demo"     # Description of the class
 
@@ -26,13 +26,13 @@ class_ = HydraClass(class_uri, class_title, class_description, endpoint=False)
 
 
 """Create new properties for the class"""
-prop1_uri = "http://hydrus.com/prop1"   # The URI of the class of the property
+prop1_uri = "http://props.hydrus.com/prop1"   # The URI of the class of the property
 prop1_title = "Prop1"                   # Title of the property
 
 dummyProp1 = HydraClassProp(prop1_uri, prop1_title, required=False, read=False, write=True)
 
 
-prop2_uri = "http://hydrus.com/prop2"
+prop2_uri = "http://props.hydrus.com/prop2"
 prop2_title = "Prop2"
 
 dummyProp2 = HydraClassProp(prop1_uri, prop2_title, required=False, read=False, write=True)
@@ -76,14 +76,14 @@ api_doc.gen_EntryPoint()        # Generates the EntryPoint object for the Doc us
 
 
 """Generate the complete API Documentation"""
-doc = api_doc.generate()        # Returns the entire API Documentation as a Python dict
+doc = api_doc.generate() # type: Union[Dict[str, Any], str]       # Returns the entire API Documentation as a Python dict
 
 if __name__ == "__main__":
     """Print the complete sample Doc in doc_writer_sample_output.py."""
     import json
 
     dump = json.dumps(doc, indent=4, sort_keys=True)
-    doc = '''"""\nGenerated API Documentation sample using doc_writer_sample.py.\n\ndoc = %s\n"""''' % dump
+    doc = '''"""Generated API Documentation sample using doc_writer_sample.py."""\n\ndoc = %s\n''' % dump
     # Python does not recognise null, true and false in JSON format, convert them to string
     doc = doc.replace('true', '"true"')
     doc = doc.replace('false', '"false"')
diff --git a/hydrus/hydraspec/doc_writer_sample_output.py b/hydrus/hydraspec/doc_writer_sample_output.py
index f5c33ce..4a4aed4 100644
--- a/hydrus/hydraspec/doc_writer_sample_output.py
+++ b/hydrus/hydraspec/doc_writer_sample_output.py
@@ -1,5 +1,4 @@
-"""
-Generated API Documentation sample using doc_writer_sample.py.
+"""Generated API Documentation sample using doc_writer_sample.py."""
 
 doc = {
     "@context": {
@@ -43,16 +42,16 @@ doc = {
         "supportedOperation": "hydra:supportedOperation",
         "supportedProperty": "hydra:supportedProperty",
         "title": "hydra:title",
-        "vocab": "https://hydrus.com/demoapi/vocab#",
+        "vocab": "https://hydrus.com/api/vocab#",
         "writeonly": "hydra:writeonly"
     },
-    "@id": "https://hydrus.com/demoapi/vocab",
+    "@id": "https://hydrus.com/api/vocab",
     "@type": "ApiDocumentation",
     "description": "Description for the API Documentation",
     "possibleStatus": [],
     "supportedClass": [
         {
-            "@id": "http://hydrus.com/dummyClass",
+            "@id": "vocab:dummyClass",
             "@type": "hydra:Class",
             "description": "A dummyClass for demo",
             "supportedOperation": [
@@ -73,7 +72,7 @@ doc = {
             "supportedProperty": [
                 {
                     "@type": "SupportedProperty",
-                    "property": "http://hydrus.com/prop1",
+                    "property": "http://props.hydrus.com/prop1",
                     "readonly": "false",
                     "required": "false",
                     "title": "Prop1",
@@ -81,7 +80,7 @@ doc = {
                 },
                 {
                     "@type": "SupportedProperty",
-                    "property": "http://hydrus.com/prop1",
+                    "property": "http://props.hydrus.com/prop1",
                     "readonly": "false",
                     "required": "false",
                     "title": "Prop2",
@@ -123,7 +122,7 @@ doc = {
             "supportedOperation": [
                 {
                     "@id": "_:dummyclass_collection_retrieve",
-                    "@type": "hydra:Operation",
+                    "@type": "http://schema.org/FindAction",
                     "description": "Retrieves all dummyClass entities",
                     "expects": "null",
                     "method": "GET",
@@ -134,9 +133,9 @@ doc = {
                     "@id": "_:dummyclass_create",
                     "@type": "http://schema.org/AddAction",
                     "description": "Create new dummyClass entitity",
-                    "expects": "http://hydrus.com/dummyClass",
+                    "expects": "vocab:dummyClass",
                     "method": "PUT",
-                    "returns": "http://hydrus.com/dummyClass",
+                    "returns": "vocab:dummyClass",
                     "statusCodes": [
                         {
                             "description": "If the dummyClass entity was created successfully.",
@@ -165,7 +164,7 @@ doc = {
             "supportedOperation": [
                 {
                     "@id": "_:entry_point",
-                    "@type": "hydra:Operation",
+                    "@type": "http://schema.org/FindAction",
                     "description": "The APIs main entry point.",
                     "expects": "null",
                     "method": "GET",
@@ -187,7 +186,7 @@ doc = {
                         "supportedOperation": [
                             {
                                 "@id": "_:_:dummyclass_collection_retrieve",
-                                "@type": "hydra:Operation",
+                                "@type": "http://schema.org/FindAction",
                                 "description": "Retrieves all dummyClass entities",
                                 "expects": "null",
                                 "method": "GET",
@@ -198,9 +197,9 @@ doc = {
                                 "@id": "_:_:dummyclass_create",
                                 "@type": "http://schema.org/AddAction",
                                 "description": "Create new dummyClass entitity",
-                                "expects": "http://hydrus.com/dummyClass",
+                                "expects": "vocab:dummyClass",
                                 "method": "PUT",
-                                "returns": "http://hydrus.com/dummyClass",
+                                "returns": "vocab:dummyClass",
                                 "statusCodes": [
                                     {
                                         "description": "If the dummyClass entity was created successfully.",
@@ -220,4 +219,3 @@ doc = {
     ],
     "title": "Title for the API Documentation"
 }
-"""
\ No newline at end of file
diff --git a/hydrus/utils.py b/hydrus/utils.py
index 5c80a8f..db8a79a 100644
--- a/hydrus/utils.py
+++ b/hydrus/utils.py
@@ -1,115 +1,216 @@
-"""Pluggable utilities for Hydrus."""
+"""
+Pluggable utilities for Hydrus.
+===============================
+Imports :
+contextlib.contextmanager : This function is a decorator that can be used to
+define a factory function for with statement context managers, without needing
+to create a class or separate __enter__() and __exit__() methods.
+Ref- https://docs.python.org/2/library/contextlib.html#contextlib.contextmanager
+flask.appcontext_pushed : Signal is sent when an application context is pushed.
+The sender is the application.
+Ref- http://flask.pocoo.org/docs/0.12/api/#flask.appcontext_pushed
+Ref- https://speakerdeck.com/mitsuhiko/advanced-flask-patterns-1
+flask.g : Used to attach values to global variables
+doc_writer_sample : Sample script used to create Hydra APIDocumentation
+hydrus.hydraspec.engine : An SQLalchemy DB engine
+sqlalchemy.orm.sessionmaker : Used to create a SQLalchemy Session
+sqlalchemy.orm.session.Session : SQLalchemy Session class
+Ref- http://docs.sqlalchemy.org/en/latest/orm/session_basics.html
+hydrus.hydraspec.doc_writer.HydraDoc : Class for Hydra Documentation
+"""
 
 from contextlib import contextmanager
 from flask import appcontext_pushed
 from flask import g
 from hydrus.hydraspec import doc_writer_sample
 from hydrus.data.db_models import engine
-from sqlalchemy.orm import sessionmaker
+from sqlalchemy.orm import sessionmaker, scoped_session
 from sqlalchemy.orm.session import Session
 from hydrus.hydraspec.doc_writer import HydraDoc
+from flask.app import Flask
+from typing import Any, Iterator
 
 
 @contextmanager
-def set_session(application, DB_SESSION):
-    """Set the database session for the app. Must be of type <hydrus.hydraspec.doc_writer.HydraDoc>."""
-    if not isinstance(DB_SESSION, Session):
-        raise TypeError("The API Doc is not of type <sqlalchemy.orm.session.Session>")
+def set_authentication(application: Flask, authentication: bool) -> Iterator:
+    """
+    Set the whether API needs to be authenticated or not (before it is run in main.py).
+
+    :param application: Flask app object
+            <flask.app.Flask>
+    :param authentication : Bool. API Auth needed or not
+            <bool>
+    """
+    if not isinstance(authentication, bool):
+        raise TypeError("Authentication flag must be of type <bool>")
 
-    def handler(sender, **kwargs):
-        g.dbsession = DB_SESSION
+    def handler(sender: Flask, **kwargs: Any) -> None:
+        g.authentication_ = authentication
     with appcontext_pushed.connected_to(handler, application):
         yield
 
 
-@contextmanager
-def set_hydrus_server_url(application, server_url):
-    """Set the server URL for the app. Must be of type <str>."""
-    if not isinstance(server_url, str):
-        raise TypeError("The server_url is not of type <str>")
-
-    def handler(sender, **kwargs):
-        g.hydrus_server_url = server_url
-    with appcontext_pushed.connected_to(handler, application):
-        yield
+def get_authentication() -> bool:
+    """
+    Check whether API needs to be authenticated or not.
+    Return and sets False if not found.
+    :return authentication : Bool. API Auth needed or not
+            <bool>
+    """
+    try:
+        authentication = getattr(g, 'authentication_')
+    except AttributeError:
+        authentication = False
+        g.authentication_ = authentication
+    return authentication
 
 
 @contextmanager
-def set_api_name(application, api_name):
-    """Set the server name or EntryPoint for the app. Must be of type <str>."""
+def set_api_name(application: Flask, api_name: str) -> Iterator:
+    """
+    Set the server name or EntryPoint for the app (before it is run in main.py).
+    :param application: Flask app object
+            <flask.app.Flask>
+    :param api_name : API/Server name or EntryPoint
+            <str>
+    """
     if not isinstance(api_name, str):
         raise TypeError("The api_name is not of type <str>")
 
-    def handler(sender, **kwargs):
+    def handler(sender: Flask, **kwargs: Any) -> None:
         g.api_name = api_name
     with appcontext_pushed.connected_to(handler, application):
         yield
 
 
+def get_api_name() -> str:
+    """
+    Get the server API name.
+    Returns an sets "api" as api_name if not found.
+    :return api_name : API/Server name or EntryPoint
+            <str>
+    """
+    try:
+        api_name = getattr(g, 'api_name')
+    except AttributeError:
+        api_name = "api"
+        g.doc = api_name
+    return api_name
+
+
 @contextmanager
-def set_doc(application, APIDOC):
-    """Set the API Documentation for the app. Must be of type <hydrus.hydraspec.doc_writer.HydraDoc>."""
+def set_doc(application: Flask, APIDOC: HydraDoc) -> Iterator:
+    """
+    Set the API Documentation for the app (before it is run in main.py).
+    :param application: Flask app object
+            <flask.app.Flask>
+    :param APIDOC : Hydra Documentation object
+            <hydrus.hydraspec.doc_writer.HydraDoc>
+    """
     if not isinstance(APIDOC, HydraDoc):
-        raise TypeError("The API Doc is not of type <hydrus.hydraspec.doc_writer.HydraDoc>")
+        raise TypeError(
+            "The API Doc is not of type <hydrus.hydraspec.doc_writer.HydraDoc>")
 
-    def handler(sender, **kwargs):
+    def handler(sender: Flask, **kwargs: Any) -> None:
         g.doc = APIDOC
     with appcontext_pushed.connected_to(handler, application):
         yield
 
+@contextmanager        
+def set_token(application: Flask, token: bool) -> Iterator:
+    """Set whether API needs to implement token based authentication."""
+    if not isinstance(token, bool):
+        raise TypeError("Token flag must be of type <bool>")
 
-@contextmanager
-def set_authentication(application, authentication):
-    """Set the wether API needs to be authenticated or not."""
-    if not isinstance(authentication, bool):
-        raise TypeError("Authentication flag must be of type <bool>")
-
-    def handler(sender, **kwargs):
-        g.authentication_ = authentication
+    def handler(sender: Flask, **kwargs: Any) -> None:
+        g.token_ = token
     with appcontext_pushed.connected_to(handler, application):
         yield
-
-
-def get_doc():
-    """Get the server API Documentation."""
-    apidoc = getattr(g, 'doc', None)
-    if apidoc is None:
-        apidoc = doc_writer_sample.api_doc
-        g.doc = apidoc
+        
+def get_doc() -> HydraDoc:
+    """
+    Get the server API Documentation.
+    Returns and sets doc_writer_sample.api_doc if not found.
+    :return apidoc : Hydra Documentation object
+            <hydrus.hydraspec.doc_writer.HydraDoc>
+    """
+    try:
+        apidoc = getattr(g, 'doc')
+    except AttributeError:
+        g.doc = apidoc = doc_writer_sample.api_doc
     return apidoc
 
 
-def get_authentication():
+def get_token() -> bool:
     """Check wether API needs to be authenticated or not."""
-    authentication = getattr(g, 'authentication_', None)
-    if authentication is None:
-        authentication = False
-        g.authentication_ = authentication
-    return authentication
-
-
-def get_api_name():
-    """Get the server API name."""
-    api_name = getattr(g, 'api_name', None)
-    if api_name is None:
-        api_name = "api"
-        g.doc = api_name
-    return api_name
+    try:
+        token = getattr(g, 'token_')
+    except AttributeError:
+        token = False
+        g.token_ = token
+    return token
+  
+@contextmanager
+def set_hydrus_server_url(application: Flask, server_url: str) -> Iterator:
+    """
+    Set the server URL for the app (before it is run in main.py).
+    :param application: Flask app object
+            <flask.app.Flask>
+    :param server_url : Server URL
+            <str>
+    """
+    if not isinstance(server_url, str):
+        raise TypeError("The server_url is not of type <str>")
+    def handler(sender: Flask, **kwargs: Any) -> None:
+        g.hydrus_server_url = server_url
+    with appcontext_pushed.connected_to(handler, application):
+        yield
 
 
-def get_hydrus_server_url():
-    """Get the server URL."""
-    hydrus_server_url = getattr(g, 'hydrus_server_url', None)
-    if hydrus_server_url is None:
+def get_hydrus_server_url() -> str:
+    """
+    Get the server URL.
+    Returns and sets "http://localhost/" if not found.
+    :return hydrus_server_url : Server URL
+            <str>
+    """
+    try:
+        hydrus_server_url = getattr(g, 'hydrus_server_url')
+    except AttributeError:
         hydrus_server_url = "http://localhost/"
         g.hydrus_server_url = hydrus_server_url
     return hydrus_server_url
 
 
-def get_session():
-    """Get the Database Session for the server."""
-    session = getattr(g, 'dbsession', None)
-    if session is None:
-        session = sessionmaker(bind=engine)()
+@contextmanager
+def set_session(application: Flask, DB_SESSION: scoped_session) -> Iterator:
+    """
+    Set the Database Session for the app before it is run in main.py.
+    :param application: Flask app object
+            <flask.app.Flask>
+    :param DB_SESSION: SQLalchemy Session object
+            <sqlalchemy.orm.session.Session>
+    """
+    if not isinstance(DB_SESSION, scoped_session) and not isinstance(DB_SESSION, Session):
+        raise TypeError(
+            "The API Doc is not of type <sqlalchemy.orm.session.Session> or <sqlalchemy.orm.scoping.scoped_session>")
+
+    def handler(sender: Flask, **kwargs: Any) -> None:
+        g.dbsession = DB_SESSION
+    with appcontext_pushed.connected_to(handler, application):
+        yield
+
+
+def get_session() -> scoped_session:
+    """
+    Get the Database Session from g.
+    Returns and sets a default Session if not found
+    :return session : SQLalchemy Session object
+            <sqlalchemy.orm.scoped_session>
+    """
+    try:
+        session = getattr(g, 'dbsession')
+    except AttributeError:
+        session = scoped_session(sessionmaker(bind=engine))
         g.dbsession = session
     return session
diff --git a/requirements.txt b/requirements.txt
index f6599b1..8d827f0 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,6 +1,4 @@
 Flask==0.11
-gevent==1.2.2
-greenlet==0.4.12
 Flask-RESTful==0.3.6
 Jinja2==2.9.6
 MarkupSafe==1.0
@@ -22,3 +20,6 @@ six==1.10.0
 thespian==3.5.2
 flask-cors
 blinker==1.4
+typing==3.6.4
+gevent==1.2.2
+mypy
diff --git a/setup.py b/setup.py
index d2d0d38..34755ee 100644
--- a/setup.py
+++ b/setup.py
@@ -1,41 +1,34 @@
-# !/usr/bin/env python
+#!/usr/bin/env python
 """Setup script for Hydrus."""
 
-from distutils.core import setup
+from setuptools import setup, find_packages
+
+try: # for pip >= 10
+    from pip._internal.req import parse_requirements
+    from pip._internal.download import PipSession
+except ImportError: # for pip <= 9.0.3
+    from pip.req import parse_requirements
+    from pip.download import PipSession
+
+
+install_requires = parse_requirements('requirements.txt', session=PipSession())
+dependencies = [str(package.req) for package in install_requires]
 
 setup(name='hydrus',
+      include_package_data=True,
       version='0.0.1',
       description='A space-based application for W3C HYDRA Draft',
       author='W3C HYDRA development group',
       author_email='public-hydra@w3.org',
       url='https://github.com/HTTP-APIs/hydrus',
-      install_requires=[
-          'Flask==0.11',
-          'Flask-RESTful==0.3.6',
-          'Jinja2==2.9.6',
-          'MarkupSafe==1.0',
-          'SQLAlchemy==1.1.10',
-          'Werkzeug==0.12.2',
-          'aniso8601==1.2.1',
-          'appdirs==1.4.3',
-          'argparse==1.2.1',
-          'click==6.7',
-          'itsdangerous==0.24',
-          'lifter==0.4.1',
-          'packaging==16.8',
-          'persisting-theory==0.2.1',
-          'psycopg2',
-          'pyparsing==2.2.0',
-          'python-dateutil==2.6.0',
-          'pytz==2017.2',
-          'six==1.10.0',
-          'thespian==3.5.2',
-          'flask-cors',
-          'blinker==1.4',
-      ],
-      packages=[
-        'hydrus',
-      ],
+      py_modules=['cli'],
+      python_requires='>=3',
+      install_requires=dependencies,
+      packages=find_packages(exclude=['contrib', 'docs', 'tests*', 'hydrus.egg-info']),
       package_dir={'hydrus':
-                   'hydrus'},
+                    'hydrus'},
+      entry_points='''
+            [console_scripts]
+            hydrus=cli:startserver
+        '''
       )


Test patch:
diff --git a/hydrus/tests/test_app.py b/hydrus/tests/test_app.py
index 7819fdf..9b31d73 100644
--- a/hydrus/tests/test_app.py
+++ b/hydrus/tests/test_app.py
@@ -12,7 +12,7 @@ from hydrus.utils import set_session, set_doc, set_api_name
 from hydrus.data import doc_parse
 from hydrus.hydraspec import doc_writer_sample, doc_maker
 from sqlalchemy import create_engine
-from sqlalchemy.orm import sessionmaker
+from sqlalchemy.orm import sessionmaker,scoped_session
 from hydrus.data.db_models import Base
 
 
@@ -40,14 +40,13 @@ class ViewsTestCase(unittest.TestCase):
         print("Creating a temporary database...")
         engine = create_engine('sqlite:///:memory:')
         Base.metadata.create_all(engine)
-        Session = sessionmaker(bind=engine)
-        session = Session()
+        session = scoped_session(sessionmaker(bind=engine))
 
         self.session = session
         self.API_NAME = "demoapi"
         self.HYDRUS_SERVER_URL = "http://hydrus.com/"
         self.app = app_factory(self.API_NAME)
-        self.doc = doc_maker.createDoc(doc_writer_sample.api_doc.generate(), self.HYDRUS_SERVER_URL, self.API_NAME)
+        self.doc = doc_maker.create_doc(doc_writer_sample.api_doc.generate(), self.HYDRUS_SERVER_URL, self.API_NAME)
 
         test_classes = doc_parse.get_classes(self.doc.generate())
         test_properties = doc_parse.get_all_properties(test_classes)
@@ -55,317 +54,274 @@ class ViewsTestCase(unittest.TestCase):
         doc_parse.insert_properties(test_properties, self.session)
 
         print("Classes and properties added successfully.")
+
+        print("Setting up Hydrus utilities... ")
+        self.api_name_util =  set_api_name(self.app, self.API_NAME)
+        self.session_util = set_session(self.app, self.session)
+        self.doc_util = set_doc(self.app, self.doc)
+        self.client = self.app.test_client()
+
+        print("Creating utilities context... ")
+        self.api_name_util.__enter__()
+        self.session_util.__enter__()
+        self.doc_util.__enter__()
+        self.client.__enter__()
+        
         print("Setup done, running tests...")
 
     @classmethod
     def tearDownClass(self):
-        """Tear down temporary database."""
+        """Tear down temporary database and exit utilities"""
+        self.client.__exit__(None, None, None)
+        self.doc_util.__exit__(None, None, None)
+        self.session_util.__exit__(None, None, None)
+        self.api_name_util.__exit__(None, None, None)
         self.session.close()
 
     def test_Index(self):
         """Test for the index."""
-        with set_api_name(self.app, self.API_NAME):
-            with set_session(self.app, self.session):
-                with set_doc(self.app, self.doc):
-                    with self.app.test_client() as client:
-                        response_get = client.get("/"+self.API_NAME)
-                        endpoints = json.loads(response_get.data.decode('utf-8'))
-                        response_post = client.post("/"+self.API_NAME, data=dict(foo="bar"))
-                        response_put = client.put("/"+self.API_NAME, data=dict(foo="bar"))
-                        response_delete = client.delete("/"+self.API_NAME)
-                        assert "@context" in endpoints
-                        assert endpoints["@id"] == "/"+self.API_NAME
-                        assert endpoints["@type"] == "EntryPoint"
-                        assert response_get.status_code == 200
-                        assert response_post.status_code == 405
-                        assert response_put.status_code == 405
-                        assert response_delete.status_code == 405
+        response_get = self.client.get("/"+self.API_NAME)
+        endpoints = json.loads(response_get.data.decode('utf-8'))
+        response_post = self.client.post("/"+self.API_NAME, data=dict(foo="bar"))
+        response_put = self.client.put("/"+self.API_NAME, data=dict(foo="bar"))
+        response_delete = self.client.delete("/"+self.API_NAME)
+        assert "@context" in endpoints
+        assert endpoints["@id"] == "/"+self.API_NAME
+        assert endpoints["@type"] == "EntryPoint"
+        assert response_get.status_code == 200
+        assert response_post.status_code == 405
+        assert response_put.status_code == 405
+        assert response_delete.status_code == 405
 
     def test_EntryPoint_context(self):
         """Test for the EntryPoint context."""
-        with set_api_name(self.app, self.API_NAME):
-            with set_session(self.app, self.session):
-                with set_doc(self.app, self.doc):
-                    with self.app.test_client() as client:
-                        response_get = client.get("/"+self.API_NAME + "/contexts/EntryPoint.jsonld")
-                        response_get_data = json.loads(response_get.data.decode('utf-8'))
-                        response_post = client.post("/"+self.API_NAME + "/contexts/EntryPoint.jsonld", data={})
-                        response_delete = client.delete("/"+self.API_NAME + "/contexts/EntryPoint.jsonld")
-                        assert response_get.status_code == 200
-                        assert "@context" in response_get_data
-                        assert response_post.status_code == 405
-                        assert response_delete.status_code == 405
+        response_get = self.client.get("/"+self.API_NAME + "/contexts/EntryPoint.jsonld")
+        response_get_data = json.loads(response_get.data.decode('utf-8'))
+        response_post = self.client.post("/"+self.API_NAME + "/contexts/EntryPoint.jsonld", data={})
+        response_delete = self.client.delete("/"+self.API_NAME + "/contexts/EntryPoint.jsonld")
+        assert response_get.status_code == 200
+        assert "@context" in response_get_data
+        assert response_post.status_code == 405
+        assert response_delete.status_code == 405
 
     def test_Vocab(self):
         """Test the vocab."""
-        with set_api_name(self.app, self.API_NAME):
-            with set_session(self.app, self.session):
-                with set_doc(self.app, self.doc):
-                    with self.app.test_client() as client:
-                        response_get = client.get("/"+self.API_NAME + "/vocab#")
-                        response_get_data = json.loads(response_get.data.decode('utf-8'))
+        response_get = self.client.get("/"+self.API_NAME + "/vocab#")
+        response_get_data = json.loads(response_get.data.decode('utf-8'))
 
-                        assert "@context" in response_get_data
-                        assert response_get_data["@type"] == "ApiDocumentation"
-                        assert response_get_data["@id"] == self.HYDRUS_SERVER_URL + self.API_NAME + "/vocab"
-                        assert response_get.status_code == 200
+        assert "@context" in response_get_data
+        assert response_get_data["@type"] == "ApiDocumentation"
+        assert response_get_data["@id"] == self.HYDRUS_SERVER_URL + self.API_NAME + "/vocab"
+        assert response_get.status_code == 200
 
-                        response_delete = client.delete("/"+self.API_NAME+"/vocab#")
-                        assert response_delete.status_code == 405
+        response_delete = self.client.delete("/"+self.API_NAME+"/vocab#")
+        assert response_delete.status_code == 405
 
-                        response_put = client.put("/"+self.API_NAME+"/vocab#", data=json.dumps(dict(foo='bar')))
-                        assert response_put.status_code == 405
+        response_put = self.client.put("/"+self.API_NAME+"/vocab#", data=json.dumps(dict(foo='bar')))
+        assert response_put.status_code == 405
 
-                        response_post = client.post("/"+self.API_NAME+"/vocab#", data=json.dumps(dict(foo='bar')))
-                        assert response_post.status_code == 405
+        response_post = self.client.post("/"+self.API_NAME+"/vocab#", data=json.dumps(dict(foo='bar')))
+        assert response_post.status_code == 405
 
     def test_Collections_GET(self):
         """Test GET on collection endpoints."""
-        with set_api_name(self.app, self.API_NAME):
-            with set_session(self.app, self.session):
-                with set_doc(self.app, self.doc):
-                    with self.app.test_client() as client:
-                        index = client.get("/"+self.API_NAME)
-                        assert index.status_code == 200
-                        endpoints = json.loads(index.data.decode('utf-8'))
-                        for endpoint in endpoints:
-                            if endpoint in self.doc.collections:
-                                response_get = client.get(endpoints[endpoint])
-                                # pdb.set_trace()
-                                assert response_get.status_code == 200
-                                response_get_data = json.loads(response_get.data.decode('utf-8'))
-                                assert "@context" in response_get_data
-                                assert "@id" in response_get_data
-                                assert "@type" in response_get_data
-                                assert "members" in response_get_data
+        index = self.client.get("/"+self.API_NAME)
+        assert index.status_code == 200
+        endpoints = json.loads(index.data.decode('utf-8'))
+        for endpoint in endpoints:
+            if endpoint in self.doc.collections:
+                response_get = self.client.get(endpoints[endpoint])
+                # pdb.set_trace()
+                assert response_get.status_code == 200
+                response_get_data = json.loads(response_get.data.decode('utf-8'))
+                assert "@context" in response_get_data
+                assert "@id" in response_get_data
+                assert "@type" in response_get_data
+                assert "members" in response_get_data
 
     def test_Collections_PUT(self):
         """Test insert data to the collection."""
-        with set_api_name(self.app, self.API_NAME):
-            with set_session(self.app, self.session):
-                with set_doc(self.app, self.doc):
-                    with self.app.test_client() as client:
-                        index = client.get("/"+self.API_NAME)
-                        assert index.status_code == 200
-                        endpoints = json.loads(index.data.decode('utf-8'))
-                        for collection_name in endpoints:
-                            if collection_name in self.doc.collections:
-                                collection = self.doc.collections[collection_name]["collection"]
-                                dummy_object = gen_dummy_object(collection.class_.title, self.doc)
-                                good_response_put = client.put(endpoints[collection_name], data=json.dumps(dummy_object))
-                                assert good_response_put.status_code == 201
+        index = self.client.get("/"+self.API_NAME)
+        assert index.status_code == 200
+        endpoints = json.loads(index.data.decode('utf-8'))
+        for collection_name in endpoints:
+            if collection_name in self.doc.collections:
+                collection = self.doc.collections[collection_name]["collection"]
+                dummy_object = gen_dummy_object(collection.class_.title, self.doc)
+                good_response_put = self.client.put(endpoints[collection_name], data=json.dumps(dummy_object))
+                assert good_response_put.status_code == 201
 
     def test_object_POST(self):
         """Test replace of a given object using ID."""
-        with set_api_name(self.app, self.API_NAME):
-            with set_session(self.app, self.session):
-                with set_doc(self.app, self.doc):
-                    with self.app.test_client() as client:
-                        index = client.get("/"+self.API_NAME)
-                        assert index.status_code == 200
-                        endpoints = json.loads(index.data.decode('utf-8'))
-                        for collection_name in endpoints:
-                            if collection_name in self.doc.collections:
-                                collection = self.doc.collections[collection_name]["collection"]
-                                class_ = self.doc.parsed_classes[collection.class_.title]["class"]
-                                class_methods = [x.method for x in class_.supportedOperation]
-                                dummy_object = gen_dummy_object(collection.class_.title, self.doc)
-                                initial_put_response = client.put(endpoints[collection_name], data=json.dumps(dummy_object))
-                                assert initial_put_response.status_code == 201
-                                response = json.loads(initial_put_response.data.decode('utf-8'))
-                                regex = r'(.*)ID (\d)* (.*)'
-                                matchObj = re.match(regex, response["message"])
-                                assert matchObj is not None
-                                id_ = matchObj.group(2)
-                                if "POST" in class_methods:
-                                    dummy_object = gen_dummy_object(collection.class_.title, self.doc)
-                                    post_replace_response = client.post(endpoints[collection_name]+'/'+id_, data=json.dumps(dummy_object))
-                                    assert post_replace_response.status_code == 200
+        index = self.client.get("/"+self.API_NAME)
+        assert index.status_code == 200
+        endpoints = json.loads(index.data.decode('utf-8'))
+        for collection_name in endpoints:
+            if collection_name in self.doc.collections:
+                collection = self.doc.collections[collection_name]["collection"]
+                class_ = self.doc.parsed_classes[collection.class_.title]["class"]
+                class_methods = [x.method for x in class_.supportedOperation]
+                dummy_object = gen_dummy_object(collection.class_.title, self.doc)
+                initial_put_response = self.client.put(endpoints[collection_name], data=json.dumps(dummy_object))
+                assert initial_put_response.status_code == 201
+                response = json.loads(initial_put_response.data.decode('utf-8'))
+                regex = r'(.*)ID (\d)* (.*)'
+                matchObj = re.match(regex, response["message"])
+                assert matchObj is not None
+                id_ = matchObj.group(2)
+                if "POST" in class_methods:
+                    dummy_object = gen_dummy_object(collection.class_.title, self.doc)
+                    post_replace_response = self.client.post(endpoints[collection_name]+'/'+id_, data=json.dumps(dummy_object))
+                    assert post_replace_response.status_code == 200
 
     def test_object_DELETE(self):
         """Test DELETE of a given object using ID."""
-        with set_api_name(self.app, self.API_NAME):
-            with set_session(self.app, self.session):
-                with set_doc(self.app, self.doc):
-                    with self.app.test_client() as client:
-                        index = client.get("/"+self.API_NAME)
-                        assert index.status_code == 200
-                        endpoints = json.loads(index.data.decode('utf-8'))
-                        for collection_name in endpoints:
-                            if collection_name in self.doc.collections:
-                                collection = self.doc.collections[collection_name]["collection"]
-                                class_ = self.doc.parsed_classes[collection.class_.title]["class"]
-                                class_methods = [x.method for x in class_.supportedOperation]
-                                dummy_object = gen_dummy_object(collection.class_.title, self.doc)
-                                initial_put_response = client.put(endpoints[collection_name], data=json.dumps(dummy_object))
-                                assert initial_put_response.status_code == 201
-                                response = json.loads(initial_put_response.data.decode('utf-8'))
-                                regex = r'(.*)ID (\d)* (.*)'
-                                matchObj = re.match(regex, response["message"])
-                                assert matchObj is not None
-                                id_ = matchObj.group(2)
-                                if "DELETE" in class_methods:
-                                    delete_response = client.delete(endpoints[collection_name]+'/'+id_)
-                                    assert delete_response.status_code == 200
+        index = self.client.get("/"+self.API_NAME)
+        assert index.status_code == 200
+        endpoints = json.loads(index.data.decode('utf-8'))
+        for collection_name in endpoints:
+            if collection_name in self.doc.collections:
+                collection = self.doc.collections[collection_name]["collection"]
+                class_ = self.doc.parsed_classes[collection.class_.title]["class"]
+                class_methods = [x.method for x in class_.supportedOperation]
+                dummy_object = gen_dummy_object(collection.class_.title, self.doc)
+                initial_put_response = self.client.put(endpoints[collection_name], data=json.dumps(dummy_object))
+                assert initial_put_response.status_code == 201
+                response = json.loads(initial_put_response.data.decode('utf-8'))
+                regex = r'(.*)ID (\d)* (.*)'
+                matchObj = re.match(regex, response["message"])
+                assert matchObj is not None
+                id_ = matchObj.group(2)
+                if "DELETE" in class_methods:
+                    delete_response = self.client.delete(endpoints[collection_name]+'/'+id_)
+                    assert delete_response.status_code == 200
 
     def test_object_PUT_at_id(self):
         """Create object in collection using PUT at specific ID."""
-        with set_api_name(self.app, self.API_NAME):
-            with set_session(self.app, self.session):
-                with set_doc(self.app, self.doc):
-                    with self.app.test_client() as client:
-                        index = client.get("/"+self.API_NAME)
-                        assert index.status_code == 200
-                        endpoints = json.loads(index.data.decode('utf-8'))
-                        for collection_name in endpoints:
-                            if collection_name in self.doc.collections:
-                                collection = self.doc.collections[collection_name]["collection"]
-                                class_ = self.doc.parsed_classes[collection.class_.title]["class"]
-                                class_methods = [x.method for x in class_.supportedOperation]
-                                dummy_object = gen_dummy_object(collection.class_.title, self.doc)
-                                if "PUT" in class_methods:
-                                    dummy_object = gen_dummy_object(collection.class_.title, self.doc)
-                                    put_response = client.put(endpoints[collection_name]+'/'+str(random.randint(100, 1000)),
-                                                              data=json.dumps(dummy_object))
-                                    assert put_response.status_code == 201
+        index = self.client.get("/"+self.API_NAME)
+        assert index.status_code == 200
+        endpoints = json.loads(index.data.decode('utf-8'))
+        for collection_name in endpoints:
+            if collection_name in self.doc.collections:
+                collection = self.doc.collections[collection_name]["collection"]
+                class_ = self.doc.parsed_classes[collection.class_.title]["class"]
+                class_methods = [x.method for x in class_.supportedOperation]
+                dummy_object = gen_dummy_object(collection.class_.title, self.doc)
+                if "PUT" in class_methods:
+                    dummy_object = gen_dummy_object(collection.class_.title, self.doc)
+                    put_response = self.client.put(endpoints[collection_name]+'/'+str(random.randint(100, 1000)),
+                                              data=json.dumps(dummy_object))
+                    assert put_response.status_code == 201
 
     def test_endpointClass_PUT(self):
         """Check non collection Class PUT."""
-        with set_api_name(self.app, self.API_NAME):
-            with set_session(self.app, self.session):
-                with set_doc(self.app, self.doc):
-                    with self.app.test_client() as client:
-                        index = client.get("/"+self.API_NAME)
-                        assert index.status_code == 200
-                        endpoints = json.loads(index.data.decode('utf-8'))
-                        for class_name in endpoints:
-                            if class_name not in self.doc.collections and class_name not in ["@context", "@id", "@type"]:
-                                class_ = self.doc.parsed_classes[class_name]["class"]
-                                class_methods = [x.method for x in class_.supportedOperation]
-                                if "PUT" in class_methods:
-                                    dummy_object = gen_dummy_object(class_.title, self.doc)
-                                    put_response = client.put(endpoints[class_name], data=json.dumps(dummy_object))
-                                    assert put_response.status_code == 201
+        index = self.client.get("/"+self.API_NAME)
+        assert index.status_code == 200
+        endpoints = json.loads(index.data.decode('utf-8'))
+        for class_name in endpoints:
+            if class_name not in self.doc.collections and class_name not in ["@context", "@id", "@type"]:
+                class_ = self.doc.parsed_classes[class_name]["class"]
+                class_methods = [x.method for x in class_.supportedOperation]
+                if "PUT" in class_methods:
+                    dummy_object = gen_dummy_object(class_.title, self.doc)
+                    put_response = self.client.put(endpoints[class_name], data=json.dumps(dummy_object))
+                    assert put_response.status_code == 201
 
     def test_endpointClass_POST(self):
         """Check non collection Class POST."""
-        with set_api_name(self.app, self.API_NAME):
-            with set_session(self.app, self.session):
-                with set_doc(self.app, self.doc):
-                    with self.app.test_client() as client:
-                        index = client.get("/"+self.API_NAME)
-                        assert index.status_code == 200
-                        endpoints = json.loads(index.data.decode('utf-8'))
-                        for class_name in endpoints:
-                            if class_name not in self.doc.collections and class_name not in ["@context", "@id", "@type"]:
-                                class_ = self.doc.parsed_classes[class_name]["class"]
-                                class_methods = [x.method for x in class_.supportedOperation]
-                                if "POST" in class_methods:
-                                    dummy_object = gen_dummy_object(class_.title, self.doc)
-                                    put_response = client.post(endpoints[class_name], data=json.dumps(dummy_object))
-                                    assert put_response.status_code == 201
+        index = self.client.get("/"+self.API_NAME)
+        assert index.status_code == 200
+        endpoints = json.loads(index.data.decode('utf-8'))
+        for class_name in endpoints:
+            if class_name not in self.doc.collections and class_name not in ["@context", "@id", "@type"]:
+                class_ = self.doc.parsed_classes[class_name]["class"]
+                class_methods = [x.method for x in class_.supportedOperation]
+                if "POST" in class_methods:
+                    dummy_object = gen_dummy_object(class_.title, self.doc)
+                    put_response = self.client.post(endpoints[class_name], data=json.dumps(dummy_object))
+                    assert put_response.status_code == 201
 
     def test_endpointClass_DELETE(self):
         """Check non collection Class DELETE."""
-        with set_api_name(self.app, self.API_NAME):
-            with set_session(self.app, self.session):
-                with set_doc(self.app, self.doc):
-                    with self.app.test_client() as client:
-                        index = client.get("/"+self.API_NAME)
-                        assert index.status_code == 200
-                        endpoints = json.loads(index.data.decode('utf-8'))
-                        for class_name in endpoints:
-                            if class_name not in self.doc.collections and class_name not in ["@context", "@id", "@type"]:
-                                class_ = self.doc.parsed_classes[class_name]["class"]
-                                class_methods = [x.method for x in class_.supportedOperation]
-                                if "DELETE" in class_methods:
-                                    put_response = client.delete(endpoints[class_name])
-                                    assert put_response.status_code == 200
+        index = self.client.get("/"+self.API_NAME)
+        assert index.status_code == 200
+        endpoints = json.loads(index.data.decode('utf-8'))
+        for class_name in endpoints:
+            if class_name not in self.doc.collections and class_name not in ["@context", "@id", "@type"]:
+                class_ = self.doc.parsed_classes[class_name]["class"]
+                class_methods = [x.method for x in class_.supportedOperation]
+                if "DELETE" in class_methods:
+                    put_response = self.client.delete(endpoints[class_name])
+                    assert put_response.status_code == 200
 
     def test_endpointClass_GET(self):
         """Check non collection Class GET."""
-        with set_api_name(self.app, self.API_NAME):
-            with set_session(self.app, self.session):
-                with set_doc(self.app, self.doc):
-                    with self.app.test_client() as client:
-                        index = client.get("/"+self.API_NAME)
-                        assert index.status_code == 200
-                        endpoints = json.loads(index.data.decode('utf-8'))
-                        for class_name in endpoints:
-                            if class_name not in self.doc.collections and class_name not in ["@context", "@id", "@type"]:
-                                class_ = self.doc.parsed_classes[class_name]["class"]
-                                class_methods = [x.method for x in class_.supportedOperation]
-                                if "GET" in class_methods:
-                                    response_get = client.get(endpoints[class_name])
-                                    assert response_get.status_code in [200, 404]
-                                    if response_get.status_code == 200:
-                                        response_get_data = json.loads(response_get.data.decode('utf-8'))
-                                        assert "@context" in response_get_data
-                                        assert "@id" in response_get_data
-                                        assert "@type" in response_get_data
+        index = self.client.get("/"+self.API_NAME)
+        assert index.status_code == 200
+        endpoints = json.loads(index.data.decode('utf-8'))
+        for class_name in endpoints:
+            if class_name not in self.doc.collections and class_name not in ["@context", "@id", "@type"]:
+                class_ = self.doc.parsed_classes[class_name]["class"]
+                class_methods = [x.method for x in class_.supportedOperation]
+                if "GET" in class_methods:
+                    response_get = self.client.get(endpoints[class_name])
+                    assert response_get.status_code in [200, 404]
+                    if response_get.status_code == 200:
+                        response_get_data = json.loads(response_get.data.decode('utf-8'))
+                        assert "@context" in response_get_data
+                        assert "@id" in response_get_data
+                        assert "@type" in response_get_data
 
     def test_bad_objects(self):
         """Checks if bad objects are added or not."""
-        with set_api_name(self.app, self.API_NAME):
-            with set_session(self.app, self.session):
-                with set_doc(self.app, self.doc):
-                    with self.app.test_client() as client:
-                        index = client.get("/"+self.API_NAME)
-                        assert index.status_code == 200
-                        endpoints = json.loads(index.data.decode('utf-8'))
-                        for collection_name in endpoints:
-                            if collection_name in self.doc.collections:
-                                bad_response_put = client.put(endpoints[collection_name], data=json.dumps(dict(foo='bar')))
-                                assert bad_response_put.status_code == 400
+        index = self.client.get("/"+self.API_NAME)
+        assert index.status_code == 200
+        endpoints = json.loads(index.data.decode('utf-8'))
+        for collection_name in endpoints:
+            if collection_name in self.doc.collections:
+                bad_response_put = self.client.put(endpoints[collection_name], data=json.dumps(dict(foo='bar')))
+                assert bad_response_put.status_code == 400
 
     def test_bad_requests(self):
         """Checks if bad requests are handled or not."""
-        with set_api_name(self.app, self.API_NAME):
-            with set_session(self.app, self.session):
-                with set_doc(self.app, self.doc):
-                    with self.app.test_client() as client:
-                        index = client.get("/"+self.API_NAME)
-                        assert index.status_code == 200
-                        endpoints = json.loads(index.data.decode('utf-8'))
-                        for collection_name in endpoints:
-                            if collection_name in self.doc.collections:
-                                collection = self.doc.collections[collection_name]["collection"]
-                                class_ = self.doc.parsed_classes[collection.class_.title]["class"]
-                                class_methods = [x.method for x in class_.supportedOperation]
-                                dummy_object = gen_dummy_object(collection.class_.title, self.doc)
-                                initial_put_response = client.put(endpoints[collection_name], data=json.dumps(dummy_object))
-                                assert initial_put_response.status_code == 201
-                                response = json.loads(initial_put_response.data.decode('utf-8'))
-                                regex = r'(.*)ID (\d)* (.*)'
-                                matchObj = re.match(regex, response["message"])
-                                assert matchObj is not None
-                                id_ = matchObj.group(2)
-                                if "POST" not in class_methods:
-                                    dummy_object = gen_dummy_object(collection.class_.title, self.doc)
-                                    post_replace_response = client.post(endpoints[collection_name]+'/'+id_, data=json.dumps(dummy_object))
-                                    assert post_replace_response.status_code == 405
-                                if "DELETE" not in class_methods:
-                                    delete_response = client.delete(endpoints[collection_name]+'/'+id_)
-                                    assert delete_response.status_code == 405
+        index = self.client.get("/"+self.API_NAME)
+        assert index.status_code == 200
+        endpoints = json.loads(index.data.decode('utf-8'))
+        for collection_name in endpoints:
+            if collection_name in self.doc.collections:
+                collection = self.doc.collections[collection_name]["collection"]
+                class_ = self.doc.parsed_classes[collection.class_.title]["class"]
+                class_methods = [x.method for x in class_.supportedOperation]
+                dummy_object = gen_dummy_object(collection.class_.title, self.doc)
+                initial_put_response = self.client.put(endpoints[collection_name], data=json.dumps(dummy_object))
+                assert initial_put_response.status_code == 201
+                response = json.loads(initial_put_response.data.decode('utf-8'))
+                regex = r'(.*)ID (\d)* (.*)'
+                matchObj = re.match(regex, response["message"])
+                assert matchObj is not None
+                id_ = matchObj.group(2)
+                if "POST" not in class_methods:
+                    dummy_object = gen_dummy_object(collection.class_.title, self.doc)
+                    post_replace_response = self.client.post(endpoints[collection_name]+'/'+id_, data=json.dumps(dummy_object))
+                    assert post_replace_response.status_code == 405
+                if "DELETE" not in class_methods:
+                    delete_response = self.client.delete(endpoints[collection_name]+'/'+id_)
+                    assert delete_response.status_code == 405
 
     def test_Endpoints_Contexts(self):
         """Test all endpoints contexts are generated properly."""
-        with set_api_name(self.app, self.API_NAME):
-            with set_session(self.app, self.session):
-                with set_doc(self.app, self.doc):
-                    with self.app.test_client() as client:
-                        index = client.get("/"+self.API_NAME)
-                        assert index.status_code == 200
-                        endpoints = json.loads(index.data.decode('utf-8'))
-                        for collection_name in endpoints:
-                            if collection_name in self.doc.collections:
-                                response_get = client.get(endpoints[collection_name])
-                                assert response_get.status_code == 200
-                                context = json.loads(response_get.data.decode('utf-8'))["@context"]
-                                response_context = client.get(context)
-                                response_context_data = json.loads(response_context.data.decode('utf-8'))
-                                assert response_context.status_code == 200
-                                assert "@context" in response_context_data
+        index = self.client.get("/"+self.API_NAME)
+        assert index.status_code == 200
+        endpoints = json.loads(index.data.decode('utf-8'))
+        for collection_name in endpoints:
+            if collection_name in self.doc.collections:
+                response_get = self.client.get(endpoints[collection_name])
+                assert response_get.status_code == 200
+                context = json.loads(response_get.data.decode('utf-8'))["@context"]
+                response_context = self.client.get(context)
+                response_context_data = json.loads(response_context.data.decode('utf-8'))
+                assert response_context.status_code == 200
+                assert "@context" in response_context_data
 
 
 if __name__ == '__main__':
@@ -373,4 +329,3 @@ if __name__ == '__main__':
     Running tests for the app. Checking if all responses are in proper order.
     """
     print(message)
-    unittest.main()
diff --git a/hydrus/tests/test_auth.py b/hydrus/tests/test_auth.py
index 0ba081c..de64dbb 100644
--- a/hydrus/tests/test_auth.py
+++ b/hydrus/tests/test_auth.py
@@ -4,13 +4,14 @@ from hydrus.data.user import generate_basic_digest
 import json
 import unittest
 from hydrus.app import app_factory
-from hydrus.utils import set_session, set_doc, set_api_name, set_authentication
+from hydrus.utils import set_session, set_doc, set_api_name, set_authentication, set_token
 from hydrus.data import doc_parse
 from hydrus.hydraspec import doc_writer_sample, doc_maker
 from sqlalchemy import create_engine
-from sqlalchemy.orm import sessionmaker
+from sqlalchemy.orm import sessionmaker,scoped_session
 from hydrus.data.db_models import Base
 from hydrus.data.user import add_user
+from base64 import b64encode
 
 
 # response = requests.get("http://127.0.0.1:8080/serverapi/CommandCollection", headers={'Authorization':'Basic QWxhZGRpbjpPcGVuU2VzYW1l'})
@@ -22,87 +23,164 @@ class AuthTestCase(unittest.TestCase):
     @classmethod
     def setUpClass(self):
         """Database setup before the tests."""
-        print("Creating a temporary datatbsse...")
+        print("Creating a temporary datatbase...")
         engine = create_engine('sqlite:///:memory:')
         Base.metadata.create_all(engine)
-        Session = sessionmaker(bind=engine)
-        session = Session()
+        session = scoped_session(sessionmaker(bind=engine))
 
         self.session = session
         self.API_NAME = "demoapi"
         self.HYDRUS_SERVER_URL = "http://hydrus.com/"
         self.app = app_factory(self.API_NAME)
-        self.doc = doc_maker.createDoc(doc_writer_sample.api_doc.generate(), self.HYDRUS_SERVER_URL, self.API_NAME)
+        self.doc = doc_maker.create_doc(doc_writer_sample.api_doc.generate(), self.HYDRUS_SERVER_URL, self.API_NAME)
 
         test_classes = doc_parse.get_classes(self.doc.generate())
         test_properties = doc_parse.get_all_properties(test_classes)
         doc_parse.insert_classes(test_classes, self.session)
         doc_parse.insert_properties(test_properties, self.session)
         add_user(1, "test", self.session)
-        self.auth_header = {"Authorization": "Basic " + generate_basic_digest(1, "test")}
+        self.auth_header = {"X-Authentication": "" , "Authorization": "Basic " + b64encode(b"1:test").decode("ascii")}
+        self.wrong_id = {"X-Authentication": "" , "Authorization": "Basic " + b64encode(b"2:test").decode("ascii")}
+        self.wrong_pass = {"X-Authentication": "" , "Authorization": "Basic " + b64encode(b"1:test2").decode("ascii")}        
         print("Classes, Properties and Users added successfully.")
+
+        print("Setting up Hydrus utilities... ")
+        self.api_name_util =  set_api_name(self.app, self.API_NAME)
+        self.session_util = set_session(self.app, self.session)
+        self.doc_util = set_doc(self.app, self.doc)
+        self.auth_util = set_authentication(self.app, True)
+        self.token_util = set_token(self.app, False)
+        self.client = self.app.test_client()
+        
+        print("Creating utilities context... ")
+        self.api_name_util.__enter__()
+        self.session_util.__enter__()
+        self.doc_util.__enter__()
+        self.auth_util.__enter__()
+        self.token_util.__enter__()
+        self.client.__enter__()
+
         print("Setup done, running tests...")
 
+
     @classmethod
     def tearDownClass(self):
-        """Tear down temporary database."""
+        """Tear down temporary database and exit utilities"""
+        self.client.__exit__(None, None, None)
+        self.auth_util.__exit__(None, None, None)
+        self.token_util.__exit__(None, None, None)
+        self.doc_util.__exit__(None, None, None)
+        self.session_util.__exit__(None, None, None)
+        self.api_name_util.__exit__(None, None, None)
         self.session.close()
 
+    def test_wrongID_GET(self):
+        """Test for the index."""
+        response_get = self.client.get("/"+self.API_NAME)
+        endpoints = json.loads(response_get.data.decode('utf-8'))
+        for endpoint in endpoints:
+            if endpoint in self.doc.collections:
+                response_get = self.client.get(endpoints[endpoint])
+                self.wrong_id['X-Authentication'] = response_get.headers['X-Authentication']
+                response_get = self.client.get(endpoints[endpoint],headers = self.wrong_id)
+                assert response_get.status_code == 401 or response_get.status_code == 400
+
+    def test_wrongID_POST(self):
+        """Test for the index."""
+        response_get = self.client.get("/"+self.API_NAME)
+        endpoints = json.loads(response_get.data.decode('utf-8'))
+        for endpoint in endpoints:
+            if endpoint in self.doc.collections:
+                response_get = self.client.get(endpoints[endpoint])
+                self.wrong_id['X-Authentication'] = response_get.headers['X-Authentication']
+                response_get = self.client.post(endpoints[endpoint], headers=self.wrong_id, data=json.dumps(dict(foo="bar")))
+                assert response_get.status_code == 401 or response_get.status_code == 400
+
+    def test_wrongPass_GET(self):
+        """Test for the index."""
+        response_get = self.client.get("/"+self.API_NAME)
+        endpoints = json.loads(response_get.data.decode('utf-8'))
+        for endpoint in endpoints:
+            if endpoint in self.doc.collections:
+                response_get = self.client.get(endpoints[endpoint])
+                self.wrong_pass['X-Authentication'] = response_get.headers['X-Authentication']
+                response_get = self.client.get(endpoints[endpoint], headers=self.wrong_pass)
+                assert response_get.status_code == 401
+
+    def test_wrongPass_POST(self):
+        """Test for the index."""
+        response_get = self.client.get("/"+self.API_NAME)
+        endpoints = json.loads(response_get.data.decode('utf-8'))
+        for endpoint in endpoints:
+            if endpoint in self.doc.collections:
+                response_get = self.client.get(endpoints[endpoint])
+                self.wrong_pass['X-Authentication'] = response_get.headers['X-Authentication']
+                response_get = self.client.post(endpoints[endpoint], headers=self.wrong_pass, data=json.dumps(dict(foo="bar")))
+                assert response_get.status_code == 401
+
+    def test_wrong_nonce_get(self):
+        """Test for the index."""
+        response_get = self.client.get("/"+self.API_NAME)
+        endpoints = json.loads(response_get.data.decode('utf-8'))
+        for endpoint in endpoints:
+            if endpoint in self.doc.collections:
+                self.auth_header['X-authentication'] = "random-string"
+                response_get = self.client.get(endpoints[endpoint], headers=self.auth_header)
+                assert response_get.status_code == 401
+
+    def test_wrong_nonce_post(self):
+        """Test for the index."""
+        response_get = self.client.get("/"+self.API_NAME)
+        endpoints = json.loads(response_get.data.decode('utf-8'))
+        for endpoint in endpoints:
+            if endpoint in self.doc.collections:
+                self.auth_header['X-authentication'] = "random-string"
+                response_get = self.client.post(endpoints[endpoint], headers=self.auth_header,data = json.dumps(dict(foo="bar")))
+                assert response_get.status_code == 401
+
     def test_Auth_GET(self):
         """Test for the index."""
-        with set_api_name(self.app, self.API_NAME):
-            with set_session(self.app, self.session):
-                with set_doc(self.app, self.doc):
-                    with set_authentication(self.app, True):
-                        with self.app.test_client() as client:
-                            response_get = client.get("/"+self.API_NAME)
-                            endpoints = json.loads(response_get.data.decode('utf-8'))
-                            for endpoint in endpoints:
-                                if endpoint in self.doc.collections:
-                                    response_get = client.get(endpoints[endpoint], headers=self.auth_header)
-                                    assert response_get.status_code != 401
+        response_get = self.client.get("/"+self.API_NAME)
+        endpoints = json.loads(response_get.data.decode('utf-8'))
+        for endpoint in endpoints:
+            if endpoint in self.doc.collections:
+                response_get = self.client.get(endpoints[endpoint])
+                self.auth_header['X-Authentication'] = response_get.headers['X-Authentication']
+                response_get = self.client.get(endpoints[endpoint],headers = self.auth_header)
+                assert response_get.status_code != 401
 
     def test_Auth_POST(self):
         """Test for the index."""
-        with set_api_name(self.app, self.API_NAME):
-            with set_session(self.app, self.session):
-                with set_doc(self.app, self.doc):
-                    with set_authentication(self.app, True):
-                        with self.app.test_client() as client:
-                            response_get = client.get("/"+self.API_NAME)
-                            endpoints = json.loads(response_get.data.decode('utf-8'))
-                            for endpoint in endpoints:
-                                if endpoint in self.doc.collections:
-                                    response_get = client.post(endpoints[endpoint], headers=self.auth_header, data=json.dumps(dict(foo="bar")))
-                                    assert response_get.status_code != 401
+        response_get = self.client.get("/"+self.API_NAME)
+        endpoints = json.loads(response_get.data.decode('utf-8'))
+        for endpoint in endpoints:
+            if endpoint in self.doc.collections:
+                response_get = self.client.get(endpoints[endpoint])
+                self.auth_header['X-Authentication'] = response_get.headers['X-Authentication']
+                response_get = self.client.post(endpoints[endpoint], headers=self.auth_header, data=json.dumps(dict(foo="bar")))
+                assert response_get.status_code != 401
 
     def test_Auth_PUT(self):
         """Test for the index."""
-        with set_api_name(self.app, self.API_NAME):
-            with set_session(self.app, self.session):
-                with set_doc(self.app, self.doc):
-                    with set_authentication(self.app, True):
-                        with self.app.test_client() as client:
-                            response_get = client.get("/"+self.API_NAME)
-                            endpoints = json.loads(response_get.data.decode('utf-8'))
-                            for endpoint in endpoints:
-                                if endpoint in self.doc.collections:
-                                    response_get = client.put(endpoints[endpoint], headers=self.auth_header, data=json.dumps(dict(foo="bar")))
-                                    assert response_get.status_code != 401
+        response_get = self.client.get("/"+self.API_NAME)
+        endpoints = json.loads(response_get.data.decode('utf-8'))
+        for endpoint in endpoints:
+            if endpoint in self.doc.collections:
+                response_get = self.client.get(endpoints[endpoint])
+                self.auth_header['X-Authentication'] = response_get.headers['X-Authentication']
+                response_get = self.client.put(endpoints[endpoint], headers=self.auth_header, data=json.dumps(dict(foo="bar")))                
+                assert response_get.status_code != 401
 
     def test_Auth_DELETE(self):
         """Test for the index."""
-        with set_api_name(self.app, self.API_NAME):
-            with set_session(self.app, self.session):
-                with set_doc(self.app, self.doc):
-                    with set_authentication(self.app, True):
-                        with self.app.test_client() as client:
-                            response_get = client.get("/"+self.API_NAME)
-                            endpoints = json.loads(response_get.data.decode('utf-8'))
-                            for endpoint in endpoints:
-                                if endpoint in self.doc.collections:
-                                    response_get = client.delete(endpoints[endpoint], headers=self.auth_header)
-                                    assert response_get.status_code != 401
+        response_get = self.client.get("/"+self.API_NAME)
+        endpoints = json.loads(response_get.data.decode('utf-8'))
+        for endpoint in endpoints:
+            if endpoint in self.doc.collections:
+                response_get = self.client.get(endpoints[endpoint])
+                self.auth_header['X-Authentication'] = response_get.headers['X-Authentication']
+                response_get = self.client.delete(endpoints[endpoint], headers=self.auth_header)
+                assert response_get.status_code != 401
 
 
 if __name__ == '__main__':
diff --git a/hydrus/tests/test_crud.py b/hydrus/tests/test_crud.py
index 280deac..5f2389a 100644
--- a/hydrus/tests/test_crud.py
+++ b/hydrus/tests/test_crud.py
@@ -3,7 +3,7 @@
 import unittest
 
 from sqlalchemy import create_engine
-from sqlalchemy.orm import sessionmaker
+from sqlalchemy.orm import sessionmaker,scoped_session
 import hydrus.data.crud as crud
 from hydrus.data.db_models import Base
 from hydrus.data import doc_parse
@@ -37,8 +37,8 @@ class TestCRUD(unittest.TestCase):
         print("Creating a temporary datatbsse...")
         engine = create_engine('sqlite:///:memory:')
         Base.metadata.create_all(engine)
-        Session = sessionmaker(bind=engine)
-        session = Session()
+        session = scoped_session(sessionmaker(bind=engine))
+
         self.session = session
         self.doc = doc
         test_classes = doc_parse.get_classes(self.doc.generate())
@@ -144,7 +144,7 @@ class TestCRUD(unittest.TestCase):
         """Test CRUD insert when wrong/undefined class is given."""
         object_ = gen_dummy_object("dummyClass", self.doc)
         id_ = 7
-        object_["@type"] = "otherClass"
+        object_["@type"] = "otherClass"
         response_code = None
         try:
             insert_response = crud.insert(object_=object_, id_=id_, session=self.session)