-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
30 changed files
with
1,467 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
!coverage.py: This is a private format, don't read it directly!{"lines": {"/Users/andela/Documents/projects/flaskapps/bucketlist-api/app/views.py": [1, 2, 3, 4, 6, 8, 9, 10, 11, 12, 13, 15, 16, 18, 21, 23], "/Users/andela/Documents/projects/flaskapps/bucketlist-api/test.py": [1, 3, 4], "/Users/andela/Documents/projects/flaskapps/bucketlist-api/app/resource.py": [1, 2, 3, 4, 5, 7, 9, 16, 17, 18, 20, 22, 28, 30, 31, 42, 43, 44, 45, 47, 49, 60, 61, 62, 63, 65, 66, 68, 71, 73, 86, 87, 88, 89, 90, 92, 94, 97, 100, 102, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 129, 132, 134, 147, 148, 149, 150, 153, 154, 155, 157, 160, 162, 173, 174, 175, 178, 179, 182, 184, 195, 196, 197, 198, 200, 201, 204, 207, 209, 223, 224, 225, 226, 227, 229, 230, 233, 234, 235, 237, 240, 243, 245, 259, 260, 261, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 275, 276, 277, 280, 283, 285, 298, 299, 300, 301, 302, 304, 305, 308, 312, 313, 324, 325, 327, 328, 330, 333, 335, 348, 349, 350, 351, 353], "/Users/andela/Documents/projects/flaskapps/bucketlist-api/app/helper.py": [1, 2, 3, 4, 6, 8, 10, 11, 12, 13, 14, 15, 17, 19, 20, 21, 22, 23, 24, 27, 31, 32, 33, 34, 35, 37, 42, 43, 44, 45, 47, 49, 53, 55, 60, 61, 62, 63, 64, 66, 71, 72, 73, 74, 75], "/Users/andela/Documents/projects/flaskapps/bucketlist-api/test_config.py": [1, 2, 4, 6], "/Users/andela/Documents/projects/flaskapps/bucketlist-api/app/models.py": [1, 2, 3, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24, 27, 28, 31, 32, 33, 34, 35, 36, 37, 38, 40, 41, 42, 44, 45, 46, 47, 48, 49, 50, 51, 54, 55, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68, 69, 71, 72, 74, 75, 76, 77, 78, 79, 80, 83, 84, 85], "/Users/andela/Documents/projects/flaskapps/bucketlist-api/production_config.py": [1, 2, 4, 6]}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[report] | ||
omit = | ||
*/python?.?/* | ||
tests/* | ||
*/site-packages/nose/* | ||
*__init__* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
*.pyc | ||
*/*.pyc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
language: python | ||
python: | ||
- "2.7" | ||
# command to install dependencies | ||
install: | ||
- pip install -r requirements.txt | ||
script: | ||
- nosetests --with-coverage | ||
after_success: | ||
- coveralls |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,146 @@ | ||
# bucketlist-api | ||
# bucketlist API | ||
[![Build Status](https://travis-ci.org/andela-snwuguru/bucketlist-api.svg?branch=ch-ci-integration)](https://travis-ci.org/andela-snwuguru/bucketlist-api) [![Coverage Status](https://coveralls.io/repos/github/andela-snwuguru/bucketlist-api/badge.svg?branch=ch-ci-integration)](https://coveralls.io/github/andela-snwuguru/bucketlist-api?branch=ch-ci-integration) | ||
|
||
According to Merriam-Webster Dictionary, a Bucket List is a list of things that one has not done before but wants to do before dying. | ||
This is a checkpoint 2 project used to evaluate Python beginner | ||
|
||
## Features, Endpoints and Accessiblity | ||
<table> | ||
<tr> | ||
<th> Features </th> | ||
<th> Endpoint</th> | ||
<th> Public</th> | ||
</tr> | ||
<tr> | ||
<td>Register </td> | ||
<td>POST /auth/register</td> | ||
<td> True</td> | ||
</tr> | ||
<tr> | ||
<td>Authentication</td> | ||
<td>POST /auth/login</td> | ||
<td>True</td> | ||
</tr> | ||
|
||
<tr> | ||
<td>Create Bucketlist</td> | ||
<td>POST /bucketlists/ </td> | ||
<td>False</td> | ||
</tr> | ||
|
||
<tr> | ||
<td>Fetch Bucketlists</td> | ||
<td>GET /bucketlists/ </td> | ||
<td>False</td> | ||
</tr> | ||
|
||
<tr> | ||
<td>Fetch Single Bucketlists</td> | ||
<td>GET /bucketlists/:id </td> | ||
<td>False</td> | ||
</tr> | ||
|
||
<tr> | ||
<td>Update bucketlist record</td> | ||
<td>PUT /bucketlists/:id </td> | ||
<td>False</td> | ||
</tr> | ||
|
||
<tr> | ||
<td>Delete bucketlist record</td> | ||
<td>DELETE /bucketlists/:id </td> | ||
<td>False</td> | ||
</tr> | ||
|
||
<tr> | ||
<td>Create Bucketlist Item</td> | ||
<td>POST /bucketlists/:id/items </td> | ||
<td>False</td> | ||
</tr> | ||
|
||
<tr> | ||
<td>Fetch Bucketlists Items</td> | ||
<td>GET /bucketlists/:id/items </td> | ||
<td>False</td> | ||
</tr> | ||
|
||
<tr> | ||
<td>Fetch Single Bucketlists item</td> | ||
<td>GET /bucketlists/:id/items/:itemId </td> | ||
<td>False</td> | ||
</tr> | ||
|
||
<tr> | ||
<td>Update bucketlist item record</td> | ||
<td>PUT /bucketlists/:id/items/:itemId </td> | ||
<td>False</td> | ||
</tr> | ||
|
||
<tr> | ||
<td>Delete bucketlist item record</td> | ||
<td>DELETE /bucketlists/:id/items/:itemId </td> | ||
<td>False</td> | ||
</tr> | ||
|
||
</table> | ||
|
||
## Dependecies | ||
All dependecies can be found in requirements.txt | ||
|
||
## How to use | ||
- Clone project git clone `` git@github.com:andela-snwuguru/bucketlist-api.git `` | ||
- Create a virtual environment `` mkvirtualenv bucketlist `` | ||
- Install dependecies `` pip install -r requirements.txt `` | ||
- Navigate to project folder `` cd ~/bucketlist-api `` | ||
- Run migrationscript | ||
``` | ||
python script.py db migrate | ||
python script.py db upgrade | ||
``` | ||
- Run Project `` python run.py `` | ||
|
||
## Sample Request | ||
|
||
#### Register new User | ||
``` | ||
Request | ||
-------- | ||
http POST http://127.0.0.1:5000/api/v1.0/auth/register username=guru password=test email=guru@mail.com | ||
Response | ||
-------- | ||
{ | ||
"data": { | ||
"date_created": "2016-05-19 19:37:20", | ||
"date_modified": "2016-05-19 19:37:20", | ||
"email": "guru@mail.com", | ||
"id": 7, | ||
"username": "guru" | ||
} | ||
} | ||
``` | ||
|
||
#### Retrieve Access Token | ||
``` | ||
Request | ||
-------- | ||
http POST http://127.0.0.1:5000/api/v1.0/auth/login username=guru password=test | ||
Response | ||
-------- | ||
{ | ||
"data": { | ||
"date_created": "2016-05-19 19:37:20", | ||
"date_modified": "2016-05-19 19:37:20", | ||
"email": "guru@mail.com", | ||
"id": 7, | ||
"username": "guru" | ||
}, | ||
"token": "098f6bcd4621d373cade4e832627b4f6|7|.Ch-n_A._bH9Hx_kpibiIlRHvFRZbVt-6UM" | ||
} | ||
``` | ||
|
||
### Documentation | ||
|
||
Api documentation is still in progress, it Will soon be available. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from flask import Flask | ||
from flask_sqlalchemy import SQLAlchemy | ||
from flask import request | ||
|
||
app = Flask(__name__) | ||
|
||
#server = request.args.get('server','production').lower() | ||
app.config.from_object('production_config') | ||
db = SQLAlchemy(app) | ||
|
||
from app import views |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
from flask_restful import reqparse | ||
import hashlib | ||
from itsdangerous import TimestampSigner | ||
from app import db | ||
|
||
encrypt_key = 'bucketlists api' | ||
|
||
def save(model): | ||
""" Save a row in the database """ | ||
try: | ||
db.session.add(model) | ||
db.session.commit() | ||
return True | ||
except: | ||
return False | ||
|
||
def delete(model): | ||
""" Deletes a row from the database """ | ||
try: | ||
db.session.delete(model) | ||
db.session.commit() | ||
return True | ||
except: | ||
return False | ||
|
||
|
||
def get_user_id_from_token(token): | ||
""" | ||
This method extracts the user id from provided access token | ||
""" | ||
data = token.split('|') | ||
try: | ||
return data[1] | ||
except: | ||
return 0 | ||
|
||
def validate_args(fields={}): | ||
""" | ||
This method helps to parse and validate provided parameters. | ||
It will return parsed argument if the require fields are in request | ||
""" | ||
parser = reqparse.RequestParser() | ||
for field in fields.keys(): | ||
help_message = field + ' can not be blank' | ||
parser.add_argument(field, required=fields[field], help=help_message) | ||
|
||
return parser.parse_args() | ||
|
||
def md5(string): | ||
""" | ||
This method will return md5 hash of a given string | ||
""" | ||
return hashlib.md5(string.encode("utf")).hexdigest() | ||
|
||
def encrypt(string): | ||
""" | ||
This method will return encrypted version of a string. | ||
It will return False if encryption fails | ||
""" | ||
try: | ||
signer = TimestampSigner(encrypt_key) | ||
return signer.sign(string) | ||
except: | ||
return False | ||
|
||
def decrypt(string, max_age=15000): | ||
""" | ||
This method will return decrypted version of an encrypted string. | ||
If age of encryption is greater than max age it will return False | ||
""" | ||
try: | ||
signer = TimestampSigner(encrypt_key) | ||
return signer.unsign(string, max_age=max_age) | ||
except: | ||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
from app import db | ||
from datetime import datetime | ||
from app.helper import encrypt, decrypt | ||
|
||
|
||
class BucketListModel(db.Model): | ||
id = db.Column(db.Integer(), primary_key=True) | ||
name = db.Column(db.String(255), unique=True) | ||
created_by = db.Column(db.Integer, db.ForeignKey('user.id')) | ||
date_created = db.Column(db.DateTime, default=db.func.current_timestamp()) | ||
date_modified = db.Column(db.DateTime, default=db.func.current_timestamp(), onupdate=db.func.current_timestamp()) | ||
user = db.relationship('User', backref=db.backref('bucketlists', lazy='dynamic')) | ||
|
||
def __init__(self, name, user): | ||
self.name = name | ||
self.user = user | ||
|
||
def get(self): | ||
return { | ||
'id':self.id, | ||
'name':self.name, | ||
'created_by':self.user.username, | ||
'date_created':str(self.date_created), | ||
'date_modified':str(self.date_modified) | ||
} | ||
|
||
def __repr__(self): | ||
return '<BucketListModel %r>' % self.name | ||
|
||
|
||
class BucketListItemModel(db.Model): | ||
id = db.Column(db.Integer(), primary_key=True) | ||
task = db.Column(db.String(255)) | ||
done = db.Column(db.Boolean(), default=False) | ||
date_created = db.Column(db.DateTime, default=db.func.current_timestamp()) | ||
date_modified = db.Column(db.DateTime, default=db.func.current_timestamp(), onupdate=db.func.current_timestamp()) | ||
bucketlist_id = db.Column(db.Integer, db.ForeignKey('bucket_list_model.id')) | ||
bucketlist = db.relationship('BucketListModel', backref=db.backref('items', lazy='dynamic')) | ||
|
||
def __init__(self, task, bucketlist): | ||
self.task = task | ||
self.bucketlist = bucketlist | ||
|
||
def get(self): | ||
return { | ||
'id':self.id, | ||
'task':self.task, | ||
'done':self.done, | ||
'bucketlists':self.bucketlist.name, | ||
'date_created':str(self.date_created), | ||
'date_modified':str(self.date_modified) | ||
} | ||
|
||
def __repr__(self): | ||
return '<BucketListItemModel %r>' % self.task | ||
|
||
|
||
class User(db.Model): | ||
id = db.Column(db.Integer, primary_key=True) | ||
username = db.Column(db.String(100), unique=True) | ||
password = db.Column(db.String(20)) | ||
email = db.Column(db.String(200), unique=True) | ||
date_created = db.Column(db.DateTime, default=db.func.current_timestamp()) | ||
date_modified = db.Column(db.DateTime, default=db.func.current_timestamp(), onupdate=db.func.current_timestamp()) | ||
|
||
def __init__(self, username, email, password): | ||
self.username = username | ||
self.email = email | ||
self.password = password | ||
|
||
def __repr__(self): | ||
return '<User %r>' % self.username | ||
|
||
def get(self): | ||
return { | ||
'id':self.id, | ||
'username':self.username, | ||
'email':self.email, | ||
'date_created':str(self.date_created), | ||
'date_modified':str(self.date_modified), | ||
} | ||
|
||
def generate_token(self): | ||
string = str(self.password) + '|' + str(self.id) + '|' | ||
return encrypt(string) |
Oops, something went wrong.