diff --git a/api/migrations/0001_initial.py b/api/migrations/0001_initial.py new file mode 100644 index 0000000..a04ae75 --- /dev/null +++ b/api/migrations/0001_initial.py @@ -0,0 +1,33 @@ +# Generated by Django 4.1.8 on 2024-02-27 17:46 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Role', + fields=[ + ('role_id', models.AutoField(primary_key=True, serialize=False)), + ('role_name', models.CharField(max_length=100)), + ], + ), + migrations.CreateModel( + name='User', + fields=[ + ('user_id', models.AutoField(primary_key=True, serialize=False)), + ('name', models.CharField(max_length=100)), + ('password', models.CharField(max_length=100)), + ('email', models.EmailField(max_length=254, unique=True)), + ('subcomm', models.CharField(max_length=100)), + ('role_id', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='api.role')), + ], + ), + ] diff --git a/api/models.py b/api/models.py index 71a8362..ceb8b0d 100644 --- a/api/models.py +++ b/api/models.py @@ -1,3 +1,19 @@ from django.db import models -# Create your models here. +class User(models.Model): + user_id = models.AutoField(primary_key=True) + name = models.CharField(max_length=100) #default length of 100 for name fields + password = models.CharField(max_length=100) + email = models.EmailField(unique=True) + role_id = models.ForeignKey('Role', on_delete=models.SET_NULL, null=True) #assume we do not want to cascade delete + subcomm = models.CharField(max_length=100) #subcomms assumed to be a name field + + def __str__(self): + return str({"user_id": self.user_id, "name": self.name, "email": self.email, "role_id": self.role_id, "subcomm": self.subcomm}) + +class Role(models.Model): + role_id = models.AutoField(primary_key=True) + role_name = models.CharField(max_length=100) + + def __str__(self): + return str({"role_id": self.role_id, "role_name": self.role_name}) diff --git a/api/serializers.py b/api/serializers.py new file mode 100644 index 0000000..4697fce --- /dev/null +++ b/api/serializers.py @@ -0,0 +1,7 @@ +from rest_framework import serializers +from .models import User + +class UserSerializer(serializers.ModelSerializer): + class Meta: + model = User + fields = '__all__' # You may specify fields you want to include diff --git a/api/tests.py b/api/tests.py index 7ce503c..2f8f846 100644 --- a/api/tests.py +++ b/api/tests.py @@ -1,3 +1,52 @@ -from django.test import TestCase +from django.urls import reverse +from rest_framework import status +from rest_framework.test import APITestCase +from .models import User, Role -# Create your tests here. +# May need to run ALTER USER CREATEDB; in psql to allow the user to create databases +class UserTests(APITestCase): + def setUp(self): + Role.objects.create(role_name="Test Role") + roleC = Role.objects.create(role_name="Test Role 3") + User.objects.create(name="Test User 3", email="test3@example.com", password="test12345", role_id=roleC, subcomm="Subcomm3") + + def test_create_user(self): + """ + Ensure we can create a new user object. + """ + data = { + "name": "Test User", + "password": "verysecurepassword", + "email": "test@example.com", + "subcomm": "Test Subcomm", + "role_id": 1 + } + + url = reverse('user-list-create') + response = self.client.post(url, data, format='json') + + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(User.objects.count(), 2) # 1 user created in this test case + 1 from setUp + self.assertIn('Test User', [user.name for user in User.objects.all()]) + + def test_view_all_users(self): + """ + Ensure we can view all users. + """ + roleB = Role.objects.create(role_name="Test Role 2") + User.objects.create(name="Test User 2", email="test2@example.com", password="test12345", role_id=roleB, subcomm="Subcomm2") + + url = reverse('user-list-create') + response = self.client.get(url) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(len(response.data), 2) # 1 user created in this test case + 1 from setUp + + def test_view_user_by_id(self): + """ + Ensure we can view a single user by ID. + """ + user = User.objects.get(email="test3@example.com") # test3user created in setUp + url = reverse('user-detail', args=[user.user_id]) + response = self.client.get(url) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data['email'], user.email) diff --git a/api/views.py b/api/views.py index 91ea44a..3d289ab 100644 --- a/api/views.py +++ b/api/views.py @@ -1,3 +1,12 @@ -from django.shortcuts import render +from rest_framework import generics +from .models import User +from .serializers import UserSerializer + +class UserListCreate(generics.ListCreateAPIView): + queryset = User.objects.all() + serializer_class = UserSerializer + +class UserDetail(generics.RetrieveAPIView): + queryset = User.objects.all() + serializer_class = UserSerializer -# Create your views here. diff --git a/finsec_website_backend/sample.env b/finsec_website_backend/sample.env deleted file mode 100644 index a908249..0000000 --- a/finsec_website_backend/sample.env +++ /dev/null @@ -1,12 +0,0 @@ -################################################### -# THIS IS A SAMPLE FILE. DO NOT USE IN PRODUCTION # -################################################### -SECRET_KEY= - -DATABASE_URL= - -DB_NAME= -DB_USER= -DB_PASSWORD= -DB_HOST= -DB_PORT= \ No newline at end of file diff --git a/finsec_website_backend/settings.py b/finsec_website_backend/settings.py index f094362..d5dc6a0 100644 --- a/finsec_website_backend/settings.py +++ b/finsec_website_backend/settings.py @@ -14,16 +14,27 @@ from datetime import timedelta import dj_database_url -import environ import os -env = environ.Env() -environ.Env.read_env() +def read_dotenv(env_file_path): + with open(env_file_path) as f: + for line in f: + if line.startswith('#') or not line.strip(): + continue + key, value = line.strip().split('=', 1) + os.environ[key] = value + +env_file = os.path.join(os.path.dirname(__file__), '.env') + +if os.path.isfile(env_file): + read_dotenv(env_file) + +# Test if the environment variables are set +print('DB_USER IS', os.environ.get('DB_USER')) # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent - # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ @@ -87,16 +98,18 @@ # https://docs.djangoproject.com/en/4.2/ref/settings/#databases if not DEBUG: - DATABASES = {'default': dj_database_url.parse(env('DATABASE_URL'))} + DATABASES = { + 'default': dj_database_url.parse(os.environ.get('DATABASE_URL')) + } else: DATABASES = { 'default': { - 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'NAME': env("DB_NAME"), - 'USER': env("DB_USER"), - 'PASSWORD': env("DB_PASSWORD"), - 'HOST': env("DB_HOST"), - 'PORT': env("DB_PORT"), + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': os.environ.get('DB_NAME'), + 'USER': os.environ.get('DB_USER'), + 'PASSWORD': os.environ.get('DB_PASSWORD'), + 'HOST': os.environ.get('DB_HOST'), + 'PORT': os.environ.get('DB_PORT'), } } diff --git a/finsec_website_backend/urls.py b/finsec_website_backend/urls.py index e47e1f7..720aade 100644 --- a/finsec_website_backend/urls.py +++ b/finsec_website_backend/urls.py @@ -16,7 +16,10 @@ """ from django.contrib import admin from django.urls import path +from api.views import UserListCreate, UserDetail urlpatterns = [ - path('admin/', admin.site.urls), + path('admin/', admin.site.urls), #do not delete + path('users/', UserListCreate.as_view(), name='user-list-create'), + path('users//', UserDetail.as_view(), name='user-detail'), ]