-
-
Notifications
You must be signed in to change notification settings - Fork 9
/
models.py
196 lines (161 loc) · 6.34 KB
/
models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
from django.conf import settings
from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.base_user import BaseUserManager
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.core.exceptions import ValidationError
from django.core.mail import send_mail
from django.core.validators import RegexValidator, _lazy_re_compile
from django.db import models
from django.template.loader import render_to_string
from django.utils.translation import ugettext_lazy as _
user_nickname_re = _lazy_re_compile(r"^[-a-zA-Z0-9_]+\Z")
validate_user_nickname_format = RegexValidator(
user_nickname_re,
_(
"Enter a valid 'nickname' consisting of letters, numbers, "
+ "underscores or hyphens."
),
"invalid",
)
def validate_user_nickname_value(value):
if value in [
"api",
"docs",
"admin",
"ping",
"static",
settings.BOTHUB_BOT_NICKNAME,
]:
raise ValidationError(_("The user nickname can't be '{}'").format(value))
class UserManager(BaseUserManager):
def _create_user(self, email, nickname, password=None, **extra_fields):
if not email:
raise ValueError("The given email must be set")
if not nickname:
raise ValueError("The given nick must be set")
email = self.normalize_email(email)
user = self.model(email=email, nickname=nickname, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, nickname, password=None, **extra_fields):
extra_fields.setdefault("is_superuser", False)
return self._create_user(email, nickname, password, **extra_fields)
def create_superuser(self, email, nickname, password=None, **extra_fields):
extra_fields.setdefault("is_superuser", True)
extra_fields.setdefault("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, nickname, password, **extra_fields)
class RepositoryOwner(models.Model):
class Meta:
verbose_name = _("repository organization")
REQUIRED_FIELDS = ["nickname"]
name = models.CharField(_("name"), max_length=150, help_text=_("User's name."))
locale = models.CharField(
_("locale"), max_length=48, help_text=_("User's locale."), blank=True
)
nickname = models.CharField(
_("nickname"),
max_length=150,
validators=[validate_user_nickname_format, validate_user_nickname_value],
help_text=_(
"User's or Organization nickname, using letters, numbers, underscores "
+ "and hyphens without spaces."
),
unique=True,
)
biography = models.TextField(_("biography"), blank=True, null=True)
joined_at = models.DateField(_("joined at"), auto_now_add=True)
def __str__(self):
return self.name # pragma: no cover
@property
def is_anonymous(self):
return False if self.is_organization else self.user.is_anonymous
@property
def user(self):
return getattr(self, "user_owner", None)
@property
def organization(self):
return getattr(self, "organization_owner", None)
@property
def is_organization(self):
return True if self.organization else False
@property
def repository_owner(self):
return self
class User(AbstractBaseUser, RepositoryOwner, PermissionsMixin):
class Meta:
verbose_name = _("user")
verbose_name_plural = _("users")
USERNAME_FIELD = "email"
email = models.EmailField(_("email"), unique=True, help_text=_("User's email."))
is_staff = models.BooleanField(_("staff status"), default=False)
is_active = models.BooleanField(_("active"), default=True)
repository_owner = models.OneToOneField(
RepositoryOwner,
on_delete=models.CASCADE,
parent_link=True,
related_name="user_owner",
)
language = models.CharField(
max_length=5, choices=settings.LANGUAGES, null=True, blank=True
)
objects = UserManager()
@property
def token_generator(self):
return PasswordResetTokenGenerator()
def send_welcome_email(self):
if not settings.SEND_EMAILS:
return False # pragma: no cover
context = {"name": self.name, "base_url": settings.BASE_URL}
send_mail(
_("Welcome to Bothub"),
render_to_string("authentication/emails/welcome.txt", context),
None,
[self.email],
html_message=render_to_string(
"authentication/emails/welcome.html", context
),
)
def make_password_reset_token(self):
return self.token_generator.make_token(self)
def send_reset_password_email(self):
if not settings.SEND_EMAILS:
return False # pragma: no cover
token = self.make_password_reset_token()
reset_url = "{}reset-password/{}/{}/".format(
settings.CONNECT_WEBAPP_BASE_URL, self.nickname, token
)
context = {"reset_url": reset_url, "base_url": settings.BASE_URL}
send_mail(
_("Reset your bothub password"),
render_to_string("authentication/emails/reset_password.txt", context),
None,
[self.email],
html_message=render_to_string(
"authentication/emails/reset_password.html", context
),
)
def check_password_reset_token(self, token):
return self.token_generator.check_token(self, token)
@staticmethod
def generate_repository_user_bot():
user, create = User.objects.get_or_create(
email=settings.BOTHUB_BOT_EMAIL,
name=settings.BOTHUB_BOT_NAME,
nickname=settings.BOTHUB_BOT_NICKNAME,
locale="",
is_staff=False,
is_active=False,
)
return user
@property
def get_user_organizations(self):
from bothub.common.models import Organization, OrganizationAuthorization
return Organization.objects.filter(
pk__in=self.organization_user_authorization.exclude(
role=OrganizationAuthorization.LEVEL_NOTHING
).values_list("organization", flat=True)
)