Refactored occurrences of users.User to get_user_model(), which allows a custom user model
parent
9f8a6aa4f5
commit
a1bd320542
|
@ -28,6 +28,7 @@ answer newbie questions, and generally made taiga that much better:
|
||||||
- Joe Letts
|
- Joe Letts
|
||||||
- Julien Palard
|
- Julien Palard
|
||||||
- luyikei <luyikei.qmltu@gmail.com>
|
- luyikei <luyikei.qmltu@gmail.com>
|
||||||
|
- Motius GmbH <mail@motius.de>
|
||||||
- Ricky Posner <e@eposner.com>
|
- Ricky Posner <e@eposner.com>
|
||||||
- Yamila Moreno <yamila.moreno@kaleidos.net>
|
- Yamila Moreno <yamila.moreno@kaleidos.net>
|
||||||
- Yaser Alraddadi <yaser@yr.sa>
|
- Yaser Alraddadi <yaser@yr.sa>
|
||||||
|
|
|
@ -25,6 +25,7 @@ not uses clasess and uses simple functions.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from django.db import transaction as tx
|
from django.db import transaction as tx
|
||||||
from django.db import IntegrityError
|
from django.db import IntegrityError
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
@ -69,7 +70,7 @@ def is_user_already_registered(*, username:str, email:str) -> (bool, str):
|
||||||
and in case he does whats the duplicated attribute
|
and in case he does whats the duplicated attribute
|
||||||
"""
|
"""
|
||||||
|
|
||||||
user_model = apps.get_model("users", "User")
|
user_model = get_user_model()
|
||||||
if user_model.objects.filter(username=username):
|
if user_model.objects.filter(username=username):
|
||||||
return (True, _("Username is already in use."))
|
return (True, _("Username is already in use."))
|
||||||
|
|
||||||
|
@ -110,7 +111,7 @@ def public_register(username:str, password:str, email:str, full_name:str):
|
||||||
if is_registered:
|
if is_registered:
|
||||||
raise exc.WrongArguments(reason)
|
raise exc.WrongArguments(reason)
|
||||||
|
|
||||||
user_model = apps.get_model("users", "User")
|
user_model = get_user_model()
|
||||||
user = user_model(username=username,
|
user = user_model(username=username,
|
||||||
email=email,
|
email=email,
|
||||||
full_name=full_name)
|
full_name=full_name)
|
||||||
|
@ -159,7 +160,7 @@ def private_register_for_new_user(token:str, username:str, email:str,
|
||||||
if is_registered:
|
if is_registered:
|
||||||
raise exc.WrongArguments(reason)
|
raise exc.WrongArguments(reason)
|
||||||
|
|
||||||
user_model = apps.get_model("users", "User")
|
user_model = get_user_model()
|
||||||
user = user_model(username=username,
|
user = user_model(username=username,
|
||||||
email=email,
|
email=email,
|
||||||
full_name=full_name)
|
full_name=full_name)
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from taiga.base import exceptions as exc
|
from taiga.base import exceptions as exc
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
|
@ -47,7 +47,7 @@ def get_user_for_token(token, scope, max_age=None):
|
||||||
except signing.BadSignature:
|
except signing.BadSignature:
|
||||||
raise exc.NotAuthenticated(_("Invalid token"))
|
raise exc.NotAuthenticated(_("Invalid token"))
|
||||||
|
|
||||||
model_cls = apps.get_model("users", "User")
|
model_cls = get_user_model()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
user = model_cls.objects.get(pk=data["user_%s_id" % (scope)])
|
user = model_cls.objects.get(pk=data["user_%s_id" % (scope)])
|
||||||
|
|
|
@ -20,6 +20,7 @@ import datetime
|
||||||
from optparse import make_option
|
from optparse import make_option
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
|
@ -28,7 +29,6 @@ from taiga.base.mails import mail_builder
|
||||||
from taiga.projects.models import Project, Membership
|
from taiga.projects.models import Project, Membership
|
||||||
from taiga.projects.history.models import HistoryEntry
|
from taiga.projects.history.models import HistoryEntry
|
||||||
from taiga.projects.history.services import get_history_queryset_by_model_instance
|
from taiga.projects.history.services import get_history_queryset_by_model_instance
|
||||||
from taiga.users.models import User
|
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
|
@ -50,7 +50,7 @@ class Command(BaseCommand):
|
||||||
|
|
||||||
# Register email
|
# Register email
|
||||||
context = {"lang": locale,
|
context = {"lang": locale,
|
||||||
"user": User.objects.all().order_by("?").first(),
|
"user": get_user_model().objects.all().order_by("?").first(),
|
||||||
"cancel_token": "cancel-token"}
|
"cancel_token": "cancel-token"}
|
||||||
|
|
||||||
email = mail_builder.registered_user(test_email, context)
|
email = mail_builder.registered_user(test_email, context)
|
||||||
|
@ -58,7 +58,7 @@ class Command(BaseCommand):
|
||||||
|
|
||||||
# Membership invitation
|
# Membership invitation
|
||||||
membership = Membership.objects.order_by("?").filter(user__isnull=True).first()
|
membership = Membership.objects.order_by("?").filter(user__isnull=True).first()
|
||||||
membership.invited_by = User.objects.all().order_by("?").first()
|
membership.invited_by = get_user_model().objects.all().order_by("?").first()
|
||||||
membership.invitation_extra_text = "Text example, Text example,\nText example,\n\nText example"
|
membership.invitation_extra_text = "Text example, Text example,\nText example,\n\nText example"
|
||||||
|
|
||||||
context = {"lang": locale, "membership": membership}
|
context = {"lang": locale, "membership": membership}
|
||||||
|
@ -88,19 +88,19 @@ class Command(BaseCommand):
|
||||||
email.send()
|
email.send()
|
||||||
|
|
||||||
# Password recovery
|
# Password recovery
|
||||||
context = {"lang": locale, "user": User.objects.all().order_by("?").first()}
|
context = {"lang": locale, "user": get_user_model().objects.all().order_by("?").first()}
|
||||||
email = mail_builder.password_recovery(test_email, context)
|
email = mail_builder.password_recovery(test_email, context)
|
||||||
email.send()
|
email.send()
|
||||||
|
|
||||||
# Change email
|
# Change email
|
||||||
context = {"lang": locale, "user": User.objects.all().order_by("?").first()}
|
context = {"lang": locale, "user": get_user_model().objects.all().order_by("?").first()}
|
||||||
email = mail_builder.change_email(test_email, context)
|
email = mail_builder.change_email(test_email, context)
|
||||||
email.send()
|
email.send()
|
||||||
|
|
||||||
# Export/Import emails
|
# Export/Import emails
|
||||||
context = {
|
context = {
|
||||||
"lang": locale,
|
"lang": locale,
|
||||||
"user": User.objects.all().order_by("?").first(),
|
"user": get_user_model().objects.all().order_by("?").first(),
|
||||||
"project": Project.objects.all().order_by("?").first(),
|
"project": Project.objects.all().order_by("?").first(),
|
||||||
"error_subject": "Error generating project dump",
|
"error_subject": "Error generating project dump",
|
||||||
"error_message": "Error generating project dump",
|
"error_message": "Error generating project dump",
|
||||||
|
@ -109,7 +109,7 @@ class Command(BaseCommand):
|
||||||
email.send()
|
email.send()
|
||||||
context = {
|
context = {
|
||||||
"lang": locale,
|
"lang": locale,
|
||||||
"user": User.objects.all().order_by("?").first(),
|
"user": get_user_model().objects.all().order_by("?").first(),
|
||||||
"error_subject": "Error importing project dump",
|
"error_subject": "Error importing project dump",
|
||||||
"error_message": "Error importing project dump",
|
"error_message": "Error importing project dump",
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ class Command(BaseCommand):
|
||||||
context = {
|
context = {
|
||||||
"lang": locale,
|
"lang": locale,
|
||||||
"url": "http://dummyurl.com",
|
"url": "http://dummyurl.com",
|
||||||
"user": User.objects.all().order_by("?").first(),
|
"user": get_user_model().objects.all().order_by("?").first(),
|
||||||
"project": Project.objects.all().order_by("?").first(),
|
"project": Project.objects.all().order_by("?").first(),
|
||||||
"deletion_date": deletion_date,
|
"deletion_date": deletion_date,
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ class Command(BaseCommand):
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"lang": locale,
|
"lang": locale,
|
||||||
"user": User.objects.all().order_by("?").first(),
|
"user": get_user_model().objects.all().order_by("?").first(),
|
||||||
"project": Project.objects.all().order_by("?").first(),
|
"project": Project.objects.all().order_by("?").first(),
|
||||||
}
|
}
|
||||||
email = mail_builder.load_dump(test_email, context)
|
email = mail_builder.load_dump(test_email, context)
|
||||||
|
@ -157,9 +157,9 @@ class Command(BaseCommand):
|
||||||
context = {
|
context = {
|
||||||
"lang": locale,
|
"lang": locale,
|
||||||
"project": Project.objects.all().order_by("?").first(),
|
"project": Project.objects.all().order_by("?").first(),
|
||||||
"changer": User.objects.all().order_by("?").first(),
|
"changer": get_user_model().objects.all().order_by("?").first(),
|
||||||
"history_entries": HistoryEntry.objects.all().order_by("?")[0:5],
|
"history_entries": HistoryEntry.objects.all().order_by("?")[0:5],
|
||||||
"user": User.objects.all().order_by("?").first(),
|
"user": get_user_model().objects.all().order_by("?").first(),
|
||||||
}
|
}
|
||||||
|
|
||||||
for notification_email in notification_emails:
|
for notification_email in notification_emails:
|
||||||
|
|
|
@ -21,6 +21,7 @@ import os
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from django.core.files.base import ContentFile
|
from django.core.files.base import ContentFile
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
@ -263,7 +264,7 @@ class WatcheableObjectModelSerializer(serializers.ModelSerializer):
|
||||||
adding_watcher_emails = list(new_watcher_emails.difference(old_watcher_emails))
|
adding_watcher_emails = list(new_watcher_emails.difference(old_watcher_emails))
|
||||||
removing_watcher_emails = list(old_watcher_emails.difference(new_watcher_emails))
|
removing_watcher_emails = list(old_watcher_emails.difference(new_watcher_emails))
|
||||||
|
|
||||||
User = apps.get_model("users", "User")
|
User = get_user_model()
|
||||||
adding_users = User.objects.filter(email__in=adding_watcher_emails)
|
adding_users = User.objects.filter(email__in=adding_watcher_emails)
|
||||||
removing_users = User.objects.filter(email__in=removing_watcher_emails)
|
removing_users = User.objects.filter(email__in=removing_watcher_emails)
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
from taiga.front.templatetags.functions import resolve
|
from taiga.front.templatetags.functions import resolve
|
||||||
|
|
||||||
|
@ -24,7 +25,7 @@ from .base import Sitemap
|
||||||
|
|
||||||
class UsersSitemap(Sitemap):
|
class UsersSitemap(Sitemap):
|
||||||
def items(self):
|
def items(self):
|
||||||
user_model = apps.get_model("users", "User")
|
user_model = get_user_model()
|
||||||
|
|
||||||
# Only active users and not system users
|
# Only active users and not system users
|
||||||
queryset = user_model.objects.filter(is_active=True,
|
queryset = user_model.objects.filter(is_active=True,
|
||||||
|
|
|
@ -17,10 +17,10 @@
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from taiga.users.models import User
|
|
||||||
from taiga.base.utils.urls import get_absolute_url
|
from taiga.base.utils.urls import get_absolute_url
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,4 +43,4 @@ def get_or_generate_config(project):
|
||||||
|
|
||||||
|
|
||||||
def get_bitbucket_user(user_id):
|
def get_bitbucket_user(user_id):
|
||||||
return User.objects.get(is_system=True, username__startswith="bitbucket")
|
return get_user_model().objects.get(is_system=True, username__startswith="bitbucket")
|
||||||
|
|
|
@ -17,9 +17,9 @@
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
|
|
||||||
from taiga.users.models import User
|
|
||||||
from taiga.users.models import AuthData
|
from taiga.users.models import AuthData
|
||||||
from taiga.base.utils.urls import get_absolute_url
|
from taiga.base.utils.urls import get_absolute_url
|
||||||
|
|
||||||
|
@ -49,6 +49,6 @@ def get_github_user(github_id):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if user is None:
|
if user is None:
|
||||||
user = User.objects.get(is_system=True, username__startswith="github")
|
user = get_user_model().objects.get(is_system=True, username__startswith="github")
|
||||||
|
|
||||||
return user
|
return user
|
||||||
|
|
|
@ -17,10 +17,10 @@
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from taiga.users.models import User
|
|
||||||
from taiga.base.utils.urls import get_absolute_url
|
from taiga.base.utils.urls import get_absolute_url
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,11 +47,11 @@ def get_gitlab_user(user_email):
|
||||||
|
|
||||||
if user_email:
|
if user_email:
|
||||||
try:
|
try:
|
||||||
user = User.objects.get(email=user_email)
|
user = get_user_model().objects.get(email=user_email)
|
||||||
except User.DoesNotExist:
|
except get_user_model().DoesNotExist:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if user is None:
|
if user is None:
|
||||||
user = User.objects.get(is_system=True, username__startswith="gitlab")
|
user = get_user_model().objects.get(is_system=True, username__startswith="gitlab")
|
||||||
|
|
||||||
return user
|
return user
|
||||||
|
|
|
@ -22,13 +22,12 @@
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
# THE SOFTWARE.
|
# THE SOFTWARE.
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
from markdown.extensions import Extension
|
from markdown.extensions import Extension
|
||||||
from markdown.inlinepatterns import Pattern
|
from markdown.inlinepatterns import Pattern
|
||||||
from markdown.util import etree, AtomicString
|
from markdown.util import etree, AtomicString
|
||||||
|
|
||||||
from taiga.users.models import User
|
|
||||||
|
|
||||||
|
|
||||||
class MentionsExtension(Extension):
|
class MentionsExtension(Extension):
|
||||||
def extendMarkdown(self, md, md_globals):
|
def extendMarkdown(self, md, md_globals):
|
||||||
|
@ -43,8 +42,8 @@ class MentionsPattern(Pattern):
|
||||||
username = m.group(3)
|
username = m.group(3)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
user = User.objects.get(username=username)
|
user = get_user_model().objects.get(username=username)
|
||||||
except User.DoesNotExist:
|
except get_user_model().DoesNotExist:
|
||||||
return "@{}".format(username)
|
return "@{}".format(username)
|
||||||
|
|
||||||
url = "/profile/{}".format(username)
|
url = "/profile/{}".format(username)
|
||||||
|
|
|
@ -19,10 +19,10 @@ from contextlib import suppress
|
||||||
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
|
||||||
from taiga.base.utils.urls import get_absolute_url
|
|
||||||
from taiga.base.utils.iterators import as_tuple
|
from taiga.base.utils.iterators import as_tuple
|
||||||
from taiga.base.utils.iterators import as_dict
|
from taiga.base.utils.iterators import as_dict
|
||||||
from taiga.mdrender.service import render as mdrender
|
from taiga.mdrender.service import render as mdrender
|
||||||
|
@ -49,7 +49,7 @@ def _get_generic_values(ids:tuple, *, typename=None, attr:str="name") -> tuple:
|
||||||
|
|
||||||
@as_dict
|
@as_dict
|
||||||
def _get_users_values(ids:set) -> dict:
|
def _get_users_values(ids:set) -> dict:
|
||||||
user_model = apps.get_model("users", "User")
|
user_model = get_user_model()
|
||||||
ids = filter(lambda x: x is not None, ids)
|
ids = filter(lambda x: x is not None, ids)
|
||||||
qs = user_model.objects.filter(pk__in=tuple(ids))
|
qs = user_model.objects.filter(pk__in=tuple(ids))
|
||||||
|
|
||||||
|
|
|
@ -14,12 +14,10 @@
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.apps import apps
|
from django.contrib.auth import get_user_model
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.conf import settings
|
|
||||||
from django_pgjson.fields import JsonField
|
from django_pgjson.fields import JsonField
|
||||||
|
|
||||||
from taiga.mdrender.service import get_diff_of_htmls
|
from taiga.mdrender.service import get_diff_of_htmls
|
||||||
|
@ -96,7 +94,7 @@ class HistoryEntry(models.Model):
|
||||||
@cached_property
|
@cached_property
|
||||||
def owner(self):
|
def owner(self):
|
||||||
pk = self.user["pk"]
|
pk = self.user["pk"]
|
||||||
model = apps.get_model("users", "User")
|
model = get_user_model()
|
||||||
try:
|
try:
|
||||||
return model.objects.get(pk=pk)
|
return model.objects.get(pk=pk)
|
||||||
except model.DoesNotExist:
|
except model.DoesNotExist:
|
||||||
|
|
|
@ -16,25 +16,21 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.db.models import Q
|
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
|
|
||||||
from taiga.base import filters
|
from taiga.base import filters
|
||||||
from taiga.base import exceptions as exc
|
from taiga.base import exceptions as exc
|
||||||
from taiga.base import response
|
from taiga.base import response
|
||||||
from taiga.base.decorators import detail_route, list_route
|
from taiga.base.decorators import list_route
|
||||||
from taiga.base.api import ModelCrudViewSet, ModelListViewSet
|
from taiga.base.api import ModelCrudViewSet, ModelListViewSet
|
||||||
from taiga.base.api.mixins import BlockedByProjectMixin
|
from taiga.base.api.mixins import BlockedByProjectMixin
|
||||||
from taiga.base.api.utils import get_object_or_404
|
from taiga.base.api.utils import get_object_or_404
|
||||||
|
|
||||||
from taiga.users.models import User
|
|
||||||
|
|
||||||
from taiga.projects.notifications.mixins import WatchedResourceMixin, WatchersViewSetMixin
|
from taiga.projects.notifications.mixins import WatchedResourceMixin, WatchersViewSetMixin
|
||||||
from taiga.projects.occ import OCCResourceMixin
|
from taiga.projects.occ import OCCResourceMixin
|
||||||
from taiga.projects.history.mixins import HistoryResourceMixin
|
from taiga.projects.history.mixins import HistoryResourceMixin
|
||||||
|
|
||||||
from taiga.projects.models import Project, IssueStatus, Severity, Priority, IssueType
|
from taiga.projects.models import Project, IssueStatus, Severity, Priority, IssueType
|
||||||
from taiga.projects.milestones.models import Milestone
|
|
||||||
from taiga.projects.votes.mixins.viewsets import VotedResourceMixin, VotersViewSetMixin
|
from taiga.projects.votes.mixins.viewsets import VotedResourceMixin, VotersViewSetMixin
|
||||||
|
|
||||||
from . import models
|
from . import models
|
||||||
|
|
|
@ -16,16 +16,14 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from taiga.base.api import serializers
|
from django.contrib.auth import get_user_model
|
||||||
from taiga.base.fields import TagsField
|
|
||||||
|
|
||||||
from taiga.users.models import User
|
from taiga.base.api import serializers
|
||||||
from taiga.users.services import get_photo_or_gravatar_url
|
|
||||||
|
|
||||||
|
|
||||||
class FanSerializer(serializers.ModelSerializer):
|
class FanSerializer(serializers.ModelSerializer):
|
||||||
full_name = serializers.CharField(source='get_full_name', required=False)
|
full_name = serializers.CharField(source='get_full_name', required=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = get_user_model()
|
||||||
fields = ('id', 'username', 'full_name')
|
fields = ('id', 'username', 'full_name')
|
||||||
|
|
|
@ -14,15 +14,11 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from operator import is_not
|
from operator import is_not
|
||||||
|
|
||||||
from django.apps import apps
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.contenttypes.models import ContentType
|
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.db import models
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
from taiga.base import response
|
from taiga.base import response
|
||||||
from taiga.base.decorators import detail_route
|
from taiga.base.decorators import detail_route
|
||||||
|
@ -34,8 +30,6 @@ from taiga.projects.notifications.utils import (attach_watchers_to_queryset,
|
||||||
attach_is_watcher_to_queryset,
|
attach_is_watcher_to_queryset,
|
||||||
attach_total_watchers_to_queryset)
|
attach_total_watchers_to_queryset)
|
||||||
|
|
||||||
from taiga.users.models import User
|
|
||||||
from . import models
|
|
||||||
from . serializers import WatcherSerializer
|
from . serializers import WatcherSerializer
|
||||||
|
|
||||||
|
|
||||||
|
@ -224,9 +218,9 @@ class EditableWatchedResourceModelSerializer(WatchedResourceModelSerializer):
|
||||||
adding_watcher_ids = list(new_watcher_ids.difference(old_watcher_ids))
|
adding_watcher_ids = list(new_watcher_ids.difference(old_watcher_ids))
|
||||||
removing_watcher_ids = list(old_watcher_ids.difference(new_watcher_ids))
|
removing_watcher_ids = list(old_watcher_ids.difference(new_watcher_ids))
|
||||||
|
|
||||||
User = apps.get_model("users", "User")
|
User = get_user_model()
|
||||||
adding_users = User.objects.filter(id__in=adding_watcher_ids)
|
adding_users = get_user_model().objects.filter(id__in=adding_watcher_ids)
|
||||||
removing_users = User.objects.filter(id__in=removing_watcher_ids)
|
removing_users = get_user_model().objects.filter(id__in=removing_watcher_ids)
|
||||||
for user in adding_users:
|
for user in adding_users:
|
||||||
services.add_watcher(obj, user)
|
services.add_watcher(obj, user)
|
||||||
|
|
||||||
|
@ -273,7 +267,7 @@ class WatchersViewSetMixin:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.object = resource.get_watchers().get(pk=pk)
|
self.object = resource.get_watchers().get(pk=pk)
|
||||||
except ObjectDoesNotExist: # or User.DoesNotExist
|
except ObjectDoesNotExist: # or User.DoesNotExist
|
||||||
return response.NotFound()
|
return response.NotFound()
|
||||||
|
|
||||||
serializer = self.get_serializer(self.object)
|
serializer = self.get_serializer(self.object)
|
||||||
|
|
|
@ -33,7 +33,7 @@ class NotifyPolicy(models.Model):
|
||||||
project user notifications preference.
|
project user notifications preference.
|
||||||
"""
|
"""
|
||||||
project = models.ForeignKey("projects.Project", related_name="notify_policies")
|
project = models.ForeignKey("projects.Project", related_name="notify_policies")
|
||||||
user = models.ForeignKey("users.User", related_name="notify_policies")
|
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="notify_policies")
|
||||||
notify_level = models.SmallIntegerField(choices=NOTIFY_LEVEL_CHOICES)
|
notify_level = models.SmallIntegerField(choices=NOTIFY_LEVEL_CHOICES)
|
||||||
|
|
||||||
created_at = models.DateTimeField(default=timezone.now)
|
created_at = models.DateTimeField(default=timezone.now)
|
||||||
|
@ -57,7 +57,7 @@ class HistoryChangeNotification(models.Model):
|
||||||
or updated when an object requires notifications.
|
or updated when an object requires notifications.
|
||||||
"""
|
"""
|
||||||
key = models.CharField(max_length=255, unique=False, editable=False)
|
key = models.CharField(max_length=255, unique=False, editable=False)
|
||||||
owner = models.ForeignKey("users.User", null=False, blank=False,
|
owner = models.ForeignKey(settings.AUTH_USER_MODEL, null=False, blank=False,
|
||||||
verbose_name=_("owner"), related_name="+")
|
verbose_name=_("owner"), related_name="+")
|
||||||
created_datetime = models.DateTimeField(null=False, blank=False, auto_now_add=True,
|
created_datetime = models.DateTimeField(null=False, blank=False, auto_now_add=True,
|
||||||
verbose_name=_("created date time"))
|
verbose_name=_("created date time"))
|
||||||
|
@ -66,7 +66,7 @@ class HistoryChangeNotification(models.Model):
|
||||||
history_entries = models.ManyToManyField("history.HistoryEntry",
|
history_entries = models.ManyToManyField("history.HistoryEntry",
|
||||||
verbose_name=_("history entries"),
|
verbose_name=_("history entries"),
|
||||||
related_name="+")
|
related_name="+")
|
||||||
notify_users = models.ManyToManyField("users.User",
|
notify_users = models.ManyToManyField(settings.AUTH_USER_MODEL,
|
||||||
verbose_name=_("notify users"),
|
verbose_name=_("notify users"),
|
||||||
related_name="+")
|
related_name="+")
|
||||||
project = models.ForeignKey("projects.Project", null=False, blank=False,
|
project = models.ForeignKey("projects.Project", null=False, blank=False,
|
||||||
|
|
|
@ -15,13 +15,10 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import json
|
|
||||||
|
|
||||||
from taiga.base.api import serializers
|
from taiga.base.api import serializers
|
||||||
from taiga.users.models import User
|
from taiga.users.models import get_user_model_safe
|
||||||
|
|
||||||
from . import models
|
from . import models
|
||||||
from . import choices
|
|
||||||
|
|
||||||
|
|
||||||
class NotifyPolicySerializer(serializers.ModelSerializer):
|
class NotifyPolicySerializer(serializers.ModelSerializer):
|
||||||
|
@ -39,5 +36,5 @@ class WatcherSerializer(serializers.ModelSerializer):
|
||||||
full_name = serializers.CharField(source='get_full_name', required=False)
|
full_name = serializers.CharField(source='get_full_name', required=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = get_user_model_safe()
|
||||||
fields = ('id', 'username', 'full_name')
|
fields = ('id', 'username', 'full_name')
|
||||||
|
|
|
@ -20,7 +20,6 @@ import datetime
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.db.transaction import atomic
|
|
||||||
from django.db import IntegrityError, transaction
|
from django.db import IntegrityError, transaction
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
@ -37,7 +36,6 @@ from taiga.projects.history.services import (make_key_from_model_object,
|
||||||
get_last_snapshot_for_key,
|
get_last_snapshot_for_key,
|
||||||
get_model_from_key)
|
get_model_from_key)
|
||||||
from taiga.permissions.service import user_has_perm
|
from taiga.permissions.service import user_has_perm
|
||||||
from taiga.users.models import User
|
|
||||||
|
|
||||||
from .models import HistoryChangeNotification, Watched
|
from .models import HistoryChangeNotification, Watched
|
||||||
|
|
||||||
|
@ -214,7 +212,7 @@ def send_notifications(obj, *, history):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
key = make_key_from_model_object(obj)
|
key = make_key_from_model_object(obj)
|
||||||
owner = User.objects.get(pk=history.user["pk"])
|
owner = get_user_model().objects.get(pk=history.user["pk"])
|
||||||
notification, created = (HistoryChangeNotification.objects.select_for_update()
|
notification, created = (HistoryChangeNotification.objects.select_for_update()
|
||||||
.get_or_create(key=key,
|
.get_or_create(key=key,
|
||||||
owner=owner,
|
owner=owner,
|
||||||
|
|
|
@ -22,8 +22,6 @@ import datetime
|
||||||
import copy
|
import copy
|
||||||
import collections
|
import collections
|
||||||
|
|
||||||
from taiga.projects.history.models import HistoryEntry
|
|
||||||
from taiga.projects.userstories.models import RolePoints
|
|
||||||
|
|
||||||
def _count_status_object(status_obj, counting_storage):
|
def _count_status_object(status_obj, counting_storage):
|
||||||
if status_obj.id in counting_storage:
|
if status_obj.id in counting_storage:
|
||||||
|
@ -228,6 +226,7 @@ def _get_milestones_stats_for_backlog(project, milestones):
|
||||||
def get_stats_for_project(project):
|
def get_stats_for_project(project):
|
||||||
# Let's fetch all the estimations related to a project with all the necesary
|
# Let's fetch all the estimations related to a project with all the necesary
|
||||||
# related data
|
# related data
|
||||||
|
RolePoints = apps.get_model('userstories', 'RolePoints')
|
||||||
role_points = RolePoints.objects.filter(
|
role_points = RolePoints.objects.filter(
|
||||||
user_story__project = project,
|
user_story__project = project,
|
||||||
).prefetch_related(
|
).prefetch_related(
|
||||||
|
@ -378,6 +377,7 @@ def _get_wiki_changes_per_member_stats(project):
|
||||||
# Wiki changes
|
# Wiki changes
|
||||||
wiki_changes = {}
|
wiki_changes = {}
|
||||||
wiki_page_keys = ["wiki.wikipage:%s"%id for id in project.wiki_pages.values_list("id", flat=True)]
|
wiki_page_keys = ["wiki.wikipage:%s"%id for id in project.wiki_pages.values_list("id", flat=True)]
|
||||||
|
HistoryEntry = apps.get_model('history', 'HistoryEntry')
|
||||||
history_entries = HistoryEntry.objects.filter(key__in=wiki_page_keys).values('user')
|
history_entries = HistoryEntry.objects.filter(key__in=wiki_page_keys).values('user')
|
||||||
for entry in history_entries:
|
for entry in history_entries:
|
||||||
editions = wiki_changes.get(entry["user"]["pk"], 0)
|
editions = wiki_changes.get(entry["user"]["pk"], 0)
|
||||||
|
|
|
@ -16,16 +16,14 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from taiga.base.api import serializers
|
from django.contrib.auth import get_user_model
|
||||||
from taiga.base.fields import TagsField
|
|
||||||
|
|
||||||
from taiga.users.models import User
|
from taiga.base.api import serializers
|
||||||
from taiga.users.services import get_photo_or_gravatar_url
|
|
||||||
|
|
||||||
|
|
||||||
class VoterSerializer(serializers.ModelSerializer):
|
class VoterSerializer(serializers.ModelSerializer):
|
||||||
full_name = serializers.CharField(source='get_full_name', required=False)
|
full_name = serializers.CharField(source='get_full_name', required=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = get_user_model()
|
||||||
fields = ('id', 'username', 'full_name')
|
fields = ('id', 'username', 'full_name')
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
@ -27,7 +28,7 @@ from collections import OrderedDict
|
||||||
###########################################################################
|
###########################################################################
|
||||||
|
|
||||||
def get_users_public_stats():
|
def get_users_public_stats():
|
||||||
model = apps.get_model("users", "User")
|
model = get_user_model()
|
||||||
queryset = model.objects.filter(is_active=True, is_system=False)
|
queryset = model.objects.filter(is_active=True, is_system=False)
|
||||||
stats = OrderedDict()
|
stats = OrderedDict()
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,8 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
from django.conf import settings
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
|
|
||||||
|
@ -49,7 +50,7 @@ class TimelineViewSet(ReadOnlyListViewSet):
|
||||||
page = self.paginate_queryset(queryset)
|
page = self.paginate_queryset(queryset)
|
||||||
if page is not None:
|
if page is not None:
|
||||||
user_ids = list(set([obj.data.get("user", {}).get("id", None) for obj in page.object_list]))
|
user_ids = list(set([obj.data.get("user", {}).get("id", None) for obj in page.object_list]))
|
||||||
User = apps.get_model("users", "User")
|
User = get_user_model()
|
||||||
users = {u.id: u for u in User.objects.filter(id__in=user_ids)}
|
users = {u.id: u for u in User.objects.filter(id__in=user_ids)}
|
||||||
|
|
||||||
for obj in page.object_list:
|
for obj in page.object_list:
|
||||||
|
@ -99,7 +100,7 @@ class TimelineViewSet(ReadOnlyListViewSet):
|
||||||
|
|
||||||
|
|
||||||
class ProfileTimeline(TimelineViewSet):
|
class ProfileTimeline(TimelineViewSet):
|
||||||
content_type = "users.user"
|
content_type = settings.AUTH_USER_MODEL.lower()
|
||||||
permission_classes = (permissions.UserTimelinePermission,)
|
permission_classes = (permissions.UserTimelinePermission,)
|
||||||
|
|
||||||
def get_timeline(self, user):
|
def get_timeline(self, user):
|
||||||
|
@ -107,7 +108,7 @@ class ProfileTimeline(TimelineViewSet):
|
||||||
|
|
||||||
|
|
||||||
class UserTimeline(TimelineViewSet):
|
class UserTimeline(TimelineViewSet):
|
||||||
content_type = "users.user"
|
content_type = settings.AUTH_USER_MODEL.lower()
|
||||||
permission_classes = (permissions.UserTimelinePermission,)
|
permission_classes = (permissions.UserTimelinePermission,)
|
||||||
|
|
||||||
def get_timeline(self, user):
|
def get_timeline(self, user):
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from django.db.models import signals
|
from django.db.models import signals
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,4 +36,4 @@ class TimelineAppConfig(AppConfig):
|
||||||
signals.post_delete.connect(handlers.delete_membership_push_to_timeline,
|
signals.post_delete.connect(handlers.delete_membership_push_to_timeline,
|
||||||
sender=apps.get_model("projects", "Membership"))
|
sender=apps.get_model("projects", "Membership"))
|
||||||
signals.post_save.connect(handlers.create_user_push_to_timeline,
|
signals.post_save.connect(handlers.create_user_push_to_timeline,
|
||||||
sender=apps.get_model("users", "User"))
|
sender=get_user_model())
|
||||||
|
|
|
@ -18,24 +18,22 @@
|
||||||
# Examples:
|
# Examples:
|
||||||
# python manage.py rebuild_timeline_for_user_creation --settings=settings.local_timeline
|
# python manage.py rebuild_timeline_for_user_creation --settings=settings.local_timeline
|
||||||
|
|
||||||
from django.conf import settings
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
from django.db.models import Model
|
from django.db.models import Model
|
||||||
from django.db import reset_queries
|
|
||||||
from django.test.utils import override_settings
|
from django.test.utils import override_settings
|
||||||
|
|
||||||
from taiga.timeline.service import (_get_impl_key_from_model,
|
from taiga.timeline.service import (_get_impl_key_from_model,
|
||||||
_timeline_impl_map, extract_user_info)
|
_timeline_impl_map, extract_user_info)
|
||||||
from taiga.timeline.models import Timeline
|
from taiga.timeline.models import Timeline
|
||||||
from taiga.timeline.signals import _push_to_timelines
|
from taiga.timeline.signals import _push_to_timelines
|
||||||
from taiga.users.models import User
|
|
||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
import gc
|
import gc
|
||||||
|
|
||||||
|
|
||||||
class BulkCreator(object):
|
class BulkCreator(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.timeline_objects = []
|
self.timeline_objects = []
|
||||||
|
@ -75,7 +73,7 @@ def custom_add_to_object_timeline(obj:object, instance:object, event_type:str, c
|
||||||
def generate_timeline():
|
def generate_timeline():
|
||||||
with patch('taiga.timeline.service._add_to_object_timeline', new=custom_add_to_object_timeline):
|
with patch('taiga.timeline.service._add_to_object_timeline', new=custom_add_to_object_timeline):
|
||||||
# Users api wasn't a HistoryResourceMixin so we can't interate on the HistoryEntries in this case
|
# Users api wasn't a HistoryResourceMixin so we can't interate on the HistoryEntries in this case
|
||||||
users = User.objects.order_by("date_joined")
|
users = get_user_model().objects.order_by("date_joined")
|
||||||
for user in users.iterator():
|
for user in users.iterator():
|
||||||
print("User:", user.date_joined)
|
print("User:", user.date_joined)
|
||||||
extra_data = {
|
extra_data = {
|
||||||
|
@ -87,6 +85,7 @@ def generate_timeline():
|
||||||
|
|
||||||
bulk_creator.flush()
|
bulk_creator.flush()
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = 'Regenerate project timeline'
|
help = 'Regenerate project timeline'
|
||||||
|
|
||||||
|
|
|
@ -20,24 +20,17 @@
|
||||||
# python manage.py rebuild_timeline --settings=settings.local_timeline --purge
|
# python manage.py rebuild_timeline --settings=settings.local_timeline --purge
|
||||||
# python manage.py rebuild_timeline --settings=settings.local_timeline --initial_date 2014-10-02
|
# python manage.py rebuild_timeline --settings=settings.local_timeline --initial_date 2014-10-02
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
from django.db.models import Model
|
from django.db.models import Model
|
||||||
from django.db import reset_queries
|
|
||||||
from django.test.utils import override_settings
|
from django.test.utils import override_settings
|
||||||
|
|
||||||
|
|
||||||
from taiga.projects.models import Project
|
from taiga.projects.models import Project
|
||||||
from taiga.projects.history import services as history_services
|
|
||||||
from taiga.projects.history.choices import HistoryType
|
|
||||||
from taiga.projects.history.models import HistoryEntry
|
from taiga.projects.history.models import HistoryEntry
|
||||||
from taiga.timeline.models import Timeline
|
from taiga.timeline.models import Timeline
|
||||||
from taiga.timeline.service import (_add_to_object_timeline, _get_impl_key_from_model,
|
from taiga.timeline.service import _get_impl_key_from_model,_timeline_impl_map, extract_user_info
|
||||||
_timeline_impl_map, extract_user_info)
|
|
||||||
from taiga.timeline.signals import on_new_history_entry, _push_to_timelines
|
from taiga.timeline.signals import on_new_history_entry, _push_to_timelines
|
||||||
from taiga.users.models import User
|
|
||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
from optparse import make_option
|
from optparse import make_option
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from django.forms import widgets
|
from django.forms import widgets
|
||||||
|
|
||||||
from taiga.base.api import serializers
|
from taiga.base.api import serializers
|
||||||
|
@ -37,7 +38,7 @@ class TimelineSerializer(serializers.ModelSerializer):
|
||||||
if hasattr(obj, "_prefetched_user"):
|
if hasattr(obj, "_prefetched_user"):
|
||||||
user = obj._prefetched_user
|
user = obj._prefetched_user
|
||||||
else:
|
else:
|
||||||
User = apps.get_model("users", "User")
|
User = get_user_model()
|
||||||
userData = obj.data.get("user", None)
|
userData = obj.data.get("user", None)
|
||||||
try:
|
try:
|
||||||
user = User.objects.get(id=userData["id"])
|
user = User.objects.get(id=userData["id"])
|
||||||
|
|
|
@ -16,14 +16,12 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from taiga.projects.history import services as history_services
|
from taiga.projects.history import services as history_services
|
||||||
from taiga.projects.models import Project
|
|
||||||
from taiga.users.models import User
|
|
||||||
from taiga.projects.history.choices import HistoryType
|
from taiga.projects.history.choices import HistoryType
|
||||||
from taiga.projects.notifications import services as notifications_services
|
|
||||||
from taiga.timeline.service import (push_to_timeline,
|
from taiga.timeline.service import (push_to_timeline,
|
||||||
build_user_namespace,
|
build_user_namespace,
|
||||||
build_project_namespace,
|
build_project_namespace,
|
||||||
|
@ -93,7 +91,7 @@ def on_new_history_entry(sender, instance, created, **kwargs):
|
||||||
elif instance.type == HistoryType.delete:
|
elif instance.type == HistoryType.delete:
|
||||||
event_type = "delete"
|
event_type = "delete"
|
||||||
|
|
||||||
user = User.objects.get(id=instance.user["pk"])
|
user = get_user_model().objects.get(id=instance.user["pk"])
|
||||||
values_diff = instance.values_diff
|
values_diff = instance.values_diff
|
||||||
_clean_description_fields(values_diff)
|
_clean_description_fields(values_diff)
|
||||||
|
|
||||||
|
|
|
@ -15,19 +15,22 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from importlib import import_module
|
||||||
|
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
import uuid
|
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
|
from django.apps.config import MODELS_MODULE_NAME
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.contrib.auth.models import UserManager, AbstractBaseUser
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
from django.core import validators
|
||||||
|
from django.core.exceptions import AppRegistryNotReady
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
from django.contrib.auth.models import UserManager, AbstractBaseUser
|
|
||||||
from django.core import validators
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from django_pgjson.fields import JsonField
|
from django_pgjson.fields import JsonField
|
||||||
from djorm_pgarray.fields import TextArrayField
|
from djorm_pgarray.fields import TextArrayField
|
||||||
|
@ -39,7 +42,42 @@ from taiga.permissions.permissions import MEMBERS_PERMISSIONS
|
||||||
from taiga.projects.choices import BLOCKED_BY_OWNER_LEAVING
|
from taiga.projects.choices import BLOCKED_BY_OWNER_LEAVING
|
||||||
from taiga.projects.notifications.choices import NotifyLevel
|
from taiga.projects.notifications.choices import NotifyLevel
|
||||||
|
|
||||||
from easy_thumbnails.files import get_thumbnailer
|
|
||||||
|
def get_user_model_safe():
|
||||||
|
"""
|
||||||
|
Fetches the user model using the app registry.
|
||||||
|
This doesn't require that an app with the given app label exists,
|
||||||
|
which makes it safe to call when the registry is being populated.
|
||||||
|
All other methods to access models might raise an exception about the
|
||||||
|
registry not being ready yet.
|
||||||
|
Raises LookupError if model isn't found.
|
||||||
|
|
||||||
|
Based on: https://github.com/django-oscar/django-oscar/blob/1.0/oscar/core/loading.py#L310-L340
|
||||||
|
Ongoing Django issue: https://code.djangoproject.com/ticket/22872
|
||||||
|
"""
|
||||||
|
user_app, user_model = settings.AUTH_USER_MODEL.split('.')
|
||||||
|
|
||||||
|
try:
|
||||||
|
return apps.get_model(user_app, user_model)
|
||||||
|
except AppRegistryNotReady:
|
||||||
|
if apps.apps_ready and not apps.models_ready:
|
||||||
|
# If this function is called while `apps.populate()` is
|
||||||
|
# loading models, ensure that the module that defines the
|
||||||
|
# target model has been imported and try looking the model up
|
||||||
|
# in the app registry. This effectively emulates
|
||||||
|
# `from path.to.app.models import Model` where we use
|
||||||
|
# `Model = get_model('app', 'Model')` instead.
|
||||||
|
app_config = apps.get_app_config(user_app)
|
||||||
|
# `app_config.import_models()` cannot be used here because it
|
||||||
|
# would interfere with `apps.populate()`.
|
||||||
|
import_module('%s.%s' % (app_config.name, MODELS_MODULE_NAME))
|
||||||
|
# In order to account for case-insensitivity of model_name,
|
||||||
|
# look up the model through a private API of the app registry.
|
||||||
|
return apps.get_registered_model(user_app, user_model)
|
||||||
|
else:
|
||||||
|
# This must be a different case (e.g. the model really doesn't
|
||||||
|
# exist). We just re-raise the exception.
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
def generate_random_hex_color():
|
def generate_random_hex_color():
|
||||||
|
@ -281,7 +319,7 @@ class Role(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class AuthData(models.Model):
|
class AuthData(models.Model):
|
||||||
user = models.ForeignKey("users.User", related_name="auth_data")
|
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="auth_data")
|
||||||
key = models.SlugField(max_length=50)
|
key = models.SlugField(max_length=50)
|
||||||
value = models.CharField(max_length=300)
|
value = models.CharField(max_length=300)
|
||||||
extra = JsonField()
|
extra = JsonField()
|
||||||
|
|
|
@ -20,6 +20,7 @@ This model contains a domain logic for users application.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -40,7 +41,7 @@ from .gravatar import get_gravatar_url
|
||||||
|
|
||||||
|
|
||||||
def get_user_by_username_or_email(username_or_email):
|
def get_user_by_username_or_email(username_or_email):
|
||||||
user_model = apps.get_model("users", "User")
|
user_model = get_user_model()
|
||||||
qs = user_model.objects.filter(Q(username__iexact=username_or_email) |
|
qs = user_model.objects.filter(Q(username__iexact=username_or_email) |
|
||||||
Q(email__iexact=username_or_email))
|
Q(email__iexact=username_or_email))
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,10 @@ def connect_webhooks_signals():
|
||||||
dispatch_uid="webhooks")
|
dispatch_uid="webhooks")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def disconnect_webhooks_signals():
|
def disconnect_webhooks_signals():
|
||||||
signals.post_save.disconnect(sender=HistoryEntry, dispatch_uid="webhooks")
|
signals.post_save.disconnect(sender=apps.get_model("history", "HistoryEntry"), dispatch_uid="webhooks")
|
||||||
|
|
||||||
|
|
||||||
class WebhooksAppConfig(AppConfig):
|
class WebhooksAppConfig(AppConfig):
|
||||||
|
|
|
@ -165,7 +165,7 @@ class WikiAttachmentFactory(Factory):
|
||||||
|
|
||||||
class UserFactory(Factory):
|
class UserFactory(Factory):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = "users.User"
|
model = settings.AUTH_USER_MODEL
|
||||||
strategy = factory.CREATE_STRATEGY
|
strategy = factory.CREATE_STRATEGY
|
||||||
|
|
||||||
username = factory.Sequence(lambda n: "user{}".format(n))
|
username = factory.Sequence(lambda n: "user{}".format(n))
|
||||||
|
|
|
@ -132,7 +132,6 @@ def test_valid_project_with_enough_public_projects_slots(client):
|
||||||
client.login(user)
|
client.login(user)
|
||||||
response = client.json.post(url, json.dumps(data))
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
|
||||||
print(response.content)
|
|
||||||
assert response.status_code == 201
|
assert response.status_code == 201
|
||||||
assert Project.objects.filter(slug="public-project-with-slots").count() == 1
|
assert Project.objects.filter(slug="public-project-with-slots").count() == 1
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,6 @@ def test_get_task_is_watcher(client):
|
||||||
assert response.data['is_watcher'] == False
|
assert response.data['is_watcher'] == False
|
||||||
|
|
||||||
response = client.post(url_watch)
|
response = client.post(url_watch)
|
||||||
print(response.data)
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from taiga.projects.models import Project
|
from django.contrib.auth import get_user_model
|
||||||
from taiga.users.models import User
|
|
||||||
|
|
||||||
|
from taiga.projects.models import Project
|
||||||
from taiga.base.utils.slug import slugify
|
from taiga.base.utils.slug import slugify
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -38,7 +38,7 @@ def test_slugify_3():
|
||||||
|
|
||||||
|
|
||||||
def test_project_slug_with_special_chars():
|
def test_project_slug_with_special_chars():
|
||||||
user = User.objects.create(username="test")
|
user = get_user_model().objects.create(username="test")
|
||||||
project = Project.objects.create(name="漢字", description="漢字", owner=user)
|
project = Project.objects.create(name="漢字", description="漢字", owner=user)
|
||||||
project.save()
|
project.save()
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ def test_project_slug_with_special_chars():
|
||||||
|
|
||||||
|
|
||||||
def test_project_with_existing_name_slug_with_special_chars():
|
def test_project_with_existing_name_slug_with_special_chars():
|
||||||
user = User.objects.create(username="test")
|
user = get_user_model().objects.create(username="test")
|
||||||
Project.objects.create(name="漢字", description="漢字", owner=user)
|
Project.objects.create(name="漢字", description="漢字", owner=user)
|
||||||
project = Project.objects.create(name="漢字", description="漢字", owner=user)
|
project = Project.objects.create(name="漢字", description="漢字", owner=user)
|
||||||
|
|
||||||
|
|
|
@ -18,19 +18,18 @@
|
||||||
|
|
||||||
from unittest.mock import patch, call
|
from unittest.mock import patch, call
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
from taiga.timeline import service
|
from taiga.timeline import service
|
||||||
from taiga.timeline.models import Timeline
|
from taiga.timeline.models import Timeline
|
||||||
from taiga.projects.models import Project
|
from taiga.projects.models import Project
|
||||||
from taiga.users.models import User
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
def test_push_to_timeline_many_objects():
|
def test_push_to_timeline_many_objects():
|
||||||
with patch("taiga.timeline.service._add_to_object_timeline") as mock:
|
with patch("taiga.timeline.service._add_to_object_timeline") as mock:
|
||||||
users = [User(), User(), User()]
|
users = [get_user_model(), get_user_model(), get_user_model()]
|
||||||
project = Project()
|
project = Project()
|
||||||
service.push_to_timeline(users, project, "test", project.created_date)
|
service.push_to_timeline(users, project, "test", project.created_date)
|
||||||
assert mock.call_count == 3
|
assert mock.call_count == 3
|
||||||
|
@ -45,7 +44,7 @@ def test_push_to_timeline_many_objects():
|
||||||
|
|
||||||
def test_add_to_objects_timeline():
|
def test_add_to_objects_timeline():
|
||||||
with patch("taiga.timeline.service._add_to_object_timeline") as mock:
|
with patch("taiga.timeline.service._add_to_object_timeline") as mock:
|
||||||
users = [User(), User(), User()]
|
users = [get_user_model(), get_user_model(), get_user_model()]
|
||||||
project = Project()
|
project = Project()
|
||||||
service._add_to_objects_timeline(users, project, "test", project.created_date)
|
service._add_to_objects_timeline(users, project, "test", project.created_date)
|
||||||
assert mock.call_count == 3
|
assert mock.call_count == 3
|
||||||
|
|
Loading…
Reference in New Issue