accrete 0.0.138__py3-none-any.whl → 0.0.140__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.
@@ -7,6 +7,7 @@ from . context import (
7
7
  TableContext,
8
8
  TableRowContext,
9
9
  ModalContext,
10
- OobContext
10
+ OobContext,
11
+ MessageContext
11
12
  )
12
13
  from .utils import modal_response, add_trigger
@@ -116,3 +116,10 @@ class OobContext(BaseContext):
116
116
  'tag': self.tag
117
117
  }})
118
118
  return res
119
+
120
+
121
+ @dataclass(kw_only=True)
122
+ class MessageContext(BaseContext):
123
+
124
+ persistent: bool = False
125
+ append: bool = False
@@ -33,8 +33,6 @@ class Filter:
33
33
  LABEL_OR = _('Or')
34
34
  LABEL_XOR = _('Not Or')
35
35
 
36
- # EXCLUDE = ['tenant']
37
-
38
36
  DATE_FORMAT = '%Y-%m-%d'
39
37
 
40
38
  TYPES_INTEGER = [
@@ -1,7 +1,7 @@
1
1
  {% load i18n %}
2
2
 
3
3
  {% if form.non_field_errors or form.save_error %}
4
- <div class="notification is-danger is-light">
4
+ <div class="notification is-danger is-light" style="word-wrap: break-word;">
5
5
  {{ form.non_field_errors }}
6
6
  {% if form.save_error %}
7
7
  <p>{{ form.save_error }}</p>
@@ -203,7 +203,7 @@
203
203
  <div id="content-right-header" class="is-flex is-flex-wrap-wrap">
204
204
  {% block header_right %}{% endblock %}
205
205
  </div>
206
- <button class="button is-subtle is-align-self-baseline m-1" style="border-radius: var(--bulma-radius-rounded)" x-on:click="showContentRight = false;">
206
+ <button class="button is-light is-align-self-baseline m-1" style="border-radius: var(--bulma-radius-medium)" x-on:click="showContentRight = false;">
207
207
  <span class="icon"><i class="fa fa-xmark"></i></span>
208
208
  </button>
209
209
  </div>
@@ -10,11 +10,11 @@
10
10
  <div id="list-entry-{{ object.pk }}" class="list-entry cell pb-0" style="height: {{ column_height }}{{ column_height_unit }}">
11
11
  <div class="box p-3"
12
12
  style="word-break: break-word; height: 100%; overflow-y: auto; {% if object.get_absolute_url %}cursor:pointer;{% endif %}"
13
- {% if object.get_absolute_url %}
14
- hx-get="{{ object.get_absolute_url }}{% querystring %}" hx-target="#content-right-header" hx-select="#content-right-header" hx-select-oob="#content-right" hx-swap="outerHTML"
15
- {% if detail_enabled %}
16
- x-on:click="$dispatch('unselect-list-entry'); showContentRight = true; selected = true; $nextTick(() => { $el.scrollIntoView( {block: 'nearest'} ) });" x-bind:class="selected ? 'box selected' : ''"
17
- {% endif %}
13
+ {% if object.get_absolute_url and detail_enabled %}
14
+ hx-get="{{ object.get_absolute_url }}{% querystring %}" hx-target="#content-right-header" hx-select="#content-right-header" hx-select-oob="#content-right" hx-swap="outerHTML"
15
+ x-on:click="$dispatch('unselect-list-entry'); showContentRight = true; selected = true; $nextTick(() => { $el.scrollIntoView( {block: 'nearest'} ) });" x-bind:class="selected ? 'box selected' : ''"
16
+ {% elif object.get_absolute_url and not detail_enabled %}
17
+ hx-get="{{ object.get_absolute_url }}{% querystring %}" hx-target="body" hx-push-url="true"
18
18
  {% endif %}
19
19
  x-data="{selected: false}" @unselect-list-entry.window="selected = false"
20
20
  >
@@ -2,10 +2,11 @@
2
2
 
3
3
  {% if messages %}
4
4
  {% for message in messages %}
5
- <div hx-swap-oob="beforeend:#message">
6
- <div class="mb-2" style="min-width: 330px; max-width: 330px" x-data="{ show: false }" x-show="show" x-cloak="" x-init="show = true; setTimeout(() => show = false, 4000)" x-transition.duration.200ms>
7
- <div class="notification has-text-centered is-light {{ message|message_class }}">
8
- <p>{{ message }}</p>
5
+ <div hx-swap-oob="{% if append %}beforeend:#message{% else %}innerHTML:#message{% endif %}">
6
+ <div class="mb-2" style="min-width: 340px; max-width: 340px" x-data="{ show: false }" x-show="show" x-cloak="" x-init="show = true; {% if not persistent %}setTimeout(() => show = false, 4000){% endif %}" x-transition.duration.200ms>
7
+ <div class="notification has-text-centered {{ message|message_class }}">
8
+ {% if persistent %}<button class="delete" x-on:click="show = false;"></button>{% endif %}
9
+ {{ message }}
9
10
  </div>
10
11
  </div>
11
12
  </div>
@@ -12,10 +12,10 @@
12
12
  <button id="{{ modal_id }}-background" class="modal-background" @click="$dispatch('close-modal-{{ modal_id }}')" style="cursor: default"></button>
13
13
  <div class="modal-card" x-show="showModal" x-transition.duration.200ms x-init="$nextTick(() => {showModal = true;})" >
14
14
  <header class="modal-card-head">
15
- <p class="modal-card-title">
15
+ <p class="modal-card-title is-flex-shrink-1">
16
16
  {{ title }}
17
17
  </p>
18
- <button class="delete" aria-label="close" @click="$dispatch('close-modal-{{ modal_id }}')"></button>
18
+ <button class="delete is-align-self-baseline" aria-label="close" @click="$dispatch('close-modal-{{ modal_id }}')"></button>
19
19
  </header>
20
20
  <section class="modal-card-body">
21
21
  {% block modal_content %}{% endblock %}
@@ -0,0 +1,23 @@
1
+ # Generated by Django 5.1.7 on 2025-03-23 08:11
2
+
3
+ import accrete.contrib.user.models
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ('user', '0007_user_managed_login'),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.RemoveConstraint(
15
+ model_name='user',
16
+ name='no_email_for_managed_user',
17
+ ),
18
+ migrations.AlterField(
19
+ model_name='user',
20
+ name='language_code',
21
+ field=models.CharField(blank=True, default=accrete.contrib.user.models.default_language_code, max_length=10, null=True, verbose_name='Language'),
22
+ ),
23
+ ]
@@ -35,6 +35,10 @@ def validate_member_login(login: str) -> None:
35
35
  raise ValidationError(message)
