diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
new file mode 100644
index 0000000000000000000000000000000000000000..a69023229f36573edb56148d0e187d8e397ce110
--- /dev/null
+++ b/.gitlab/CODEOWNERS
@@ -0,0 +1,4 @@
+# Code owners file
+
+## Changes to these file(s) require approval from the teaching team
+sonar-project.properties @addianto @hafiyyan94
\ No newline at end of file
diff --git a/README.md b/README.md
index 3020546098563953b463aa84d24bb2958f22f589..3734ba0a5f9c94947bcea0145748b6214280794a 100755
--- a/README.md
+++ b/README.md
@@ -2,6 +2,13 @@
 
 > Internship matchmaking platform for students and companies.
 
+[![pipeline status](https://gitlab.cs.ui.ac.id/pmpl/class-project/kape/badges/master/pipeline.svg)](https://gitlab.cs.ui.ac.id/pmpl/class-project/kape/commits/master)
+[![coverage report](https://gitlab.cs.ui.ac.id/pmpl/class-project/kape/badges/master/coverage.svg)](https://gitlab.cs.ui.ac.id/pmpl/class-project/kape/commits/master)
+
+[![Quality Gate Status](https://pmpl.cs.ui.ac.id/sonarqube/api/project_badges/measure?project=id.ac.ui.cs.foss%3Akape&metric=alert_status)](https://pmpl.cs.ui.ac.id/sonarqube/dashboard?id=id.ac.ui.cs.foss%3Akape)
+[![Bugs](https://pmpl.cs.ui.ac.id/sonarqube/api/project_badges/measure?project=id.ac.ui.cs.foss%3Akape&metric=bugs)](https://pmpl.cs.ui.ac.id/sonarqube/dashboard?id=id.ac.ui.cs.foss%3Akape)
+[![Code Smells](https://pmpl.cs.ui.ac.id/sonarqube/api/project_badges/measure?project=id.ac.ui.cs.foss%3Akape&metric=code_smells)](https://pmpl.cs.ui.ac.id/sonarqube/dashboard?id=id.ac.ui.cs.foss%3Akape)
+
 ## Table of Contents
 
 - [Install](#install)
diff --git a/core/admin.py b/core/admin.py
index f30ded64324bcdff514ec1de0fd65d3ef0ff4e7c..b54eadf892ec46490d97dc3debac5ce39cd2748f 100755
--- a/core/admin.py
+++ b/core/admin.py
@@ -1,11 +1,11 @@
 from django.contrib import admin
 
 from core.models.accounts import Company, Supervisor, Student
+from core.models.feedbacks import Feedback
 from core.models.vacancies import Vacancy
 
 admin.site.register(Company)
 admin.site.register(Student)
 admin.site.register(Supervisor)
 admin.site.register(Vacancy)
-
-
+admin.site.register(Feedback)
diff --git a/core/migrations/0014_feedback.py b/core/migrations/0014_feedback.py
new file mode 100644
index 0000000000000000000000000000000000000000..e8183198862766fdf15316cfcb43e4719a36cc12
--- /dev/null
+++ b/core/migrations/0014_feedback.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.5 on 2019-10-03 13:39
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0013_auto_20170602_1130'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Feedback',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('created', models.DateTimeField(auto_now_add=True)),
+                ('title', models.CharField(blank=True, default=b'', max_length=100)),
+                ('content', models.TextField()),
+            ],
+            options={
+                'ordering': ['created'],
+            },
+        ),
+    ]
diff --git a/core/models/feedbacks.py b/core/models/feedbacks.py
new file mode 100644
index 0000000000000000000000000000000000000000..c473ae82716b8c4a19526757c0bd09ab9a2c4363
--- /dev/null
+++ b/core/models/feedbacks.py
@@ -0,0 +1,10 @@
+from django.db import models
+
+
+class Feedback(models.Model):
+    created = models.DateTimeField(auto_now_add=True)
+    title = models.CharField(max_length=100, blank=True, default='')
+    content = models.TextField()
+
+    class Meta:
+        ordering = ['created']
diff --git a/core/serializers/feedbacks.py b/core/serializers/feedbacks.py
new file mode 100644
index 0000000000000000000000000000000000000000..2558730792530d18a2199e96b4cba2d53f7ea0ee
--- /dev/null
+++ b/core/serializers/feedbacks.py
@@ -0,0 +1,9 @@
+from rest_framework import serializers
+
+from core.models.feedbacks import Feedback
+
+
+class FeedbackSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = Feedback
+        fields = ['id', 'title', 'content']
diff --git a/core/tests/__init__.py b/core/tests/__init__.py
index 76d673e4b0147d067a601ad568adbcc76c97c056..e8d87c6482286bd702d604fd44d22315c9d42b2c 100755
--- a/core/tests/__init__.py
+++ b/core/tests/__init__.py
@@ -1,3 +1,4 @@
 # __init__.py
 from core.tests.test_accounts import LoginTests, RegisterTests
 from core.tests.test_vacancies import ApplicationTests, BookmarkApplicationTests, CompanyListsTests
+from core.tests.test_feedbacks import FeedbacksTests
diff --git a/core/tests/test_accounts.py b/core/tests/test_accounts.py
index 35458deb5cb4174f6856ffcdfd95439d6ba6e3a6..25281a7cc774e3a409d4eebb22cabca899f6d795 100644
--- a/core/tests/test_accounts.py
+++ b/core/tests/test_accounts.py
@@ -8,6 +8,7 @@ from core.models.accounts import Company, Supervisor, Student
 class LoginTests(APITestCase):
     @requests_mock.Mocker()
     def test_succesful_student_login_relogin(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",
@@ -16,7 +17,7 @@ class LoginTests(APITestCase):
                 "kodeidentitas": "1234567890",
                 "nama_role": "mahasiswa"
         }, status_code=200)
-        m.get('https://api.cs.ui.ac.id/siakngcs/mahasiswa/1234567890/', json={
+        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": [{
@@ -35,6 +36,7 @@ class LoginTests(APITestCase):
 
     @requests_mock.Mocker()
     def test_successful_supervisor_login_relogin(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.dosen",
             "nama": "Dummy Dosen",
@@ -106,6 +108,7 @@ class ProfileUpdateTests(APITestCase):
 
     @requests_mock.Mocker()
     def test_student_profile_update(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",
@@ -114,7 +117,7 @@ class ProfileUpdateTests(APITestCase):
             "kodeidentitas": "1234567890",
             "nama_role": "mahasiswa"
         }, status_code=200)
-        m.get('https://api.cs.ui.ac.id/siakngcs/mahasiswa/1234567890/', json={
+        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": [{
diff --git a/core/tests/test_feedbacks.py b/core/tests/test_feedbacks.py
new file mode 100644
index 0000000000000000000000000000000000000000..f45dba9d7380edf778b6653af3812d00a84ff133
--- /dev/null
+++ b/core/tests/test_feedbacks.py
@@ -0,0 +1,258 @@
+import requests_mock
+from rest_framework import status
+from rest_framework.test import APITestCase
+
+from core.models.feedbacks import Feedback
+
+
+class FeedbacksTests(APITestCase):
+    def login(self, m):
+        # Login
+        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)
+        login_url = '/api/login/'
+        self.client.post(login_url, {'username': 'dummy.mahasiswa', 'password': 'lalala', 'login-type': 'sso-ui'},
+                         format='json')
+
+    @requests_mock.Mocker()
+    def test_feedback_list_with_more_than_10_feedback_and_with_page_number(self, m):
+        self.login(m)
+
+        # test_feedback_list_with_more_than_10_feedback_and_with_page_number
+        for i in range(15):
+            Feedback.objects.create(content="a feedback", title="a title")
+
+        feedbacks_url = '/api/feedbacks/'
+        feedbacks_url_page_1 = '/api/feedbacks/?page=1'
+        feedbacks_url_page_2 = '/api/feedbacks/?page=2'
+
+        response1 = self.client.get(feedbacks_url_page_1)
+        self.assertEqual(response1.status_code, status.HTTP_200_OK)
+        self.assertEqual(response1.data['count'], 15)
+        self.assertIn(feedbacks_url_page_2, response1.data['next'])
+        self.assertEqual(response1.data['previous'], None)
+        self.assertEqual(len(response1.data['results']), 10)
+
+        response2 = self.client.get(feedbacks_url_page_2)
+        self.assertEqual(response2.status_code, status.HTTP_200_OK)
+        self.assertEqual(response2.data['count'], 15)
+        self.assertIn(feedbacks_url, response2.data['previous'])
+        self.assertEqual(response2.data['next'], None)
+        self.assertEqual(len(response2.data['results']), 5)
+
+    @requests_mock.Mocker()
+    def test_feedback_list_with_more_than_10_feedback_and_without_page_number(self, m):
+        self.login(m)
+
+        # test_feedback_list_with_more_than_10_feedback_and_without_page_number
+        for i in range(15):
+            Feedback.objects.create(content="a feedback", title="a title")
+
+        feedbacks_url = '/api/feedbacks/'
+        feedbacks_url_page_2 = '/api/feedbacks/?page=2'
+
+        response1 = self.client.get(feedbacks_url)
+        self.assertEqual(response1.status_code, status.HTTP_200_OK)
+        self.assertEqual(response1.data['count'], 15)
+        self.assertIn(feedbacks_url_page_2, response1.data['next'])
+        self.assertEqual(response1.data['previous'], None)
+        self.assertEqual(len(response1.data['results']), 10)
+
+        response2 = self.client.get(feedbacks_url_page_2)
+        self.assertEqual(response2.status_code, status.HTTP_200_OK)
+        self.assertEqual(response2.data['count'], 15)
+        self.assertIn(feedbacks_url, response2.data['previous'])
+        self.assertEqual(response2.data['next'], None)
+        self.assertEqual(len(response2.data['results']), 5)
+
+    @requests_mock.Mocker()
+    def test_feedback_list_with_less_than_or_equals_10_feedbacks_and_with_zero_feedback_and_without_page_number(self,
+                                                                                                                m):
+        self.login(m)
+
+        # test_feedback_list_with_more_than_10_feedback_and_without_page_number
+        feedbacks_url = '/api/feedbacks/'
+
+        response1 = self.client.get(feedbacks_url)
+        self.assertEqual(response1.status_code, status.HTTP_200_OK)
+        self.assertEqual(response1.data['count'], 0)
+        self.assertEqual(response1.data['next'], None)
+        self.assertEqual(response1.data['previous'], None)
+        self.assertEqual(len(response1.data['results']), 0)
+
+    @requests_mock.Mocker()
+    def test_feedback_list_with_less_than_or_equals_10_feedbacks_and_with_more_than_zero_feedback_and_with_page_number(
+            self, m):
+        self.login(m)
+
+        # test_feedback_list_with_less_than_10_feedbacks_and_with_more_than_zero_feedback_and_with_page_number
+        for i in range(5):
+            Feedback.objects.create(content="a feedback", title="a title")
+
+        feedbacks_url_page_1 = '/api/feedbacks/?page=1'
+
+        response1 = self.client.get(feedbacks_url_page_1)
+        self.assertEqual(response1.status_code, status.HTTP_200_OK)
+        self.assertEqual(response1.data['count'], 5)
+        self.assertEqual(response1.data['previous'], None)
+        self.assertEqual(response1.data['next'], None)
+        self.assertEqual(len(response1.data['results']), 5)
+
+    @requests_mock.Mocker()
+    def test_feedback_list_with_less_than_or_equals_10_feedbacks_and_with_more_than_zero_feedback_and_without_page_number(
+            self,
+            m):
+        self.login(m)
+
+        # test_feedback_list_with_less_than_10_feedbacks_and_with_more_than_zero_feedback_and_without_page_number
+        for i in range(5):
+            Feedback.objects.create(content="a feedback", title="a title")
+
+        feedbacks_url = '/api/feedbacks/'
+
+        response1 = self.client.get(feedbacks_url)
+        self.assertEqual(response1.status_code, status.HTTP_200_OK)
+        self.assertEqual(response1.data['count'], 5)
+        self.assertEqual(response1.data['previous'], None)
+        self.assertEqual(response1.data['next'], None)
+        self.assertEqual(len(response1.data['results']), 5)
+
+    @requests_mock.Mocker()
+    def test_feedback_list_with_less_than_or_equals_10_feedbacks_and_with_zero_feedback_and_with_page_number(self, m):
+        self.login(m)
+
+        # test_feedback_list_with_less_than_10_feedbacks_and_with_zero_feedback_and_with_page_number
+        feedbacks_url = '/api/feedbacks/?page=1'
+
+        response1 = self.client.get(feedbacks_url)
+        self.assertEqual(response1.status_code, status.HTTP_200_OK)
+        self.assertEqual(response1.data['count'], 0)
+        self.assertEqual(response1.data['next'], None)
+        self.assertEqual(response1.data['previous'], None)
+        self.assertEqual(len(response1.data['results']), 0)
+
+    @requests_mock.Mocker()
+    def test_feedbacks_create_with_title_and_content(self, m):
+        self.login(m)
+
+        # test_feedbacks_create_with_title_and_content
+        feedbacks_url = '/api/feedbacks/'
+        response = self.client.post(feedbacks_url,
+                                    {"content": "a content", "title": "a title"})
+
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(response.data["title"], "a title")
+        self.assertEqual(response.data["content"], "a content")
+
+    @requests_mock.Mocker()
+    def test_feedbacks_create_without_title_and_with_content(self, m):
+        self.login(m)
+
+        # test_feedbacks_create_without_title_and_with_content
+        feedbacks_url = '/api/feedbacks/'
+        response = self.client.post(feedbacks_url,
+                                    {"content": "a content"})
+
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+        self.assertEqual(response.data['detail'], "Please send a json object that have title and content property")
+
+    @requests_mock.Mocker()
+    def test_feedbacks_create_without_content_and_with_title(self, m):
+        self.login(m)
+
+        # test_feedbacks_create_without_content_and_with_title
+        feedbacks_url = '/api/feedbacks/'
+        response = self.client.post(feedbacks_url,
+                                    {"title": "a title"})
+
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+        self.assertEqual(response.data['detail'], "Please send a json object that have title and content property")
+
+    @requests_mock.Mocker()
+    def test_feedbacks_create_without_content_and_without_title(self, m):
+        self.login(m)
+
+        # test_feedbacks_create_without_content_and_without_title
+        feedbacks_url = '/api/feedbacks/'
+        response = self.client.post(feedbacks_url,
+                                    {})
+
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+        self.assertEqual(response.data['detail'], "Please send a json object that have title and content property")
+
+    @requests_mock.Mocker()
+    def test_feedbacks_delete_with_exist_data_and_with_data_id(self, m):
+        self.login(m)
+
+        # test_feedbacks_delete_with_exist_data_and_with_data_id
+
+        new_feedback = Feedback(title="a title", content="a content")
+        new_feedback.save()
+        feedback_id = new_feedback.id
+
+        feedbacks_url = '/api/feedbacks/' + str(feedback_id) + '/'
+        response = self.client.delete(feedbacks_url)
+
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(response.data["detail"], "Feedback with id {} was removed".format(feedback_id))
+
+    @requests_mock.Mocker()
+    def test_feedbacks_delete_with_exist_data_and_with_data_id(self, m):
+        self.login(m)
+
+        # test_feedbacks_delete_with_exist_data_and_with_data_id
+
+        new_feedback = Feedback(title="a title", content="a content")
+        new_feedback.save()
+        feedback_id = new_feedback.id
+
+        feedbacks_url = '/api/feedbacks/' + str(feedback_id) + '/'
+        response = self.client.delete(feedbacks_url)
+
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(response.data["detail"], "Feedback with id {} was removed".format(feedback_id))
+
+    @requests_mock.Mocker()
+    def test_feedbacks_delete_with_not_exist_data_and_with_data_id(self, m):
+        self.login(m)
+
+        # test_feedbacks_delete_with_not_exist_data_and_with_data_id
+        new_feedback = Feedback(title="a title", content="a content")
+        new_feedback.save()
+        feedback_id = new_feedback.id
+        new_feedback.delete()
+
+        feedbacks_url = '/api/feedbacks/' + str(feedback_id) + '/'
+        response = self.client.delete(feedbacks_url)
+
+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+        self.assertEqual(response.data["detail"], "Feedback with id {} doesn't exist".format(feedback_id))
+
+    @requests_mock.Mocker()
+    def test_feedbacks_delete_without_data_id(self, m):
+        self.login(m)
+
+        # test_feedbacks_delete_without_data_id
+        feedbacks_url = '/api/feedbacks/'
+        response = self.client.delete(feedbacks_url)
+
+        self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)
diff --git a/core/tests/test_vacancies.py b/core/tests/test_vacancies.py
index 78cdc5a2a71e0fcf48249f1a28df4277fb5221d7..1667ac14aaed6ec90c9f50562ea9c96ea363b47d 100644
--- a/core/tests/test_vacancies.py
+++ b/core/tests/test_vacancies.py
@@ -12,6 +12,7 @@ from core.models.vacancies import Vacancy, Application
 class ApplicationTests(APITestCase):
     @requests_mock.Mocker()
     def test_application_list(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",
@@ -20,7 +21,7 @@ class ApplicationTests(APITestCase):
             "kodeidentitas": "1234567890",
             "nama_role": "mahasiswa"
         }, status_code=200)
-        m.get('https://api.cs.ui.ac.id/siakngcs/mahasiswa/1234567890/', json={
+        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": [{
@@ -42,6 +43,7 @@ class ApplicationTests(APITestCase):
 
     @requests_mock.Mocker()
     def test_application_create_and_delete(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",
@@ -50,7 +52,7 @@ class ApplicationTests(APITestCase):
             "kodeidentitas": "1234567890",
             "nama_role": "mahasiswa"
         }, status_code=200)
-        m.get('https://api.cs.ui.ac.id/siakngcs/mahasiswa/1234567890/', json={
+        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": [{
@@ -84,6 +86,7 @@ class ApplicationTests(APITestCase):
 class BookmarkApplicationTests(APITestCase):
     @requests_mock.Mocker()
     def test_application_list(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",
@@ -92,7 +95,7 @@ class BookmarkApplicationTests(APITestCase):
             "kodeidentitas": "1234567890",
             "nama_role": "mahasiswa"
         }, status_code=200)
-        m.get('https://api.cs.ui.ac.id/siakngcs/mahasiswa/1234567890/', json={
+        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": [{
@@ -114,6 +117,7 @@ class BookmarkApplicationTests(APITestCase):
 
     @requests_mock.Mocker()
     def test_application_create_and_delete(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",
@@ -122,7 +126,7 @@ class BookmarkApplicationTests(APITestCase):
             "kodeidentitas": "1234567890",
             "nama_role": "mahasiswa"
         }, status_code=200)
-        m.get('https://api.cs.ui.ac.id/siakngcs/mahasiswa/1234567890/', json={
+        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": [{
diff --git a/core/views/accounts.py b/core/views/accounts.py
index 0b74350fbc0a57c6d6d6a22562cfd647bc7f99a9..9ea10d861229a65fbb8bef2ac4ff23f8803f9539 100644
--- a/core/views/accounts.py
+++ b/core/views/accounts.py
@@ -9,6 +9,7 @@ from rest_framework.parsers import FormParser,MultiPartParser
 from rest_framework.permissions import AllowAny
 from rest_framework.permissions import IsAdminUser, IsAuthenticated
 from rest_framework.response import Response
+from .sso_login import get_access_token, verify_user, get_riwayat_user, get_summary_user
 
 from core.lib.permissions import IsAdminOrStudent, IsAdminOrSelfOrReadOnly, IsAdminOrCompany, IsAdminOrSupervisor, \
     IsAdminOrSupervisorOrCompanyOrSelf
@@ -81,14 +82,9 @@ class StudentViewSet(viewsets.ModelViewSet):
             raise PermissionDenied("You are not allowed to see other student's transcript")
 
         if student.show_transcript:
-            s = requests.Session()
-            credentials = settings.API_CS_CREDENTIALS
-            s.get('https://api.cs.ui.ac.id/api-auth/login/')
-            csrf = s.cookies['csrftoken']
-            resp = s.post('https://api.cs.ui.ac.id/api-auth/login/',
-                          data={'username': credentials["user"], 'password': credentials["password"],
-                                'csrfmiddlewaretoken': csrf})
-            response = s.get('https://api.cs.ui.ac.id/siakngcs/mahasiswa/' + str(student.npm) + '/riwayat/')
+            access_token = get_access_token(credentials["user"], credentials["password"])
+            ver_user = verify_user(access_token)
+            response = get_riwayat_user(access_token, ver_user['identity_number'])
             return Response({'name': student.full_name, 'transcript': response.json()}, status=status.HTTP_200_OK)
         else:
             return Response({'name': student.full_name, 'error': 'student does not allow transcript to be shown'},
@@ -146,7 +142,7 @@ class LoginViewSet(viewsets.GenericViewSet):
             return Response(status=status.HTTP_400_BAD_REQUEST)
         if login_type == "sso-ui":
             r = requests.post('https://api.cs.ui.ac.id/authentication/ldap/v2/',
-                              json={"username": username, "password": password})
+                              data={"username": username, "password": password})
             resp = r.json()
             if resp.get('state') != 0:
                 # create user
@@ -167,8 +163,9 @@ class LoginViewSet(viewsets.GenericViewSet):
                 login(request, user)
                 if created:
                     if resp.get('nama_role') == "mahasiswa":
-                        student_detail = requests.get('https://api.cs.ui.ac.id/siakngcs/mahasiswa/{}/'.format(resp.get("kodeidentitas")))
-                        resp_student_detail = student_detail.json()
+                        access_token = get_access_token(username, password)
+                        ver_user = verify_user(access_token)
+                        resp_student_detail = get_summary_user(access_token, ver_user['identity_number'])
                         student = Student.objects.create(
                             user=user,
                             npm=resp.get("kodeidentitas"),
diff --git a/core/views/feedbacks.py b/core/views/feedbacks.py
new file mode 100644
index 0000000000000000000000000000000000000000..42464b653148dcaf8b00bf235553342390dc53fa
--- /dev/null
+++ b/core/views/feedbacks.py
@@ -0,0 +1,63 @@
+from rest_framework import viewsets, status
+from rest_framework.response import Response
+
+from core.lib.permissions import IsAdminOrStudent
+from core.models.feedbacks import Feedback
+from core.serializers.feedbacks import FeedbackSerializer
+
+
+class FeedbackViewSet(viewsets.GenericViewSet):
+    """
+    This viewset automatically provides `list`, `create`, `retrieve`,
+    `update` and `destroy` feedback actions.
+
+    Additionally we also provide an extra `highlight` action.
+    """
+    queryset = Feedback.objects.all()
+    serializer_class = FeedbackSerializer
+    permission_classes = [IsAdminOrStudent]
+
+    def list(self, request):
+        """
+        Get list of feedbacks
+        ---
+        """
+        feedbacks = Feedback.objects.all()
+        page = self.paginate_queryset(feedbacks)
+        serialized_page_data = FeedbackSerializer(page, many=True, context={'request': request}).data
+        print (serialized_page_data)
+        return self.get_paginated_response(serialized_page_data)
+
+    def create(self, request):
+        """
+        Create a feedback
+        ---
+        """
+        if 'title' in request.data and 'content' in request.data:
+            new_feedback = Feedback(title=request.data['title'], content=request.data['content'])
+            new_feedback.save()
+            serialized_new_feedback = FeedbackSerializer(new_feedback, context={'request': request})
+            serialized_new_feedback_data = serialized_new_feedback.data
+            print(serialized_new_feedback_data)
+            return Response(serialized_new_feedback_data)
+        else:
+            message = {"detail": "Please send a json object that have title and content property"}
+            print(message)
+            return Response(message, status=status.HTTP_400_BAD_REQUEST)
+
+    def destroy(self, request, pk):
+        """
+        Remove feedback {id}
+        ---
+        """
+        if Feedback.objects.filter(id=pk).count() != 0:
+            print (request.data)
+            delete_feedback = Feedback.objects.get(id=pk)
+            delete_feedback.delete()
+            message = {"detail": "Feedback with id {} was removed".format(pk)}
+            print(message)
+            return Response(message, status=status.HTTP_200_OK)
+        else:
+            message = {"detail": "Feedback with id {} doesn't exist".format(pk)}
+            print(message)
+            return Response(message, status=status.HTTP_400_BAD_REQUEST)
diff --git a/core/views/sso_login.py b/core/views/sso_login.py
new file mode 100644
index 0000000000000000000000000000000000000000..669bf2be7327b5e268015c8b4e303734ee64cd47
--- /dev/null
+++ b/core/views/sso_login.py
@@ -0,0 +1,48 @@
+import requests
+
+API_MAHASISWA = "https://api.cs.ui.ac.id/siakngcs/mahasiswa/"
+API_RIWAYAT_MAHASISWA = API_MAHASISWA+'{npm}/riwayat/'
+API_VERIFY_USER = "https://akun.cs.ui.ac.id/oauth/token/verify/"
+def get_access_token(username, password):
+    try:
+        url = "https://akun.cs.ui.ac.id/oauth/token/"
+
+        payload = "username=" + username + "&password=" + password + "&grant_type=password"
+        headers = {
+            'authorization': "Basic WDN6TmtGbWVwa2RBNDdBU05NRFpSWDNaOWdxU1UxTHd5d3U1V2VwRzpCRVFXQW43RDl6a2k3NEZ0bkNpWVhIRk50Ymg3eXlNWmFuNnlvMU1uaUdSVWNGWnhkQnBobUU5TUxuVHZiTTEzM1dsUnBwTHJoTXBkYktqTjBxcU9OaHlTNGl2Z0doczB0OVhlQ3M0Ym1JeUJLMldwbnZYTXE4VU5yTEFEMDNZeA==",
+            'cache-control': "no-cache",
+            'content-type': "application/x-www-form-urlencoded"
+        }
+        response = requests.request("POST", url, data=payload, headers=headers)
+
+        return response.json()["access_token"]
+    except Exception as e:
+        return None
+        # raise Exception("username atau password sso salah, input : [{}, {}]".format(username, password,))
+
+def get_client_id():
+    client_id = 'X3zNkFmepkdA47ASNMDZRX3Z9gqSU1Lwywu5WepG'
+    return client_id
+
+def verify_user(access_token):
+    print ("#get identity number")
+    parameters = {"access_token": access_token, "client_id": get_client_id()}
+    response = requests.get(API_VERIFY_USER, params=parameters)
+    print ("response => ", response.json())
+    return response.json()
+
+def get_summary_user(access_token, npm):
+    print ("#get summary user => ", npm)
+    parameters = {"access_token": access_token, "client_id": get_client_id()}
+    response = requests.get(API_MAHASISWA+str(npm), params=parameters)
+    print ("response => ", response.text)
+    print ("response => ", response.json())
+    return response.json()
+
+def get_riwayat_user(access_token, npm):
+    print ("#get riwayat user => ", npm)
+    parameters = {"access_token": access_token, "client_id": get_client_id()}
+    response = requests.get(API_RIWAYAT_MAHASISWA.format(npm=npm), params=parameters)
+    print ("response => ", response.text)
+    print ("response => ", response.json())
+    return response.json()
diff --git a/kape/urls.py b/kape/urls.py
index 21a1d46bafe92dfd1c3fbfee2bc1545dff38d28d..5ae9c0787fc03f3f61d7fe4abe83f9f62a6736b1 100755
--- a/kape/urls.py
+++ b/kape/urls.py
@@ -26,6 +26,7 @@ from core.views.accounts import StudentViewSet, CompanyViewSet, SupervisorViewSe
     CompanyRegisterViewSet
 from core.views.vacancies import VacancyViewSet, BookmarkedVacancyByStudentViewSet, StudentApplicationViewSet, \
     CompanyApplicationViewSet, CompanyVacanciesViewSet, ApplicationViewSet
+from core.views.feedbacks import FeedbackViewSet
 
 schema_view = get_swagger_view()
 router = routers.DefaultRouter()
@@ -37,6 +38,7 @@ router.register(r'login', LoginViewSet)
 router.register(r'register', CompanyRegisterViewSet)
 router.register(r'vacancies', VacancyViewSet)
 router.register(r'applications', ApplicationViewSet)
+router.register(r'feedbacks', FeedbackViewSet)
 # router.register(r'students/(?P<student_id>\d+)/profile', StudentProfileViewSet)
 router.register(r'students/(?P<student_id>\d+)/bookmarked-vacancies', BookmarkedVacancyByStudentViewSet,
                 base_name='bookmarked-vacancy-list')
diff --git a/sonar-project.properties b/sonar-project.properties
index 48a6c493c8cf0d1ead4cb49babe175535621ae67..c3db74cddc82e00230c7f6527111959ce3a27b3d 100644
--- a/sonar-project.properties
+++ b/sonar-project.properties
@@ -7,6 +7,7 @@
 sonar.projectKey=id.ac.ui.cs.foss:kape
 sonar.exclusions=/.devcontainer/,/.gitlab/,*.config.js,/.tmp/,
 sonar.scm.provider=git
+sonar.projectVersion=1.0.0
 
 ## Authentication
 ### sonar.login=[pass token via CLI/CI]