Package: tamarin-utils
Tamarin UtilsSentrysettings.pyfromtamarinimportsentry...SENTRY_KEY='<your sentry key>'SENTRY_ORGANIZATION='<your sentry organization name>'SENTRY_PROJECT='<your sentry project name>'SENTRY_ALLOWED_ALL='if true all status captured'# default FalseSENTRY_ALLOWED_STATUS='list of status that should capture'# default []sentry.init()orfromtamarinimportsentry...SENTRY_URL='<your sentry url>'SENTRY_ALLOWED_ALL='if true all status captured'# default FalseSENTRY_ALLOWED_STATUS=['<allowed status or condition>']# default []sentry.init()Elastic searchsettings.pyELASTIC_PROTOCOL='<http or https>'# default 'http'ELASTIC_HOST='<host that elastic run>'# default 'localhost'ELASTIC_PORT='<listen port>'# default 9200ELASTIC_USE_SSL=''# default FalseTIME_ZONE='<elastic timezone>'# default 'UTC'ELASTIC_ALLOWED_STATUS=['<allowed status or condition>']# default []ELASTIC_USER='<elastic username>'# default ''ELASTIC_PASSWORD='<elastic secret>'# default ''Firebasesettings.pyFIREBASE_APP_OPTIONS='<app dict options>'# default {}FIREBASE_APP_NAME='your app name'# default 'FIRESTORE_DEFAULT'Logfor use log, you must config elastic search and sentry beforeJWT Authenticationin your root urls.py file (or any other url config),
include routes for Tamarin’s
TokenObtainPairView and TokenRefreshView views:fromdjango.urlsimportpathfromtamarin.rest.authorizationimport(TamarinTokenObtainPairView,TamarinRefreshView)urlpatterns=[...,path('apiv1/accounts/token/',TamarinTokenObtainPairView.as_view(),name='token_obtain_pair'),path('apiv1/accounts/refresh/',TamarinRefreshView.as_view(),name='token_refresh'),...]SettingsSome of Tamarin’s authentication behavior can be
customized through settings variables in settings.pyfromdatetimeimporttimedeltaSIMPLE_JWT={'ACCESS_TOKEN_LIFETIME':timedelta(minutes=5),'REFRESH_TOKEN_LIFETIME':timedelta(days=1),'ROTATE_REFRESH_TOKENS':False,'BLACKLIST_AFTER_ROTATION':True,'ALGORITHM':'HS256','SIGNING_KEY':SECRET_KEY,'VERIFYING_KEY':None,'AUDIENCE':None,'ISSUER':None,'AUTH_HEADER_TYPES':('Bearer',),'USER_ID_FIELD':'id','USER_ID_CLAIM':'user_id','AUTH_TOKEN_CLASSES':('tamarin.rest.authorization.AccessToken',),'TOKEN_TYPE_CLAIM':'token_type','JTI_CLAIM':'jti','SLIDING_TOKEN_REFRESH_EXP_CLAIM':'refresh_exp','SLIDING_TOKEN_LIFETIME':timedelta(minutes=5),'SLIDING_TOKEN_REFRESH_LIFETIME':timedelta(days=1),}Database ReplicaRouterWithdatabase.router.ReplicaRouterall read queries will go to a replica
database;  all inserts, updates, and deletes will do to thedefaultdatabase.
First, defineREPLICA_DATABASESin your settings.  It should be a list of
database aliases that can be found inDATABASES:DATABASES={'default':{...},'replica-1':{...},'replica-2':{...},}REPLICA_DATABASES=['replica-1','replica-2']Then putdatabase.router.ReplicaRouterinto DATABASE_ROUTERS:DATABASE_ROUTERS=('tamarin.database.router.ReplicaRouter',)The replica databases will be chosen in round-robin fashion.
If you want to get a connection to a replica in your app, usedatabase.router.ReplicaRouterfromdjango.dbimportconnectionsfromtamarin.databaseimportrouterconnection=connections[router.get_replica()]Database PinningReplicaRouterIn some applications, the lag between the primary database receiving a
write and its replication to the replicas is enough to cause inconsistency
for the end user. For example, imagine a scenario with 1 second of replication lag.
If a user makes a forum post (to the primary) and then is redirected
to a fully-rendered view of it (from a replica) 500ms later, the view will fail.
If this is a problem in your application, consider usingmultidb.PinningReplicaRouter.
This router works in combination withmultidb.middleware.PinningRouterMiddlewareto assure that, after writing to thedefaultdatabase, future reads from the same
user agent are directed to thedefaultdatabase for a configurable length of time.PinningRouterMiddlewareidentifies database writes primarily by request type,
assuming that requests with HTTP methods that are notGET,TRACE,HEAD, orOPTIONSare writes. You can indicate that any view writes to the database by using thetamarin.database.router.db_writedecorator. This will cause the same result
as if the request were, e.g., aPOST.To usePinningReplicaRouter, put it intoDATABASE_ROUTERSin your settings:DATABASE_ROUTERS=('database.router.PinningReplicaRouter',)Then, install the middleware. It must be listed before any other middleware
which performs database writes:MIDDLEWARE_CLASSES=('multidb.middleware.PinningRouterMiddleware',...moremiddlewarehere...)PinningRouterMiddlewareattaches a cookie to any user agent who has just written.
The cookie should be set to expire at a time longer than your replication lag.
By default, its value is a conservative 15 seconds, but it can be adjusted like so:TAMARIN_PINNING_SECONDS=5If you need to change the name of the cookie, use theTAMARIN_PINNING_COOKIEsetting:TAMARIN_PINNING_COOKIE='tamarin_pin_writes'