Facturation: ajouter les endpoints nécessaires au bon fonctionnement des cellules facture de combo (#76495) #52

Merged
lguerin merged 3 commits from wip/76495-api-invoices-for-combo-cells into main 2023-04-24 09:28:50 +02:00
Owner
No description provided.
lguerin reviewed 2023-04-13 18:13:28 +02:00
@ -37,0 +55,4 @@
r'(?P<invoice_identifier>[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12})/pay/$',
views.invoicing_invoice_pay,
name='api-invoicing-invoice-pay',
),
Author
Owner

je n'ai pas fait le endpoint pdf, je le rajouterai quand on saura éditer des pdf

je n'ai pas fait le endpoint pdf, je le rajouterai quand on saura éditer des pdf
bdauvergne marked this conversation as resolved
lguerin reviewed 2023-04-13 18:14:27 +02:00
@ -78,0 +157,4 @@
class InvoicingInvoicePay(APIView):
# XXX ?
authentication_classes = []
permission_classes = ()
Author
Owner

Heu là je ne sais pas.
Il a fallu que j'ajoute ça pour pouvoir faire un paiement depuis le portail, mais je ne sais pas s'il ne me manquerait pas un bout de config.

Heu là je ne sais pas. Il a fallu que j'ajoute ça pour pouvoir faire un paiement depuis le portail, mais je ne sais pas s'il ne me manquerait pas un bout de config.
Owner

Si tu charges debian_config_common.py dans ton debian/debian_config.py normalement il n'y a rien à faire (ne même pas déclarer authentication/permission_classes, les valeurs par défaut suffisent):

$ grep -C3 -H -n REST.*DEFAULT.*ION debian/debian_config_common.py 
debian/debian_config_common.py-406-    if 'REST_FRAMEWORK' not in globals():
debian/debian_config_common.py-407-        REST_FRAMEWORK = {}
debian/debian_config_common.py-408-    if 'authentic2' not in INSTALLED_APPS:
debian/debian_config_common.py:409:        REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'] = (
debian/debian_config_common.py-410-            'hobo.rest_authentication.PublikAuthentication',
debian/debian_config_common.py-411-            'hobo.rest_authentication.APIClientAuthentication',
debian/debian_config_common.py-412-        )
debian/debian_config_common.py-413-    else:
debian/debian_config_common.py:414:        REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'] = ('hobo.rest_authentication.PublikAuthentication',)
debian/debian_config_common.py:415:    REST_FRAMEWORK['DEFAULT_PERMISSION_CLASSES'] = ('rest_framework.permissions.IsAuthenticated',)
debian/debian_config_common.py-416-    REST_FRAMEWORK['DEFAULT_RENDERER_CLASSES'] = ('rest_framework.renderers.JSONRenderer',)
Si tu charges debian_config_common.py dans ton debian/debian_config.py normalement il n'y a rien à faire (ne même pas déclarer authentication/permission_classes, les valeurs par défaut suffisent): ``` $ grep -C3 -H -n REST.*DEFAULT.*ION debian/debian_config_common.py debian/debian_config_common.py-406- if 'REST_FRAMEWORK' not in globals(): debian/debian_config_common.py-407- REST_FRAMEWORK = {} debian/debian_config_common.py-408- if 'authentic2' not in INSTALLED_APPS: debian/debian_config_common.py:409: REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'] = ( debian/debian_config_common.py-410- 'hobo.rest_authentication.PublikAuthentication', debian/debian_config_common.py-411- 'hobo.rest_authentication.APIClientAuthentication', debian/debian_config_common.py-412- ) debian/debian_config_common.py-413- else: debian/debian_config_common.py:414: REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'] = ('hobo.rest_authentication.PublikAuthentication',) debian/debian_config_common.py:415: REST_FRAMEWORK['DEFAULT_PERMISSION_CLASSES'] = ('rest_framework.permissions.IsAuthenticated',) debian/debian_config_common.py-416- REST_FRAMEWORK['DEFAULT_RENDERER_CLASSES'] = ('rest_framework.renderers.JSONRenderer',)
Owner

Si ça n'a pas marché tout seul il y a peut-être une souci au niveau des clés déclarés coté portail et coté lingo (voir le hobo.json dans le répertoire du tenant si c'est cohérent, sinon juste refaire un déploiement factice, i.e. éditer le nom du service dans hobo, ne rien changer, puis sauver).

Si ça n'a pas marché tout seul il y a peut-être une souci au niveau des clés déclarés coté portail et coté lingo (voir le hobo.json dans le répertoire du tenant si c'est cohérent, sinon juste refaire un déploiement factice, i.e. éditer le nom du service dans hobo, ne rien changer, puis sauver).
Author
Owner

J'ai bien hobo.rest_authentication.PublikAuthentication et hobo.rest_authentication.APIClientAuthentication dans DEFAULT_AUTHENTICATION_CLASSES, et les mêmes clés côté lingo et combo

