general: remove ozwillo extension (#53229)
This commit is contained in:
parent
fb3627eaf8
commit
5e865ad9b3
|
@ -13,9 +13,6 @@ recursive-include hobo/locale *.po *.mo
|
|||
recursive-include hobo/environment/locale *.po *.mo
|
||||
recursive-include hobo/agent/authentic2/locale *.po *.mo
|
||||
recursive-include tests *.py *.json
|
||||
recursive-include hobo/contrib/ozwillo/scripts *.py
|
||||
recursive-include hobo/contrib/ozwillo/examples *.json
|
||||
include hobo/contrib/ozwillo/README.rst
|
||||
include hobo/multitenant/README
|
||||
include MANIFEST.in
|
||||
include COPYING
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
Ozwillo contrib app for SICTIAM
|
||||
===============================
|
||||
|
||||
Install on Debian
|
||||
-----------------
|
||||
|
||||
1. add `hobo.contrib.ozwillo` to INSTALLED_APPS
|
||||
|
||||
2. copy files from examples/ into /etc/hobo/ozwillo/ (must be readable by all)
|
||||
|
||||
3. copy following line in /etc/sudoers.d/sictiam::
|
||||
|
||||
hobo ALL=(ALL:ALL) NOPASSWD: ALL
|
||||
|
||||
4. set the following variables in `/etc/hobo/settings.d/10_ozwillo.py`:
|
||||
|
||||
- OZWILLO_SECRET
|
||||
- OZWILLO_ENV_DOMAIN (e.g: sictiam.dev.entrouvert.org)
|
||||
- OZWILLO_DESTRUCTION_URI
|
||||
- OZWILLO_DESTRUCTION_SECRET
|
||||
- OZWILLO_PLATEFORM (https://dev.entrouvert.org/projects/sictiam/wiki/Raccordement_OpenID_Connect_%C3%A0_Ozwillo for the values)
|
||||
- OZWILLO_SERVICES (use only for the destruction, explained down)
|
||||
|
||||
Exemple::
|
||||
|
||||
OZWILLO_DESTRUCTION_SECRET = "mysecret"
|
||||
OZWILLO_DESTRUCTION_URI = "https://hobo-sve.test-demarches.sictiam.fr/ozwillo/delete-publik-instance/"
|
||||
OZWILLO_ENABLED = True,
|
||||
OZWILLO_ENV_DOMAIN = "test-demarches.sictiam.fr"
|
||||
OZWILLO_PLATEFORM = "https://accounts.ozwillo-preprod.eu/"
|
||||
OZWILLO_SECRET = "myothersecret"
|
||||
OZWILLO_SERVICES = {
|
||||
"authentic-multitenant": [
|
||||
"connexion-",
|
||||
"authentic2-multitenant-manage"
|
||||
],
|
||||
"combo_agent": [
|
||||
"agents-",
|
||||
"combo-manage"
|
||||
],
|
||||
"combo_usager": [
|
||||
"",
|
||||
"combo-manage"
|
||||
],
|
||||
"fargo": [
|
||||
"porte-documents-",
|
||||
"fargo-manage"
|
||||
],
|
||||
"hobo": [
|
||||
"hobo-",
|
||||
"hobo-manage"
|
||||
],
|
||||
"passerelle": [
|
||||
"passerelle-",
|
||||
"passerelle-manage"
|
||||
],
|
||||
"wcs": [
|
||||
"demarches-",
|
||||
"wcsctl"
|
||||
]
|
||||
}
|
||||
|
||||
Design
|
||||
------
|
||||
|
||||
The views create-publik-instance receive an ozwillo request with some clients
|
||||
informations (secret and id), the ozwillo user sending the request, the
|
||||
organization name (which is the collectivity's name to deploy) and the
|
||||
registration uri (where you're supposed to POST when the job's done).
|
||||
|
||||
The script modify a template_recipe by replacing every 'instance_name' by the
|
||||
actual organization name, and same for the combo user extract (rewritting all
|
||||
the url_redirect fields).
|
||||
|
||||
The script then launch a cook and three commands :
|
||||
- the import of the combo user with the modified extract
|
||||
- the import of the combo agent
|
||||
- a runscript creating a role (same as the one in wcs linked to the form sve
|
||||
'agents sve'), a provider (the details are in the page linked for the parameter
|
||||
OZWILLO_PLATEFORM) and an admin User in Authentic who is the ozwillo user
|
||||
sending the request.
|
||||
|
||||
In the final acknowledgement response, the script sends a 'services'
|
||||
dictionnary for ozillo to set some links and parameters in its backoffice about
|
||||
the app deployed).
|
||||
|
||||
OZWILLO_SERVICES is a dict following this pattern: 'service_user':
|
||||
['service_prefix', 'service_command_manager']. E.G::
|
||||
|
||||
{
|
||||
"authentic-multitenant": ["connexion-", "authentic2-multitenant-manage"],
|
||||
"combo_agent": ["agents-", "combo-manage"],
|
||||
"combo_usager": ["", "combo-manage"],
|
||||
"fargo": ["porte-documents-", "fargo-manage"],
|
||||
"hobo": ["hobo-", "hobo-manage"],
|
||||
"passerelle": ["passerelle-", "passerelle-manage"],
|
||||
"wcs": ["demarches-", "wcsctl"]
|
||||
}
|
||||
|
||||
Destruction
|
||||
===========
|
||||
|
||||
For the complete destruction of w.c.s. instances it's necessary that in the
|
||||
default skeleton (`/var/lib/wcs/skeletons/export.zip`) the `config.pck` file
|
||||
contains a key `postgresql.createdb-connection-params`.
|
|
@ -1,10 +0,0 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from .models import OzwilloInstance
|
||||
|
||||
|
||||
class OzwilloInstanceAdmin(admin.ModelAdmin):
|
||||
list_display = ['id', 'domain_slug', 'external_ozwillo_id', 'state', 'created', 'modified']
|
||||
list_filter = ['state', 'created', 'modified']
|
||||
|
||||
admin.site.register(OzwilloInstance, OzwilloInstanceAdmin)
|
|
@ -1,30 +0,0 @@
|
|||
[
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"fields": {
|
||||
"extra_css_class": "",
|
||||
"groups": [],
|
||||
"order": 1,
|
||||
"placeholder": "content",
|
||||
"public": true,
|
||||
"restricted_to_unlogged": false,
|
||||
"slug": "services",
|
||||
"text": "<h2>Bienvenue</h2>\r\n"
|
||||
},
|
||||
"model": "data.textcell"
|
||||
}
|
||||
],
|
||||
"fields": {
|
||||
"exclude_from_navigation": false,
|
||||
"groups": [],
|
||||
"order": 1,
|
||||
"parent": null,
|
||||
"public": false,
|
||||
"redirect_url": "",
|
||||
"slug": "index",
|
||||
"template_name": "standard",
|
||||
"title": "Accueil"
|
||||
}
|
||||
}
|
||||
]
|
|
@ -1,169 +0,0 @@
|
|||
[
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"fields": {
|
||||
"extra_css_class": "",
|
||||
"groups": [],
|
||||
"order": 0,
|
||||
"placeholder": "content",
|
||||
"public": true,
|
||||
"restricted_to_unlogged": true,
|
||||
"slug": "",
|
||||
"text": "<h2>Bienvenue</h2>\r\n\r\n<p>Bienvenue sur votre compte usager.</p>\r\n\r\n<p>Pour suivre vos démarches en cours, créez votre compte personnel ou identifiez-vous depuis <a href=\"/login/\">la page de connexion</a>.</p>\r\n"
|
||||
},
|
||||
"model": "data.textcell"
|
||||
},
|
||||
{
|
||||
"fields": {
|
||||
"extra_css_class": "",
|
||||
"groups": [],
|
||||
"order": 1,
|
||||
"placeholder": "content",
|
||||
"public": false,
|
||||
"restricted_to_unlogged": false,
|
||||
"slug": "",
|
||||
"text": "<h2>Bienvenue</h2>\r\n\r\n<p>Bienvenue sur votre compte usager.</p>\r\n"
|
||||
},
|
||||
"model": "data.textcell"
|
||||
},
|
||||
{
|
||||
"fields": {
|
||||
"extra_css_class": "",
|
||||
"groups": [],
|
||||
"order": 2,
|
||||
"placeholder": "right",
|
||||
"public": true,
|
||||
"restricted_to_unlogged": false,
|
||||
"slug": "",
|
||||
"wcs_site": ""
|
||||
},
|
||||
"model": "wcs.trackingcodeinputcell"
|
||||
},
|
||||
{
|
||||
"fields": {
|
||||
"extra_css_class": "",
|
||||
"groups": [],
|
||||
"order": 3,
|
||||
"placeholder": "right",
|
||||
"public": true,
|
||||
"restricted_to_unlogged": true,
|
||||
"slug": "",
|
||||
"text": "<h2>Demandes en cours</h2>\r\n\r\n<p>Connectez-vous pour voir vos demandes en cours.</p>\r\n"
|
||||
},
|
||||
"model": "data.textcell"
|
||||
},
|
||||
{
|
||||
"fields": {
|
||||
"current_forms": true,
|
||||
"done_forms": false,
|
||||
"extra_css_class": "",
|
||||
"groups": [],
|
||||
"order": 4,
|
||||
"placeholder": "right",
|
||||
"public": false,
|
||||
"restricted_to_unlogged": false,
|
||||
"slug": "",
|
||||
"wcs_site": ""
|
||||
},
|
||||
"model": "wcs.wcscurrentformscell"
|
||||
},
|
||||
{
|
||||
"fields": {
|
||||
"extra_css_class": "",
|
||||
"groups": [],
|
||||
"order": 5,
|
||||
"placeholder": "footer",
|
||||
"public": true,
|
||||
"restricted_to_unlogged": false,
|
||||
"slug": "",
|
||||
"text": "<p>Ce service est proposé par le <a href=\"http://www.sictiam.fr/\">SICTIAM</a>.</p>\r\n"
|
||||
},
|
||||
"model": "data.textcell"
|
||||
},
|
||||
{
|
||||
"fields": {
|
||||
"category_reference": "eservices:nous-contacter",
|
||||
"extra_css_class": "",
|
||||
"groups": [],
|
||||
"limit": null,
|
||||
"manual_order": {
|
||||
"data": []
|
||||
},
|
||||
"order": 6,
|
||||
"ordering": "popularity",
|
||||
"placeholder": "content",
|
||||
"public": true,
|
||||
"restricted_to_unlogged": false,
|
||||
"slug": ""
|
||||
},
|
||||
"model": "wcs.wcsformsofcategorycell"
|
||||
}
|
||||
],
|
||||
"fields": {
|
||||
"exclude_from_navigation": false,
|
||||
"groups": [],
|
||||
"order": 1,
|
||||
"parent": null,
|
||||
"public": true,
|
||||
"redirect_url": "",
|
||||
"slug": "index",
|
||||
"template_name": "two-columns",
|
||||
"title": "Accueil"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"fields": {
|
||||
"extra_css_class": "",
|
||||
"groups": [],
|
||||
"order": 0,
|
||||
"placeholder": "footer",
|
||||
"public": true,
|
||||
"restricted_to_unlogged": false,
|
||||
"slug": ""
|
||||
},
|
||||
"model": "data.parentcontentcell"
|
||||
}
|
||||
],
|
||||
"fields": {
|
||||
"exclude_from_navigation": false,
|
||||
"groups": [],
|
||||
"order": 2,
|
||||
"parent": null,
|
||||
"public": true,
|
||||
"redirect_url": "[idp_url]accounts/",
|
||||
"slug": "mon-compte",
|
||||
"template_name": "standard",
|
||||
"title": "Mon compte"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"fields": {
|
||||
"extra_css_class": "",
|
||||
"groups": [],
|
||||
"order": 0,
|
||||
"placeholder": "footer",
|
||||
"public": true,
|
||||
"restricted_to_unlogged": false,
|
||||
"slug": ""
|
||||
},
|
||||
"model": "data.parentcontentcell"
|
||||
}
|
||||
],
|
||||
"fields": {
|
||||
"exclude_from_navigation": false,
|
||||
"groups": [],
|
||||
"order": 3,
|
||||
"parent": null,
|
||||
"public": true,
|
||||
"redirect_url": "[eservices_url]",
|
||||
"slug": "nous-contacter",
|
||||
"template_name": "standard",
|
||||
"title": "Nous contacter"
|
||||
}
|
||||
}
|
||||
]
|
|
@ -1,67 +0,0 @@
|
|||
{
|
||||
"steps": [
|
||||
{
|
||||
"create-hobo": {
|
||||
"url": "https://${hobo}/",
|
||||
"primary": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"create-authentic": {
|
||||
"title": "Connexion",
|
||||
"url": "https://${authentic}/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"set-idp": {}
|
||||
},
|
||||
{
|
||||
"create-combo": {
|
||||
"template_name": "portal-user",
|
||||
"title": "Compte citoyen",
|
||||
"url": "https://${combo}/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"create-combo": {
|
||||
"slug": "portal-agent",
|
||||
"template_name": "portal-agent",
|
||||
"title": "Portail agent",
|
||||
"url": "https://${combo_agent}/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"create-wcs": {
|
||||
"template_name": "export.zip",
|
||||
"title": "D\u00e9marches",
|
||||
"url": "https://${wcs}/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"create-fargo": {
|
||||
"title": "Porte documents",
|
||||
"url": "https://${fargo}/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"create-passerelle": {
|
||||
"title": "Passerelle",
|
||||
"url": "https://${passerelle}/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"set-theme": {
|
||||
"theme": "publik"
|
||||
}
|
||||
}
|
||||
],
|
||||
"variables": {
|
||||
"authentic": "connexion-instance_name.sictiam.dev.entrouvert.org",
|
||||
"combo": "instance_name.sictiam.dev.entrouvert.org",
|
||||
"combo_agent": "agents-instance_name.sictiam.dev.entrouvert.org",
|
||||
"fargo": "porte-documents-instance_name.sictiam.dev.entrouvert.org",
|
||||
"hobo": "hobo-instance_name.sictiam.dev.entrouvert.org",
|
||||
"passerelle": "passerelle-instance_name.sictiam.dev.entrouvert.org",
|
||||
"wcs": "demarches-instance_name.sictiam.dev.entrouvert.org"
|
||||
}
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
# Ozwillo plugin to deploy Publik
|
||||
# Copyright (C) 2017 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import logging
|
||||
|
||||
from hobo.contrib.ozwillo.models import OzwilloInstance
|
||||
|
||||
from django.db.transaction import atomic
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument('args', nargs='*')
|
||||
|
||||
@atomic
|
||||
def handle(self, *args, **options):
|
||||
qs = OzwilloInstance.objects.select_for_update()
|
||||
|
||||
# deployment
|
||||
if args:
|
||||
# allow deploying manually failed instances
|
||||
to_deploy = qs.fiter(
|
||||
domain_slug__in=args,
|
||||
state__in=[OzwilloInstance.STATE_TO_DEPLOY, OzwilloInstance.STATE_DEPLOY_ERROR])
|
||||
else:
|
||||
# deploy everything to be deployed
|
||||
to_deploy = qs.filter(
|
||||
state=OzwilloInstance.STATE_TO_DEPLOY)
|
||||
for instance in to_deploy:
|
||||
try:
|
||||
with atomic():
|
||||
instance.deploy()
|
||||
except Exception:
|
||||
logger.exception(u'ozwillo: deploying %s from CRON failed', instance)
|
||||
instance.deploy_error()
|
||||
|
||||
# destruction
|
||||
if args:
|
||||
# allow deploying manually failed instances
|
||||
to_destroy = qs.filter(
|
||||
domain_slug__in=args,
|
||||
state__in=[OzwilloInstance.STATE_TO_DESTROY, OzwilloInstance.STATE_DESTROY_ERROR])
|
||||
else:
|
||||
# destroy everything to be destroyed
|
||||
to_destroy = qs.filter(state=OzwilloInstance.STATE_TO_DESTROY)
|
||||
for instance in to_destroy:
|
||||
try:
|
||||
with atomic():
|
||||
instance.destroy()
|
||||
except Exception:
|
||||
logger.exception(u'ozwillo: destroying %s from CRON failed', instance)
|
||||
instance.destroy_error()
|
||||
|
||||
logger = logging.getLogger(__name__)
|
|
@ -1,21 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='OzwilloInstance',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('domain_slug', models.CharField(unique=True, max_length=250)),
|
||||
('external_ozwillo_id', models.CharField(max_length=450)),
|
||||
],
|
||||
),
|
||||
]
|
|
@ -1,52 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.13 on 2018-05-17 10:47
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('ozwillo', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='ozwilloinstance',
|
||||
name='created',
|
||||
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ozwilloinstance',
|
||||
name='deploy_data',
|
||||
field=models.TextField(null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ozwilloinstance',
|
||||
name='modified',
|
||||
field=models.DateTimeField(auto_now=True, default=django.utils.timezone.now),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ozwilloinstance',
|
||||
name='state',
|
||||
field=models.CharField(choices=[(b'new', b'new'), (b'to_deploy', b'to_deploy'), (b'deployed', b'deployed'), (b'deploy_error', b'deploy_error'), (b'to_destroy', b'to_destroy'), (b'destroy_error', b'destroy_error'), (b'destroyed', b'destroyed')], default=b'deployed', max_length=16),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ozwilloinstance',
|
||||
name='external_ozwillo_id',
|
||||
field=models.CharField(max_length=450, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ozwilloinstance',
|
||||
name='modified',
|
||||
field=models.DateTimeField(auto_now=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ozwilloinstance',
|
||||
name='state',
|
||||
field=models.CharField(choices=[(b'new', b'new'), (b'to_deploy', b'to_deploy'), (b'deployed', b'deployed'), (b'deploy_error', b'deploy_error'), (b'to_destroy', b'to_destroy'), (b'destroy_error', b'destroy_error'), (b'destroyed', b'destroyed')], default=b'new', max_length=16),
|
||||
),
|
||||
]
|
|
@ -1,20 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.13 on 2018-05-24 08:28
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('ozwillo', '0002_auto_20180517_1047'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='ozwilloinstance',
|
||||
name='domain_slug',
|
||||
field=models.CharField(max_length=250),
|
||||
),
|
||||
]
|
|
@ -1,285 +0,0 @@
|
|||
# Ozwillo plugin to deploy Publik
|
||||
# Copyright (C) 2017 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
import tempfile
|
||||
import json
|
||||
|
||||
import requests
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.db.transaction import atomic
|
||||
from django.utils.text import slugify
|
||||
from django.core.management import call_command
|
||||
from django.db import connection
|
||||
|
||||
from tenant_schemas.utils import tenant_context
|
||||
|
||||
|
||||
class OzwilloInstance(models.Model):
|
||||
STATE_NEW = 'new'
|
||||
STATE_TO_DEPLOY = 'to_deploy'
|
||||
STATE_DEPLOY_ERROR = 'deploy_error'
|
||||
STATE_DEPLOYED = 'deployed'
|
||||
STATE_TO_DESTROY = 'to_destroy'
|
||||
STATE_DESTROY_ERROR = 'destroy_error'
|
||||
STATE_DESTROYED = 'destroyed'
|
||||
|
||||
STATES = [
|
||||
(STATE_NEW, 'new'),
|
||||
(STATE_TO_DEPLOY, 'to_deploy'),
|
||||
(STATE_DEPLOYED, 'deployed'),
|
||||
(STATE_DEPLOY_ERROR, 'deploy_error'),
|
||||
(STATE_TO_DESTROY, 'to_destroy'),
|
||||
(STATE_DESTROY_ERROR, 'destroy_error'),
|
||||
(STATE_DESTROYED, 'destroyed'),
|
||||
]
|
||||
|
||||
state = models.CharField(max_length=16, default=STATE_NEW, choices=STATES)
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
domain_slug = models.CharField(max_length=250)
|
||||
external_ozwillo_id = models.CharField(max_length=450, unique=True)
|
||||
deploy_data = models.TextField(null=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.domain_slug
|
||||
|
||||
def __repr__(self):
|
||||
return '<OzwilloInstance external_ozwillo_id: %r domain_slug: %r state: %r>' % (
|
||||
self.external_ozwillo_id, self.domain_slug, self.state)
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
return json.loads(self.deploy_data) if self.deploy_data else None
|
||||
|
||||
def to_deploy(self):
|
||||
assert self.state == self.STATE_NEW
|
||||
try:
|
||||
with atomic():
|
||||
# lock the new instance to prevent collision with the CRON job
|
||||
OzwilloInstance.objects.select_for_update().filter(id=self.id)
|
||||
# instance starts with the NEW state, to prevent the CRON from
|
||||
# deploying instance juste created
|
||||
# only instance in the state STATE_TO_DEPLOY are deployed.
|
||||
self.state = self.STATE_TO_DEPLOY
|
||||
self.save()
|
||||
self.deploy()
|
||||
except Exception:
|
||||
# something failed, still make the instance to be deployed
|
||||
# an reraise exception
|
||||
self.state = self.STATE_TO_DEPLOY
|
||||
self.save()
|
||||
raise
|
||||
|
||||
def to_destroy(self):
|
||||
assert self.state == self.STATE_DEPLOYED
|
||||
self.state = self.STATE_TO_DESTROY
|
||||
self.save()
|
||||
|
||||
def deploy_error(self):
|
||||
assert self.state in [self.STATE_DEPLOY_ERROR, self.STATE_TO_DEPLOY]
|
||||
if self.state == self.STATE_TO_DEPLOY:
|
||||
self.state = self.STATE_DEPLOY_ERROR
|
||||
self.save()
|
||||
|
||||
def deploy(self):
|
||||
logger.info(u'ozwillo: deploy start for %s', self)
|
||||
data = self.data
|
||||
if not data:
|
||||
logger.warning(u'ozwillo: unable to deploy, no data')
|
||||
return
|
||||
|
||||
# Request parsing
|
||||
client_id = data['client_id']
|
||||
client_secret = data['client_secret']
|
||||
instance_id = data['instance_id']
|
||||
instance_name = data['organization_name']
|
||||
instance_name = slugify(instance_name)
|
||||
registration_uri = data['instance_registration_uri']
|
||||
user = data['user']
|
||||
|
||||
# Cook new platform
|
||||
template_recipe = json.load(open('/etc/hobo/ozwillo/template_recipe.json', 'rb'))
|
||||
var = template_recipe['variables']
|
||||
for key, value in var.items():
|
||||
var[key] = value.replace('instance_name', instance_name)
|
||||
|
||||
template_recipe['variables'] = var
|
||||
domain = var['combo']
|
||||
domain_agent = var['combo_agent']
|
||||
domain_passerelle = var['passerelle']
|
||||
logger.info(u'ozwillo: cooking %s', template_recipe)
|
||||
|
||||
with tempfile.NamedTemporaryFile() as recipe_file:
|
||||
json.dump(template_recipe, recipe_file)
|
||||
recipe_file.flush()
|
||||
|
||||
# cook play with the tenant context, we must protect from that
|
||||
with tenant_context(connection.tenant):
|
||||
call_command('cook', recipe_file.name, timeout=1000, verbosity=0)
|
||||
|
||||
# Load user portal template
|
||||
logger.info(u'ozwillo: loading combo template')
|
||||
run_command([
|
||||
'sudo', '-u', 'combo',
|
||||
'combo-manage', 'tenant_command', 'import_site',
|
||||
'/etc/hobo/ozwillo/import-site-template.json',
|
||||
'-d', domain
|
||||
])
|
||||
|
||||
# Load agent portal template
|
||||
logger.info(u'ozwillo: loading combo agent template')
|
||||
run_command([
|
||||
'sudo', '-u', 'combo',
|
||||
'combo-manage', 'tenant_command', 'import_site',
|
||||
'/etc/hobo/ozwillo/import-site-agents.json',
|
||||
'-d', domain_agent
|
||||
])
|
||||
|
||||
# Configure OIDC Ozwillo authentication
|
||||
logger.info(u'ozwillo: configuring OIDC ozwillo authentication')
|
||||
domain_name = 'connexion-%s.%s' % (instance_name, settings.OZWILLO_ENV_DOMAIN)
|
||||
if run_command([
|
||||
'sudo', '-u', 'authentic-multitenant',
|
||||
'authentic2-multitenant-manage', 'tenant_command', 'oidc-register-issuer',
|
||||
'-d', domain_name,
|
||||
'--scope', 'profile',
|
||||
'--scope', 'email',
|
||||
'--issuer', settings.OZWILLO_PLATEFORM,
|
||||
'--client-id', client_id,
|
||||
'--client-secret', client_secret,
|
||||
'--claim-mapping', 'given_name first_name always_verified',
|
||||
'--claim-mapping', 'family_name last_name always_verified',
|
||||
'--ou-slug', 'default',
|
||||
'--claim-mapping', 'email email required',
|
||||
'Ozwillo'
|
||||
]):
|
||||
# creation of the admin user depends upon the creation of provider
|
||||
logger.info(u'ozwillo: creating admin user')
|
||||
create_user_script = os.path.dirname(__file__) + '/scripts/create_user_ozwillo.py'
|
||||
run_command([
|
||||
'sudo', '-u', 'authentic-multitenant',
|
||||
'authentic2-multitenant-manage', 'tenant_command', 'runscript', '-d', domain_name,
|
||||
create_user_script, user['email_address'], user['id'], user['name']
|
||||
])
|
||||
|
||||
# Load passerelle template
|
||||
logger.info(u'ozwillo: loading passerelle template')
|
||||
run_command([
|
||||
'sudo', '-u', 'passerelle',
|
||||
'passerelle-manage', 'tenant_command', 'import_site',
|
||||
'/etc/hobo/ozwillo/import-site-passerelle.json',
|
||||
'--import-user', '-d', domain_passerelle
|
||||
])
|
||||
|
||||
# Sending done event to Ozwillo
|
||||
services = {
|
||||
'services': [{
|
||||
'local_id': 'publik',
|
||||
'name': 'Publik - %s' % (instance_name),
|
||||
'service_uri': 'https://connexion-%s.%s/accounts/oidc/login?iss=%s'
|
||||
% (instance_name, settings.OZWILLO_ENV_DOMAIN,
|
||||
settings.OZWILLO_PLATEFORM),
|
||||
'description': 'Gestion de la relation usagers',
|
||||
'tos_uri': 'https://publik.entrouvert.com/',
|
||||
'policy_uri': 'https://publik.entrouvert.com/',
|
||||
'icon': 'https://publik.entrouvert.com/static/img/logo-publik-64x64.png',
|
||||
'payment_option': 'FREE',
|
||||
'target_audience': ['PUBLIC_BODIES',
|
||||
'CITIZENS',
|
||||
'COMPANIES'],
|
||||
'contacts': ['https://publik.entrouvert.com/'],
|
||||
'redirect_uris': ['https://connexion-%s.%s/accounts/oidc/callback/'
|
||||
% (instance_name, settings.OZWILLO_ENV_DOMAIN)],
|
||||
}],
|
||||
'instance_id': instance_id,
|
||||
'destruction_uri': settings.OZWILLO_DESTRUCTION_URI,
|
||||
'destruction_secret': settings.OZWILLO_DESTRUCTION_SECRET,
|
||||
'needed_scopes': []
|
||||
}
|
||||
logger.info(u'ozwillo: sending registration request, %r', services)
|
||||
headers = {'Content-type': 'application/json', 'Accept': 'application/json'}
|
||||
response = requests.post(
|
||||
registration_uri,
|
||||
data=json.dumps(services),
|
||||
auth=(client_id, client_secret),
|
||||
headers=headers)
|
||||
logger.info(u'ozwillo: registration response, status=%s content=%r',
|
||||
response.status_code, response.content)
|
||||
self.state = self.STATE_DEPLOYED
|
||||
self.save()
|
||||
logger.info(u'ozwillo: deploy finished')
|
||||
|
||||
def destroy_error(self):
|
||||
assert self.state in [self.STATE_DESTROY_ERROR, self.STATE_TO_DESTROY]
|
||||
if self.state == self.STATE_TO_DESTROY:
|
||||
self.state = self.STATE_DESTROY_ERROR
|
||||
self.save()
|
||||
|
||||
|
||||
def destroy(self):
|
||||
logger.info(u'ozwillo: destroy start for %s', self)
|
||||
instance_slug = self.domain_slug
|
||||
services = settings.OZWILLO_SERVICES.copy()
|
||||
# w.c.s. is handled differently
|
||||
wcs = services.pop('wcs')
|
||||
|
||||
for s, infos in services.items():
|
||||
# to get the two combo instances which have same service
|
||||
service_user = s.split('_')[0]
|
||||
|
||||
tenant = '%s%s.%s' % (infos[0], instance_slug, settings.OZWILLO_ENV_DOMAIN)
|
||||
|
||||
run_command([
|
||||
'sudo', '-u', service_user, infos[1],
|
||||
'delete_tenant', '--force-drop', tenant
|
||||
])
|
||||
|
||||
tenant = '%s%s.%s' % (wcs[0], instance_slug, settings.OZWILLO_ENV_DOMAIN)
|
||||
run_command([
|
||||
'sudo', '-u', 'wcs',
|
||||
wcs[1], '-f', '/etc/wcs/wcs-au-quotidien.cfg',
|
||||
'delete_tenant', '--force-drop', tenant
|
||||
])
|
||||
|
||||
logger.info(u'ozwillo: destroy finished')
|
||||
self.state = self.STATE_DESTROYED
|
||||
self.save()
|
||||
|
||||
|
||||
def run_command(args):
|
||||
try:
|
||||
process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except OSError as e:
|
||||
logger.error('ozwillo: launching subprocess %s raised error %s', args, e)
|
||||
return False
|
||||
logger.info('ozwillo: launching subprocess with pid %s : %s', process.pid, args)
|
||||
stdoutdata, stderrdata = process.communicate()
|
||||
if process.returncode != 0:
|
||||
logger.error('ozwillo: subprocess %s failed returncode=%s stdout=%r stderr=%r',
|
||||
process.pid, process.returncode, stdoutdata, stderrdata)
|
||||
return False
|
||||
logger.info('ozwillo: subprocess terminated')
|
||||
return True
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
import sys
|
||||
import logging
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
from authentic2_auth_oidc.models import OIDCAccount
|
||||
from authentic2_auth_oidc.models import OIDCProvider
|
||||
from authentic2.a2_rbac.models import Role, OrganizationalUnit
|
||||
|
||||
|
||||
def create_user(user_id, email_addressi, user_name, provider):
|
||||
while True:
|
||||
new_user = User.objects.create()
|
||||
oidc_account, created = OIDCAccount.objects.select_related().get_or_create(provider=provider, sub=user_id, defaults={'user': new_user})
|
||||
if created:
|
||||
if OIDCAccount.objects.filter(provider=provider, sub=user_id).count() > 1:
|
||||
oidc_account.delete()
|
||||
new_user.delete()
|
||||
continue
|
||||
break
|
||||
else:
|
||||
new_user.delete()
|
||||
new_user = oidc_account.user
|
||||
break
|
||||
|
||||
new_user.email = email_address
|
||||
new_user.ou = provider.ou
|
||||
new_user.is_superuser = True
|
||||
new_user.is_staff = True
|
||||
new_user.first_name = 'admin'
|
||||
new_user.last_name = user_name
|
||||
new_user.save()
|
||||
|
||||
return new_user
|
||||
|
||||
|
||||
# create agent_sve role
|
||||
ou = OrganizationalUnit.objects.get(default=True)
|
||||
role, created = Role.objects.get_or_create(uuid='3f3367d817bb4a9aa98e7ed6c83b5b09',
|
||||
defaults={'name': u'Agents SVE',
|
||||
'ou': ou})
|
||||
|
||||
# set the provider for the user creation
|
||||
provider = OIDCProvider.objects.get(name='Ozwillo')
|
||||
|
||||
# get user info from args sent to the script
|
||||
args = sys.argv
|
||||
email_address = args[1]
|
||||
user_id = args[2]
|
||||
user_name = args[3]
|
||||
|
||||
# create admin user in Publik from Ozwillo
|
||||
User = get_user_model()
|
||||
user = create_user(user_id, email_address, user_name, provider)
|
||||
logging.info('owzillo provisionning: user created with uuid: %s', user.uuid)
|
|
@ -1,148 +0,0 @@
|
|||
# Ozwillo plugin to deploy Publik
|
||||
# Copyright (C) 2017-2019 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import json
|
||||
import datetime
|
||||
import logging
|
||||
from urllib import urlencode
|
||||
import pprint
|
||||
import os
|
||||
|
||||
import requests
|
||||
from robobrowser.browser import RoboBrowser
|
||||
|
||||
from django.utils.six.moves.urllib import parse as urlparse
|
||||
|
||||
from hobo.multitenant.middleware import TenantMiddleware
|
||||
from tenant_schemas.utils import tenant_context
|
||||
|
||||
|
||||
def run_on_all_tenants(f):
|
||||
for tenant in TenantMiddleware.get_tenants():
|
||||
with tenant_context(tenant):
|
||||
try:
|
||||
f(tenant)
|
||||
except:
|
||||
logging.exception('unable to provision')
|
||||
|
||||
def provision_users(tenant):
|
||||
from django.conf import settings
|
||||
|
||||
if not getattr(settings, 'OZWILLO_ADMIN', None):
|
||||
logging.warning('No OZWILLO_ADMIN setting found')
|
||||
return
|
||||
|
||||
logger = logging.getLogger('ozwillo_synchro')
|
||||
from authentic2_auth_oidc.models import OIDCProvider
|
||||
for provider in OIDCProvider.objects.all():
|
||||
if 'ozwillo' in provider.issuer or 'accounts.sictiam.fr' in provider.issuer:
|
||||
auth_url = provider.authorization_endpoint
|
||||
token_url = provider.token_endpoint
|
||||
client_id = provider.client_id
|
||||
client_secret = provider.client_secret
|
||||
redirect_uri = urlparse.urljoin(tenant.get_base_url(), '/accounts/oidc/callback/')
|
||||
instance_users_url = urlparse.urljoin(token_url.replace('accounts', 'kernel'), '/apps/acl/instance/')
|
||||
break
|
||||
else:
|
||||
logger.warning('No ozwillo OIDC provider found for %s', tenant.get_base_url())
|
||||
return
|
||||
|
||||
session = requests.Session()
|
||||
session.verify = False
|
||||
|
||||
br = RoboBrowser(user_agent='Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0',
|
||||
session=session)
|
||||
|
||||
query = urlencode({
|
||||
'client_id': client_id,
|
||||
'response_type': 'code',
|
||||
'scope': 'openid offline_access',
|
||||
'prompt': 'consent',
|
||||
'redirect_uri': redirect_uri
|
||||
})
|
||||
response = br.open(auth_url + '?%s' % query)
|
||||
response = br._states[-1].response
|
||||
if br._states[-1].response.status_code != 200:
|
||||
logger.warning(u'OIDC authorization request failed: %s %r', response.status_code, response._content[:1000])
|
||||
return
|
||||
referer = br.response.request.url
|
||||
br.session.headers['Referer'] = referer
|
||||
form = br.get_form(action='/a/login')
|
||||
form['u'] = settings.OZWILLO_ADMIN[0]
|
||||
form['pwd'] = settings.OZWILLO_ADMIN[1]
|
||||
br.submit_form(form=form)
|
||||
referer = br.response.request.url
|
||||
br.session.headers['Referer'] = referer
|
||||
form = br.get_form()
|
||||
br.submit_form(form=form, allow_redirects=False)
|
||||
|
||||
if 'Location' not in br.response.headers:
|
||||
logger.warning(u'Not authorization form %r %r', response.status_code, response._content[:1000])
|
||||
return
|
||||
|
||||
cb_url = urlparse.urlparse(br.response.headers['location'])
|
||||
|
||||
code = urlparse.parse_qs(cb_url.query)['code'][0]
|
||||
|
||||
logger.info('Getting token from %s', token_url)
|
||||
response = requests.post(token_url, auth=(client_id, client_secret),
|
||||
data={
|
||||
'code': code,
|
||||
'redirect_uri': redirect_uri,
|
||||
'grant_type': 'authorization_code'})
|
||||
logger.info('Got %s', response.json())
|
||||
access_token = response.json()['access_token']
|
||||
logger.info('Getting instance users from %s', instance_users_url + client_id)
|
||||
response = requests.get(instance_users_url + client_id,
|
||||
headers={'Authorization': 'Bearer %s' % access_token})
|
||||
logger.info('Got %s', response.json())
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from authentic2_auth_oidc.models import OIDCAccount
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
for user in response.json():
|
||||
logging.info('Provisionning email %s with sub %s', user['user_email_address'], user['user_id'])
|
||||
while True:
|
||||
new_user = User.objects.create()
|
||||
oidc_account, created = OIDCAccount.objects.select_related().get_or_create(provider=provider, sub=user['user_id'], defaults={'user': new_user})
|
||||
if created:
|
||||
if OIDCAccount.objects.filter(provider=provider, sub=user['user_id']).count() > 1:
|
||||
oidc_account.delete()
|
||||
new_user.delete()
|
||||
continue
|
||||
logging.info('provisionned with uuid %s', new_user.uuid)
|
||||
break
|
||||
else:
|
||||
new_user.delete()
|
||||
new_user = oidc_account.user
|
||||
break
|
||||
save = False
|
||||
if new_user.username != user['user_name']:
|
||||
new_user.username = user['user_name']
|
||||
save = True
|
||||
if new_user.email != user['user_email_address']:
|
||||
new_user.email = user['user_email_address']
|
||||
save = True
|
||||
if new_user.ou != provider.ou:
|
||||
new_user.ou = provider.ou
|
||||
save = True
|
||||
if save:
|
||||
new_user.save()
|
||||
|
||||
|
||||
run_on_all_tenants(provision_users)
|
|
@ -1,25 +0,0 @@
|
|||
# Ozwillo plugin to deploy
|
||||
# Copyright (C) 2017 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.conf.urls import url, include
|
||||
|
||||
from . import views
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'create-publik-instance', views.create_publik_instance, name='ozwillo-create-publik-instance'),
|
||||
url(r'delete-publik-instance', views.delete_publik_instance, name='ozwillo-delete-publik-instance'),
|
||||
]
|
|
@ -1,144 +0,0 @@
|
|||
# Ozwillo plugin to deploy Publik
|
||||
# Copyright (C) 2017 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import logging
|
||||
import json
|
||||
import hmac
|
||||
import threading
|
||||
from hashlib import sha1
|
||||
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.conf import settings
|
||||
from django.http import (HttpResponseForbidden, HttpResponseBadRequest,
|
||||
HttpResponseNotFound, HttpResponse)
|
||||
from django.utils.text import slugify
|
||||
from django.db import DatabaseError
|
||||
from django.db.transaction import atomic
|
||||
|
||||
from .models import OzwilloInstance
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def valid_signature_required(setting):
|
||||
'''Validate Ozwillo signatures'''
|
||||
signature_header_name = 'HTTP_X_HUB_SIGNATURE'
|
||||
|
||||
def decorator(func):
|
||||
def wrapper(request, *args, **kwargs):
|
||||
api_secret = getattr(settings, setting)
|
||||
if signature_header_name in request.META:
|
||||
if request.META[signature_header_name].startswith('sha1='):
|
||||
algo, received_hmac = request.META[signature_header_name].rsplit('=')
|
||||
computed_hmac = hmac.new(api_secret, request.content, sha1).hexdigest()
|
||||
# the received hmac is uppercase according to
|
||||
# http://doc.ozwillo.com/#ref-3-2-1
|
||||
if received_hmac.lower() != computed_hmac:
|
||||
logger.error(u'ozwillo: invalid HMAC')
|
||||
return HttpResponseForbidden('invalid HMAC')
|
||||
else:
|
||||
logger.error(u'ozwillo: invalid HMAC algo')
|
||||
return HttpResponseForbidden('invalid HMAC algo')
|
||||
else:
|
||||
logger.error(u'ozwillo: no HMAC in the header')
|
||||
return HttpResponseForbidden('no HMAC in the header')
|
||||
return func(request, *args, **kwargs)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
|
||||
def is_ozwillo_enabled(func):
|
||||
def wrapper(request):
|
||||
if not getattr(settings, 'OZWILLO_ENABLED', False):
|
||||
return HttpResponseNotFound('owillo providing is not active here.')
|
||||
return func(request)
|
||||
return wrapper
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
@is_ozwillo_enabled
|
||||
@valid_signature_required(setting='OZWILLO_SECRET')
|
||||
def create_publik_instance(request):
|
||||
try:
|
||||
data = json.loads(request.text)
|
||||
except ValueError:
|
||||
logger.warning(u'ozwillo: received non JSON request')
|
||||
return HttpResponseBadRequest('invalid JSON content')
|
||||
|
||||
logger.info(u'ozwillo: create publik instance request, %r', data)
|
||||
|
||||
if 'organization_name' not in data.keys():
|
||||
logger.warning(u'ozwillo: missing organization_name')
|
||||
return HttpResponseBadRequest('missing parameter "organization_name"')
|
||||
|
||||
org_name = slugify(data['organization_name'])
|
||||
# forbid creation of an instance if a not destroyed previous one exists
|
||||
if OzwilloInstance.objects.exclude(state=OzwilloInstance.STATE_DESTROYED).filter(domain_slug=org_name):
|
||||
logger.warning(u'ozwillo: instance %s already exists', org_name)
|
||||
return HttpResponseBadRequest('instance %s already exists' % org_name)
|
||||
|
||||
try:
|
||||
instance = OzwilloInstance.objects.create(
|
||||
external_ozwillo_id=data['instance_id'],
|
||||
state=OzwilloInstance.STATE_NEW,
|
||||
domain_slug=org_name,
|
||||
# deploy_data is a TextField containing JSON
|
||||
deploy_data=json.dumps(data, indent=4))
|
||||
except DatabaseError as e:
|
||||
logger.warning(u'ozwillo: could not create instance_id %r org_name %r: %r',
|
||||
data['instance_id'], org_name, e)
|
||||
return HttpResponseBadRequest(u'cannot create the instance: %r', e)
|
||||
|
||||
# immediate deploy in a thread
|
||||
def thread_function(data):
|
||||
try:
|
||||
instance.to_deploy()
|
||||
except Exception:
|
||||
logger.exception(u'ozwillo: error occured duging initial deploy request %s', org_name)
|
||||
thread = threading.Thread(target=thread_function, args=(data,))
|
||||
thread.start()
|
||||
|
||||
return HttpResponse()
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
@is_ozwillo_enabled
|
||||
@valid_signature_required(setting='OZWILLO_DESTRUCTION_SECRET')
|
||||
@atomic
|
||||
def delete_publik_instance(request):
|
||||
try:
|
||||
data = json.loads(request.text)
|
||||
except ValueError:
|
||||
logger.warning(u'ozwillo: received non JSON request')
|
||||
return HttpResponseBadRequest('invalid JSON content')
|
||||
|
||||
logger.info(u'ozwillo: delete publik instance request (%r)', data)
|
||||
|
||||
try:
|
||||
instance_id = data['instance_id']
|
||||
except KeyError:
|
||||
logger.warning(u'ozwillo: no instance id in destroy request (%r)', data)
|
||||
return HttpResponseBadRequest('no instance id')
|
||||
try:
|
||||
instance = OzwilloInstance.objects.select_for_update().get(
|
||||
external_ozwillo_id=instance_id,
|
||||
# only deployed instances can be destroyed
|
||||
state=OzwilloInstance.STATE_DEPLOYED)
|
||||
except OzwilloInstance.DoesNotExist:
|
||||
return HttpResponseBadRequest('no instance with id %s' % data['instance_id'])
|
||||
instance.to_destroy()
|
||||
logger.info(u'ozwillo: destroy registered for %s (%s)', instance.domain_slug, instance.external_ozwillo_id)
|
||||
return HttpResponse(status=200)
|
|
@ -57,8 +57,3 @@ urlpatterns += [
|
|||
url(r'^login/local/$', login_local), # to be used as backup, in case of idp down
|
||||
url(r'^accounts/mellon/', include('mellon.urls')),
|
||||
]
|
||||
|
||||
if 'hobo.contrib.ozwillo' in settings.INSTALLED_APPS:
|
||||
urlpatterns += [
|
||||
url(r'ozwillo/', include('hobo.contrib.ozwillo.urls')),
|
||||
]
|
||||
|
|
|
@ -2,9 +2,8 @@ import os
|
|||
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
BROKER_URL = 'memory://'
|
||||
OZWILLO_SECRET = 'secret'
|
||||
|
||||
INSTALLED_APPS += ('hobo.contrib.ozwillo', 'hobo.agent.common')
|
||||
INSTALLED_APPS += ('hobo.agent.common', )
|
||||
|
||||
ALLOWED_HOSTS.append('localhost')
|
||||
|
||||
|
|
Loading…
Reference in New Issue