36
36
 
37
37
 
38
+ def default_language_code():
39
+ return settings.LANGUAGE_CODE
40
+
41
+
38
42
  class UserManager(BaseUserManager):
39
43
  use_in_migrations = True
40
44
 
@@ -87,11 +91,6 @@ class User(AbstractBaseUser, PermissionsMixin):
87
91
  name='email_or_login_set',
88
92
  violation_error_message='E-Mail or Login must be set'
89
93
  ),
90
- models.CheckConstraint(
91
- condition=Q(is_managed=False, email__isnull=False) | Q(is_managed=True, email__isnull=True),
92
- name='no_email_for_managed_user',
93
- violation_error_message='Managed users must not have an E-Mail address'
94
- ),
95
94
  models.CheckConstraint(
96
95
  condition=Q(is_managed=True, login__isnull=False) | Q(is_managed=False),
97
96
  name='managed_login',
@@ -99,10 +98,6 @@ class User(AbstractBaseUser, PermissionsMixin):
99
98
  )
100
99
  ]
101
100
 
102
- filter_exclude = [
103
- 'password'
104
- ]
105
-
106
101
  username_validator = UnicodeUsernameValidator()
107
102
  login_validator = validate_member_login
108
103
 
@@ -178,7 +173,8 @@ class User(AbstractBaseUser, PermissionsMixin):
178
173
  verbose_name=_('Language'),
179
174
  max_length=10,