J'ai ça dans les logs côté lingo:

Unauthorized: /api/regie/blah/invoice/544c7a9a-652a-4628-9599-3b8709e60890/pay/
"POST /api/regie/blah/invoice/544c7a9a-652a-4628-9599-3b8709e60890/pay/?NameID=&email=&orig=combo.dev.publik.love&algo=sha256&timestamp=2023-04-13T09%3A18%3A51Z&nonce=2fb8367cbc9c49d7132666332819b858&signature=PSGecbF0U4H5zQEFRK5tx1QjGAx5QvuJSvRWVRkIS4w%3D HTTP/1.0" 401 37

Et côté combo:

failed to POST https://lingo.dev.publik.love/api/regie/blah/invoice/544c7a9a-652a-4628-9599-3b8709e60890/pay/?NameID=&email=&orig=combo.dev.publik.love&algo=sha256&timestamp=2023-04-13T09%3A18%3A51Z&nonce=2fb8367cbc9c49d7132666332819b858&signature=PSGecbF0U4H5zQEFRK5tx1QjGAx5QvuJSvRWVRkIS4w%3D (401)
b'{"err":1,"err_desc":"user-not-found"}'
J'ai bien hobo.rest_authentication.PublikAuthentication et hobo.rest_authentication.APIClientAuthentication dans DEFAULT_AUTHENTICATION_CLASSES, et les mêmes clés côté lingo et combo J'ai ça dans les logs côté lingo: ``` Unauthorized: /api/regie/blah/invoice/544c7a9a-652a-4628-9599-3b8709e60890/pay/ "POST /api/regie/blah/invoice/544c7a9a-652a-4628-9599-3b8709e60890/pay/?NameID=&email=&orig=combo.dev.publik.love&algo=sha256&timestamp=2023-04-13T09%3A18%3A51Z&nonce=2fb8367cbc9c49d7132666332819b858&signature=PSGecbF0U4H5zQEFRK5tx1QjGAx5QvuJSvRWVRkIS4w%3D HTTP/1.0" 401 37 ``` Et côté combo: ``` failed to POST https://lingo.dev.publik.love/api/regie/blah/invoice/544c7a9a-652a-4628-9599-3b8709e60890/pay/?NameID=&email=&orig=combo.dev.publik.love&algo=sha256&timestamp=2023-04-13T09%3A18%3A51Z&nonce=2fb8367cbc9c49d7132666332819b858&signature=PSGecbF0U4H5zQEFRK5tx1QjGAx5QvuJSvRWVRkIS4w%3D (401) b'{"err":1,"err_desc":"user-not-found"}' ```
Owner

D'ac, le souci c'est ça 👍

?NameID=&email=

déjà c'est bizarre d'avoir les deux, mais surtout ils sont vides. Soit tu n'en mets pas et tu t'authentifies "en tant que service" avec tous les droits possibles, soit c'est défini et tu as les "droits" de l'utilisateur correspondant en fonction du contexte.

Ici il y a un truc qui déconne dans combo, on dirait qu'on est pas loggé sur le portail.

D'ac, le souci c'est ça 👍 ?NameID=&email= déjà c'est bizarre d'avoir les deux, mais surtout ils sont vides. Soit tu n'en mets pas et tu t'authentifies "en tant que service" avec tous les droits possibles, soit c'est défini et tu as les "droits" de l'utilisateur correspondant en fonction du contexte. Ici il y a un truc qui déconne dans combo, on dirait qu'on est pas loggé sur le portail.
Author
Owner

la méthode pay_invoice (combo/lingo) envoie:

            response = requests.post(url, remote_service='auto', data=json.dumps(data), headers=headers)

pas de user en param, puisque ça peut être fait dans un cron

la méthode `pay_invoice` (combo/lingo) envoie: ``` response = requests.post(url, remote_service='auto', data=json.dumps(data), headers=headers) ``` pas de user en param, puisque ça peut être fait dans un cron
Owner

Généralement pour les factures on notifie passerelle qui n'utilise pas rest-framework et ses classes d'authentification, c'est bien possible qu'on découvre que c'est incompatible à cette occasion, mais clairement la classe hobo.rest_authentication.PublikAuthentication n'accepte pas la présence d'un champ NameID vide (et pour les paiements sur panier c'est vers w.c.s. qui pareil ne se comporte pas de la même manière je suppose).

À faire :

  • vérifier que w.c.s et passerelle considèrent qu'un NameID vide c'est comme pas de NameID
  • modifier PublikAuthentication pour prendre ce comportement, puisque c'est le comportement existant, ou alors pay_invoice().

Mais le comportement de passerelle et w.c.s. est potentiellement problématique vu qu'un NameID vide est considéré comme une autorisation par service et pas par utilisateur (ça permettrait de lire des choses qu'on ne devrait pas)...

