Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/wncc/SoC-Portal
Browse files Browse the repository at this point in the history
  • Loading branch information
AdvaitP10 committed Apr 11, 2024
2 parents bfba87e + 072cc07 commit 85149aa
Show file tree
Hide file tree
Showing 28 changed files with 1,118 additions and 2 deletions.
138 changes: 138 additions & 0 deletions backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# Django #
*.log
*.pot
*.pyc
__pycache__
db.sqlite3
media

# Backup files #
*.bak

# If you are using PyCharm #
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf

# AWS User-specific
.idea/**/aws.xml

# Generated files
.idea/**/contentModel.xml

# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml

# Gradle
.idea/**/gradle.xml
.idea/**/libraries

# File-based project format
*.iws

# IntelliJ
out/

# JIRA plugin
atlassian-ide-plugin.xml

# Python #
*.py[cod]
*$py.class

# Distribution / packaging
.Python build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.whl
*.egg-info/
.installed.cfg
*.egg
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
.pytest_cache/
nosetests.xml
coverage.xml
*.cover
.hypothesis/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery
celerybeat-schedule.*

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# mkdocs documentation
/site

# mypy
.mypy_cache/

# Sublime Text #
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache
*.sublime-workspace
*.sublime-project

# sftp configuration file
sftp-config.json

# Package control specific files Package
Control.last-run
Control.ca-list
Control.ca-bundle
Control.system-ca-bundle
GitHub.sublime-settings

# Visual Studio Code #
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history
Empty file added backend/accounts/__init__.py
Empty file.
5 changes: 5 additions & 0 deletions backend/accounts/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.contrib import admin
from .models import UserProfile

# Register your models here.
admin.site.register(UserProfile)
6 changes: 6 additions & 0 deletions backend/accounts/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class AccountsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'accounts'
13 changes: 13 additions & 0 deletions backend/accounts/custom_auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from rest_framework_simplejwt.authentication import JWTAuthentication


class CookieJWTAuthentication(JWTAuthentication):
def authenticate(self, request):
header = super().authenticate(request)
if header is None:
# Attempt to get token from the cookie
token = request.COOKIES.get("auth")
if token:
return self.get_user(self.get_validated_token(token)), None

return header
79 changes: 79 additions & 0 deletions backend/accounts/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import requests
from django.conf import settings
from rest_framework.response import Response
from rest_framework.exceptions import APIException
from rest_framework import status

IITB_SSO = settings.IITB_SSO


class SSOError(APIException):
"""Exception for SSO errors."""

status_code = status.HTTP_400_BAD_REQUEST
default_detail = "Something went wrong with the SSO"
default_code = "sso_error"


def fetch_from_sso(auth_code, redir, request):
"""Perform login with code and redir."""
# Get our access token
post_data = {
"code": auth_code,
"redirect_uri": redir,
"grant_type": "authorization_code",
}
post_data = (
"code="
+ auth_code
+ "&redirect_uri="
+ redir
+ "&grant_type=authorization_code"
)
print(IITB_SSO)
response = requests.post(
IITB_SSO["TOKEN_URL"],
data=post_data,
headers={
"Authorization": "Basic " + IITB_SSO["CLIENT_SECRET_BASE64"],
"Content-Type": "application/x-www-form-urlencoded",
},
verify=not settings.SSO_BAD_CERT,
allow_redirects=False,
timeout=10,
)
response_json = response.json()

# Check that we have the access token
if "access_token" not in response_json:
raise SSOError(
response_json or "SSO server did not validate request, try again",
)

# Get the user's profile
profile_response = requests.get(
IITB_SSO["PROFILE_URL"],
headers={
"Authorization": "Bearer " + response_json["access_token"],
},
verify=not settings.SSO_BAD_CERT,
timeout=10,
)
profile_json = profile_response.json()

# Check if we got at least the user's SSO id
if "id" not in profile_json:
raise SSOError(
"SSO server did not send requested info, try again",
)

