Skip to content

Commit 761d01f

Browse files
authored
Merge pull request #15 from PROCOLLAB-github/feature/auth
Feature/auth
2 parents 50c6cec + 81691b1 commit 761d01f

8 files changed

Lines changed: 183 additions & 34 deletions

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,5 @@ dmypy.json
135135

136136
cache
137137

138-
static
138+
static
139+
staticfiles

users/admin.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,7 @@ class CustomUserAdmin(admin.ModelAdmin):
3636
{
3737
"fields": (
3838
"about_me",
39-
# "key_skills",
40-
# "useful_to_project",
4139
"status",
42-
# "speciality",
4340
"city",
4441
"region",
4542
"organization",
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Generated by Django 4.1.2 on 2022-11-04 17:57
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("users", "0010_alter_expert_user_alter_investor_user_and_more"),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name="expert",
15+
name="additional_role",
16+
field=models.PositiveSmallIntegerField(
17+
choices=[(2, "Ментор"), (3, "Эксперт"), (4, "Инвестор")], null=True
18+
),
19+
),
20+
migrations.AddField(
21+
model_name="investor",
22+
name="additional_role",
23+
field=models.PositiveSmallIntegerField(
24+
choices=[(2, "Ментор"), (3, "Эксперт"), (4, "Инвестор")], null=True
25+
),
26+
),
27+
migrations.AddField(
28+
model_name="mentor",
29+
name="additional_role",
30+
field=models.PositiveSmallIntegerField(
31+
choices=[(2, "Ментор"), (3, "Эксперт"), (4, "Инвестор")], null=True
32+
),
33+
),
34+
]
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Generated by Django 4.1.2 on 2022-11-06 14:37
2+
3+
from django.db import migrations, models
4+
import django.utils.timezone
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
("industries", "0001_initial"),
11+
("users", "0011_expert_additional_role_investor_additional_role_and_more"),
12+
]
13+
14+
operations = [
15+
migrations.RemoveField(
16+
model_name="member",
17+
name="speciality",
18+
),
19+
migrations.RemoveField(
20+
model_name="mentor",
21+
name="job",
22+
),
23+
migrations.AddField(
24+
model_name="customuser",
25+
name="datetime_created",
26+
field=models.DateTimeField(
27+
auto_now_add=True, default=django.utils.timezone.now
28+
),
29+
preserve_default=False,
30+
),
31+
migrations.AddField(
32+
model_name="member",
33+
name="preferred_industries",
34+
field=models.ManyToManyField(
35+
blank=True, related_name="members", to="industries.industry"
36+
),
37+
),
38+
migrations.AlterField(
39+
model_name="member",
40+
name="key_skills",
41+
field=models.CharField(blank=True, max_length=512),
42+
),
43+
]

users/models.py

Lines changed: 79 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from django.dispatch import receiver
55

66
from industries.models import Industry
7-
87
from users.managers import CustomUserManager
98

109

@@ -14,26 +13,27 @@ def get_default_user_type():
1413

1514
class CustomUser(AbstractUser):
1615
"""
17-
User model
16+
CustomUser model
17+
18+
This model is used to store the user common information.
1819
1920
Attributes:
2021
email: CharField instance of user's email.
2122
first_name: CharField instance of the user first name.
2223
last_name: CharField instance of the user last name.
23-
patronymic: CharField instance of the user patronymic.
2424
password: CharField instance of the user password.
2525
is_active: Boolean indicating if user confirmed email.
26-
birthday: DateField instance of the user's birthday.
26+
user_type: PositiveSmallIntegerField indicating the user's type according to VERBOSE_USER_TYPES.
27+
patronymic: CharField instance of the user patronymic.
2728
avatar: URLField instance of the user's avatar url.
28-
key_skills: CharField instance of user skills containing keys.
29-
useful_to_project: CharField instance of the something useful... TODO
29+
birthday: DateField instance of the user's birthday.
3030
about_me: TextField instance contains information about the user.
3131
status: CharField instance notifies about the user's status.
32-
speciality: CharField instance the user's specialty.
33-
city: CharField instance the user's name city.
3432
region: CharField instance the user's name region.
33+
city: CharField instance the user's name city.
3534
organization: CharField instance the user's place of study or work.
36-
tags: CharField instance tags. TODO
35+
datetime_updated: A DateTimeField indicating date of update.
36+
datetime_created: A DateTimeField indicating date of creation.
3737
"""
3838

