diff --git a/npsat_backend/settings.py b/npsat_backend/settings.py index a23184d..9b1925e 100644 --- a/npsat_backend/settings.py +++ b/npsat_backend/settings.py @@ -9,6 +9,7 @@ """ from npsat_backend.local_settings import * +from datetime import timedelta # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/ @@ -48,9 +49,16 @@ "npsat_manager", "rest_framework", "rest_framework.authtoken", + "rest_framework_simplejwt.token_blacklist", #'drf_yasg', # django rest framework schema generator ] +REST_FRAMEWORK = { + 'DEFAULT_AUTHENTICATION_CLASSES': ( + 'rest_framework_simplejwt.authentication.JWTAuthentication', + ) +} + #set settings.ALLOWED_HOSTS if DEBUG is False --Michael if DEBUG: INSTALLED_APPS += ("corsheaders",) @@ -221,3 +229,45 @@ }, }, } + +# SECURITY WARNING: keep the secret key used in production secret! +# SECRET_KEY = 'cy-$09=nyil!_ohoaz^9gs*3-ue4ls-0ibmg!b%%p9j5j)%0t1' + +# SIMPLE_JWT = { +# "ACCESS_TOKEN_LIFETIME": timedelta(minutes=5), +# "REFRESH_TOKEN_LIFETIME": timedelta(days=100), +# "ROTATE_REFRESH_TOKENS": True, +# "BLACKLIST_AFTER_ROTATION": True, +# "UPDATE_LAST_LOGIN": False, + +# "ALGORITHM": "HS256", +# "VERIFYING_KEY": "", +# "AUDIENCE": None, +# "ISSUER": None, +# "JSON_ENCODER": None, +# "JWK_URL": None, +# "LEEWAY": 0, + +# "AUTH_HEADER_TYPES": ("Bearer",), +# "AUTH_HEADER_NAME": "HTTP_AUTHORIZATION", +# "USER_ID_FIELD": "id", +# "USER_ID_CLAIM": "user_id", +# "USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule", + +# "AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",), +# "TOKEN_TYPE_CLAIM": "token_type", +# "TOKEN_USER_CLASS": "rest_framework_simplejwt.models.TokenUser", + +# "JTI_CLAIM": "jti", + +# "SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp", +# "SLIDING_TOKEN_LIFETIME": timedelta(minutes=5), +# "SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1), + +# "TOKEN_OBTAIN_SERIALIZER": "npsat_manager.serializers.MyTokenObtainPairSerializer", +# "TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSerializer", +# "TOKEN_VERIFY_SERIALIZER": "rest_framework_simplejwt.serializers.TokenVerifySerializer", +# "TOKEN_BLACKLIST_SERIALIZER": "rest_framework_simplejwt.serializers.TokenBlacklistSerializer", +# "SLIDING_TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainSlidingSerializer", +# "SLIDING_TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSlidingSerializer", +# } \ No newline at end of file diff --git a/npsat_backend/urls.py b/npsat_backend/urls.py index fc3b717..06d47aa 100644 --- a/npsat_backend/urls.py +++ b/npsat_backend/urls.py @@ -22,6 +22,10 @@ from rest_framework import permissions from rest_framework.schemas import get_schema_view as drf_get_schema_view +from rest_framework_simplejwt.views import ( + TokenRefreshView, +) + # from drf_yasg.views import get_schema_view # from drf_yasg import openapi @@ -51,6 +55,8 @@ urlpatterns = [ path("admin/", admin.site.urls), + path('api/token/', views.MyTokenObtainPairView.as_view(), name='token_obtain_pair'), + path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), re_path(r"^api/", include(router.urls)), re_path( r"^api-token-auth/", views.CustomAuthToken.as_view() diff --git a/npsat_manager/data/scenarios/MantisScenariosNames.csv b/npsat_manager/data/scenarios/MantisScenariosNames.csv index 83cb87f..536c8eb 100644 --- a/npsat_manager/data/scenarios/MantisScenariosNames.csv +++ b/npsat_manager/data/scenarios/MantisScenariosNames.csv @@ -1,13 +1,15 @@ Category,Code name,User friendly name,Short description,Long description,url -Load Scenario,GNLM,GNLM,Generalized Nitrogen Loading Model,,http://ucd-cws.github.io/nitrates/ +Load Scenario,GNLM,GNLM,"Groundwater Nitrogen Loading Model (Harter et al., 2017)",,http://ucd-cws.github.io/nitrates/ Load Scenario,SWAT1,Baseline,,, Load Scenario,SWAT2,High Fertilization,,, Load Scenario,SWAT3,High Irrigation,,, Load Scenario,SWAT4,High Irrigation and High Fertilization,,, -Unsaturated Scenario,C2VSIM_SPRING_2000,Typical vadose zone thickness (spring 2000),Based on 2000 spring data from the C2Vsim fine grid model ,,gwt.ucdavis.edu -Unsaturated Scenario,C2VSIM_SPRING_2015,Drought vadose zone thickness (spring 2015),Based on 2015 spring data from the C2Vsim fine grid model,,gwt.ucdavis.edu -Flow Scenario,C2VSIM_III_03,C2Vsim,"This scenario is based on a long-term average of C2VSim flow conditions. Flow conditions are averaged over separate, balanced periods for each of the three large regions, Sacramento Valley, San Joaquin Valley, and Tulare Lake Basin. (A CVHM based flow scenario is awaiting release of CVHM 2).",,gwt.ucdavis.edu -Flow Scenario,CVHMRun01,CVHM(currently unavailable),Simulation based on CVHM average flow conditions. Each basin has been averaged on a different period,,gwt.ucdavis.edu -Well Type Scenario,VI,Public Supply Wells and Irrigation Wells,Computes nitrate-N at large production wells,This scenario predicts the nitrate-N outcome at all large production wells - irrigation wells and public supply wells. These wells are explicitly represented in the underlying flow model as pumping wells. Their specific location is precise to the township-section (1 square mile) and randomized within the section. The well pumping rate, screen length and depth corresponds to reported values, where available, or to a simulated, randomized values that are typical for wells in the corresponding groundwater sub-basin., -Well Type Scenario,VD,Domestic Wells,Computes nitrate-N at domestic wells,This scenario predicts the nitrate-N outcome at all domestic wells known to California DWR. These wells are assumed to have very low pumping rates. Their specific location is precise to the township-section (1 square mile) and randomized within the section. The well screen length and depth corresponds to reported values, where available, or to a simulated, randomized values that are typical for wells in the corresponding groundwater sub-basin., -Well Type Scenario,VM,Virtual Shallow Monitoring Well Network Grid(currently unavailable),Computes nitrate-N in a virtual monitoring well network,This scenario predicts the nitrate-N outcome at hypothetical monitoring wells in the shallow part of the aquifer. Monitoring wells are placed every 165 ft and "measure" the average nitrate-N concentration across the first 200 ft below the water table., \ No newline at end of file +Unsaturated Scenario,CVHM2_MAR24,CVHM2 Typical vadose zone thickness,Based on CVHM average water level data conditioned on average water level data from 2011 - 2023,,https://github.com/UCD-GW-Nitrate/cv-unsat/blob/main/ConditionCVHM_WaterLevel.ipynb +Unsaturated Scenario,C2VSIM_MAR24,C2VSIM Typical vadose zone thickness,Based on C2VSIM average water level data conditioned on average water level data from 2011 - 2023,,https://github.com/UCD-GW-Nitrate/cv-unsat/blob/main/ConditionC2VSim_WaterLevel.ipynb +Flow Scenario,CVHM2_MAR24_Padj,CVHM2 with Pumping adjusted to match the Recharge,Simulation based on CVHM2 average flow conditions for the period 2009 - 2019,, +Flow Scenario,CVHM2_MAR24_Radj,CVHM2 with Recharge adjusted to match the Pumping,Simulation based on CVHM2 average flow conditions for the period 2009 - 2019,, +Flow Scenario,C2VSIM_MAR24_Padj,C2VSIM with Pumping adjusted to match the Recharge,Simulation based on CVHM2 average flow conditions for the period 2000 - 2015,, +Flow Scenario,C2VSIM_MAR24_Radj,C2VSIM with Recharge adjusted to match the Pumping,Simulation based on CVHM2 average flow conditions for the period 2000 - 2015,, +Well Type Scenario,VI,Public Supply Wells and Irrigation Wells,Computes nitrate-N at large production wells,"This scenario predicts the nitrate-N outcome at all large production wells - irrigation wells and public supply wells. These wells are explicitly represented in the underlying flow model as pumping wells. Their specific location is precise to the township-section (1 square mile) and randomized within the section. The well pumping rate, screen length and depth corresponds to reported values, where available, or to a simulated, randomized values that are typical for wells in the corresponding groundwater sub-basin. ", +Well Type Scenario,VD,Domestic Wells,Computes nitrate-N at domestic wells,"This scenario predicts the nitrate-N outcome at all domestic wells known to California DWR. These wells are assumed to have very low pumping rates. Their specific location is precise to the township-section (1 square mile) and randomized within the section. The well screen length and depth corresponds to reported values, where available, or to a simulated, randomized values that are typical for wells in the corresponding groundwater sub-basin. ", +Well Type Scenario,VM,Virtual Shallow Monitoring Well Network Grid,Computes nitrate-N in a virtual monitoring well network,"This scenario predicts the nitrate-N outcome at hypothetical monitoring wells in the shallow part of the aquifer. Monitoring wells are placed every 165 ft and ""measure"" the average nitrate-N concentration across the first 200 ft below the water table. ", \ No newline at end of file diff --git a/npsat_manager/serializers.py b/npsat_manager/serializers.py index 4d10612..9895505 100644 --- a/npsat_manager/serializers.py +++ b/npsat_manager/serializers.py @@ -6,7 +6,15 @@ from npsat_backend import local_settings from django.db.models import Q from django.contrib.auth.models import User +from rest_framework_simplejwt.serializers import TokenObtainPairSerializer +class MyTokenObtainPairSerializer(TokenObtainPairSerializer): + @classmethod + def get_token(cls, user): + token = super().get_token(user) + token['username'] = user.username + + return token class CropSerializer(serializers.ModelSerializer): class Meta: diff --git a/npsat_manager/views.py b/npsat_manager/views.py index bf9eb11..1bd8ffb 100644 --- a/npsat_manager/views.py +++ b/npsat_manager/views.py @@ -24,9 +24,13 @@ from django.http import HttpResponse from django.db.models import Q from django.contrib.auth.models import User +from rest_framework_simplejwt.views import TokenObtainPairView log = logging.getLogger("npsat.manager") +class MyTokenObtainPairView(TokenObtainPairView): + serializer_class = serializers.MyTokenObtainPairSerializer + class CustomAuthToken(ObtainAuthToken): """ Via https://www.django-rest-framework.org/api-guide/authentication/ @@ -359,7 +363,7 @@ def retrieve(self, request, *args, **kwargs): elif not base_model and include_base: raise APIException("Base model is not found!") else: - serializer = self.get_serializer(instance, many=True) + serializer = self.get_serializer(instance) return Response(serializer.data) def list(self, response): diff --git a/requirements.txt b/requirements.txt index abbb30e..e71202d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,3 +5,4 @@ django-cors-headers six waitress psycopg2 +djangorestframework-simplejwt \ No newline at end of file