Fakultas Ilmu Komputer UI

Commit 70e6aa0f authored by Kefas Satrio Bangkit Solidedantyo's avatar Kefas Satrio Bangkit Solidedantyo
Browse files

Merge branch 'user-model' into 'staging'

User model

See merge request !29
parents fbba9065 777d5fc6
Pipeline #70283 passed with stages
in 5 minutes and 35 seconds
......@@ -11,7 +11,7 @@ pylint:
- pip install -r requirements.txt
when: on_success
script:
- pylint --load-plugins pylint_django --rcfile=./.pylintrc dietela_backend dietela_program dietela_quiz nutritionists
- pylint --load-plugins pylint_django --rcfile=./.pylintrc dietela_backend dietela_program dietela_quiz nutritionists authentication
UnitTest:
image: python:3.6.5
......@@ -29,7 +29,7 @@ UnitTest:
- coverage erase
- SSLCONF="?sslmode=require"
- echo "$TEST_DATABASE_URL$SSLCONF"
- DATABASE_URL="$TEST_DATABASE_URL$SSLCONF" coverage run --branch --source=dietela_quiz,nutritionists,dietela_program manage.py test --keepdb
- DATABASE_URL="$TEST_DATABASE_URL$SSLCONF" coverage run --branch --source=dietela_quiz,nutritionists,dietela_program,authentication manage.py test --keepdb
- coverage xml -i
- coverage report -m
artifacts:
......
......@@ -4,6 +4,7 @@ disable=
C0115, # missing-class-docstring
C0116, # missing-function-docstring
E5110, # django-not-configured
E1120, # no-value-for-parameter
[DESIGN]
max-parents=15
......
from django.contrib import admin
from .models import CustomUser
admin.site.register(CustomUser)
from django.apps import AppConfig
class AuthenticationConfig(AppConfig):
name = 'authentication'
from django.contrib.auth.base_user import BaseUserManager
from django.utils.translation import ugettext_lazy as _
class CustomUserManager(BaseUserManager):
"""
Custom user model manager where email is the unique identifiers
for authentication instead of usernames.
"""
def create_user(self, email, password, **extra_fields):
"""
Create and save a User with the given email and password.
"""
if not email:
raise ValueError(_('The Email must be set'))
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, password, **extra_fields):
"""
Create and save a SuperUser with the given email and password.
"""
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError(_('Superuser must have is_staff=True.'))
if extra_fields.get('is_superuser') is not True:
raise ValueError(_('Superuser must have is_superuser=True.'))
return self.create_user(email, password, **extra_fields)
# Generated by Django 3.1 on 2021-04-07 15:21
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
('dietela_quiz', '__first__'),
]
operations = [
migrations.CreateModel(
name='CustomUser',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('email', models.EmailField(max_length=254, unique=True, verbose_name='email address')),
('is_staff', models.BooleanField(default=False)),
('is_active', models.BooleanField(default=True)),
('date_joined', models.DateTimeField(default=django.utils.timezone.now)),
('diet_profile', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user', to='dietela_quiz.dietprofile')),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
],
options={
'abstract': False,
},
),
]
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.utils.translation import gettext_lazy as _
from django.utils import timezone
from dietela_quiz.models import DietProfile
from .managers import CustomUserManager
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(default=timezone.now)
diet_profile = models.OneToOneField(
DietProfile,
on_delete=models.CASCADE,
primary_key=False,
related_name="user",
blank=True, null=True
)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
def __str__(self):
return self.email
from rest_framework.test import APITestCase
from dietela_quiz.models import DietProfile
from .models import CustomUser
class UserModelTests(APITestCase):
@classmethod
def setUpTestData(cls):
cls.diet_profile_1 = DietProfile.objects.create(
name="test",
email="test@test.com",
age=21,
weight=70,
height=173,
gender=1,
special_condition=2,
body_activity=2,
vegetables_in_one_day=2,
fruits_in_one_day=2,
fried_food_in_one_day=2,
sweet_snacks_in_one_day=2,
sweet_drinks_in_one_day=2,
packaged_food_in_one_day=2,
large_meal_in_one_day=2,
snacks_in_one_day=2,
breakfast_type=2,
current_condition=2,
problem_to_solve=2,
health_problem=[1])
def test_create_user(self):
user = CustomUser.objects.create_user(email='email2@email.com', password='tes',
diet_profile=self.diet_profile_1,)
self.assertEqual(str(user), 'email2@email.com')
self.assertEqual(user.email, 'email2@email.com')
self.assertTrue(user.is_active)
self.assertFalse(user.is_staff)
self.assertFalse(user.is_superuser)
try:
# username is None for the AbstractUser option
# username does not exist for the AbstractBaseUser option
self.assertIsNone(user.username)
except AttributeError:
pass
with self.assertRaises(TypeError):
CustomUser.objects.create_user()
with self.assertRaises(TypeError):
CustomUser.objects.create_user(email='')
with self.assertRaises(ValueError):
CustomUser.objects.create_user(email='', password="tes")
def test_create_superuser(self):
admin_user = CustomUser.objects.create_superuser('super@user.com', 'foo')
self.assertEqual(admin_user.email, 'super@user.com')
self.assertTrue(admin_user.is_active)
self.assertTrue(admin_user.is_staff)
self.assertTrue(admin_user.is_superuser)
try:
# username is None for the AbstractUser option
# username does not exist for the AbstractBaseUser option
self.assertIsNone(admin_user.username)
except AttributeError:
pass
with self.assertRaises(ValueError):
CustomUser.objects.create_superuser(
email='super@user.com', password='foo', is_superuser=False)
with self.assertRaises(ValueError):
CustomUser.objects.create_superuser(
email='super@user.com', password='foo', is_staff=False)
......@@ -48,10 +48,13 @@ INSTALLED_APPS = [
'django.contrib.staticfiles',
'rest_framework',
'corsheaders',
'multiselectfield',
# apps
'nutritionists',
'dietela_quiz',
'dietela_program',
'multiselectfield',
'authentication'
]
MIDDLEWARE = [
......@@ -155,3 +158,5 @@ CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = [
"http://localhost:3000",
]
AUTH_USER_MODEL = 'authentication.CustomUser'
# Generated by Django 3.1 on 2021-03-20 14:38
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='DietelaProgram',
fields=[
('id',
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name='ID')),
('name',
models.CharField(
max_length=255)),
('price',
models.FloatField()),
],
),
]
# Generated by Django 3.1 on 2021-03-28 11:55
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dietela_program', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='dietelaprogram',
name='unique_code',
field=models.CharField(default='', max_length=255),
),
]
# Generated by Django 3.1 on 2021-03-22 16:06
from django.db import migrations, models
import multiselectfield.db.fields
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='DietProfile',
fields=[
('id',
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name='ID')),
('name',
models.CharField(
max_length=100)),
('email',
models.EmailField(
max_length=100)),
('age',
models.PositiveIntegerField()),
('weight',
models.PositiveIntegerField()),
('height',
models.PositiveIntegerField()),
('gender',
models.IntegerField(
choices=[
(1,
'Laki-laki'),
(2,
'Perempuan')])),
('special_condition',
models.IntegerField(
choices=[
(1,
'Tidak ada'),
(2,
'Hamil Trimester 1'),
(3,
'Hamil Trimester 2'),
(4,
'Hamil Trimester 3'),
(5,
'Menyusui Bayi 0-6 Bulan'),
(6,
'Menyusui Bayi 7-12 Bulan')])),
('body_activity',
models.IntegerField(
choices=[
(1,
'Lebih banyak duduk dan tidak rutin olahraga'),
(2,
'Banyak jalan, banyak bergerak, tetapi tidak rutin olahraga'),
(3,
'Olahraga rutin 30-45 menit per hari'),
(4,
'Olahraga rutin 45-60 menit per hari'),
(5,
'Olahraga rutin lebih dari 60 menit per hari')])),
('vegetables_in_one_day',
models.IntegerField(
choices=[
(1,
'0 porsi'),
(2,
'1 porsi'),
(3,
'2 porsi'),
(4,
'3 porsi'),
(5,
'Lebih dari 3 porsi')])),
('fruits_in_one_day',
models.IntegerField(
choices=[
(1,
'0 porsi'),
(2,
'1 porsi'),
(3,
'2 porsi'),
(4,
'3 porsi'),
(5,
'Lebih dari 3 porsi')])),
('fried_food_in_one_day',
models.IntegerField(
choices=[
(1,
'0 potong'),
(2,
'1 potong'),
(3,
'2 potong'),
(4,
'3 potong'),
(5,
'Lebih dari 3 potong')])),
('sweet_snacks_in_one_day',
models.IntegerField(
choices=[
(1,
'0 potong'),
(2,
'1 potong'),
(3,
'2 potong'),
(4,
'3 potong'),
(5,
'Lebih dari 3 potong')])),
('sweet_drinks_in_one_day',
models.IntegerField(
choices=[
(1,
'0 gelas'),
(2,
'1 gelas'),
(3,
'2 gelas'),
(4,
'3 gelas'),
(5,
'Lebih dari 3 gelas')])),
('packaged_food_in_one_day',
models.IntegerField(
choices=[
(1,
'0 porsi'),
(2,
'1 porsi'),
(3,
'2 porsi'),
(4,
'3 porsi'),
(5,
'Lebih dari 3 porsi')])),
('large_meal_in_one_day',
models.IntegerField(
choices=[
(1,
'1 kali'),
(2,
'2 kali'),
(3,
'3 kali'),
(4,
'Lebih dari 3 kali')])),
('snacks_in_one_day',
models.IntegerField(
choices=[
(1,
'Tidak pernah'),
(2,
'1 kali '),
(3,
'2 kali'),
(4,
'3 kali'),
(5,
'Lebih dari 3 kali')])),
('breakfast_type',
models.IntegerField(
choices=[
(1,
'Tidak pernah makan pagi'),
(2,
'Makanan yang ringan saja'),
(3,
'Makanan yang sampai mengenyangkan perut')])),
('current_condition',
models.IntegerField(
choices=[
(1,
'Saya belum tertarik melakukan diet dan gaya hidup sehat dan tidak tahu kondisi gizi serta kesehatan saya'),
(2,
'Saya belum tertarik melakukan diet dan gaya hidup sehat meskipun saya tahu kondisi gizi dan kesehatan saya'),
(3,
'Saya mulai tertarik melakukan diet dan gaya hidup sehat meskipun saya tidak tahu kondisi gizi dan kesehatan saya'),
(4,
'Saya mulai tertarik melakukan diet dan gaya hidup sehat dan tahu kondisi gizi dan kesehatan saya'),
(5,
'Saya sudah tahu manfaat diet dan gaya hidup sehat namun belum tahu harus mulai menerapkannya dari mana'),
(6,
'Saya sudah pernah merubah diet dan gaya hidup menjadi lebih sehat tetapi tidak bertahan lama (dilakukan kurang dari 6 bulan)'),
(7,
'Saya sudah pernah berhasil menjalani diet dan gaya hidup sehat selama lebih dari 6 bulan dan ingin melakukannya lagi')])),
('problem_to_solve',
models.IntegerField(
choices=[
(1,
'Turun berat badan dengan target yang realistis'),
(2,
'Naik berat badan dengan target yang realistis'),
(3,
'Berat badan yang bertahan permanen, menjaga agar berat badan tidak naik, anti yo-yo diet'),
(4,
'Butuh pengaturan gizi Ibu Hamil'),
(5,
'Butuh pengaturan gizi Ibu Menyusui'),
(6,
'Menyiapkan tubuh untuk mencapai kesuburan dan persiapan kehamilan'),
(7,
'Mengatur gula darah tinggi (Pre-diabetes), hiperlipidemia (kolesterol), hipertensi (tekanan darah tinggi)'),
(8,
'Capai pola makan sehat dan tetap enjoy menikmati makanan yang disukai'),
(9,
'Transisi vegan'),
(10,
' Butuh pengaturan gizi pada anak-anak atau remaja')])),
('health_problem',
multiselectfield.db.fields.MultiSelectField(
choices=[
(1,
'Tidak ada yang perlu dikhawatirkan'),
(2,
'Diabetes Tipe 2'),
(3,
'Diabetes Tipe 1'),
(4,
'PCOS (Polycystic Ovary Syndrome)'),
(5,
'Kolesterol tinggi'),
(6,
'Asam urat tinggi'),
(7,
'Tekanan darah tinggi'),
(8,
'Gula darah tinggi'),
(9,
'Kanker'),
(10,
'HIV/AIDS'),
(11,
'Maag/GERD/Dispepsia/Gangguan lambung'),
(12,
'Penyintas Kanker'),
(13,
'Penyakit Kronis Lainnya')],
max_length=29)),
],
),
]
# Generated by Django 3.1 on 2021-03-23 14:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dietela_quiz', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='dietprofile',
name='snacks_in_one_day',
field=models.IntegerField(choices=[(1, 'Tidak pernah'), (2, '1 kali'), (3, '2 kali'), (4, '3 kali'), (5, 'Lebih dari 3 kali')]),
),
]
# Generated by Django 3.1 on 2021-03-28 12:55
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('dietela_quiz', '0002_auto_20210323_2144'),
]
operations = [
migrations.CreateModel(
name='QuizResult',
fields=[
('diet_profile', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='dietela_quiz.dietprofile')),
('age', models.PositiveIntegerField()),
('weight', models.PositiveIntegerField()),
('height', models.PositiveIntegerField()),
('gender', models.IntegerField(choices=[(1, 'Laki-laki'), (2, 'Perempuan')])),
('body_mass_index', models.PositiveIntegerField()),
('nutrition_status', models.CharField(max_length=100)),
('ideal_weight_range', models.JSONField()),
('daily_energy_needs', models.FloatField()),
('daily_nutrition_needs', models.JSONField()),
('vegetable_and_fruit_sufficiency', models.CharField(max_length=100)),
('vegetable_and_fruit_diet_recommendation', models.TextField()),
('sugar_salt_fat_problem', models.CharField(max_length=100)),