def handle(self, *args, **options): nrc_client = NotificationsConfig.get_client() kanaal_name = "test" Kanaal(kanaal_name, "test") data = { "kanaal": kanaal_name, "hoofdObject": "https://example.com", "resource": "test", "resourceUrl": "https://example.com", "actie": "create", "aanmaakdatum": "2019-01-01T12:00:00Z", "kenmerken": {}, } try: nrc_client.create("notificaties", data) self.stdout.write( self.style.SUCCESS( f"Notification successfully sent to {nrc_client.base_url}!" )) except Exception as e: self.stdout.write( self.style.ERROR( f"Something went wrong while sending the notification to {nrc_client.base_url}" )) raise CommandError(e)
def resend_notification(notification: FailedNotification) -> None: """ Resend a failed notification. The message is extracted from the failed notification log. If any resends fail, they are logged again with the same original logger, making them available for future retries. """ assert notification.retried_at is None, "Can only resend not-retried notifications" config = NotificationsConfig.get_solo() client = config.get_client() try: client.create("notificaties", notification.message) except ClientError as error: notifs_logger.warning( "Could not deliver message to %s", client.base_url, exc_info=True, extra={ "notification_msg": notification.message, "status_code": notification.status_code, }, ) raise ResendFailure from error finally: notification.retried_at = timezone.now() notification.save()
def test_notification_config_inaccessible_create(self): conf = NotificationsConfig.get_solo() conf.api_root = "http://localhost:8001/api/v1/" conf.save() url = get_operation_url("zaak_create") zaaktype = ZaakTypeFactory.create(concept=False) zaaktype_url = reverse(zaaktype) data = { "zaaktype": f"http://testserver{zaaktype_url}", "vertrouwelijkheidaanduiding": VertrouwelijkheidsAanduiding.openbaar, "bronorganisatie": "517439943", "verantwoordelijkeOrganisatie": VERANTWOORDELIJKE_ORGANISATIE, "registratiedatum": "2012-01-13", "startdatum": "2012-01-13", "toelichting": "Een stel dronken toeristen speelt versterkte " "muziek af vanuit een gehuurde boot.", "zaakgeometrie": { "type": "Point", "coordinates": [4.910649523925713, 52.37240093589432], }, } response = self.client.post(url, data, **ZAAK_WRITE_KWARGS) self.assertEqual(response.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR) self.assertFalse(Zaak.objects.exists()) self.assertFalse(StatusLog.objects.exists())
def save(self, *args, **kwargs): super().save(*args, **kwargs) # To use the mechanics in vng-api-common, we create a JWTSecret object # so we don't need to implement our own authentication layer for the # notification callback API. if self.callback_client_id and self.callback_secret: JWTSecret.objects.update_or_create( identifier=self.callback_client_id, defaults={ 'secret': self.callback_secret, }) # Create NotificationConfig to store the NC. notifications_config = NotificationsConfig.get_solo() if self.nc_base_url: notifications_config.api_root = self.nc_base_url notifications_config.client_id = self.nc_client_id or self.global_api_client_id notifications_config.secret = self.nc_secret or self.global_api_secret notifications_config.save() # Create Subscription based on details here with default channel and # topics. Subscription.objects.update_or_create(config=notifications_config, defaults={ 'callback_url': self.callback_url, 'client_id': self.callback_client_id, 'secret': self.callback_secret, 'channels': [ 'zaken', ] })
def _test_nrc_config() -> list: if not apps.is_installed("vng_api_common.notifications"): return [] from vng_api_common.notifications.models import NotificationsConfig nrc_config = NotificationsConfig.get_solo() nrc_client = NotificationsConfig.get_client() has_nrc_auth = nrc_client.auth is not None checks = [ (_("NRC"), nrc_config.api_root, nrc_config.api_root.endswith("/")), ( _("Credentials for NRC"), _("Configured") if has_nrc_auth else _("Missing"), has_nrc_auth, ), ] # check if permissions in AC are fine if has_nrc_auth: error = False try: nrc_client.list("kanaal") except requests.ConnectionError: error = True message = _("Could not connect with NRC") except ClientError as exc: error = True message = _( "Cannot retrieve kanalen: HTTP {status_code} - {error_code}" ).format(status_code=exc.args[0]["status"], error_code=exc.args[0]["code"]) else: message = _("Can retrieve kanalen") checks.append( (_("NRC connection and authorizations"), message, not error)) return checks
def setUp(self): super().setUp() config = NotificationsConfig.get_solo() Service.objects.create( api_type=APITypes.nrc, api_root=config.api_root, client_id="test", secret="test", user_id="test", user_representation="Test", )
def test_register_webhook_success(request_with_middleware, *mocks): config = NotificationsConfig.get_solo() subscription = Subscription.objects.create( config=config, callback_url="https://example.com/callback", client_id="client_id", secret="secret", channels=["zaken"], ) register_webhook(object, request_with_middleware, Subscription.objects.all()) messages = list(get_messages(request_with_middleware)) assert len(messages) == 0 subscription.refresh_from_db() assert subscription._subscription == "https://example.com/api/v1/abonnementen/1"
def test_register_webhook_client_error(request_with_middleware): config = NotificationsConfig.get_solo() Subscription.objects.create( config=config, callback_url="https://example.com/callback", client_id="client_id", secret="secret", channels=["zaken"], ) with patch("zds_client.client.Client.create", side_effect=ClientError("exception")): register_webhook(object, request_with_middleware, Subscription.objects.all()) messages = list(get_messages(request_with_middleware)) assert len(messages) == 1 assert messages[0].message == _( "Something went wrong while registering subscription for {callback_url}: {e}" ).format(callback_url="https://example.com/callback", e="exception")
def test_correct_credentials_used(self): svc, _ = Service.objects.update_or_create( api_root="https://open-notificaties.local/api/v1/", defaults=dict( label="NRC", api_type=APITypes.nrc, client_id="some-client-id", secret="some-secret", auth_type=AuthTypes.zgw, ), ) config = NotificationsConfig.get_solo() config.api_root = svc.api_root config.save() with requests_mock.Mocker() as m: mock_service_oas_get(m, "nrc", url=svc.api_root) m.get("https://open-notificaties.local/api/v1/kanaal?naam=zaken", json=[]) m.post("https://open-notificaties.local/api/v1/kanaal", status_code=201) call_command("register_kanaal", kanaal="zaken") # check for auth in the calls for request in m.request_history[1:]: with self.subTest(method=request.method, url=request.url): self.assertIn("Authorization", request.headers) token = request.headers["Authorization"].split(" ")[1] try: jwt.decode(token, key="some-secret", algorithms=["HS256"]) except Exception as exc: self.fail( "Not a vaid JWT in Authorization header: %s" % exc)
def test_setup_configuration(self): openzaak_domain = "open-zaak.utrecht.nl" nrc_root = "https://open-notificaties.utrecht.nl/api/v1/" municipality = "Utrecht" openzaak_to_notif_secret = "12345" notif_to_openzaak_secret = "54321" call_command( "setup_configuration", openzaak_domain, nrc_root, municipality, openzaak_to_notif_secret, notif_to_openzaak_secret, ) site = Site.objects.get_current() self.assertEqual(site.domain, openzaak_domain) self.assertEqual(site.name, f"Open Zaak {municipality}") notif_config = NotificationsConfig.get_solo() self.assertEqual(notif_config.api_root, nrc_root) api_credential = APICredential.objects.get() self.assertEqual(api_credential.api_root, nrc_root) self.assertEqual( api_credential.label, f"Open Notificaties {municipality}", ) self.assertEqual(api_credential.client_id, f"open-zaak-{municipality.lower()}") self.assertEqual(api_credential.secret, openzaak_to_notif_secret) self.assertEqual(api_credential.user_id, f"open-zaak-{municipality.lower()}") self.assertEqual(api_credential.user_representation, f"Open Zaak {municipality}") notif_api_jwtsecret_ac = JWTSecret.objects.get() self.assertEqual( notif_api_jwtsecret_ac.identifier, f"open-notificaties-{municipality.lower()}", ) self.assertEqual(notif_api_jwtsecret_ac.secret, notif_to_openzaak_secret) notif_api_applicatie_ac = Applicatie.objects.get( label=f"Open Notificaties {municipality}") self.assertEqual(notif_api_applicatie_ac.client_ids, [notif_api_jwtsecret_ac.identifier]) notif_api_autorisatie_ac = Autorisatie.objects.get( applicatie=notif_api_applicatie_ac) self.assertEqual(notif_api_autorisatie_ac.component, ComponentTypes.ac) self.assertEqual(notif_api_autorisatie_ac.scopes, [SCOPE_AUTORISATIES_LEZEN.label]) openzaak_applicatie_notif = Applicatie.objects.get( label=f"Open Zaak {municipality}") self.assertEqual(openzaak_applicatie_notif.client_ids, [f"open-zaak-{municipality.lower()}"]) openzaak_autorisatie_notif = Autorisatie.objects.get( applicatie=openzaak_applicatie_notif) self.assertEqual(openzaak_autorisatie_notif.component, ComponentTypes.nrc) self.assertEqual( openzaak_autorisatie_notif.scopes, [ SCOPE_NOTIFICATIES_CONSUMEREN_LABEL, SCOPE_NOTIFICATIES_PUBLICEREN_LABEL, ], )
def handle(self, *args, **options): try: openzaak_domain = options["openzaak_domain"] notifications_api_root = options["notifications_api_root"] municipality = options["municipality"] openzaak_to_notif_secret = options["openzaak_to_notif_secret"] notif_to_openzaak_secret = options["notif_to_openzaak_secret"] # See: https://open-zaak.readthedocs.io/en/latest/installation/configuration.html#setting-the-domain site = Site.objects.get_current() site.domain = openzaak_domain site.name = f"Open Zaak {municipality}" site.save() # For the steps below, see: # https://open-zaak.readthedocs.io/en/latest/installation/configuration.html#open-zaak # Step 1 notif_config = NotificationsConfig.get_solo() notif_config.api_root = notifications_api_root notif_config.save() # Step 2 if not APICredential.objects.filter( api_root=notifications_api_root ).exists(): APICredential.objects.create( api_root=notifications_api_root, label=f"Open Notificaties {municipality}", client_id=f"open-zaak-{municipality.lower()}", secret=openzaak_to_notif_secret, user_id=f"open-zaak-{municipality.lower()}", user_representation=f"Open Zaak {municipality}", ) # Step 3 notif_api_jwtsecret_ac = JWTSecret.objects.create( identifier=f"open-notificaties-{municipality.lower()}", secret=notif_to_openzaak_secret, ) notif_api_applicatie_ac = Applicatie.objects.create( label=f"Open Notificaties {municipality}", client_ids=[notif_api_jwtsecret_ac.identifier], ) Autorisatie.objects.create( applicatie=notif_api_applicatie_ac, component=ComponentTypes.ac, scopes=[SCOPE_AUTORISATIES_LEZEN], ) # Step 4 openzaak_applicatie_notif = Applicatie.objects.create( label=f"Open Zaak {municipality}", client_ids=[f"open-zaak-{municipality.lower()}"], ) Autorisatie.objects.create( applicatie=openzaak_applicatie_notif, component=ComponentTypes.nrc, scopes=[ SCOPE_NOTIFICATIES_CONSUMEREN_LABEL, SCOPE_NOTIFICATIES_PUBLICEREN_LABEL, ], ) self.stdout.write( self.style.SUCCESS( "Initial configuration for Open Zaak was setup successfully" ) ) except Exception as e: raise CommandError( f"Something went wrong while setting up initial configuration: {e}" )
def test_notificationsconfig_custom_client(): config = NotificationsConfig.get_solo() client = config.get_client() assert client == "testclient"