Merge branch 'master' into aureplop/fewer_requests

This commit is contained in:
Aurélien Delobelle 2017-04-17 20:45:01 +02:00
commit 2eee8f58aa
10 changed files with 158 additions and 88 deletions

1
cof/settings/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
secret.py

View file

@ -1,32 +1,40 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
Django settings for cof project. Django common settings for cof project.
For more information on this file, see Everything which is supposed to be identical between the production server and
https://docs.djangoproject.com/en/1.8/topics/settings/ the local development server should be here.
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.8/ref/settings/
""" """
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Database credentials
try:
from .secret import DBNAME, DBUSER, DBPASSWD
except ImportError:
# On the local development VM, theses credentials are in the environment
DBNAME = os.environ["DBNAME"]
DBUSER = os.environ["DBUSER"]
DBPASSWD = os.environ["DBPASSWD"]
except KeyError:
raise RuntimeError("Secrets missing")
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' # Other secrets
try:
from .secret import (
SECRET_KEY, RECAPTCHA_PUBLIC_KEY, RECAPTCHA_PRIVATE_KEY, ADMINS
)
except ImportError:
raise RuntimeError("Secrets missing")
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret! BASE_DIR = os.path.dirname(
SECRET_KEY = 'q()(zn4m63i%5cp4)f+ww4-28_w+ly3q9=6imw2ciu&_(5_4ah' os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
)
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
# Application definition # Application definition
INSTALLED_APPS = ( INSTALLED_APPS = [
'gestioncof', 'gestioncof',
'django.contrib.auth', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.contenttypes',
@ -41,18 +49,15 @@ INSTALLED_APPS = (
'autocomplete_light', 'autocomplete_light',
'captcha', 'captcha',
'django_cas_ng', 'django_cas_ng',
'debug_toolbar',
'debug_panel',
'bootstrapform', 'bootstrapform',
'kfet', 'kfet',
'channels', 'channels',
'widget_tweaks', 'widget_tweaks',
'custommail', 'custommail',
'djconfig', 'djconfig',
) ]
MIDDLEWARE_CLASSES = ( MIDDLEWARE_CLASSES = [
'debug_panel.middleware.DebugPanelMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.csrf.CsrfViewMiddleware',
@ -63,7 +68,7 @@ MIDDLEWARE_CLASSES = (
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'djconfig.middleware.DjConfigMiddleware', 'djconfig.middleware.DjConfigMiddleware',
) ]
ROOT_URLCONF = 'cof.urls' ROOT_URLCONF = 'cof.urls'
@ -90,17 +95,12 @@ TEMPLATES = [
}, },
] ]
# WSGI_APPLICATION = 'cof.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.mysql', 'ENGINE': 'django.db.backends.mysql',
'NAME': os.environ['DBNAME'], 'NAME': DBNAME,
'USER': os.environ['DBUSER'], 'USER': DBUSER,
'PASSWORD': os.environ['DBPASSWD'], 'PASSWORD': DBPASSWD,
'HOST': os.environ.get('DBHOST', 'localhost'), 'HOST': os.environ.get('DBHOST', 'localhost'),
} }
} }
@ -119,19 +119,6 @@ USE_L10N = True
USE_TZ = True USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = '/var/www/static/'
# Media upload (through ImageField, SiteField)
# https://docs.djangoproject.com/en/1.9/ref/models/fields/
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
MEDIA_URL = '/media/'
# Various additional settings # Various additional settings
SITE_ID = 1 SITE_ID = 1
@ -164,12 +151,6 @@ AUTHENTICATION_BACKENDS = (
'kfet.backends.GenericTeamBackend', 'kfet.backends.GenericTeamBackend',
) )
# LDAP_SERVER_URL = 'ldaps://ldap.spi.ens.fr:636'
# EMAIL_HOST="nef.ens.fr"
RECAPTCHA_PUBLIC_KEY = "DUMMY"
RECAPTCHA_PRIVATE_KEY = "DUMMY"
RECAPTCHA_USE_SSL = True RECAPTCHA_USE_SSL = True
# Channels settings # Channels settings
@ -184,18 +165,4 @@ CHANNEL_LAYERS = {
} }
} }
def show_toolbar(request):
"""
On ne veut pas la vérification de INTERNAL_IPS faite par la debug-toolbar
car cela interfère avec l'utilisation de Vagrant. En effet, l'adresse de la
machine physique n'est pas forcément connue, et peut difficilement être
mise dans les INTERNAL_IPS.
"""
return DEBUG
DEBUG_TOOLBAR_CONFIG = {
'SHOW_TOOLBAR_CALLBACK': show_toolbar,
}
FORMAT_MODULE_PATH = 'cof.locale' FORMAT_MODULE_PATH = 'cof.locale'

47
cof/settings/dev.py Normal file
View file

