Skip to content

Commit

Permalink
Merge 76ef957 into 1f4daeb
Browse files Browse the repository at this point in the history
  • Loading branch information
Nwuguru Sunday committed Sep 13, 2016
2 parents 1f4daeb + 76ef957 commit 784f3cc
Show file tree
Hide file tree
Showing 96 changed files with 4,515 additions and 16 deletions.
6 changes: 6 additions & 0 deletions .bowerrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"directory": "bucketlist/static/lib",
"analytics": false,
"timeout": 120000,
"interactive": false
}
1 change: 1 addition & 0 deletions .coverage
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": {}}
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
*.pyc
.env.yml
.env.py
db.sqlite3
__pycache__
bucketlist/bucketlist/development.py
bucketlist/static_cdn/*
bucketlist/static_cdn/*
.DS_Store
11 changes: 11 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
language: python
python:
- "2.7"
# command to install dependencies
install:
- pip install -r requirements.txt
script:
- cd bucketlist
- python manage.py test
after_success:
- coveralls
2 changes: 1 addition & 1 deletion Procfile
Original file line number Diff line number Diff line change
@@ -1 +1 @@
web: gunicorn bucketlist.wsgi --pythonpath=bucketlist --log-file=-
web: python bucketlist/manage.py migrate; gunicorn bucketlist.wsgi --pythonpath=bucketlist --log-file=-
79 changes: 77 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,77 @@
# bucketlist-django
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.
# Django Powered Bucketlist Application

[![Build Status](https://travis-ci.org/andela-snwuguru/bucketlist-django.svg?branch=master)](https://travis-ci.org/andela-snwuguru/bucketlist-django) [![Coverage Status](https://coveralls.io/repos/github/andela-snwuguru/bucketlist-django/badge.svg?branch=master)](https://coveralls.io/github/andela-snwuguru/bucketlist-django?branch=master)

Nobody lives forever, it is what we do or archive that lives forever in the heart of men. This application gives you little hope to archive that. Pen it down, challenge yourself to do more.

### Technology used

- Django - Easy and faster way to build better web applications.
- Djangorestframework - Django REST framework is a powerful and flexible toolkit for building Web APIs in Django powered apps.
- AngularJS - AngularJS lets you extend HTML vocabulary for your application.
- AngularJS Material - Angular Material is both a UI Component framework and a reference implementation of Google's Material Design Specification.
- Django swagger - An API documentation generator for Swagger UI and Django REST Framework.

### API Documentation

The API documentation can be found <a href="https://littlehope.herokuapp.com/api/v1/docs">here</a>

### How to use

To install and run this application locally, you need to have python installed on your machine.

#### Installation

To install the build locally

- `` $ git clone https://github.com/andela-snwuguru/bucketlist-django.git ``
- `` $ cd bucketlist-django ``
- `` $ pip install -r requirements.txt ``

#### Set Up your environment key

#### bucketlist-django/bucketlist/bucketlist/development.py

Development.py file is required to get the database configuration. See content below
```
import os, sys
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'testdb.sqlite3') if 'test' in sys.argv else os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
DEBUG = True
```

#### bucketlist-django/.env.py
.env.py file is also required to configure secured information. See content below.

```
SECRET_KEY = "your-secret-code"
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = 'oauth2 key from google'
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = 'oauth2 secret from google'
SOCIAL_AUTH_FACEBOOK_KEY = 'app id'
SOCIAL_AUTH_FACEBOOK_SECRET = 'app secret'
SOCIAL_AUTH_TWITTER_KEY = 'customer key'
SOCIAL_AUTH_TWITTER_SECRET = 'customer secret'
```


#### Run your build

`` $ python bucketlist/manage.py runserver ``

#### Running the test

`` $ cd bucketlist && python manage.py test ``

### How to Contribute

This is an open source project, feel free to fork the repo, add functionality to the project and raise a pull request.
19 changes: 19 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "bucketlist-django",
"description": "Pen it down, push yourself to do more",
"scripts": {},
"env": {},
"formation": {
"web": {
"quantity": 1
}
},
"addons": [
"heroku-postgresql"
],
"buildpacks": [
{
"url": "heroku/python"
}
]
}
30 changes: 30 additions & 0 deletions bower.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "Bucketlists",
"version": "1.1.7",
"authors": [
"Nwuguru Sunday <sunday.nwuguru@andela.com>"
],
"description": "Challenge yourself to do more",
"main": "manage.py",
"keywords": [
"angularjs",
"Python",
"Django"
],
"license": "GNU",
"homepage": "http://littlehope.herokuapp.com/",
"private": false,
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"angular": "~1.5.3",
"angular-sanitize": "~1.5.3",
"angular-animate": "~1.5.3",
"angular-material": "~1.1.0-rc2"
}
}
1 change: 1 addition & 0 deletions bucketlist/.coverage

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions bucketlist/bucketlist/production.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import os, sys
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
import dj_database_url

if 'test' in sys.argv:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'testdb.sqlite3'),
}
}
SECRET_KEY = "test-secret"


else:
DATABASES = {
'default': dj_database_url.config()
}
DEBUG = False
77 changes: 68 additions & 9 deletions bucketlist/bucketlist/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,71 @@
"""

import os
import datetime
from django_envie.workroom import convertfiletovars

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
convertfiletovars()


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '@f*bztzc-o%4zoas@34fwdss)^+98v+b96ea_w!(+uitaw&#_e'
SECRET_KEY = os.getenv('SECRET_KEY')

# SECURITY WARNING: don't run with debug turned on in production!
import dj_database_url

DATABASES = {
'default': dj_database_url.config()
}

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

ALLOWED_HOSTS = ['*']

DEBUG = False
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = os.getenv('SOCIAL_AUTH_GOOGLE_OAUTH2_KEY')
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = os.getenv('SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET')
SOCIAL_AUTH_FACEBOOK_KEY = os.getenv('SOCIAL_AUTH_FACEBOOK_KEY')
SOCIAL_AUTH_FACEBOOK_SECRET = os.getenv('SOCIAL_AUTH_FACEBOOK_SECRET')
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']
SOCIAL_AUTH_TWITTER_KEY = os.getenv('SOCIAL_AUTH_TWITTER_KEY')
SOCIAL_AUTH_TWITTER_SECRET = os.getenv('SOCIAL_AUTH_TWITTER_SECRET')
SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/'
SOCIAL_AUTH_LOGIN_URL = '/'

try:
from .development import *
except ImportError:
pass
from .production import *

# REST

# Application definition
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
),
}

SWAGGER_SETTINGS = {
'enabled_methods': [
'get',
'post',
'put',
'delete'
],
}

JWT_AUTH = {
'JWT_ALLOW_REFRESH': True,
'JWT_AUTH_HEADER_PREFIX': 'DBL',
'JWT_RESPONSE_PAYLOAD_HANDLER': 'bucketlists.api.helper.jwt_response_payload_handler',
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=1200),

}

# Application definition

Expand All @@ -49,6 +86,19 @@
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'bucketlists',
'rest_framework',
'social.apps.django_app.default',
'django_nose',
'rest_framework_swagger',
]

# Use nose to run all tests
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'

NOSE_ARGS = [
'--with-coverage',
'--cover-package=bucketlists.api,bucketlists.views',
]

MIDDLEWARE_CLASSES = [
Expand All @@ -62,19 +112,28 @@
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

AUTHENTICATION_BACKENDS = (
'social.backends.facebook.FacebookOAuth2',
'social.backends.google.GoogleOAuth2',
'social.backends.twitter.TwitterOAuth',
'django.contrib.auth.backends.ModelBackend',
)

ROOT_URLCONF = 'bucketlist.urls'

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'social.apps.django_app.context_processors.backends',
'social.apps.django_app.context_processors.login_redirect',
],
},
},
Expand Down
7 changes: 6 additions & 1 deletion bucketlist/bucketlist/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/v1/docs/', include('rest_framework_swagger.urls')),
url('', include('social.apps.django_app.urls', namespace='social')),
url(r'^', include('bucketlists.urls', namespace='bucketlists')),
url(r'^api/v1/',
include('bucketlists.api.urls', namespace='bucketlists-api')),
]
Empty file.
25 changes: 25 additions & 0 deletions bucketlist/bucketlists/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from django.contrib import admin
from .models import *


class BucketListAdmin(admin.ModelAdmin):
list_display = ['name', 'date_modified', 'date_created']
list_display_links = ['name']
list_filter = ['date_created']
search_fields = ['name']

class Meta:
model = BucketList


class BucketListItemAdmin(admin.ModelAdmin):
list_display = ['task', 'bucketlist', 'date_modified', 'date_created']
list_display_links = ['task']
list_filter = ['date_created', 'bucketlist']
search_fields = ['task']

class Meta:
model = BucketListItem

admin.site.register(BucketList, BucketListAdmin)
admin.site.register(BucketListItem, BucketListItemAdmin)
Empty file.
19 changes: 19 additions & 0 deletions bucketlist/bucketlists/api/helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from django.shortcuts import get_object_or_404

from bucketlists.models import BucketList


def get_bucketlist_by_api_view(obj):
bucketlist_id = obj.kwargs.get('id',0)
return get_object_or_404(
BucketList,
id=int(bucketlist_id),
user=obj.request.user
)


def jwt_response_payload_handler(token, user=None, request=None):
return {
'token': token,
'user': user.username
}
5 changes: 5 additions & 0 deletions bucketlist/bucketlists/api/pagination.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from rest_framework.pagination import PageNumberPagination


class CustomPageNumberPagination(PageNumberPagination):
page_size = 10
7 changes: 7 additions & 0 deletions bucketlist/bucketlists/api/permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from rest_framework.permissions import BasePermission


class IsOwner(BasePermission):

def has_object_permission(self, request, view, obj):
return request.user == obj.user
Loading

0 comments on commit 784f3cc

Please sign in to comment.