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

communities added #23

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
4 changes: 2 additions & 2 deletions Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ RUN BUILD_DEPS=" \
COPY --chown=django:django . .

RUN mkdir /static && chown -R django:django /static
RUN mkdir /app/media && chown -R django:django /app/media
#RUN mkdir /app/media && chown -R django:django /app/media

USER django:django
# USER django:django

ENTRYPOINT [ "/app/scripts/docker/entrypoint-dev.sh" ]
2 changes: 2 additions & 0 deletions api/controllers/club_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ def create_club(name, abstract, link, head, uploaded_file_url):
"""
try:
club_member_privilege = ClubMemberPrivilege.objects.filter(name = "Admin")
print(club_member_privilege)
if club_member_privilege.exists():
print(name, head, abstract, link, uploaded_file_url)
club = Club.objects.create(name = name, abstract = abstract, link=link, head = head, image = uploaded_file_url)
ClubMemberRelationship.objects.create(club = club, user = head, privilege = club_member_privilege[0])
return True
Expand Down
21 changes: 21 additions & 0 deletions api/controllers/community_utilities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from api.models import Community, CommunityMemberPrivilege, CommunityMemberRelationship
import logging

logger = logging.getLogger(__name__)

def create_community(name, abstract, link, head, uploaded_file_url):
"""
Helper to create club and assign club user relationship
"""
try:
community_member_privilege = CommunityMemberPrivilege.objects.filter(name = "Admin")
if community_member_privilege.exists():
community = Community.objects.create(name = name, abstract = abstract, link=link, head = head, image = uploaded_file_url)
CommunityMemberRelationship.objects.create(community = community, user = head, privilege = community_member_privilege[0])
return True
else:
logger.error("Admin access not found")
return False
except Exception as e:
logger.error(e)
return False
65 changes: 65 additions & 0 deletions api/decorators/community_permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import logging
from django.contrib.sessions.models import Session
from api.controllers.response_format import unauthorized_response, error_response
from api.models import User, Community, CommunityMemberRelationship, ClubMemberPrivilege
from django.http import HttpRequest
logger = logging.getLogger('django')

def IsAdminDec(view):
'''
Checks if is_admin to create projects.
'''

def wrapper(*args, **kwargs):
try:
request = args[0]
assert isinstance(request, HttpRequest)
user_id = request.session.get('user_id')
session_key = request.session.session_key
user_session = Session.objects.get(pk=session_key)
assert user_session.get_decoded().get('user_id') == user_id
user = request.user
if user.is_admin:
request.is_admin = True
else:
request.is_admin = False
except Exception as e:
logger.info('IsAdmin Decorator: Unauthorized response')
return unauthorized_response()
return view(*args, **kwargs)
return wrapper

def CheckAccessPrivilegeDec(view):
'''
Checks the Access Privilege and puts it in request.
'''

def wrapper(*args, **kwargs):
try:
print("ChkAccessPriv")
request = args[0]
assert isinstance(request, HttpRequest)
user_id = request.session.get('user_id')
session_key = request.session.session_key
user_session = Session.objects.get(pk=session_key)
assert user_session.get_decoded().get('user_id') == user_id
user = request.user
name = request.POST.get("name")

try:
community = Community.objects.get(name=name)
except Community.DoesNotExist:
return error_response("Community does not exist")

try:
community_member_relationship = CommunityMemberRelationship.objects.get(user=user,community=community)
except CommunityMemberRelationship.DoesNotExist:
return error_response("User is not a member of the community")

request.access_privilege = community_member_relationship.privilege.name

except Exception as e:
logger.info('CheckAccessPrivilege Decorator: Unauthorized response')
return unauthorized_response()
return view(*args, **kwargs)
return wrapper
49 changes: 49 additions & 0 deletions api/migrations/0002_community_communitymemberprivilege_and_more.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Generated by Django 4.1.5 on 2023-01-30 05:04

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


class Migration(migrations.Migration):

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

operations = [
migrations.CreateModel(
name='Community',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('name', models.CharField(default=None, max_length=255)),
('abstract', models.TextField(max_length=10000.0)),
('link', models.CharField(max_length=100)),
('image', models.FileField(blank=True, null=True, upload_to='media/')),
('head', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'ordering': ['-created_at', '-updated_at'],
'abstract': False,
},
),
migrations.CreateModel(
name='CommunityMemberPrivilege',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('code', models.IntegerField(choices=[(1, 'View'), (2, 'Admin')])),
('name', models.CharField(max_length=25)),
],
),
migrations.CreateModel(
name='CommunityMemberRelationship',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('community', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.community')),
('privilege', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='api.communitymemberprivilege')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
41 changes: 41 additions & 0 deletions api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,47 @@ def create_superuser(self, email, name, password, **extra_details):

return self._create_user(email, name, password, **extra_details)

class CommunityMemberRelationship(models.Model):
community = models.ForeignKey("community", on_delete=models.CASCADE)
user = models.ForeignKey("User", on_delete=models.CASCADE)
privilege = models.ForeignKey("CommunityMemberPrivilege", on_delete=models.PROTECT)

class CommunityMemberPrivilege(models.Model):
"""
Different permission levels for the members
of a project.
1. View (Default): No Write or edit access, can only
view the contents of the page.
2. Admin : Can add members to users and assign privilege to the users.
"""

class AvailablePrivileges(models.IntegerChoices):
"""Text Choice for allowed privileges."""

VIEW = 1, _("View")
ADMIN = 2, _("Admin")

code = models.IntegerField(choices=AvailablePrivileges.choices)

# human readable privilege name
name = models.CharField(max_length=25)

class Community(TimestampedModel):
name = models.CharField(max_length=255, default=None, unique=False)

abstract = models.TextField(max_length=1e4)

link = models.CharField(max_length=100)

image = models.FileField(null=True,blank=True,upload_to='media/')

head = models.ForeignKey("User", on_delete=models.CASCADE)

def __str__(self):
"""Returns name of club"""
# TODO
pass


class User(AbstractBaseUser, PermissionsMixin, TimestampedModel):
"""User Model"""
Expand Down
17 changes: 15 additions & 2 deletions api/urls.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.urls import re_path as url
from .views import user, project, club
from .views import user, project, club ,community

# namespacing app
app_name = 'api'
Expand Down Expand Up @@ -30,7 +30,8 @@
url('project/edit', project.Edit.as_view(), name='project-edit'),
#Tags
# url('project/tags', project.Tags.as_view(), name='tags'),

url('community/edit', community.Edit.as_view(), name='community-edit'),
url('community/create', community.Create.as_view(), name='community-create'),
# Club routes
#search route: pass a parameter type (name) and value
url('clubs', club.AllClubs.as_view(), name='club-all'),
Expand All @@ -41,5 +42,17 @@
url('club/edit', club.Edit.as_view(), name='club-edit'),
#Tags
# url('club/tags', club.Tags.as_view(), name='tags'),

# Club routes
#search route: pass a parameter type (name) and value
url('community/search', community.Search.as_view(), name='search'),
url('community', community.AllCommunities.as_view(), name='community-all'),

# create route
#url('community/create', community.Create.as_view(), name='community-create'),
# edit route

#Tags


]
4 changes: 2 additions & 2 deletions api/views/club.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,13 @@ class Create(View):
"""
def post(self, req):
name = req.POST.get("name")
head = req.POST.get("email")
head = req.POST.get("head")
abstract = req.POST.get("abstract")
link = req.POST.get("link")
myfile = req.FILES['image']
fs = FileSystemStorage()
filename = fs.save(myfile.name, myfile)
uploaded_file_url = fs.url(filename)
print(uploaded_file_url)