3939
ADMIN = 0
@@ -56,14 +56,12 @@ class CustomUser(AbstractUser):
5656
last_name = models.CharField(max_length=255, blank=False)
5757
password = models.CharField(max_length=255, blank=False)
5858
is_active = models.BooleanField(default=False, editable=False)
59-
datetime_updated = models.DateTimeField(auto_now=True)
60-
6159
user_type = models.PositiveSmallIntegerField(
6260
choices=VERBOSE_USER_TYPES,
6361
default=get_default_user_type,
6462
)
6563

66-
patronymic = models.CharField(max_length=255, blank=True) # Отчество
64+
patronymic = models.CharField(max_length=255, blank=True)
6765
avatar = models.URLField(null=True, blank=True)
6866
birthday = models.DateField(null=True)
6967
about_me = models.TextField(blank=True)
@@ -72,6 +70,9 @@ class CustomUser(AbstractUser):
7270
city = models.CharField(max_length=255, blank=True)
7371
organization = models.CharField(max_length=255, blank=True)
7472

73+
datetime_updated = models.DateTimeField(null=False, auto_now=True)
74+
datetime_created = models.DateTimeField(null=False, auto_now_add=True)
75+
7576
USERNAME_FIELD = "email"
7677
REQUIRED_FIELDS = []
7778

@@ -86,46 +87,98 @@ def __str__(self):
8687
return f"User<{self.id}> - {self.first_name} {self.last_name}"
8788

8889

90+
class AbstractUserWithRole(models.Model):
91+
"""
92+
AbstractUserWithRole abstract model
93+
94+
This model adds additional role field to the user model.
95+
96+
Attributes:
97+
additional_role: PositiveSmallIntegerField indicating the user's additional role
98+
according to VERBOSE_ROLE_TYPES.
99+
100+
"""
101+
102+
MENTOR = 2
103+
EXPERT = 3
104+
INVESTOR = 4
105+
106+
VERBOSE_ROLE_TYPES = (
107+
(MENTOR, "Ментор"),
108+
(EXPERT, "Эксперт"),
109+
(INVESTOR, "Инвестор"),
110+
)
111+
112+
additional_role = models.PositiveSmallIntegerField(
113+
choices=VERBOSE_ROLE_TYPES,
114+
null=True,
115+
)
116+
117+
class Meta:
118+
abstract = True
119+
120+
89121
class Member(models.Model):
122+
"""
123+
Member model
124+
125+
Represents the CustomUser with the MEMBER user type.
126+
127+
Attributes:
128+
user: ForeignKey instance of the CustomUser model.
129+
key_skills: CharField instance indicating member key skills.
130+
useful_to_project: TextField instance indicates actions useful
131+
for the development and maintenance of the project.
132+
preferred_industries: ManyToManyField indicating user industries preferred for work.
133+
"""
134+
90135
user = models.OneToOneField(
91136
CustomUser, on_delete=models.CASCADE, related_name="member"
92137
)
93138

94-
key_skills = models.CharField(max_length=255, blank=True) # TODO
139+
key_skills = models.CharField(max_length=512, blank=True)
95140
useful_to_project = models.TextField(blank=True)
96-
speciality = models.CharField(max_length=255, blank=True)
141+
preferred_industries = models.ManyToManyField(
142+
Industry, blank=True, related_name="members"
143+
)
97144

98145
def __str__(self):
99146
return f"Member<{self.id}> - {self.user.first_name} {self.user.last_name}"
100147

101148

