Fakultas Ilmu Komputer UI

Commit 6ce9bcf6 authored by Jonathan Christopher Jakub's avatar Jonathan Christopher Jakub
Browse files

[#20] Fix: set same profile URL to be accessed by both admins and contributors

parent 2e3213ce
......@@ -12,7 +12,7 @@
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/profil-admin/">
<a class="nav-link" href="/profil/">
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Profil</span>
</a>
</li>
......
......@@ -118,7 +118,7 @@
</li>
<li class="nav-item">
<a class="nav-link" href="/profil-admin/">
<a class="nav-link" href="/profil/">
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Profil</span>
</a>
</li>
......
......@@ -127,7 +127,7 @@
</li>
<li class="nav-item">
<a class="nav-link" href="/profil-admin/">
<a class="nav-link" href="/profil/">
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Profil</span>
</a>
</li>
......
......@@ -151,7 +151,7 @@
</li>
<li class="nav-item">
<a class="nav-link" href="/profil-admin/">
<a class="nav-link" href="/profil/">
<span
class="mr-2 d-none d-lg-inline text-gray-600 small"
>Profil</span
......
......@@ -46,12 +46,12 @@
<!-- Nav Item - Dashboard -->
<li class="nav-item">
<a class="nav-link" href="/profil-admin/">
<a class="nav-link" href="/profil/">
<span>Halaman Profil</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="/sunting-admin/">
<a class="nav-link" href="/sunting/">
<span>Sunting Profil</span></a>
</li>
......@@ -86,7 +86,7 @@
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/profil-admin/">
<a class="nav-link" href="/profil/">
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Profil</span>
</a>
</li>
......
......@@ -31,14 +31,10 @@
<li class="nav-item">
<a class="nav-link" href="/administration">Administrasi</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/profil-admin">Profil</a>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="/profil">Profil</a>
</li>
{% endif %}
<li class="nav-item">
<a class="nav-link" href="/profil">Profil</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/logout">Logout</a>
</li>
......
{% extends 'app/base_admin.html'%}
{% load static %}
{% block title %}
<title>Halaman Profil Admin | Digipus</title>
{% endblock %}
{% block content %}
<div class="profile-content white-text">
<div>
{% if not user.default_profile_picture %}
<img class="img-profile rounded-circle" src="https://i.ibb.co/9wgPzyZ/default-image.png" alt="User profile picture">
{% else %}
<img class="img-profile rounded-circle" src="{{ user.profile_picture.url }}" alt="User profile picture">
{% endif %}
<div class="profile-margin"></div>
<h2>{{ user.name }}</h2>
<h4>{{ user.email }}</h4>
<h4>{{ user.biography }}</h4>
<div class="profile-margin"></div>
<div class="row">
<div class="col-md-6 my-auto" style="font-size: 2rem;">
instansi
</div>
<div class="col-md-6 my-auto" style="font-size: 1.2rem;">
{{user.instansi}}
</div>
</div>
<div class="row">
<div class="col-md-6 my-auto" style="font-size: 2rem;">
LinkedIn
</div>
<div class="col-md-6 my-auto" style="font-size: 1.2rem;">
<a href="https://linkedin.com">{{ user.linkedin }}</a>
</div>
</div>
<div class="row">
<div class="col-md-6 my-auto" style="font-size: 2rem;">
Facebook
</div>
<div class="col-md-6 my-auto" style="font-size: 1.2rem;">
<a href="https://facebook.com">{{ user.facebook }}</a>
</div>
</div>
<div class="row">
<div class="col-md-6 my-auto" style="font-size: 2rem;">
Twitter
</div>
<div class="col-md-6 my-auto" style="font-size: 1.2rem;">
<a href="https://twitter.com">{{ user.twitter }}</a>
</div>
</div>
<div class="row">
<div class="col-md-6 my-auto" style="font-size: 2rem;">
Instagram
</div>
<div class="col-md-6 my-auto" style="font-size: 1.2rem;">
<a href="https://instagram.com">{{ user.instagram }}</a>
</div>
</div>
</div>
</div>
{% endblock %}
\ No newline at end of file
......@@ -8,6 +8,7 @@
{% block content %}
<div class="profile-content white-text">
<div>
<h1 class="mt-2">Profil {% if user.is_admin %}Admin{% else %}Kontributor{% endif %}</h1>
<div class="img-squared">
{% if not user.default_profile_picture %}
<img class="img-profile rounded-circle" src="https://i.ibb.co/9wgPzyZ/default-image.png" alt="User profile picture">
......
......@@ -8,7 +8,7 @@
{% block content %}
<div class="container">
<div class="col-20">
<h1 class="mt-2">Sunting Profil</h1>
<h1 class="mt-2">Sunting Profil {% if user.is_admin %}Admin{% else %}Kontributor{% endif %}</h1>
<hr class="mt-0 mb-4">
<form id="add_form" method="POST" action="{% url 'sunting' %}" novalidate enctype="multipart/form-data">
{% csrf_token %}
......
{% extends 'app/base_admin.html' %}
{% load static %}
{% block title %}
<title>Sunting Profil Admin | Digipus</title>
{% endblock %}
{% block content %}
<div class="container">
<div class="col-20">
<h1 class="mt-2">Sunting Profil</h1>
<hr class="mt-0 mb-4">
<form id="add_form" method="POST" action="{% url 'sunting-admin' %}" novalidate enctype="multipart/form-data">
{% csrf_token %}
{% for field in form %}
<div class="col-md-6">
<div class="fieldWrapper">
{{ field.label_tag }} {{ field }}
<span class="text-danger">
{{ field.errors }}
</span>
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
</div>
{% endfor %}
<div class="form-margin"></div>
<div class="col-md-6">
<div class="fieldWrapper">
<button type="submit" class="btn btn-success btn-edit" style="background-color: #615CFD; border-color: #615CFD;">Simpan</button>
</div>
</div>
</form>
</div>
</div>
{% endblock %}
\ No newline at end of file
......@@ -44,13 +44,11 @@ from .views import (
DaftarKatalog,
DashboardKontributorView,
DetailMateri,
ProfilKontributorView,
ProfilView,
SuntingProfilView,
SuksesLoginAdminView,
SuksesLoginKontributorView,
SuntingProfilView,
ProfilAdminView,
PostsView,
SuntingProfilAdminView,
RevisiMateriView,
ReqMateriView,
KatalogPerKontributorView,
......@@ -1079,163 +1077,88 @@ class DeleteMateriTest(TestCase):
response = self.client.get(self.url)
self.assertEqual(response.status_code, 302)
class ProfilAdminTest(TestCase):
def setUp(self):
self.client = Client()
self.kontributor = User.objects.create_contributor(email="kontributor@gov.id",
password="kontributor")
self.admin = User.objects.create_admin(email="admin@gov.id",
password="admin")
self.url = "/profil-admin/"
self.view = ProfilAdminView
self.template_name = "profil-admin.html"
def test_profil_Admin_view(self):
found = resolve(self.url)
self.assertEqual(found.func.__name__, self.view.as_view().__name__)
def test_profil_admin_template(self):
# Login
self.client.login(email="admin@gov.id",
password="admin")
# Test
response = self.client.get(self.url)
self.assertTemplateUsed(response, self.template_name)
# Logout
self.client.logout()
def test_profil_admin_url(self):
# Login
response = self.client.get(self.url)
self.assertNotEqual(response.status_code, 200)
self.client.login(email="admin@gov.id",
password="admin")
# Test
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
# Logout
self.client.logout()
class ProfilViewTest(TestCase):
@classmethod
def setUpTestData(cls):
cls.client = Client()
cls.url = "/profil/"
cls.template_name = "profil.html"
cls.view = ProfilView
cls.contributor_credentials = {"email": "contributor@gov.id", "password": "justpass"}
cls.contributor = User.objects.create_contributor(**cls.contributor_credentials)
class ProfilKontributorTest(TestCase):
def setUp(self):
self.client = Client()
self.kontributor = User.objects.create_contributor(email="kontributor@gov.id",
password="kontributor")
self.admin = User.objects.create_admin(email="admin@gov.id",
password="admin")
self.url = "/profil/"
self.view = ProfilKontributorView
self.template_name = "profil.html"
cls.admin_credentials = {"email": "admin@gov.id", "password": "justpass"}
cls.admin = User.objects.create_admin(**cls.admin_credentials)
def test_profil_kontributor_view(self):
def test_returns_correct_profile_view(self):
found = resolve(self.url)
self.assertEqual(found.func.__name__, self.view.as_view().__name__)
def test_profil_kontributor_template(self):
# Login
self.client.login(email="kontributor@gov.id",
password="kontributor")
# Test
response = self.client.get(self.url)
def _request_as_user(self, credentials):
self.client = Client()
self.client.login(**credentials)
return self.client.get(self.url)
def test_returns_correct_template(self):
response = self._request_as_user(self.contributor_credentials)
self.assertTemplateUsed(response, self.template_name)
# Logout
self.client.logout()
def test_profil_kontributor_url(self):
# Login
self.client.login(email="kontributor@gov.id",
password="kontributor")
# Test
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
# Logout
self.client.logout()
def test_unauthenticated_access_blocked(self):
response = self._request_as_user({})
self.assertEqual(response.status_code, 403)
def test_profil_kontributor_access(self):
# Kontributor
# Login
self.client.login(email="kontributor@gov.id",
password="kontributor")
# Test
response = self.client.get(self.url)
def test_authorized_access_success(self):
response = self._request_as_user(self.contributor_credentials)
self.assertEqual(response.status_code, 200)
# Logout
self.client.logout()
self.assertIn("Profil Kontributor", response.content.decode())
# Admin
# Login
self.client.login(email="admin@gov.id",
password="admin")
# Test
response = self.client.get(self.url)
self.assertEqual(response.status_code, 403)
response = self._request_as_user(self.admin_credentials)
self.assertEqual(response.status_code, 200)
self.assertIn("Profil Admin", response.content.decode())
html = response.content.decode("utf-8")
self.assertIn(ERROR_403_MESSAGE, html)
# Logout
self.client.logout()
# Anonim
# Test
response = self.client.get(self.url)
self.assertEqual(response.status_code, 403)
class SuntingProfilViewTest(TestCase):
html = response.content.decode("utf-8")
self.assertIn(ERROR_403_MESSAGE, html)
@classmethod
def setUpTestData(cls):
cls.client = Client()
cls.url = "/sunting/"
cls.template_name = "sunting.html"
cls.view = SuntingProfilView
cls.contributor_credentials = {"email": "contributor@gov.id", "password": "justpass"}
cls.contributor = User.objects.create_contributor(**cls.contributor_credentials)
class SuntingProfilTest(TestCase):
def setUp(self):
self.client = Client()
self.kontributor = User.objects.create_contributor(email="kontributor@gov.id",
password="kontributor")
self.admin = User.objects.create_admin(email="admin@gov.id",
password="admin")
self.url = "/sunting/"
self.view = SuntingProfilView
self.template_name = "sunting.html"
cls.admin_credentials = {"email": "admin@gov.id", "password": "justpass"}
cls.admin = User.objects.create_admin(**cls.admin_credentials)
def test_sunting_profile_view(self):
found = resolve(self.url)
self.assertEqual(found.func.__name__, self.view.as_view().__name__)
def test_sunting_profile_template(self):
# Login
self.client.login(email="kontributor@gov.id",
password="kontributor")
# Test
def _request_as_user(self, credentials):
self.client = Client()
self.client.login(**credentials)
return self.client.get(self.url)
def test_returns_correct_template(self):
self.client.login(**self.contributor_credentials)
response = self.client.get(self.url)
self.assertTemplateUsed(response, self.template_name)
# Logout
self.client.logout()
def test_sunting_profile_url(self):
# Login
self.client.login(email="kontributor@gov.id",
password="kontributor")
# Test
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
# Logout
self.client.logout()
def test_unauthenticated_access_blocked(self):
response = self._request_as_user({})
self.assertEqual(response.status_code, 403)
def test_sunting_profile_access(self):
# Kontributor
# Login
self.client.login(email="kontributor@gov.id",
password="kontributor")
# Test
response = self.client.get(self.url)
def test_authorized_access_success(self):
response = self._request_as_user(self.contributor_credentials)
self.assertEqual(response.status_code, 200)
# Logout
self.client.logout()
self.assertIn("Sunting Profil Kontributor", response.content.decode())
def test_sunting_profile_access_anonymous(self):
# Test
response = self.client.get(self.url)
self.assertEqual(response.status_code, 403)
response = self._request_as_user(self.admin_credentials)
self.assertEqual(response.status_code, 200)
self.assertIn("Sunting Profil Admin", response.content.decode())
def test_sunting_profile_autofocus(self):
form_data = {
......@@ -1250,58 +1173,10 @@ class SuntingProfilTest(TestCase):
}
form = SuntingProfilForm(data=form_data)
# Test
self.assertEqual(form.fields["twitter"].widget.attrs.get("autofocus"), "")
self.assertEqual(form.fields["instagram"].widget.attrs.get("autofocus"), None)
class SuntingProfilAdminTest(TestCase):
def setUp(self):
self.client = Client()
self.kontributor = User.objects.create_contributor(email="kontributor@gov.id",
password="kontributor")
self.admin = User.objects.create_admin(email="admin@gov.id",
password="admin")
self.url = "/sunting-admin/"
self.view = SuntingProfilAdminView
self.template_name = "sunting_admin.html"
def test_sunting_profile_admin_view(self):
found = resolve(self.url)
self.assertEqual(found.func.__name__, self.view.as_view().__name__)
def test_sunting_profile_admin_template(self):
# Login
self.client.login(email="admin@gov.id",
password="admin")
# Test
response = self.client.get(self.url)
self.assertTemplateUsed(response, self.template_name)
# Logout
self.client.logout()
def test_sunting_profile_admin_url(self):
# Login
self.client.login(email="admin@gov.id",
password="admin")
# Test
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
# Logout
self.client.logout()
def test_sunting_profile_admin_access(self):
# Kontributor
# Login
self.client.login(email="admin@gov.id",
password="admin")
# Test
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
# Logout
self.client.logout()
class SuksesLoginKontributorTest(TestCase):
def setUp(self):
self.client = Client()
......
from django.contrib.auth import views as auth_views
from django.urls import path, re_path
from app import views
from app.views import (DashboardKontributorView, ProfilKontributorView,
from app.views import (DashboardKontributorView, ProfilView,
SuksesLoginAdminView, SuksesLoginKontributorView, DownloadHistoryView,
SuntingProfilView, UploadMateriHTML, UploadMateriView, UploadMateriExcelView,
ProfilAdminView, PostsView, SuntingProfilAdminView,
SuntingProfilView, UploadMateriHTML, UploadMateriView, UploadMateriExcelView, PostsView,
ReqMateriView, KatalogPerKontributorView, MateriFavorite, PasswordChangeViews, password_success)
from django.contrib.auth import views as auth_views
urlpatterns = [
path("", views.DaftarKatalog.as_view(), name="daftar_katalog"),
path("materi/<int:pk>/", views.DetailMateri.as_view(), name="detail-materi"),
......@@ -23,15 +24,13 @@ urlpatterns = [
path("revisi/materi/<int:pk>/", views.RevisiMateriView.as_view(), name="revisi"),
path("unggah/", UploadMateriView.as_view(), name="unggah"),
path("unggah_excel/", UploadMateriExcelView.as_view(), name="unggah_excel"),
path("profil/", ProfilKontributorView.as_view(), name="profil"),
path("profil/", ProfilView.as_view(), name="profil"),
path("sunting/", SuntingProfilView.as_view(), name="sunting"),
path("sukses-kontributor/", SuksesLoginKontributorView.as_view(),
name="sukses-kontributor"),
path("sukses-admin/", SuksesLoginAdminView.as_view(), name="sukses-admin"),
re_path(r"^.*\.html", views.pages, name="pages"),
path("profil-admin/", ProfilAdminView.as_view(), name="profil-admin"),
path("posts/", PostsView.as_view(), name='posts'),
path("sunting-admin/", SuntingProfilAdminView.as_view(), name="sunting-admin"),
path("req-materi/", ReqMateriView.as_view(), name="req-materi"),
path("profil/<str:email>/", KatalogPerKontributorView.as_view(),
name="katalog-per-kontributor"),
......
......@@ -406,40 +406,17 @@ class DashboardKontributorView(TemplateView):
return self.render_to_response(context)
class ProfilAdminView(TemplateView):
template_name = "profil-admin.html"
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated or not request.user.is_admin:
raise PermissionDenied(request)
return super(ProfilAdminView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(ProfilAdminView, self).get_context_data(**kwargs)
return context
def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
current_user = self.request.user
context["user"] = current_user
return self.render_to_response(context)
class ProfilKontributorView(TemplateView):
class ProfilView(TemplateView):
template_name = "profil.html"
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated or not request.user.is_contributor:
if not request.user.is_authenticated:
raise PermissionDenied(request)
return super(ProfilKontributorView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(ProfilKontributorView, self).get_context_data(**kwargs)
return context
return super(ProfilView, self).dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
current_user = self.request.user
current_user = request.user
context["user"] = current_user
return self.render_to_response(context)
......@@ -448,63 +425,14 @@ class SuntingProfilView(TemplateView):
template_name = "sunting.html"
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated or not request.user.is_contributor:
if not request.user.is_authenticated:
raise PermissionDenied(request)
return super(SuntingProfilView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(SuntingProfilView, self).get_context_data(**kwargs)
return context
def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
current_user = self.request.user
context["user"] = current_user
context["form"] = SuntingProfilForm(instance=current_user)
return self.render_to_response(context)
def post(self, request, *args, **kwargs):