if not req.is_admin:
return error_response("PERMISSION DENIED TO CREATE CLUB")
Expand All @@ -75,6 +74,7 @@ def post(self, req):
return error_response("A club with the same name exists! Please switch to a new club name")

try:
print(name, abstract, link, user, uploaded_file_url)
if create_club(name, abstract, link, user, uploaded_file_url):
logger.info('Club(name={}) creation successful'.format(name))
return "Club created successfully!"
Expand Down
110 changes: 110 additions & 0 deletions api/views/community.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
from django.utils.decorators import method_decorator
from django.views.generic import View
from api.decorators.response import JsonResponseDec
from api.decorators.community_permissions import IsAdminDec, CheckAccessPrivilegeDec
from api.models import Community, User
from api.controllers.response_format import error_response
from api.controllers.community_utilities import create_community
from django.core.files.storage import FileSystemStorage
from django.db.models import Q
import logging

logger = logging.getLogger(__name__)
from django.forms.models import model_to_dict

def list_to_dict(items):
'''
Converts a given QuerySet into a list of dictionaries
'''
converted = []
for item in items:
new_item = model_to_dict(item)
del new_item['image']
converted.append(new_item)
return converted

@method_decorator(JsonResponseDec, name='dispatch')
class AllCommunities(View):
"""
Return all Communities
"""
def get(self, req):
communities = Community.objects.all()
return {
'data': list_to_dict(communities)
}

@method_decorator(JsonResponseDec, name='dispatch')
class Search(View):
def get(self, req):
query = req.GET.get("query")
communities = Community.objects.filter(Q(head__name__unaccent__icontains = query) | Q(name__unaccent__icontains=query))
return {
'data': list_to_dict(communities)
}

class Tags(View):
def get(self, req):
pass

@method_decorator(JsonResponseDec, name='dispatch')
@method_decorator(IsAdminDec, name='dispatch')
class Create(View):
"""
Creates a community if user has admin access and community details (link and name) are unique
"""
def post(self, req):
print(req)
name = req.POST.get("name")
head = req.POST.get("head")
abstract = req.POST.get("abstract")
link = req.POST.get("link")
myfile = req.FILES["image"]
fs = FileSystemStorage()
filename = fs.save(myfile.name, myfile)
uploaded_file_url = fs.url(filename)
#print(uploaded_file_url)

if not req.is_admin:
return error_response("PERMISSION DENIED TO CREATE COMMUNITY")
try:
user = User.objects.get(email=head)
except User.DoesNotExist:
return error_response("User does not exist")
print("user exist")
if Community.objects.filter(name=name).exists():
return error_response("A community with the same name exists! Please switch to a new community name")

try:
if create_community(name, abstract, link, user, uploaded_file_url):
logger.info('Community(name={}) creation successful'.format(name))
return "Community created successfully!"
else:
return error_response("Invalid details")
except Exception as e:
logger.error(e)
return error_response("Community creation failed")

@method_decorator(JsonResponseDec, name='dispatch')
@method_decorator(CheckAccessPrivilegeDec, name='dispatch')
class Edit(View):
"""
Updates following details in a community if user has "Admin" access
1. Abstract
2. link
"""
def post(self, req):
name = req.POST.get("name")
link = req.POST.get("link")
abstract = req.POST.get("abstract")
if not (req.access_privilege == "Edit" or req.access_privilege == "Admin" ):
return error_response("USER DOESN'T HAVE EDIT ACCESS")
try:
community = Community.objects.get(name=name)
community.link = link
community.abstract = abstract
community.save()
logger.info('Community(name={}) update successful'.format(community.name))
return "Community updated successfully!"
except Community.DoesNotExist:
return error_response("Community doesn't exist")