Commit b016dda4 authored by David Seaward's avatar David Seaward

* add limitmonitoring app with woocommerce skeleton

* clean up ldapregister templates
* mention external resources in README
parent 5853a933
...@@ -12,6 +12,7 @@ Prerequisites ...@@ -12,6 +12,7 @@ Prerequisites
* Debian 8 * Debian 8
* Python 3.4 or 3.5 * Python 3.4 or 3.5
* Django 1.11 (included in Python packages below)
* Nginx * Nginx
* Additional dependency packages: * Additional dependency packages:
* `libsasl2-dev` * `libsasl2-dev`
...@@ -23,7 +24,10 @@ Prerequisites ...@@ -23,7 +24,10 @@ Prerequisites
* `uwsgi-emperor` * `uwsgi-emperor`
* `uwsgi-plugin-python3` * `uwsgi-plugin-python3`
* Python/Django packages: see `requires/requirements.txt` * Python/Django packages: see `requires/requirements.txt`
* Includes Django 1.11 * External resources:
* LDAP database
* WooCommerce instance (REST API)
* RabbitMQ server
Other versions and alternatives may work but are untested. Other versions and alternatives may work but are untested.
......
...@@ -18,3 +18,6 @@ AUTH_LDAP_BIND_DN=cn=admin,dc=example,dc=com ...@@ -18,3 +18,6 @@ AUTH_LDAP_BIND_DN=cn=admin,dc=example,dc=com
AUTH_LDAP_USER_SEARCH_BASE_DN=ou=people,dc=example,dc=com AUTH_LDAP_USER_SEARCH_BASE_DN=ou=people,dc=example,dc=com
SQLITE_DB_PATH = /var/opt/purist/account/db.sqlite3 SQLITE_DB_PATH = /var/opt/purist/account/db.sqlite3
STATICFILES_DIRS = /var/opt/purist/brand STATICFILES_DIRS = /var/opt/purist/brand
WOO_URL = https://example.com
WOO_WP_API = True
WOO_VERSION = wc/v1
...@@ -4,3 +4,5 @@ ...@@ -4,3 +4,5 @@
[settings] [settings]
DJANGO_SECRET_KEY=random_key DJANGO_SECRET_KEY=random_key
AUTH_LDAP_BIND_PASSWORD=ldap_password AUTH_LDAP_BIND_PASSWORD=ldap_password
WOO_CONSUMER_KEY = woo_key
WOO_CONSUMER_SECRET = woo_secret
...@@ -15,4 +15,3 @@ threads = 1 ...@@ -15,4 +15,3 @@ threads = 1
plugins = python3,logfile plugins = python3,logfile
logger = file:/var/log/uwsgi/app/purist_account.log logger = file:/var/log/uwsgi/app/purist_account.log
vacuum = true vacuum = true
...@@ -5,13 +5,14 @@ ...@@ -5,13 +5,14 @@
<title>{{ site_title }} - {{ site_byline }}</title> <title>{{ site_title }} - {{ site_byline }}</title>
<link rel="icon" sizes="960x960" href="{% static 'favicon.png' %}"> <link rel="icon" sizes="960x960" href="{% static 'favicon.png' %}">
<meta name="application-name" content="{{ site_title }}"> <meta name="application-name" content="{{ site_title }}">
<meta charset="UTF-8">
</head> </head>
<body style="text-align: center"> <body style="text-align: center">
<p style="text-align: right"> <p style="text-align: right">
{% if request.user.is_authenticated %} {% if request.user.is_authenticated %}
{% trans "Your are logged in as" %} {{ username }}<br/> {% trans "Logged in as" %} {{ username }}<br/>
<a href="{% url 'auth_password_change' %}">{% trans "Change password" %}</a> | <a href="{% url 'auth_password_change' %}">{% trans "Change password" %}</a> |
{% if request.user.is_superuser %} {% if request.user.is_superuser %}
...@@ -22,7 +23,7 @@ ...@@ -22,7 +23,7 @@
{% else %} {% else %}
{% trans "You are not logged in." %}<br/> {% trans "You are not logged in." %}<br/>
<a href="{% url 'auth_login' %}">{% trans "Log in" %}</a> {% trans "or" %} <a href="{% url 'auth_login' %}">{% trans "Log in" %}</a> {% trans "or" %}
<a href="{% url 'registration_register' %}">{% trans "register" %}</a> <a href="{% url 'registration_register' %}">{% trans "register." %}</a>
{% endif %} {% endif %}
</p> </p>
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
<header style="justify-content: space-between;"> <header style="justify-content: space-between;">
<div id="title_box"> <div id="title_box">
<a href="{% url 'home_page' %}"><img class="logo" src="{% static 'logo.png' %}" alt="Purist"/></a> <a href="{% url 'home' %}"><img class="logo" src="{% static 'logo.png' %}" alt="Purist"/></a>
<div id="title_text"> <div id="title_text">
<h1>{% block header %}Base{% endblock %}</h1> <h1>{% block header %}Base{% endblock %}</h1>
<p>{% block byline %}Byline{% endblock %}</p> <p>{% block byline %}Byline{% endblock %}</p>
......
from django.conf import settings
from django.shortcuts import render from django.shortcuts import render
from purist_account import settings
def home(request):
def home_page(request):
render_data = { render_data = {
"username": request.user.get_username(), "username": request.user.get_username(),
......
# Register your models here.
from django.apps import AppConfig
class LimitMonitorConfig(AppConfig):
name = 'limitmonitor'
verbose_name = 'Limit monitor'
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="{% static 'PuristFlex.css' %}"/>
<title>User limits</title>
<link rel="icon" sizes="960x960" href="{% static 'favicon.png' %}">
<meta name="application-name" content="{{ site_title }}">
<meta charset="UTF-8">
</head>
<body>
<table style="border-collapse: collapse;">
<thead>
<tr>
<th>Service</th>
<th>Active</th>
<th>Expires</th>
<th>Credit</th>
</tr>
</thead>
<tbody>
{% for limit in limits %}
<tr>
<th>{{ limit.service }}</th>
<td>{{ limit.is_active }}</td>
<td>{{ limit.expiry_date }}</td>
<td>{{ limit.time_total }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
# -*- coding: utf-8 -*-
# Generated by Django 1.11.3 on 2017-07-19 14:16
from __future__ import unicode_literals
import django.db.models.deletion
import django.utils.timezone
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Credit',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('time_credit', models.DecimalField(decimal_places=2, default=0, max_digits=6)),
('volume_credit', models.DecimalField(decimal_places=2, default=0, max_digits=6)),
('old_expiry_date', models.DateTimeField(default=None, null=True)),
('old_time_total', models.DecimalField(decimal_places=2, default=None, max_digits=6, null=True)),
('old_volume_total', models.DecimalField(decimal_places=2, default=None, max_digits=6, null=True)),
('new_expiry_date', models.DateTimeField(default=None, null=True)),
('new_time_total', models.DecimalField(decimal_places=2, default=None, max_digits=6, null=True)),
('new_volume_total', models.DecimalField(decimal_places=2, default=None, max_digits=6, null=True)),
('created_date', models.DateTimeField(default=django.utils.timezone.now)),
('updated_date', models.DateTimeField(default=django.utils.timezone.now)),
],
),
migrations.CreateModel(
name='ExternalBundle',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('parser', models.CharField(choices=[('WOO1', 'WooCommerce v1')], max_length=30)),
('external_key', models.CharField(max_length=30)),
('service',
models.CharField(choices=[('TUNNEL', 'Tunnel'), ('COMMUNICATION', 'Communication')], max_length=30)),
('time_credit', models.DecimalField(decimal_places=2, default=0, max_digits=6)),
('volume_credit', models.DecimalField(decimal_places=2, default=0, max_digits=6)),
('created_date', models.DateTimeField(default=django.utils.timezone.now)),
('updated_date', models.DateTimeField(default=django.utils.timezone.now)),
],
),
migrations.CreateModel(
name='ExternalCredit',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('parser', models.CharField(choices=[('WOO1', 'WooCommerce v1')], max_length=30)),
('external_key', models.CharField(max_length=30)),
('label', models.CharField(max_length=30)),
('bundle_key', models.CharField(max_length=30)),
('bundle_label', models.CharField(max_length=30)),
('quantity', models.DecimalField(decimal_places=2, default=1, max_digits=6)),
('account_name', models.CharField(default='', max_length=30)),
('additional_data', models.TextField(default='')),
('is_converted', models.BooleanField(default=False)),
('created_date', models.DateTimeField(default=django.utils.timezone.now)),
('updated_date', models.DateTimeField(default=django.utils.timezone.now)),
],
),
migrations.CreateModel(
name='Limit',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('service',
models.CharField(choices=[('TUNNEL', 'Tunnel'), ('COMMUNICATION', 'Communication')], max_length=30)),
('expiry_date', models.DateTimeField(blank=True, default=None)),
('volume_total', models.DecimalField(decimal_places=2, max_digits=6)),
('time_total', models.DecimalField(decimal_places=2, max_digits=6)),
('is_active', models.BooleanField()),
('created_date', models.DateTimeField(default=django.utils.timezone.now)),
('updated_date', models.DateTimeField(default=django.utils.timezone.now)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.AddField(
model_name='credit',
name='external',
field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE,
to='limitmonitor.ExternalCredit'),
),
migrations.AddField(
model_name='credit',
name='limit',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='limitmonitor.Limit'),
),
]
import woocommerce
from django.conf import settings
from django.db import models
from django.utils import timezone
EXTERNAL_PARSER_CHOICES = (
("WOO1", "WooCommerce v1"),
)
SERVICE_CHOICES = (
("TUNNEL", "Tunnel"),
("COMMUNICATION", "Communication"),
)
def get_wcapi():
return woocommerce.API(
url=settings.WOO_URL,
consumer_key=settings.WOO_CONSUMER_KEY,
consumer_secret=settings.WOO_CONSUMER_SECRET,
wp_api=settings.WOO_WP_API,
version=settings.WOO_VERSION
)
class Limit(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
service = models.CharField(max_length=30, choices=SERVICE_CHOICES)
expiry_date = models.DateTimeField(default=None, blank=True)
volume_total = models.DecimalField(decimal_places=2, max_digits=6)
time_total = models.DecimalField(decimal_places=2, max_digits=6)
is_active = models.BooleanField()
created_date = models.DateTimeField(default=timezone.now)
updated_date = models.DateTimeField(default=timezone.now)
class ExternalBundle(models.Model):
parser = models.CharField(max_length=30, choices=EXTERNAL_PARSER_CHOICES)
external_key = models.CharField(max_length=30)
service = models.CharField(max_length=30, choices=SERVICE_CHOICES)
time_credit = models.DecimalField(default=0, decimal_places=2, max_digits=6)
volume_credit = models.DecimalField(default=0, decimal_places=2, max_digits=6)
created_date = models.DateTimeField(default=timezone.now)
updated_date = models.DateTimeField(default=timezone.now)
class ExternalCredit(models.Model):
parser = models.CharField(max_length=30, choices=EXTERNAL_PARSER_CHOICES)
external_key = models.CharField(max_length=30)
label = models.CharField(max_length=30)
bundle_key = models.CharField(max_length=30)
bundle_label = models.CharField(max_length=30)
quantity = models.DecimalField(default=1, decimal_places=2, max_digits=6)
account_name = models.CharField(max_length=30, default="")
additional_data = models.TextField(default="")
is_converted = models.BooleanField(default=False)
created_date = models.DateTimeField(default=timezone.now)
updated_date = models.DateTimeField(default=timezone.now)
class Credit(models.Model):
limit = models.ForeignKey(Limit)
external = models.ForeignKey(ExternalCredit, null=True, default=None)
time_credit = models.DecimalField(default=0, decimal_places=2, max_digits=6)
volume_credit = models.DecimalField(default=0, decimal_places=2, max_digits=6)
old_expiry_date = models.DateTimeField(null=True, default=None)
old_time_total = models.DecimalField(null=True, default=None, decimal_places=2, max_digits=6)
old_volume_total = models.DecimalField(null=True, default=None, decimal_places=2, max_digits=6)
new_expiry_date = models.DateTimeField(null=True, default=None)
new_time_total = models.DecimalField(null=True, default=None, decimal_places=2, max_digits=6)
new_volume_total = models.DecimalField(null=True, default=None, decimal_places=2, max_digits=6)
created_date = models.DateTimeField(default=timezone.now)
updated_date = models.DateTimeField(default=timezone.now)
# Create your tests here.
from django.conf import settings
from django.shortcuts import render
from .models import Limit
def userlimit(request):
username = request.user.get_username()
limits = Limit.objects.filter(user__username=username)
render_data = {
"username": username,
"site_title": settings.SITE_TITLE,
"site_byline": settings.SITE_BYLINE,
"limits": limits,
}
return render(request, 'limitmonitor/userlimit.html', render_data)
...@@ -33,7 +33,7 @@ ALLOWED_HOSTS = config("ALLOWED_HOSTS", cast=Csv()) ...@@ -33,7 +33,7 @@ ALLOWED_HOSTS = config("ALLOWED_HOSTS", cast=Csv())
# #
# INSTALLED_APPS = ["registration_defaults", ] + INSTALLED_APPS + ["ldapregister", ] # INSTALLED_APPS = ["registration_defaults", ] + INSTALLED_APPS + ["ldapregister", ]
INSTALLED_APPS += ["crispy_forms", "ldapregister", ] INSTALLED_APPS += ["crispy_forms", "ldapregister", "limitmonitor", ]
REGISTRATION_OPEN = config("REGISTRATION_OPEN", cast=bool) REGISTRATION_OPEN = config("REGISTRATION_OPEN", cast=bool)
...@@ -85,6 +85,10 @@ AUTH_USER_MODEL = 'ldapregister.User' ...@@ -85,6 +85,10 @@ AUTH_USER_MODEL = 'ldapregister.User'
SQLITE_DB_PATH = config("SQLITE_DB_PATH") SQLITE_DB_PATH = config("SQLITE_DB_PATH")
DATABASES = { DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': SQLITE_DB_PATH,
},
'ldap': { 'ldap': {
'ENGINE': 'ldapdb.backends.ldap', 'ENGINE': 'ldapdb.backends.ldap',
'NAME': AUTH_LDAP_SERVER_URI, 'NAME': AUTH_LDAP_SERVER_URI,
...@@ -92,10 +96,6 @@ DATABASES = { ...@@ -92,10 +96,6 @@ DATABASES = {
'PASSWORD': AUTH_LDAP_BIND_PASSWORD, 'PASSWORD': AUTH_LDAP_BIND_PASSWORD,
'TLS': AUTH_LDAP_START_TLS, 'TLS': AUTH_LDAP_START_TLS,
}, },
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': SQLITE_DB_PATH,
},
} }
DATABASE_ROUTERS = ['ldapdb.router.Router'] DATABASE_ROUTERS = ['ldapdb.router.Router']
...@@ -107,3 +107,14 @@ STATICFILES_DIRS = config("STATICFILES_DIRS", cast=Csv()) ...@@ -107,3 +107,14 @@ STATICFILES_DIRS = config("STATICFILES_DIRS", cast=Csv())
SITE_TITLE = config("SITE_TITLE") SITE_TITLE = config("SITE_TITLE")
SITE_BYLINE = config("SITE_BYLINE") SITE_BYLINE = config("SITE_BYLINE")
#
# WOOCOMMERCE
#
WOO_URL = config("WOO_URL")
WOO_WP_API = config("WOO_WP_API", cast=bool)
WOO_VERSION = config("WOO_VERSION")
WOO_CONSUMER_KEY = secret_config("WOO_CONSUMER_KEY")
WOO_CONSUMER_SECRET = secret_config("WOO_CONSUMER_SECRET")
...@@ -19,13 +19,14 @@ from django.views.generic import RedirectView ...@@ -19,13 +19,14 @@ from django.views.generic import RedirectView
from registration.backends.simple.views import RegistrationView from registration.backends.simple.views import RegistrationView
import ldapregister.views import ldapregister.views
import limitmonitor.views
from ldapregister.forms import RegistrationForm from ldapregister.forms import RegistrationForm
urlpatterns = [ urlpatterns = [
url(r'^$', ldapregister.views.home_page, name='home_page'), url(r'^$', ldapregister.views.home, name='home'),
url(r'^admin/', admin.site.urls), url(r'^admin/', admin.site.urls),
url(r'^accounts/$', RedirectView.as_view(url='/')), url(r'^accounts/$', RedirectView.as_view(url='/')),
url(r'^accounts/profile/$', RedirectView.as_view(url='/')), url(r'^accounts/profile/$', limitmonitor.views.userlimit, name='limitmonitor_userlimit'),
url(r'^accounts/register/$', RegistrationView.as_view(form_class=RegistrationForm), name='registration_register'), url(r'^accounts/register/$', RegistrationView.as_view(form_class=RegistrationForm), name='registration_register'),
url(r'^accounts/', include('registration.backends.simple.urls')), url(r'^accounts/', include('registration.backends.simple.urls')),
] ]
Django==1.11.3 Django==1.11.3
Jinja2==2.9.6 Jinja2==2.9.6
WooCommerce==1.2.1
celery==4.0.2
dj-database-url==0.4.2 dj-database-url==0.4.2
django-auth-ldap==1.2.13 django-auth-ldap==1.2.13
django-crispy-forms==1.6.1 django-crispy-forms==1.6.1
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment