-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add api.config
module for Settings
#392
Conversation
Add `fastapi-users` package with `beanie` and `oauth` tools for user management. The specific `10.4.0` version has been selected to make it compatible with `fastapi 0.68.1` package version. Signed-off-by: Jeny Sadadia <[email protected]>
Add `User` model and extend user model provided by `fastapi-users`. Add an extra field `username` and create `unique` index on it. Also add field `groups` for user groups. Also add schema for user CRUD operation. Use `ModelId` as a parent class for `UserRead` to enable json encoder for ObjectId. Use `Settings` class to rename collection name for `User` model from default `User` to `user`. This change is needed to align the collection name with `Database.COLLECTIONS`. Signed-off-by: Jeny Sadadia <[email protected]>
Implement `Database.initialize_beanie` method to initialize Beanie ODM to use `fastapi-users` tools for MongoDB. Signed-off-by: Jeny Sadadia <[email protected]>
In order to use `fastapi-users` package for MongoDB, initialize Beanie on app startup as per the package requirements. Signed-off-by: Jeny Sadadia <[email protected]>
Implement `Authentication.get_user_authentication_backend` to get authentication backend for user management. Authentication backend for `fastapi-users` is composed of two parts: Transaport and Strategy. Transport is a mechanism for token transmisson i.e. bearer or cookie. Strategy is a method to generate and secure tokens. It can be JWT, database or Redis. To accommodate user management with current API design, `Bearer` is selected as a transport method and `JWT` is selected as strategy. Signed-off-by: Jeny Sadadia <[email protected]>
Add `user_manager.py` to implement custom user management logic. Extend `BaseUserManager` provided by `fastapi-users` to have customized core logic for user management. Add database adapter `get_user_db` to create a link between user model from `fastapi-users` and API database configuration. Inject `UserManager` at a runtime in a database session. Add `email_sender` module to send verification and reset password token for user accounts via email. Add email templates. Signed-off-by: Jeny Sadadia <[email protected]>
Create an instance of `FastAPIUsers` to bind `UserManager` with authentication backend. Signed-off-by: Jeny Sadadia <[email protected]>
Register different routers provided by the package to our application. Signed-off-by: Jeny Sadadia <[email protected]>
Run pylint on newly created user related files i.e. `api.user_manager` and `api.user_models` in Github workflows. Signed-off-by: Jeny Sadadia <[email protected]>
Update GET users endpoint as per `User` model defined in `users_model.py`. Also drop `/users/profile` endpoint as the updated user schema doesn't have `profile` field. Signed-off-by: Jeny Sadadia <[email protected]>
`fastapi-users` provides inbuilt router `/users/<user-id>` for getting user matching ID. Hence, deleting `get_user_by_id` handler that serves the similar purpose. Signed-off-by: Jeny Sadadia <[email protected]>
Implement custom route for user registration to ensure unique username. The route will also convert user group names to `UserGroup` objects. Then the router will call endpoint of `register_router` provided by `fastapi-users` to create a user account. Drop old POST `/user/<username>` handler for user account creation to use this route instead. Signed-off-by: Jeny Sadadia <[email protected]>
`/login` endpoint has a field `username` that actually accepts user email address for login. The reason is `fastapi-users` uses `OAuth2PasswordRequestForm` to get login information under the hood that has `username` field. `login` handler uses `BaseUserManager.authenticate` method to authenticate user. Overload the authenticate method to use `username` for authentication instead of `email`. Signed-off-by: Jeny Sadadia <[email protected]>
Use dependency callable `FastAPIUsers.current_user` for getting current active user for authenticated routes. Use it for `/whoami`, POST `/node`, pubsub, and regression related endpoints. Signed-off-by: Jeny Sadadia <[email protected]>
Use dependency callable `FastAPIUsers.current_user` for getting current active super user for authenticated routes. Use it for POST `/user/register` endpoint which needs a superuser for creating other regular users. Signed-off-by: Jeny Sadadia <[email protected]>
Use latest `User` model schema implemented using `fastapi-users` package. Initialize Beanie as per the package requirement before inserting document to database. Signed-off-by: Jeny Sadadia <[email protected]>
Overload routes for updating users to ensure unique usernames. It is also used to get user group names as a list of strings and convert it to `UserGroup` object to insert it into DB. Removed all former user routers and update handlers to use `fastapi-users` instead. Drop `models.User` and `models.UserProfile` to use latest user model from `user_models.py`. Signed-off-by: Jeny Sadadia <[email protected]>
Now the authentication methods have been used from `fastapi-users` package. Hence, remove all the methods from `Authentication` class related to access tokens, scopes, passwords, and getting current user. Also update signature of the class constructor to drop unused variables. Rename variable `Settings.access_token_expire_minutes` to `Settings.access_token_expire_seconds` as `JWTStrategy` class takes token expiry time in seconds. Update logic to create an instance of `Authentication` class in `api.main` module. Signed-off-by: Jeny Sadadia <[email protected]>
At the moment, original `FastAPI` app instance and versioned app instance both has same name `app`. Renamed the versioned app instance in order to use original app instace for mocking dependency callable with `app.dependency_overrides`. This is required to mock calls to `get_current_user` and `get_current_superuser` for user related tests. Update `Dockerfile` to use `versioned_app` instance for running API. Signed-off-by: Jeny Sadadia <[email protected]>
Use `versioned_app` instance for creating test client instance. Update all user related tests to use latest endpoints and user schema from `fastapi-users` integration. Add environment variables related to email settings to Github actions workflow as `UserManager` needs them to initialize `EmailSender` instance. Signed-off-by: Jeny Sadadia <[email protected]>
Integrate `mongomock_motor` package to mock async mongo client for Beanie initialization. Add fixture to initialize Beanie on app startup. Remove fixtures and add methods to get current active user. Update `app.dependency_overrides` dictionary to mock dependency callable from `fastapi-users` to get users while creating `TestClient`. Update all the user related tests. Add environment variable to Github actions workflow file. Signed-off-by: Jeny Sadadia <[email protected]>
d2ebd9a
to
cc0bd43
Compare
Instead of defining multiple settings class in different API modules like `pubsub`, `auth`, `email_sender`, add `api.config` module to store all different settings classes. Signed-off-by: Jeny Sadadia <[email protected]>
cc0bd43
to
e90f890
Compare
OK I've tested this which includes the changes from #377 and it's working with a few minor fixes and tweaks. I'll prepare the follow-up PRs and merge these two so we should have all this in place today, as well as the related |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Arguably this should have been called api.settings
but that's a detail.
Replaced with #403 (rebase with just the last commit from this PR). |
On top of #377
api: add
api.config
to define various module settingsInstead of defining multiple settings class in different API modules like
pubsub
,auth
,email_sender
, addapi.config
module to store all different settings classes.