180
175
  null=True,
181
- blank=True
176
+ blank=True,
177
+ default=default_language_code
182
178
  )
183
179
 
184
180
  theme = models.CharField(
@@ -211,3 +207,7 @@ class User(AbstractBaseUser, PermissionsMixin):
211
207
  def all_tenants(self):
212
208
  tenants = Tenant.objects.filter(members__user=self)
213
209
  return tenants
210
+
211
+ @staticmethod
212
+ def exclude_from_filter():
213
+ return ['password']
@@ -80,7 +80,7 @@ def user_change_password(request):
80
80
  + f'?{request.GET.urlencode()}'
81
81
  )
82
82
  ctx.update(form=form)
83
- return ui.modal_response(request, 'user/change_password.html', ctx)
83
+ return ui.modal_response(request, 'user/change_password.html', ctx, update=True)
84
84
  return render(request, 'user/change_password.html', ctx)
85
85
 
86
86
 
@@ -103,5 +103,5 @@ def user_change_email(request):
103
103
  if form.is_saved:
104
104
  return redirect('user:detail')
105
105
  ctx.update(form=form)
106
- return ui.modal_response(request, 'user/change_email.html', ctx)
106
+ return ui.modal_response(request, 'user/change_email.html', ctx, update=True)
107
107
  return render(request, 'user/change_email.html', ctx)
@@ -0,0 +1,21 @@
1
+ # Generated by Django 5.1.7 on 2025-03-23 10:21
2
+
3
+ import django.db.models.deletion
4
+ from django.conf import settings
5
+ from django.db import migrations, models
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ dependencies = [
11
+ ('accrete', '0005_accessgroup_apply_on_alter_member_access_groups_and_more'),
12
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
13
+ ]
14
+
15
+ operations = [
16
+ migrations.AlterField(
17
+ model_name='member',
18
+ name='user',
19
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='memberships', to=settings.AUTH_USER_MODEL),
20
+ ),
21
+ ]
@@ -0,0 +1,18 @@
1
+ # Generated by Django 5.1.7 on 2025-03-31 20:23
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('accrete', '0006_alter_member_user'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name='accessgroup',
15
+ name='description',
16
+ field=models.TextField(blank=True, null=True, verbose_name='Description'),
17
+ ),
18
+ ]
accrete/models.py CHANGED
@@ -90,7 +90,7 @@ class Member(models.Model):
90
90
  user = models.ForeignKey(
91
91
  to=settings.AUTH_USER_MODEL,
92
92
  related_name='memberships',
93
- on_delete=models.PROTECT
93
+ on_delete=models.CASCADE
94
94
  )
95
95
 
96
96
  tenant = models.ForeignKey(
@@ -136,6 +136,12 @@ class AccessGroup(models.Model):
136
136
  max_length=255
137
137
  )
138
138
 
