This PR follows up with the conversation we had via email and cleans up
the auth implementation.
**New `AuthRepository`**
The `AuthTokenRepository`, `AuthLoginComponent` and
`AuthLogoutComponent` have been refactored into a single
`AuthRepository`.
This `AuthRepository` exposes the `isAuthenticated` boolean, which is
used by `go_router` to handle redirects.
Also, has two methods, `login(email, pass)` and `logout()`, similar to
what we had in the components.
The implementation uses the new `SharedPreferencesService`, which is a
service to access the `shared_preferences` plugin to store the `String`
token.
**New `AuthApiClient`**
The `ApiClient` has been split in two. The `/login` REST call is moved
to the `AuthApiClient`, while the other calls that require an auth token
remain in the `ApiClient`.
**`ApiClient` credentials**
The main open question is, what is the best way to pass the auth token
to the api client?
I've found several alternatives:
1. `ApiClient` has a `token` setter which the `AuthRepository` calls to
set the token
- Implemented in this PR.
- Follows our architecture design.
- `AuthRepository` should be the source of truth, but the
`ApiClient.token` could be set externally by mistake, so the single
source of truth principle gets blurry.
2. `ApiClient` calls to the `AuthRepository` to obtain the token.
- This is what the code was doing before.
- `AuthRepository` is the source of truth.
- But the dependency "Service to Repository" breaks our architecture
design principle.
3. `ApiClient` calls to the `SharedPreferencesService` to obtain the
token (
- `SharedPreferencesService` is the source of truth, as the `ApiClient`
doesn't need the `AuthRepository`.
- We see a "Service calling a Service" which maybe breaks our
architecture design principle?
4. The `ApiClient` doesn't hold the token at all, intead, each call
requires us to pass a token.
- Tried to implement it but becomes very complex.
- Makes other repositories depend on the `AuthRepository` or the
`SharedPreferencesService`.
Personal take: I have implemented 1 in this PR because it is the one
that follows best the architecture recommendations. However I see some
pitfalls, e.g. the `AuthRepository` needs to fetch the token from the
`SharedPreferencesService` at least once on app start and pass it to the
`ApiClient`. While on the solution 2 that's never a problem, since the
`AuthRepository` is being called from the `ApiClient` and so it is
always the source of truth for authentication.
I am looking forward for your thoughts @ericwindmill
## Pre-launch Checklist
- [x] I read the [Flutter Style Guide] _recently_, and have followed its
advice.
- [x] I signed the [CLA].
- [x] I read the [Contributors Guide].
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] All existing and new tests are passing.
If you need help, consider asking for advice on the #hackers-devrel
channel on [Discord].
<!-- Links -->
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md
[CLA]: https://cla.developers.google.com/
[Discord]:
https://github.com/flutter/flutter/blob/master/docs/contributing/Chat.md
[Contributors Guide]:
https://github.com/flutter/samples/blob/main/CONTRIBUTING.md