@ -0,0 +1,47 @@
"""
Django development settings for the cof project.
The settings that are not listed here are imported from .common
"""
import os
from .common import *
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
DEBUG = True
# ---
# Apache static/media config
# ---
STATIC_URL = '/static/'
STATIC_ROOT = '/var/www/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
MEDIA_URL = '/media/'
# ---
# Debug tool bar
# ---
def show_toolbar(request):
"""
On ne veut pas la vérification de INTERNAL_IPS faite par la debug-toolbar
car cela interfère avec l'utilisation de Vagrant. En effet, l'adresse de la
machine physique n'est pas forcément connue, et peut difficilement être
mise dans les INTERNAL_IPS.
"""
return DEBUG
INSTALLED_APPS += ["debug_toolbar", "debug_panel"]
MIDDLEWARE_CLASSES = (
["debug_panel.middleware.DebugPanelMiddleware"]
+ MIDDLEWARE_CLASSES
)
DEBUG_TOOLBAR_CONFIG = {
'SHOW_TOOLBAR_CALLBACK': show_toolbar,
}

26
cof/settings/prod.py Normal file
View file

@ -0,0 +1,26 @@
"""
Django development settings for the cof project.
The settings that are not listed here are imported from .common
"""
import os
from .common import *
DEBUG = False
ALLOWED_HOSTS = [
"cof.ens.fr",
"www.cof.ens.fr",
"dev.cof.ens.fr"
]
STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), "static")
STATIC_URL = "/gestion/static/"
MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), "media")
MEDIA_URL = "/gestion/media/"
LDAP_SERVER_URL = "ldaps://ldap.spi.ens.fr:636"
EMAIL_HOST = "nef.ens.fr"

View file

@ -0,0 +1,4 @@
SECRET_KEY = 'q()(zn4m63i%5cp4)f+ww4-28_w+ly3q9=6imw2ciu&_(5_4ah'
RECAPTCHA_PUBLIC_KEY = "DUMMY"
RECAPTCHA_PRIVATE_KEY = "DUMMY"
ADMINS = None

View file

@ -92,8 +92,7 @@ class Account(models.Model):
# Propriétés supplémentaires # Propriétés supplémentaires
@property @property
def real_balance(self): def real_balance(self):
if (hasattr(self, 'negative') and if hasattr(self, 'negative') and self.negative.balance_offset:
self.negative.balance_offset is not None):
return self.balance - self.negative.balance_offset return self.balance - self.negative.balance_offset
return self.balance return self.balance
@ -222,6 +221,29 @@ class Account(models.Model):
def delete(self, *args, **kwargs): def delete(self, *args, **kwargs):
pass pass
def update_negative(self):
if self.real_balance < 0:
if hasattr(self, 'negative') and not self.negative.start:
self.negative.start = timezone.now()
self.negative.save()
elif not hasattr(self, 'negative'):
self.negative = (
AccountNegative.objects.create(
account=self, start=timezone.now(),
)
)
elif hasattr(self, 'negative'):
# self.real_balance >= 0
balance_offset = self.negative.balance_offset
if balance_offset:
(
Account.objects
.filter(pk=self.pk)
.update(balance=F('balance')-balance_offset)
)
self.refresh_from_db()
self.negative.delete()
class UserHasAccount(Exception): class UserHasAccount(Exception):
def __init__(self, trigramme): def __init__(self, trigramme):
self.trigramme = trigramme self.trigramme = trigramme

View file

@ -1116,22 +1116,15 @@ def kpsul_perform_operations(request):
with transaction.atomic(): with transaction.atomic():
# If not cash account, # If not cash account,
# saving account's balance and adding to Negative if not in # saving account's balance and adding to Negative if not in
if not operationgroup.on_acc.is_cash: on_acc = operationgroup.on_acc
Account.objects.filter(pk=operationgroup.on_acc.pk).update( if not on_acc.is_cash:
balance=F('balance') + operationgroup.amount) (
operationgroup.on_acc.refresh_from_db() Account.objects
if operationgroup.on_acc.balance < 0: .filter(pk=on_acc.pk)
if hasattr(operationgroup.on_acc, 'negative'): .update(balance=F('balance') + operationgroup.amount)
if not operationgroup.on_acc.negative.start: )
operationgroup.on_acc.negative.start = timezone.now() on_acc.refresh_from_db()
operationgroup.on_acc.negative.save() on_acc.update_negative()
else:
negative = AccountNegative(
account=operationgroup.on_acc, start=timezone.now())
negative.save()
elif (hasattr(operationgroup.on_acc, 'negative') and
not operationgroup.on_acc.negative.balance_offset):
operationgroup.on_acc.negative.delete()
# Updating checkout's balance # Updating checkout's balance
if to_checkout_balance: if to_checkout_balance:
@ -1322,8 +1315,15 @@ def kpsul_cancel_operations(request):
(Operation.objects.filter(pk__in=opes) (Operation.objects.filter(pk__in=opes)
.update(canceled_by=canceled_by, canceled_at=canceled_at)) .update(canceled_by=canceled_by, canceled_at=canceled_at))
for account in to_accounts_balances: for account in to_accounts_balances:
Account.objects.filter(pk=account.pk).update( (
balance = F('balance') + to_accounts_balances[account]) Account.objects
.filter(pk=account.pk)
.update(balance=F('balance') + to_accounts_balances[account])
)
if not account.is_cash:
# Should always be true, but we want to be sure
account.refresh_from_db()
account.update_negative()
for checkout in to_checkouts_balances: for checkout in to_checkouts_balances:
Checkout.objects.filter(pk=checkout.pk).update( Checkout.objects.filter(pk=checkout.pk).update(
balance = F('balance') + to_checkouts_balances[checkout]) balance = F('balance') + to_checkouts_balances[checkout])

