From 3b9e4e3c559cb584402052a0b34e1e399104e25a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Jaillet Date: Thu, 9 Feb 2017 15:54:53 +0100 Subject: [PATCH] ozwillo: create ozwillo app in contrib (#14935) --- hobo/contrib/__init__.py | 0 hobo/contrib/ozwillo/__init__.py | 0 hobo/contrib/ozwillo/import-site-agents.json | 30 +++++ hobo/contrib/ozwillo/import-site-template.json | 169 +++++++++++++++++++++++++ hobo/contrib/ozwillo/import-site.json | 1 + hobo/contrib/ozwillo/template_recipe.json | 72 +++++++++++ hobo/contrib/ozwillo/urls.py | 26 ++++ hobo/contrib/ozwillo/views.py | 124 ++++++++++++++++++ hobo/urls.py | 4 + 9 files changed, 426 insertions(+) create mode 100644 hobo/contrib/__init__.py create mode 100644 hobo/contrib/ozwillo/__init__.py create mode 100644 hobo/contrib/ozwillo/import-site-agents.json create mode 100644 hobo/contrib/ozwillo/import-site-template.json create mode 100644 hobo/contrib/ozwillo/import-site.json create mode 100644 hobo/contrib/ozwillo/template_recipe.json create mode 100644 hobo/contrib/ozwillo/urls.py create mode 100644 hobo/contrib/ozwillo/views.py diff --git a/hobo/contrib/__init__.py b/hobo/contrib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hobo/contrib/ozwillo/__init__.py b/hobo/contrib/ozwillo/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hobo/contrib/ozwillo/import-site-agents.json b/hobo/contrib/ozwillo/import-site-agents.json new file mode 100644 index 0000000..866c2e6 --- /dev/null +++ b/hobo/contrib/ozwillo/import-site-agents.json @@ -0,0 +1,30 @@ +[ + { + "cells": [ + { + "fields": { + "extra_css_class": "", + "groups": [], + "order": 1, + "placeholder": "content", + "public": true, + "restricted_to_unlogged": false, + "slug": "services", + "text": "

Bienvenue

\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" + } + } +] diff --git a/hobo/contrib/ozwillo/import-site-template.json b/hobo/contrib/ozwillo/import-site-template.json new file mode 100644 index 0000000..8cbb2ed --- /dev/null +++ b/hobo/contrib/ozwillo/import-site-template.json @@ -0,0 +1,169 @@ +[ + { + "cells": [ + { + "fields": { + "extra_css_class": "", + "groups": [], + "order": 0, + "placeholder": "content", + "public": true, + "restricted_to_unlogged": true, + "slug": "", + "text": "

Bienvenue

\r\n\r\n

Bienvenue sur votre compte usager.

\r\n\r\n

Pour suivre vos démarches en cours, créez votre compte personnel ou identifiez-vous depuis la page de connexion.

\r\n" + }, + "model": "data.textcell" + }, + { + "fields": { + "extra_css_class": "", + "groups": [], + "order": 1, + "placeholder": "content", + "public": false, + "restricted_to_unlogged": false, + "slug": "", + "text": "

Bienvenue

\r\n\r\n

Bienvenue sur votre compte usager.

\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": "

Demandes en cours

\r\n\r\n

Connectez-vous pour voir vos demandes en cours.

\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": "

Ce service est proposé par le SICTIAM.

\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": "https://connexion-instance_name.sictiam.dev.entrouvert.org/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": "https://demarches-instance_name.sictiam.dev.entrouvert.org/saisine-par-voie-electronique/tryauth", + "slug": "nous-contacter", + "template_name": "standard", + "title": "Nous contacter" + } + } +] diff --git a/hobo/contrib/ozwillo/import-site.json b/hobo/contrib/ozwillo/import-site.json new file mode 100644 index 0000000..2154402 --- /dev/null +++ b/hobo/contrib/ozwillo/import-site.json @@ -0,0 +1 @@ +[{"fields": {"groups": [], "slug": "index", "exclude_from_navigation": false, "parent": null, "title": "Accueil", "template_name": "two-columns", "order": 1, "redirect_url": "", "public": true}, "cells": [{"fields": {"extra_css_class": "", "restricted_to_unlogged": true, "slug": "", "text": "

Bienvenue

\r\n\r\n

Bienvenue sur votre compte usager.

\r\n\r\n

Pour suivre vos démarches en cours, créez votre compte personnel ou identifiez-vous depuis la page de connexion.

\r\n", "public": true, "groups": [], "placeholder": "content", "order": 0}, "model": "data.textcell"}, {"fields": {"extra_css_class": "", "restricted_to_unlogged": false, "slug": "", "text": "

Bienvenue

\r\n\r\n

Bienvenue sur votre compte usager.

\r\n", "public": false, "groups": [], "placeholder": "content", "order": 1}, "model": "data.textcell"}, {"fields": {"extra_css_class": "", "restricted_to_unlogged": false, "slug": "", "wcs_site": "", "public": true, "groups": [], "placeholder": "right", "order": 2}, "model": "wcs.trackingcodeinputcell"}, {"fields": {"extra_css_class": "", "restricted_to_unlogged": true, "slug": "", "text": "

Demandes en cours

\r\n\r\n

Connectez-vous pour voir vos demandes en cours.

\r\n", "public": true, "groups": [], "placeholder": "right", "order": 3}, "model": "data.textcell"}, {"fields": {"extra_css_class": "", "restricted_to_unlogged": false, "slug": "", "done_forms": false, "current_forms": true, "wcs_site": "", "public": false, "groups": [], "placeholder": "right", "order": 4}, "model": "wcs.wcscurrentformscell"}, {"fields": {"extra_css_class": "", "restricted_to_unlogged": false, "slug": "", "text": "

Ce service est proposé par le SICTIAM.

\r\n", "public": true, "groups": [], "placeholder": "footer", "order": 5}, "model": "data.textcell"}, {"fields": {"extra_css_class": "", "restricted_to_unlogged": false, "slug": "", "ordering": "popularity", "placeholder": "content", "public": true, "limit": null, "groups": [], "manual_order": {"data": []}, "category_reference": "eservices:nous-contacter", "order": 6}, "model": "wcs.wcsformsofcategorycell"}]}, {"fields": {"groups": [], "slug": "mon-compte", "exclude_from_navigation": false, "parent": null, "title": "Mon compte", "template_name": "standard", "order": 2, "redirect_url": "https://connexion-entrouvert.sictiam.dev.entrouvert.org/accounts/", "public": true}, "cells": [{"fields": {"extra_css_class": "", "restricted_to_unlogged": false, "slug": "", "public": true, "groups": [], "placeholder": "footer", "order": 0}, "model": "data.parentcontentcell"}]}, {"fields": {"groups": [], "slug": "nous-contacter", "exclude_from_navigation": false, "parent": null, "title": "Nous contacter", "template_name": "standard", "order": 3, "redirect_url": "https://demarches-entrouvert.sictiam.dev.entrouvert.org/saisine-par-voie-electronique/tryauth", "public": true}, "cells": [{"fields": {"extra_css_class": "", "restricted_to_unlogged": false, "slug": "", "public": true, "groups": [], "placeholder": "footer", "order": 0}, "model": "data.parentcontentcell"}]}] \ No newline at end of file diff --git a/hobo/contrib/ozwillo/template_recipe.json b/hobo/contrib/ozwillo/template_recipe.json new file mode 100644 index 0000000..aac57ae --- /dev/null +++ b/hobo/contrib/ozwillo/template_recipe.json @@ -0,0 +1,72 @@ +{ + "steps" : [ + { + "create-hobo" : { + "url" : "https://${hobo}/" + } + }, + { + "create-authentic" : { + "title" : "Connexion", + "url" : "https://${authentic}/" + } + }, + { + "set-idp" : {} + }, + { + "create-superuser" : { + "username" : "admin", + "email" : "admin@example.net" + } + }, + { + "create-combo" : { + "template_name" : "portal-user", + "title" : "Compte citoyen", + "url" : "https://${combo}/" + } + }, + { + "create-combo" : { + "template_name" : "portal-agent", + "title" : "Portail agent", + "url" : "https://${combo_agent}/", + "slug" : "portal-agent" + } + }, + { + "create-wcs" : { + "url" : "https://${wcs}/", + "title" : "Démarches", + "template_name": "export.wcs" + } + }, + { + "create-fargo" : { + "url" : "https://${fargo}/", + "title" : "Porte documents" + } + }, + { + "create-passerelle" : { + "url" : "https://${passerelle}/", + "title" : "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", + "hobo" : "hobo-instance_name.sictiam.dev.entrouvert.org", + "wcs" : "demarches-instance_name.sictiam.dev.entrouvert.org", + "passerelle": "passerelle-instance_name.sictiam.dev.entrouvert.org", + "fargo": "porte-documents-instance_name.sictiam.dev.entrouvert.org" + } +} diff --git a/hobo/contrib/ozwillo/urls.py b/hobo/contrib/ozwillo/urls.py new file mode 100644 index 0000000..5015764 --- /dev/null +++ b/hobo/contrib/ozwillo/urls.py @@ -0,0 +1,26 @@ +# 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 . + +from django.conf.urls import patterns, url, include + +from . import views + + +urlpatterns = patterns('', + 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'), +) + diff --git a/hobo/contrib/ozwillo/views.py b/hobo/contrib/ozwillo/views.py new file mode 100644 index 0000000..200d11f --- /dev/null +++ b/hobo/contrib/ozwillo/views.py @@ -0,0 +1,124 @@ +# 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 . + +import logging +import requests +import io +import json +import subprocess +import hmac +from hashlib import sha1 + +from django.conf import settings +from django.http import HttpResponseForbidden, HttpResponseBadRequest +from django.core.management import call_command + + +logger = logging.getLogger(__name__) + +def valid_signature_required(func): + signature_header_name = 'X-Hub-Signature' + api_secret = settings.OZWILLO_SECRET + def wrapper(request): + if signature_header_name in request.headers: + if request.headers[signature_header_name].startswith('sha1='): + algo, received_hmac = request.headers[signature_header_name].rsplit('=') + computed_hmac = hmac.new(api_secret, request.data, 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('Invalid HMAC') + return HttpResponseForbidden('Invalid HMAC') + else: + logger.error('Invalid HMAC algo') + return('Invalid HMAC algo') + else: + logger.error('No HMAC in the header') + return('No HMAC in the header') + return func(request) + return wrapper + +@valid_signature_required +def create_publik_instance(request): + data = json.loads(request.body) + + client_id = data.pop('client_id') + client_secret = data.pop('client_secret') + instance_id = data.pop('instance_id') + instance_name = data.pop('organization_name', None) + + if not instance_name: + return HttpResponseBadRequest('Missing parameter "instance_name"') + + registration_uri = data.pop('instance_registration_uri') + organization = data['organization'] + user = data['user'] + + services = {'services': [{ + 'local_id': 'publik', + 'name': 'Publik - %s' % (instance_name), + 'service_uri':'https://connexion-%s.%s/accounts/oidc/login' % (instance_name, settings.OZWILLO_ENV_DOMAIN), + '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.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': [] + } + + template_recipe = json.load(open('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'] + imp_site_template = json.load(open('import-site-template.json', 'r')) + + for row in imp_site_template: + row['fields']['redirect_url'] = row['fields']['redirect_url'].replace('instance_name', instance_name) + + with io.open('import-site.json', 'w', encoding='utf-8') as f: + f.write(unicode(json.dumps(imp_site_template, ensure_ascii=False))) + + with io.open('recipe_%s.json' % instance_name, 'w', encoding='utf-8') as f: + f.write(unicode(json.dumps(template_recipe, ensure_ascii=False))) + + call_command('cook', 'recipe_%s.json' % instance_name) + ret_code = subprocess.call(['sudo', '-u', 'combo', 'combo-manage', + 'tenant_command', 'import_site', + 'import-site.json', '-d', domain]) + ret_code = subprocess.call(['sudo', '-u', 'combo', 'combo-manage', + 'tenant_command', 'import_site', + 'import-site-agents.json', '-d', domain_agent]) + + headers = {'Content-type': 'application/json', 'Accept': 'application/json'} + r = requests.post(registration_uri, data=json.dumps(services), auth=(client_id, client_secret), headers=headers) + +@valid_signature_required +def delete_publik_instance(request): + pass + diff --git a/hobo/urls.py b/hobo/urls.py index e7dbc24..5de9ca2 100644 --- a/hobo/urls.py +++ b/hobo/urls.py @@ -32,3 +32,7 @@ urlpatterns += patterns('', 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 += patterns('', + url(r'ozwillo/', include('hobo.contrib.ozwillo.urls')) + ) -- 2.11.0