From 847d5afd548b10b49ac249ea4c89fb2ceb9334fb Mon Sep 17 00:00:00 2001 From: Ricardo Lobo Date: Sat, 20 Feb 2016 06:01:37 +0000 Subject: [PATCH] barebones experimental version, coded under pressure in the lcd coding night #1 --- .dockerignore | 28 +++ .gitignore | 18 ++ Dockerfile | 57 ++++++ dist/initialize.sh | 15 ++ dist/lcdmarket | 19 ++ dist/lcdmarket.conf | 21 ++ dist/requirements.txt | 10 + lcdmarket/__init__.py | 0 lcdmarket/api/__init__.py | 0 lcdmarket/api/admin.py | 3 + lcdmarket/api/apps.py | 5 + lcdmarket/api/migrations/0001_initial.py | 37 ++++ .../0001_squashed_0011_auto_20160211_2005.py | 110 +++++++++++ .../api/migrations/0002_account_avatar.py | 20 ++ lcdmarket/api/migrations/0002_tag.py | 25 +++ .../api/migrations/0003_auto_20160220_0343.py | 78 ++++++++ lcdmarket/api/migrations/0003_project.py | 39 ++++ .../api/migrations/0004_auto_20160211_1115.py | 25 +++ .../api/migrations/0004_auto_20160220_0346.py | 25 +++ .../api/migrations/0005_auto_20160211_1639.py | 39 ++++ .../api/migrations/0005_auto_20160220_0348.py | 20 ++ .../api/migrations/0006_auto_20160211_1640.py | 50 +++++ .../api/migrations/0006_auto_20160220_0352.py | 20 ++ .../api/migrations/0007_auto_20160211_1641.py | 30 +++ .../api/migrations/0007_auto_20160220_0402.py | 35 ++++ .../api/migrations/0008_auto_20160211_1641.py | 31 +++ .../api/migrations/0008_auto_20160220_0504.py | 25 +++ .../api/migrations/0009_auto_20160211_1642.py | 24 +++ .../api/migrations/0010_auto_20160211_2003.py | 39 ++++ .../api/migrations/0011_auto_20160211_2005.py | 27 +++ lcdmarket/api/migrations/__init__.py | 0 lcdmarket/api/models.py | 127 ++++++++++++ lcdmarket/api/serializers.py | 37 ++++ lcdmarket/api/views.py | 54 ++++++ lcdmarket/settings.py | 183 ++++++++++++++++++ lcdmarket/urls.py | 25 +++ lcdmarket/wsgi.py | 16 ++ manage.py | 10 + readme.md | 5 + 39 files changed, 1332 insertions(+) create mode 100644 .dockerignore create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100755 dist/initialize.sh create mode 100644 dist/lcdmarket create mode 100644 dist/lcdmarket.conf create mode 100644 dist/requirements.txt create mode 100644 lcdmarket/__init__.py create mode 100644 lcdmarket/api/__init__.py create mode 100644 lcdmarket/api/admin.py create mode 100644 lcdmarket/api/apps.py create mode 100644 lcdmarket/api/migrations/0001_initial.py create mode 100644 lcdmarket/api/migrations/0001_squashed_0011_auto_20160211_2005.py create mode 100644 lcdmarket/api/migrations/0002_account_avatar.py create mode 100644 lcdmarket/api/migrations/0002_tag.py create mode 100644 lcdmarket/api/migrations/0003_auto_20160220_0343.py create mode 100644 lcdmarket/api/migrations/0003_project.py create mode 100644 lcdmarket/api/migrations/0004_auto_20160211_1115.py create mode 100644 lcdmarket/api/migrations/0004_auto_20160220_0346.py create mode 100644 lcdmarket/api/migrations/0005_auto_20160211_1639.py create mode 100644 lcdmarket/api/migrations/0005_auto_20160220_0348.py create mode 100644 lcdmarket/api/migrations/0006_auto_20160211_1640.py create mode 100644 lcdmarket/api/migrations/0006_auto_20160220_0352.py create mode 100644 lcdmarket/api/migrations/0007_auto_20160211_1641.py create mode 100644 lcdmarket/api/migrations/0007_auto_20160220_0402.py create mode 100644 lcdmarket/api/migrations/0008_auto_20160211_1641.py create mode 100644 lcdmarket/api/migrations/0008_auto_20160220_0504.py create mode 100644 lcdmarket/api/migrations/0009_auto_20160211_1642.py create mode 100644 lcdmarket/api/migrations/0010_auto_20160211_2003.py create mode 100644 lcdmarket/api/migrations/0011_auto_20160211_2005.py create mode 100644 lcdmarket/api/migrations/__init__.py create mode 100644 lcdmarket/api/models.py create mode 100644 lcdmarket/api/serializers.py create mode 100644 lcdmarket/api/views.py create mode 100644 lcdmarket/settings.py create mode 100644 lcdmarket/urls.py create mode 100644 lcdmarket/wsgi.py create mode 100755 manage.py create mode 100644 readme.md diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..6944be6 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,28 @@ +# linux temporary files +*~ + +# emacs temporary files +\#*\# + +# ignore itself +.dockerignore + +# ignore Dockerfile +Dockerfile + +# ignore docker compose file +docker-compose.yml + +# ignore git +.git +.gitignore +.gitmodules + +# ignore coverage files +.coverage +.cover + +# ignore static files +# except default +lcd/api/static +!lcd/api/static/media/default_400x400.png diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7d54534 --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +# linux temporary files +*~ + +# emacs temporary files +\#*\# + +# ignore coverage files +.coverage +cover + +# python cache +__pycache__ + +# ignore static files +lcdmarket/api/static/ + +# sqlite3 database +*.sqlite3 \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1e3aeb2 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,57 @@ +# Use this as a base image +FROM ubuntu:14.04 + +# Maintainer Info +MAINTAINER Ricardo Lobo + +# set default environment +ENV APP_IN_PRODUCTION=false + +# update repos and install +# pip3, supervisor, nginx +# python postgres adapter +RUN apt-get update && \ +apt-get -y install \ +python3-pip \ +supervisor \ +nginx \ +python3-psycopg2 + +# install Pillow dependencies +RUN apt-get -y install \ +libtiff5-dev \ +libjpeg8-dev \ +zlib1g-dev \ +libfreetype6-dev \ +liblcms2-dev \ +libwebp-dev \ +tcl8.6-dev \ +tk8.6-dev \ +python-tk + +# development dependencies +RUN apt-get -y install nano + +# copy code to image +COPY . /var/www/ + +# set the working directory +WORKDIR /var/www/ + +# install django and django dependencies using pip3 +RUN pip3 install -r /var/www/dist/requirements.txt + +# make init script executable +RUN chmod ug+x /var/www/dist/initialize.sh + +# set locale +RUN locale-gen pt_PT.UTF-8 + +# remove nginx default site +RUN rm /etc/nginx/sites-enabled/default + +# copy supervisor configuration +COPY ./dist/lcdmarket.conf /etc/supervisor/conf.d/lcdmarket.conf + +# default command +CMD ["/usr/bin/supervisord"] \ No newline at end of file diff --git a/dist/initialize.sh b/dist/initialize.sh new file mode 100755 index 0000000..fb4941a --- /dev/null +++ b/dist/initialize.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# copy and enable lcd site api virtual server +cp ./dist/lcdmarket /etc/nginx/sites-available/ +ln -s /etc/nginx/sites-available/lcdmarket /etc/nginx/sites-enabled/lcdmarket + +# in development mode +if [ "$APP_IN_PRODUCTION" != "true" ]; then + # migrations are automatic + python3 /var/www/manage.py migrate --noinput + # static files are collected on container init + python3 /var/www/manage.py collectstatic --noinput +fi + +exit 0 diff --git a/dist/lcdmarket b/dist/lcdmarket new file mode 100644 index 0000000..1c3f4b4 --- /dev/null +++ b/dist/lcdmarket @@ -0,0 +1,19 @@ +server { + listen 80; + + # traffic related to static files are nginx responsability + location /static/ { + alias /var/www/lcdmarket/api/static/; + } + + # remaining traffic is passed to gunicorn that is listening + # on port 8001, we are adding some headers here to the original + # request + location / { + proxy_pass http://127.0.0.1:8000; + proxy_set_header X-Forwarded-Host $server_name; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $http_host; + add_header P3P 'CP="ALL DSP COR PSAa PSDa OUR NOR ONL UNI COM NAV"'; + } +} diff --git a/dist/lcdmarket.conf b/dist/lcdmarket.conf new file mode 100644 index 0000000..a3d8b35 --- /dev/null +++ b/dist/lcdmarket.conf @@ -0,0 +1,21 @@ +[supervisord] +nodaemon=true + +[program:initialize] +command=/bin/bash /var/www/dist/initialize.sh +exitcodes=0 +startsecs=0 +priority=10 + +[program:nginx] +command=/usr/sbin/nginx -g "daemon off;" +autostart=true +autorestart=true +priority=20 + +[program:gunicorn] +directory=/var/www/ +command=/usr/local/bin/gunicorn -b 127.0.0.1:8000 -w 4 lcdmarket.wsgi +autostart=true +autorestart=true +priority=20 diff --git a/dist/requirements.txt b/dist/requirements.txt new file mode 100644 index 0000000..2404172 --- /dev/null +++ b/dist/requirements.txt @@ -0,0 +1,10 @@ +gunicorn +django +djangorestframework +django-cors-headers +django-filter +djangorestframework-jwt +django-nose +coverage +Pillow +drf-nested-routers diff --git a/lcdmarket/__init__.py b/lcdmarket/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lcdmarket/api/__init__.py b/lcdmarket/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lcdmarket/api/admin.py b/lcdmarket/api/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/lcdmarket/api/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/lcdmarket/api/apps.py b/lcdmarket/api/apps.py new file mode 100644 index 0000000..d87006d --- /dev/null +++ b/lcdmarket/api/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class ApiConfig(AppConfig): + name = 'api' diff --git a/lcdmarket/api/migrations/0001_initial.py b/lcdmarket/api/migrations/0001_initial.py new file mode 100644 index 0000000..9f8b32f --- /dev/null +++ b/lcdmarket/api/migrations/0001_initial.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-08 19:27 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Account', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('email', models.EmailField(max_length=254, unique=True)), + ('first_name', models.CharField(max_length=40)), + ('last_name', models.CharField(max_length=40)), + ('certification_name', models.CharField(blank=True, max_length=255, null=True)), + ('is_superuser', models.BooleanField(default=False)), + ('is_active', models.BooleanField(default=True)), + ('is_staff', models.BooleanField(default=False)), + ('is_public', models.BooleanField(default=False)), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/lcdmarket/api/migrations/0001_squashed_0011_auto_20160211_2005.py b/lcdmarket/api/migrations/0001_squashed_0011_auto_20160211_2005.py new file mode 100644 index 0000000..af0cc85 --- /dev/null +++ b/lcdmarket/api/migrations/0001_squashed_0011_auto_20160211_2005.py @@ -0,0 +1,110 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-12 22:17 +from __future__ import unicode_literals + +from django.conf import settings +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + replaces = [('api', '0001_initial'), ('api', '0002_tag'), ('api', '0003_project'), ('api', '0004_auto_20160211_1115'), ('api', '0005_auto_20160211_1639'), ('api', '0006_auto_20160211_1640'), ('api', '0007_auto_20160211_1641'), ('api', '0008_auto_20160211_1641'), ('api', '0009_auto_20160211_1642'), ('api', '0010_auto_20160211_2003'), ('api', '0011_auto_20160211_2005')] + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Account', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('email', models.EmailField(max_length=254, unique=True)), + ('first_name', models.CharField(max_length=40)), + ('last_name', models.CharField(max_length=40)), + ('certification_name', models.CharField(blank=True, max_length=255, null=True)), + ('is_superuser', models.BooleanField(default=False)), + ('is_active', models.BooleanField(default=True)), + ('is_staff', models.BooleanField(default=False)), + ('is_public', models.BooleanField(default=False)), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Tag', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50, unique=True, validators=[django.core.validators.RegexValidator('^[a-z0-9_ \\-]*$', message='Use only lowercase letters, and numbers, - or _.'), django.core.validators.MinLengthValidator(3, message='Mininum Length of 3 chars.')])), + ('created', models.DateTimeField(auto_now_add=True, null=True)), + ('updated', models.DateTimeField(auto_now=True, null=True)), + ], + ), + migrations.CreateModel( + name='Project', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=75, validators=[django.core.validators.MinLengthValidator(2)])), + ('deleted', models.BooleanField(default=False)), + ('public', models.BooleanField(default=False)), + ('cover', models.ImageField(default='default_400x400.png', upload_to='')), + ('state', models.IntegerField(default=1)), + ('slug', models.SlugField(max_length=75, unique=True)), + ('description', models.TextField(blank=True, null=True)), + ('goals', models.TextField(blank=True, null=True)), + ('requirements', models.TextField(blank=True, null=True)), + ('assets', models.TextField(blank=True, null=True)), + ('start_date', models.DateTimeField(null=True)), + ('end_date', models.DateTimeField(null=True)), + ('order', models.PositiveSmallIntegerField()), + ], + ), + migrations.CreateModel( + name='ProjectAreas', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Project')), + ('tag', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Tag')), + ], + ), + migrations.AddField( + model_name='project', + name='areas', + field=models.ManyToManyField(through='api.ProjectAreas', to='api.Tag'), + ), + migrations.CreateModel( + name='ProjectContributors', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('is_manager', models.BooleanField(default=False)), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ('contributor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Tag')), + ], + ), + migrations.AddField( + model_name='projectcontributors', + name='project', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Project'), + ), + migrations.AddField( + model_name='project', + name='contributors', + field=models.ManyToManyField(through='api.ProjectContributors', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='projectcontributors', + name='contributor', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/lcdmarket/api/migrations/0002_account_avatar.py b/lcdmarket/api/migrations/0002_account_avatar.py new file mode 100644 index 0000000..b914bb9 --- /dev/null +++ b/lcdmarket/api/migrations/0002_account_avatar.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-17 18:25 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0001_squashed_0011_auto_20160211_2005'), + ] + + operations = [ + migrations.AddField( + model_name='account', + name='avatar', + field=models.ImageField(default='default_avatar_200x200.png', upload_to=''), + ), + ] diff --git a/lcdmarket/api/migrations/0002_tag.py b/lcdmarket/api/migrations/0002_tag.py new file mode 100644 index 0000000..8e04280 --- /dev/null +++ b/lcdmarket/api/migrations/0002_tag.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-08 21:32 +from __future__ import unicode_literals + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Tag', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50, unique=True, validators=[django.core.validators.RegexValidator('^[a-z0-9_ \\-]*$', message='Use only lowercase letters, and numbers, - or _.'), django.core.validators.MinLengthValidator(3, message='Mininum Length of 3 chars.')])), + ('created', models.DateTimeField(auto_now_add=True, null=True)), + ('updated', models.DateTimeField(auto_now=True, null=True)), + ], + ), + ] diff --git a/lcdmarket/api/migrations/0003_auto_20160220_0343.py b/lcdmarket/api/migrations/0003_auto_20160220_0343.py new file mode 100644 index 0000000..d60ebd2 --- /dev/null +++ b/lcdmarket/api/migrations/0003_auto_20160220_0343.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-20 03:43 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0002_account_avatar'), + ] + + operations = [ + migrations.CreateModel( + name='Product', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50)), + ('description', models.TextField()), + ('value', models.DecimalField(decimal_places=2, max_digits=5)), + ('is_approved', models.BooleanField()), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ], + ), + migrations.CreateModel( + name='Transfer', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50)), + ('amount', models.DecimalField(decimal_places=2, max_digits=5)), + ('is_pendent', models.BooleanField()), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ], + ), + migrations.RemoveField( + model_name='project', + name='areas', + ), + migrations.RemoveField( + model_name='project', + name='contributors', + ), + migrations.RemoveField( + model_name='projectareas', + name='project', + ), + migrations.RemoveField( + model_name='projectareas', + name='tag', + ), + migrations.RemoveField( + model_name='projectcontributors', + name='contributor', + ), + migrations.RemoveField( + model_name='projectcontributors', + name='project', + ), + migrations.RemoveField( + model_name='account', + name='certification_name', + ), + migrations.DeleteModel( + name='Project', + ), + migrations.DeleteModel( + name='ProjectAreas', + ), + migrations.DeleteModel( + name='ProjectContributors', + ), + migrations.DeleteModel( + name='Tag', + ), + ] diff --git a/lcdmarket/api/migrations/0003_project.py b/lcdmarket/api/migrations/0003_project.py new file mode 100644 index 0000000..69abefb --- /dev/null +++ b/lcdmarket/api/migrations/0003_project.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-08 21:57 +from __future__ import unicode_literals + +from django.conf import settings +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0002_tag'), + ] + + operations = [ + migrations.CreateModel( + name='Project', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=75, validators=[django.core.validators.MinLengthValidator(2)])), + ('deleted', models.BooleanField(default=False)), + ('public', models.BooleanField(default=False)), + ('cover', models.ImageField(default='default_400x400', upload_to='')), + ('state', models.IntegerField(default=1)), + ('slug', models.SlugField(max_length=75, unique=True)), + ('description', models.TextField(blank=True, null=True)), + ('goals', models.TextField(blank=True, null=True)), + ('requirements', models.TextField(blank=True, null=True)), + ('assets', models.TextField(blank=True, null=True)), + ('start_date', models.DateTimeField(null=True)), + ('end_date', models.DateTimeField(null=True)), + ('order', models.PositiveSmallIntegerField()), + ('areas', models.ManyToManyField(related_name='project_tags', to='api.Tag')), + ('contributors', models.ManyToManyField(related_name='project_contributors', to=settings.AUTH_USER_MODEL)), + ('managers', models.ManyToManyField(related_name='project_manager', to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/lcdmarket/api/migrations/0004_auto_20160211_1115.py b/lcdmarket/api/migrations/0004_auto_20160211_1115.py new file mode 100644 index 0000000..d3b2ac0 --- /dev/null +++ b/lcdmarket/api/migrations/0004_auto_20160211_1115.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-11 11:15 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0003_project'), + ] + + operations = [ + migrations.AlterField( + model_name='project', + name='areas', + field=models.ManyToManyField(related_name='areas', to='api.Tag'), + ), + migrations.AlterField( + model_name='project', + name='cover', + field=models.ImageField(default='default_400x400.png', upload_to=''), + ), + ] diff --git a/lcdmarket/api/migrations/0004_auto_20160220_0346.py b/lcdmarket/api/migrations/0004_auto_20160220_0346.py new file mode 100644 index 0000000..ffba7c2 --- /dev/null +++ b/lcdmarket/api/migrations/0004_auto_20160220_0346.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-20 03:46 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0003_auto_20160220_0343'), + ] + + operations = [ + migrations.AlterField( + model_name='product', + name='value', + field=models.IntegerField(), + ), + migrations.AlterField( + model_name='transfer', + name='amount', + field=models.IntegerField(), + ), + ] diff --git a/lcdmarket/api/migrations/0005_auto_20160211_1639.py b/lcdmarket/api/migrations/0005_auto_20160211_1639.py new file mode 100644 index 0000000..8506473 --- /dev/null +++ b/lcdmarket/api/migrations/0005_auto_20160211_1639.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-11 16:39 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0004_auto_20160211_1115'), + ] + + operations = [ + migrations.CreateModel( + name='ProjectAreas', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ], + ), + migrations.AlterField( + model_name='project', + name='areas', + field=models.ManyToManyField(through='api.ProjectAreas', to='api.Tag'), + ), + migrations.AddField( + model_name='projectareas', + name='project', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Project'), + ), + migrations.AddField( + model_name='projectareas', + name='tag', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Tag'), + ), + ] diff --git a/lcdmarket/api/migrations/0005_auto_20160220_0348.py b/lcdmarket/api/migrations/0005_auto_20160220_0348.py new file mode 100644 index 0000000..c227e8a --- /dev/null +++ b/lcdmarket/api/migrations/0005_auto_20160220_0348.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-20 03:48 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0004_auto_20160220_0346'), + ] + + operations = [ + migrations.AlterField( + model_name='product', + name='is_approved', + field=models.BooleanField(default=False), + ), + ] diff --git a/lcdmarket/api/migrations/0006_auto_20160211_1640.py b/lcdmarket/api/migrations/0006_auto_20160211_1640.py new file mode 100644 index 0000000..448cf77 --- /dev/null +++ b/lcdmarket/api/migrations/0006_auto_20160211_1640.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-11 16:40 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0005_auto_20160211_1639'), + ] + + operations = [ + migrations.CreateModel( + name='Inter', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ], + ), + migrations.RemoveField( + model_name='projectareas', + name='project', + ), + migrations.RemoveField( + model_name='projectareas', + name='tag', + ), + migrations.AlterField( + model_name='project', + name='areas', + field=models.ManyToManyField(through='api.Inter', to='api.Tag'), + ), + migrations.DeleteModel( + name='ProjectAreas', + ), + migrations.AddField( + model_name='inter', + name='project', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Project'), + ), + migrations.AddField( + model_name='inter', + name='tag', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Tag'), + ), + ] diff --git a/lcdmarket/api/migrations/0006_auto_20160220_0352.py b/lcdmarket/api/migrations/0006_auto_20160220_0352.py new file mode 100644 index 0000000..90b48ee --- /dev/null +++ b/lcdmarket/api/migrations/0006_auto_20160220_0352.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-20 03:52 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0005_auto_20160220_0348'), + ] + + operations = [ + migrations.AlterField( + model_name='product', + name='description', + field=models.TextField(null=True), + ), + ] diff --git a/lcdmarket/api/migrations/0007_auto_20160211_1641.py b/lcdmarket/api/migrations/0007_auto_20160211_1641.py new file mode 100644 index 0000000..5abf8f8 --- /dev/null +++ b/lcdmarket/api/migrations/0007_auto_20160211_1641.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-11 16:41 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0006_auto_20160211_1640'), + ] + + operations = [ + migrations.RemoveField( + model_name='inter', + name='project', + ), + migrations.RemoveField( + model_name='inter', + name='tag', + ), + migrations.RemoveField( + model_name='project', + name='areas', + ), + migrations.DeleteModel( + name='Inter', + ), + ] diff --git a/lcdmarket/api/migrations/0007_auto_20160220_0402.py b/lcdmarket/api/migrations/0007_auto_20160220_0402.py new file mode 100644 index 0000000..3851a46 --- /dev/null +++ b/lcdmarket/api/migrations/0007_auto_20160220_0402.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-20 04:02 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0006_auto_20160220_0352'), + ] + + operations = [ + migrations.AddField( + model_name='transfer', + name='account', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='origin', to=settings.AUTH_USER_MODEL), + preserve_default=False, + ), + migrations.AddField( + model_name='transfer', + name='product', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='api.Product'), + preserve_default=False, + ), + migrations.AddField( + model_name='transfer', + name='target_account', + field=models.ForeignKey(default=2, on_delete=django.db.models.deletion.CASCADE, related_name='target', to=settings.AUTH_USER_MODEL), + preserve_default=False, + ), + ] diff --git a/lcdmarket/api/migrations/0008_auto_20160211_1641.py b/lcdmarket/api/migrations/0008_auto_20160211_1641.py new file mode 100644 index 0000000..5c37f5f --- /dev/null +++ b/lcdmarket/api/migrations/0008_auto_20160211_1641.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-11 16:41 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0007_auto_20160211_1641'), + ] + + operations = [ + migrations.CreateModel( + name='Inter', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Project')), + ('tag', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Tag')), + ], + ), + migrations.AddField( + model_name='project', + name='areas', + field=models.ManyToManyField(through='api.Inter', to='api.Tag'), + ), + ] diff --git a/lcdmarket/api/migrations/0008_auto_20160220_0504.py b/lcdmarket/api/migrations/0008_auto_20160220_0504.py new file mode 100644 index 0000000..dd8ca31 --- /dev/null +++ b/lcdmarket/api/migrations/0008_auto_20160220_0504.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-20 05:04 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0007_auto_20160220_0402'), + ] + + operations = [ + migrations.AddField( + model_name='account', + name='balance', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='transfer', + name='is_pendent', + field=models.BooleanField(default=True), + ), + ] diff --git a/lcdmarket/api/migrations/0009_auto_20160211_1642.py b/lcdmarket/api/migrations/0009_auto_20160211_1642.py new file mode 100644 index 0000000..982d418 --- /dev/null +++ b/lcdmarket/api/migrations/0009_auto_20160211_1642.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-11 16:42 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0008_auto_20160211_1641'), + ] + + operations = [ + migrations.RenameModel( + old_name='Inter', + new_name='ProjectAreas', + ), + migrations.AlterField( + model_name='project', + name='areas', + field=models.ManyToManyField(through='api.ProjectAreas', to='api.Tag'), + ), + ] diff --git a/lcdmarket/api/migrations/0010_auto_20160211_2003.py b/lcdmarket/api/migrations/0010_auto_20160211_2003.py new file mode 100644 index 0000000..ab417fc --- /dev/null +++ b/lcdmarket/api/migrations/0010_auto_20160211_2003.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-11 20:03 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0009_auto_20160211_1642'), + ] + + operations = [ + migrations.CreateModel( + name='ProjectContributors', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('is_manager', models.BooleanField(default=False)), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ('contributor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Tag')), + ], + ), + migrations.RemoveField( + model_name='project', + name='contributors', + ), + migrations.RemoveField( + model_name='project', + name='managers', + ), + migrations.AddField( + model_name='projectcontributors', + name='project', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Project'), + ), + ] diff --git a/lcdmarket/api/migrations/0011_auto_20160211_2005.py b/lcdmarket/api/migrations/0011_auto_20160211_2005.py new file mode 100644 index 0000000..9880b4c --- /dev/null +++ b/lcdmarket/api/migrations/0011_auto_20160211_2005.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-11 20:05 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0010_auto_20160211_2003'), + ] + + operations = [ + migrations.AddField( + model_name='project', + name='contributors', + field=models.ManyToManyField(through='api.ProjectContributors', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='projectcontributors', + name='contributor', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/lcdmarket/api/migrations/__init__.py b/lcdmarket/api/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lcdmarket/api/models.py b/lcdmarket/api/models.py new file mode 100644 index 0000000..12f31e5 --- /dev/null +++ b/lcdmarket/api/models.py @@ -0,0 +1,127 @@ +from django.db import models + +from django.contrib.auth.models import AbstractBaseUser +from django.contrib.auth.models import BaseUserManager +from django.conf import settings +from django.core.exceptions import ObjectDoesNotExist +from django.utils.text import slugify +from django.db.models import Max +from django.core.validators import MinLengthValidator, RegexValidator +from lcdmarket.api import states + +class AccountManager(BaseUserManager): + """ + Custom Account Model Manager + """ + + def create_user(self, email, password=None, **kwargs): + + if not email: + raise ValueError('Users must have a valid email address.') + + account = self.model( + email=self.normalize_email(email), + first_name=kwargs.get('first_name'), + last_name=kwargs.get('last_name') + ) + + account.set_password(password) + account.save() + + return account + + def create_superuser(self, email, password, **kwargs): + account = self.create_user(email, password, **kwargs) + account.is_superuser = True + account.save() + return account + +# here we are extending the default user model +class Account(AbstractBaseUser): + email = models.EmailField(unique=True) + avatar = models.ImageField(null=False, default="default_avatar_200x200.png") + first_name = models.CharField(max_length=40) + last_name = models.CharField(max_length=40) + balance = models.IntegerField(default=0) + is_superuser = models.BooleanField(default=False) + is_active = models.BooleanField(default=True) + is_staff = models.BooleanField(default=False) + is_public = models.BooleanField(default=False) + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now=True) + objects = AccountManager() + + @property + def full_name(self): + return ' '.join([self.first_name, self.last_name]) + + # we will use the email as the username credential + # the required field here is need because it's the way + # django wants it when extending the default model (?) + USERNAME_FIELD = 'email' + # these fields are used by the createsuperuser command + REQUIRED_FIELDS = ['first_name', 'last_name'] + + def __str__(self): + """ + Account string representation in python3 + """ + return self.email + + def get_short_name(self): + if self.first_name: + return self.first_name + else: + return None + + def has_perm(self, perm, obj=None): + return self.is_admin() + + def has_module_perms(self, app_label): + return self.is_admin() + + # we want is_admin to te used as a model property and + # not has a model method + # so he have set a @property, for an explanation and example see + # https://www.stavros.io/posts/how-replace-django-model-field-property/ + @property + def is_admin(self): + # admin is a user that satisfies all the following conditions + # is active, superuser and staff + return self.is_superuser and self.is_staff and self.is_active + + +class Product(models.Model): + name = models.CharField(max_length=50) + description = models.TextField(null=True) + value = models.IntegerField(null=False) + is_approved = models.BooleanField(default=False) + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now=True) + + def __str__(self): + return self.name + +class Transfer(models.Model): + name = models.CharField(max_length=50) + amount = models.IntegerField() + product = models.ForeignKey('Product') + account = models.ForeignKey('Account', related_name='origin') + target_account = models.ForeignKey('Account', related_name='target') + is_pendent = models.BooleanField(default=True) + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now=True) + + def __str__(self): + return 'transfer ' + str(self.id) + + def save(self, *args, **kwargs): + self.amount = self.product.value + # update account balance + self.account.balance = self.account.balance + self.product.value + self.account.save() + # update target account balance + self.target_account.balance = self.target_account.balance - self.product.value + self.target_account.save() + super(Transfer, self).save(*args, **kwargs) + diff --git a/lcdmarket/api/serializers.py b/lcdmarket/api/serializers.py new file mode 100644 index 0000000..449ddc6 --- /dev/null +++ b/lcdmarket/api/serializers.py @@ -0,0 +1,37 @@ +""" +Custom serializer classes for api application +""" + +from rest_framework import serializers +from lcdmarket.api import models + +class AccountSerializer(serializers.ModelSerializer): + """ + account serializer class + """ + password = serializers.CharField(write_only=True, required=False) + confirm_password = serializers.CharField(write_only=True, required=False) + + class Meta: + model = models.Account + fields = ('id', 'avatar', 'email', 'first_name', 'last_name', 'full_name', 'balance', 'is_superuser', 'password', 'confirm_password', + 'is_staff', 'is_active', 'is_public', 'created', 'updated', ) + read_only_fields = ('is_staff', 'is_active', 'is_superuser', 'balance', 'created', 'updated', 'balance') + + +class ProductSerializer(serializers.ModelSerializer): + """ + Product Serializer + """ + class Meta: + model = models.Product + fields = ('id', 'name', 'description', 'value') + +class TransferSerializer(serializers.ModelSerializer): + """ + Transfer Serializer + """ + class Meta: + model = models.Transfer + fields = ('id', 'amount', 'product', 'account', 'target_account', 'is_pendent') + read_only_fields = ('amount', 'is_pendent') diff --git a/lcdmarket/api/views.py b/lcdmarket/api/views.py new file mode 100644 index 0000000..f9a254f --- /dev/null +++ b/lcdmarket/api/views.py @@ -0,0 +1,54 @@ +""" +Api View Sets +""" + +from django.shortcuts import render +from django.core.exceptions import ObjectDoesNotExist +from lcdmarket.api import models +from rest_framework import viewsets +from rest_framework import mixins +from rest_framework import permissions +from lcdmarket.api import serializers +from lcdmarket.api import permissions as custom_permissions +from lcdmarket.api import utils +from rest_framework.response import Response +from rest_framework import status +from rest_framework.decorators import detail_route, list_route + +class AccountViewSet(viewsets.ModelViewSet): + """ + Account View Set + """ + serializer_class = serializers.AccountSerializer + search_fields = ('first_name', 'last_name', 'email') + permission_classes = [custom_permissions.AccountCustomPermission] + ordering_fields = ('id', ) + ordering = 'id' + + @list_route() + def me(self, request): + serializer = self.get_serializer(request.user) + return Response(serializer.data) + + def get_queryset(self): + queryset = models.Account.objects.all() + if self.request.user.is_authenticated() and self.request.user.is_admin: + return queryset + return queryset.filter(is_public=True) + +class ProductViewSet(viewsets.ModelViewSet): + """ + Product View Set + """ + queryset = models.Product.objects.all() + serializer_class = serializers.ProductSerializer + permission_classes = [permissions.IsAuthenticated] + + +class TransferViewSet(viewsets.ModelViewSet): + """ + Transfer View Set + """ + queryset = models.Transfer.objects.all() + serializer_class = serializers.TransferSerializer + permission_classes = [permissions.IsAuthenticated] diff --git a/lcdmarket/settings.py b/lcdmarket/settings.py new file mode 100644 index 0000000..97ad2d2 --- /dev/null +++ b/lcdmarket/settings.py @@ -0,0 +1,183 @@ +""" +Django settings for lcd project. + +Generated by 'django-admin startproject' using Django 1.9.2. + +For more information on this file, see +https://docs.djangoproject.com/en/1.9/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/1.9/ref/settings/ +""" + +import os +from datetime import timedelta + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + +# 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 = os.environ['SECRET_KEY'] + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +# Use this model for authentication +AUTH_USER_MODEL = 'api.Account' + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'rest_framework', + 'corsheaders', + 'lcdmarket.api', + 'django_nose' +] + + +# REST Framework Configuration +REST_FRAMEWORK = { + 'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAdminUser',), + 'DEFAULT_AUTHENTICATION_CLASSES': ( + 'rest_framework.authentication.SessionAuthentication', + 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', + ), + 'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend', + 'rest_framework.filters.SearchFilter', + 'rest_framework.filters.OrderingFilter'), + 'PAGE_SIZE': 25 +} + +# Django Cors Headers Configuration +# http://stackoverflow.com/questions/19743396/cors-cannot-use-wildcard-in-access-control-allow-origin-when-credentials-flag-i +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials +# cors middleware configuration +# need to know the local ip address of your device for testing $ ./adb shell netcfg +CORS_ORIGIN_ALLOW_ALL = False +CORS_ALLOW_CREDENTIALS = True +CORS_ORIGIN_WHITELIST = ( + 'manager.lcdporto.org', 'www.lcdporto.org', 'lcdporto.org', + 'manager.lcdporto.local', 'www.lcdporto.local', 'lcdporto.local', + 'localhost:8000', +) + +# AUTHENTICATION - JWT CONFIGURATION +# For the official docs see: http://getblimp.github.io/django-rest-framework-jwt/ +JWT_AUTH = { + 'JWT_AUTH_HEADER_PREFIX': 'Bearer', + 'JWT_ALLOW_REFRESH': True, + 'JWT_EXPIRATION_DELTA': timedelta(hours=2), + 'JWT_REFRESH_EXPIRATION_DELTA': timedelta(days=15) +} + + +MIDDLEWARE_CLASSES = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'corsheaders.middleware.CorsMiddleware' +] + +ROOT_URLCONF = 'lcdmarket.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + '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', + ], + }, + }, +] + +WSGI_APPLICATION = 'lcdmarket.wsgi.application' + + +# Password validation +# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/1.9/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.8/howto/static-files/ +# https://docs.djangoproject.com/en/1.8/howto/static-files/deployment/ (for production environment) +STATIC_ROOT = '/var/www/lcdmarket/api/static/' +STATIC_URL = '/static/' + +# @todo what is the correct production setting +MEDIA_ROOT = STATIC_ROOT + 'media/' +MEDIA_URL = STATIC_URL + 'media/' + + +# Database +# https://docs.djangoproject.com/en/1.8/ref/settings/#databases +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'lcdmarket.sqlite3'), + } +} + +# TESTING SETTINGS +# Use nose to run all tests +TEST_RUNNER = 'django_nose.NoseTestSuiteRunner' + +# Tell nose what to run and how to run +NOSE_ARGS = [ + '--with-coverage', + '--cover-package=lcd.api.models, lcd.api.serializers, lcd.api.views', + '--cover-html', + '--cover-erase', + '--verbosity=3', +] diff --git a/lcdmarket/urls.py b/lcdmarket/urls.py new file mode 100644 index 0000000..a74ba48 --- /dev/null +++ b/lcdmarket/urls.py @@ -0,0 +1,25 @@ +""" +Url routing +""" + +from rest_framework import routers +from django.conf import settings +from django.conf.urls.static import static +from django.conf.urls import include, url +from django.contrib import admin +from lcdmarket.api import views +from rest_framework_jwt.views import obtain_jwt_token, refresh_jwt_token +from rest_framework_nested import routers + +# setting up api root routes +ROUTER = routers.DefaultRouter() +ROUTER.register(r'accounts', views.AccountViewSet, 'account') +ROUTER.register(r'products', views.ProductViewSet) +ROUTER.register(r'transfers', views.TransferViewSet) + +urlpatterns = [ + url(r'^', include(ROUTER.urls)), + url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')), + url(r'^api-token-auth/', obtain_jwt_token), + url(r'^api-token-refresh/', refresh_jwt_token) +] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/lcdmarket/wsgi.py b/lcdmarket/wsgi.py new file mode 100644 index 0000000..b2deeb4 --- /dev/null +++ b/lcdmarket/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for lcd project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "lcdmarket.settings") + +application = get_wsgi_application() diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..896e427 --- /dev/null +++ b/manage.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "lcdmarket.settings") + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..6cd0670 --- /dev/null +++ b/readme.md @@ -0,0 +1,5 @@ +# LCDMarket API + +## Introduction + +RESTful API for LCDMarket project.