Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing Files in Accounts App Causing Errors (#22) #23

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added socbackend/accounts/__init__.py
Empty file.
5 changes: 5 additions & 0 deletions socbackend/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 socbackend/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'
52 changes: 52 additions & 0 deletions socbackend/accounts/custom_auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from rest_framework_simplejwt.authentication import JWTAuthentication
import logging
logger = logging.getLogger(__name__)

import jwt
from django.conf import settings
from rest_framework.exceptions import AuthenticationFailed

logger = logging.getLogger(__name__)

class CookieJWTAuthentication(JWTAuthentication):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.user_model = get_user_model()

def authenticate(self, request):
logger.debug("Starting authentication process")

# Check for JWT in cookies
token = request.COOKIES.get('jwt')
logger.debug(f"Token from cookies: {token}")

# If not found in cookies, check the Authorization header
if not token:
auth_header = request.headers.get('Authorization')
logger.debug(f"Authorization header: {auth_header}")
if auth_header and auth_header.startswith('Bearer '):
token = auth_header.split(' ')[1]
logger.debug(f"Token from Authorization header: {token}")

if not token:
logger.debug("No token found")
return None

try:
payload = jwt.decode(token, settings.JWT_SECRET_KEY, algorithms=['HS256'])
logger.debug(f"Payload: {payload}")
except jwt.ExpiredSignatureError:
logger.error("Token has expired")
raise AuthenticationFailed('Token has expired')
except jwt.InvalidTokenError:
logger.error("Invalid token")
raise AuthenticationFailed('Invalid token')

try:
user = self.user_model.objects.get(id=payload['user_id'])
logger.debug(f"Authenticated user: {user}")
except self.user_model.DoesNotExist:
logger.error("User not found")
raise AuthenticationFailed('User not found')

return (user, None)
79 changes: 79 additions & 0 deletions socbackend/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
32 changes: 32 additions & 0 deletions socbackend/accounts/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Generated by Django 4.2.6 on 2024-04-20 08:49

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)),
('name', models.CharField(blank=True, default='', max_length=100)),
('profile_picture', models.ImageField(blank=True, default='', upload_to=accounts.models.upload_to_location)),
('phone_number', models.CharField(max_length=15)),
('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.CharField(choices=[('First Year', 'First Year'), ('Second Year', 'Second Year'), ('Third Year', 'Third Year'), ('Fourth Year', 'Fourth Year'), ('Fifth Year', 'Fifth Year'), ('M.Tech', 'M.Tech'), ('Ph.D.', 'Ph.D.')], max_length=100)),
('department', models.CharField(choices=[('Aerospace Engineering', 'Aerospace Engineering'), ('Biosciences and Bioengineering', 'Biosciences and Bioengineering'), ('Chemical Engineering', 'Chemical Engineering'), ('Civil Engineering', 'Civil Engineering'), ('Computer Science and Engineering', 'Computer Science and Engineering'), ('Earth Sciences', 'Earth Sciences'), ('Electrical Engineering', 'Electrical Engineering'), ('Energy Science and Engineering', 'Energy Science and Engineering'), ('Engineering Physics', 'Engineering Physics'), ('Humanities and Social Sciences', 'Humanities and Social Sciences'), ('Industrial Design Centre', 'Industrial Design Centre'), ('Mathematics', 'Mathematics'), ('Mechanical Engineering', 'Mechanical Engineering'), ('Metallurgical Engineering and Materials Science', 'Metallurgical Engineering and Materials Science'), ('Physics', 'Physics')], max_length=50)),
('verified', models.BooleanField(default=False)),
('verification_token', models.CharField(blank=True, default='', max_length=32)),
],
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.2.6 on 2024-05-08 23:15

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(choices=[('Aerospace Engineering', 'Aerospace Engineering'), ('Biosciences and Bioengineering', 'Biosciences and Bioengineering'), ('Chemical Engineering', 'Chemical Engineering'), ('Chemistry', 'Chemistry'), ('Civil Engineering', 'Civil Engineering'), ('Computer Science and Engineering', 'Computer Science and Engineering'), ('Earth Sciences', 'Earth Sciences'), ('Electrical Engineering', 'Electrical Engineering'), ('Energy Science and Engineering', 'Energy Science and Engineering'), ('Engineering Physics', 'Engineering Physics'), ('Environmental Science and Engineering', 'Environmental Science and Engineering'), ('Humanities and Social Sciences', 'Humanities and Social Sciences'), ('Industrial Design Centre', 'Industrial Design Centre'), ('Mathematics', 'Mathematics'), ('Mechanical Engineering', 'Mechanical Engineering'), ('Metallurgical Engineering and Materials Science', 'Metallurgical Engineering and Materials Science'), ('Physics', 'Physics')], max_length=50),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.25 on 2024-05-11 07:39

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('accounts', '0002_alter_userprofile_department'),
]

