diff --git a/.DS_Store b/.DS_Store index 4808ac2..b4c80e4 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index 64c7e13..31682a1 100644 --- a/.gitignore +++ b/.gitignore @@ -140,6 +140,10 @@ dmypy.json .idea *.pyc dev.env +.vscode/settings.json + +#vscode settings +.vscode/ #vscode settings .vscode/ diff --git a/CDC_Backend/.DS_Store b/CDC_Backend/.DS_Store index e1c3358..7f94099 100644 Binary files a/CDC_Backend/.DS_Store and b/CDC_Backend/.DS_Store differ diff --git a/CDC_Backend/APIs/companyUrls.py b/CDC_Backend/APIs/companyUrls.py index 4db1c55..e09de52 100644 --- a/CDC_Backend/APIs/companyUrls.py +++ b/CDC_Backend/APIs/companyUrls.py @@ -5,4 +5,5 @@ from . import companyViews urlpatterns = [ path('addPlacement/', companyViews.addPlacement, name="Add Placement"), path('verifyEmail/', companyViews.verifyEmail, name="Verify Email"), + path('getAutoFillJnf/', companyViews.autoFillJnf, name="Auto FIll JNF"), ] diff --git a/CDC_Backend/APIs/companyViews.py b/CDC_Backend/APIs/companyViews.py index 590673e..60e144c 100644 --- a/CDC_Backend/APIs/companyViews.py +++ b/CDC_Backend/APIs/companyViews.py @@ -1,6 +1,7 @@ from rest_framework.decorators import api_view from .utils import * +from .serializers import * logger = logging.getLogger('db') @@ -283,7 +284,8 @@ def verifyEmail(request): "opening_type": PLACEMENT, "company_name": opening.company_name, } - sendEmail([opening.email, CDC_MAIl_ADDRESS], COMPANY_OPENING_SUBMITTED_TEMPLATE_SUBJECT.format(id=opening.id), data, + sendEmail([opening.email, CDC_MAIl_ADDRESS], + COMPANY_OPENING_SUBMITTED_TEMPLATE_SUBJECT.format(id=opening.id), data, COMPANY_OPENING_SUBMITTED_TEMPLATE, attachment_jnf_respone) return Response({'action': "Verify Email", 'message': "Email Verified Successfully"}, @@ -298,3 +300,23 @@ def verifyEmail(request): logger.warning("Verify Email: " + str(sys.exc_info())) return Response({'action': "Verify Email", 'message': "Something went wrong"}, status=status.HTTP_400_BAD_REQUEST) + + +@api_view(['GET']) +@precheck([PLACEMENT_ID]) +def autoFillJnf(request): + try: + data = request.GET + placement_id = data.get(PLACEMENT_ID) + opening = get_object_or_404(Placement, id=placement_id) + serializer = AutofillSerializers(opening) + return Response({'action': "Get AutoFill", 'message': 'Data Found', 'placement_data': serializer.data}, + status=status.HTTP_200_OK) + except Http404: + return Response({'action': "Get AutoFill", 'message': 'Placement Not Found'}, + status=status.HTTP_404_NOT_FOUND) + except Exception as e: + traceback_str = traceback.format_exc() + logger.warning("Get AutoFill: " + traceback_str) + return Response({'action': "Get AutoFill", 'message': "Something went wrong"}, + status=status.HTTP_400_BAD_REQUEST) diff --git a/CDC_Backend/APIs/constants.py b/CDC_Backend/APIs/constants.py index 526eb9e..d2daf91 100644 --- a/CDC_Backend/APIs/constants.py +++ b/CDC_Backend/APIs/constants.py @@ -49,6 +49,9 @@ CDC_MAIl_ADDRESS = 'cdc@iitdh.ac.in' # To be Configured Properly CLIENT_ID = os.environ.get('GOOGLE_OAUTH_CLIENT_ID') # Google Login Client ID +CLIENT_SECRET = os.environ.get('GOOGLE_OAUTH_CLIENT_SECRET') # Google Login Client Secret +REDIRECT_URI = 'postmessage' # Google Login Redirect URI +OAUTH2_API_ENDPOINT = 'https://oauth2.googleapis.com/token' # Google Login OAUTH2 URL # To be Configured Properly PLACEMENT_OPENING_URL = "https://cdc.iitdh.ac.in/portal/student/dashboard/placements/{id}" # On frontend, this is the URL to be opened @@ -58,6 +61,9 @@ LINK_TO_APPLICATIONS_CSV = "https://cdc.iitdh.ac.in/storage/Application_CSV/" LINK_TO_EMAIl_VERIFICATION_API = "https://cdc.iitdh.ac.in/portal/company/verifyEmail?token={token}" PDF_FILES_SERVING_ENDPOINT = 'https://cdc.iitdh.ac.in/storage/Company_Attachments/' # TODO: Change this to actual URL +AUTH_CODE = "code" +ID_TOKEN = "id_token" +REFRESH_TOKEN = "refresh_token" EMAIL = "email" STUDENT = 'student' @@ -90,6 +96,7 @@ FIELD = "field" STATUS_ACCEPTING_APPLICATIONS = "Accepting Applications" PLACEMENT = "Placement" +PLACEMENT_ID = "placement_id" COMPANY_NAME = "company_name" ADDRESS = "address" @@ -158,7 +165,7 @@ STUDENT_APPLICATION_SUBMITTED_TEMPLATE_SUBJECT = 'CDC - Application Submitted - STUDENT_APPLICATION_UPDATED_TEMPLATE_SUBJECT = 'CDC - Application Updated - {company_name}' COMPANY_EMAIl_VERIFICATION_TEMPLATE_SUBJECT = 'Email Verification - Career Development Cell, IIT Dharwad' NOTIFY_STUDENTS_OPENING_TEMPLATE_SUBJECT = 'Placement Opportunity at {company_name}' - +REMINDER_STUDENTS_OPENING_TEMPLATE_SUBJECT = 'Reminder - Placement Opportunity at {company_name}' STUDENT_APPLICATION_SUBMITTED_TEMPLATE = 'student_application_submitted.html' COMPANY_OPENING_SUBMITTED_TEMPLATE = 'company_opening_submitted.html' STUDENT_APPLICATION_STATUS_SELECTED_TEMPLATE = 'student_application_status_selected.html' @@ -167,7 +174,7 @@ STUDENT_APPLICATION_UPDATED_TEMPLATE = 'student_application_updated.html' COMPANY_EMAIL_VERIFICATION_TEMPLATE = 'company_email_verification.html' COMPANY_JNF_RESPONSE_TEMPLATE = 'company_jnf_response.html' NOTIFY_STUDENTS_OPENING_TEMPLATE = 'notify_students_new_opening.html' - +REMINDER_STUDENTS_OPENING_TEMPLATE = 'students_opening_reminder.html' APPLICATION_CSV_COL_NAMES = ['Applied At', 'Roll No.', 'Name', 'Email', 'Phone Number', 'Branch', 'Batch', 'CPI', 'Resume', 'Selected', ] diff --git a/CDC_Backend/APIs/serializers.py b/CDC_Backend/APIs/serializers.py index ad7d9f7..19d94bc 100644 --- a/CDC_Backend/APIs/serializers.py +++ b/CDC_Backend/APIs/serializers.py @@ -188,4 +188,11 @@ class PlacementApplicationSerializerForAdmin(serializers.ModelSerializer): class ContributorSerializer(serializers.ModelSerializer): class Meta: - model = Contributor \ No newline at end of file + model = Contributor + + + +class AutofillSerializers(serializers.ModelSerializer): + class Meta: + model = Placement + fields = '__all__' \ No newline at end of file diff --git a/CDC_Backend/APIs/studentViews.py b/CDC_Backend/APIs/studentViews.py index e02e0f1..62d36b4 100644 --- a/CDC_Backend/APIs/studentViews.py +++ b/CDC_Backend/APIs/studentViews.py @@ -7,15 +7,42 @@ logger = logging.getLogger('db') @api_view(['POST']) +@precheck(required_data=[AUTH_CODE]) +@get_token() @isAuthorized(allowed_users='*') -def login(request, id, email, user_type): +def login(request, id, email, user_type, token, refresh_token): try: - return Response({'action': "Login", 'message': "Verified", "user_type": user_type}, + return Response({'action': "Login", 'message': "Verified", "user_type": user_type, "id_token": token, "refresh_token": refresh_token}, status=status.HTTP_200_OK) except: return Response({'action': "Login", 'message': "Something Went Wrong"}, status=status.HTTP_400_BAD_REQUEST) +@api_view(['POST']) +@precheck(required_data=[REFRESH_TOKEN]) +def refresh(request): + refresh_token = request.data[REFRESH_TOKEN] + data = { + 'refresh_token': refresh_token, + 'client_id': CLIENT_ID, + 'client_secret': CLIENT_SECRET, + 'redirect_uri': REDIRECT_URI, + 'grant_type': 'refresh_token' + } + response = rq.post(OAUTH2_API_ENDPOINT, data=data) + if response.status_code == 200: + id_info = id_token.verify_oauth2_token(response.json()['id_token'], requests.Request(), CLIENT_ID) + if id_info['iss'] not in ['accounts.google.com', 'https://accounts.google.com']: + raise ValueError('Wrong issuer.') + user_types = User.objects.filter(email=id_info['email']).values_list('user_type', flat=True) + return Response({'action': "Refresh Token", 'message': "Token Refreshed", "id_token": response.json()['id_token'], "user_type": user_types[0]}, + status=status.HTTP_200_OK) + else: + logger.error("refresh_token"+str(response)) + return Response({'action': "Refresh Token", 'message': "Something Went Wrong"}, + status=status.HTTP_400_BAD_REQUEST) + + @api_view(['GET']) @isAuthorized(allowed_users=[STUDENT]) diff --git a/CDC_Backend/APIs/urls.py b/CDC_Backend/APIs/urls.py index 36f929e..af80640 100644 --- a/CDC_Backend/APIs/urls.py +++ b/CDC_Backend/APIs/urls.py @@ -4,6 +4,7 @@ from . import studentViews, studentUrls, companyUrls, adminUrls urlpatterns = [ path('login/', studentViews.login, name="Login"), + path('refresh_token/', studentViews.refresh, name="Refresh Token"), path('student/', include(studentUrls)), path('company/', include(companyUrls)), path('admin/', include(adminUrls)), diff --git a/CDC_Backend/APIs/utils.py b/CDC_Backend/APIs/utils.py index be57175..63f2729 100644 --- a/CDC_Backend/APIs/utils.py +++ b/CDC_Backend/APIs/utils.py @@ -33,6 +33,38 @@ from .models import User, PrePlacementOffer, PlacementApplication, Placement, St logger = logging.getLogger('db') +def get_token(): + def decorator(view_func): + def wrapper_func(request, *args, **kwargs): + try: + authcode = request.data[AUTH_CODE] + data = { + 'code': authcode, + 'client_id': CLIENT_ID, + 'client_secret': CLIENT_SECRET, + 'redirect_uri': REDIRECT_URI, + 'grant_type': 'authorization_code' + } + r = rq.post(OAUTH2_API_ENDPOINT, data=data) + if r.status_code == 200: + response = r.json() + token = response[ID_TOKEN] + refresh_token = response[REFRESH_TOKEN] + request.META["HTTP_AUTHORIZATION"] = "Bearer " + token + request.META["MODIFIED"] = "True" + kwargs['refresh_token'] = refresh_token + return view_func(request, *args, **kwargs) + else: + return Response({'action': "Get Token", 'message': "Invalid Auth Code"}, + status=status.HTTP_400_BAD_REQUEST) + except Exception as e: + logger.warning("Get Token: " + str(sys.exc_info())) + return Response({'action': "Get Token", 'message': str(e)}, + status=status.HTTP_400_BAD_REQUEST) + return wrapper_func + return decorator + + def precheck(required_data=None): if required_data is None: required_data = [] @@ -84,7 +116,10 @@ def isAuthorized(allowed_users=None): user.last_login_time = timezone.now() user.save() if len(set(user.user_type).intersection(set(allowed_users))) or allowed_users == '*': - return view_func(request, user.id, user.email, user.user_type, *args, **kwargs) + if "MODIFIED" in headers: + return view_func(request, user.id, user.email, user.user_type, token_id, *args, **kwargs) + else: + return view_func(request, user.id, user.email, user.user_type, *args, **kwargs) else: raise PermissionError("Access Denied. You are not allowed to use this service") else: @@ -285,7 +320,7 @@ def opening_description_table_html(opening): else: # if isinstance(opening, QueryDict): details = opening keys = list(details.keys()) - newdetails = {} + newdetails = {"ID": opening.id} for key in keys: if isinstance(details[key], list): details[key] = {"details": details[key], "type": ["list"]} diff --git a/CDC_Backend/CDC_Backend/settings.py b/CDC_Backend/CDC_Backend/settings.py index 2447ee0..7df7fc3 100644 --- a/CDC_Backend/CDC_Backend/settings.py +++ b/CDC_Backend/CDC_Backend/settings.py @@ -30,7 +30,7 @@ DEBUG = os.environ.get('DEBUG') == "True" ALLOWED_HOSTS = ['cdc.iitdh.ac.in', 'localhost'] -ADMINS = [('Gowtham Sai', '190010036@iitdh.ac.in'), ('Karthik Mv', '200010030@iitdh.ac.in')] +ADMINS = [ ('Karthik Mv', '200010030@iitdh.ac.in')] # Application definition INSTALLED_APPS = [ @@ -47,7 +47,7 @@ INSTALLED_APPS = [ 'background_task', 'simple_history', 'import_export', - "django_extensions" + 'django_extensions' ] MIDDLEWARE = [ diff --git a/CDC_Backend/scripts/send_reminder_mails.py b/CDC_Backend/scripts/send_reminder_mails.py new file mode 100644 index 0000000..0048c34 --- /dev/null +++ b/CDC_Backend/scripts/send_reminder_mails.py @@ -0,0 +1,63 @@ +from APIs.models import Placement, Student, PlacementApplication, User +from APIs.utils import sendEmail, PlacementApplicationConditions +from APIs.constants import * +from django.shortcuts import get_object_or_404 +from django.utils import timezone +import time +import pytz + +REPEAT_AFTER = 10 * 60 + + +def send_reminder_mails(): + placements = Placement.objects.all() + students = Student.objects.all() + + for placement in placements.iterator(): + print("Processing placement: ", placement) + # if placement is approved and email is verified + if not (placement.offer_accepted and placement.email_verified): + continue + + # if placement is not expired + if placement.deadline_datetime < timezone.now(): + continue + + # send the reminder mail if the deadline is within 24 hours +- ReapetAfter + if timezone.now() - timezone.timedelta( + seconds=REPEAT_AFTER) <= placement.deadline_datetime - timezone.timedelta(days=1) < timezone.now() + \ + timezone.timedelta(seconds=REPEAT_AFTER): + for student in students: + try: + # if Application not found then send email + if not PlacementApplication.objects.filter(placement=placement, student=student).exists(): + if student.branch in placement.allowed_branch: + if student.degree == 'bTech' or placement.rs_eligible is True: + if PlacementApplicationConditions(student, placement)[0]: + student_user = get_object_or_404(User, id=student.id) + # change timezone to IST + deadline_datetime = placement.deadline_datetime.astimezone(pytz.timezone('Asia/Kolkata')) + data = { + "company_name": placement.company_name, + "opening_type": 'Placement', + "deadline": deadline_datetime.strftime("%A, %-d %B %Y, %-I:%M %p"), + "link": PLACEMENT_OPENING_URL.format(id=placement.id) + } + print("Sending mail to " + student_user.email, "placement id: ", placement.id) + sendEmail(student_user.email, + REMINDER_STUDENTS_OPENING_TEMPLATE_SUBJECT.format( + company_name=placement.company_name), + data, REMINDER_STUDENTS_OPENING_TEMPLATE) + + except Exception as e: + print(e) + continue + + +def run(): + while True: + print("Sleeping for", REPEAT_AFTER, "seconds") + time.sleep(REPEAT_AFTER) + print("Running send_reminder_mails()") + send_reminder_mails() + diff --git a/CDC_Backend/templates/students_opening_reminder.html b/CDC_Backend/templates/students_opening_reminder.html index 4541089..dd0b9d2 100644 --- a/CDC_Backend/templates/students_opening_reminder.html +++ b/CDC_Backend/templates/students_opening_reminder.html @@ -45,7 +45,7 @@

