Fakultas Ilmu Komputer UI

Commit 0aae65a3 authored by Muhammad Ariq Basyar's avatar Muhammad Ariq Basyar
Browse files

Merge branch 'PBI-10-edit_profile' into 'development'

PBI 10 edit profile

See merge request !52
parents c54ba8bb dc96d1cb
Pipeline #80511 passed with stages
in 13 minutes and 30 seconds
# Generated by Django 3.1.7 on 2021-05-31 15:29
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('informasi_fasilitas', '0020_merge_20210531_1241'),
]
operations = [
migrations.AlterField(
model_name='kegiatan',
name='zona_waktu',
field=models.CharField(choices=[('WIB', 'WIB'), ('WITA', 'WITA'), ('WIT', 'WIT')], default='WIB', max_length=4),
),
]
......@@ -47,10 +47,11 @@ class FotoKegiatanSerializer(serializers.ModelSerializer):
class KegiatanSerializer(serializers.ModelSerializer):
place_id = serializers.CharField(source='lokasi.place_id', read_only=True)
creator = serializers.CharField(source='user.last_name', read_only=True)
creator_email = serializers.CharField(source='user.email', read_only=True)
class Meta:
model = Kegiatan
fields = ('id', 'place_id', 'creator', 'lokasi', 'user',
fields = ('id', 'place_id', 'creator', 'lokasi', 'user', 'creator_email',
'nama_kegiatan', 'penyelenggara', 'deskripsi',
"links", "nomor_kontak", "nama_kontak",
"zona_waktu", 'time_start', 'time_end')
......@@ -86,9 +87,12 @@ class KegiatanSerializerRead(KegiatanSerializer):
class KomentarKegiatanSerializer(serializers.ModelSerializer):
kegiatan = serializers.IntegerField(source='informasi.id', read_only=True)
creator = serializers.CharField(source='user.last_name', read_only=True)
creator_email = serializers.CharField(source='user.email', read_only=True)
class Meta:
model = KomentarKegiatan
fields = ('id', 'creator', 'kegiatan', 'deskripsi', 'created')
fields = ('id', 'creator', 'kegiatan', 'deskripsi', 'created',
'creator_email')
extra_kwargs = {
'deskripsi': {'required': True},
'created': {'required' : True}
......
from unittest.mock import patch
from datetime import timedelta
from http import HTTPStatus
import json
import shutil
import os
from datetime import timedelta
from http import HTTPStatus
from django.test import Client
from django.urls import reverse
from django.test import override_settings
from django.utils import timezone
from django.core.files.uploadedfile import SimpleUploadedFile
from django.conf import settings
from unittest.mock import patch
from .test_base import InformasiFasilitasViewTest
from .models import Lokasi, Kegiatan, FotoKegiatan
from pplbackend.utils import response_decode
from .models import Kegiatan, FotoKegiatan
class KegiatanRelatedViewTest(InformasiFasilitasViewTest):
......@@ -102,6 +104,7 @@ class KegiatanRelatedViewTest(InformasiFasilitasViewTest):
expected_json = self.mock_kegiatan_test.copy()
expected_json.update({'creator': 'mock last_name',
'place_id': 'mock_place_id',
'creator_email': self.mock_user_test['email'],
'time_start': self.kegiatan_time_start,
'time_end': self.kegiatan_time_end})
self.assertEqual(response.status_code, HTTPStatus.CREATED)
......@@ -137,6 +140,7 @@ class KegiatanRelatedViewTest(InformasiFasilitasViewTest):
'id': self.kegiatan.id,
'place_id': self.kegiatan.lokasi.place_id,
'creator': self.kegiatan.user.last_name,
'creator_email': self.kegiatan.user.email,
'nama_kegiatan': self.kegiatan.nama_kegiatan,
'penyelenggara': self.kegiatan.penyelenggara,
'deskripsi': self.kegiatan.deskripsi,
......@@ -158,6 +162,7 @@ class KegiatanRelatedViewTest(InformasiFasilitasViewTest):
'id': self.kegiatan.id,
'place_id': self.kegiatan.lokasi.place_id,
'creator': self.kegiatan.user.last_name,
'creator_email': self.kegiatan.user.email,
'nama_kegiatan': self.kegiatan.nama_kegiatan,
'penyelenggara': self.kegiatan.penyelenggara,
'deskripsi': self.kegiatan.deskripsi,
......@@ -186,6 +191,7 @@ class KegiatanRelatedViewTest(InformasiFasilitasViewTest):
'id': kegiatan_wita.id,
'place_id': kegiatan_wita.lokasi.place_id,
'creator': kegiatan_wita.user.last_name,
'creator_email': kegiatan_wita.user.email,
'nama_kegiatan': kegiatan_wita.nama_kegiatan,
'penyelenggara': kegiatan_wita.penyelenggara,
'deskripsi': kegiatan_wita.deskripsi,
......@@ -214,6 +220,7 @@ class KegiatanRelatedViewTest(InformasiFasilitasViewTest):
'id': kegiatan_wit.id,
'place_id': kegiatan_wit.lokasi.place_id,
'creator': kegiatan_wit.user.last_name,
'creator_email': kegiatan_wit.user.email,
'nama_kegiatan': kegiatan_wit.nama_kegiatan,
'penyelenggara': kegiatan_wit.penyelenggara,
'deskripsi': kegiatan_wit.deskripsi,
......@@ -234,6 +241,7 @@ class KegiatanRelatedViewTest(InformasiFasilitasViewTest):
'id': self.kegiatan.id,
'place_id': self.kegiatan.lokasi.place_id,
'creator': self.kegiatan.user.last_name,
'creator_email': self.kegiatan.user.email,
'nama_kegiatan': self.kegiatan.nama_kegiatan,
'penyelenggara': self.kegiatan.penyelenggara,
'deskripsi': self.kegiatan.deskripsi,
......@@ -265,6 +273,7 @@ class KegiatanRelatedViewTest(InformasiFasilitasViewTest):
expected_json = self.mock_kegiatan_test.copy()
expected_json.update({'creator': 'mock last_name',
'place_id': 'mock_place_id',
'creator_email': self.mock_user_test['email'],
'time_start': self.kegiatan_time_start,
'time_end': self.kegiatan_time_end})
......@@ -311,7 +320,8 @@ class KegiatanRelatedViewTest(InformasiFasilitasViewTest):
'id': self.kegiatan.id,
'place_id': self.kegiatan.lokasi.place_id,
'creator': self.kegiatan.user.last_name,
'nama_kegiatan': self.kegiatan.nama_kegiatan,
'creator_email': self.kegiatan.user.email,
'nama_kegiatan' : self.kegiatan.nama_kegiatan,
'penyelenggara': self.kegiatan.penyelenggara,
'deskripsi': self.kegiatan.deskripsi,
'links': self.kegiatan.links,
......
import json
from http import HTTPStatus
from django.urls import reverse
from pplbackend.utils import response_decode
from .test_base import InformasiFasilitasViewTest
from .models import KomentarFasilitas
from pplbackend.utils import response_decode
......@@ -48,6 +48,7 @@ class KomentarRelatedViewTest(InformasiFasilitasViewTest):
'id': komentar.id,
'deskripsi': komentar.deskripsi,
'creator': komentar.user.last_name,
'creator_email': komentar.user.email,
'created': komentar.created.strftime(TIME_FORMAT),
}
}
......
......@@ -13,7 +13,6 @@ from pplbackend.utils import response_decode
class LokasiRelatedViewTest(InformasiFasilitasViewTest):
def setUp(self):
super().setUp()
self.list_lokasi_url = reverse('list-lokasi')
......
......@@ -38,7 +38,7 @@ urlpatterns = [
path('lokasi/kegiatan-terdekat',
views_kegiatan.nearest_kegiatan, name='nearest-kegiatan'),
path('lokasi/search-kegiatan',
views_kegiatan.search_kegiatan, name='search-kegiatan'),
......@@ -53,22 +53,22 @@ urlpatterns = [
path('lokasi/list-foto-kegiatan/<str:place_id>/<int:kegiatan_id>',
views_kegiatan.list_foto_kegiatan, name='list-foto-kegiatan'),
path('lokasi/list-kegiatan-by-latest-added/<int:start_index>/<int:query_limit>',
views_kegiatan.list_kegiatan_by_latest_added, name='list-kegiatan-by-latest-added'),
path('lokasi/list-kegiatan-by-latest-added/<int:start_index>',
views_kegiatan.list_kegiatan_by_latest_added, name='list-kegiatan-by-latest-added'),
path('lokasi/list-kegiatan-by-name/<int:start_index>/<int:query_limit>',
views_kegiatan.list_kegiatan_by_name, name='list-kegiatan-by-name'),
path('lokasi/list-kegiatan-by-name/<int:start_index>',
views_kegiatan.list_kegiatan_by_name, name='list-kegiatan-by-name'),
path('lokasi/list-kegiatan-by-time/<int:start_index>/<int:query_limit>',
views_kegiatan.list_kegiatan_by_time, name='list-kegiatan-by-time'),
path('lokasi/list-kegiatan-by-time/<int:start_index>',
views_kegiatan.list_kegiatan_by_time, name='list-kegiatan-by-time'),
......@@ -80,7 +80,7 @@ urlpatterns = [
path('lokasi/add-komentar-kegiatan/<str:place_id>/<int:kegiatan_id>',
views_komentar_kegiatan.add_komentar_kegiatan, name='add-komentar-kegiatan'),
path('lokasi/delete-komentar-kegiatan/<str:place_id>/<int:kegiatan_id>/<int:komentar_id>',
views_komentar_kegiatan.delete_komentar_kegiatan, name='delete-komentar-kegiatan'),
]
......@@ -270,6 +270,7 @@ def list_komentar(request, place_id, id):
komentar_details["id"] = komentar.id
komentar_details["deskripsi"] = komentar.deskripsi
komentar_details["creator"] = komentar.user.last_name
komentar_details["creator_email"] = komentar.user.email
komentar_details["created"] = komentar.created.strftime(
TIME_FORMAT)
return JsonResponse(return_json, status=HTTPStatus.OK)
......
import json
from http import HTTPStatus
from django.test import TestCase, Client, override_settings
from django.conf import settings
from django.test import TestCase, Client
from django.db.utils import IntegrityError
from django.contrib.auth.models import User
from django.urls import path, include, reverse
from pplbackend.utils import get_client_login_with_user
from .models import Sekolah, Penyandang, Komunitas
from .serializers import SekolahSerializer, KomunitasSerializer
import django
ID = 'id'
NAME = 'name'
......@@ -118,25 +118,11 @@ def penyandang_setup():
def auth_setup():
email = 'mock_user@email.com'
passcode = 'pass12345'
Client().post('/api/register/', {
'name': 'name',
'email': email,
'phone_number': 000000000,
'password': passcode
})
test_user = User.objects.get(username=email)
test_user.is_active = True
test_user.save()
token_response = Client().post('/api-token-auth/',
{'username': email, 'password': passcode})
content = json.loads(token_response.content.decode('utf-8'))
token = content['token']
return Client(HTTP_AUTHORIZATION='token '+token)
user = User.objects.create_user(username=email)
return get_client_login_with_user(user)
class LayananKhususModelTest(TestCase):
def test_models_sekolah_not_created(self):
with self.assertRaises(IntegrityError) as ex:
obj = Sekolah(name=None)
......@@ -170,9 +156,7 @@ class LayananKhususModelTest(TestCase):
count = Komunitas.objects.all().count()
self.assertNotEqual(count, 0)
class LayananKhususViewsTest(TestCase):
urlpatterns = [
path('layanan-khusus/', include('layanan_khusus.urls')),
]
......@@ -297,7 +281,6 @@ class LayananKhususViewsTest(TestCase):
class LayananKhususSearchTest(TestCase):
urlpatterns = [
path('layanan-khusus/', include('layanan_khusus.urls')),
]
......
......@@ -8,6 +8,7 @@ from rest_framework.permissions import IsAuthenticated
from .models import Sekolah, Komunitas
from .serializers import SekolahSerializer, PenyandangSerializer, KomunitasSerializer
from django.contrib.postgres.search import SearchVector, SearchQuery
from django.forms.models import model_to_dict
@api_view(['GET'])
@authentication_classes([])
......@@ -86,28 +87,13 @@ def pencarian(request):
return_json = {}
for sekolah in list_sekolah:
return_json[indeks] = {}
sekolah_details = return_json[indeks]
sekolah_details["name"] = sekolah.name
sekolah_details["alamat"] = sekolah.alamat
sekolah_details["no_telp"] = sekolah.no_telp
sekolah_details["website"] = sekolah.website
sekolah_details["jumlah_siswa"] = sekolah.jumlah_siswa
sekolah_details["status"] = sekolah.status
sekolah_details["jenis_sekolah"] = sekolah.jenis_sekolah
sekolah_details["akreditasi"] = sekolah.akreditasi
return_json[indeks] = model_to_dict(sekolah)
return_json[indeks].pop("id")
indeks += 1
for komunitas in list_komunitas:
return_json[indeks] = {}
komunitas_details = return_json[indeks]
komunitas_details["name"] = komunitas.name
komunitas_details["alamat"] = komunitas.alamat
komunitas_details["no_telp"] = komunitas.no_telp
komunitas_details["website"] = komunitas.website
komunitas_details["jenis_komunitas"] = komunitas.jenis_komunitas
return_json[indeks] = model_to_dict(komunitas)
return_json[indeks].pop("id")
indeks += 1
return JsonResponse(return_json, status=HTTPStatus.OK)
......
from rest_framework import permissions
class UserViewPermission(permissions.BasePermission):
def has_permission(self, request, view):
if view.action in ['register', 'retrieve', 'activate']:
return True
if view.action == 'update':
return request.user.is_authenticated
return False
def has_object_permission(self, request, view, obj):
if view.action == 'update':
return request.user.id == obj.user.id
return True
from rest_framework.renderers import TemplateHTMLRenderer
class AccountActivationHTMLRenderer(TemplateHTMLRenderer):
template_name = 'acc_activate_success.html'
from django.test import TestCase
from .permissions import UserViewPermission
class MockUser:
def __init__(self, id=1, is_authenticated=False):
self.id = id
self.is_authenticated = is_authenticated
class MockUserAuthenticated(MockUser):
def __init__(self, *args, **kwargs):
super().__init__(is_authenticated=True, *args, **kwargs)
class MockUserNotAuthenticated(MockUser):
def __init__(self, *args, **kwargs):
super().__init__(is_authenticated=False, *args, **kwargs)
class MockRequest:
def __init__(self, user):
self.user = user
class MockView:
def __init__(self, action):
self.action = action
class MockObject:
def __init__(self, user):
self.user = user
class TestPermission(TestCase):
def setUp(self):
self.user_view_permission = UserViewPermission()
self.authenticated_request = MockRequest(MockUserAuthenticated())
self.not_authenticated_request = MockRequest(MockUserNotAuthenticated())
self.view_list = MockView('list')
self.view_create = MockView('register')
self.view_retrieve = MockView('retrieve')
self.view_update = MockView('update')
self.view_delete = MockView('delete')
# has permission tests
def test_permission_authenticated_cant_list(self):
ret = self.user_view_permission\
.has_permission(self.authenticated_request, self.view_list)
self.assertFalse(ret)
def test_permission_not_authenticated_cant_list(self):
ret = self.user_view_permission\
.has_permission(self.not_authenticated_request, self.view_list)
self.assertFalse(ret)
def test_permission_authenticated_can_create(self):
ret = self.user_view_permission\
.has_permission(self.authenticated_request, self.view_create)
self.assertTrue(ret)
def test_permission_not_authenticated_can_create(self):
ret = self.user_view_permission\
.has_permission(self.not_authenticated_request, self.view_create)
self.assertTrue(ret)
def test_permission_authenticated_can_update(self):
ret = self.user_view_permission\
.has_permission(self.authenticated_request, self.view_update)
self.assertTrue(ret)
def test_permission_not_authenticated_cant_update(self):
ret = self.user_view_permission\
.has_permission(self.not_authenticated_request, self.view_update)
self.assertFalse(ret)
def test_permission_authenticated_cant_delete(self):
ret = self.user_view_permission\
.has_permission(self.authenticated_request, self.view_delete)
self.assertFalse(ret)
def test_permission_not_authenticated_cant_delete(self):
ret = self.user_view_permission\
.has_permission(self.not_authenticated_request, self.view_delete)
self.assertFalse(ret)
# has object permission tests
def test_object_permission_can_update_same_user(self):
user = MockUser(id=self.authenticated_request.user.id)
obj = MockObject(user)
ret = self.user_view_permission\
.has_object_permission(self.authenticated_request, self.view_update, obj)
self.assertTrue(ret)
def test_object_permission_cant_update_difference_user(self):
user = MockUser(id=self.authenticated_request.user.id + 1)
obj = MockObject(user)
ret = self.user_view_permission\
.has_object_permission(self.authenticated_request, self.view_update, obj)
self.assertFalse(ret)
def test_object_permission_other_action(self):
user = MockUser(id=self.authenticated_request.user.id + 1)
obj = MockObject(user)
ret = self.user_view_permission\
.has_object_permission(self.authenticated_request, self.view_list, obj)
self.assertTrue(ret)
from datetime import datetime
from django.utils import six
from django.test import TestCase
from .tokens import account_activation_token
class MockUser:
pk = 1
is_active = False
class TestTokenGenerator(TestCase):
def test_make_hash_value(self):
user = MockUser()
now = datetime.now()
ret = account_activation_token._make_hash_value(user, now)
expected = (six.text_type(user.pk) + six.text_type(now) +
six.text_type(user.is_active))
self.assertEqual(ret, expected)
from unittest.mock import MagicMock, patch
from django.test import TestCase
from django.test.client import RequestFactory
from .utils import send_activation_email
class MockUser:
pk = 1
email = 'dummy@email.com'
username = email
last_name = 'dummy the boi'
class TestUtilsUser(TestCase):
mock_activation_endpoint = '/api/user/activate/someuid/some-token/'
mock_email_message = MagicMock()
mock_user = MockUser()
mock_request = RequestFactory().get('')
mock_subject = 'dummy subject'
mock_token = 'some-token'
mock_uid = 'someuid'
mock_bytes = b'some bytes'
@patch('new_rest_api.utils.EmailMessage', return_value=mock_email_message)
@patch('new_rest_api.utils.reverse', return_value=mock_activation_endpoint)
@patch('new_rest_api.utils.account_activation_token.make_token', return_value=mock_token)
@patch('new_rest_api.utils.urlsafe_base64_encode', return_value=mock_uid)
@patch('new_rest_api.utils.force_bytes', return_value=mock_bytes)
def test_send_activation_email(self, mock_force_bytes, mock_urlsafe,
mock_make_token, mock_reverse, mock_init_email):
send_activation_email(self.mock_user, self.mock_request, subject=self.mock_subject)
absolute_uri = self.mock_request.build_absolute_uri(self.mock_activation_endpoint)
message = f"""
Hai {self.mock_user.last_name},
Selamat datang di aplikasi bisaGO.
Sebelum anda bisa menggunakan akun anda, silahkan melakukan aktivasi dengan meng-klik link di bawah ini.
{absolute_uri}
Terima kasih dan selamat menggunakan bisaGO.
Salam,
bisaGO dev Team
"""
mock_force_bytes.assert_called_once_with(self.mock_user.pk)
mock_urlsafe.assert_called_once_with(self.mock_bytes)
mock_make_token.assert_called_once_with(self.mock_user)
mock_reverse.assert_called_once_with('user-activate',
kwargs={'uidb64': self.mock_uid, 'token': self.mock_token})
mock_init_email.assert_called_once_with(self.mock_subject, message,
to=[self.mock_user.email])
self.mock_email_message.send.assert_called_once()
from http import HTTPStatus as status
from unittest.mock import patch, MagicMock
from django.contrib.auth.models import User
from django.core.files.uploadedfile import SimpleUploadedFile
from django.urls import reverse
from django.test import TestCase
from pplbackend.utils import response_decode
class TestUserViews(TestCase):
mock_email_message = MagicMock()
mock_token = 'some-token%s' % ('n'*27)
mock_uid = 'someuid'
def setUp(self):
self.user = User.objects.create_user(username='test@gmail.com')
self.register_url = reverse('user-register')
self.detail_url = reverse('user-detail',
kwargs={'user__username':'test@gmail.com'})
self.update_url = self.detail_url
self.image = SimpleUploadedFile("test1.jpg",
content=open("test_file/test1.jpg", 'rb').read(), content_type='image/jpeg')
self.register_data = {
'name': 'Dummy the boi',
'email': 'dummy@test.com',
'password': 'password',
'phone_number': '000011112222',
'tanggal_lahir': '2000-01-01',
'jenis_kelamin': 'laki-laki',
'foto': self.image,
}
@patch('registrasi.serializers.send_activation_email')
def test_register_and_send_activation_email_is_called_and_user_inactive(self,
mock_ativation_email):
resp = self.client.post(self.register_url, data=self.register_data)
data = response_decode(resp)
expected = {
'response': 'User registered, check activation link on your email',
'email': 'dummy@test.com',
'name': 'Dummy the boi',
}
user = User.objects.get(username='dummy@test.com')
mock_ativation_email.assert_called_once()
self.assertEqual(data, expected)
self.assertFalse(user.is_active)
self.assertEqual(resp.status_code, status.CREATED)
def test_register_invalid_required_fields(self):
resp = self.client.post(self.register_url, data={})
data = response_decode(resp)
expected = {
'name': ['This field is required.'],
'email': ['This field is required.'],
'password': ['This field is required.'],
'tanggal_lahir': ['This field is required.'],
'jenis_kelamin': ['This field is required.'],
'phone_number': ['This field is required.']
}
self.assertEqual(data, expected)
self.assertEqual(resp.status_code, status.BAD_REQUEST)
@patch('new_rest_api.views.account_activation_token.check_token', return_value=True)