diff --git a/tdrs-backend/docker-compose.local.yml b/tdrs-backend/docker-compose.local.yml index 3c8e76317..d2cd5289c 100644 --- a/tdrs-backend/docker-compose.local.yml +++ b/tdrs-backend/docker-compose.local.yml @@ -36,6 +36,7 @@ services: environment: - discovery.type=single-node - xpack.security.enabled=false + - cluster.routing.allocation.disk.threshold_enabled=false - logger.discovery.level=debug ports: - 9200:9200 diff --git a/tdrs-backend/tdpservice/data_files/views.py b/tdrs-backend/tdpservice/data_files/views.py index f01bb5be6..ebc769172 100644 --- a/tdrs-backend/tdpservice/data_files/views.py +++ b/tdrs-backend/tdpservice/data_files/views.py @@ -54,6 +54,7 @@ class DataFileViewSet(ModelViewSet): def create(self, request, *args, **kwargs): """Override create to upload in case of successful scan.""" + logger.debug(f"{self.__class__.__name__}: {request}") response = super().create(request, *args, **kwargs) # only if file is passed the virus scan and created successfully will we perform side-effects: @@ -61,6 +62,7 @@ def create(self, request, *args, **kwargs): # * Upload to ACF-TITAN # * Send email to user + logger.debug(f"{self.__class__.__name__}: status: {response.status_code}") if response.status_code == status.HTTP_201_CREATED or response.status_code == status.HTTP_200_OK: user = request.user data_file_id = response.data.get('id') @@ -109,6 +111,7 @@ def create(self, request, *args, **kwargs): if len(recipients) > 0: send_data_submitted_email(list(recipients), data_file, email_context, subject) + logger.debug(f"{self.__class__.__name__}: return val: {response}") return response def get_s3_versioning_id(self, file_name, prefix): diff --git a/tdrs-backend/tdpservice/users/api/authorization_check.py b/tdrs-backend/tdpservice/users/api/authorization_check.py index 57ed30527..3ac867be0 100644 --- a/tdrs-backend/tdpservice/users/api/authorization_check.py +++ b/tdrs-backend/tdpservice/users/api/authorization_check.py @@ -21,6 +21,8 @@ class AuthorizationCheck(APIView): def get(self, request, *args, **kwargs): """Handle get request and verify user is authorized.""" + logger.debug(f"{self.__class__.__name__}: {request} {request.user} {args} {kwargs}") + user = request.user serializer = UserProfileSerializer(user) diff --git a/tdrs-backend/tdpservice/users/authentication.py b/tdrs-backend/tdpservice/users/authentication.py index d238771ff..4002f440c 100644 --- a/tdrs-backend/tdpservice/users/authentication.py +++ b/tdrs-backend/tdpservice/users/authentication.py @@ -12,10 +12,13 @@ class CustomAuthentication(BaseAuthentication): @staticmethod def authenticate(username=None, login_gov_uuid=None, hhs_id=None): """Authenticate user with the request and username.""" + # TODO: Provide separate implementations for two unrelated workflows + # both using this method. (The latter appears to always fail.) + # References: + # tdpservice/users/api/login.py:TokenAuthorizationOIDC.handleUser + # https://www.django-rest-framework.org/api-guide/authentication User = get_user_model() - logging.debug("CustomAuthentication::authenticate:hhs_id {}".format(hhs_id)) - logging.debug("CustomAuthentication::authenticate:login_gov_uuid {}".format(login_gov_uuid)) - logging.debug("CustomAuthentication::authenticate:username {}".format(username)) + logging.debug(f"CustomAuthentication::authenticate: {username}, {login_gov_uuid}, {hhs_id}") try: if hhs_id: try: diff --git a/tdrs-backend/tdpservice/users/management/commands/generate_dev_user.py b/tdrs-backend/tdpservice/users/management/commands/generate_dev_user.py new file mode 100755 index 000000000..fcb4932a0 --- /dev/null +++ b/tdrs-backend/tdpservice/users/management/commands/generate_dev_user.py @@ -0,0 +1,34 @@ +"""generate_dev_user command.""" + +from django.contrib.auth import get_user_model +from django.contrib.auth.models import Group +from django.core.management import BaseCommand + +User = get_user_model() + +email = "dev@test.com" +pswd = "pass" +first = "Jon" +last = "Tester" + +class Command(BaseCommand): + """Command class.""" + + def handle(self, *args, **options): + """Generate dev user if it doesn't exist.""" + try: + user = User.objects.get(username=email) + print(f"Found {vars(user)}") + except User.DoesNotExist: + group = Group.objects.get(name="Developer") + user = User.objects.create(username=email, + email=email, + password=pswd, + is_superuser=True, + is_staff=True, + first_name=first, + last_name=last, + stt_id=31, + account_approval_status="Approved") + user.groups.add(group) + print(f"Created {vars(user)}") diff --git a/tdrs-backend/tdpservice/users/permissions.py b/tdrs-backend/tdpservice/users/permissions.py index 81e54fe54..31106304c 100644 --- a/tdrs-backend/tdpservice/users/permissions.py +++ b/tdrs-backend/tdpservice/users/permissions.py @@ -8,6 +8,9 @@ from collections import ChainMap from copy import deepcopy from typing import List, Optional, TYPE_CHECKING +import logging + +logger = logging.getLogger(__name__) if TYPE_CHECKING: # pragma: no cover @@ -126,6 +129,7 @@ class IsApprovedPermission(permissions.DjangoModelPermissions): def has_permission(self, request, view): """Return True if the user has been assigned a group and is approved.""" + logging.debug(f"{self.__class__.__name__}: {request} ; {view}") return (request.user.groups.first() is not None and request.user.account_approval_status == AccountApprovalStatusChoices.APPROVED) @@ -160,6 +164,8 @@ def has_permission(self, request, view): Data Analyst will only have permission to files within their STT and a Regional Manager will only have permission to files within their region. """ + logging.debug(f"{self.__class__.__name__}: {request} ; {view}") + # Checks for existence of `data_files.view_datafile` Permission has_permission = super().has_permission(request, view) diff --git a/tdrs-frontend/.env b/tdrs-frontend/.env index 087144285..882a4aafa 100644 --- a/tdrs-frontend/.env +++ b/tdrs-frontend/.env @@ -4,6 +4,9 @@ # WARNING: This file is checked in to source control, do NOT store any secrets in this file # +# Uncomment for local dev only! +#REACT_APP_DEVAUTH=dev@test.com + # The hostname behind the tdrs-backend Django app REACT_APP_BACKEND_HOST=http://127.0.0.1:8080 diff --git a/tdrs-frontend/docker-compose.yml b/tdrs-frontend/docker-compose.yml index d75772fa5..23c0a0669 100644 --- a/tdrs-frontend/docker-compose.yml +++ b/tdrs-frontend/docker-compose.yml @@ -7,7 +7,7 @@ services: ports: - 8090:8090 networks: - - local + - default volumes: - ./reports:/zap/wrk/:rw - ../scripts/zap-hook.py:/zap/scripts/zap-hook.py:ro @@ -21,7 +21,6 @@ services: - 3000:80 - 8080:8080 networks: - - local - default volumes: - ./:/home/node/app @@ -29,6 +28,7 @@ services: - NGINX_FRONTEND=tdp-frontend - BACK_END=web - LOCAL_DEV=true + - REACT_APP_DEVAUTH=${REACT_APP_DEVAUTH} command: > /bin/sh -c "echo 'starting nginx' && @@ -42,9 +42,6 @@ services: && nginx -g 'daemon off;'" networks: - local: - driver: bridge - default: external: name: external-net diff --git a/tdrs-frontend/src/components/Profile/Profile.jsx b/tdrs-frontend/src/components/Profile/Profile.jsx index 232fc3470..5ae65cdeb 100644 --- a/tdrs-frontend/src/components/Profile/Profile.jsx +++ b/tdrs-frontend/src/components/Profile/Profile.jsx @@ -12,7 +12,7 @@ import { function Profile() { const user = useSelector((state) => state.auth.user) // Most higher-env users will only have a single role, so just grab the first one. - const primaryRole = user?.roles[0] + const primaryRole = user?.roles?.[0] const missingAccessRequest = useSelector(accountIsMissingAccessRequest) const isAccessRequestPending = useSelector(accountIsInReview) diff --git a/tdrs-frontend/src/index.js b/tdrs-frontend/src/index.js index 3a2f2060c..809c03c6c 100644 --- a/tdrs-frontend/src/index.js +++ b/tdrs-frontend/src/index.js @@ -24,8 +24,28 @@ axios.defaults.xsrfCookieName = 'csrftoken' axios.defaults.xsrfHeaderName = 'X-CSRFToken' axios.defaults.withCredentials = true +function devLogin(devEmail) { + const BACKEND_URL = process.env.REACT_APP_BACKEND_URL + axios + .post(`${BACKEND_URL}/login/cypress`, { + username: devEmail, + token: 'local-cypress-token', + }) + .then(function (response) { + console.log(response) + }) + .catch(function (error) { + console.log(error) + }) + store.dispatch({ type: 'SET_AUTH', payload: { devEmail } }) + console.log(`dispatched SET_AUTH(${devEmail})`) +} + // call auth_check const store = configureStore() +if (process.env.REACT_APP_DEVAUTH && !store.getState().auth?.user) { + devLogin(process.env.REACT_APP_DEVAUTH) +} store.dispatch(fetchAuth()) // if (window.location.href.match(/https:\/\/.*\.app\.cloud\.gov/)) {