The use of a lazy function here make the Django migration
detector to generate a migration every time we run `makemigrations`.
This is not mandatory to have a lazy here as the settings are loaded
once at runtime beginning.
As the choices makes noop migrations, we directly use the setting in
the initial migration.
This adds the plugin system to easily manage
Organization related customizations. This first
plugin tries (best effort) to get a proper name
for the Organization, using its SIRET. This
is French specificities but another plugin can
be defined for other cases.
Use the common way to define permissions on the API.
Note: we keep here the notion of "public" contacts,
even if the API does not really allows that. The use
case is not clear for that, but we allow contact w/o
owner to be displayed.
Move the user <-> contact relation for "profile" to
the contact model.
Now the Contact model is the only one to point to
User (and not backward).
Contact:
- FK to User for the owner
- FK to User for the profile
To improve code readability, I propose to rename
the contact field `override`. This comes along
with the fact a contact should not not always
override another (it's the case were I only want
to create some personal contacts).
We make the full name mandatory and add a field to
allow user to store personnal notes on the contact.
This also make the "base" contact not mandatory because
user may want to create new contacts out of the blue.
When updating an Organization in the Django admin, the validator
falsly raises a "duplicated" error because it does not exclude the
current object from the database lookup.
This allows, on a per user basis, the display of
features.
The main goal here is to allow Team admin or owner
to see the management views.
We also added the same for the two other features
(mailboxes and contacts)
This will be improved later if needed :)
After some reflexion, the use of a slug field raises to many
problems without being really needed.
One problem is the slug is made from the group name, but we
don't have unicity on this, so a user might be blocked without
any clue.
We also want to allow group names to be reused (which is already
allowed except for the automatic slug).
The unique ID that will be shared with Service Providers will be
the PK/UUID.
We introduce the Organization model has a "hat" for all
users and team.
Each User must have a "default" organization.
Each Team must have an organization.
When a User creates a new Team, the team is linked to their
default Organization.
For now the Organization should not be visible to end users
this is a purely technical aspect as it.
The models are also adding a permission to allow User to edit
an Organization, but for now there are no endpoints for that.
Next steps:
- Add an Organization to each User and Team on all environments
to mark Organization as mandatory in database.
- Add scope to Organization to list the Service Provider list
allowed for a User in an Organization.
- Add endpoints + frontend to manage Organization's scopes
The email field on the user is renamed to "admin_email" for clarity. The
"email" and "name" fields of user's main identity are made available on
the user model so it is easier to access it.
When generating an Invitation object within the database, our intention
is to promptly notify the user via email. We send them an invitation
to join Desk.
This code is inspired by Joanie successful order flow.
Johann's design was missing a link to Desk, I simply added a button which
redirect to the staging url. This url is hardcoded, we should refactor it
when we will deploy Desk in pre-prod or prod environments.
Johann's design relied on Marianne font. I implemented a simpler version,
which uses a google font. That's not important for MVP.
Look and feel of this first invitation template is enough to make our PoC
functionnal, which is the more important.
Improved code readability, by extracting this well-scoped unit of
logic in a dedicated method. Also, rename active_invitations to match
'valid' vocabulary used elsewhere in the doc. If no valid invitation
exists, early return to avoid nesting.
Nest invitation router below team router and add create endpoints for
authenticated administrators/owners to invite new members to their team,
list valid and expired invitations or delete invite altogether.
Update will not be handled for now. Delete and recreate if needed.
We recently updated Ruff from 0.2.2 to v0.3, which introduced
Ruff 2024.2 style. This new style updated Ruff formatter's behavior,
making our make lint command fails.
Ruff 2024.2 style add a blank line after the module docstring.
Please take a look at Ruff ChangeLog to get more info.
We need a name for the user when we display the members in the
frontend. This commit adds the name column to the identity model.
We sync the Keycloak user with the identity model when the user
logs in to fill and udpate the name automatically.
Integrate 'mozilla-django-oidc' dependency, to support
Authorization Code flow, which is required by Agent Connect.
Thus, we provide a secure back channel OIDC flow, and return
to the client only a session cookie.
Done:
- Replace JWT authentication by Session based authentication in DRF
- Update Django settings to make OIDC configurations easily editable
- Add 'mozilla-django-oidc' routes to our router
- Implement a custom Django Authentication class to adapt
'mozilla-django-oidc' to our needs
'mozilla-django-oidc' routes added are:
- /authenticate
- /callback (the redirect_uri called back by the Idp)
- /logout
Create invitation model, factory and related tests to prepare back-end
for invitation endpoints. We chose to use a separate dedicated model
for separation of concerns, see
https://github.com/numerique-gouv/people/issues/25
*Broken Identity string representation
Resolving a format error in the Identity string representation caused by
potential None values in the email field. This issue was discovered when
attempting to access the User details page in the Django Admin
*Broken User creation form
The replacement of the User's username with an email led to errors in
the UserAdmin class. The base class used the 'username' field in the
'add_fieldsets' attribute. This problem was discovered while attempting to
create a new user in the Django Admin.
Make Team's Slug field non-editable in the Django admin. It avoid
UX issues by preventing accidental slug overwrites during updates.
The Slug is now displayed in the teams list view.
The admin was broken as we did not worry about it up to now. On the frontend
we want to use OIDC authentication only but for the admin, it is better if
the default authentication works as well. To allow this, we propose to add
an "email" field to the user model and make it the identifier in place of
the usual username. Some changes are necessary to make the "createsuperuser"
management command work.
We also had to fix the "oidc_user_getter" method to make it work with Keycloak.
Some tests were added to secure that everything works as expected.
Used https://github.com/openfun/joanie as boilerplate, ran a few
transformations with ChapGPT and adapted models and endpoints to
fit to my current vision of the project.