[Doctrine DBAL will remove its event system in version 4.0](https://github.com/doctrine/dbal/issues/5784) and logs deprecation warnings whenever code uses the event system. Our code uses the event system to generate access and update tokens for donations and memberships when they are saved. To avoid filling our log files with deprecation warnings (which make debugging harder because they clutter the log files and may lead to false assumptions) and make our code ready for updating to Doctrine version 4, we need to change the way how and when we store security tokens.
**Background information**
When we wrote the Fundraising Application and created the domain model, we did not want to "pollute" our domain object (Donation) with HTTP-specific access control properties, so we opted for "sneaking them in" through the Doctrine entity when the donation is saved.
**Solution**
We still want the general concept of access control (in this case "the owner has a token that allows them access") inside our use cases. We need to pass an interface into the `AddDonation` and `AddMembership` use cases that'll allow us to create the credentials.
Currently, the `TokenFetcher` dependency of the use case exposes the existence of tokens to the domain. With the [refactorings for the Paypal API](https://phabricator.wikimedia.org/T344271) we'll use a system that doesn't expose concepts like tokens on the wrong layers.
**Acceptance criteria:**
- The deprecation warning for the event system no longer occurs
**Non-Goals:**
- Extracting the access tokens from the data blob in `spenden` into their own table - This would be too much effort right now. However, make sure that there is only one class for interacting with the database, so they can be swapped out in the future.
**Implementation details:**
When integrating the changed bounded contexts into the Fundraising App, you can remove event-related code from `ContextFactoryCollection`, `DoctrineFactory` and `FunFunFactory`. In `FunFunFactory`, `getPlainEntityManager` can become the new `getEntityManager`.
The Fundraising Operation Center does not need any changes - it doesn't call the "Add Donation" and "Add Membership" use cases and doesn't initialize Doctrine with event subscribers.
Suggested Approach for generating tokens inside the "create" use cases:
- The payment bounded context has an interface `addAuthenticationTokensToUrl` that can add tokens to any URL.
- The membership and donation bounded contexts have interfaces that can "announce" an entity to the authentication layer (e.g. `createAuthorizationForDonation(id)` and `createAuthorizationForMembership(id)`). These methods might be added to the existing `DonationAuthorizer` and `MembershipAuthorizer` interfaces.
- The Fundraising Application has an authorizer implementation of the 3 interfaces. It creates in-memory tokens when the `createAuthorizationForDonation(id)` and `createAuthorizationForMembership(id)` are called and appends them to URLs. The authorizer should also implement event handlers for the "donation created" and "membership crated" *domain* events to write the in-memory tokens to the database (see `FunFunFactorysetupEventListeners`).
- The `addAuthenticationTokensToUrl` implementation will take over some of the functionality of the UrlGenerators in the payment domain (because in the long run we want to be more flexible with our Application-Level URL parameters and should not encode them in the Payment bounded context). This means we'll have to check the target URL (with URL values from the payment section if the application configuration) and append the right parameters:
- application domain (test-spenden-2.wikimedia.de, spenden.wikimedia.de, etc): check the path and append path-dependent parameters:
- donation-confirmation: append `id`, `updateToken` and `accessToken`
- handle-paypal-payment-notification `accessToken`
- micropayment domain: `sid` (donation id), `token` (accesstoken), `utoken` (update token)
- paypal domain: check if the URL is for the API (`api-m.sandbox.paypal.com` or `api-m.paypal.com`) or the old-style-parameter passing (`paypal.com/cgi-bin/webscr?`)
- for the API, don't append anything
- for the parameter passing, append a json-encoded `custom` parameter with an object that has (`sid` (donation id) and `utoken` (update token)).
- sofort domain: don't append anything, we sent the parameters via the API
You need to test if the payment and notification flows are still working!