wbcore 1.61.3__py2.py3-none-any.whl → 1.61.4__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wbcore/configurations/base.py +2 -2
- wbcore/configurations/configurations/apps.py +1 -1
- wbcore/configurations/configurations/rest_framework.py +1 -1
- wbcore/contrib/agenda/viewsets/menu/calendar_items.py +1 -2
- wbcore/contrib/agenda/viewsets/menu/conference_room.py +4 -5
- wbcore/contrib/authentication/admin.py +15 -2
- wbcore/contrib/authentication/factories/users.py +4 -2
- wbcore/contrib/authentication/migrations/0008_user_is_internal.py +18 -0
- wbcore/contrib/authentication/models/users.py +16 -6
- wbcore/contrib/authentication/serializers/users.py +1 -1
- wbcore/contrib/authentication/viewsets/menu/user_activities.py +6 -3
- wbcore/contrib/authentication/viewsets/menu/users.py +1 -2
- wbcore/contrib/authentication/viewsets/users.py +2 -2
- wbcore/contrib/currency/tests/test_serializers.py +3 -1
- wbcore/contrib/directory/admin/entries.py +1 -1
- wbcore/contrib/directory/models/entries.py +21 -30
- wbcore/contrib/directory/tests/test_permissions.py +2 -4
- wbcore/contrib/directory/viewsets/endpoints/relationships.py +1 -2
- wbcore/contrib/directory/viewsets/entries.py +1 -1
- wbcore/contrib/directory/viewsets/menu/contacts.py +2 -3
- wbcore/contrib/directory/viewsets/menu/entries.py +5 -14
- wbcore/contrib/directory/viewsets/menu/relationships.py +2 -3
- wbcore/contrib/directory/viewsets/menu/utils.py +8 -9
- wbcore/contrib/documents/models/documents.py +1 -1
- wbcore/contrib/documents/viewsets/documents.py +3 -3
- wbcore/contrib/geography/viewsets/geography.py +1 -1
- wbcore/contrib/permission/apps.py +15 -0
- wbcore/contrib/permission/configurations.py +3 -0
- wbcore/contrib/{guardian → permission}/filters.py +2 -2
- wbcore/contrib/permission/internal/registry.py +43 -0
- wbcore/contrib/permission/management/__init__.py +4 -0
- wbcore/contrib/{guardian → permission}/models/mixins.py +73 -3
- wbcore/{permissions → contrib/permission}/permissions.py +1 -3
- wbcore/contrib/{guardian → permission}/tasks.py +1 -1
- wbcore/{tests/test_permissions → contrib/permission/tests}/test_backend.py +4 -6
- wbcore/contrib/{guardian → permission}/tests/test_model_mixins.py +6 -6
- wbcore/contrib/{guardian → permission}/tests/test_tasks.py +7 -7
- wbcore/contrib/{guardian → permission}/tests/test_utils.py +12 -12
- wbcore/contrib/{guardian → permission}/tests/test_viewsets.py +3 -3
- wbcore/contrib/{guardian → permission}/urls.py +1 -1
- wbcore/contrib/{guardian → permission}/utils.py +32 -4
- wbcore/contrib/{guardian → permission}/viewsets/configs/buttons.py +2 -2
- wbcore/contrib/{guardian → permission}/viewsets/configs/displays.py +1 -1
- wbcore/contrib/{guardian → permission}/viewsets/configs/endpoints.py +3 -3
- wbcore/contrib/{guardian → permission}/viewsets/configs/titles.py +1 -1
- wbcore/contrib/{guardian → permission}/viewsets/mixins.py +2 -2
- wbcore/contrib/{guardian → permission}/viewsets/viewsets.py +2 -2
- wbcore/contrib/workflow/viewsets/menu/condition.py +2 -3
- wbcore/contrib/workflow/viewsets/menu/data.py +2 -7
- wbcore/contrib/workflow/viewsets/menu/process.py +2 -5
- wbcore/contrib/workflow/viewsets/menu/step.py +16 -21
- wbcore/contrib/workflow/viewsets/menu/transition.py +2 -3
- wbcore/contrib/workflow/viewsets/menu/workflow.py +2 -5
- wbcore/tests/models.py +1 -1
- wbcore/urls.py +2 -2
- {wbcore-1.61.3.dist-info → wbcore-1.61.4.dist-info}/METADATA +1 -1
- {wbcore-1.61.3.dist-info → wbcore-1.61.4.dist-info}/RECORD +69 -70
- wbcore/contrib/guardian/apps.py +0 -6
- wbcore/contrib/guardian/configurations.py +0 -3
- wbcore/permissions/mixins.py +0 -72
- wbcore/permissions/registry.py +0 -33
- wbcore/permissions/shortcuts.py +0 -38
- wbcore/permissions/utils.py +0 -26
- /wbcore/contrib/{guardian → permission}/__init__.py +0 -0
- /wbcore/contrib/{guardian/migrations → permission/internal}/__init__.py +0 -0
- /wbcore/{permissions → contrib/permission/internal}/backend.py +0 -0
- /wbcore/contrib/{guardian → permission}/migrations/0001_initial.py +0 -0
- /wbcore/contrib/{guardian/tests → permission/migrations}/__init__.py +0 -0
- /wbcore/contrib/{guardian → permission}/models/__init__.py +0 -0
- /wbcore/contrib/{guardian → permission}/models/models.py +0 -0
- /wbcore/{permissions → contrib/permission/tests}/__init__.py +0 -0
- /wbcore/contrib/{guardian → permission}/tests/conftest.py +0 -0
- /wbcore/contrib/{guardian → permission}/viewsets/__init__.py +0 -0
- /wbcore/contrib/{guardian → permission}/viewsets/configs/__init__.py +0 -0
- {wbcore-1.61.3.dist-info → wbcore-1.61.4.dist-info}/WHEEL +0 -0
wbcore/configurations/base.py
CHANGED
|
@@ -6,9 +6,9 @@ from wbcore.contrib.authentication.configurations import (
|
|
|
6
6
|
AuthenticationConfigurationMixin,
|
|
7
7
|
)
|
|
8
8
|
from wbcore.contrib.directory.configurations import DirectoryConfigurationMixin
|
|
9
|
-
from wbcore.contrib.guardian.configurations import Guardian
|
|
10
9
|
from wbcore.contrib.io.configurations import ImportExportBaseConfiguration
|
|
11
10
|
from wbcore.contrib.notifications.configurations import NotificationConfiguration
|
|
11
|
+
from wbcore.contrib.permission.configurations import PermissionConfiguration
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class DevBaseConfiguration(
|
|
@@ -27,7 +27,7 @@ class DevBaseConfiguration(
|
|
|
27
27
|
configurations.Authentication,
|
|
28
28
|
configurations.DevMiddleware,
|
|
29
29
|
configurations.LocalStaticfiles,
|
|
30
|
-
|
|
30
|
+
PermissionConfiguration,
|
|
31
31
|
configurations.WBCore,
|
|
32
32
|
configurations.Celery,
|
|
33
33
|
configurations.I18NL10N,
|
|
@@ -17,7 +17,7 @@ class Restframework:
|
|
|
17
17
|
),
|
|
18
18
|
"DEFAULT_PERMISSION_CLASSES": (
|
|
19
19
|
"rest_framework.permissions.IsAuthenticated",
|
|
20
|
-
"wbcore.
|
|
20
|
+
"wbcore.contrib.permission.permissions.RestAPIModelPermissions",
|
|
21
21
|
),
|
|
22
22
|
"DATETIME_FORMAT": "%Y-%m-%dT%H:%M:%S%z",
|
|
23
23
|
"DEFAULT_THROTTLE_CLASSES": [
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
from django.utils.translation import gettext as _
|
|
2
2
|
|
|
3
3
|
from wbcore.menus import ItemPermission, MenuItem
|
|
4
|
-
from wbcore.permissions.shortcuts import is_internal_user
|
|
5
4
|
|
|
6
5
|
CALENDAR_MENUITEM = MenuItem(
|
|
7
6
|
label=_("Calendar"),
|
|
8
7
|
endpoint="wbcore:agenda:calendaritem-list",
|
|
9
8
|
permission=ItemPermission(
|
|
10
|
-
method=lambda request:
|
|
9
|
+
method=lambda request: request.user.is_internal, permissions=["agenda.view_calendaritem"]
|
|
11
10
|
),
|
|
12
11
|
)
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
from django.utils.translation import gettext as _
|
|
2
2
|
|
|
3
3
|
from wbcore.menus import ItemPermission, MenuItem
|
|
4
|
-
from wbcore.permissions.shortcuts import is_internal_user
|
|
5
4
|
|
|
6
5
|
BUILDING_MENUITEM = MenuItem(
|
|
7
6
|
label=_("Buildings"),
|
|
8
7
|
endpoint="wbcore:agenda:building-list",
|
|
9
8
|
permission=ItemPermission(
|
|
10
|
-
method=lambda request:
|
|
9
|
+
method=lambda request: request.user.is_internal,
|
|
11
10
|
permissions=["agenda.view_building"],
|
|
12
11
|
),
|
|
13
12
|
add=MenuItem(
|
|
14
13
|
label=_("Create Building"),
|
|
15
14
|
endpoint="wbcore:agenda:building-list",
|
|
16
15
|
permission=ItemPermission(
|
|
17
|
-
method=lambda request:
|
|
16
|
+
method=lambda request: request.user.is_internal,
|
|
18
17
|
permissions=["agenda.add_building"],
|
|
19
18
|
),
|
|
20
19
|
),
|
|
@@ -24,14 +23,14 @@ CONFERENCE_ROOM_MENUITEM = MenuItem(
|
|
|
24
23
|
label=_("Conference Rooms"),
|
|
25
24
|
endpoint="wbcore:agenda:conferenceroom-list",
|
|
26
25
|
permission=ItemPermission(
|
|
27
|
-
method=lambda request:
|
|
26
|
+
method=lambda request: request.user.is_internal,
|
|
28
27
|
permissions=["agenda.view_conferenceroom"],
|
|
29
28
|
),
|
|
30
29
|
add=MenuItem(
|
|
31
30
|
label=_("Create Conference Room"),
|
|
32
31
|
endpoint="wbcore:agenda:conferenceroom-list",
|
|
33
32
|
permission=ItemPermission(
|
|
34
|
-
method=lambda request:
|
|
33
|
+
method=lambda request: request.user.is_internal,
|
|
35
34
|
permissions=["agenda.add_conferenceroom"],
|
|
36
35
|
),
|
|
37
36
|
),
|
|
@@ -23,6 +23,8 @@ from django.utils.translation import gettext_lazy as _
|
|
|
23
23
|
from django.views.decorators.csrf import csrf_protect
|
|
24
24
|
from django.views.decorators.debug import sensitive_post_parameters
|
|
25
25
|
|
|
26
|
+
from wbcore.contrib.permission.internal.registry import UserBackendRegistry
|
|
27
|
+
|
|
26
28
|
from .models import Token, User, UserActivity
|
|
27
29
|
|
|
28
30
|
csrf_protect_m = method_decorator(csrf_protect)
|
|
@@ -93,8 +95,8 @@ class UserAdmin(admin.ModelAdmin):
|
|
|
93
95
|
add_form = UserCreationForm
|
|
94
96
|
change_password_form = AdminPasswordChangeForm
|
|
95
97
|
|
|
96
|
-
list_display = ("email", "username", "uuid", "is_staff", "is_active", "is_register")
|
|
97
|
-
list_filter = ("is_staff", "is_superuser", "is_active", "groups")
|
|
98
|
+
list_display = ("email", "username", "uuid", "is_staff", "is_active", "is_register", "is_internal")
|
|
99
|
+
list_filter = ("is_staff", "is_superuser", "is_active", "is_internal", "groups")
|
|
98
100
|
search_fields = ("email", "username")
|
|
99
101
|
ordering = ("email",)
|
|
100
102
|
filter_horizontal = (
|
|
@@ -245,3 +247,14 @@ class UserAdmin(admin.ModelAdmin):
|
|
|
245
247
|
request.POST = request.POST.copy()
|
|
246
248
|
request.POST["_continue"] = 1
|
|
247
249
|
return super(UserAdmin, self).response_add(request, obj, post_url_continue)
|
|
250
|
+
|
|
251
|
+
actions = ["reset_internal_user_cache"]
|
|
252
|
+
|
|
253
|
+
@admin.action(description=_("Reset Internal User Cache (select any user to activate)"))
|
|
254
|
+
def reset_internal_user_cache(self, request, queryset):
|
|
255
|
+
"""
|
|
256
|
+
Generic action that does not depend on selected objects.
|
|
257
|
+
"""
|
|
258
|
+
|
|
259
|
+
UserBackendRegistry().refresh_users(reset_all=True)
|
|
260
|
+
messages.success(request, _("User reset succesfully"))
|
|
@@ -5,7 +5,7 @@ from dynamic_preferences.registries import global_preferences_registry
|
|
|
5
5
|
|
|
6
6
|
from wbcore.contrib.directory.factories import CompanyFactory, PersonFactory
|
|
7
7
|
from wbcore.contrib.directory.models import Company
|
|
8
|
-
from wbcore.
|
|
8
|
+
from wbcore.contrib.permission.internal.registry import UserBackendRegistry
|
|
9
9
|
|
|
10
10
|
from ..models import Group, User
|
|
11
11
|
|
|
@@ -45,6 +45,8 @@ class UserFactory(factory.django.DjangoModelFactory):
|
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
class InternalUserFactory(UserFactory):
|
|
48
|
+
is_internal = True
|
|
49
|
+
|
|
48
50
|
@factory.post_generation
|
|
49
51
|
def add_internal_profile(self, create, extracted, **kwargs):
|
|
50
52
|
main_company_id = global_preferences_registry.manager()["directory__main_company"]
|
|
@@ -59,7 +61,7 @@ class InternalUserFactory(UserFactory):
|
|
|
59
61
|
self.user_permissions.add(
|
|
60
62
|
Permission.objects.get(content_type__app_label="authentication", codename="is_internal_user")
|
|
61
63
|
)
|
|
62
|
-
|
|
64
|
+
UserBackendRegistry().refresh_users()
|
|
63
65
|
|
|
64
66
|
|
|
65
67
|
class SuperUserFactory(UserFactory):
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Generated by Django 5.2.9 on 2026-01-26 12:25
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('authentication', '0007_alter_token_unique_together_token_unique_token'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AddField(
|
|
14
|
+
model_name='user',
|
|
15
|
+
name='is_internal',
|
|
16
|
+
field=models.BooleanField(default=False, help_text='If true, define this user as internal which grants specific permissions.', verbose_name='Internal'),
|
|
17
|
+
),
|
|
18
|
+
]
|
|
@@ -18,9 +18,20 @@ from wbcore.signals import pre_merge
|
|
|
18
18
|
from wbcore.utils.models import MergeError
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
class UserQuerySet(models.QuerySet):
|
|
22
|
+
def filter_internal(self):
|
|
23
|
+
return self.filter(is_internal=True)
|
|
24
|
+
|
|
25
|
+
|
|
21
26
|
class UserManager(BaseUserManager):
|
|
22
27
|
use_in_migrations = True
|
|
23
28
|
|
|
29
|
+
def get_queryset(self) -> UserQuerySet:
|
|
30
|
+
return UserQuerySet(self.model, using=self._db)
|
|
31
|
+
|
|
32
|
+
def filter_internal(self):
|
|
33
|
+
return self.get_queryset().filter_internal()
|
|
34
|
+
|
|
24
35
|
@classmethod
|
|
25
36
|
def normalize_username(cls, username):
|
|
26
37
|
return unicodedata.normalize("NFKC", force_str(username))
|
|
@@ -77,6 +88,11 @@ class User(AbstractBaseUser, PermissionsMixin):
|
|
|
77
88
|
is_register = models.BooleanField(
|
|
78
89
|
_("register"), default=True, help_text=_("Specifies whether this user has registered its email. ")
|
|
79
90
|
)
|
|
91
|
+
is_internal = models.BooleanField(
|
|
92
|
+
_("Internal"),
|
|
93
|
+
default=False,
|
|
94
|
+
help_text="If true, define this user as internal which grants specific permissions.",
|
|
95
|
+
)
|
|
80
96
|
date_joined = models.DateTimeField(_("date joined"), default=timezone.now)
|
|
81
97
|
metadata = models.JSONField(default=dict, blank=True)
|
|
82
98
|
|
|
@@ -91,12 +107,6 @@ class User(AbstractBaseUser, PermissionsMixin):
|
|
|
91
107
|
swappable = "AUTH_USER_MODEL"
|
|
92
108
|
permissions = [("administrate_user", "Administrate Users"), ("is_internal_user", "Internal User")]
|
|
93
109
|
|
|
94
|
-
@property
|
|
95
|
-
def is_internal(self):
|
|
96
|
-
from wbcore.permissions.registry import user_registry
|
|
97
|
-
|
|
98
|
-
return self in user_registry.internal_users
|
|
99
|
-
|
|
100
110
|
def get_full_name(self):
|
|
101
111
|
full_name = "%s %s" % (self.profile.first_name, self.profile.last_name)
|
|
102
112
|
return full_name.strip()
|
|
@@ -271,7 +271,7 @@ class UserProfileModelSerializer(wb_serializers.ModelSerializer):
|
|
|
271
271
|
resources["reset_settings"] = reverse(
|
|
272
272
|
"wbcore:authentication:userprofile-reset-settings", args=[instance.id], request=request
|
|
273
273
|
)
|
|
274
|
-
if user.
|
|
274
|
+
if user.is_internal:
|
|
275
275
|
resources["see_profile"] = reverse(
|
|
276
276
|
"wbcore:directory:person-detail", args=[instance.profile.id], request=request
|
|
277
277
|
)
|
|
@@ -6,35 +6,38 @@ USER_ACTIVITY_MENUITEM = MenuItem(
|
|
|
6
6
|
label=_("User Activity"),
|
|
7
7
|
endpoint="wbcore:authentication:useractivity-list",
|
|
8
8
|
permission=ItemPermission(
|
|
9
|
+
method=lambda request: request.user.is_internal,
|
|
9
10
|
permissions=[
|
|
10
11
|
"authentication.view_user",
|
|
11
12
|
"authentication.add_user",
|
|
12
13
|
"authentication.delete_user",
|
|
13
14
|
"authentication.change_user",
|
|
14
|
-
]
|
|
15
|
+
],
|
|
15
16
|
),
|
|
16
17
|
)
|
|
17
18
|
USER_ACTIVITY_TABLE_MENUITEM = MenuItem(
|
|
18
19
|
label=_("User Activity Table"),
|
|
19
20
|
endpoint="wbcore:authentication:useractivitytable-list",
|
|
20
21
|
permission=ItemPermission(
|
|
22
|
+
method=lambda request: request.user.is_internal,
|
|
21
23
|
permissions=[
|
|
22
24
|
"authentication.view_user",
|
|
23
25
|
"authentication.add_user",
|
|
24
26
|
"authentication.delete_user",
|
|
25
27
|
"authentication.change_user",
|
|
26
|
-
]
|
|
28
|
+
],
|
|
27
29
|
),
|
|
28
30
|
)
|
|
29
31
|
USER_ACTIVITY_CHART_MENUITEM = MenuItem(
|
|
30
32
|
label=_("User Activity Chart"),
|
|
31
33
|
endpoint="wbcore:authentication:useractivitychart-list",
|
|
32
34
|
permission=ItemPermission(
|
|
35
|
+
method=lambda request: request.user.is_internal,
|
|
33
36
|
permissions=[
|
|
34
37
|
"authentication.view_user",
|
|
35
38
|
"authentication.add_user",
|
|
36
39
|
"authentication.delete_user",
|
|
37
40
|
"authentication.change_user",
|
|
38
|
-
]
|
|
41
|
+
],
|
|
39
42
|
),
|
|
40
43
|
)
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
from django.utils.translation import gettext as _
|
|
2
2
|
|
|
3
3
|
from wbcore.menus import ItemPermission, MenuItem
|
|
4
|
-
from wbcore.permissions.shortcuts import is_internal_user
|
|
5
4
|
|
|
6
5
|
USER_MENUITEM = MenuItem(
|
|
7
6
|
label=_("Users"),
|
|
8
7
|
endpoint="wbcore:authentication:user-list",
|
|
9
8
|
permission=ItemPermission(
|
|
10
|
-
method=lambda request:
|
|
9
|
+
method=lambda request: request.user.is_internal, permissions=["authentication.view_user"]
|
|
11
10
|
),
|
|
12
11
|
add=MenuItem(
|
|
13
12
|
label=_("Create New User"),
|
|
@@ -200,7 +200,7 @@ class UserRepresentationViewSet(viewsets.RepresentationViewSet):
|
|
|
200
200
|
serializer_class = UserRepresentationSerializer
|
|
201
201
|
|
|
202
202
|
def get_queryset(self):
|
|
203
|
-
if self.request.user.
|
|
203
|
+
if self.request.user.is_internal:
|
|
204
204
|
return User.objects.all()
|
|
205
205
|
return User.objects.filter(id=self.request.user.id)
|
|
206
206
|
|
|
@@ -302,7 +302,7 @@ class UserModelViewSet(viewsets.ModelViewSet):
|
|
|
302
302
|
def get_queryset(self):
|
|
303
303
|
if self.request.user.has_perm("authentication.administrate_user"):
|
|
304
304
|
qs = User.objects.all()
|
|
305
|
-
elif self.request.user.
|
|
305
|
+
elif self.request.user.is_internal:
|
|
306
306
|
qs = User.objects.filter(profile__relationship_managers=self.request.user.profile)
|
|
307
307
|
else:
|
|
308
308
|
qs = User.objects.filter(id=self.request.user.id)
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from decimal import Decimal
|
|
2
|
+
|
|
1
3
|
import pytest
|
|
2
4
|
from django.utils import timezone
|
|
3
5
|
from pytest_mock import MockerFixture
|
|
@@ -42,7 +44,7 @@ class TestSerializers:
|
|
|
42
44
|
def expected_data_fx_rate(self, currency_fx_rate):
|
|
43
45
|
return {
|
|
44
46
|
"id": currency_fx_rate.id,
|
|
45
|
-
"value": currency_fx_rate.value,
|
|
47
|
+
"value": Decimal(currency_fx_rate.value),
|
|
46
48
|
"date": currency_fx_rate.date,
|
|
47
49
|
"currency": currency_fx_rate.currency_id,
|
|
48
50
|
}
|
|
@@ -232,4 +232,4 @@ class PersonAdmin(EntryAdmin):
|
|
|
232
232
|
if telephone and telephone.get("number", None):
|
|
233
233
|
TelephoneContact.objects.get_or_create(entry=obj, number=telephone["number"], defaults=telephone)
|
|
234
234
|
if email and email.get("address", None):
|
|
235
|
-
EmailContact.objects.get_or_create(
|
|
235
|
+
EmailContact.objects.get_or_create(address=email["address"], defaults={"entry": obj})
|
|
@@ -40,7 +40,6 @@ from wbcore.contrib.directory.models.relationships import (
|
|
|
40
40
|
from wbcore.contrib.directory.signals import deactivate_profile
|
|
41
41
|
from wbcore.contrib.directory.typings import Person as PersonDTO
|
|
42
42
|
from wbcore.models import WBModel
|
|
43
|
-
from wbcore.permissions.shortcuts import get_internal_users
|
|
44
43
|
from wbcore.utils.models import (
|
|
45
44
|
ActiveObjectManager,
|
|
46
45
|
ComplexToStringMixin,
|
|
@@ -233,7 +232,7 @@ class EntryDefaultQueryset(models.QuerySet):
|
|
|
233
232
|
)
|
|
234
233
|
|
|
235
234
|
def filter_only_internal(self) -> models.QuerySet:
|
|
236
|
-
return self.filter(id__in=
|
|
235
|
+
return self.filter(id__in=User.objects.filter_internal().values("profile"))
|
|
237
236
|
|
|
238
237
|
def annotate_all(self) -> models.QuerySet:
|
|
239
238
|
qs = self
|
|
@@ -620,7 +619,7 @@ class Person(Entry):
|
|
|
620
619
|
verbose_name = _("Person")
|
|
621
620
|
verbose_name_plural = _("Persons")
|
|
622
621
|
|
|
623
|
-
@
|
|
622
|
+
@property
|
|
624
623
|
def is_internal(self) -> bool:
|
|
625
624
|
if user := getattr(self, "user_account", None):
|
|
626
625
|
return user.is_internal
|
|
@@ -720,28 +719,18 @@ class Person(Entry):
|
|
|
720
719
|
if profile := getattr(user, "profile", None):
|
|
721
720
|
return profile
|
|
722
721
|
else:
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
):
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
first_name = usernames[0]
|
|
736
|
-
if not last_name and len(usernames) > 1:
|
|
737
|
-
last_name = usernames[1]
|
|
738
|
-
person = cls.objects.create(first_name=first_name, last_name=last_name)
|
|
739
|
-
EmailContact.objects.create(
|
|
740
|
-
primary=True,
|
|
741
|
-
location=ContactLocationChoices.WORK.name,
|
|
742
|
-
entry=person,
|
|
743
|
-
address=user.email,
|
|
744
|
-
)
|
|
722
|
+
contact = EmailContact.objects.get_or_create(address=user.email)[0]
|
|
723
|
+
if contact.entry:
|
|
724
|
+
with suppress(Person.DoesNotExist):
|
|
725
|
+
return Person.objects.get(id=contact.entry.id)
|
|
726
|
+
usernames = user.username.split("-")
|
|
727
|
+
if not first_name:
|
|
728
|
+
first_name = usernames[0]
|
|
729
|
+
if not last_name and len(usernames) > 1:
|
|
730
|
+
last_name = usernames[1]
|
|
731
|
+
person = cls.objects.create(first_name=first_name.title(), last_name=last_name.title())
|
|
732
|
+
contact.entry_id = person.id
|
|
733
|
+
contact.save()
|
|
745
734
|
return person
|
|
746
735
|
|
|
747
736
|
@classmethod
|
|
@@ -753,13 +742,15 @@ class Person(Entry):
|
|
|
753
742
|
user {User} -- The user used to generate the profile
|
|
754
743
|
"""
|
|
755
744
|
|
|
756
|
-
person = cls.objects.create(first_name=first_name, last_name=last_name)
|
|
745
|
+
person = cls.objects.create(first_name=first_name.title(), last_name=last_name.title())
|
|
757
746
|
if email:
|
|
758
|
-
EmailContact.objects.
|
|
759
|
-
primary=True,
|
|
760
|
-
location=ContactLocationChoices.WORK.name,
|
|
761
|
-
entry=person,
|
|
747
|
+
EmailContact.objects.get_or_create(
|
|
762
748
|
address=email,
|
|
749
|
+
defaults={
|
|
750
|
+
"primary": True,
|
|
751
|
+
"location": ContactLocationChoices.WORK.name,
|
|
752
|
+
"entry": person,
|
|
753
|
+
},
|
|
763
754
|
)
|
|
764
755
|
|
|
765
756
|
return person
|
|
@@ -57,10 +57,8 @@ class TestEntryPermissionQueryset:
|
|
|
57
57
|
Test that internal user can see everything
|
|
58
58
|
"""
|
|
59
59
|
user, anonymous_profile, any_person, any_company, employer, colleague, client = entry_fixtures
|
|
60
|
-
user.
|
|
61
|
-
|
|
62
|
-
)
|
|
63
|
-
user = User.objects.get(id=user.id)
|
|
60
|
+
user.is_internal = True
|
|
61
|
+
user.save()
|
|
64
62
|
|
|
65
63
|
assert set(Entry.objects.filter_for_user(user)) == {
|
|
66
64
|
user.profile.entry_ptr,
|
|
@@ -2,7 +2,6 @@ from rest_framework.reverse import reverse
|
|
|
2
2
|
|
|
3
3
|
from wbcore.contrib.directory.models import ClientManagerRelationship
|
|
4
4
|
from wbcore.metadata.configs.endpoints import EndpointViewConfig
|
|
5
|
-
from wbcore.permissions.shortcuts import is_internal_user
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
class RelationshipEntryModelEndpoint(EndpointViewConfig):
|
|
@@ -76,6 +75,6 @@ class UserIsClientEndpointConfig(EndpointViewConfig):
|
|
|
76
75
|
return None
|
|
77
76
|
|
|
78
77
|
def get_instance_endpoint(self, **kwargs):
|
|
79
|
-
if
|
|
78
|
+
if self.request.user.is_internal:
|
|
80
79
|
return reverse("wbcore:directory:person-list", request=self.request)
|
|
81
80
|
return None
|
|
@@ -122,7 +122,7 @@ class EntryModelViewSet(MergeMixin, EntryPermissionMixin, TransparencyMixin, vie
|
|
|
122
122
|
|
|
123
123
|
@cached_property
|
|
124
124
|
def is_internal_user(self):
|
|
125
|
-
return self.request.user.
|
|
125
|
+
return self.request.user.is_internal
|
|
126
126
|
|
|
127
127
|
|
|
128
128
|
class PersonModelViewSet(ModelTranslateMixin, EntryModelViewSet):
|
|
@@ -2,14 +2,13 @@ from django.utils.translation import gettext as _
|
|
|
2
2
|
|
|
3
3
|
from wbcore.contrib.directory.models import BankingContact
|
|
4
4
|
from wbcore.menus import ItemPermission, MenuItem
|
|
5
|
-
from wbcore.permissions.shortcuts import is_internal_user
|
|
6
5
|
|
|
7
6
|
PENDING_BANKINGCONTACT_MENUITEM = MenuItem(
|
|
8
7
|
label=_("Pending Banking Contacts"),
|
|
9
8
|
endpoint="wbcore:directory:bankingcontact-list",
|
|
10
9
|
endpoint_get_parameters={"status": BankingContact.Status.PENDING.value},
|
|
11
10
|
permission=ItemPermission(
|
|
12
|
-
method=lambda request:
|
|
11
|
+
method=lambda request: request.user.is_internal,
|
|
13
12
|
permissions=[
|
|
14
13
|
"directory.view_bankingcontact",
|
|
15
14
|
"directory.administrate_banking_contact",
|
|
@@ -21,6 +20,6 @@ TELEPHONECONTACTSEARCH_MENUITEM = MenuItem(
|
|
|
21
20
|
label=_("Search by Telephone Contact"),
|
|
22
21
|
endpoint="wbcore:directory:telephonecontact-list",
|
|
23
22
|
permission=ItemPermission(
|
|
24
|
-
method=lambda request:
|
|
23
|
+
method=lambda request: request.user.is_internal, permissions=["directory.view_telephonecontact"]
|
|
25
24
|
),
|
|
26
25
|
)
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
from django.utils.translation import gettext as _
|
|
2
2
|
|
|
3
3
|
from wbcore.menus import ItemPermission, MenuItem
|
|
4
|
-
from wbcore.permissions.shortcuts import is_internal_user
|
|
5
4
|
|
|
6
5
|
YOUR_CONTACT_MENUITEM = MenuItem(
|
|
7
6
|
label=_("Your Contact"),
|
|
8
7
|
endpoint="wbcore:directory:clientmanagerrelationship-userclient-list",
|
|
9
|
-
permission=ItemPermission(method=lambda request: request.user.is_active and not request.user.
|
|
8
|
+
permission=ItemPermission(method=lambda request: request.user.is_active and not request.user.is_internal),
|
|
10
9
|
)
|
|
11
10
|
|
|
12
11
|
COMPANY_MENUITEM = MenuItem(
|
|
@@ -33,30 +32,22 @@ PERSON_MENUITEM = MenuItem(
|
|
|
33
32
|
SYSTEMEMPLOYEE_MENUITEM = MenuItem(
|
|
34
33
|
label=_("Employees"),
|
|
35
34
|
endpoint="wbcore:directory:systememployee-list",
|
|
36
|
-
permission=ItemPermission(
|
|
37
|
-
method=lambda request: is_internal_user(request.user), permissions=["directory.view_person"]
|
|
38
|
-
),
|
|
35
|
+
permission=ItemPermission(method=lambda request: request.user.is_internal, permissions=["directory.view_person"]),
|
|
39
36
|
)
|
|
40
37
|
|
|
41
38
|
BANK_MENUITEM = MenuItem(
|
|
42
39
|
label=_("Banks"),
|
|
43
40
|
endpoint="wbcore:directory:bank-list",
|
|
44
|
-
permission=ItemPermission(
|
|
45
|
-
method=lambda request: is_internal_user(request.user), permissions=["directory.view_bank"]
|
|
46
|
-
),
|
|
41
|
+
permission=ItemPermission(method=lambda request: request.user.is_internal, permissions=["directory.view_bank"]),
|
|
47
42
|
add=MenuItem(
|
|
48
43
|
label=_("Create Bank"),
|
|
49
44
|
endpoint="wbcore:directory:bank-list",
|
|
50
|
-
permission=ItemPermission(
|
|
51
|
-
method=lambda request: is_internal_user(request.user), permissions=["directory.add_bank"]
|
|
52
|
-
),
|
|
45
|
+
permission=ItemPermission(method=lambda request: request.user.is_internal, permissions=["directory.add_bank"]),
|
|
53
46
|
),
|
|
54
47
|
)
|
|
55
48
|
|
|
56
49
|
USERISMANAGER_MENUITEM = MenuItem(
|
|
57
50
|
label=_("Your Clients/Prospects/Contacts"),
|
|
58
51
|
endpoint="wbcore:directory:clientmanagerrelationship-usermanager-list",
|
|
59
|
-
permission=ItemPermission(
|
|
60
|
-
method=lambda request: is_internal_user(request.user), permissions=["directory.view_person"]
|
|
61
|
-
),
|
|
52
|
+
permission=ItemPermission(method=lambda request: request.user.is_internal, permissions=["directory.view_person"]),
|
|
62
53
|
)
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
from django.utils.translation import gettext as _
|
|
2
2
|
|
|
3
3
|
from wbcore.menus import ItemPermission, MenuItem
|
|
4
|
-
from wbcore.permissions.shortcuts import is_internal_user
|
|
5
4
|
|
|
6
5
|
RELATIONSHIPTYPE_MENUITEM = MenuItem(
|
|
7
6
|
label=_("Relationship Types"),
|
|
8
7
|
endpoint="wbcore:directory:relationship-type-list",
|
|
9
8
|
permission=ItemPermission(
|
|
10
|
-
method=lambda request:
|
|
9
|
+
method=lambda request: request.user.is_internal,
|
|
11
10
|
permissions=["directory.view_relationshiptype"],
|
|
12
11
|
),
|
|
13
12
|
add=MenuItem(
|
|
14
13
|
label=_("Create Relationship Type"),
|
|
15
14
|
endpoint="wbcore:directory:relationship-type-list",
|
|
16
15
|
permission=ItemPermission(
|
|
17
|
-
method=lambda request:
|
|
16
|
+
method=lambda request: request.user.is_internal,
|
|
18
17
|
permissions=["directory.add_relationshiptype"],
|
|
19
18
|
),
|
|
20
19
|
),
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
from django.utils.translation import gettext as _
|
|
2
2
|
|
|
3
3
|
from wbcore.menus import ItemPermission, MenuItem
|
|
4
|
-
from wbcore.permissions.shortcuts import is_internal_user
|
|
5
4
|
|
|
6
5
|
POSITION_MENUITEM = MenuItem(
|
|
7
6
|
label=_("Company Positions"),
|
|
8
7
|
endpoint="wbcore:directory:position-list",
|
|
9
8
|
permission=ItemPermission(
|
|
10
|
-
method=lambda request:
|
|
9
|
+
method=lambda request: request.user.is_internal,
|
|
11
10
|
permissions=["directory.view_position"],
|
|
12
11
|
),
|
|
13
12
|
add=MenuItem(
|
|
14
13
|
label=_("Create Position"),
|
|
15
14
|
endpoint="wbcore:directory:position-list",
|
|
16
15
|
permission=ItemPermission(
|
|
17
|
-
method=lambda request:
|
|
16
|
+
method=lambda request: request.user.is_internal,
|
|
18
17
|
permissions=["directory.add_position"],
|
|
19
18
|
),
|
|
20
19
|
),
|
|
@@ -24,14 +23,14 @@ CUSTOMERSTATUS_MENUITEM = MenuItem(
|
|
|
24
23
|
label=_("Customer Statuses"),
|
|
25
24
|
endpoint="wbcore:directory:customerstatus-list",
|
|
26
25
|
permission=ItemPermission(
|
|
27
|
-
method=lambda request:
|
|
26
|
+
method=lambda request: request.user.is_internal,
|
|
28
27
|
permissions=["directory.view_customerstatus"],
|
|
29
28
|
),
|
|
30
29
|
add=MenuItem(
|
|
31
30
|
label=_("Create Customer Status"),
|
|
32
31
|
endpoint="wbcore:directory:customerstatus-list",
|
|
33
32
|
permission=ItemPermission(
|
|
34
|
-
method=lambda request:
|
|
33
|
+
method=lambda request: request.user.is_internal,
|
|
35
34
|
permissions=["directory.add_customerstatus"],
|
|
36
35
|
),
|
|
37
36
|
),
|
|
@@ -41,14 +40,14 @@ COMPANYTYPE_MENUITEM = MenuItem(
|
|
|
41
40
|
label=_("Company Types"),
|
|
42
41
|
endpoint="wbcore:directory:companytype-list",
|
|
43
42
|
permission=ItemPermission(
|
|
44
|
-
method=lambda request:
|
|
43
|
+
method=lambda request: request.user.is_internal,
|
|
45
44
|
permissions=["directory.view_companytype"],
|
|
46
45
|
),
|
|
47
46
|
add=MenuItem(
|
|
48
47
|
label=_("Create Company Type"),
|
|
49
48
|
endpoint="wbcore:directory:companytype-list",
|
|
50
49
|
permission=ItemPermission(
|
|
51
|
-
method=lambda request:
|
|
50
|
+
method=lambda request: request.user.is_internal,
|
|
52
51
|
permissions=["directory.add_companytype"],
|
|
53
52
|
),
|
|
54
53
|
),
|
|
@@ -59,14 +58,14 @@ SPECIALIZATION_MENUITEM = MenuItem(
|
|
|
59
58
|
label=_("Specializations"),
|
|
60
59
|
endpoint="wbcore:directory:specialization-list",
|
|
61
60
|
permission=ItemPermission(
|
|
62
|
-
method=lambda request:
|
|
61
|
+
method=lambda request: request.user.is_internal,
|
|
63
62
|
permissions=["directory.view_specialization"],
|
|
64
63
|
),
|
|
65
64
|
add=MenuItem(
|
|
66
65
|
label=_("Create Specialization"),
|
|
67
66
|
endpoint="wbcore:directory:specialization-list",
|
|
68
67
|
permission=ItemPermission(
|
|
69
|
-
method=lambda request:
|
|
68
|
+
method=lambda request: request.user.is_internal,
|
|
70
69
|
permissions=["directory.add_specialization"],
|
|
71
70
|
),
|
|
72
71
|
),
|
|
@@ -22,7 +22,7 @@ from django.utils.translation import gettext_lazy as _
|
|
|
22
22
|
from slugify import slugify
|
|
23
23
|
|
|
24
24
|
from wbcore.contrib.authentication.models import User
|
|
25
|
-
from wbcore.contrib.
|
|
25
|
+
from wbcore.contrib.permission.models.mixins import PermissionObjectModelMixin
|
|
26
26
|
from wbcore.models import WBModel
|
|
27
27
|
from wbcore.utils.html import convert_html2text
|
|
28
28
|
from wbcore.workers import Queue
|