# Check that we have basic details like name and roll no.
required_fields = ["first_name", "roll_number", "username"]
if not all(
[((field in profile_json) and profile_json[field]) for field in required_fields]
):
raise SSOError(
"All required fields not present",
)

return profile_json
28 changes: 28 additions & 0 deletions backend/accounts/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 4.2.6 on 2024-03-30 10:31

import accounts.models
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

initial = True

dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
]

operations = [
migrations.CreateModel(
name='UserProfile',
fields=[
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)),
('profile_picture', models.ImageField(blank=True, default='', upload_to=accounts.models.upload_to_location)),
('roll_number', models.CharField(error_messages={'unique': 'A user with that roll number already exists.'}, help_text='Required. 20 characters or fewer.', max_length=20, unique=True, verbose_name='roll number')),
('year', models.IntegerField(choices=[(1, 'First Year'), (2, 'Second Year'), (3, 'Third Year'), (4, 'Fourth Year'), (5, 'Fifth Year')], default=2)),
('department', models.CharField(blank=True, choices=[('Chemical Engineering', 'Chemical Engineering'), ('Mechanical Engineering', 'Mechanical Engineering'), ('Electrical Engineering', 'Electrical Engineering')], max_length=50, null=True)),
],
),
]
18 changes: 18 additions & 0 deletions backend/accounts/migrations/0002_alter_userprofile_department.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.2.6 on 2024-03-31 11:22

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('accounts', '0001_initial'),
]

operations = [
migrations.AlterField(
model_name='userprofile',
name='department',
field=models.CharField(blank=True, choices=[('Chemical Engineering', 'Chemical Engineering'), ('Mechanical Engineering', 'Mechanical Engineering'), ('Electrical Engineering', 'Electrical Engineering')], default='', max_length=50),
),
]
Empty file.
49 changes: 49 additions & 0 deletions backend/accounts/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from django.db import models
from django.contrib.auth.models import User


def upload_to_location(instance, filename):
return "profile_pictures/{filename}".format(filename=filename)


# Create your models here.
class UserProfile(models.Model):
user = models.OneToOneField(
User,
on_delete=models.CASCADE,
primary_key=True,
)
profile_picture = models.ImageField(
upload_to=upload_to_location, blank=True, default=""
)
roll_number = models.CharField(
"roll number",
max_length=20,
unique=True,
help_text="Required. 20 characters or fewer.",
error_messages={
"unique": "A user with that roll number already exists.",
},
)

class YearChoices(models.IntegerChoices):
YEAR_1 = 1, "First Year"
YEAR_2 = 2, "Second Year"
YEAR_3 = 3, "Third Year"
YEAR_4 = 4, "Fourth Year"
YEAR_5 = 5, "Fifth Year"

year = models.IntegerField(choices=YearChoices.choices, default=YearChoices.YEAR_2)

class DepartmentChoices(models.TextChoices):
CHEMICAL_ENGINEERING = "Chemical Engineering", "Chemical Engineering"
MECHANICAL_ENGINEERING = "Mechanical Engineering", "Mechanical Engineering"
ELECTRICAL_ENGINEERING = "Electrical Engineering", "Electrical Engineering"

department = models.CharField(
max_length=50, choices=DepartmentChoices.choices, blank=True, default=""
)
# Add more fields as required

def __str__(self):
return f"{self.roll_number} - {self.user.username}"
13 changes: 13 additions & 0 deletions backend/accounts/permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from rest_framework.permissions import BasePermission
from django.core.exceptions import ObjectDoesNotExist


class HasUserProfile(BasePermission):
message = "User must have created their profile."

def has_permission(self, request, view):
try:
request.user.userprofile # Will raise an error if the user does not have a profile
return True
except ObjectDoesNotExist:
return False
Loading

0 comments on commit 85149aa

Please sign in to comment.