chapps.rest.routers.users module
User record management implemented by factories
This module defines API routes for managing User records, and defines the JoinAssoc data to describe the relationship between User records and other record types: Domain, Email, and Quota.
As such, this is the only router where the factories are used to create or update records with multiple associations. It seems a good opportunity for another example.
- chapps.rest.routers.users.api = <fastapi.routing.APIRouter object>
The API router for User record maintenance
This router is once again full of calls to the factories in the
commonmodule. The User model is the most connected to other things, however, and so seems like a good spot for examples related to associations.Creating Users
When creating a User record, it seems likely that the caller might like to automatically associate the new User with an existing Quota record, and at least one Domain record, perhaps even an Email record. The factory will provide a coroutine which will optionally accept ID lists for these associations. That is to say, the coroutine will treat them as optional arguments and do nothing if they are not provided.
All of the logic and magic behind making this go smoothly is hidden within the
JoinAssocclass. We simply provide a list of these associations to the factory and it handles the rest:api.post( "/", status_code=201, response_model=UserResp, responses={status.HTTP_409_CONFLICT: {"description": "Unique key error."}}, )(create_item(User, response_model=UserResp, assoc=user_join_assoc))
In the above example, the FastAPI code for specifying details about the POST route takes up more space than the factory call to obtain the actual User creation coroutine.
The definition of
user_join_assocmay be found below. It is a list containing references to all threeJoinAssocinstances, relating to a Quota and lists of Domain and Email records.Handling Associations
Sometimes there is a need to remove a specific association from a list, or add one or a handful. It would be helpful if it were not necessary to obtain or manufacture a list of IDs in order to use a replacement-type edit such as the basic model update route. The User model has a number of different associations to manage, so here is an example of adding domains:
api.put("/{item_id}/domains/", response_model=TextResp)( adjust_associations( User, assoc=[user_domains_assoc], assoc_op=AssocOperation.add ) )
I chose to use PUT because it is associated with partial updates. Within the API router wrapper, we use a call to the
adjust_associations()route factory, which returns a coroutine which will take a User ID and a list of Domain IDs as arguments. When invoked via the API, that coroutine will ensure that all the existing Domain records listed are associated to the User.IntegrityErroris ignored during the process, so any attempts to add an existing association or to add a nonexistent Domain will not raise errors – all existing Domain records identified by ID will be associated to the User, and other associations to that User will be preserved.- Parameters
scope (MutableMapping[str, Any]) –
receive (Callable[[], Awaitable[MutableMapping[str, Any]]]) –
send (Callable[[MutableMapping[str, Any]], Awaitable[None]]) –
- Return type
None
- async chapps.rest.routers.users.map_usernames_to_quota_ids(user_ids)[source]
Map User identfiers onto Quota ids
If a display requires a large matrix of users with their quota settings, this routine may be helpful. The Quota records may be fetched before or after, just once for each kind of quota, and then cross-referenced much more efficiently than requesting each separately.
The
responsecontains a list of JSON objects (hashes or dictionaries), with the keysuser_nameandquota_id. Only existing users are returned, possibly withquota_idset toNoneif the user has no quota policy assigned. They are sorted by the user’s ID value.
- async chapps.rest.routers.users.map_usernames_to_domain_ids(user_ids)[source]
Map User identfiers onto Domain id lists
If a display requires a large matrix of users with their domain authorizations, this routine may be helpful. The Domain records may be fetched before or after, just once for each domain, and then cross-referenced much more efficiently than requesting each separately.
The
responsecontains a list of JSON objects (hashes or dictionaries), with the keysuser_nameanddomain_ids. Only existing users are returned, possibly withdomain_idsset toNoneif the user has no domain authorizations. They are sorted by the user’s ID value.
- async chapps.rest.routers.users.map_usernames_to_email_ids(user_ids)[source]
Map User identfiers onto Email id lists
If a display requires a large matrix of users with their email authorizations, this routine may be helpful. The Email records may be fetched before or after, just once for each email, and then cross-referenced much more efficiently than requesting each separately.
The
responsecontains a list of JSON objects (hashes or dictionaries), with the keysuser_nameandemail_ids. Only existing users are returned, possibly withemail_idsset toNoneif the user has no email authorizations. They are sorted by the user’s ID value.