139
+ description = models.TextField(
140
+ verbose_name=_('Description'),
141
+ null=True,
142
+ blank=True
143
+ )
144
+
139
145
  code = models.CharField(
140
146
  verbose_name=_('Code'),
141
147
  max_length=100
accrete/tenant.py CHANGED
@@ -39,11 +39,6 @@ class Unscoped:
39
39
  self.tenant = tenant
40
40
 
41
41
  def __enter__(self):
42
- if self.tenant is None:
43
- _logger.warning(
44
- 'Entering unscoped context manager with tenant already set to None!',
45
- stack_info=True
46
- )
47
42
  set_tenant(False)
48
43
 
49
44
  def __exit__(self, exc_type, exc_val, exc_tb):
@@ -57,7 +52,7 @@ def unscoped():
57
52
  def per_tenant(include: Q = None, exclude: Q = None):
58
53
  def decorator(f):
59
54
  def wrapper(*args, **kwargs):
60
- tenants: QuerySet = apps.get_model('accrete', 'Tenant').objects.all()
55
+ tenants = apps.get_model('accrete', 'Tenant').objects.all()
61
56
  if include is not None:
62
57
  tenants = tenants.filter(include)
63
58
  if exclude is not None:
@@ -74,6 +69,15 @@ def per_tenant(include: Q = None, exclude: Q = None):
74
69
  return decorator
75
70
 
76
71
 
72
+ def unscope():
73
+ def decorator(f):
74
+ def wrapper(*args, **kwargs):
75
+ with unscoped():
76
+ f(*args, **kwargs)
77
+ return wrapper
78
+ return decorator
79
+
80
+
77
81
  def tenant_has_group(access_group_code: str) -> bool:
78
82
  tenant = get_tenant()
79
83
  if not tenant:
accrete/utils/views.py CHANGED
@@ -141,8 +141,7 @@ def method_not_allowed(method: str, allowed: list[str]) -> HttpResponseNotAllowe
141
141
  def render_templates(
142
142
  templates: list[str | tuple[str, dict]],
143
143
  context: dict = None,
144
- request=None,
145
- log_not_found: bool = False
144
+ request=None
146
145
  ) -> str:
147
146
  context = {} if context is None else context
148
147
  content = ''
@@ -150,13 +149,11 @@ def render_templates(
150
149
  if isinstance(template, tuple):
151
150
  template_name, template_context = template
152
151
  else:
153
- template_name = template
154
- template_context = context
152
+ template_name, template_context = template, context
155
153
  try:
156
154
  content += render_to_string(template_name, template_context, request)
157
155
  except TemplateDoesNotExist as e:
158
- if log_not_found:
159
- _logger.warning(repr(e))
156
+ _logger.warning(repr(e))
160
157
  except Exception as e:
161
158
  _logger.exception(repr(e))
162
159
  raise e
accrete/views.py CHANGED
@@ -1,29 +1,34 @@
1
1
  import os
2
- from enum import Enum
3
2
  from functools import wraps
4
3
  from django.http import HttpResponse, HttpResponseNotFound
5
4
  from django.contrib.auth.mixins import LoginRequiredMixin
6
5
  from django.contrib.auth.views import login_required
7
6
  from django.core.exceptions import ImproperlyConfigured
8
- from django.shortcuts import redirect, get_object_or_404
7
+ from django.shortcuts import redirect, get_object_or_404, resolve_url
9
8
  from django.conf import settings
10
9
  from accrete.models import Tenant, Member
11
10
  from accrete.tenant import get_tenant, tenant_has_group, member_has_group
12
- from . import config
11
+ from accrete import config
13
12
 
14
13
 
15
14
  class TenantRequiredMixin(LoginRequiredMixin):
16
15
 
16
+ # Redirect to the specified url if the group check fails
17
17
  TENANT_NOT_SET_URL = None
18
18
  GROUP_NOT_SET_URL = None
19
+
20
+ # If set, one of the supplied groups must be present on the
21
+ # tenant or member respectively. If the list item is of type tuple,
22
+ # all the groups in the tuple must be present.
19
23
  TENANT_GROUPS: list[str | tuple[str]] = []
20
24
  MEMBER_GROUPS: list[str | tuple[str]] = []
21
25
 
22
26
  def dispatch(self, request, *args, **kwargs):
23
27
  res = super().dispatch(request, *args, **kwargs)
24
- tenant = self.get_tenant()
25
- if not tenant:
28
+ if not self.get_tenant():
26
29
  return self.handle_tenant_not_set()
30
+ if self.request.user.is_superuser:
31
+ return res
27
32
  if not self.check_tenant_group():
28
33
  return self.handle_tenant_group_not_set()
29
34
  if not self.check_member_group():
@@ -31,7 +36,10 @@ class TenantRequiredMixin(LoginRequiredMixin):
31
36
  return res
32
37
 
33
38
  def handle_tenant_not_set(self):
34
- return redirect(self.get_tenant_not_set_url())
39
+ return redirect(
40
+ resolve_url(self.get_tenant_not_set_url())
41
+ + f'?next={self.request.get_full_path_info()}'
42
+ )
35
43
 
36
44
  def handle_tenant_group_not_set(self):
37
45
  return redirect(self.get_group_not_set_url())
@@ -41,8 +49,8 @@ class TenantRequiredMixin(LoginRequiredMixin):
41
49
 
42
50
  def get_tenant_not_set_url(self):
43
51
  tenant_not_set_url = (
44
- self.TENANT_NOT_SET_URL
45
- or settings.ACCRETE_TENANT_NOT_SET_URL
52
+ self.TENANT_NOT_SET_URL
53
+ or config.ACCRETE_TENANT_NOT_SET_URL
46
54
  )
47
55
  if not tenant_not_set_url:
48
56
  cls_name = self.__class__.__name__
@@ -57,7 +65,7 @@ class TenantRequiredMixin(LoginRequiredMixin):
57
65
  def get_group_not_set_url(self):
58
66
  group_not_set_url = (
59
67
  self.GROUP_NOT_SET_URL
60
- or settings.ACCRETE_GROUP_NOT_SET_URL
68
+ or config.ACCRETE_GROUP_NOT_SET_URL
61
69
  )
62
70
  if not group_not_set_url:
63
71
  cls_name = self.__class__.__name__
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: accrete
3
- Version: 0.0.138
3
+ Version: 0.0.140
4
4
  Summary: Django Shared Schema Multi Tenant
5
5
  Author-email: Benedikt Jilek <benedikt.jilek@pm.me>
6
6
  License: Copyright (c) 2025 Benedikt Jilek
@@ -7,12 +7,12 @@ accrete/fields.py,sha256=9SlltB5AJvDfiAbYGWZemrqpjqDl1XNgNrhyTGoBJ2A,4693
7
7
  accrete/forms.py,sha256=H2hPQemslRLvTVV0Wl1TfUmTc5wU3Z98nQTMiLMliqo,1288
8
8
  accrete/managers.py,sha256=DevRVm7cStvlfz6TriitSINr40POCi4HNaHX48VkrMA,1620
9
9
  accrete/middleware.py,sha256=Xt8iU8K8nBsReGEKrbNsQMWRYwy50MLpQx4fx4QF110,2305
10
- accrete/models.py,sha256=YRF4Hj0g7WR6ERTduqDfftPlmo8dbE1TCMCooqLfUmg,5492
10
+ accrete/models.py,sha256=ONj6Q4Gqxq_g6GbYeXKWVCgb7MZNmN846K3Ec_NuAds,5612
11
11
  accrete/storage.py,sha256=Jp3oE_uPMqgarjS_G49KDFrR2eSe4XuIJK9oAF_QBxk,1288
12
- accrete/tenant.py,sha256=GGKEhKLsC6JAkNGrMvp4l8ScsyfrDMocwJL5LBPe2Go,2307
12
+ accrete/tenant.py,sha256=vfalmdfDsjYbl-ol3RqvsTC-YnuQs0JuSC7o85UInG0,2289
13
13
  accrete/tests.py,sha256=Agltbzwwh5htvq_Qi9vqvxutzmg_GwgPS_N19xJZRlw,7197
14
14
  accrete/urls.py,sha256=goDFR-yhOlLLy7AMi9pmh2aBkxdtZtwXNg6mwI2zPhU,227
15
- accrete/views.py,sha256=sSockI3rguVM17t0P7ubmI6TFIOD7oR4V1NOaSTHUCA,5492
15
+ accrete/views.py,sha256=JNv1T9Bv_eay5LcPauoSSeyga7ftNIZg9xdPSOQPUnI,5862
16
16
  accrete/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  accrete/contrib/country/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  accrete/contrib/country/admin.py,sha256=0dAcFPfC8c80fhKKOL26-5Wl1uWXBYrkUJEjo2sEkk4,329
@@ -60,11 +60,11 @@ accrete/contrib/system_mail/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2
60
60
  accrete/contrib/system_mail/views.py,sha256=xc1IQHrsij7j33TUbo-_oewy3vs03pw_etpBWaMYJl0,63
61
61
  accrete/contrib/system_mail/migrations/0001_initial.py,sha256=6cwkkRXGjXvwXoMjjgmWmcPyXSTlUbhW1vMiHObk9MQ,1074
62
62
  accrete/contrib/system_mail/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
- accrete/contrib/ui/__init__.py,sha256=Oqqr4o9CfwNi4nM3-9n60-GcaNQfcZrSLIw_JLLSrFM,247
63
+ accrete/contrib/ui/__init__.py,sha256=3kcANg-pw-KR_JdAV1C-EtgPceAQmYbNq5tUJ7e5X0E,267
64
64
  accrete/contrib/ui/admin.py,sha256=suMo4x8I3JBxAFBVIdE-5qnqZ6JAZV0FESABHOSc-vg,63
65
65
  accrete/contrib/ui/apps.py,sha256=E0ao2ox6PQ3ldfeR17FXJUUJuGiWjm2DPCxHbPXGzls,152
66
- accrete/contrib/ui/context.py,sha256=ubWlgkCSehJLkCx3GYApu0c53jNyu--qkRCBZ0mipI8,2563
67
- accrete/contrib/ui/filter.py,sha256=9JO5-9CfnVA2jQz3SaQ1BlrV85c6O8KlCZEiGJIO1PY,13351
66
+ accrete/contrib/ui/context.py,sha256=689qnX9u3Nqrw8t08td38X2PoSSH935qm6sQj5MPznE,2680
67
+ accrete/contrib/ui/filter.py,sha256=zLTWWSvsfvwBMNWgpZqP2kRKXCVW_50mhTQyJA36ywo,13323
68
68
  accrete/contrib/ui/middleware.py,sha256=QprWR8FXK9iMPIvLQAeYASaUJSW0uD9BHoYroMKrph0,1560
69
69
  accrete/contrib/ui/models.py,sha256=Vjc0p2XbAPgE6HyTF6vll98A4eDhA5AvaQqsc4kQ9AQ,57
70
70
  accrete/contrib/ui/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2nk6VY-g,60
@@ -198,12 +198,12 @@ accrete/contrib/ui/templates/django/forms/widgets/select.html,sha256=uSfDpOQox2m
198
198
  accrete/contrib/ui/templates/django/forms/widgets/text.html,sha256=MSmLlQc7PsPoDLVtTOOiWNprrsPriNr712yFxaHyDIo,47
199
199
  accrete/contrib/ui/templates/django/forms/widgets/textarea.html,sha256=c9BTedqb3IkXLyVYd0p9pR8DFnsXCNGoxVBWZTk_Fic,278
200
200
  accrete/contrib/ui/templates/ui/content_right.html,sha256=3DQqbjAafaLtWUTGcBTCzObQEII35DVLfWQ6i6KDh6Y,379
201
- accrete/contrib/ui/templates/ui/form_error.html,sha256=uA8FLdZyeU0vXJHlGK3rcBqcmXb63MLPV32uQyUTak4,348
202
- accrete/contrib/ui/templates/ui/layout.html,sha256=tHatnE3OgcYVxUpDlktl-PCXNx5BG1ev-X_ggjqBK24,13180
203
- accrete/contrib/ui/templates/ui/list.html,sha256=MIqSs2eZlPFslZYujkkKELm0MogaDo0uYFOS79ihI4E,2371
201
+ accrete/contrib/ui/templates/ui/form_error.html,sha256=uPfIkK9OMpy5H147AxVxNAhG6dKBa9Wq64_f4tk5UU8,379
202
+ accrete/contrib/ui/templates/ui/layout.html,sha256=iBrCGIdMTkBOG1oFCPdPiNse_X-CT97_JDVtVlPhxFE,13178
203
+ accrete/contrib/ui/templates/ui/list.html,sha256=_GfXSrmecjsUDHUVO0_Z7mYZNOB4D3Uxz8G2mr0_jxE,2495
204
204
  accrete/contrib/ui/templates/ui/list_update.html,sha256=mLQTCgkKfVI5jrgei-Upc1u87iXL0Q63uLzXHPwMyeo,110
205
- accrete/contrib/ui/templates/ui/message.html,sha256=FTVOCWVs8EzaJEdri7lTbkXWA5ZPdMWpIDlnOjq2yik,550
206
- accrete/contrib/ui/templates/ui/modal.html,sha256=a1_IF3752ClFDfCDqcAIU1-1mK6IrIzDHvylnUOBp00,2101
205
+ accrete/contrib/ui/templates/ui/message.html,sha256=3LPe1D5tmEhan7Ldrwy3MsK6cL1uZSKt6aDYQNtNVHc,732
206
+ accrete/contrib/ui/templates/ui/modal.html,sha256=5qhu9JMr9J72MjuCGXFeCncyWqA8fWil_JSzQK62SIw,2141
207
207
  accrete/contrib/ui/templates/ui/oob.html,sha256=lZHIBBYclefbGkKguS1A7vrtOhODJizbSRaGAAHDvG8,267
208
208
  accrete/contrib/ui/templates/ui/table.html,sha256=L7yBeaBX1GMbunUF4-wV3QOdbn6csKiTbDUmmaPaZaA,4044
209
209
  accrete/contrib/ui/templates/ui/table_row_update.html,sha256=_7tKQlCXxczguYQ-6rkZRwukYBswsh3J2cwT4ke_sQM,445
@@ -226,10 +226,10 @@ accrete/contrib/user/apps.py,sha256=oHDrAiHf-G57mZLyxqGJzRY2DbPprGFD-QgyVJG_ruI,
226
226
  accrete/contrib/user/auth_backends.py,sha256=doGdxil4fjhgY5oC2s8zueQq-bQsZ1fyiAo46HyBHLk,598
227
227
  accrete/contrib/user/forms.py,sha256=BpwF_t1-7BpBVmwLpIm6hdqUpPqajoR0ZGOJ8cmaO6M,3290
228
228
  accrete/contrib/user/middleware.py,sha256=qblcujwJsthopagyT-hPFq4HsMyGt-VvqZw5TQopBjk,403
229
- accrete/contrib/user/models.py,sha256=HXGI6NF_n7b7vou4w8Pgp_GCg3bNA6L2znoP2Qg_658,6422
229
+ accrete/contrib/user/models.py,sha256=K0yOZUZaY8DmOuWd3N3qWOQHCKMyNV6IW84veT7_ZP4,6257
230
230
  accrete/contrib/user/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2nk6VY-g,60
231
231
  accrete/contrib/user/urls.py,sha256=_fBa--3NfyYN10Td7PGHpetJYy42SMqTyCCXhgynkEQ,407
232
- accrete/contrib/user/views.py,sha256=df6Ns5XO__BuTgkj1DoeNitT7cdeToh7u7gjycYwngY,3409
232
+ accrete/contrib/user/views.py,sha256=oPiyyO7RnfI48iKCO7O5_HMk2vioNEUDowKRe-Xwzm0,3435
233
233
  accrete/contrib/user/locale/de/LC_MESSAGES/django.mo,sha256=p3rgUg6WltAVIMkQsjvjBqTsd_usLhSr1GH4Cyltc2c,433
234
234
  accrete/contrib/user/locale/de/LC_MESSAGES/django.po,sha256=f_Nxpo3HTm2L3f3zoHLfeWsZ-4IQp_EEVSku6TCZSvw,1870
235
235
  accrete/contrib/user/migrations/0001_initial.py,sha256=JWfM9PcMDfkJUdCjLWuWieGs6643qP0KdbCyr5uAZoY,2950
@@ -239,6 +239,7 @@ accrete/contrib/user/migrations/0004_user_login_alter_user_email_user_email_or_l
239
239
  accrete/contrib/user/migrations/0005_remove_user_email_or_login_set_and_more.py,sha256=XLfHah_DWplMZX_ZiP9YFoACNwdqTvh0golfrhVAtq0,733
240
240
  accrete/contrib/user/migrations/0006_remove_user_email_or_login_set_user_is_managed_and_more.py,sha256=Js3cQuT6mRtyIk2OnYfx8wwO6dCkoTZqIydRkBJcb9Q,1337
241
241
  accrete/contrib/user/migrations/0007_user_managed_login.py,sha256=SfG1Yj9m_g-sZbvfLi2u-tm53QDtnMDdJd584REoPs4,648
242
+ accrete/contrib/user/migrations/0008_remove_user_no_email_for_managed_user_and_more.py,sha256=XypG6tN0WmLyJV8sbZgSVqNFbTxRsBHWhIRyMJGfV7c,655
242
243
  accrete/contrib/user/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
243
244
  accrete/contrib/user/templates/user/accrete_navbar_end_dropdown.html,sha256=suPoeu1Dm49rDCrhnrkSZY8cBDsovnKqKGXcS5q-7o0,334
244
245
  accrete/contrib/user/templates/user/change_email.html,sha256=w9gBnU_O45YchY0EqD9mUK5oeDaD4cN92tHN80QjReA,815
@@ -263,14 +264,16 @@ accrete/migrations/0002_initial.py,sha256=dFOM7kdHlx7pVAh8cTDlZMtciN4O9Z547HAzEK
263
264
  accrete/migrations/0003_remove_member_name.py,sha256=bnZrzOIXcqsoGfbqgohTN5OHm2IldnLlBz1HNJDeqKc,315
264
265
  accrete/migrations/0004_rename_accessgroupmember_memberaccessgrouprel_and_more.py,sha256=NXEKuRyIjLFXqycWB1jIZFQ0ppevMwz1I6rAr9qKrk4,1404
265
266
  accrete/migrations/0005_accessgroup_apply_on_alter_member_access_groups_and_more.py,sha256=1ZL_PG2W_5h1x1oGAUALn2Ks0kzbFusHF7XEXE1J9Pg,996
267
+ accrete/migrations/0006_alter_member_user.py,sha256=l1m1uaP1q8yaCqX2cWdzRcL-fe4VLb1SqQmP966weNQ,643
268
+ accrete/migrations/0007_accessgroup_description.py,sha256=T8BX0gSckC_fM_uD6a5-fdD-ucAn54vyY7_8o0tDIXA,429
266
269
  accrete/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
267
270
  accrete/utils/__init__.py,sha256=saw9zi2XItJOPbv4fjTXOpl7StNtC803jHhapFcGx08,312
268
271
  accrete/utils/dates.py,sha256=apM6kt6JhGrKgoT0jfav1W-8AUVTxNc9xt3fJQ2n0JI,1492
269
272
  accrete/utils/forms.py,sha256=JJ3EY1xcVP6L10i5cSVgh57G0uvFUjiVwUCpEqmBCos,3407
270
273
  accrete/utils/log.py,sha256=BH0MBDweAjx30wGBO4F3sFhbgkSoEs7T1lLLjlYZNnA,407
271
274
  accrete/utils/models.py,sha256=2xTacvcpmDK_Bp4rAK7JdVLf8HU009LYNJ6eSpMgYZI,1014
272
- accrete/utils/views.py,sha256=6UcvyKE9kLv2ZfkhEgnnV3PxAYrcgLKbgN6_kTlI3Hg,5104
273
- accrete-0.0.138.dist-info/METADATA,sha256=6Znh8zNWQPjWXQ3mAnGh3o0W_qUCxREFeLw5-SqjYHs,4953
274
- accrete-0.0.138.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
275
- accrete-0.0.138.dist-info/licenses/LICENSE,sha256=vHwb4Qnv8UfYKFiCWyTuRGsi49x19UQwHRCky3b2_NE,1057
276
- accrete-0.0.138.dist-info/RECORD,,
275
+ accrete/utils/views.py,sha256=PsKpUFjxCm6_l_nfVs-cNIY0lNTdkocm2uohR3o9eEo,5025
276
+ accrete-0.0.140.dist-info/METADATA,sha256=TZ8ip0yYrzLgj2QUztolGlKF0fS2YjSmtq7_1pMgtOY,4953
277
+ accrete-0.0.140.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
278
+ accrete-0.0.140.dist-info/licenses/LICENSE,sha256=vHwb4Qnv8UfYKFiCWyTuRGsi49x19UQwHRCky3b2_NE,1057
279
+ accrete-0.0.140.dist-info/RECORD,,