Commit 644efd05 authored by David Seaward's avatar David Seaward Committed by Gogs

Merge branch 'master' of david.seaward/account_web into master

parents a8c69d90 442341c2
......@@ -13,11 +13,15 @@ Prerequisites
* Debian 8
* Python 3.4 or 3.5
* Nginx
* Additional Debian packages:
* Additional dependency packages:
* `libsasl2-dev`
* `libldap2-dev`
* `libssl-dev`
* `python3-dev`
* Additional uWSGI packages:
* `uwsgi`
* `uwsgi-emperor`
* `uwsgi-plugin-python3`
* Python/Django packages: see `requires/requirements.txt`
* Includes Django 1.11
......@@ -26,31 +30,55 @@ Other versions and alternatives may work but are untested.
Setup
-----
* Create project folders:
* `/opt/purist_account/` (code)
* `/etc/opt/purist_account/` (configuration)
* `/var/opt/purist_account/static/` (data and static web files)
* `/var/log/purist_account/` (logs)
* Copy project code into `/opt/purist_account/`
* Install Debian prerequisites (`apt install libsasl2-dev` ...)
* Set up virtualenv
* Create virtualenv in project folder (`virtualenv . --python=python3`)
* Activate virtualenv (`./bin/activate.py`)
* Install Debian packages (`apt install libsasl2-dev libldap2-dev...`)
* Create installation folders:
* `/opt/purist/account/` (code)
* `/opt/purist/account_virtualenv/` (Python environment)
* `/etc/opt/purist/account/` (configuration)
* `/var/opt/purist/account/static/` (data and static web files)
* `/var/log/purist/account/` (logs)
* Populate brand data (if it doesn't already exist):
* Create `/var/opt/purist/brand/` (shared data and static web files)
* Populate `brand` folder
* `chown --recursive www-data:www-data /var/opt/purist`
* Copy project code:
* Copy code into `/opt/purist/account/`
* `chown --recursive www-data:www-data /opt/purist`
* Set up virtualenv:
* Create virtualenv (`virtualenv /opt/purist/account_virtualenv --python=python3`)
* `cd /opt/purist/account`
* Activate virtualenv (`source ../account_virtualenv/bin/activate`)
* Install Python packages (`pip install --requirement requires/requirements.txt`)
* Complete Django settings
* `cp ./conf/etc/config.ini /etc/opt/purist_account/`
* `cp ./conf/etc/secret.ini /etc/opt/purist_account/`
* Confirm packages by comparing `pip freeze` output with `requires/requirements.txt`
* Deactivate virtualenv (`deactivate`)
* Complete Django settings:
* `cp ./conf/etc/config.ini /etc/opt/purist/account/`
* `cp ./conf/etc/secret.ini /etc/opt/purist/account/`
* Fill in settings
* Run `./manage.py collectstatic`
* Run `./manage.py migrate`
* Run `./manage.py createsuperuser`
* Run initial setup:
* Activate virtualenv (`source ../account_virtualenv/bin/activate`)
* `./manage.py collectstatic`
* `./manage.py migrate`
* `./manage.py createsuperuser`
* When prompted, enter the credentials of your LDAP superuser /
account manager
* Hook up Nginx
* Deactivate virtualenv (`deactivate`)
* Hook up Nginx:
* `cp ./config/nginx/purist_account /etc/nginx/available_sites/`
* `ln -s /etc/nginx/sites-available/purist_account /etc/nginx/sites-enabled/purist_account`
* Hook up system service (i.e. systemd, supervisord...) to runserver
directive (`manage.py runserver`)
* Update `server_name` value
* `cd /etc/nginx/sites-enabled`
* `ln --symbolic ../sites-available/purist_account`
* Hook up uWSGI:
* `sudo apt install uwsgi uwsgi-emperor uwsgi-plugin-python3`
* `cp ./conf/uwsgi_emperor_vassals/purist_account.ini /etc/uwsgi-emperor/vassals/`
* Restart services:
* `sudo service uwsgi-emperor restart`
* `sudo service nginx restart`
* Check logs:
* `/var/log/uwsgi/emperor.log`
* `/var/log/uwsgi/app/purist_account.log`
* `/var/log/nginx/error.log`
* `/var/log/nginx/access.log`
For more options and details see
<https://docs.djangoproject.com/en/1.11/#the-development-process>
......@@ -60,8 +88,8 @@ Update
* Stop site
* Update packages with `apt update && apt upgrade`
* Update code in `/opt/purist_account/`
* Update settings in `/etc/opt/purist_account/`
* Update code in `/opt/purist/account/`
* Update settings in `/etc/opt/purist/account/`
* Update virtualenv:
* Activate virtualenv (`./bin/activate.py`)
* Update Python packages (`pip install --requirement requires/requirements.txt`)
......
[settings]
# stored as /etc/opt/purist_account/config.ini
# stored as /etc/opt/purist/account/config.ini
# note that % must be escaped as %%
[settings]
SITE_TITLE=Title
SITE_BYLINE=Example byline
DEBUG=True
ALLOWED_HOSTS=localhost
STATIC_ROOT = /var/opt/purist/account/static
......
[settings]
# stored as /etc/opt/purist_account/secret.ini
# stored as /etc/opt/purist/account/secret.ini
# note that % must be escaped as %%
[settings]
DJANGO_SECRET_KEY=random_key
AUTH_LDAP_BIND_PASSWORD=ldap_password
......@@ -3,23 +3,23 @@
# the upstream component nginx needs to connect to
upstream django {
server unix:/var/opt/purist_account/uwsgi.sock; # for a file socket
server unix:/var/opt/purist/account/uwsgi.sock; # for a file socket
}
# the upstream component nginx needs to connect to
# the main server block
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
server_name example.com; # change this
charset utf-8;
location /static/ {
alias /var/opt/purist_account/static;
alias /var/opt/purist/account/static/;
}
location /favicon.ico {
alias /var/opt/purist_account/favicon.ico;
alias /var/opt/purist/brand/favicon.ico;
}
location / {
......@@ -27,4 +27,3 @@ server {
include /etc/nginx/uwsgi_params;
}
}
# stored as /etc/uwsgi-emperor/vassals/purist_account.ini
[uwsgi]
socket = /var/opt/purist/account/uwsgi.sock
chmod-socket = 775
chdir = /opt/purist/account
master = true
virtualenv = /opt/purist/account_virtualenv
env = DJANGO_SETTINGS_MODULE=purist_account.settings
module = purist_account.wsgi:application
uid = www-data
gid = www-data
processes = 1
threads = 1
plugins = python3,logfile
logger = file:/var/log/uwsgi/app/purist_account.log
vacuum = true
......@@ -3,11 +3,11 @@ from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .models import User, LdapGroup, LdapPerson
#
# Declare admin models
#
class UserAdmin(BaseUserAdmin):
pass
......@@ -28,3 +28,10 @@ class LdapPersonAdmin(admin.ModelAdmin):
admin.site.register(User, UserAdmin)
admin.site.register(LdapGroup, LdapGroupAdmin)
admin.site.register(LdapPerson, LdapPersonAdmin)
#
# Set admin titles
#
admin.site.site_title = "Site administration"
admin.site.site_header = "Site administration"
from django.utils.translation import ugettext_lazy as _
from registration.forms import RegistrationForm as BaseRegistrationForm
from .models import User
class RegistrationForm(BaseRegistrationForm):
email = None # override base definition to remove email field
def __init__(self, *args, **kwargs):
super(RegistrationForm, self).__init__(*args, **kwargs)
self.fields[User.USERNAME_FIELD].label = _("Username")
self.fields["password1"].label = _("Passphrase")
self.fields["password2"].label = _("Passphrase confirmation")
class Meta(BaseRegistrationForm.Meta):
model = User
# override base definition to remove email field
fields = (
User.USERNAME_FIELD,
'password1',
'password2',
)
......@@ -2,34 +2,38 @@
<html lang="en">
<head>
<link rel="stylesheet" href="{% static 'PuristFlex.css' %}"/>
<title>Purist - Easy, secure communication for everyone</title>
<title>{{ site_title }} - {{ site_byline }}</title>
<link rel="icon" sizes="960x960" href="{% static 'favicon.png' %}">
<meta name="application-name" content="Purist">
</head>
<body style="text-align: center">
{% if username %}
<p style="text-align: right">
You are logged in as {{username}}.<br />
<a href="/accounts/logout/">Log out</a>
{% if username %}
{% trans "Your are logged in as" %} {{ username }}<br/>
<a href="{% url 'auth_password_change' %}">{% trans "Change password" %}</a><br/>
<a href="{% url 'auth_logout' %}">{% trans "Log out" %}</a>
{% else %}
{% trans "You are not logged in." %}<br/>
<a href="{% url 'auth_login' %}">{% trans "Log in" %}</a> {% trans "or" %}
<a href="{% url 'registration_register' %}">{% trans "register" %}</a>
{% endif %}
</p>
{% else %}
<p style="text-align: right">
You are not logged in.<br />
<a href="/accounts/login/">Log in</a> or <a href="/accounts/register/">register</a>.
</p>
{% endif %}
<h1><img style="max-height: 30%; max-width: 50%" src="{% static 'logo.png' %}" alt="Purist"/></h1>
<h1><img style="max-height: 40vh; max-width: 40vw" src="{% static 'logo.png' %}" alt="{{ site_title }}"/></h1>
<p>Easy, secure communication for everyone</p>
<p>{{ site_byline }}</p>
<p><a href="https://plan.puri.st">plan</a> | <a href="https://code.puri.sm/purist">code</a> | <a
href="http://dev.comms.puri.st:8000">test</a> | <a href="/admin/">admin</a></p>
<p>
<a href="https://plan.puri.st">plan</a> | <a href="https://code.puri.sm/purist">code</a> |
<a href="http://dev.comms.puri.st">test</a> | <a href="/admin/">admin</a>
</p>
<p style="font-size: small">Services provided by <a href="https://puri.sm">Purism SPC</a>. Stand-in logo from <a
href="https://openclipart.org/detail/158443/kawaii-rainbow">Openclipart</a> [CC0].</p>
<p style="font-size: small">
Services provided by <a href="https://puri.sm">Purism SPC</a>. Stand-in logo from
<a href="https://plan.puri.st/project/overview/design/logo">Openclipart</a> [CC0].
</p>
</body>
</html>
......@@ -28,11 +28,12 @@ class UserManager(BaseUserManager):
class User(AbstractUser):
objects = UserManager()
REQUIRED_FIELDS = ['email']
REQUIRED_FIELDS = []
def __init__(self, *args, **kwargs):
return super(User, self).__init__(*args, **kwargs)
user = super(User, self).__init__(*args, **kwargs)
return user
def validate_unique(self, exclude=None):
......
......@@ -18,23 +18,25 @@
<body>
<header>
<a href="{% url 'home_page' %}"><img class="logo" src="{% static 'logo.png' %}" alt="Purist"/></a>
<div>
<h1>{% block header %}Base{% endblock %}</h1>
<!-- p></p -->
<p>
{% block byline %}Byline{% endblock %} |
{% if user.is_authenticated %}
{% trans "Logged in" %}: {{ user.username }}
(<a href="{% url 'auth_logout' %}">{% trans "Log out" %}</a> |
<a href="{% url 'auth_password_change' %}">{% trans "Change password" %}</a>)
{% else %}
<a href="{% url 'auth_login' %}">{% trans "Log in" %}</a>
{% endif %}
</p>
<header style="justify-content: space-between;">
<div id="title_box">
<a href="{% url 'home_page' %}"><img class="logo" src="{% static 'logo.png' %}" alt="Purist"/></a>
<div id="title_text">
<h1>{% block header %}Base{% endblock %}</h1>
<p>{% block byline %}Byline{% endblock %}</p>
</div>
</div>
<div id="log_state">
{% if user.is_authenticated %}
{% trans "Logged in as" %} {{ user.username }}<br/>
<a href="{% url 'auth_password_change' %}">{% trans "Change password" %}</a><br/>
<a href="{% url 'auth_logout' %}">{% trans "Log out" %}</a>
{% else %}
{% trans "You are not logged in." %}<br/>
<a href="{% url 'auth_login' %}">{% trans "Log in" %}</a> {% trans "or" %}
<a href="{% url 'registration_register' %}">{% trans "register" %}</a>
{% endif %}
</div>
</header>
......
......@@ -21,6 +21,7 @@
</section>
</main>
<p class="text-center">{% trans "No account yet?" %} <a href="{% url 'registration_register' %}">{% trans "Register!"
%}</a></p>
<p class="text-center">{% trans "No account yet?" %}
<a href="{% url 'registration_register' %}">{% trans "Register!" %}</a>
</p>
{% endblock %}
......@@ -4,9 +4,7 @@
{% block title %}{% trans 'Log out' %}{% endblock %}
{% block header %}{% trans 'Log out' %}{% endblock %}
{% block byline %}{% endblock %}
{% block byline %}{% trans 'You have been logged out' %}{% endblock %}
{% block content %}
<br/>
<p>{% trans "You have been logged out" %}</p>
{% endblock %}
from django.shortcuts import render
# from registration.backends.simple.views import
from purist_account import settings
def home_page(request):
render_data = {
"username": request.user.get_username(),
"site_title": settings.SITE_TITLE,
"site_byline": settings.SITE_BYLINE,
}
return render(request, 'ldapregister/home.html', render_data)
......@@ -9,8 +9,8 @@ from .settings_original import *
# LOAD CONFIGURATION FILE
#
CONFIG_PATH = '/etc/opt/purist_account/config.ini'
SECRET_PATH = '/etc/opt/purist_account/secret.ini'
CONFIG_PATH = '/etc/opt/purist/account/config.ini'
SECRET_PATH = '/etc/opt/purist/account/secret.ini'
config = Config(RepositoryIni(CONFIG_PATH))
secret_config = Config(RepositoryIni(SECRET_PATH))
......@@ -47,7 +47,14 @@ REG_GROUP_OBJECT_CLASSES = config("REG_GROUP_OBJECT_CLASSES", cast=Csv())
# AUTHENTICATION
#
# AUTH_PASSWORD_VALIDATORS = [] # override
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'OPTIONS': {
'min_length': 15,
}
},
]
AUTHENTICATION_BACKENDS = (
'django_auth_ldap.backend.LDAPBackend',
......@@ -96,3 +103,7 @@ DATABASE_ROUTERS = ['ldapdb.router.Router']
STATIC_ROOT = config("STATIC_ROOT")
STATICFILES_DIRS = config("STATICFILES_DIRS", cast=Csv())
SITE_TITLE = config("SITE_TITLE")
SITE_BYLINE = config("SITE_BYLINE")
......@@ -17,13 +17,14 @@ from django.conf.urls import include, url
from django.contrib import admin
from django.views.generic import RedirectView
from registration.backends.simple.views import RegistrationView
import ldapregister.views
import ldapregister.views
from ldapregister.forms import RegistrationForm
urlpatterns = [
url(r'^$', ldapregister.views.home_page, name='home_page'),
url(r'^admin/', admin.site.urls),
url(r'^accounts/$', RedirectView.as_view(url='/')),
url(r'^accounts/profile/$', RedirectView.as_view(url='/')),
url(r'^accounts/register/$', RegistrationView.as_view(form_class=RegistrationForm), name='registration_register'),
url(r'^accounts/', include('registration.backends.simple.urls')),
......
Django==1.11.2
django-auth-ldap==1.2.12
Jinja2==2.9.6
dj-database-url==0.4.2
django-auth-ldap==1.2.13
django-crispy-forms==1.6.1
django-ldapdb==0.9.0
django-registration==2.2
Jinja2==2.9.6
jinja2-django-tags==0.5
pyasn1==0.2.3
python-decouple==3.0
dj-database-url==0.4.2
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