operations = [
migrations.AlterField(
model_name='userprofile',
name='department',
field=models.CharField(choices=[('Aerospace Engineering', 'Aerospace Engineering'), ('Biosciences and Bioengineering', 'Biosciences and Bioengineering'), ('Chemical Engineering', 'Chemical Engineering'), ('Chemistry', 'Chemistry'), ('Civil Engineering', 'Civil Engineering'), ('Computer Science and Engineering', 'Computer Science and Engineering'), ('Earth Sciences', 'Earth Sciences'), ('Economics', 'Economics'), ('Electrical Engineering', 'Electrical Engineering'), ('Energy Science and Engineering', 'Energy Science and Engineering'), ('Engineering Physics', 'Engineering Physics'), ('Environmental Science and Engineering', 'Environmental Science and Engineering'), ('Humanities and Social Sciences', 'Humanities and Social Sciences'), ('Industrial Design Centre', 'Industrial Design Centre'), ('Mathematics', 'Mathematics'), ('Mechanical Engineering', 'Mechanical Engineering'), ('Metallurgical Engineering and Materials Science', 'Metallurgical Engineering and Materials Science'), ('Physics', 'Physics'), ('Other', 'Other')], max_length=50),
),
]
Empty file.
49 changes: 49 additions & 0 deletions socbackend/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
from .options import DepartmentChoices, YearChoices

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,
)
name = models.CharField(max_length=100, blank=True, default="")
profile_picture = models.ImageField(
upload_to=upload_to_location, blank=True, default=""
)
phone_number = models.CharField(max_length=15, blank=False, null=False)
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.",
},
)
year = models.CharField(choices=YearChoices.choices, null=False, blank=False, max_length=100)
department = models.CharField(
max_length=50, choices=DepartmentChoices.choices, blank=False, null=False
)

verified = models.BooleanField(default=False)

verification_token = models.CharField(max_length=32, blank=True, default="")




# Add more fields as required

def __str__(self):
return f"{self.roll_number} - {self.user.username}"
37 changes: 37 additions & 0 deletions socbackend/accounts/options.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from django.db import models



class DepartmentChoices(models.TextChoices):
AEROSPACE_ENGINEERING = "Aerospace Engineering", "Aerospace Engineering"
BIOSCIENCES_AND_BIOENGINEERING = "Biosciences and Bioengineering", "Biosciences and Bioengineering"
CHEMICAL_ENGINEERING = "Chemical Engineering", "Chemical Engineering"
CHEMISTRY = "Chemistry", "Chemistry"
CIVIL_ENGINEERING = "Civil Engineering", "Civil Engineering"
COMPUTER_SCIENCE_AND_ENGINEERING = "Computer Science and Engineering", "Computer Science and Engineering"
EARTH_SCIENCES = "Earth Sciences", "Earth Sciences"
ECONOMICS= "Economics", "Economics"
ELECTRICAL_ENGINEERING = "Electrical Engineering", "Electrical Engineering"
ENERGY_SCIENCE_AND_ENGINEERING = "Energy Science and Engineering", "Energy Science and Engineering"
ENGINEERING_PHYSICS = "Engineering Physics", "Engineering Physics"
ENVIRONMENTAL_SCIENCES= "Environmental Science and Engineering", "Environmental Science and Engineering"
HUMANITIES_AND_SOCIAL_SCIENCES = "Humanities and Social Sciences", "Humanities and Social Sciences"
INDUSTRIAL_DESIGN_CENTRE = "Industrial Design Centre", "Industrial Design Centre"
MATHEMATICS = "Mathematics", "Mathematics"
MECHANICAL_ENGINEERING = "Mechanical Engineering", "Mechanical Engineering"
METALLURGICAL_ENGINEERING_AND_MATERIALS_SCIENCE = "Metallurgical Engineering and Materials Science", "Metallurgical Engineering and Materials Science"
PHYSICS = "Physics", "Physics"
OTHER= "Other", "Other"



from django.db import models

class YearChoices(models.TextChoices):
First_Year = "First Year", "First Year"
Second_Year = "Second Year", "Second Year"
Third_Year = "Third Year", "Third Year"
Fourth_Year = "Fourth Year", "Fourth Year"
Fifth_Year = "Fifth Year", "Fifth Year"
M_Tech = "M.Tech", "M.Tech"
Ph_D = "Ph.D.", "Ph.D."
32 changes: 32 additions & 0 deletions socbackend/accounts/optionsold.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from django.db import models



class DepartmentChoices(models.TextChoices):
AEROSPACE_ENGINEERING = "Aerospace Engineering", "Aerospace Engineering"
BIOSCIENCES_AND_BIOENGINEERING = "Biosciences and Bioengineering", "Biosciences and Bioengineering"
CHEMICAL_ENGINEERING = "Chemical Engineering", "Chemical Engineering"
CIVIL_ENGINEERING = "Civil Engineering", "Civil Engineering"
COMPUTER_SCIENCE_AND_ENGINEERING = "Computer Science and Engineering", "Computer Science and Engineering"
EARTH_SCIENCES = "Earth Sciences", "Earth Sciences"
ELECTRICAL_ENGINEERING = "Electrical Engineering", "Electrical Engineering"
ENERGY_SCIENCE_AND_ENGINEERING = "Energy Science and Engineering", "Energy Science and Engineering"
ENGINEERING_PHYSICS = "Engineering Physics", "Engineering Physics"
HUMANITIES_AND_SOCIAL_SCIENCES = "Humanities and Social Sciences", "Humanities and Social Sciences"
INDUSTRIAL_DESIGN_CENTRE = "Industrial Design Centre", "Industrial Design Centre"
MATHEMATICS = "Mathematics", "Mathematics"
MECHANICAL_ENGINEERING = "Mechanical Engineering", "Mechanical Engineering"
METALLURGICAL_ENGINEERING_AND_MATERIALS_SCIENCE = "Metallurgical Engineering and Materials Science", "Metallurgical Engineering and Materials Science"
PHYSICS = "Physics", "Physics"


from django.db import models

class YearChoices(models.TextChoices):
First_Year = "First Year", "First Year"
Second_Year = "Second Year", "Second Year"
Third_Year = "Third Year", "Third Year"
Fourth_Year = "Fourth Year", "Fourth Year"
Fifth_Year = "Fifth Year", "Fifth Year"
M_Tech = "M.Tech", "M.Tech"
Ph_D = "Ph.D.", "Ph.D."
13 changes: 13 additions & 0 deletions socbackend/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
Loading