Fakultas Ilmu Komputer UI

Commit 2b1f0814 authored by Jonathan Christopher Jakub's avatar Jonathan Christopher Jakub
Browse files

Merge branch '1706040151-20' into 'master'

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

Closes #20

See merge request !54
parents 2e3213ce 6ce9bcf6
Pipeline #59424 passed with stages
in 17 minutes and 11 seconds
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
</a> </a>
</li> </li>
<li class="nav-item"> <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> <span class="mr-2 d-none d-lg-inline text-gray-600 small">Profil</span>
</a> </a>
</li> </li>
......
...@@ -118,7 +118,7 @@ ...@@ -118,7 +118,7 @@
</li> </li>
<li class="nav-item"> <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> <span class="mr-2 d-none d-lg-inline text-gray-600 small">Profil</span>
</a> </a>
</li> </li>
......
...@@ -127,7 +127,7 @@ ...@@ -127,7 +127,7 @@
</li> </li>
<li class="nav-item"> <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> <span class="mr-2 d-none d-lg-inline text-gray-600 small">Profil</span>
</a> </a>
</li> </li>
......
...@@ -151,7 +151,7 @@ ...@@ -151,7 +151,7 @@
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="/profil-admin/"> <a class="nav-link" href="/profil/">
<span <span
class="mr-2 d-none d-lg-inline text-gray-600 small" class="mr-2 d-none d-lg-inline text-gray-600 small"
>Profil</span >Profil</span
......
...@@ -46,12 +46,12 @@ ...@@ -46,12 +46,12 @@
<!-- Nav Item - Dashboard --> <!-- Nav Item - Dashboard -->
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="/profil-admin/"> <a class="nav-link" href="/profil/">
<span>Halaman Profil</span></a> <span>Halaman Profil</span></a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="/sunting-admin/"> <a class="nav-link" href="/sunting/">
<span>Sunting Profil</span></a> <span>Sunting Profil</span></a>
</li> </li>
...@@ -86,7 +86,7 @@ ...@@ -86,7 +86,7 @@
</a> </a>
</li> </li>
<li class="nav-item"> <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> <span class="mr-2 d-none d-lg-inline text-gray-600 small">Profil</span>
</a> </a>
</li> </li>
......
...@@ -31,14 +31,10 @@ ...@@ -31,14 +31,10 @@
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="/administration">Administrasi</a> <a class="nav-link" href="/administration">Administrasi</a>
</li> </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 %} {% endif %}
<li class="nav-item">
<a class="nav-link" href="/profil">Profil</a>
</li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="/logout">Logout</a> <a class="nav-link" href="/logout">Logout</a>
</li> </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 @@ ...@@ -8,6 +8,7 @@
{% block content %} {% block content %}
<div class="profile-content white-text"> <div class="profile-content white-text">
<div> <div>
<h1 class="mt-2">Profil {% if user.is_admin %}Admin{% else %}Kontributor{% endif %}</h1>
<div class="img-squared"> <div class="img-squared">
{% if not user.default_profile_picture %} {% 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"> <img class="img-profile rounded-circle" src="https://i.ibb.co/9wgPzyZ/default-image.png" alt="User profile picture">
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
{% block content %} {% block content %}
<div class="container"> <div class="container">
<div class="col-20"> <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"> <hr class="mt-0 mb-4">
<form id="add_form" method="POST" action="{% url 'sunting' %}" novalidate enctype="multipart/form-data"> <form id="add_form" method="POST" action="{% url 'sunting' %}" novalidate enctype="multipart/form-data">
{% csrf_token %} {% 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 ( ...@@ -44,13 +44,11 @@ from .views import (
DaftarKatalog, DaftarKatalog,
DashboardKontributorView, DashboardKontributorView,
DetailMateri, DetailMateri,
ProfilKontributorView, ProfilView,
SuntingProfilView,
SuksesLoginAdminView, SuksesLoginAdminView,
SuksesLoginKontributorView, SuksesLoginKontributorView,
SuntingProfilView,
ProfilAdminView,
PostsView, PostsView,
SuntingProfilAdminView,
RevisiMateriView, RevisiMateriView,
ReqMateriView, ReqMateriView,
KatalogPerKontributorView, KatalogPerKontributorView,
...@@ -1079,163 +1077,88 @@ class DeleteMateriTest(TestCase): ...@@ -1079,163 +1077,88 @@ class DeleteMateriTest(TestCase):
response = self.client.get(self.url) response = self.client.get(self.url)
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
class ProfilAdminTest(TestCase): class ProfilViewTest(TestCase):
def setUp(self): @classmethod
self.client = Client() def setUpTestData(cls):
self.kontributor = User.objects.create_contributor(email="kontributor@gov.id", cls.client = Client()
password="kontributor") cls.url = "/profil/"
self.admin = User.objects.create_admin(email="admin@gov.id", cls.template_name = "profil.html"
password="admin") cls.view = ProfilView
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()
cls.contributor_credentials = {"email": "contributor@gov.id", "password": "justpass"}
cls.contributor = User.objects.create_contributor(**cls.contributor_credentials)
class ProfilKontributorTest(TestCase): cls.admin_credentials = {"email": "admin@gov.id", "password": "justpass"}
def setUp(self): cls.admin = User.objects.create_admin(**cls.admin_credentials)
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"
def test_profil_kontributor_view(self): def test_returns_correct_profile_view(self):
found = resolve(self.url) found = resolve(self.url)
self.assertEqual(found.func.__name__, self.view.as_view().__name__) self.assertEqual(found.func.__name__, self.view.as_view().__name__)
def test_profil_kontributor_template(self): def _request_as_user(self, credentials):
# Login self.client = Client()
self.client.login(email="kontributor@gov.id", self.client.login(**credentials)
password="kontributor") return self.client.get(self.url)
# Test
response = 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) self.assertTemplateUsed(response, self.template_name)
# Logout
self.client.logout()
def test_profil_kontributor_url(self): def test_unauthenticated_access_blocked(self):
# Login response = self._request_as_user({})
self.client.login(email="kontributor@gov.id", self.assertEqual(response.status_code, 403)
password="kontributor")
# Test
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
# Logout
self.client.logout()
def test_profil_kontributor_access(self): def test_authorized_access_success(self):
# Kontributor response = self._request_as_user(self.contributor_credentials)
# Login
self.client.login(email="kontributor@gov.id",
password="kontributor")
# Test
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
# Logout self.assertIn("Profil Kontributor", response.content.decode())
self.client.logout()
# Admin response = self._request_as_user(self.admin_credentials)
# Login self.assertEqual(response.status_code, 200)
self.client.login(email="admin@gov.id", self.assertIn("Profil Admin", response.content.decode())
password="admin")
# Test
response = self.client.get(self.url)
self.assertEqual(response.status_code, 403)
html = response.content.decode("utf-8")
self.assertIn(ERROR_403_MESSAGE, html)
# Logout
self.client.logout()
# Anonim class SuntingProfilViewTest(TestCase):
# Test
response = self.client.get(self.url)
self.assertEqual(response.status_code, 403)
html = response.content.decode("utf-8") @classmethod
self.assertIn(ERROR_403_MESSAGE, html) 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): cls.admin_credentials = {"email": "admin@gov.id", "password": "justpass"}
def setUp(self): cls.admin = User.objects.create_admin(**cls.admin_credentials)
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"
def test_sunting_profile_view(self): def test_sunting_profile_view(self):
found = resolve(self.url) found = resolve(self.url)
self.assertEqual(found.func.__name__, self.view.as_view().__name__) self.assertEqual(found.func.__name__, self.view.as_view().__name__)
def test_sunting_profile_template(self): def _request_as_user(self, credentials):
# Login self.client = Client()
self.client.login(email="kontributor@gov.id", self.client.login(**credentials)
password="kontributor") return self.client.get(self.url)
# Test
def test_returns_correct_template(self):
self.client.login(**self.contributor_credentials)
response = self.client.get(self.url) response = self.client.get(self.url)
self.assertTemplateUsed(response, self.template_name) self.assertTemplateUsed(response, self.template_name)
# Logout
self.client.logout()
def test_sunting_profile_url(self): def test_unauthenticated_access_blocked(self):
# Login response = self._request_as_user({})
self.client.login(email="kontributor@gov.id", self.assertEqual(response.status_code, 403)
password="kontributor")
# Test
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
# Logout
self.client.logout()
def test_sunting_profile_access(self): def test_authorized_access_success(self):
# Kontributor response = self._request_as_user(self.contributor_credentials)
# Login
self.client.login(email="kontributor@gov.id",
password="kontributor")
# Test
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
# Logout self.assertIn("Sunting Profil Kontributor", response.content.decode())
self.client.logout()
def test_sunting_profile_access_anonymous(self): response = self._request_as_user(self.admin_credentials)
# Test self.assertEqual(response.status_code, 200)
response = self.client.get(self.url) self.assertIn("Sunting Profil Admin", response.content.decode())
self.assertEqual(response.status_code, 403)
def test_sunting_profile_autofocus(self): def test_sunting_profile_autofocus(self):
form_data = { form_data = {
...@@ -1250,58 +1173,10 @@ class SuntingProfilTest(TestCase): ...@@ -1250,58 +1173,10 @@ class SuntingProfilTest(TestCase):
} }
form = SuntingProfilForm(data=form_data) form = SuntingProfilForm(data=form_data)
# Test
self.assertEqual(form.fields["twitter"].widget.attrs.get("autofocus"), "") self.assertEqual(form.fields["twitter"].widget.attrs.get("autofocus"), "")
self.assertEqual(form.fields["instagram"].widget.attrs.get("autofocus"), None) 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): class SuksesLoginKontributorTest(TestCase):
def setUp(self): def setUp(self):
self.client = Client() self.client = Client()
......
from django.contrib.auth import views as auth_views
from django.urls import path, re_path from django.urls import path, re_path
from app import views from app import views
from app.views import (DashboardKontributorView, ProfilKontributorView, from app.views import (DashboardKontributorView, ProfilView,
SuksesLoginAdminView, SuksesLoginKontributorView, DownloadHistoryView, SuksesLoginAdminView, SuksesLoginKontributorView, DownloadHistoryView,
SuntingProfilView, UploadMateriHTML, UploadMateriView, UploadMateriExcelView, SuntingProfilView, UploadMateriHTML, UploadMateriView, UploadMateriExcelView, PostsView,
ProfilAdminView, PostsView, SuntingProfilAdminView,
ReqMateriView, KatalogPerKontributorView, MateriFavorite, PasswordChangeViews, password_success) ReqMateriView, KatalogPerKontributorView, MateriFavorite, PasswordChangeViews, password_success)
from django.contrib.auth import views as auth_views
urlpatterns = [ urlpatterns = [
path("", views.DaftarKatalog.as_view(), name="daftar_katalog"), path("", views.DaftarKatalog.as_view(), name="daftar_katalog"),
path("materi/<int:pk>/", views.DetailMateri.as_view(), name="detail-materi"), path("materi/<int:pk>/", views.DetailMateri.as_view(), name="detail-materi"),
...@@ -23,15 +24,13 @@ urlpatterns = [ ...@@ -23,15 +24,13 @@ urlpatterns = [