Généralement pour les factures on notifie passerelle qui n'utilise pas rest-framework et ses classes d'authentification, c'est bien possible qu'on découvre que c'est incompatible à cette occasion, mais clairement la classe hobo.rest_authentication.PublikAuthentication n'accepte pas la présence d'un champ NameID vide (et pour les paiements sur panier c'est vers w.c.s. qui pareil ne se comporte pas de la même manière je suppose). À faire : * vérifier que w.c.s et passerelle considèrent qu'un NameID vide c'est comme pas de NameID * modifier PublikAuthentication pour prendre ce comportement, puisque c'est le comportement existant, ou alors pay_invoice(). Mais le comportement de passerelle et w.c.s. est potentiellement problématique vu qu'un NameID vide est considéré comme une autorisation par service et pas par utilisateur (ça permettrait de lire des choses qu'on ne devrait pas)...
Owner

vérifier que w.c.s et passerelle considèrent qu'un NameID vide c'est comme pas de NameID

Pour w.c.s. un NameID vide n'est pas équivalent à l'absence de NameID,

        # email or NameID were given as empty to the query string, this maps
        # [to] the anonymous user case.
> vérifier que w.c.s et passerelle considèrent qu'un NameID vide c'est comme pas de NameID Pour w.c.s. un NameID vide n'est *pas* équivalent à l'absence de NameID, ``` # email or NameID were given as empty to the query string, this maps # [to] the anonymous user case. ```
Owner

Pour w.c.s. un NameID vide n'est pas équivalent à l'absence de NameID,

        # email or NameID were given as empty to the query string, this maps
        # [to] the anonymous user case.

Pour les endpoints de l'API peut-être mais pas pour les triggers si item.by n'est pas défini :

      signed_request = is_url_signed()
        user = get_user_from_api_query_string() or get_request().user
....
                if signed_request and not item.by:
                    pass
                else:
                    if not user:
                        raise errors.AccessForbiddenError('user not authenticated')
                    if not item.check_auth(self.formdata, user):
                        raise errors.AccessForbiddenError('unsufficient roles')

item.by n'est pas configuré je pense en général pour un trigger "pay" et donc ça marche. Je dirai que la correction est à faire coté combo, il ne doit pas mettre de NameID/email pour une notification de paiement. C'est sans objet.

> Pour w.c.s. un NameID vide n'est *pas* équivalent à l'absence de NameID, > > ``` > # email or NameID were given as empty to the query string, this maps > # [to] the anonymous user case. > ``` Pour les endpoints de l'API peut-être mais pas pour les triggers si item.by n'est pas défini : ``` signed_request = is_url_signed() user = get_user_from_api_query_string() or get_request().user .... if signed_request and not item.by: pass else: if not user: raise errors.AccessForbiddenError('user not authenticated') if not item.check_auth(self.formdata, user): raise errors.AccessForbiddenError('unsufficient roles') ``` item.by n'est pas configuré je pense en général pour un trigger "pay" et donc ça marche. Je dirai que la correction est à faire coté combo, il ne doit pas mettre de NameID/email pour une notification de paiement. C'est sans objet.
bdauvergne marked this conversation as resolved
lguerin reviewed 2023-04-13 18:15:59 +02:00
@ -78,0 +92,4 @@
.distinct()
.order_by('pk')
)
for agenda_pricing in agenda_pricing_qs:
Author
Owner

Il faut parcourir les grilles tarifaires attachées aux agendas de la régie, c'est vraiment pas top.
A revoir avec le plan long terme pour paramétrer les infos du payeur.

Il faut parcourir les grilles tarifaires attachées aux agendas de la régie, c'est vraiment pas top. A revoir avec le plan long terme pour paramétrer les infos du payeur.
Author
Owner

le build jenkins échoue, parce qu'il faut une evol côté publik-django-templatetags pour passer directement le nameid au filtre filter_by_user (entrouvert/publik-django-templatetags#2)

le build jenkins échoue, parce qu'il faut une evol côté publik-django-templatetags pour passer directement le nameid au filtre filter_by_user (https://git.entrouvert.org/entrouvert/publik-django-templatetags/pulls/2)
lguerin reviewed 2023-04-14 10:02:37 +02:00
@ -78,0 +177,4 @@
Transaction.make_payment(
regie=invoice.regie,
invoices=[invoice],
amount=invoice.remaining_amount,
Author
Owner

reprendre le montant trouvé dans data après merge de #76572

reprendre le montant trouvé dans data après merge de #76572
bdauvergne approved these changes 2023-04-22 16:27:15 +02:00
lguerin changed target branch from wip/76130-payments to main 2023-04-24 09:19:04 +02:00
lguerin added 3 commits 2023-04-24 09:21:40 +02:00
lguerin merged commit cac94810c0 into main 2023-04-24 09:28:50 +02:00
lguerin deleted branch wip/76495-api-invoices-for-combo-cells 2023-04-24 09:28:50 +02:00
Sign in to join this conversation.
No reviewers
No Label
No Milestone
No Assignees
3 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: entrouvert/lingo#52
No description provided.