102-
class Mentor(models.Model):
149+
class Mentor(AbstractUserWithRole):
103150
"""
104151
Mentor model
105152
153+
Represents the CustomUser with the MENTOR user type.
154+
106155
Attributes:
107-
job: CharField instance current user job.
108-
useful_to_project: CharField instance some text.
156+
user: ForeignKey instance of the CustomUser model.
157+
useful_to_project: TextField instance indicates actions useful
158+
for the development and maintenance of the project.
109159
"""
110160

111161
user = models.OneToOneField(
112162
CustomUser, on_delete=models.CASCADE, related_name="mentor"
113163
)
114-
115-
job = models.CharField(max_length=255, blank=True)
164+
# CustomUser already has a field called "organization"
165+
# job = models.CharField(max_length=255, blank=True)
116166
useful_to_project = models.TextField(blank=True)
117167

118168
def __str__(self):
119169
return f"Mentor<{self.id}> - {self.user.first_name} {self.user.last_name}"
120170

121171

122-
class Expert(models.Model):
172+
class Expert(AbstractUserWithRole):
123173
"""
124174
Expert model
125175
176+
Represents the CustomUser with the EXPERT user type.
177+
126178
Attributes:
127-
preferred_industries: CharField instance TODO
128-
useful_to_project: CharField instance TODO
179+
preferred_industries: ManyToManyField indicating user industries preferred for work.
180+
useful_to_project: TextField instance indicates actions useful
181+
for the development and maintenance of the project.
129182
"""
130183

131184
user = models.OneToOneField(
@@ -143,12 +196,14 @@ def __str__(self):
143196
return f"Expert<{self.id}> - {self.user.first_name} {self.user.last_name}"
144197

145198

146-
class Investor(models.Model):
199+
class Investor(AbstractUserWithRole):
147200
"""
148201
Investor model
149202
203+
Represents the CustomUser with the INVESTOR user type.
204+
150205
Attributes:
151-
preferred_industries: CharField instance TODO
206+
preferred_industries: ManyToManyField indicating user industries preferred for work.
152207
interaction_process_description: CharField describes the interaction process.
153208
154209
"""

users/serializers.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@ class Meta:
1010
fields = [
1111
"key_skills",
1212
"useful_to_project",
13-
"speciality",
13+
"preferred_industries",
1414
]
1515

1616

1717
class MentorSerializer(serializers.ModelSerializer):
1818
class Meta:
1919
model = Mentor
2020
fields = [
21-
"job",
2221
"useful_to_project",
22+
"additional_role",
2323
]
2424

2525

@@ -29,6 +29,7 @@ class Meta:
2929
fields = [
3030
"preferred_industries",
3131
"useful_to_project",
32+
"additional_role",
3233
]
3334

3435

@@ -38,6 +39,7 @@ class Meta:
3839
fields = [
3940
"interaction_process_description",
4041
"preferred_industries",
42+
"additional_role",
4143
]
4244

4345

users/urls.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from django.urls import path, re_path
22

3-
43
from users.views import (
54
EmailResetPassword,
65
ResetPassword,
6+
SpecialistsList,
77
UserDetail,
88
UserList,
99
VerifyEmail,
@@ -13,6 +13,9 @@
1313

1414
urlpatterns = [
1515
path("users/", UserList.as_view()),
16+
path(
17+
"specialists/", SpecialistsList.as_view()
18+
), # this url actually returns mentors, experts and investors
1619
path("users/<int:pk>/", UserDetail.as_view()),
1720
path("users/reset-password/", EmailResetPassword.as_view()),
1821
re_path(
@@ -31,7 +34,7 @@
3134
name="password_reset_sent",
3235
),
3336
re_path(
34-
r"^password-reset//(?P<key>[-:\w]+)/$",
37+
r"^password-reset/(?P<key>[-:\w]+)/$",
3538
ResetPassword.as_view(),
3639
name="password_reset",
3740
),

0 commit comments

Comments
 (0)