{{ opening_type }} Opportunity at {{ company_name }}

- Gentle reminder for the same. + Gentle reminder to fill out the application form. Interested students can apply before {{ deadline }} in the CDC-webportal.

diff --git a/README.md b/README.md index bae49a2..1c41ba8 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,8 @@ python# CDC - Backend ### Setup 1. Download the Repository to your local machine
-2. Create a Virtual Environment in the [CDC_Backend](./) folder with this command below
+2. Make Sure u have downloaded python from python.org or windows store. +3. Create a Virtual Environment in the [CDC_Backend](./) folder with this command below
`python -m venv venv` 3. Activate the environment with this command
`.\venv\Scripts\activate` (for WINDOWS)
@@ -14,6 +15,17 @@ python# CDC - Backend `pip install -r requirements.txt ` 5. Ensure that you have the PostgreSQL installed on your machine and is running on PORT **5432**
6. Make sure to give the correct database credentials in [settings.py](./CDC_Backend/CDC_Backend/settings.py)(https://www.youtube.com/watch?v=bE9h6aAky4s&t=193s) +7. Run these following commands below. (The same are there in setup.sh for linux users and setup.bat for windows users) +```cd CDC_Backend +python manage.py flush --no-input +python manage.py makemigrations +python manage.py migrate +python manage.py collectstatic --noinput +mkdir Storage +python manage.py makemigrations APIs +``` + + ### Running the Application @@ -28,13 +40,20 @@ python# CDC - Backend 1. You can access the admin panel by running the server and opening 2. Run `python manage.py createsuperuser` to create a user to access the admin panel. -3. Set up the Username and Password -4. You can log in and change the database values anytime. +3. if there is an error due to time then sync your machine time . +4. Set up the Username and Password +5. You can log in and change the database values anytime. +6. Create your id as insitute Roll No for both admin and student . +7. if you are still getting an error ,open inspect and see in network +And then recognize it +8.Check the client link in dev.env in backend and .env in frontend is the same + # Error 1.make sure that your machine time and google time are same ,if not go to setting of date and time and sync this 2.make sure u have used same id for both student and Admin that is your iitfh roll_no 3. same client link in .env of frontend or constants.py of bakcend + ### Deploying 1. Add the hosted domain name in `ALLOWED_HOSTS` in [settings.py](./CDC_Backend/CDC_Backend/settings.py) diff --git a/doc/setup/postgres.md b/doc/setup/postgres.md index d3dba5e..8941fa6 100644 --- a/doc/setup/postgres.md +++ b/doc/setup/postgres.md @@ -1,6 +1,6 @@ typical conf file for pg_hba.conf for dev work. - +``` # TYPE DATABASE USER ADDRESS METHOD # "local" is for Unix domain socket connections only @@ -13,4 +13,5 @@ host all all ::1/128 md5 # replication privilege. local replication all peer host replication all 127.0.0.1/32 ident -host replication all ::1/128 ident \ No newline at end of file +host replication all ::1/128 ident +``` diff --git a/requirements.txt b/requirements.txt index d6465e1..efc1a43 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,6 +14,7 @@ django-background-tasks==1.2.5 django-compat==1.0.15 django-cors-headers==3.11.0 django-db-logger==0.1.12 +django-extensions==3.2.1 django-import-export==2.8.0 django-simple-history==3.1.1 djangorestframework==3.13.1 diff --git a/setup.bat b/setup.bat new file mode 100644 index 0000000..26ffaf0 --- /dev/null +++ b/setup.bat @@ -0,0 +1,15 @@ + +start /wait python -m venv venv && venv\Scripts\activate && pip install -r requirements.txt &^ +echo Environment Setup Complete &^ +timeout 3 > NUL &^ +echo enter password for user postgres &^ +createdb -h localhost -p 5432 -U postgres cdc &^ +cd "CDC_Backend" &^ + +python manage.py flush --no-input &^ +python manage.py makemigrations &^ +python manage.py migrate &^ +echo Migrations complete &^ +cd .. &^ +start .\superuser.bat &^ +echo done successfully diff --git a/setup.sh b/setup.sh index 86a2bc3..aaa20b9 100644 --- a/setup.sh +++ b/setup.sh @@ -20,3 +20,11 @@ else echo "${DIR} Directory Created" fi +echo Do you want ceate credentials for super user (Y/N) ? +read create +create=${create^^} + +if [ "$create" == "Y" ]; then + ### Take action if user want to create ### + python3 manage.py createsuperuser +fi diff --git a/superuser.bat b/superuser.bat new file mode 100644 index 0000000..7afce95 --- /dev/null +++ b/superuser.bat @@ -0,0 +1,12 @@ +@echo off +set /p create="do you want to create supruser ? (Y/N) " + +cd "CDC_Backend" &^ + +if %create% equ Y ( python manage.py createsuperuser ) +if %create% equ y ( python manage.py createsuperuser ) + +python manage.py collectstatic --noinput +if exist Storage (echo Storage Directory already exists) else ( echo Creating Storage Directory... & mkdir Storage & echo Storage Directory Created) +timeout 3 > NUL +pause