View file

@ -36,7 +36,7 @@ chown -R ubuntu:www-data /var/www/static
# Mise en place du .bash_profile pour tout configurer lors du `vagrant ssh` # Mise en place du .bash_profile pour tout configurer lors du `vagrant ssh`
cat >> ~ubuntu/.bashrc <<EOF cat >> ~ubuntu/.bashrc <<EOF
# On utilise la version de développement de GestioCOF # On utilise la version de développement de GestioCOF
export DJANGO_SETTINGS_MODULE='cof.settings_dev' export DJANGO_SETTINGS_MODULE='cof.settings.dev'
# Identifiants MySQL # Identifiants MySQL
export DBUSER="$DBUSER" export DBUSER="$DBUSER"
@ -61,8 +61,11 @@ sudo -H -u ubuntu python3 -m venv ~ubuntu/venv
sudo -H -u ubuntu ~ubuntu/venv/bin/pip install -U pip sudo -H -u ubuntu ~ubuntu/venv/bin/pip install -U pip
sudo -H -u ubuntu ~ubuntu/venv/bin/pip install -r requirements.txt -r requirements-devel.txt sudo -H -u ubuntu ~ubuntu/venv/bin/pip install -r requirements.txt -r requirements-devel.txt
# Installation des secrets
sudo -H -u ubuntu cp cof/settings/secret_example.py cof/settings/secret.py
# Préparation de Django # Préparation de Django
sudo -H -u ubuntu DJANGO_SETTINGS_MODULE='cof.settings_dev' DBUSER=$DBUSER DBNAME=$DBNAME DBPASSWD=$DBPASSWD bash provisioning/prepare_django.sh sudo -H -u ubuntu DJANGO_SETTINGS_MODULE='cof.settings.dev' DBUSER=$DBUSER DBNAME=$DBNAME DBPASSWD=$DBPASSWD bash provisioning/prepare_django.sh
# Installation du cron pour les mails de rappels # Installation du cron pour les mails de rappels
sudo -H -u ubuntu crontab provisioning/cron.dev sudo -H -u ubuntu crontab provisioning/cron.dev

View file

@ -1,5 +1,5 @@
# On utilise la version de développement de GestioCOF # On utilise la version de développement de GestioCOF
DJANGO_SETTINGS_MODULE='cof.settings_dev' DJANGO_SETTINGS_MODULE='cof.settings.dev'
# Identifiants MySQL # Identifiants MySQL
DBUSER="cof_gestion" DBUSER="cof_gestion"

View file

@ -2,7 +2,7 @@
command=/home/ubuntu/venv/bin/python /vagrant/manage.py runworker command=/home/ubuntu/venv/bin/python /vagrant/manage.py runworker
directory=/vagrant/ directory=/vagrant/
user=ubuntu user=ubuntu
environment=DBUSER={DBUSER},DBNAME={DBNAME},DBPASSWD={DBPASSWD},DJANGO_SETTINGS_MODULE="cof.settings_dev" environment=DBUSER={DBUSER},DBNAME={DBNAME},DBPASSWD={DBPASSWD},DJANGO_SETTINGS_MODULE="cof.settings.dev"
autostart=true autostart=true
autorestart=true autorestart=true
redirect_stderr=true redirect_stderr=true
@ -11,7 +11,7 @@ redirect_stderr=true
[program:interface] [program:interface]
command=/home/ubuntu/venv/bin/daphne -b 127.0.0.1 -p 8001 cof.asgi:channel_layer command=/home/ubuntu/venv/bin/daphne -b 127.0.0.1 -p 8001 cof.asgi:channel_layer
environment=DBUSER={DBUSER},DBNAME={DBNAME},DBPASSWD={DBPASSWD},DJANGO_SETTINGS_MODULE="cof.settings_dev" environment=DBUSER={DBUSER},DBNAME={DBNAME},DBPASSWD={DBPASSWD},DJANGO_SETTINGS_MODULE="cof.settings.dev"
directory=/vagrant/ directory=/vagrant/
redirect_stderr=true redirect_stderr=true
autostart=true autostart=true