Skip to content

Commit

Permalink
Merge pull request #1 from jonathankamau/development
Browse files Browse the repository at this point in the history
#PR Peer Review
  • Loading branch information
jonathankamau authored Sep 6, 2017
2 parents 825dfba + 502cd75 commit 0b132e6
Show file tree
Hide file tree
Showing 24 changed files with 1,492 additions and 234 deletions.
39 changes: 39 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[run]
omit =
*/tests/*
test_*
*sqlalchemy/*
*werkzeug/*
*ctypes/*
*encodings/*
*jinja2/*
*flask/*
*click/*
*flask_api/*
*flask_restful/*
*markupsafe/*
*psycopg2/*
*html/*
*http/*
*aniso8601*
*flask_marshmallow*
*marshmallow*
*pytz*
bucketlist.py
bucketlist/app.py
bucketlist/app/authenticate_token.py
bucketlist/instance.py
*dateutil*
*decimal.py
*numbers.py
*pydoc.py
*hmac.py
*mimetypes.py
*itsdangerous.py
*stringprep.py
*flask_httpauth.py
*jwt/*
*uuid.py
*models
*models/db/sqlalchemy_declarative.py

12 changes: 11 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,12 @@
.DS_Store
__pycache__/
__pycache__/
migrations
.coverage
cover/
instance/test_app.py
.gitconfig
app/helpers.py
.env
Library/
tmp/
instance/config.py
102 changes: 102 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
## Checkpoint 2: Bucket List API application
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/e002026263b1406f842a68886b81577e)](https://www.codacy.com/app/jonathankamau/cp2-bucketlist-application?utm_source=github.com&utm_medium=referral&utm_content=jonathankamau/cp2-bucketlist-application&utm_campaign=Badge_Grade)
[![Codacy Badge](https://api.codacy.com/project/badge/Coverage/e002026263b1406f842a68886b81577e)](https://www.codacy.com/app/jonathankamau/cp2-bucketlist-application?utm_source=github.com&utm_medium=referral&utm_content=jonathankamau/cp2-bucketlist-application&utm_campaign=Badge_Grade)
![CircleCI](https://circleci.com/gh/jonathankamau/cp2-bucketlist-application/tree/development.svg?style=shield&circle-token=51bfa19ac63ea6e9c476ed22b04b5b44f8b5e069)


This API enables the user to create bucketlist and list of items in the bucketlist. The items can be marked as `done` when completed.

#### URL endpoints

| URL Endpoint | HTTP Methods | Summary |
| -------- | ------------- | --------- |
| `/api/v1/auth/register/` | `POST` | Register a new user|
| `/api/v1/auth/login/` | `POST` | Login and retrieve token|
| `/api/v1/bucketlists/` | `POST` | Create a new Bucketlist |
| `/api/v1/bucketlists/` | `GET` | Retrieve all bucketlists for user |
| `/api/v1/bucketlists/?limit=2&page=1` | `GET` | Retrieve one bucketlist per page |
| `/api/v1/bucketlists/<id>/` | `GET` | Retrieve bucket list details |
| `/api/v1/bucketlists/<id>/` | `PUT` | Update bucket list details |
| `/api/v1/bucketlists/<id>/` | `DELETE` | Delete a bucket list |
| `/api/v1/bucketlists/<id>/items/` | `POST` | Create items in a bucket list |
| `/api/v1/bucketlists/<id>/items/<item_id>/` | `DELETE`| Delete a item in a bucket list|
| `/api/v1/bucketlists/<id>/items/<item_id>/` | `PUT`| update a bucket list item details|

### Installation
1. create a working directory

$ mkdir -p work-dir
$ cd workdir


2. clone this repo to local
- Via SSH

git clone git@github.com:jonathankamau/cp2-bucketlist-application.git

- via HTTPS

git clone https://github.com/jonathankamau/cp2-bucketlist-application.git
3. Navigate to project directory


$ cd cp2-bucketlist-application
$ git checkout development

4. (Recommended)Create virtual environment


$ virtualenv venv-bucketlist
$ source bucketlist-venv/bin/activate

5. Set up the development environment for the project


$ pip install -r requirements.txt
$ python manage.py db init
$ python manage.py db migrate
$ python manage.py db upgrade

6. run server

$ python manage.py runserver
Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

7. Running tests

Run the following command in order to run tests:
$ nosetests -v

Running tests to check coverage:
$ nosetests --with-coverage

### APPLICATION OPERATIONS

1. Register the user

![Register](https://cloud.githubusercontent.com/assets/26286275/26498848/1e0a7b66-4239-11e7-9e91-7515869032bc.png)

2. Login the user
![Login](https://cloud.githubusercontent.com/assets/26286275/26499067/e8cca36a-4239-11e7-80ab-b07277ee5733.png)

3. Create a bucketlist
![Create A Bucketlist](https://cloud.githubusercontent.com/assets/26286275/26499805/922dba78-423c-11e7-84eb-3cc8abfd3f1f.png)

4. Get all bucketlists
![Get Bucketlists](https://cloud.githubusercontent.com/assets/26286275/26499814/98ac6728-423c-11e7-860d-63fc5de57fbe.png)

5. Get a bucketlist
![Get a bucketlist](https://cloud.githubusercontent.com/assets/26286275/26500073/595eb674-423d-11e7-8468-6900a80af5d5.png)

6. Create a bucketlist item
![Create Bucketlist Item](https://cloud.githubusercontent.com/assets/26286275/26500441/a0e81fa2-423e-11e7-9ceb-08b9c2a61cf4.png)

The API server is accessible on `http://127.0.0.1:5000/`
and it is also accessible online on https://jk-bucketlist.herokuapp.com

### Sample API Use Case
Access the endpoints using your preferred client e.g Postman

71 changes: 46 additions & 25 deletions app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,57 @@
import os
import os.path
import sys

from flask_api import FlaskAPI
from flask import Flask
from flask_bcrypt import Bcrypt
from flask_restful import reqparse, Resource, Api
from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth
from flask import request, jsonify, abort, Blueprint
from flask_sqlalchemy import SQLAlchemy


app = Flask(__name__)
from app.config import bucketlist_config

app_settings = os.getenv(
'APP_SETTINGS',
'instance.config.DevelopmentConfig'
)
app.config.from_object(app_settings)

bcrypt = Bcrypt(app)
db = SQLAlchemy(app)
db = SQLAlchemy()
auth = HTTPBasicAuth()


# # local imports
# from instance.config import app_config
def create_app(config_name):
from app.models import User, Bucketlist, BucketlistItems
from app.resources import (RegisterUser, UserLogin,
BucketlistAPI, BucketlistItem,
GetUpdateBucketlistItem, GetBucketlist, UpdateBucketlist)

# #app = FlaskAPI(__name__)
# bcrypt = Bcrypt()
# db = SQLAlchemy()
# # db variable initialization
# #db = SQLAlchemy()
app = FlaskAPI(__name__, instance_relative_config=True)
app.config.from_object(bucketlist_config[config_name])
scriptpath = os.path.dirname(__file__)
filename = os.path.join(scriptpath, 'config.py')
app.config.from_pyfile(filename)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['BUNDLE_ERRORS'] = True

# def create_app(config_name):
# app = FlaskAPI(__name__, instance_relative_config=True)
# app.config.from_object(app_config[config_name])
# app.config.from_pyfile('config.py')
# app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# db.init_app(app)
# return app
api_blueprint = Blueprint('api', __name__)
api = Api(api_blueprint)


db.init_app(app)

# urls
api.add_resource(
RegisterUser, '/auth/register', endpoint='register')
api.add_resource(
UserLogin, '/auth/login', endpoint='login')
api.add_resource(
BucketlistAPI, '/bucketlists/', endpoint='bucketlists')
api.add_resource(
GetBucketlist, '/bucketlists/<int:bucketlist_id>', endpoint='bucketlist-search')
api.add_resource(
BucketlistItem, '/bucketlists/<int:bucketlist_id>/items/', endpoint='items')
api.add_resource(
UpdateBucketlist, '/bucketlists/<int:bucketlist_id>', endpoint='update')
api.add_resource(
GetUpdateBucketlistItem, '/bucketlists/<int:bucketlist_id>/items/<int:item_id>',
endpoint='item-search')

app.register_blueprint(api_blueprint, url_prefix='/bucketlist_api/v1.0')

return app
20 changes: 20 additions & 0 deletions app/authenticate_token.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import os


from flask import g
from flask_httpauth import HTTPTokenAuth

from app.models import User



auth_token = HTTPTokenAuth('Bearer')

@auth_token.verify_token
def verify_token(token):
g.current_user = User.verify_auth_token(token)
return g.current_user not in ['Invalid Token!', 'Expired Token!']

@auth_token.error_handler
def unauthorized_token():
return {'Error':'Please send a valid authentication token'}, 401
10 changes: 8 additions & 2 deletions app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,24 @@ class Config(object):
"""Parent configuration class."""
DEBUG = False
CSRF_ENABLED = True
DATABASE_URL="postgresql://localhost/bucketlist"
SECRET = os.getenv('SECRET')
SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL')
JSON_SORT_KEYS = False

class DevelopmentConfig(Config):
"""Configurations for Development."""
DEBUG = True
FLASK_CONFIG = "development"
JSON_SORT_KEYS = False
SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL')

class TestingConfig(Config):
"""Configurations for Testing, with a separate test database."""
TESTING = True
SQLALCHEMY_DATABASE_URI = 'postgresql:///bucketlist'
SQLALCHEMY_DATABASE_URI = 'postgresql://localhost/bucketlist_test'
DEBUG = True
FLASK_CONFIG = "testing"

class StagingConfig(Config):
"""Configurations for Staging."""
Expand All @@ -26,7 +32,7 @@ class ProductionConfig(Config):
DEBUG = False
TESTING = False

app_config = {
bucketlist_config = {
'development': DevelopmentConfig,
'testing': TestingConfig,
'staging': StagingConfig,
Expand Down
6 changes: 0 additions & 6 deletions app/hello.py

This file was deleted.

Loading

0 comments on commit 0b132e6

Please sign in to comment.