From 90449e45fec9e4df5af4c439d054ba9eaecc44e8 Mon Sep 17 00:00:00 2001
From: MISAEL JONATHAN <misael.jonathan@ui.ac.id>
Date: Sat, 12 Oct 2019 23:52:26 +0700
Subject: [PATCH] Merge branch 'master' into '1606879773-27'

# Conflicts:
#   core/models/accounts.py
---
 .DS_Store                                   | Bin 0 -> 8196 bytes
 core/migrations/0002_auto_20191012_2215.py  |  27 ++++++++++++++
 core/migrations/0003_merge_20191012_2251.py |  16 +++++++++
 core/models/accounts.py                     |   6 ++--
 core/tests/test_accounts.py                 |  38 +++++++++++++++++++-
 5 files changed, 83 insertions(+), 4 deletions(-)
 create mode 100755 .DS_Store
 create mode 100644 core/migrations/0002_auto_20191012_2215.py
 create mode 100644 core/migrations/0003_merge_20191012_2251.py
 mode change 100755 => 100644 core/models/accounts.py

diff --git a/.DS_Store b/.DS_Store
new file mode 100755
index 0000000000000000000000000000000000000000..c94171ef775f8dfbac7ea6ed40af6f87cef4032e
GIT binary patch
literal 8196
zcmZQzU|@7AO)+F(kYHe7;9!8z0^AH(0Z1N%F(jFwBC;U!7#IW?7)lt5J#+GtlXCKt
zpmL+sXb6mkz-S1JhQMeDjE2DA3IRrlb2xC+`w-btax?@+LtsRP0H}OWfVAxy9H4Xq
zga%15FfuTJy8w&~3@oq!Vg&aC7(j9$tsokt6-0xyGBAQzU^Bp485p5j8NuBUkUjyh
zQH%^=?F@`yn?d4W?F@`yn;94wA=()jp*Ax@dnk+$?F@_%?F@`y+rdVT5~Cq78Ukn`
z0P4H5F(fh+GZZtVqV?ZFS;?A#fkERx7=U%MFeEeNGZZnTBK7k@>Q<tu<6=l*NMg`q
zC}t>R$YIE2C}ButFh<qGD2}E_h#`d`pCOqcn<15<h(Q-@Q!YaRLq6DTdJL5exePgI
zX0)Q2!NuT$WJVf8CPNOoTNyv2>0xF_WyoVFLp7NJ<ntL|kN=1IJewhrp#a@929VFO
zs!J*_E`W}NoJ=an$t*50Fu2ah#LU9V#?HaP#lgkP6&sw9UmjeNSW;T-lvorE;sqp@
zWF$e^A^G_^aCTx+SY~Q@ynu*veqKppW?pI$NO^E(N@`MKQA~JdUP^wsQ+{b)N-@|R
zs00TGCkJP|fJAk*iK(fMf{B@7t&T#qxw(Okf{C$NZ7nB<xT>M8XF_geRdr2m-Au4o
z;iW7CKZFk_XEA`vdT2nD1sCPz<maV>i*p7BUIvhO5koFRB7+_{^70tc81xvjPzHqr
z7#P42j~ry|3_c8=49*O$41Ns346djV!3c_CWYwHt8}b+u8PXY28T1$m7%I_pfFc-K
z2M<FYLq0<aLn=c&LoS$A3Q88}?gB+QBL`BH3o;ZiB!Uwp#4cTi9BASK`-&l-ArIAN
zP+~wafd|b59Qr^Zf})R;p@5-?A)ld)A(Nq)ArsRkP^h5k2x4$$aAa^{@MUmi&|}DD
zNI`WQDA}Xv;AKG7k<XCBkb+GoI9w`_!bJd705B9Xlrm(3S-Id0RKifqpvO?cP{B}w
zYBM-gko9weGju9AMv5RQ1d9*F85kImb#a1q6)}{7iwAH>qS^xv6J#9{48<UG84|(8
z2_!_b7*ZLM8A`zE1{A^tVADz%G8t0Q(*rofkj-NO7h}a3{<CIaV0?iRKA_^R7*w1x
z=rNQtq%tJI(*YKDgTn_|zYv-pT?UX@iBR*hAihHLJ1De}%@9K~LysW|T+D-V45$bP
z<;_fnbV%r<nbnHsA3+SW2$}F1%>;1_6CgP$ks$}Etia(OQ2JwvKnh<>zd_;_lzIuc
z3>4NVX2FZLk;h<$cv%9}|953zz%~94Q8h}AhQMeD49gH;WN`_0ae}tuu=x<w*9P^c
z6QGiyJ~*g5&Isz4L-c`^fV%eJ?l>c4QW310kpa?^XJml%<QW+lKw1ZIAYioqCs0R%
R+fm4EiP8EWoRo(Z0RU(dZxH|h

literal 0
HcmV?d00001

diff --git a/core/migrations/0002_auto_20191012_2215.py b/core/migrations/0002_auto_20191012_2215.py
new file mode 100644
index 00000000..fdd7a86a
--- /dev/null
+++ b/core/migrations/0002_auto_20191012_2215.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.17 on 2019-10-12 15:15
+from __future__ import unicode_literals
+
+import core.models.accounts
+import django.core.validators
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='student',
+            name='photo',
+            field=models.FileField(blank=True, null=True, upload_to=core.models.accounts.get_student_photo_file_path, validators=[django.core.validators.FileExtensionValidator([b'jpg', b'jpeg', b'png'])]),
+        ),
+        migrations.AlterField(
+            model_name='student',
+            name='resume',
+            field=models.FileField(blank=True, null=True, upload_to=core.models.accounts.get_student_resume_file_path, validators=[django.core.validators.FileExtensionValidator([b'pdf'])]),
+        ),
+    ]
diff --git a/core/migrations/0003_merge_20191012_2251.py b/core/migrations/0003_merge_20191012_2251.py
new file mode 100644
index 00000000..413b589e
--- /dev/null
+++ b/core/migrations/0003_merge_20191012_2251.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.17 on 2019-10-12 15:51
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0002_auto_20191012_2215'),
+        ('core', '0002_vacancy_benefits'),
+    ]
+
+    operations = [
+    ]
diff --git a/core/models/accounts.py b/core/models/accounts.py
old mode 100755
new mode 100644
index b299a712..2aeee60e
--- a/core/models/accounts.py
+++ b/core/models/accounts.py
@@ -4,7 +4,7 @@ import uuid
 from datetime import date
 from django.utils import timezone
 from django.contrib.auth.models import User
-from django.core.validators import MinValueValidator, MaxValueValidator, RegexValidator
+from django.core.validators import MinValueValidator, MaxValueValidator, RegexValidator, FileExtensionValidator
 from django.db import models
 
 from core.lib.validators import validate_document_file_extension, validate_image_file_extension, validate_npm
@@ -69,7 +69,7 @@ class Student(models.Model):
     updated = models.DateTimeField(auto_now=True)
     user = models.OneToOneField(User)
     npm = models.IntegerField(validators=[validate_npm], unique=True)
-    resume = models.FileField(upload_to=get_student_resume_file_path, null=True, blank=True, validators=[validate_document_file_extension])
+    resume = models.FileField(upload_to=get_student_resume_file_path, null=True, blank=True, validators=[FileExtensionValidator(['pdf'])])
     sertifikat = models.FileField(upload_to=get_student_sertifikat_file_path, null=True, blank=True, validators=[validate_document_file_extension])
     phone_number = models.CharField(max_length=100, blank=True, db_index=True, null=True, validators=[RegexValidator(r'^0\d{1,11}$')])
     gender = models.CharField(max_length=30, blank=True, null=True)
@@ -81,8 +81,8 @@ class Student(models.Model):
     major = models.CharField(max_length=30, blank=True, null=True)
     batch = models.CharField(max_length=4, blank=True, null=True)
     show_transcript = models.BooleanField(default=False)
+    photo = models.FileField(upload_to=get_student_photo_file_path, null=True, blank=True, validators=[FileExtensionValidator(['jpg', 'jpeg', 'png'])]) 
     self_description = models.CharField(max_length=500, blank=True, db_index=True, null=True)
-    photo = models.FileField(upload_to=get_student_photo_file_path, null=True, blank=True, validators=[validate_image_file_extension])
     portfolio_link = models.URLField(blank=True, null=True)
     linkedin_url = models.URLField(max_length=200,blank=True, null=True)
     hackerrank_url = models.URLField(max_length=200,blank=True, null=True)
diff --git a/core/tests/test_accounts.py b/core/tests/test_accounts.py
index f5573074..6f74af3d 100644
--- a/core/tests/test_accounts.py
+++ b/core/tests/test_accounts.py
@@ -4,6 +4,7 @@ from rest_framework import status
 from rest_framework.test import APIClient, APITestCase
 from django.contrib.auth.models import User
 from django.core.exceptions import ValidationError
+from StringIO import StringIO
 from core.models.accounts import Company, Supervisor, Student, get_current_age
 
 
@@ -146,7 +147,7 @@ class ProfileUpdateTests(APITestCase):
                 "angkatan": "2017"
             }]
         }, status_code=200)
-        print("Hello World!")
+        
         url = '/api/login/'
         response = self.client.post(url, {'username': 'dummy.mahasiswa', 'password': 'lalala', 'login-type': 'sso-ui'},
                                     format='json')
@@ -250,6 +251,41 @@ class ProfileUpdateTests(APITestCase):
         self.assertEqual(response.status_code, status.HTTP_202_ACCEPTED)
         self.assertEqual(response.data.get('intro'), 'Saya tertarik dengan dunia front-end development')
 
+    @requests_mock.Mocker()
+    def test_student_profile_update_filetype_validation(self, m):
+        m.get('https://akun.cs.ui.ac.id/oauth/token/verify/?client_id=X3zNkFmepkdA47ASNMDZRX3Z9gqSU1Lwywu5WepG', json={"username": 'dummy.mahasiswa', "role": 'mahasiswa', "identity_number": '1234567890'}, status_code=200)
+        m.post('https://api.cs.ui.ac.id/authentication/ldap/v2/', json={
+            "username": "dummy.mahasiswa",
+            "nama": "Dummy Mahasiswa",
+            "state": 1,
+            "kode_org": "01.00.12.01:mahasiswa",
+            "kodeidentitas": "1234567890",
+            "nama_role": "mahasiswa"
+        }, status_code=200)
+        m.get('https://api.cs.ui.ac.id/siakngcs/mahasiswa/1234567890?client_id=X3zNkFmepkdA47ASNMDZRX3Z9gqSU1Lwywu5WepG', json={
+            "kota_lahir": "kota_kota",
+            "tgl_lahir": "2017-12-31",
+            "program": [{
+                "nm_org": "Ilmu Informasi",
+                "angkatan": "2017"
+            }]
+        }, status_code=200)
+
+        url = '/api/login/'
+        response = self.client.post(url, {'username': 'dummy.mahasiswa', 'password': 'lalala', 'login-type': 'sso-ui'},
+                                    format='json')
+        student_id = response.data.get('student').get('id')
+
+        url = '/api/students/' + str(student_id) + '/profile/'
+        imgfile = StringIO('JPG\x01\x00\x01\x00\x80\x01\x00\x00\x00\x00ccc,\x00'
+                     '\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;')
+        imgfile.name = 'test_img_file.jpg'
+        response = self.client.patch(url, {'photo': imgfile}, format='multipart')
+        self.assertEqual(response.status_code, status.HTTP_202_ACCEPTED)
+
+        imgfile.name = 'test_img_file.pdf'
+        response = self.client.patch(url, {'photo': imgfile}, format='multipart')
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
         url = '/api/students/' + str(student_id) + "/profile/"
         data = self._create_test_file_pdf('./assets/img/UI.png')
         response = self.client.patch(url, data, format='multipart')
-- 
GitLab