cleanning debian branch
This commit is contained in:
parent
e31d6413d5
commit
19b4516525
48
README
48
README
|
@ -1,48 +0,0 @@
|
||||||
wcsinst
|
|
||||||
=======
|
|
||||||
|
|
||||||
wcsinst is a web application to deploy w.c.s. instances; it is released under
|
|
||||||
the GNU AGPL Licence.
|
|
||||||
|
|
||||||
|
|
||||||
Architecture
|
|
||||||
------------
|
|
||||||
|
|
||||||
This project is composed of two Django applications; wcsinst provides a model
|
|
||||||
and is expected to be installed as part of an administrative portal; wcsinstd
|
|
||||||
provides the web API to deploy w.c.s. instances and should be installed on its
|
|
||||||
own, on the host instances should be deployed.
|
|
||||||
|
|
||||||
|
|
||||||
Configuration
|
|
||||||
-------------
|
|
||||||
|
|
||||||
If the WCSINSTD_URL environment variable is set, ./manage.py will run itself as
|
|
||||||
a standalone wcsinst (admin) site. Go to /admin/.
|
|
||||||
|
|
||||||
Example: WCSINSTD_URL=http://127.0.0.1:8001/ ./manage.py runserver
|
|
||||||
|
|
||||||
The wcsinstd application expects a WCSINST_WCS_APP_DIR setting, that should
|
|
||||||
point to the w.c.s. application directory (typically /var/lib/wcs/).
|
|
||||||
|
|
||||||
Additionally it expects site skeletons to be made available from the
|
|
||||||
media/skeletons directory; the default skeleton should go in a subdirectory
|
|
||||||
named "default".
|
|
||||||
|
|
||||||
A skeleton directory has the following files:
|
|
||||||
|
|
||||||
- export.wcs: as produced from wcs, admin/export
|
|
||||||
- idff-metadata-template: template file for ID-FF 1.2 metadata (optional)
|
|
||||||
- saml2-metadata-template: template file for SAMLv2 metadata (optional)
|
|
||||||
- private-key.pem & public-key.pem: pair of keys for ID-FF/SAML (optional)
|
|
||||||
- idp-metadata.xml: metadata of the identity provider (optional)
|
|
||||||
- site-options.cfg: template file for the w.c.s. site-options.cfg file
|
|
||||||
- apache-vhost.conf: tempalte file for the Apache virtual host configuration
|
|
||||||
|
|
||||||
The template files contains template strings (cf the Python documentation);
|
|
||||||
there is a single variable made available, named domain (hence ${domain} to
|
|
||||||
use it).
|
|
||||||
|
|
||||||
The wcsinstd application should be able to run "sudo -n /etc/init.d/apache2
|
|
||||||
reload", to reload virtual hosts configuration. Virtual host configuration
|
|
||||||
files are created in $media/vhosts.d
|
|
|
@ -1,178 +0,0 @@
|
||||||
# Django settings for wcsinst project.
|
|
||||||
|
|
||||||
import os
|
|
||||||
import json
|
|
||||||
import logging.handlers
|
|
||||||
import wcsinst
|
|
||||||
|
|
||||||
DEBUG = 'DEBUG' in os.environ
|
|
||||||
TEMPLATE_DEBUG = DEBUG
|
|
||||||
|
|
||||||
VAR_DIR = '/var/lib/wcsinstd'
|
|
||||||
PROJECT_PATH = os.path.dirname(wcsinst.__file__)
|
|
||||||
|
|
||||||
if 'ADMINS' in os.environ:
|
|
||||||
ADMINS = [ x.split(';') for x in os.environ['ADMINS'].split(',') ]
|
|
||||||
else:
|
|
||||||
ADMINS = ( ('root', 'root@localhost') )
|
|
||||||
|
|
||||||
MANAGERS = ADMINS
|
|
||||||
|
|
||||||
DATABASES = {
|
|
||||||
'default': {
|
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
|
||||||
'NAME': os.path.join(VAR_DIR, 'wcsinst.sqlite3'),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Hosts/domain names that are valid for this site; required if DEBUG is False
|
|
||||||
# See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts
|
|
||||||
if 'ALLOWED_HOSTS' in os.environ:
|
|
||||||
ALLOWED_HOSTS = os.environ['ALLOWED_HOSTS'].split(',')
|
|
||||||
else:
|
|
||||||
ALLOWED_HOSTS = [ '*' ]
|
|
||||||
|
|
||||||
# Local time zone for this installation. Choices can be found here:
|
|
||||||
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
|
|
||||||
# although not all choices may be available on all operating systems.
|
|
||||||
# In a Windows environment this must be set to your system time zone.
|
|
||||||
TIME_ZONE = 'Europe/Brussels'
|
|
||||||
|
|
||||||
# Language code for this installation. All choices can be found here:
|
|
||||||
# http://www.i18nguy.com/unicode/language-identifiers.html
|
|
||||||
LANGUAGE_CODE = 'fr-fr'
|
|
||||||
|
|
||||||
SITE_ID = 1
|
|
||||||
|
|
||||||
# If you set this to False, Django will make some optimizations so as not
|
|
||||||
# to load the internationalization machinery.
|
|
||||||
USE_I18N = True
|
|
||||||
|
|
||||||
# If you set this to False, Django will not format dates, numbers and
|
|
||||||
# calendars according to the current locale.
|
|
||||||
USE_L10N = True
|
|
||||||
|
|
||||||
# If you set this to False, Django will not use timezone-aware datetimes.
|
|
||||||
USE_TZ = True
|
|
||||||
|
|
||||||
# Absolute filesystem path to the directory that will hold user-uploaded files.
|
|
||||||
# Example: "/var/www/example.com/media/"
|
|
||||||
MEDIA_ROOT = os.path.join(VAR_DIR, 'media')
|
|
||||||
|
|
||||||
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
|
|
||||||
# trailing slash.
|
|
||||||
# Examples: "http://example.com/media/", "http://media.example.com/"
|
|
||||||
MEDIA_URL = '/media/'
|
|
||||||
|
|
||||||
# Absolute path to the directory static files should be collected to.
|
|
||||||
# Don't put anything in this directory yourself; store your static files
|
|
||||||
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
|
|
||||||
# Example: "/var/www/example.com/static/"
|
|
||||||
STATIC_ROOT = os.path.join(VAR_DIR, 'static')
|
|
||||||
|
|
||||||
# URL prefix for static files.
|
|
||||||
# Example: "http://example.com/static/", "http://static.example.com/"
|
|
||||||
STATIC_URL = '/static/'
|
|
||||||
|
|
||||||
# Additional locations of static files
|
|
||||||
STATICFILES_DIRS = (
|
|
||||||
os.path.join(VAR_DIR, 'extra-static'),
|
|
||||||
)
|
|
||||||
|
|
||||||
# List of finder classes that know how to find static files in
|
|
||||||
# various locations.
|
|
||||||
STATICFILES_FINDERS = (
|
|
||||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
|
||||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
|
||||||
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
|
|
||||||
)
|
|
||||||
|
|
||||||
# Make this unique, and don't share it with anybody.
|
|
||||||
SECRET_KEY = os.environ.get('SECRET_KEY') or file('/etc/wcsinstd/secret').read()
|
|
||||||
|
|
||||||
# List of callables that know how to import templates from various sources.
|
|
||||||
TEMPLATE_LOADERS = (
|
|
||||||
'django.template.loaders.filesystem.Loader',
|
|
||||||
'django.template.loaders.app_directories.Loader',
|
|
||||||
# 'django.template.loaders.eggs.Loader',
|
|
||||||
)
|
|
||||||
|
|
||||||
MIDDLEWARE_CLASSES = (
|
|
||||||
'django.middleware.common.CommonMiddleware',
|
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
|
||||||
# Uncomment the next line for simple clickjacking protection:
|
|
||||||
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
|
||||||
)
|
|
||||||
|
|
||||||
ROOT_URLCONF = 'wcsinst.urls'
|
|
||||||
|
|
||||||
# Python dotted path to the WSGI application used by Django's runserver.
|
|
||||||
WSGI_APPLICATION = 'wcsinst.wsgi.application'
|
|
||||||
|
|
||||||
TEMPLATE_DIRS = (
|
|
||||||
os.path.join(PROJECT_PATH, 'wcsinst', 'templates'),
|
|
||||||
os.path.join(VAR_DIR, 'templates'),
|
|
||||||
)
|
|
||||||
|
|
||||||
INSTALLED_APPS = (
|
|
||||||
'south',
|
|
||||||
'django.contrib.auth',
|
|
||||||
'django.contrib.contenttypes',
|
|
||||||
'django.contrib.sessions',
|
|
||||||
'django.contrib.sites',
|
|
||||||
'django.contrib.messages',
|
|
||||||
'django.contrib.staticfiles',
|
|
||||||
'django.contrib.admin',
|
|
||||||
)
|
|
||||||
|
|
||||||
# A sample logging configuration. The only tangible logging
|
|
||||||
# performed by this configuration is to send an email to
|
|
||||||
# the site admins on every HTTP 500 error when DEBUG=False.
|
|
||||||
# See http://docs.djangoproject.com/en/dev/topics/logging for
|
|
||||||
# more details on how to customize your logging configuration.
|
|
||||||
LOGGING = {
|
|
||||||
'version': 1,
|
|
||||||
'disable_existing_loggers': True,
|
|
||||||
'formatters': {
|
|
||||||
'syslog': {
|
|
||||||
'format': 'wcsinstd(pid=%(process)d) %(levelname)s %(name)s: %(message)s',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'handlers': {
|
|
||||||
'mail_admins': {
|
|
||||||
'level': 'ERROR',
|
|
||||||
'filters': [],
|
|
||||||
'class': 'django.utils.log.AdminEmailHandler'
|
|
||||||
},
|
|
||||||
'syslog': {
|
|
||||||
'level': 'DEBUG',
|
|
||||||
'class': 'entrouvert.logging.handlers.SysLogHandler',
|
|
||||||
'formatter': 'syslog',
|
|
||||||
'facility': logging.handlers.SysLogHandler.LOG_LOCAL0,
|
|
||||||
'address': '/dev/log',
|
|
||||||
'max_length': 999,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'loggers': {
|
|
||||||
'': {
|
|
||||||
'handlers': ['mail_admins','syslog'],
|
|
||||||
'level': 'DEBUG' if DEBUG else 'INFO',
|
|
||||||
'propagate': True,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
INSTALLED_APPS += ('wcsinst.wcsinstd',)
|
|
||||||
|
|
||||||
if 'SENTRY_DSN' in os.environ:
|
|
||||||
INSTALLED_APPS += ('raven.contrib.django.raven_compat',)
|
|
||||||
RAVEN_CONFIG = {
|
|
||||||
'dsn': os.environ.get('SENTRY_DSN'),
|
|
||||||
}
|
|
||||||
|
|
||||||
for var in ('WCSINST_WCSCTL_SCRIPT', 'WCSINST_URL_TEMPLATE', 'WCSINST_WCS_APP_DIR'):
|
|
||||||
if var in os.environ:
|
|
||||||
globals()[var] = os.environ[var]
|
|
|
@ -1,32 +0,0 @@
|
||||||
"""
|
|
||||||
WSGI config for wcsinst project.
|
|
||||||
|
|
||||||
This module contains the WSGI application used by Django's development server
|
|
||||||
and any production WSGI deployments. It should expose a module-level variable
|
|
||||||
named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
|
|
||||||
this application via the ``WSGI_APPLICATION`` setting.
|
|
||||||
|
|
||||||
Usually you will have the standard Django WSGI application here, but it also
|
|
||||||
might make sense to replace the whole Django WSGI application with a custom one
|
|
||||||
that later delegates to the Django one. For example, you could introduce WSGI
|
|
||||||
middleware here, or combine a Django application with an application of another
|
|
||||||
framework.
|
|
||||||
|
|
||||||
"""
|
|
||||||
import os
|
|
||||||
|
|
||||||
# We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks
|
|
||||||
# if running multiple sites in the same mod_wsgi process. To fix this, use
|
|
||||||
# mod_wsgi daemon mode with each site in its own daemon process, or use
|
|
||||||
# os.environ["DJANGO_SETTINGS_MODULE"] = "wcsinst.settings"
|
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "debian_settings")
|
|
||||||
|
|
||||||
# This application object is used by any WSGI server configured to use this
|
|
||||||
# file. This includes Django's development server, if the WSGI_APPLICATION
|
|
||||||
# setting points here.
|
|
||||||
from django.core.wsgi import get_wsgi_application
|
|
||||||
application = get_wsgi_application()
|
|
||||||
|
|
||||||
# Apply WSGI middleware here.
|
|
||||||
# from helloworld.wsgi import HelloWorldApplication
|
|
||||||
# application = HelloWorldApplication(application)
|
|
|
@ -31,7 +31,7 @@ DAEMON_ARGS="--pid $PIDFILE \
|
||||||
--workers=1 \
|
--workers=1 \
|
||||||
--worker-class=sync \
|
--worker-class=sync \
|
||||||
--timeout=60 \
|
--timeout=60 \
|
||||||
debian_wsgi:application"
|
wcsinst.wsgi:application"
|
||||||
|
|
||||||
export PYTHONPATH=/usr/lib/$NAME
|
export PYTHONPATH=/usr/lib/$NAME
|
||||||
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
pip install --upgrade pip
|
|
||||||
pip install --upgrade pylint
|
|
||||||
pip install --upgrade -v -r requirements.txt
|
|
||||||
echo Nothing to test for now
|
|
||||||
(pylint -f parseable --rcfile /var/lib/jenkins/pylint.django.rc wcsinst/ | tee pylint.out) || /bin/true
|
|
10
manage.py
10
manage.py
|
@ -1,10 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "wcsinst.settings")
|
|
||||||
|
|
||||||
from django.core.management import execute_from_command_line
|
|
||||||
|
|
||||||
execute_from_command_line(sys.argv)
|
|
|
@ -1,3 +0,0 @@
|
||||||
django < 1.6
|
|
||||||
south>=0.8,<0.9
|
|
||||||
http://pypi.python.org/packages/source/d/django-jsonresponse/django-jsonresponse-0.5.tar.gz
|
|
33
setup.py
33
setup.py
|
@ -1,33 +0,0 @@
|
||||||
#! /usr/bin/python
|
|
||||||
|
|
||||||
from setuptools import setup, find_packages
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
VERSION='0.1'
|
|
||||||
|
|
||||||
def get_version():
|
|
||||||
if os.path.exists('.git'):
|
|
||||||
p = subprocess.Popen(['git','describe','--dirty'], stdout=subprocess.PIPE)
|
|
||||||
result = p.communicate()[0]
|
|
||||||
return result.split()[0].replace('-','.')
|
|
||||||
return VERSION
|
|
||||||
|
|
||||||
setup(name='wcsinst',
|
|
||||||
version=get_version(),
|
|
||||||
license='AGPLv3',
|
|
||||||
description='',
|
|
||||||
url='https://dev.entrouvert.org/projects/wcsinst/',
|
|
||||||
download_url='http://repos.entrouvert.org/wcsinst.git/',
|
|
||||||
author="Entr'ouvert",
|
|
||||||
author_email="info@entrouvert.com",
|
|
||||||
packages=find_packages(os.path.dirname(__file__) or '.'),
|
|
||||||
scripts=['manage.py'],
|
|
||||||
include_package_data = True,
|
|
||||||
install_requires=[
|
|
||||||
'django >= 1.5.1, < 1.6',
|
|
||||||
],
|
|
||||||
dependency_links = [
|
|
||||||
'http://pypi.python.org/packages/source/d/django-jsonresponse/django-jsonresponse-0.5.tar.gz',
|
|
||||||
],
|
|
||||||
)
|
|
|
@ -1,163 +0,0 @@
|
||||||
# Django settings for wcsinst project.
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
DEBUG = True
|
|
||||||
TEMPLATE_DEBUG = DEBUG
|
|
||||||
|
|
||||||
PROJECT_PATH = os.path.dirname(os.path.dirname(__file__))
|
|
||||||
|
|
||||||
ADMINS = (
|
|
||||||
# ('Your Name', 'your_email@example.com'),
|
|
||||||
)
|
|
||||||
|
|
||||||
MANAGERS = ADMINS
|
|
||||||
|
|
||||||
DATABASES = {
|
|
||||||
'default': {
|
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
|
||||||
'NAME': os.path.join(PROJECT_PATH, 'wcsinst.sqlite3'),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Hosts/domain names that are valid for this site; required if DEBUG is False
|
|
||||||
# See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts
|
|
||||||
ALLOWED_HOSTS = []
|
|
||||||
|
|
||||||
# Local time zone for this installation. Choices can be found here:
|
|
||||||
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
|
|
||||||
# although not all choices may be available on all operating systems.
|
|
||||||
# In a Windows environment this must be set to your system time zone.
|
|
||||||
TIME_ZONE = 'Europe/Brussels'
|
|
||||||
|
|
||||||
# Language code for this installation. All choices can be found here:
|
|
||||||
# http://www.i18nguy.com/unicode/language-identifiers.html
|
|
||||||
LANGUAGE_CODE = 'fr-fr'
|
|
||||||
|
|
||||||
SITE_ID = 1
|
|
||||||
|
|
||||||
# If you set this to False, Django will make some optimizations so as not
|
|
||||||
# to load the internationalization machinery.
|
|
||||||
USE_I18N = True
|
|
||||||
|
|
||||||
# If you set this to False, Django will not format dates, numbers and
|
|
||||||
# calendars according to the current locale.
|
|
||||||
USE_L10N = True
|
|
||||||
|
|
||||||
# If you set this to False, Django will not use timezone-aware datetimes.
|
|
||||||
USE_TZ = True
|
|
||||||
|
|
||||||
# Absolute filesystem path to the directory that will hold user-uploaded files.
|
|
||||||
# Example: "/var/www/example.com/media/"
|
|
||||||
MEDIA_ROOT = os.path.join(PROJECT_PATH, 'media')
|
|
||||||
|
|
||||||
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
|
|
||||||
# trailing slash.
|
|
||||||
# Examples: "http://example.com/media/", "http://media.example.com/"
|
|
||||||
MEDIA_URL = '/media/'
|
|
||||||
|
|
||||||
# Absolute path to the directory static files should be collected to.
|
|
||||||
# Don't put anything in this directory yourself; store your static files
|
|
||||||
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
|
|
||||||
# Example: "/var/www/example.com/static/"
|
|
||||||
STATIC_ROOT = os.path.join(PROJECT_PATH, 'static')
|
|
||||||
|
|
||||||
# URL prefix for static files.
|
|
||||||
# Example: "http://example.com/static/", "http://static.example.com/"
|
|
||||||
STATIC_URL = '/static/'
|
|
||||||
|
|
||||||
# Additional locations of static files
|
|
||||||
STATICFILES_DIRS = (
|
|
||||||
os.path.join(PROJECT_PATH, 'wcsinst', 'static'),
|
|
||||||
)
|
|
||||||
|
|
||||||
# List of finder classes that know how to find static files in
|
|
||||||
# various locations.
|
|
||||||
STATICFILES_FINDERS = (
|
|
||||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
|
||||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
|
||||||
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
|
|
||||||
)
|
|
||||||
|
|
||||||
# Make this unique, and don't share it with anybody.
|
|
||||||
SECRET_KEY = 'sw-v(^psaet3)44flti-zr!=u64mzfeaodkey(m=&^nz(=43!o'
|
|
||||||
|
|
||||||
# List of callables that know how to import templates from various sources.
|
|
||||||
TEMPLATE_LOADERS = (
|
|
||||||
'django.template.loaders.filesystem.Loader',
|
|
||||||
'django.template.loaders.app_directories.Loader',
|
|
||||||
# 'django.template.loaders.eggs.Loader',
|
|
||||||
)
|
|
||||||
|
|
||||||
MIDDLEWARE_CLASSES = (
|
|
||||||
'django.middleware.common.CommonMiddleware',
|
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
|
||||||
# Uncomment the next line for simple clickjacking protection:
|
|
||||||
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
|
||||||
)
|
|
||||||
|
|
||||||
ROOT_URLCONF = 'wcsinst.urls'
|
|
||||||
|
|
||||||
# Python dotted path to the WSGI application used by Django's runserver.
|
|
||||||
WSGI_APPLICATION = 'wcsinst.wsgi.application'
|
|
||||||
|
|
||||||
TEMPLATE_DIRS = (
|
|
||||||
os.path.join(PROJECT_PATH, 'wcsinst', 'templates'),
|
|
||||||
)
|
|
||||||
|
|
||||||
INSTALLED_APPS = (
|
|
||||||
'south',
|
|
||||||
'django.contrib.auth',
|
|
||||||
'django.contrib.contenttypes',
|
|
||||||
'django.contrib.sessions',
|
|
||||||
'django.contrib.sites',
|
|
||||||
'django.contrib.messages',
|
|
||||||
'django.contrib.staticfiles',
|
|
||||||
'django.contrib.admin',
|
|
||||||
)
|
|
||||||
|
|
||||||
# A sample logging configuration. The only tangible logging
|
|
||||||
# performed by this configuration is to send an email to
|
|
||||||
# the site admins on every HTTP 500 error when DEBUG=False.
|
|
||||||
# See http://docs.djangoproject.com/en/dev/topics/logging for
|
|
||||||
# more details on how to customize your logging configuration.
|
|
||||||
LOGGING = {
|
|
||||||
'version': 1,
|
|
||||||
'disable_existing_loggers': False,
|
|
||||||
'filters': {
|
|
||||||
'require_debug_false': {
|
|
||||||
'()': 'django.utils.log.RequireDebugFalse'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'handlers': {
|
|
||||||
'mail_admins': {
|
|
||||||
'level': 'ERROR',
|
|
||||||
'filters': ['require_debug_false'],
|
|
||||||
'class': 'django.utils.log.AdminEmailHandler'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'loggers': {
|
|
||||||
'django.request': {
|
|
||||||
'handlers': ['mail_admins'],
|
|
||||||
'level': 'ERROR',
|
|
||||||
'propagate': True,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WCSINSTD_URL = os.environ.get('WCSINSTD_URL')
|
|
||||||
|
|
||||||
if WCSINSTD_URL:
|
|
||||||
INSTALLED_APPS += ('wcsinst.wcsinst',)
|
|
||||||
else:
|
|
||||||
INSTALLED_APPS += ('wcsinst.wcsinstd',)
|
|
||||||
|
|
||||||
WCSINST_WCSCTL_SCRIPT = os.environ.get('WCSINST_WCSCTL_SCRIPT', 'wcsctl')
|
|
||||||
|
|
||||||
try:
|
|
||||||
from local_settings import *
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
|
@ -1,13 +0,0 @@
|
||||||
from django.conf.urls import patterns, include, url
|
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
from django.contrib import admin
|
|
||||||
admin.autodiscover()
|
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
|
||||||
url(r'^admin/', include(admin.site.urls)),
|
|
||||||
)
|
|
||||||
|
|
||||||
if 'wcsinst.wcsinstd' in settings.INSTALLED_APPS:
|
|
||||||
urlpatterns += patterns('',
|
|
||||||
(r'^wcsinstd/', include('wcsinst.wcsinstd.urls')))
|
|
|
@ -1,31 +0,0 @@
|
||||||
from django.contrib import admin
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
from models import WcsInstance, ApiSecret, Variable
|
|
||||||
|
|
||||||
class ApiSecretsInline(admin.TabularInline):
|
|
||||||
model = ApiSecret
|
|
||||||
verbose_name = _('API secret')
|
|
||||||
verbose_name_plural = _('API secrets')
|
|
||||||
|
|
||||||
class VariablesInline(admin.TabularInline):
|
|
||||||
model = Variable
|
|
||||||
verbose_name = _('variable')
|
|
||||||
verbose_name_plural = _('variables')
|
|
||||||
|
|
||||||
class WcsInstanceAdmin(admin.ModelAdmin):
|
|
||||||
prepopulated_fields = {'domain': ('title',)}
|
|
||||||
fieldsets = (
|
|
||||||
(None, {'fields': ('title', 'domain'),}),
|
|
||||||
('site-options.cfg',
|
|
||||||
{'fields': ('postgresql', ('saml2_use_role', 'saml2_role_prefix',), 'backoffice_feed_url' )}
|
|
||||||
),
|
|
||||||
('site-options.cfg au-quotidien',
|
|
||||||
{'fields': ('drupal', 'ezldap', 'strongbox', 'clicrdv', 'domino' )}
|
|
||||||
),
|
|
||||||
)
|
|
||||||
inlines = [VariablesInline, ApiSecretsInline]
|
|
||||||
save_as = True
|
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(WcsInstance, WcsInstanceAdmin)
|
|
|
@ -1,34 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
import datetime
|
|
||||||
from south.db import db
|
|
||||||
from south.v2 import SchemaMigration
|
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(SchemaMigration):
|
|
||||||
|
|
||||||
def forwards(self, orm):
|
|
||||||
# Adding model 'WcsInstance'
|
|
||||||
db.create_table(u'wcsinst_wcsinstance', (
|
|
||||||
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
|
||||||
('title', self.gf('django.db.models.fields.CharField')(max_length=50)),
|
|
||||||
('domain', self.gf('django.db.models.fields.CharField')(max_length=100)),
|
|
||||||
))
|
|
||||||
db.send_create_signal(u'wcsinst', ['WcsInstance'])
|
|
||||||
|
|
||||||
|
|
||||||
def backwards(self, orm):
|
|
||||||
# Deleting model 'WcsInstance'
|
|
||||||
db.delete_table(u'wcsinst_wcsinstance')
|
|
||||||
|
|
||||||
|
|
||||||
models = {
|
|
||||||
u'wcsinst.wcsinstance': {
|
|
||||||
'Meta': {'object_name': 'WcsInstance'},
|
|
||||||
'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
complete_apps = ['wcsinst']
|
|
|
@ -1,142 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
import datetime
|
|
||||||
from south.db import db
|
|
||||||
from south.v2 import SchemaMigration
|
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(SchemaMigration):
|
|
||||||
|
|
||||||
def forwards(self, orm):
|
|
||||||
# Adding model 'Variable'
|
|
||||||
db.create_table(u'wcsinst_variable', (
|
|
||||||
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
|
||||||
('key', self.gf('django.db.models.fields.CharField')(max_length=128)),
|
|
||||||
('value', self.gf('django.db.models.fields.CharField')(max_length=1024, blank=True)),
|
|
||||||
('wcs_instance', self.gf('django.db.models.fields.related.ForeignKey')(related_name='variables', to=orm['wcsinst.WcsInstance'])),
|
|
||||||
))
|
|
||||||
db.send_create_signal(u'wcsinst', ['Variable'])
|
|
||||||
|
|
||||||
# Adding model 'ApiSecret'
|
|
||||||
db.create_table(u'wcsinst_apisecret', (
|
|
||||||
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
|
||||||
('key', self.gf('django.db.models.fields.CharField')(max_length=128)),
|
|
||||||
('value', self.gf('django.db.models.fields.CharField')(max_length=1024, blank=True)),
|
|
||||||
('wcs_instance', self.gf('django.db.models.fields.related.ForeignKey')(related_name='api_secrets', to=orm['wcsinst.WcsInstance'])),
|
|
||||||
))
|
|
||||||
db.send_create_signal(u'wcsinst', ['ApiSecret'])
|
|
||||||
|
|
||||||
# Adding field 'WcsInstance.postgresql'
|
|
||||||
db.add_column(u'wcsinst_wcsinstance', 'postgresql',
|
|
||||||
self.gf('django.db.models.fields.BooleanField')(default=False),
|
|
||||||
keep_default=False)
|
|
||||||
|
|
||||||
# Adding field 'WcsInstance.saml2_use_role'
|
|
||||||
db.add_column(u'wcsinst_wcsinstance', 'saml2_use_role',
|
|
||||||
self.gf('django.db.models.fields.BooleanField')(default=False),
|
|
||||||
keep_default=False)
|
|
||||||
|
|
||||||
# Adding field 'WcsInstance.saml2_role_prefix'
|
|
||||||
db.add_column(u'wcsinst_wcsinstance', 'saml2_role_prefix',
|
|
||||||
self.gf('django.db.models.fields.CharField')(default='', max_length=128, blank=True),
|
|
||||||
keep_default=False)
|
|
||||||
|
|
||||||
# Adding field 'WcsInstance.backoffice_feed_url'
|
|
||||||
db.add_column(u'wcsinst_wcsinstance', 'backoffice_feed_url',
|
|
||||||
self.gf('django.db.models.fields.URLField')(default='', max_length=128, blank=True),
|
|
||||||
keep_default=False)
|
|
||||||
|
|
||||||
# Adding field 'WcsInstance.drupal'
|
|
||||||
db.add_column(u'wcsinst_wcsinstance', 'drupal',
|
|
||||||
self.gf('django.db.models.fields.BooleanField')(default=False),
|
|
||||||
keep_default=False)
|
|
||||||
|
|
||||||
# Adding field 'WcsInstance.ezldap'
|
|
||||||
db.add_column(u'wcsinst_wcsinstance', 'ezldap',
|
|
||||||
self.gf('django.db.models.fields.BooleanField')(default=False),
|
|
||||||
keep_default=False)
|
|
||||||
|
|
||||||
# Adding field 'WcsInstance.strongbox'
|
|
||||||
db.add_column(u'wcsinst_wcsinstance', 'strongbox',
|
|
||||||
self.gf('django.db.models.fields.BooleanField')(default=False),
|
|
||||||
keep_default=False)
|
|
||||||
|
|
||||||
# Adding field 'WcsInstance.clicrdv'
|
|
||||||
db.add_column(u'wcsinst_wcsinstance', 'clicrdv',
|
|
||||||
self.gf('django.db.models.fields.BooleanField')(default=False),
|
|
||||||
keep_default=False)
|
|
||||||
|
|
||||||
# Adding field 'WcsInstance.domino'
|
|
||||||
db.add_column(u'wcsinst_wcsinstance', 'domino',
|
|
||||||
self.gf('django.db.models.fields.BooleanField')(default=False),
|
|
||||||
keep_default=False)
|
|
||||||
|
|
||||||
|
|
||||||
def backwards(self, orm):
|
|
||||||
# Deleting model 'Variable'
|
|
||||||
db.delete_table(u'wcsinst_variable')
|
|
||||||
|
|
||||||
# Deleting model 'ApiSecret'
|
|
||||||
db.delete_table(u'wcsinst_apisecret')
|
|
||||||
|
|
||||||
# Deleting field 'WcsInstance.postgresql'
|
|
||||||
db.delete_column(u'wcsinst_wcsinstance', 'postgresql')
|
|
||||||
|
|
||||||
# Deleting field 'WcsInstance.saml2_use_role'
|
|
||||||
db.delete_column(u'wcsinst_wcsinstance', 'saml2_use_role')
|
|
||||||
|
|
||||||
# Deleting field 'WcsInstance.saml2_role_prefix'
|
|
||||||
db.delete_column(u'wcsinst_wcsinstance', 'saml2_role_prefix')
|
|
||||||
|
|
||||||
# Deleting field 'WcsInstance.backoffice_feed_url'
|
|
||||||
db.delete_column(u'wcsinst_wcsinstance', 'backoffice_feed_url')
|
|
||||||
|
|
||||||
# Deleting field 'WcsInstance.drupal'
|
|
||||||
db.delete_column(u'wcsinst_wcsinstance', 'drupal')
|
|
||||||
|
|
||||||
# Deleting field 'WcsInstance.ezldap'
|
|
||||||
db.delete_column(u'wcsinst_wcsinstance', 'ezldap')
|
|
||||||
|
|
||||||
# Deleting field 'WcsInstance.strongbox'
|
|
||||||
db.delete_column(u'wcsinst_wcsinstance', 'strongbox')
|
|
||||||
|
|
||||||
# Deleting field 'WcsInstance.clicrdv'
|
|
||||||
db.delete_column(u'wcsinst_wcsinstance', 'clicrdv')
|
|
||||||
|
|
||||||
# Deleting field 'WcsInstance.domino'
|
|
||||||
db.delete_column(u'wcsinst_wcsinstance', 'domino')
|
|
||||||
|
|
||||||
|
|
||||||
models = {
|
|
||||||
u'wcsinst.apisecret': {
|
|
||||||
'Meta': {'object_name': 'ApiSecret'},
|
|
||||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'key': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
|
||||||
'value': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}),
|
|
||||||
'wcs_instance': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'api_secrets'", 'to': u"orm['wcsinst.WcsInstance']"})
|
|
||||||
},
|
|
||||||
u'wcsinst.variable': {
|
|
||||||
'Meta': {'object_name': 'Variable'},
|
|
||||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'key': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
|
||||||
'value': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}),
|
|
||||||
'wcs_instance': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variables'", 'to': u"orm['wcsinst.WcsInstance']"})
|
|
||||||
},
|
|
||||||
u'wcsinst.wcsinstance': {
|
|
||||||
'Meta': {'object_name': 'WcsInstance'},
|
|
||||||
'backoffice_feed_url': ('django.db.models.fields.URLField', [], {'max_length': '128', 'blank': 'True'}),
|
|
||||||
'clicrdv': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'domino': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'drupal': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'ezldap': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'postgresql': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'saml2_role_prefix': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
|
|
||||||
'saml2_use_role': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'strongbox': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
complete_apps = ['wcsinst']
|
|
|
@ -1,117 +0,0 @@
|
||||||
import json
|
|
||||||
import logging
|
|
||||||
import urllib2
|
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db import models
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
class WcsInstance(models.Model):
|
|
||||||
title = models.CharField(max_length=50)
|
|
||||||
domain = models.CharField(max_length=100)
|
|
||||||
|
|
||||||
# site-options.cfg options
|
|
||||||
postgresql = models.BooleanField(verbose_name=_('postgresql'),
|
|
||||||
blank=True)
|
|
||||||
saml2_use_role = models.BooleanField(verbose_name=_('use saml2 roles'),
|
|
||||||
blank=True)
|
|
||||||
saml2_role_prefix = models.CharField(verbose_name=_('role prefix'),
|
|
||||||
blank=True, max_length=128)
|
|
||||||
backoffice_feed_url = models.URLField(verbose_name=_('backoffice feed url'),
|
|
||||||
blank=True, max_length=128)
|
|
||||||
drupal = models.BooleanField(verbose_name=_('drupal'),
|
|
||||||
blank=True)
|
|
||||||
ezldap = models.BooleanField(verbose_name=_('ezldap'),
|
|
||||||
blank=True)
|
|
||||||
strongbox = models.BooleanField(verbose_name=_('strongbox'),
|
|
||||||
blank=True)
|
|
||||||
clicrdv = models.BooleanField(verbose_name=_('clicrdv'),
|
|
||||||
blank=True)
|
|
||||||
domino = models.BooleanField(verbose_name=_('domino'),
|
|
||||||
blank=True)
|
|
||||||
|
|
||||||
|
|
||||||
def __unicode__(self):
|
|
||||||
return '%s (%s)' % (self.title, self.domain)
|
|
||||||
|
|
||||||
def site_options_cfg(self):
|
|
||||||
d = {
|
|
||||||
'postgresql': self.postgresql,
|
|
||||||
'saml2_use_role': self.saml2_use_role,
|
|
||||||
'saml2_role_prefix': self.saml2_role_prefix,
|
|
||||||
'backoffice_feed_url': self.backoffice_feed_url,
|
|
||||||
'drupal': self.drupal,
|
|
||||||
'ezldap': self.ezldap,
|
|
||||||
'strongbox': self.strongbox,
|
|
||||||
'clicrdv': self.clicrdv,
|
|
||||||
'domino': self.domino,
|
|
||||||
}
|
|
||||||
d['api_secrets'] = dict((kv.key, kv.value) for kv in self.api_secrets.all())
|
|
||||||
d['variables'] = dict((kv.key, kv.value) for kv in self.variables.all())
|
|
||||||
return d
|
|
||||||
|
|
||||||
def to_json(self):
|
|
||||||
return {
|
|
||||||
'title': self.title,
|
|
||||||
'domain': self.domain,
|
|
||||||
'site_options_cfg': self.site_options_cfg(),
|
|
||||||
}
|
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
|
||||||
created = (self.id is None)
|
|
||||||
super(WcsInstance, self).save(*args, **kwargs)
|
|
||||||
# notify wcsinstd
|
|
||||||
if not settings.WCSINSTD_URL:
|
|
||||||
return
|
|
||||||
if created:
|
|
||||||
url = settings.WCSINSTD_URL + 'wcsinstd/create'
|
|
||||||
else:
|
|
||||||
url = settings.WCSINSTD_URL + 'wcsinstd/%s/' % self.domain
|
|
||||||
post_data = json.dumps(self.to_json())
|
|
||||||
request = urllib2.Request(url)
|
|
||||||
request.add_header('Accept', 'application/json')
|
|
||||||
request.add_header('Content-Type', 'application/json;charset=UTF-8')
|
|
||||||
request.add_data(post_data)
|
|
||||||
try:
|
|
||||||
p = urllib2.urlopen(request)
|
|
||||||
except urllib2.HTTPError as e:
|
|
||||||
logger.error('wcsinstd HTTP error (%s)', str(e))
|
|
||||||
print e.read()
|
|
||||||
except urllib2.URLError as e:
|
|
||||||
print e
|
|
||||||
logger.error('wcsinstd URL error (%s)', str(e))
|
|
||||||
else:
|
|
||||||
out_data = p.read()
|
|
||||||
p.close()
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
verbose_name = _('wcs instance')
|
|
||||||
verbose_name_plural = _('wcs instances')
|
|
||||||
|
|
||||||
|
|
||||||
class KeyValue(models.Model):
|
|
||||||
key = models.CharField(max_length=128)
|
|
||||||
value = models.CharField(max_length=1024, blank=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
abstract = True
|
|
||||||
|
|
||||||
|
|
||||||
class Variable(KeyValue):
|
|
||||||
wcs_instance = models.ForeignKey(WcsInstance, related_name='variables')
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
verbose_name = _('variable')
|
|
||||||
verbose_name_plural = _('variables')
|
|
||||||
|
|
||||||
|
|
||||||
class ApiSecret(KeyValue):
|
|
||||||
wcs_instance = models.ForeignKey(WcsInstance, related_name='api_secrets')
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
verbose_name = _('api secret')
|
|
||||||
verbose_name_plural = _('api secrets')
|
|
||||||
|
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
"""
|
|
||||||
This file demonstrates writing tests using the unittest module. These will pass
|
|
||||||
when you run "manage.py test".
|
|
||||||
|
|
||||||
Replace this with more appropriate tests for your application.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
|
|
||||||
class SimpleTest(TestCase):
|
|
||||||
def test_basic_addition(self):
|
|
||||||
"""
|
|
||||||
Tests that 1 + 1 always equals 2.
|
|
||||||
"""
|
|
||||||
self.assertEqual(1 + 1, 2)
|
|
|
@ -1 +0,0 @@
|
||||||
# Create your views here.
|
|
|
@ -1,5 +0,0 @@
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
URL_TEMPLATE = getattr(settings, 'WCSINST_URL_TEMPLATE', 'https://%(domain)s')
|
|
||||||
WCS_APP_DIR = getattr(settings, 'WCSINST_WCS_APP_DIR', None)
|
|
||||||
WCSCTL_SCRIPT = getattr(settings, 'WCSINST_WCSCTL_SCRIPT', 'wcsctl')
|
|
|
@ -1,226 +0,0 @@
|
||||||
import string
|
|
||||||
import cPickle
|
|
||||||
import os
|
|
||||||
import zipfile
|
|
||||||
import subprocess
|
|
||||||
from urlparse import urlparse
|
|
||||||
|
|
||||||
from cStringIO import StringIO
|
|
||||||
import xml.etree.ElementTree as ET
|
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
import psycopg2
|
|
||||||
|
|
||||||
from . import app_settings
|
|
||||||
|
|
||||||
|
|
||||||
def get_provider_key(provider_id):
|
|
||||||
return provider_id.replace('://', '-').replace('/', '-').replace('?', '-').replace(':', '-')
|
|
||||||
|
|
||||||
|
|
||||||
class DeployInstance(object):
|
|
||||||
skeleton = 'default'
|
|
||||||
|
|
||||||
skel_dir = None
|
|
||||||
collectivity_install_dir = None
|
|
||||||
|
|
||||||
def __init__(self, domain, title, site_options_cfg):
|
|
||||||
self.domain = domain
|
|
||||||
self.title = title
|
|
||||||
self.site_options_cfg = site_options_cfg
|
|
||||||
|
|
||||||
def make(self):
|
|
||||||
self.skel_dir = os.path.join(settings.MEDIA_ROOT, 'skeletons', self.skeleton)
|
|
||||||
|
|
||||||
url_template = app_settings.URL_TEMPLATE
|
|
||||||
self.url = str(url_template % {'domain': self.domain})
|
|
||||||
|
|
||||||
host, path = urlparse(self.url)[1:3]
|
|
||||||
if path.endswith('/'):
|
|
||||||
path = path[:-1]
|
|
||||||
|
|
||||||
coldir = host
|
|
||||||
if path:
|
|
||||||
coldir += path.replace('/', '+')
|
|
||||||
|
|
||||||
self.collectivity_install_dir = os.path.join(app_settings.WCS_APP_DIR, coldir)
|
|
||||||
|
|
||||||
if os.path.exists(self.collectivity_install_dir):
|
|
||||||
# site exists, let's update it
|
|
||||||
pass
|
|
||||||
anew = False
|
|
||||||
else:
|
|
||||||
anew = True
|
|
||||||
os.mkdir(self.collectivity_install_dir)
|
|
||||||
|
|
||||||
z = zipfile.ZipFile(os.path.join(self.skel_dir, 'export.wcs'), 'r')
|
|
||||||
|
|
||||||
for f in z.namelist():
|
|
||||||
path = os.path.join(self.collectivity_install_dir, f)
|
|
||||||
data = z.read(f)
|
|
||||||
if not os.path.exists(os.path.dirname(path)):
|
|
||||||
os.mkdir(os.path.dirname(path))
|
|
||||||
open(path, 'w').write(data)
|
|
||||||
z.close()
|
|
||||||
|
|
||||||
config_file = os.path.join(self.collectivity_install_dir, 'config.pck')
|
|
||||||
if os.path.exists(config_file):
|
|
||||||
wcs_cfg = cPickle.load(file(os.path.join(self.collectivity_install_dir, 'config.pck')))
|
|
||||||
else:
|
|
||||||
wcs_cfg = {}
|
|
||||||
|
|
||||||
has_sql = self.make_sql_config(wcs_cfg)
|
|
||||||
self.make_sso_config(wcs_cfg)
|
|
||||||
self.make_site_options()
|
|
||||||
|
|
||||||
cPickle.dump(wcs_cfg, file(config_file, 'w'))
|
|
||||||
|
|
||||||
if has_sql:
|
|
||||||
self.make_sql_tables(wcs_cfg)
|
|
||||||
|
|
||||||
self.make_apache_vhost()
|
|
||||||
self.reload_apache()
|
|
||||||
|
|
||||||
|
|
||||||
def make_sql_config(self, wcs_cfg):
|
|
||||||
if not wcs_cfg.get('postgresql'):
|
|
||||||
# this is not a site configured to use SQL
|
|
||||||
return False
|
|
||||||
|
|
||||||
database_name = wcs_cfg['postgresql'].get('database', 'wcs')
|
|
||||||
domain_table_name = self.domain.replace('-', '_').replace('.', '_')
|
|
||||||
if '_' in database_name:
|
|
||||||
database_name = '%s_%s' % (database_name.split('_')[0], domain_table_name)
|
|
||||||
else:
|
|
||||||
database_name = '%s_%s' % (database_name, domain_table_name)
|
|
||||||
|
|
||||||
postgresql_cfg = {}
|
|
||||||
for k, v in wcs_cfg['postgresql'].items():
|
|
||||||
if v:
|
|
||||||
postgresql_cfg[k] = v
|
|
||||||
try:
|
|
||||||
pgconn = psycopg2.connect(**postgresql_cfg)
|
|
||||||
except psycopg2.Error:
|
|
||||||
# XXX: log
|
|
||||||
raise
|
|
||||||
|
|
||||||
pgconn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
|
||||||
cur = pgconn.cursor()
|
|
||||||
try:
|
|
||||||
cur.execute('''CREATE DATABASE %s''' % database_name)
|
|
||||||
except psycopg2.Error as e:
|
|
||||||
print 'got psycopg2 error:', e
|
|
||||||
cur.close()
|
|
||||||
|
|
||||||
wcs_cfg['postgresql']['database'] = database_name
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def make_sql_tables(self, wcs_cfg):
|
|
||||||
params = []
|
|
||||||
for param in ('database', 'user', 'password', 'host', 'port'):
|
|
||||||
if wcs_cfg.get('postgresql').get(param):
|
|
||||||
if param == 'database':
|
|
||||||
params.append('--dbname')
|
|
||||||
else:
|
|
||||||
params.append('--' + param)
|
|
||||||
params.append(wcs_cfg.get('postgresql').get(param))
|
|
||||||
os.system('%s convert-to-sql %s %s' % (app_settings.WCSCTL_SCRIPT, ' '.join(params), self.domain))
|
|
||||||
|
|
||||||
def make_sso_config(self, wcs_cfg):
|
|
||||||
has_idff = False
|
|
||||||
has_saml2 = False
|
|
||||||
|
|
||||||
service_provider_configuration = {}
|
|
||||||
|
|
||||||
if self.url.endswith('/'):
|
|
||||||
url_stripped = self.url[:-1]
|
|
||||||
else:
|
|
||||||
url_stripped = self.url
|
|
||||||
|
|
||||||
if os.path.exists(os.path.join(self.skel_dir, 'idff-metadata-template')):
|
|
||||||
# there's a ID-FF metadata template, so we do the ID-FF stuff
|
|
||||||
has_idff = True
|
|
||||||
service_provider_configuration.update({
|
|
||||||
'base_url': '%s/liberty' % url_stripped,
|
|
||||||
'metadata': 'metadata.xml',
|
|
||||||
'providerid': '%s/liberty/metadata' % url_stripped,
|
|
||||||
})
|
|
||||||
|
|
||||||
idff_metadata_template = file(
|
|
||||||
os.path.join(self.skel_dir, 'idff-metadata-template')).read()
|
|
||||||
file(os.path.join(self.collectivity_install_dir, 'metadata.xml'), 'w').write(
|
|
||||||
string.Template(idff_metadata_template).substitute({'url': url_stripped}))
|
|
||||||
|
|
||||||
if os.path.exists(os.path.join(self.skel_dir, 'saml2-metadata-template')):
|
|
||||||
# there's a SAMLv2 metadata template, so we do the SAMLv2 stuff
|
|
||||||
has_saml2 = True
|
|
||||||
service_provider_configuration.update({
|
|
||||||
'saml2_base_url': '%s/saml' % url_stripped,
|
|
||||||
'saml2_metadata': 'saml2-metadata.xml',
|
|
||||||
'saml2_providerid': '%s/saml/metadata' % url_stripped
|
|
||||||
})
|
|
||||||
|
|
||||||
saml2_metadata_template = file(
|
|
||||||
os.path.join(self.skel_dir, 'saml2-metadata-template')).read()
|
|
||||||
file(os.path.join(self.collectivity_install_dir, 'saml2-metadata.xml'), 'w').write(
|
|
||||||
string.Template(saml2_metadata_template).substitute({'url': url_stripped}))
|
|
||||||
|
|
||||||
if has_idff or has_saml2:
|
|
||||||
idp_metadata = ET.parse(file(os.path.join(self.skel_dir, 'idp-metadata.xml')))
|
|
||||||
entity_id = idp_metadata.getroot().attrib['entityID']
|
|
||||||
idp_key = get_provider_key(entity_id)
|
|
||||||
|
|
||||||
wcs_cfg['identification'] = {'methods': ['idp']}
|
|
||||||
wcs_cfg['idp'] = {
|
|
||||||
idp_key: {
|
|
||||||
'metadata': 'provider-%s-metadata.xml' % idp_key,
|
|
||||||
'metadata_url': entity_id,
|
|
||||||
'publickey_url': None,
|
|
||||||
'role': 2}}
|
|
||||||
wcs_cfg['sp'] = {
|
|
||||||
'common_domain': None,
|
|
||||||
'common_domain_getter_url': None,
|
|
||||||
'organization_name': self.title.encode('utf-8'),
|
|
||||||
'privatekey': 'private-key.pem',
|
|
||||||
'publickey': 'public-key.pem'}
|
|
||||||
wcs_cfg['sp'].update(service_provider_configuration)
|
|
||||||
|
|
||||||
file(os.path.join(self.collectivity_install_dir, 'provider-%s-metadata.xml' % idp_key), 'w').write(
|
|
||||||
file(os.path.join(self.skel_dir, 'idp-metadata.xml')).read())
|
|
||||||
file(os.path.join(self.collectivity_install_dir, 'public-key.pem'), 'w').write(
|
|
||||||
file(os.path.join(self.skel_dir, 'public-key.pem')).read())
|
|
||||||
file(os.path.join(self.collectivity_install_dir, 'private-key.pem'), 'w').write(
|
|
||||||
file(os.path.join(self.skel_dir, 'private-key.pem')).read())
|
|
||||||
else:
|
|
||||||
wcs_cfg['identification'] = {'methods': ['password']}
|
|
||||||
|
|
||||||
|
|
||||||
def make_site_options(self):
|
|
||||||
options_template_path = os.path.join(self.skel_dir, 'site-options.cfg')
|
|
||||||
if not os.path.exists(options_template_path):
|
|
||||||
return
|
|
||||||
options_template = file(options_template_path).read()
|
|
||||||
file(os.path.join(self.collectivity_install_dir, 'site-options.cfg'), 'w').write(
|
|
||||||
string.Template(options_template).substitute({
|
|
||||||
'domain': self.domain,
|
|
||||||
'options': self.site_options_cfg
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def make_apache_vhost(self):
|
|
||||||
apache_vhost_template_path = os.path.join(self.skel_dir, 'apache-vhost.conf')
|
|
||||||
if not os.path.exists(apache_vhost_template_path):
|
|
||||||
return
|
|
||||||
apache_vhost_template = file(apache_vhost_template_path).read()
|
|
||||||
apache_dir = os.path.join(settings.MEDIA_ROOT, 'vhosts.d')
|
|
||||||
if not os.path.exists(apache_dir):
|
|
||||||
os.mkdir(apache_dir)
|
|
||||||
file(os.path.join(apache_dir, '%s.conf' % self.domain), 'w').write(
|
|
||||||
string.Template(apache_vhost_template).substitute({'domain': self.domain}))
|
|
||||||
|
|
||||||
|
|
||||||
def reload_apache(self):
|
|
||||||
os.system('sudo -n /etc/init.d/apache2 reload')
|
|
|
@ -1,3 +0,0 @@
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
# Create your models here.
|
|
|
@ -1,7 +0,0 @@
|
||||||
from django.conf.urls import patterns, url, include
|
|
||||||
|
|
||||||
urlpatterns = patterns('wcsinst.wcsinstd.views',
|
|
||||||
url(r'^create$', 'create'),
|
|
||||||
url(r'^(?P<instance>[\w\.-]+)/$', 'update'),
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
import json
|
|
||||||
import threading
|
|
||||||
|
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
|
||||||
from django.views.decorators.http import require_POST
|
|
||||||
|
|
||||||
from jsonresponse import to_json
|
|
||||||
|
|
||||||
from .deploy import DeployInstance
|
|
||||||
|
|
||||||
|
|
||||||
@csrf_exempt
|
|
||||||
@to_json('api')
|
|
||||||
@require_POST
|
|
||||||
def create(request):
|
|
||||||
data = json.loads(request.body)
|
|
||||||
deploy = DeployInstance(**data)
|
|
||||||
threading.Thread(target=deploy.make).start()
|
|
||||||
return {}
|
|
||||||
|
|
||||||
|
|
||||||
@csrf_exempt
|
|
||||||
@to_json('api')
|
|
||||||
@require_POST
|
|
||||||
def update(request, instance):
|
|
||||||
print 'updating instance:', instance
|
|
||||||
data = json.loads(request.body)
|
|
||||||
if data.get('domain') != instance:
|
|
||||||
raise Exception('domain mismatch') # -> should remove/add ?
|
|
||||||
deploy = DeployInstance(**data)
|
|
||||||
threading.Thread(target=deploy.make).start()
|
|
||||||
return {}
|
|
|
@ -1,32 +0,0 @@
|
||||||
"""
|
|
||||||
WSGI config for wcsinst project.
|
|
||||||
|
|
||||||
This module contains the WSGI application used by Django's development server
|
|
||||||
and any production WSGI deployments. It should expose a module-level variable
|
|
||||||
named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
|
|
||||||
this application via the ``WSGI_APPLICATION`` setting.
|
|
||||||
|
|
||||||
Usually you will have the standard Django WSGI application here, but it also
|
|
||||||
might make sense to replace the whole Django WSGI application with a custom one
|
|
||||||
that later delegates to the Django one. For example, you could introduce WSGI
|
|
||||||
middleware here, or combine a Django application with an application of another
|
|
||||||
framework.
|
|
||||||
|
|
||||||
"""
|
|
||||||
import os
|
|
||||||
|
|
||||||
# We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks
|
|
||||||
# if running multiple sites in the same mod_wsgi process. To fix this, use
|
|
||||||
# mod_wsgi daemon mode with each site in its own daemon process, or use
|
|
||||||
# os.environ["DJANGO_SETTINGS_MODULE"] = "wcsinst.settings"
|
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "wcsinst.settings")
|
|
||||||
|
|
||||||
# This application object is used by any WSGI server configured to use this
|
|
||||||
# file. This includes Django's development server, if the WSGI_APPLICATION
|
|
||||||
# setting points here.
|
|
||||||
from django.core.wsgi import get_wsgi_application
|
|
||||||
application = get_wsgi_application()
|
|
||||||
|
|
||||||
# Apply WSGI middleware here.
|
|
||||||
# from helloworld.wsgi import HelloWorldApplication
|
|
||||||
# application = HelloWorldApplication(application)
|
|
Reference in New Issue