471 lines
16 KiB
Python
471 lines
16 KiB
Python
# Copyright (C) 2022 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 base64
|
|
import json
|
|
import urllib.parse
|
|
|
|
import requests
|
|
from django.db import models
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
from passerelle.base.models import BaseResource
|
|
from passerelle.utils.api import endpoint
|
|
from passerelle.utils.jsonresponse import APIError
|
|
|
|
BASE_ENPOINT_PARAMS = {
|
|
'organism': {'description': _('Organisme'), 'example_value': 'NOMDEVILLE'},
|
|
'budget': {'description': _('Budget'), 'example_value': '01'},
|
|
'exercice': {'description': _('Exercice'), 'example_value': '2022'},
|
|
}
|
|
|
|
ENTITY_TYPE_PARAM = {'optionnal': False, 'description': _('Entity type'), 'example_value': 'FACTURE'}
|
|
|
|
ENTITY_REF_PARAM = {'optionnal': False, 'description': _('Entity ref'), 'example_value': ''}
|
|
|
|
GF_DOCUMENTS_DOCUMENT_READ_PARAMS = dict(BASE_ENPOINT_PARAMS)
|
|
GF_DOCUMENTS_DOCUMENT_READ_PARAMS.update(
|
|
{
|
|
'entity_type': ENTITY_TYPE_PARAM,
|
|
'entity_ref': ENTITY_REF_PARAM,
|
|
'document_ref': {'optionnal': False, 'description': _('Document ref'), 'example_value': ''},
|
|
}
|
|
)
|
|
|
|
GF_DOCUMENTS_ENTITIES_GETFREF_PARAMS = dict(BASE_ENPOINT_PARAMS)
|
|
GF_DOCUMENTS_ENTITIES_GETFREF_PARAMS.update(
|
|
{
|
|
'entity_type': ENTITY_TYPE_PARAM,
|
|
'entity_code': {'optionnal': False, 'description': _('Entity type'), 'example_value': 'RMA01'},
|
|
}
|
|
)
|
|
|
|
GF_DOCUMENTS_ENTITIES_READ_PARAMS = dict(BASE_ENPOINT_PARAMS)
|
|
GF_DOCUMENTS_ENTITIES_READ_PARAMS.update(
|
|
{
|
|
'entity_type': ENTITY_TYPE_PARAM,
|
|
'entity_ref': ENTITY_REF_PARAM,
|
|
}
|
|
)
|
|
|
|
GF_DOCUMENTS_ENTITIES_SEARCH_PARAMS = dict(BASE_ENPOINT_PARAMS)
|
|
GF_DOCUMENTS_ENTITIES_SEARCH_PARAMS.update(
|
|
{
|
|
'entity_type': ENTITY_TYPE_PARAM,
|
|
's': {'optionnal': False, 'description': _('Search criteria'), 'example_value': ''},
|
|
}
|
|
)
|
|
|
|
GF_DOCUMENTS_ENTITIES_LIST_PARAMS = dict(BASE_ENPOINT_PARAMS)
|
|
GF_DOCUMENTS_ENTITIES_LIST_PARAMS.update(
|
|
{
|
|
'entity_type': ENTITY_TYPE_PARAM,
|
|
'entity_ref': ENTITY_REF_PARAM,
|
|
'code_list': {'optionnal': False, 'description': _('Code list'), 'example_value': ''},
|
|
}
|
|
)
|
|
|
|
DOCUMENT_CREATE_OR_UPDATE_SCHEMA = {
|
|
'type': 'object',
|
|
'title': _('Document creation or update'),
|
|
'properties': {
|
|
'file': {
|
|
'title': _('File object'),
|
|
'type': 'object',
|
|
'properties': {
|
|
'filename': {
|
|
'type': 'string',
|
|
'description': _('Filename'),
|
|
},
|
|
'content': {
|
|
'type': 'string',
|
|
'description': _('Content'),
|
|
},
|
|
'content_type': {
|
|
'type': 'string',
|
|
'description': _('Content type'),
|
|
},
|
|
},
|
|
'required': ['content'],
|
|
},
|
|
'entity_type': {
|
|
'type': 'string',
|
|
},
|
|
'entity_ref': {
|
|
'type': 'string',
|
|
},
|
|
'astre_ref': {
|
|
'type': 'string',
|
|
},
|
|
'ged_ref': {
|
|
'type': 'string',
|
|
},
|
|
'doc_type': {
|
|
'type': 'string',
|
|
},
|
|
'description': {
|
|
'type': 'string',
|
|
},
|
|
'filename': {
|
|
'type': 'string',
|
|
'description': _('Filename (takes precendence over filename in "file" object)'),
|
|
},
|
|
'indpj': {
|
|
'type': 'string',
|
|
},
|
|
'domain_code': {
|
|
'type': 'string',
|
|
},
|
|
},
|
|
'required': ['entity_type', 'entity_ref', 'doc_type', 'file'],
|
|
'unflatten': False,
|
|
}
|
|
|
|
DOCUMENT_DELETE_SCHEMA = {
|
|
'type': 'object',
|
|
'title': _('Document delete'),
|
|
'properties': {
|
|
'entity_type': {
|
|
'type': 'string',
|
|
},
|
|
'entity_ref': {
|
|
'type': 'string',
|
|
},
|
|
'document_ref': {
|
|
'type': 'string',
|
|
},
|
|
},
|
|
'required': ['entity_type', 'entity_ref', 'document_ref'],
|
|
'unflatten': False,
|
|
}
|
|
|
|
ASTRE_ERRORS = (
|
|
'UndefinedError',
|
|
'VersionError',
|
|
'ConfigError',
|
|
'AuthError',
|
|
'ConfError',
|
|
'DataError',
|
|
'NotFoundError',
|
|
'AstreError',
|
|
'AstreException',
|
|
)
|
|
|
|
AUTH_CHOICES = [
|
|
('AD', 'AD'),
|
|
('EXTERNE', 'EXTERNE'),
|
|
('LDAP', 'LDAP'),
|
|
('NORMAL', 'NORMAL'),
|
|
]
|
|
|
|
|
|
class AstreREST(BaseResource):
|
|
base_url = models.URLField(_('API URL'))
|
|
username = models.CharField(_('Username'), max_length=32)
|
|
password = models.CharField(_('Password'), max_length=32)
|
|
database = models.CharField('Database', max_length=32)
|
|
auth = models.CharField(_('Authentication mode'), max_length=32, choices=AUTH_CHOICES, blank=True)
|
|
organism = models.CharField('Organisme', max_length=32)
|
|
budget = models.CharField('Budget', max_length=32)
|
|
exercice = models.CharField('Exercice', max_length=32)
|
|
verify_cert = models.BooleanField(default=True, verbose_name=_('Check HTTPS Certificate validity'))
|
|
|
|
category = _('Business Process Connectors')
|
|
|
|
class Meta:
|
|
verbose_name = 'Astre REST'
|
|
|
|
def check_status(self):
|
|
self._astre_call('astre/webservices/gf/documents/referentiel/typedocument/list/json')
|
|
|
|
@property
|
|
def encrypted_password(self):
|
|
key = 48
|
|
password = ''
|
|
for char in self.password:
|
|
password += chr(ord(char) ^ key)
|
|
return urllib.parse.quote(password, 'iso-8859-1')
|
|
|
|
def _astre_call(self, path, method='get', params=None, data=None, files=None, expect_json=True):
|
|
params = params or {}
|
|
url = urllib.parse.urljoin(self.base_url, path)
|
|
authentication_params = {
|
|
'login': self.username,
|
|
'password': self.encrypted_password,
|
|
'database': self.database,
|
|
}
|
|
if self.auth:
|
|
authentication_params['auth'] = self.auth
|
|
|
|
kwargs = {}
|
|
if method == 'get':
|
|
kwargs['headers'] = authentication_params
|
|
|
|
elif method == 'post':
|
|
if not data:
|
|
data = {}
|
|
data.update(authentication_params)
|
|
kwargs['data'] = data
|
|
if files:
|
|
kwargs['files'] = files
|
|
|
|
resp = getattr(self.requests, method)(url, params=params, **kwargs)
|
|
|
|
try:
|
|
resp.raise_for_status()
|
|
except requests.RequestException as e:
|
|
content = getattr(getattr(e, 'response', None), 'content', None)
|
|
raise APIError('request failed', url, e, content)
|
|
try:
|
|
json_resp = resp.json()
|
|
if hasattr(json_resp, 'get') and json_resp.get('code') in ASTRE_ERRORS:
|
|
msg = json_resp.get('code')
|
|
if json_resp.get('message'):
|
|
msg += ': %s' % json_resp.get('message')
|
|
raise APIError(msg)
|
|
return json_resp
|
|
except json.JSONDecodeError:
|
|
if expect_json:
|
|
raise
|
|
return resp.text
|
|
|
|
def _get_context_param(self, params, concat=True):
|
|
res = []
|
|
for param_name in ('organism', 'budget', 'exercice'):
|
|
res.append(params[param_name] if param_name in params else getattr(self, param_name))
|
|
if concat:
|
|
return '%s-%s-%s' % tuple(res)
|
|
return res
|
|
|
|
def _get_document_create_update_data(self, post_data):
|
|
organism, budget, exercice = self._get_context_param(post_data, concat=False)
|
|
return {
|
|
'codeOrganisme': organism,
|
|
'codeBudget': budget,
|
|
'codeExercice': exercice,
|
|
'typeEntite': post_data['entity_type'],
|
|
'refEntite': post_data['entity_ref'],
|
|
'referenceAstre': post_data.get('astre_ref', ''),
|
|
'referenceGed': post_data.get('ged_ref', ''),
|
|
'typeDoc': post_data['doc_type'],
|
|
'description': post_data.get('description', ''),
|
|
'nomFichier': post_data.get('filename', '') or post_data['file'].get('filename', ''),
|
|
'typeMime': post_data['file'].get('mime_type', ''),
|
|
'indPJ': post_data.get('indpj', ''),
|
|
'codeDomaine': post_data.get('domain_code', ''),
|
|
}
|
|
|
|
def _get_data_source(self, data):
|
|
res = []
|
|
for record in data:
|
|
res.append(
|
|
{
|
|
'id': record['code'],
|
|
'text': record['libelle'],
|
|
'code': record['code'],
|
|
'libelle': record['libelle'],
|
|
}
|
|
)
|
|
return res
|
|
|
|
@endpoint(
|
|
methods=['get'],
|
|
perm='can_access',
|
|
name='gf-documents-entites-getref',
|
|
parameters=GF_DOCUMENTS_ENTITIES_GETFREF_PARAMS,
|
|
)
|
|
def gf_documents_entites_getref(self, request, **kwargs):
|
|
contexte = self._get_context_param(kwargs)
|
|
fonctionnal_key = '%s-%s' % (kwargs['entity_type'], kwargs['entity_code'])
|
|
path = 'astre/webservices/gf/documents/entites/getRefEntite/%s/%s' % (contexte, fonctionnal_key)
|
|
return {'data': self._astre_call(path, expect_json=False)}
|
|
|
|
@endpoint(
|
|
methods=['get'],
|
|
perm='can_access',
|
|
name='gf-documents-entites-list',
|
|
parameters=GF_DOCUMENTS_ENTITIES_LIST_PARAMS,
|
|
)
|
|
def gf_documents_entites_list(self, request, **kwargs):
|
|
contexte = self._get_context_param(kwargs)
|
|
entity_key = '%s-%s' % (kwargs['entity_type'], kwargs['entity_ref'])
|
|
path = 'astre/webservices/gf/documents/entites/%s/%s/list/%s/json' % (
|
|
contexte,
|
|
entity_key,
|
|
kwargs['code_list'],
|
|
)
|
|
data = []
|
|
for record in self._astre_call(path):
|
|
data.append(
|
|
{
|
|
'id': record['codeEntite'],
|
|
'text': record['libelleEntite'],
|
|
'codeEntite': record['codeEntite'],
|
|
'libelleEntite': record['libelleEntite'],
|
|
'typeEntite': record['typeEntite'],
|
|
'refEntite': record['refEntite'],
|
|
'codeOrganisme': record['codeOrganisme'],
|
|
}
|
|
)
|
|
return {'data': data}
|
|
|
|
@endpoint(
|
|
methods=['get'],
|
|
perm='can_access',
|
|
name='gf-documents-entites-read',
|
|
parameters=GF_DOCUMENTS_ENTITIES_READ_PARAMS,
|
|
)
|
|
def gf_documents_entites_read(self, request, **kwargs):
|
|
contexte = self._get_context_param(kwargs)
|
|
entity_key = '%s-%s' % (kwargs['entity_type'], kwargs['entity_ref'])
|
|
path = 'astre/webservices/gf/documents/entites/read/%s/%s/json' % (contexte, entity_key)
|
|
return {'data': self._astre_call(path)}
|
|
|
|
@endpoint(
|
|
methods=['get'],
|
|
perm='can_access',
|
|
name='gf-documents-entites-search',
|
|
parameters=GF_DOCUMENTS_ENTITIES_SEARCH_PARAMS,
|
|
)
|
|
def gf_documents_entites_search(self, request, **kwargs):
|
|
contexte = self._get_context_param(kwargs)
|
|
path = 'astre/webservices/gf/documents/entites/search/%s/%s/json' % (
|
|
contexte,
|
|
kwargs['entity_type'],
|
|
)
|
|
data = []
|
|
for record in self._astre_call(path, params={'s': kwargs['s']}):
|
|
data.append(
|
|
{
|
|
'id': record['codeEntite'],
|
|
'text': record['libEntite'],
|
|
'refEntite': record['refEntite'],
|
|
'libEntite': record['libEntite'],
|
|
'typeEntite': record['typeEntite'],
|
|
'codeEntite': record['codeEntite'],
|
|
'codeOrganisme': record['codeOrganisme'],
|
|
}
|
|
)
|
|
|
|
return {'data': data}
|
|
|
|
@endpoint(
|
|
name='gf-documents-gedmanager-document-create',
|
|
description=_('Create document'),
|
|
perm='can_access',
|
|
post={
|
|
'request_body': {
|
|
'schema': {
|
|
'application/json': DOCUMENT_CREATE_OR_UPDATE_SCHEMA,
|
|
}
|
|
}
|
|
},
|
|
)
|
|
def gf_documents_gedmanager_document_create(self, request, post_data):
|
|
send_data = self._get_document_create_update_data(post_data)
|
|
return {
|
|
'data': self._astre_call(
|
|
'astre/webservices/gf/documents/gedmanager/document/create/json',
|
|
method='post',
|
|
data=send_data,
|
|
files={'fichier': base64.b64decode(post_data['file']['content'])},
|
|
)
|
|
}
|
|
|
|
@endpoint(
|
|
name='gf-documents-gedmanager-document-delete',
|
|
description=_('Delete document'),
|
|
perm='can_access',
|
|
post={
|
|
'request_body': {
|
|
'schema': {
|
|
'application/json': DOCUMENT_DELETE_SCHEMA,
|
|
}
|
|
}
|
|
},
|
|
)
|
|
def gf_documents_gedmanager_document_delete(self, request, post_data):
|
|
organism, budget, exercice = self._get_context_param(post_data, concat=False)
|
|
send_data = {
|
|
'codeOrganisme': organism,
|
|
'codeBudget': budget,
|
|
'codeExercice': exercice,
|
|
'typeEntite': post_data['entity_type'],
|
|
'refEntite': post_data['entity_ref'],
|
|
'referenceGed': post_data['document_ref'],
|
|
}
|
|
return {
|
|
'data': self._astre_call(
|
|
'astre/webservices/gf/documents/gedmanager/document/delete/json',
|
|
method='post',
|
|
data=send_data,
|
|
)
|
|
}
|
|
|
|
@endpoint(
|
|
methods=['get'],
|
|
perm='can_access',
|
|
name='gf-documents-gedmanager-document-read',
|
|
parameters=GF_DOCUMENTS_DOCUMENT_READ_PARAMS,
|
|
)
|
|
def gf_documents_gedmanager_document_read(self, request, **kwargs):
|
|
context = self._get_context_param(kwargs)
|
|
entity_key = '%s-%s' % (kwargs['entity_type'], kwargs['entity_ref'])
|
|
path = '/astre/webservices/gf/documents/gedmanager/document/read/%s/%s/%s/json?metadonnees=all' % (
|
|
context,
|
|
entity_key,
|
|
kwargs['document_ref'],
|
|
)
|
|
return {'data': self._astre_call(path)}
|
|
|
|
@endpoint(
|
|
name='gf-documents-gedmanager-document-update',
|
|
description=_('Update document'),
|
|
perm='can_access',
|
|
post={
|
|
'request_body': {
|
|
'schema': {
|
|
'application/json': DOCUMENT_CREATE_OR_UPDATE_SCHEMA,
|
|
}
|
|
}
|
|
},
|
|
)
|
|
def gf_documents_gedmanager_document_update(self, request, post_data):
|
|
send_data = self._get_document_create_update_data(post_data)
|
|
return {
|
|
'data': self._astre_call(
|
|
'astre/webservices/gf/documents/gedmanager/document/update/json',
|
|
method='post',
|
|
data=send_data,
|
|
files={'fichier': base64.b64decode(post_data['file']['content'])},
|
|
)
|
|
}
|
|
|
|
@endpoint(methods=['get'], perm='can_access', name='gf-documents-referentiel-domainepj')
|
|
def gf_documents_referentiel_domainepj(self, request):
|
|
return {
|
|
'data': self._get_data_source(
|
|
self._astre_call('astre/webservices/gf/documents/referentiel/domainepj/list/json')
|
|
)
|
|
}
|
|
|
|
@endpoint(methods=['get'], perm='can_access', name='gf-documents-referentiel-typedocument')
|
|
def gf_documents_referentiel_typedocument(self, request):
|
|
return {
|
|
'data': self._get_data_source(
|
|
self._astre_call('astre/webservices/gf/documents/referentiel/typedocument/list/json')
|
|
)
|
|
}
|