nettoyage des applications obsolètes/squash des migrations (#40685) #219
|
@ -6,6 +6,7 @@ set -e
|
|||
CHECK_MIGRATIONS_SETTINGS=`mktemp`
|
||||
trap "rm -f ${CHECK_MIGRATIONS_SETTINGS}" EXIT
|
||||
cat <<EOF >${CHECK_MIGRATIONS_SETTINGS}
|
||||
LANGUAGE_CODE = 'en'
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.dummy',
|
||||
|
|
|
@ -18,7 +18,6 @@ import contextlib
|
|||
import datetime
|
||||
import threading
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db import connection, models
|
||||
from django.db.models import query
|
||||
|
@ -167,7 +166,8 @@ class RoleQuerySet(query.QuerySet):
|
|||
return qs
|
||||
|
||||
def all_members(self):
|
||||
User = get_user_model()
|
||||
from authentic2.custom_user.models import User
|
||||
|
||||
prefetch = Prefetch('roles', queryset=self, to_attr='direct')
|
||||
return (
|
||||
User.objects.filter(
|
||||
|
|
|
@ -6,12 +6,7 @@ import authentic2.utils.misc
|
|||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('authentic2', '0004_service'),
|
||||
('django_rbac', '__first__'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('contenttypes', '0001_initial'),
|
||||
]
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
|
@ -118,7 +113,7 @@ class Migration(migrations.Migration):
|
|||
),
|
||||
(
|
||||
'members',
|
||||
models.ManyToManyField(related_name='roles', to=settings.AUTH_USER_MODEL, blank=True),
|
||||
models.ManyToManyField(related_name='roles', to='auth.User', blank=True),
|
||||
),
|
||||
(
|
||||
'ou',
|
||||
|
|
|
@ -2,36 +2,10 @@
|
|||
|
||||
from django.db import migrations
|
||||
|
||||
from authentic2.a2_rbac.models import CHANGE_OP, MANAGE_MEMBERS_OP
|
||||
|
||||
|
||||
def update_self_administration_perm(apps, schema_editor):
|
||||
Role = apps.get_model('a2_rbac', 'Role')
|
||||
Permission = apps.get_model('a2_rbac', 'Permission')
|
||||
Operation = apps.get_model('django_rbac', 'Operation')
|
||||
ContentType = apps.get_model('contenttypes', 'ContentType')
|
||||
change_op, _ = Operation.objects.get_or_create(slug=str(CHANGE_OP.slug))
|
||||
manage_members_op, _ = Operation.objects.get_or_create(slug=str(MANAGE_MEMBERS_OP.slug))
|
||||
ct = ContentType.objects.get_for_model(Role)
|
||||
perms_to_delete = []
|
||||
for role in Role.objects.all():
|
||||
try:
|
||||
perm = role.permissions.get(operation=change_op, target_ct=ct, target_id=role.pk)
|
||||
except Permission.DoesNotExist:
|
||||
continue
|
||||
|
||||
new_perm, _ = Permission.objects.get_or_create(
|
||||
operation=manage_members_op, target_ct=ct, target_id=role.pk, ou__isnull=True
|
||||
)
|
||||
role.permissions.add(new_perm)
|
||||
role.permissions.remove(perm)
|
||||
perms_to_delete.append(perm.pk)
|
||||
Permission.objects.filter(pk__in=perms_to_delete, roles__isnull=True).delete()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('a2_rbac', '0023_role_can_manage_members'),
|
||||
]
|
||||
|
||||
operations = [migrations.RunPython(update_self_administration_perm, migrations.RunPython.noop)]
|
||||
operations = []
|
||||
|
|
|
@ -7,8 +7,6 @@ from authentic2.migrations import DropPartialIndexes
|
|||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('authentic2', '0039_add_unique_attribute_constraint'),
|
||||
('contenttypes', '0002_remove_content_type_name'),
|
||||
('a2_rbac', '0028_ou_home_url'),
|
||||
('a2_rbac', '0027_auto_20220331_1521'),
|
||||
]
|
||||
|
|
|
@ -3,40 +3,9 @@
|
|||
from django.db import migrations
|
||||
|
||||
|
||||
def copy_operations_data(apps, schema_editor):
|
||||
OldOperation = apps.get_model('django_rbac', 'Operation')
|
||||
NewOperation = apps.get_model('a2_rbac', 'Operation')
|
||||
Permission = apps.get_model('a2_rbac', 'Permission')
|
||||
|
||||
operation_map = {}
|
||||
for operation in OldOperation.objects.all():
|
||||
operation_map[operation.pk] = NewOperation.objects.create(slug=operation.slug)
|
||||
|
||||
for permission in Permission.objects.all():
|
||||
permission.operation_new = operation_map[permission.operation_id]
|
||||
permission.save()
|
||||
|
||||
|
||||
def reverse_copy_operations_data(apps, schema_editor):
|
||||
OldOperation = apps.get_model('django_rbac', 'Operation')
|
||||
NewOperation = apps.get_model('a2_rbac', 'Operation')
|
||||
Permission = apps.get_model('a2_rbac', 'Permission')
|
||||
|
||||
operation_map = {}
|
||||
for operation in NewOperation.objects.all():
|
||||
operation_map[operation.pk] = OldOperation.objects.create(slug=operation.slug)
|
||||
|
||||
for permission in Permission.objects.all():
|
||||
permission.operation = operation_map[permission.operation_new_id]
|
||||
permission.save()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('a2_rbac', '0031_new_operation_model'),
|
||||
('django_rbac', '0009_auto_20221004_1343'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(copy_operations_data, reverse_code=reverse_copy_operations_data),
|
||||
]
|
||||
operations = []
|
||||
|
|
|
@ -6,7 +6,6 @@ from django.db import migrations
|
|||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('a2_rbac', '0036_delete_roleattribute'),
|
||||
('authenticators', '0013_migrate_min_password_strength'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
|
|
|
@ -0,0 +1,289 @@
|
|||
# Generated by Django 3.2.23 on 2023-12-14 21:01
|
||||
|
||||
import django.contrib.postgres.fields
|
||||
import django.core.validators
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
import authentic2.a2_rbac.fields
|
||||
import authentic2.a2_rbac.utils
|
||||
import authentic2.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
replaces = [
|
||||
('a2_rbac', '0001_initial'),
|
||||
('a2_rbac', '0002_role_external_id'),
|
||||
('a2_rbac', '0003_partial_unique_index_on_name_and_slug'),
|
||||
('a2_rbac', '0004_auto_20150523_0028'),
|
||||
('a2_rbac', '0005_auto_20150526_1406'),
|
||||
('a2_rbac', '0006_auto_20150619_1056'),
|
||||
('a2_rbac', '0007_auto_20150708_1337'),
|
||||
('a2_rbac', '0008_auto_20150810_1953'),
|
||||
('a2_rbac', '0009_partial_unique_index_on_permission'),
|
||||
('a2_rbac', '0010_auto_20160209_1417'),
|
||||
('a2_rbac', '0011_auto_20160209_1511'),
|
||||
('a2_rbac', '0013_auto_20170629_0007'),
|
||||
('a2_rbac', '0014_auto_20170711_1024'),
|
||||
('a2_rbac', '0015_organizationalunit_validate_emails'),
|
||||
('a2_rbac', '0016_auto_20171208_1429'),
|
||||
('a2_rbac', '0017_organizationalunit_user_can_reset_password'),
|
||||
('a2_rbac', '0018_organizationalunit_user_add_password_policy'),
|
||||
('a2_rbac', '0019_organizationalunit_show_username'),
|
||||
('a2_rbac', '0020_partial_unique_index_on_name'),
|
||||
('a2_rbac', '0021_auto_20200317_1514'),
|
||||
('a2_rbac', '0022_auto_20200402_1101'),
|
||||
('a2_rbac', '0023_role_can_manage_members'),
|
||||
('a2_rbac', '0024_fix_self_admin_perm'),
|
||||
('a2_rbac', '0025_auto_20210622_1132'),
|
||||
('a2_rbac', '0026_add_roleparenting_soft_delete'),
|
||||
('a2_rbac', '0026_organizationalunit_check_required_on_login_attributes'),
|
||||
('a2_rbac', '0027_auto_20211213_0949'),
|
||||
('a2_rbac', '0027_auto_20220331_1521'),
|
||||
('a2_rbac', '0028_ou_home_url'),
|
||||
('a2_rbac', '0029_use_unique_constraints'),
|
||||
('a2_rbac', '0030_organizationalunit_min_password_strength'),
|
||||
('a2_rbac', '0031_new_operation_model'),
|
||||
('a2_rbac', '0032_copy_operations_data'),
|
||||
('a2_rbac', '0033_remove_old_operation_fk'),
|
||||
('a2_rbac', '0034_new_role_fields'),
|
||||
('a2_rbac', '0035_populate_role_fields'),
|
||||
('a2_rbac', '0036_delete_roleattribute'),
|
||||
]
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('contenttypes', '0002_remove_content_type_name'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Operation',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('slug', models.CharField(max_length=32, unique=True, verbose_name='slug')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='OrganizationalUnit',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
(
|
||||
'uuid',
|
||||
models.CharField(
|
||||
default=authentic2.a2_rbac.utils.get_hex_uuid,
|
||||
max_length=32,
|
||||
unique=True,
|
||||
verbose_name='uuid',
|
||||
),
|
||||
),
|
||||
('name', models.CharField(max_length=256, verbose_name='name')),
|
||||
('slug', models.SlugField(max_length=256, verbose_name='slug')),
|
||||
('description', models.TextField(blank=True, verbose_name='description')),
|
||||
(
|
||||
'username_is_unique',
|
||||
models.BooleanField(blank=True, default=False, verbose_name='Username is unique'),
|
||||
),
|
||||
(
|
||||
'email_is_unique',
|
||||
models.BooleanField(blank=True, default=False, verbose_name='Email is unique'),
|
||||
),
|
||||
(
|
||||
'default',
|
||||
authentic2.a2_rbac.fields.UniqueBooleanField(verbose_name='Default organizational unit'),
|
||||
),
|
||||
(
|
||||
'validate_emails',
|
||||
models.BooleanField(blank=True, default=False, verbose_name='Validate emails'),
|
||||
),
|
||||
(
|
||||
'show_username',
|
||||
models.BooleanField(blank=True, default=True, verbose_name='Show username'),
|
||||
),
|
||||
(
|
||||
'check_required_on_login_attributes',
|
||||
models.BooleanField(
|
||||
blank=True, default=True, verbose_name='Check required on login attributes'
|
||||
),
|
||||
),
|
||||
(
|
||||
'user_can_reset_password',
|
||||
models.BooleanField(
|
||||
blank=True,
|
||||
choices=[(None, 'System default'), (True, 'Yes'), (False, 'No')],
|
||||
default=None,
|
||||
null=True,
|
||||
verbose_name='Users can reset password',
|
||||
),
|
||||
),
|
||||
(
|
||||
'user_add_password_policy',
|
||||
models.IntegerField(
|
||||
choices=[(0, 'Send reset link'), (1, 'Manual password definition')],
|
||||
default=0,
|
||||
verbose_name='User creation password policy',
|
||||
),
|
||||
),
|
||||
(
|
||||
'clean_unused_accounts_alert',
|
||||
models.PositiveIntegerField(
|
||||
blank=True,
|
||||
default=730,
|
||||
null=True,
|
||||
validators=[
|
||||
django.core.validators.MinValueValidator(
|
||||
30,
|
||||
'Ensure that this value is greater than 30 days, or leave blank for deactivating.',
|
||||
)
|
||||
],
|
||||
verbose_name='Days after which the user receives an account deletion alert',
|
||||
),
|
||||
),
|
||||
(
|
||||
'clean_unused_accounts_deletion',
|
||||
models.PositiveIntegerField(
|
||||
blank=True,
|
||||
default=760,
|
||||
null=True,
|
||||
validators=[
|
||||
django.core.validators.MinValueValidator(
|
||||
30,
|
||||
'Ensure that this value is greater than 30 days, or leave blank for deactivating.',
|
||||
)
|
||||
],
|
||||
verbose_name='Delay in days before cleaning unused accounts',
|
||||
),
|
||||
),
|
||||
('home_url', models.URLField(blank=True, max_length=256, null=True, verbose_name='Home URL')),
|
||||
('logo', models.ImageField(blank=True, upload_to='services/logos', verbose_name='Logo')),
|
||||
(
|
||||
'colour',
|
||||
models.CharField(
|
||||
blank=True,
|
||||
max_length=32,
|
||||
null=True,
|
||||
validators=[authentic2.validators.HexaColourValidator()],
|
||||
verbose_name='Colour',
|
||||
),
|
||||
),
|
||||
(
|
||||
'phone_is_unique',
|
||||
models.BooleanField(blank=True, default=False, verbose_name='Phone is unique'),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'organizational unit',
|
||||
'verbose_name_plural': 'organizational units',
|
||||
'ordering': ('name',),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Permission',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('target_id', models.PositiveIntegerField()),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'permission',
|
||||
'verbose_name_plural': 'permissions',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Role',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
(
|
||||
'uuid',
|
||||
models.CharField(
|
||||
default=authentic2.a2_rbac.utils.get_hex_uuid,
|
||||
max_length=32,
|
||||
unique=True,
|
||||
verbose_name='uuid',
|
||||
),
|
||||
),
|
||||
('slug', models.SlugField(max_length=256, verbose_name='slug')),
|
||||
('description', models.TextField(blank=True, verbose_name='description')),
|
||||
('name', models.TextField(verbose_name='name')),
|
||||
('details', models.TextField(blank=True, verbose_name='Role details (frontoffice)')),
|
||||
(
|
||||
'emails',
|
||||
django.contrib.postgres.fields.ArrayField(
|
||||
base_field=models.EmailField(max_length=254), default=list, size=None
|
||||
),
|
||||
),
|
||||
('emails_to_members', models.BooleanField(default=True, verbose_name='Emails to members')),
|
||||
('is_superuser', models.BooleanField(default=False)),
|
||||
(
|
||||
'admin_scope_id',
|
||||
models.PositiveIntegerField(
|
||||
blank=True, null=True, verbose_name='administrative scope id'
|
||||
),
|
||||
),
|
||||
('external_id', models.TextField(blank=True, db_index=True, verbose_name='external id')),
|
||||
(
|
||||
'can_manage_members',
|
||||
models.BooleanField(default=True, verbose_name='Allow adding or deleting role members'),
|
||||
),
|
||||
(
|
||||
'admin_scope_ct',
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to='contenttypes.contenttype',
|
||||
verbose_name='administrative scope content type',
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'role',
|
||||
'verbose_name_plural': 'roles',
|
||||
'ordering': ('ou', 'service', 'name'),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='RoleParenting',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('direct', models.BooleanField(blank=True, default=True)),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Creation date')),
|
||||
('deleted', models.DateTimeField(null=True, verbose_name='Deletion date')),
|
||||
(
|
||||
'child',
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name='parent_relation',
|
||||
to='a2_rbac.role',
|
||||
),
|
||||
),
|
||||
(
|
||||
'parent',
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name='child_relation',
|
||||
to='a2_rbac.role',
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'role parenting relation',
|
||||
'verbose_name_plural': 'role parenting relations',
|
||||
},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,174 @@
|
|||
# Generated by Django 3.2.23 on 2023-12-14 21:01
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
replaces = [
|
||||
('a2_rbac', '0037_remove_organizationalunit_min_password_strength'),
|
||||
('a2_rbac', '0038_organizationalunit_phone_is_unique'),
|
||||
('a2_rbac', '0039_set_user_view_permissions_by_ou'),
|
||||
]
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('a2_rbac', '0040_replace'),
|
||||
('custom_user', '0037_replace'),
|
||||
('contenttypes', '0002_remove_content_type_name'),
|
||||
('authentic2', '0051_replace'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='role',
|
||||
name='members',
|
||||
field=models.ManyToManyField(blank=True, related_name='roles', to='custom_user.User'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='role',
|
||||
name='ou',
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to='a2_rbac.organizationalunit',
|
||||
verbose_name='organizational unit',
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='role',
|
||||
name='permissions',
|
||||
field=models.ManyToManyField(blank=True, related_name='roles', to='a2_rbac.Permission'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='role',
|
||||
name='service',
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name='roles',
|
||||
to='authentic2.service',
|
||||
verbose_name='service',
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='permission',
|
||||
name='operation',
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, to='a2_rbac.operation', verbose_name='operation'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='permission',
|
||||
name='ou',
|
||||
field=models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name='scoped_permission',
|
||||
to='a2_rbac.organizationalunit',
|
||||
verbose_name='organizational unit',
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='permission',
|
||||
name='target_ct',
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype'
|
||||
),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='organizationalunit',
|
||||
unique_together={('name',), ('slug',)},
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='roleparenting',
|
||||
unique_together={('parent', 'child', 'direct')},
|
||||
),
|
||||
migrations.AlterIndexTogether(
|
||||
name='roleparenting',
|
||||
index_together={('child', 'parent', 'direct')},
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='role',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(('admin_scope_ct__isnull', True)),
|
||||
fields=('ou', 'service', 'slug'),
|
||||
name='slug_uniq_idx',
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='role',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(('admin_scope_ct__isnull', True)),
|
||||
fields=('ou', 'service', 'name'),
|
||||
name='name_uniq_idx',
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='role',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(('admin_scope_ct__isnull', True), ('service__isnull', True)),
|
||||
fields=('ou', 'slug'),
|
||||
name='null_service_slug_uniq_idx',
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='role',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(('admin_scope_ct__isnull', True), ('ou__isnull', True)),
|
||||
fields=('service', 'slug'),
|
||||
name='null_ou_slug_uniq_idx',
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='role',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(
|
||||
('admin_scope_ct__isnull', True), ('ou__isnull', True), ('service__isnull', True)
|
||||
),
|
||||
fields=('slug',),
|
||||
name='null_ou_service_slug_uniq_idx',
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='role',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(('admin_scope_ct__isnull', True), ('service__isnull', True)),
|
||||
fields=('ou', 'name'),
|
||||
name='null_service_name_uniq_idx',
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='role',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(('admin_scope_ct__isnull', True), ('ou__isnull', True)),
|
||||
fields=('service', 'name'),
|
||||
name='null_ou_name_uniq_idx',
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='role',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(
|
||||
('admin_scope_ct__isnull', True), ('ou__isnull', True), ('service__isnull', True)
|
||||
),
|
||||
fields=('name',),
|
||||
name='null_ou_service_name_uniq_idx',
|
||||
),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='role',
|
||||
unique_together={('admin_scope_ct', 'admin_scope_id')},
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='permission',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(('ou__isnull', True)),
|
||||
fields=('operation', 'target_ct', 'target_id'),
|
||||
name='null_ou_uniq_idx',
|
||||
),
|
||||
),
|
||||
]
|
|
@ -19,8 +19,6 @@ import os
|
|||
from collections import namedtuple
|
||||
|
||||
from django.apps import apps
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.contrib.postgres.fields import ArrayField
|
||||
|
@ -363,9 +361,7 @@ class Role(AbstractBase):
|
|||
null=True,
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
members = models.ManyToManyField(
|
||||
to=settings.AUTH_USER_MODEL, swappable=True, blank=True, related_name='roles'
|
||||
)
|
||||
members = models.ManyToManyField(to='custom_user.User', swappable=True, blank=True, related_name='roles')
|
||||
permissions = models.ManyToManyField(to=Permission, related_name='roles', blank=True)
|
||||
name = models.TextField(verbose_name=_('name'))
|
||||
details = models.TextField(_('Role details (frontoffice)'), blank=True)
|
||||
|
@ -426,7 +422,8 @@ class Role(AbstractBase):
|
|||
)
|
||||
|
||||
def all_members(self):
|
||||
User = get_user_model()
|
||||
from authentic2.custom_user.models import User
|
||||
|
||||
prefetch = Prefetch('roles', queryset=self.__class__.objects.filter(pk=self.pk), to_attr='direct')
|
||||
|
||||
return (
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
import uuid
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.text import slugify
|
||||
|
||||
|
@ -44,7 +43,8 @@ def get_default_ou_pk():
|
|||
|
||||
|
||||
def get_view_user_perm(ou=None):
|
||||
User = get_user_model()
|
||||
from authentic2.custom_user.models import User
|
||||
|
||||
view_user_perm, dummy = models.Permission.objects.get_or_create(
|
||||
operation=get_operation(models.VIEW_OP),
|
||||
target_ct=ContentType.objects.get_for_model(ContentType),
|
||||
|
@ -74,7 +74,8 @@ def get_search_ou_perm(ou=None):
|
|||
|
||||
|
||||
def get_manage_authorizations_user_perm(ou=None):
|
||||
User = get_user_model()
|
||||
from authentic2.custom_user.models import User
|
||||
|
||||
manage_authorizations_user_perm, dummy = models.Permission.objects.get_or_create(
|
||||
operation=get_operation(models.MANAGE_AUTHORIZATIONS_OP),
|
||||
target_ct=ContentType.objects.get_for_model(ContentType),
|
||||
|
|
|
@ -32,7 +32,6 @@ from django.views.decorators.cache import never_cache
|
|||
from . import app_settings, attribute_kinds, decorators, models
|
||||
from .custom_user.models import DeletedUser, Profile, ProfileType, User
|
||||
from .forms.profile import BaseUserForm, modelform_factory
|
||||
from .nonce.models import Nonce
|
||||
from .utils import misc as utils_misc
|
||||
|
||||
|
||||
|
@ -49,11 +48,6 @@ class CleanupAdminMixin(admin.ModelAdmin):
|
|||
return actions
|
||||
|
||||
|
||||
@admin.register(Nonce)
|
||||
class NonceModelAdmin(admin.ModelAdmin):
|
||||
list_display = ('value', 'context', 'not_on_or_after')
|
||||
|
||||
|
||||
class AttributeValueAdmin(admin.ModelAdmin):
|
||||
list_display = ('content_type', 'owner', 'attribute', 'content')
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ from functools import partial
|
|||
|
||||
import requests
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.hashers import identify_hasher
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import MultipleObjectsReturned
|
||||
|
@ -75,8 +74,6 @@ from .utils import misc as utils_misc
|
|||
from .utils.api import DjangoRBACPermission, NaturalKeyRelatedField
|
||||
from .utils.lookups import Unaccent
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class HookMixin:
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
|
@ -153,7 +150,6 @@ class RegistrationSerializer(serializers.Serializer):
|
|||
authorized = request.user.has_perm(perm)
|
||||
if not authorized:
|
||||
raise serializers.ValidationError(_('you are not authorized to create users in this ou'))
|
||||
User = get_user_model()
|
||||
if ou:
|
||||
if app_settings.A2_EMAIL_IS_UNIQUE or app_settings.A2_REGISTRATION_EMAIL_IS_UNIQUE:
|
||||
if 'email' not in attrs:
|
||||
|
@ -207,7 +203,6 @@ class PasswordChangeSerializer(serializers.Serializer):
|
|||
new_password = serializers.CharField(required=True, allow_null=True)
|
||||
|
||||
def validate(self, attrs):
|
||||
User = get_user_model()
|
||||
qs = User.objects.filter(email__iexact=attrs['email'])
|
||||
if attrs['ou']:
|
||||
qs = qs.filter(ou=attrs['ou'])
|
||||
|
@ -394,7 +389,6 @@ class BaseUserSerializer(serializers.ModelSerializer):
|
|||
return instance
|
||||
|
||||
def validate(self, attrs):
|
||||
User = get_user_model()
|
||||
qs = User.objects.all()
|
||||
|
||||
ou = None
|
||||
|
@ -439,7 +433,7 @@ class BaseUserSerializer(serializers.ModelSerializer):
|
|||
return attrs
|
||||
|
||||
class Meta:
|
||||
model = get_user_model()
|
||||
model = User
|
||||
extra_kwargs = {
|
||||
'uuid': {
|
||||
'read_only': False,
|
||||
|
@ -556,7 +550,7 @@ class IsoDateTimeFilter(BaseIsoDateTimeFilter):
|
|||
|
||||
class UsersFilter(FilterSet):
|
||||
class Meta:
|
||||
model = get_user_model()
|
||||
model = User
|
||||
fields = {
|
||||
'username': ['exact', 'iexact'],
|
||||
'first_name': [
|
||||
|
@ -721,7 +715,7 @@ class UsersAPI(api_mixins.GetOrCreateMixinView, HookMixin, ExceptionHandlerMixin
|
|||
|
||||
def check_modified_uuids(self, timestamp, users, unknown_uuids):
|
||||
modified_users_uuids = set()
|
||||
user_ct = ContentType.objects.get_for_model(get_user_model())
|
||||
user_ct = ContentType.objects.get_for_model(User)
|
||||
reference_ids = [reference_integer(user) for user in users]
|
||||
user_events = Event.objects.filter(
|
||||
models.Q(reference_ids__overlap=reference_ids) | models.Q(user__in=users),
|
||||
|
@ -999,7 +993,6 @@ class UserProfilesAPI(ExceptionHandlerMixin, APIView):
|
|||
|
||||
def initial(self, request, *args, **kwargs):
|
||||
super().initial(request, *args, **kwargs)
|
||||
User = get_user_model()
|
||||
self.profile_type = get_object_or_404(ProfileType, slug=kwargs['profile_type_slug'])
|
||||
self.user = get_object_or_404(User, uuid=kwargs['user_uuid'])
|
||||
self.identifier = request.GET.get('identifier', '')
|
||||
|
@ -1175,7 +1168,6 @@ class RoleMembershipsAPI(ExceptionHandlerMixin, APIView):
|
|||
|
||||
def initial(self, request, *, role_uuid=None, role_slug=None, **kwargs):
|
||||
super().initial(request, role_uuid=role_uuid, role_slug=role_slug, **kwargs)
|
||||
User = get_user_model()
|
||||
if role_uuid:
|
||||
self.role = get_object_or_404(Role, uuid=role_uuid)
|
||||
if role_slug:
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
DEFAULT_MIN_PASSWORD_STRENGTH = 3
|
||||
|
||||
|
||||
def get_default_min_password_strength():
|
||||
return DEFAULT_MIN_PASSWORD_STRENGTH
|
|
@ -12,10 +12,7 @@ import authentic2.utils.evaluate
|
|||
class Migration(migrations.Migration):
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.RBAC_OU_MODEL),
|
||||
('a2_rbac', '0036_delete_roleattribute'),
|
||||
]
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
|
|
|
@ -7,9 +7,7 @@ from django.db import migrations, models
|
|||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.RBAC_ROLE_MODEL),
|
||||
('authenticators', '0004_auto_20220726_1708'),
|
||||
('authentic2_auth_saml', '0012_move_add_role_action'),
|
||||
]
|
||||
|
||||
state_operations = [
|
||||
|
|
|
@ -6,7 +6,6 @@ from django.db import migrations, models
|
|||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('authentic2', '0048_rename_services_runtime_settings'),
|
||||
('authenticators', '0009_migrate_new_password_settings'),
|
||||
]
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ def migrate_min_password_strength(apps, schema_editor):
|
|||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('authenticators', '0012_loginpasswordauthenticator_min_password_strength'),
|
||||
('a2_rbac', '0036_delete_roleattribute'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
|
|
|
@ -0,0 +1,325 @@
|
|||
# Generated by Django 3.2.23 on 2023-12-14 21:01
|
||||
|
||||
import uuid
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
import authentic2.utils.evaluate
|
||||
import authentic2.utils.template
|
||||
from authentic2.apps.authenticators import get_default_min_password_strength
|
||||
|
||||
|
||||
def create_login_password_authenticator(apps, schema_editor):
|
||||
LoginPasswordAuthenticator = apps.get_model('authenticators', 'LoginPasswordAuthenticator')
|
||||
LoginPasswordAuthenticator.objects.create(slug='password-authenticator', enabled=True)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
replaces = [
|
||||
('authenticators', '0001_initial'),
|
||||
('authenticators', '0002_loginpasswordauthenticator'),
|
||||
('authenticators', '0003_auto_20220413_1504'),
|
||||
('authenticators', '0004_auto_20220726_1708'),
|
||||
('authenticators', '0005_addroleaction'),
|
||||
('authenticators', '0006_loginpasswordauthenticator_registration_open'),
|
||||
('authenticators', '0007_migrate_registration_open'),
|
||||
('authenticators', '0008_new_password_settings_fields'),
|
||||
('authenticators', '0009_migrate_new_password_settings'),
|
||||
('authenticators', '0010_auto_20230614_1017'),
|
||||
('authenticators', '0011_migrate_a2_accept_authentication_settings'),
|
||||
('authenticators', '0012_loginpasswordauthenticator_min_password_strength'),
|
||||
('authenticators', '0013_migrate_min_password_strength'),
|
||||
('authenticators', '0014_auto_20230801_1517'),
|
||||
('authenticators', '0015_alter_baseauthenticator_button_label'),
|
||||
('authenticators', '0016_alter_addroleaction_condition'),
|
||||
('authenticators', '0017_auto_20230927_1517'),
|
||||
('authenticators', '0018_auto_20230927_1519'),
|
||||
('authenticators', '0019_fix_addroleaction_condition'),
|
||||
]
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('a2_rbac', '0040_replace'),
|
||||
('authentic2', '0051_replace'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='BaseAuthenticator',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('uuid', models.CharField(default=uuid.uuid4, editable=False, max_length=255, unique=True)),
|
||||
('name', models.CharField(blank=True, max_length=128, verbose_name='Name')),
|
||||
('slug', models.SlugField(unique=True)),
|
||||
('order', models.IntegerField(default=0, editable=False, verbose_name='Order')),
|
||||
('enabled', models.BooleanField(default=False, editable=False)),
|
||||
(
|
||||
'show_condition',
|
||||
models.CharField(
|
||||
blank=True,
|
||||
default='',
|
||||
help_text='Condition controlling authenticator display. For example, "\'backoffice\' in '
|
||||
'login_hint or remote_addr == \'1.2.3.4\'" would hide the authenticator from normal users '
|
||||
'except if they come from the specified IP address. Available variables include '
|
||||
'service_ou_slug, service_slug, remote_addr, login_hint and headers.',
|
||||
max_length=1024,
|
||||
validators=[authentic2.utils.evaluate.condition_validator],
|
||||
verbose_name='Show condition',
|
||||
),
|
||||
),
|
||||
(
|
||||
'button_description',
|
||||
models.CharField(
|
||||
blank=True,
|
||||
help_text='Description will be shown at the top of login block (unless already set by theme).',
|
||||
max_length=256,
|
||||
verbose_name='Login block description',
|
||||
),
|
||||
),
|
||||
(
|
||||
'button_label',
|
||||
models.CharField(default='Login', max_length=256, verbose_name='Login button label'),
|
||||
),
|
||||
(
|
||||
'ou',
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to='a2_rbac.organizationalunit',
|
||||
verbose_name='organizational unit',
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'ordering': ('-enabled', 'order', 'name', 'slug', 'ou'),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AddRoleAction',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
(
|
||||
'mandatory',
|
||||
models.BooleanField(default=False, editable=False, verbose_name='Mandatory (unused)'),
|
||||
),
|
||||
(
|
||||
'condition',
|
||||
models.CharField(
|
||||
blank=True,
|
||||
default='',
|
||||
help_text='Django condition controlling role attribution. For example, "\'Admin\' in attributes.groups" '
|
||||
'will attribute the role if attributes has "groups" attribute containing the value "Admin". Variable "attributes" '
|
||||
'contains the attributes received from the identity provider. If condition is not satisfied the role will be removed.',
|
||||
max_length=1024,
|
||||
validators=[authentic2.utils.template.validate_condition_template],
|
||||
verbose_name='Condition',
|
||||
),
|
||||
),
|
||||
(
|
||||
'authenticator',
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name='add_role_actions',
|
||||
to='authenticators.baseauthenticator',
|
||||
),
|
||||
),
|
||||
(
|
||||
'role',
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name='add_role_actions',
|
||||
to='a2_rbac.role',
|
||||
verbose_name='Role',
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Add a role',
|
||||
'verbose_name_plural': 'Add roles',
|
||||
'default_related_name': 'add_role_actions',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='LoginPasswordAuthenticator',
|
||||
fields=[
|
||||
(
|
||||
'baseauthenticator_ptr',
|
||||
models.OneToOneField(
|
||||
auto_created=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
parent_link=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to='authenticators.baseauthenticator',
|
||||
),
|
||||
),
|
||||
(
|
||||
'registration_open',
|
||||
models.BooleanField(
|
||||
default=True,
|
||||
help_text='Allow users to create accounts.',
|
||||
verbose_name='Registration open',
|
||||
),
|
||||
),
|
||||
(
|
||||
'remember_me',
|
||||
models.PositiveIntegerField(
|
||||
blank=True,
|
||||
help_text='Session duration as seconds when using the remember me checkbox. Leave blank to hide the checkbox.',
|
||||
null=True,
|
||||
verbose_name='Remember me duration',
|
||||
),
|
||||
),
|
||||
(
|
||||
'include_ou_selector',
|
||||
models.BooleanField(default=False, verbose_name='Include OU selector in login form'),
|
||||
),
|
||||
(
|
||||
'accept_email_authentication',
|
||||
models.BooleanField(
|
||||
default=True, verbose_name='Let the users identify with their email address'
|
||||
),
|
||||
),
|
||||
(
|
||||
'accept_phone_authentication',
|
||||
models.BooleanField(
|
||||
default=False, verbose_name='Let the users identify with their phone number'
|
||||
),
|
||||
),
|
||||
(
|
||||
'min_password_strength',
|
||||
models.IntegerField(
|
||||
blank=True,
|
||||
choices=[
|
||||
(None, 'Follow static checks'),
|
||||
(0, 'Very Weak'),
|
||||
(1, 'Weak'),
|
||||
(2, 'Fair'),
|
||||
(3, 'Good'),
|
||||
(4, 'Strong'),
|
||||
],
|
||||
default=get_default_min_password_strength,
|
||||
help_text='Password strength, using dynamic indicators such as common names, dates and other popular patterns. Selecting '
|
||||
'"static checks" will instead validate that a password contains enough different kind of caracters. Password indicator on '
|
||||
'registration form will reflect the chosen policy.',
|
||||
null=True,
|
||||
verbose_name='Minimum password strength',
|
||||
),
|
||||
),
|
||||
(
|
||||
'password_min_length',
|
||||
models.PositiveIntegerField(default=8, null=True, verbose_name='Password minimum length'),
|
||||
),
|
||||
(
|
||||
'password_regex',
|
||||
models.CharField(
|
||||
blank=True,
|
||||
default='',
|
||||
max_length=512,
|
||||
verbose_name='Regular expression for validating passwords',
|
||||
),
|
||||
),
|
||||
(
|
||||
'password_regex_error_msg',
|
||||
models.CharField(
|
||||
blank=True,
|
||||
default='',
|
||||
max_length=1024,
|
||||
verbose_name='Error message to show when the password do not validate the regular expression',
|
||||
),
|
||||
),
|
||||
(
|
||||
'login_exponential_retry_timeout_duration',
|
||||
models.FloatField(
|
||||
default=1,
|
||||
help_text='Exponential backoff base factor duration as seconds until next try after a login failure.',
|
||||
verbose_name='Retry timeout duration',
|
||||
),
|
||||
),
|
||||
(
|
||||
'login_exponential_retry_timeout_factor',
|
||||
models.FloatField(
|
||||
default=1.8,
|
||||
help_text='Exponential backoff factor duration as seconds until next try after a login failure.',
|
||||
verbose_name='Retry timeout factor',
|
||||
),
|
||||
),
|
||||
(
|
||||
'login_exponential_retry_timeout_max_duration',
|
||||
models.PositiveIntegerField(
|
||||
default=3600,
|
||||
help_text='Maximum exponential backoff maximum duration as seconds until next try after a login failure.',
|
||||
verbose_name='Retry timeout max duration',
|
||||
),
|
||||
),
|
||||
(
|
||||
'login_exponential_retry_timeout_min_duration',
|
||||
models.PositiveIntegerField(
|
||||
default=10,
|
||||
help_text='Minimum exponential backoff maximum duration as seconds until next try after a login failure.',
|
||||
verbose_name='Retry timeout min duration',
|
||||
),
|
||||
),
|
||||
(
|
||||
'emails_ip_ratelimit',
|
||||
models.CharField(
|
||||
default='10/h',
|
||||
help_text='Maximum rate of email sendings triggered by the same IP address.',
|
||||
max_length=32,
|
||||
verbose_name='Emails IP ratelimit',
|
||||
),
|
||||
),
|
||||
(
|
||||
'sms_ip_ratelimit',
|
||||
models.CharField(
|
||||
default='10/h',
|
||||
help_text='Maximum rate of SMSs triggered by the same IP address.',
|
||||
max_length=32,
|
||||
verbose_name='SMS IP ratelimit',
|
||||
),
|
||||
),
|
||||
(
|
||||
'emails_address_ratelimit',
|
||||
models.CharField(
|
||||
default='3/d',
|
||||
help_text='Maximum rate of emails sent to the same email address.',
|
||||
max_length=32,
|
||||
verbose_name='Emails address ratelimit',
|
||||
),
|
||||
),
|
||||
(
|
||||
'sms_number_ratelimit',
|
||||
models.CharField(
|
||||
default='10/h',
|
||||
help_text='Maximum rate of SMSs sent to the same phone number.',
|
||||
max_length=32,
|
||||
verbose_name='SMS number ratelimit',
|
||||
),
|
||||
),
|
||||
(
|
||||
'phone_identifier_field',
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to='authentic2.attribute',
|
||||
verbose_name='Phone field used as user identifier',
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Password',
|
||||
},
|
||||
bases=('authenticators.baseauthenticator',),
|
||||
),
|
||||
migrations.RunPython(create_login_password_authenticator, reverse_code=migrations.RunPython.noop),
|
||||
]
|
|
@ -37,6 +37,7 @@ from authentic2.models import Attribute
|
|||
from authentic2.utils.evaluate import condition_validator, evaluate_condition
|
||||
from authentic2.utils.template import validate_condition_template
|
||||
|
||||
from . import get_default_min_password_strength
|
||||
from .query import AuthenticatorManager
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -335,7 +336,7 @@ class LoginPasswordAuthenticator(BaseAuthenticator):
|
|||
min_password_strength = models.IntegerField(
|
||||
verbose_name=_('Minimum password strength'),
|
||||
choices=MIN_PASSWORD_STRENGTH_CHOICES,
|
||||
default=3,
|
||||
default=get_default_min_password_strength,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text=_(
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
import django
|
||||
import django.contrib.postgres.fields
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
from django.db.models import JSONField
|
||||
from django.utils import timezone
|
||||
|
@ -12,11 +11,7 @@ from django.utils import timezone
|
|||
class Migration(migrations.Migration):
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('authentic2', '0027_remove_deleteduser'),
|
||||
('sessions', '0001_initial'),
|
||||
]
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
|
@ -92,7 +87,7 @@ class Migration(migrations.Migration):
|
|||
db_constraint=False,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.DO_NOTHING,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
to='custom_user.User',
|
||||
verbose_name='user',
|
||||
),
|
||||
),
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
# Generated by Django 3.2.23 on 2023-12-14 21:01
|
||||
|
||||
import django.contrib.postgres.fields
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
replaces = [('journal', '0001_initial'), ('journal', '0002_event_api')]
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('sessions', '0001_initial'),
|
||||
('custom_user', '0037_replace'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='EventType',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('name', models.SlugField(max_length=256, unique=True, verbose_name='name')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'event type',
|
||||
'verbose_name_plural': 'event types',
|
||||
'ordering': ('name',),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Event',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
(
|
||||
'timestamp',
|
||||
models.DateTimeField(
|
||||
blank=True,
|
||||
default=django.utils.timezone.now,
|
||||
editable=False,
|
||||
verbose_name='timestamp',
|
||||
),
|
||||
),
|
||||
(
|
||||
'reference_ids',
|
||||
django.contrib.postgres.fields.ArrayField(
|
||||
base_field=models.BigIntegerField(),
|
||||
null=True,
|
||||
size=None,
|
||||
verbose_name='reference ids',
|
||||
),
|
||||
),
|
||||
(
|
||||
'reference_ct_ids',
|
||||
django.contrib.postgres.fields.ArrayField(
|
||||
base_field=models.IntegerField(),
|
||||
null=True,
|
||||
size=None,
|
||||
verbose_name='reference ct ids',
|
||||
),
|
||||
),
|
||||
('data', models.JSONField(null=True, verbose_name='data')),
|
||||
('api', models.BooleanField(default=False, verbose_name='API')),
|
||||
(
|
||||
'session',
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
db_constraint=False,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.DO_NOTHING,
|
||||
to='sessions.session',
|
||||
verbose_name='session',
|
||||
),
|
||||
),
|
||||
(
|
||||
'type',
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to='journal.eventtype',
|
||||
verbose_name='type',
|
||||
),
|
||||
),
|
||||
(
|
||||
'user',
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
db_constraint=False,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.DO_NOTHING,
|
||||
to='custom_user.user',
|
||||
verbose_name='user',
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'event',
|
||||
'verbose_name_plural': 'events',
|
||||
'ordering': ('timestamp', 'id'),
|
||||
},
|
||||
),
|
||||
]
|
|
@ -23,7 +23,6 @@ from contextlib import contextmanager
|
|||
from datetime import datetime, timedelta
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.contrib.postgres.fields import ArrayField
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
|
@ -41,8 +40,6 @@ from .utils import Statistics
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
_registry = {}
|
||||
|
||||
|
||||
|
@ -87,6 +84,8 @@ class EventTypeDefinition(metaclass=EventTypeDefinitionMeta):
|
|||
|
||||
@classmethod
|
||||
def record(cls, *, user=None, session=None, references=None, data=None, api=False):
|
||||
from authentic2.custom_user.models import User
|
||||
|
||||
event_type = EventType.objects.get_for_name(cls.name)
|
||||
|
||||
if user and not isinstance(user, User):
|
||||
|
@ -216,6 +215,8 @@ class EventType(models.Model):
|
|||
class EventQuerySet(QuerySet):
|
||||
@classmethod
|
||||
def _which_references_query(cls, instance_or_model_class_or_queryset):
|
||||
from authentic2.custom_user.models import User
|
||||
|
||||
if isinstance(instance_or_model_class_or_queryset, list):
|
||||
return functools.reduce(
|
||||
operator.or_,
|
||||
|
@ -315,7 +316,7 @@ class Event(models.Model):
|
|||
|
||||
user = models.ForeignKey(
|
||||
verbose_name=_('user'),
|
||||
to=User,
|
||||
to='custom_user.User',
|
||||
on_delete=models.DO_NOTHING,
|
||||
db_constraint=False,
|
||||
blank=True,
|
||||
|
@ -489,6 +490,8 @@ class EventCursor(str):
|
|||
|
||||
def prefetch_events_references(events, prefetcher=None):
|
||||
'''Prefetch references on an iterable of events, prevent N+1 queries problem.'''
|
||||
from authentic2.custom_user.models import User
|
||||
|
||||
grouped_references = defaultdict(set)
|
||||
references = {}
|
||||
|
||||
|
|
|
@ -17,13 +17,12 @@
|
|||
import re
|
||||
from functools import reduce
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.db.models import Q
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from . import models
|
||||
from authentic2.custom_user.models import User
|
||||
|
||||
User = get_user_model()
|
||||
from . import models
|
||||
|
||||
QUOTED_RE = re.compile(r'^[a-z0-9_-]*:"[^"]*"$')
|
||||
LEXER_RE = re.compile(r'([a-z0-9_-]*:(?:"[^"]*"|[^ ]*)|[^\s]*)\s*')
|
||||
|
|
|
@ -1,484 +0,0 @@
|
|||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('auth', '0002_auto_20150323_1720'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='AttributeItem',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
|
||||
),
|
||||
(
|
||||
'attribute_name',
|
||||
models.CharField(
|
||||
default=('OpenLDAProotDSE', 'OpenLDAProotDSE'),
|
||||
max_length=100,
|
||||
verbose_name='Attribute name',
|
||||
choices=[
|
||||
('OpenLDAProotDSE', 'OpenLDAProotDSE'),
|
||||
('aRecord', 'aRecord'),
|
||||
('administrativeRole', 'administrativeRole'),
|
||||
('alias', 'alias'),
|
||||
('aliasedObjectName', 'aliasedObjectName'),
|
||||
('altServer', 'altServer'),
|
||||
('associatedDomain', 'associatedDomain'),
|
||||
('associatedName', 'associatedName'),
|
||||
('attributeTypes', 'attributeTypes'),
|
||||
('audio', 'audio'),
|
||||
('authPassword', 'authPassword'),
|
||||
('authorityRevocationList', 'authorityRevocationList'),
|
||||
('authzFrom', 'authzFrom'),
|
||||
('authzTo', 'authzTo'),
|
||||
('bootFile', 'bootFile'),
|
||||
('bootParameter', 'bootParameter'),
|
||||
('buildingName', 'buildingName'),
|
||||
('businessCategory', 'businessCategory'),
|
||||
('c', 'c'),
|
||||
('cACertificate', 'cACertificate'),
|
||||
('cNAMERecord', 'cNAMERecord'),
|
||||
('carLicense', 'carLicense'),
|
||||
('certificateRevocationList', 'certificateRevocationList'),
|
||||
('children', 'children'),
|
||||
('cn', 'cn'),
|
||||
('co', 'co'),
|
||||
('collectiveAttributeSubentries', 'collectiveAttributeSubentries'),
|
||||
('collectiveAttributeSubentry', 'collectiveAttributeSubentry'),
|
||||
('collectiveExclusions', 'collectiveExclusions'),
|
||||
('configContext', 'configContext'),
|
||||
('contextCSN', 'contextCSN'),
|
||||
('createTimestamp', 'createTimestamp'),
|
||||
('creatorsName', 'creatorsName'),
|
||||
('crossCertificatePair', 'crossCertificatePair'),
|
||||
('dITContentRules', 'dITContentRules'),
|
||||
('dITRedirect', 'dITRedirect'),
|
||||
('dITStructureRules', 'dITStructureRules'),
|
||||
('dSAQuality', 'dSAQuality'),
|
||||
('dc', 'dc'),
|
||||
('deltaRevocationList', 'deltaRevocationList'),
|
||||
('departmentNumber', 'departmentNumber'),
|
||||
('description', 'description'),
|
||||
('destinationIndicator', 'destinationIndicator'),
|
||||
('displayName', 'displayName'),
|
||||
('distinguishedName', 'distinguishedName'),
|
||||
('dmdName', 'dmdName'),
|
||||
('dnQualifier', 'dnQualifier'),
|
||||
('documentAuthor', 'documentAuthor'),
|
||||
('documentIdentifier', 'documentIdentifier'),
|
||||
('documentLocation', 'documentLocation'),
|
||||
('documentPublisher', 'documentPublisher'),
|
||||
('documentTitle', 'documentTitle'),
|
||||
('documentVersion', 'documentVersion'),
|
||||
('drink', 'drink'),
|
||||
('dynamicObject', 'dynamicObject'),
|
||||
('dynamicSubtrees', 'dynamicSubtrees'),
|
||||
('eduOrgHomePageURI', 'eduOrgHomePageURI'),
|
||||
('eduOrgIdentityAuthNPolicyURI', 'eduOrgIdentityAuthNPolicyURI'),
|
||||
('eduOrgLegalName', 'eduOrgLegalName'),
|
||||
('eduOrgSuperiorURI', 'eduOrgSuperiorURI'),
|
||||
('eduOrgWhitePagesURI', 'eduOrgWhitePagesURI'),
|
||||
('eduPersonAffiliation', 'eduPersonAffiliation'),
|
||||
('eduPersonAssurance', 'eduPersonAssurance'),
|
||||
('eduPersonEntitlement', 'eduPersonEntitlement'),
|
||||
('eduPersonNickname', 'eduPersonNickname'),
|
||||
('eduPersonOrgDN', 'eduPersonOrgDN'),
|
||||
('eduPersonOrgUnitDN', 'eduPersonOrgUnitDN'),
|
||||
('eduPersonPrimaryAffiliation', 'eduPersonPrimaryAffiliation'),
|
||||
('eduPersonPrimaryOrgUnitDN', 'eduPersonPrimaryOrgUnitDN'),
|
||||
('eduPersonPrincipalName', 'eduPersonPrincipalName'),
|
||||
('eduPersonScopedAffiliation', 'eduPersonScopedAffiliation'),
|
||||
('eduPersonTargetedID', 'eduPersonTargetedID'),
|
||||
('email', 'email'),
|
||||
('employeeNumber', 'employeeNumber'),
|
||||
('employeeType', 'employeeType'),
|
||||
('enhancedSearchGuide', 'enhancedSearchGuide'),
|
||||
('entry', 'entry'),
|
||||
('entryCSN', 'entryCSN'),
|
||||
('entryDN', 'entryDN'),
|
||||
('entryTtl', 'entryTtl'),
|
||||
('entryUUID', 'entryUUID'),
|
||||
('extensibleObject', 'extensibleObject'),
|
||||
('fax', 'fax'),
|
||||
('gecos', 'gecos'),
|
||||
('generationQualifier', 'generationQualifier'),
|
||||
('gidNumber', 'gidNumber'),
|
||||
('givenName', 'givenName'),
|
||||
('glue', 'glue'),
|
||||
('hasSubordinates', 'hasSubordinates'),
|
||||
('homeDirectory', 'homeDirectory'),
|
||||
('homePhone', 'homePhone'),
|
||||
('homePostalAddress', 'homePostalAddress'),
|
||||
('host', 'host'),
|
||||
('houseIdentifier', 'houseIdentifier'),
|
||||
('info', 'info'),
|
||||
('initials', 'initials'),
|
||||
('internationaliSDNNumber', 'internationaliSDNNumber'),
|
||||
('ipHostNumber', 'ipHostNumber'),
|
||||
('ipNetmaskNumber', 'ipNetmaskNumber'),
|
||||
('ipNetworkNumber', 'ipNetworkNumber'),
|
||||
('ipProtocolNumber', 'ipProtocolNumber'),
|
||||
('ipServicePort', 'ipServicePort'),
|
||||
('ipServiceProtocolSUPname', 'ipServiceProtocolSUPname'),
|
||||
('janetMailbox', 'janetMailbox'),
|
||||
('jpegPhoto', 'jpegPhoto'),
|
||||
('knowledgeInformation', 'knowledgeInformation'),
|
||||
('l', 'l'),
|
||||
('labeledURI', 'labeledURI'),
|
||||
('ldapSyntaxes', 'ldapSyntaxes'),
|
||||
('loginShell', 'loginShell'),
|
||||
('mDRecord', 'mDRecord'),
|
||||
('mXRecord', 'mXRecord'),
|
||||
('macAddress', 'macAddress'),
|
||||
('mail', 'mail'),
|
||||
('mailForwardingAddress', 'mailForwardingAddress'),
|
||||
('mailHost', 'mailHost'),
|
||||
('mailLocalAddress', 'mailLocalAddress'),
|
||||
('mailPreferenceOption', 'mailPreferenceOption'),
|
||||
('mailRoutingAddress', 'mailRoutingAddress'),
|
||||
('manager', 'manager'),
|
||||
('matchingRuleUse', 'matchingRuleUse'),
|
||||
('matchingRules', 'matchingRules'),
|
||||
('member', 'member'),
|
||||
('memberNisNetgroup', 'memberNisNetgroup'),
|
||||
('memberUid', 'memberUid'),
|
||||
('mobile', 'mobile'),
|
||||
('modifiersName', 'modifiersName'),
|
||||
('modifyTimestamp', 'modifyTimestamp'),
|
||||
('monitorContext', 'monitorContext'),
|
||||
('nSRecord', 'nSRecord'),
|
||||
('name', 'name'),
|
||||
('nameForms', 'nameForms'),
|
||||
('namingCSN', 'namingCSN'),
|
||||
('namingContexts', 'namingContexts'),
|
||||
('nisMapEntry', 'nisMapEntry'),
|
||||
('nisMapNameSUPname', 'nisMapNameSUPname'),
|
||||
('nisNetgroupTriple', 'nisNetgroupTriple'),
|
||||
('o', 'o'),
|
||||
('objectClass', 'objectClass'),
|
||||
('objectClasses', 'objectClasses'),
|
||||
('oncRpcNumber', 'oncRpcNumber'),
|
||||
('organizationalStatus', 'organizationalStatus'),
|
||||
('otherMailbox', 'otherMailbox'),
|
||||
('ou', 'ou'),
|
||||
('owner', 'owner'),
|
||||
('pager', 'pager'),
|
||||
('personalSignature', 'personalSignature'),
|
||||
('personalTitle', 'personalTitle'),
|
||||
('photo', 'photo'),
|
||||
('physicalDeliveryOfficeName', 'physicalDeliveryOfficeName'),
|
||||
('postOfficeBox', 'postOfficeBox'),
|
||||
('postalAddress', 'postalAddress'),
|
||||
('postalCode', 'postalCode'),
|
||||
('preferredDeliveryMethod', 'preferredDeliveryMethod'),
|
||||
('preferredLanguage', 'preferredLanguage'),
|
||||
('presentationAddress', 'presentationAddress'),
|
||||
('protocolInformation', 'protocolInformation'),
|
||||
('pseudonym', 'pseudonym'),
|
||||
('ref', 'ref'),
|
||||
('referral', 'referral'),
|
||||
('registeredAddress', 'registeredAddress'),
|
||||
('rfc822MailMember', 'rfc822MailMember'),
|
||||
('role', 'role'),
|
||||
('roleOccupant', 'roleOccupant'),
|
||||
('roomNumber', 'roomNumber'),
|
||||
('sOARecord', 'sOARecord'),
|
||||
('schacHomeOrganization', 'schacHomeOrganization'),
|
||||
('schacHomeOrganizationType', 'schacHomeOrganizationType'),
|
||||
('searchGuide', 'searchGuide'),
|
||||
('secretary', 'secretary'),
|
||||
('seeAlso', 'seeAlso'),
|
||||
('serialNumber', 'serialNumber'),
|
||||
('shadowExpire', 'shadowExpire'),
|
||||
('shadowFlag', 'shadowFlag'),
|
||||
('shadowInactive', 'shadowInactive'),
|
||||
('shadowLastChange', 'shadowLastChange'),
|
||||
('shadowMax', 'shadowMax'),
|
||||
('shadowMin', 'shadowMin'),
|
||||
('shadowWarning', 'shadowWarning'),
|
||||
('singleLevelQuality', 'singleLevelQuality'),
|
||||
('sn', 'sn'),
|
||||
('st', 'st'),
|
||||
('street', 'street'),
|
||||
('structuralObjectClass', 'structuralObjectClass'),
|
||||
('subentry', 'subentry'),
|
||||
('subschema', 'subschema'),
|
||||
('subschemaSubentry', 'subschemaSubentry'),
|
||||
('subtreeMaximumQuality', 'subtreeMaximumQuality'),
|
||||
('subtreeMinimumQuality', 'subtreeMinimumQuality'),
|
||||
('subtreeSpecification', 'subtreeSpecification'),
|
||||
('supannActivite', 'supannActivite'),
|
||||
('supannAffectation', 'supannAffectation'),
|
||||
('supannAliasLogin', 'supannAliasLogin'),
|
||||
('supannAutreMail', 'supannAutreMail'),
|
||||
('supannAutreTelephone', 'supannAutreTelephone'),
|
||||
('supannCivilite', 'supannCivilite'),
|
||||
('supannCodeEntite', 'supannCodeEntite'),
|
||||
('supannCodeEntiteParent', 'supannCodeEntiteParent'),
|
||||
('supannCodeINE', 'supannCodeINE'),
|
||||
('supannEmpCorps', 'supannEmpCorps'),
|
||||
('supannEmpId', 'supannEmpId'),
|
||||
('supannEntiteAffectation', 'supannEntiteAffectation'),
|
||||
('supannEntiteAffectationPrincipale', 'supannEntiteAffectationPrincipale'),
|
||||
('supannEtablissement', 'supannEtablissement'),
|
||||
('supannEtuAnneeInscription', 'supannEtuAnneeInscription'),
|
||||
('supannEtuCursusAnnee', 'supannEtuCursusAnnee'),
|
||||
('supannEtuDiplome', 'supannEtuDiplome'),
|
||||
('supannEtuElementPedagogique', 'supannEtuElementPedagogique'),
|
||||
('supannEtuEtape', 'supannEtuEtape'),
|
||||
('supannEtuId', 'supannEtuId'),
|
||||
('supannEtuInscription', 'supannEtuInscription'),
|
||||
('supannEtuRegimeInscription', 'supannEtuRegimeInscription'),
|
||||
('supannEtuSecteurDisciplinaire', 'supannEtuSecteurDisciplinaire'),
|
||||
('supannEtuTypeDiplome', 'supannEtuTypeDiplome'),
|
||||
('supannGroupeAdminDN', 'supannGroupeAdminDN'),
|
||||
('supannGroupeDateFin', 'supannGroupeDateFin'),
|
||||
('supannGroupeLecteurDN', 'supannGroupeLecteurDN'),
|
||||
('supannListeRouge', 'supannListeRouge'),
|
||||
('supannMailPerso', 'supannMailPerso'),
|
||||
('supannOrganisme', 'supannOrganisme'),
|
||||
('supannParrainDN', 'supannParrainDN'),
|
||||
('supannRefId', 'supannRefId'),
|
||||
('supannRole', 'supannRole'),
|
||||
('supannRoleEntite', 'supannRoleEntite'),
|
||||
('supannRoleGenerique', 'supannRoleGenerique'),
|
||||
('supannTypeEntite', 'supannTypeEntite'),
|
||||
('supannTypeEntiteAffectation', 'supannTypeEntiteAffectation'),
|
||||
('superiorUUID', 'superiorUUID'),
|
||||
('supportedAlgorithms', 'supportedAlgorithms'),
|
||||
('supportedApplicationContext', 'supportedApplicationContext'),
|
||||
('supportedAuthPasswordSchemes', 'supportedAuthPasswordSchemes'),
|
||||
('supportedControl', 'supportedControl'),
|
||||
('supportedExtension', 'supportedExtension'),
|
||||
('supportedFeatures', 'supportedFeatures'),
|
||||
('supportedLDAPVersion', 'supportedLDAPVersion'),
|
||||
('supportedSASLMechanisms', 'supportedSASLMechanisms'),
|
||||
('syncConsumerSubentry', 'syncConsumerSubentry'),
|
||||
('syncProviderSubentry', 'syncProviderSubentry'),
|
||||
('syncTimestamp', 'syncTimestamp'),
|
||||
('syncreplCookie', 'syncreplCookie'),
|
||||
('telephoneNumber', 'telephoneNumber'),
|
||||
('teletexTerminalIdentifier', 'teletexTerminalIdentifier'),
|
||||
('telexNumber', 'telexNumber'),
|
||||
('textEncodedORAddress', 'textEncodedORAddress'),
|
||||
('title', 'title'),
|
||||
('top', 'top'),
|
||||
('uid', 'uid'),
|
||||
('uidNumber', 'uidNumber'),
|
||||
('uniqueIdentifier', 'uniqueIdentifier'),
|
||||
('uniqueMember', 'uniqueMember'),
|
||||
('userCertificate', 'userCertificate'),
|
||||
('userClass', 'userClass'),
|
||||
('userPKCS12', 'userPKCS12'),
|
||||
('userPassword', 'userPassword'),
|
||||
('userSMIMECertificate', 'userSMIMECertificate'),
|
||||
('vendorName', 'vendorName'),
|
||||
('vendorVersion', 'vendorVersion'),
|
||||
('x121Address', 'x121Address'),
|
||||
('x500UniqueIdentifier', 'x500UniqueIdentifier'),
|
||||
],
|
||||
),
|
||||
),
|
||||
(
|
||||
'output_name_format',
|
||||
models.CharField(
|
||||
default=('urn:oasis:names:tc:SAML:2.0:attrname-format:uri', 'SAMLv2 URI'),
|
||||
max_length=100,
|
||||
verbose_name='Output name format',
|
||||
choices=[
|
||||
('urn:oasis:names:tc:SAML:2.0:attrname-format:uri', 'SAMLv2 URI'),
|
||||
('urn:oasis:names:tc:SAML:2.0:attrname-format:basic', 'SAMLv2 BASIC'),
|
||||
],
|
||||
),
|
||||
),
|
||||
(
|
||||
'output_namespace',
|
||||
models.CharField(
|
||||
default=('Default', 'Default'),
|
||||
max_length=100,
|
||||
verbose_name='Output namespace',
|
||||
choices=[
|
||||
('Default', 'Default'),
|
||||
(
|
||||
'http://schemas.xmlsoap.org/ws/2005/05/identity/claims',
|
||||
'http://schemas.xmlsoap.org/ws/2005/05/identity/claims',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
('required', models.BooleanField(default=False, verbose_name='Required')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'attribute list item',
|
||||
'verbose_name_plural': 'attribute list items',
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AttributeList',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
|
||||
),
|
||||
('name', models.CharField(unique=True, max_length=100, verbose_name='Name')),
|
||||
(
|
||||
'attributes',
|
||||
models.ManyToManyField(
|
||||
related_name='attributes of the list',
|
||||
null=True,
|
||||
verbose_name='Attributes',
|
||||
to='attribute_aggregator.AttributeItem',
|
||||
blank=True,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'attribute list',
|
||||
'verbose_name_plural': 'attribute lists',
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AttributeSource',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
|
||||
),
|
||||
('name', models.CharField(unique=True, max_length=200, verbose_name='Name')),
|
||||
(
|
||||
'namespace',
|
||||
models.CharField(
|
||||
default=('Default', 'Default'),
|
||||
max_length=100,
|
||||
verbose_name='Namespace',
|
||||
choices=[
|
||||
('Default', 'Default'),
|
||||
(
|
||||
'http://schemas.xmlsoap.org/ws/2005/05/identity/claims',
|
||||
'http://schemas.xmlsoap.org/ws/2005/05/identity/claims',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'attribute source',
|
||||
'verbose_name_plural': 'attribute sources',
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='LdapSource',
|
||||
fields=[
|
||||
(
|
||||
'attributesource_ptr',
|
||||
models.OneToOneField(
|
||||
parent_link=True,
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to='attribute_aggregator.AttributeSource',
|
||||
on_delete=models.CASCADE,
|
||||
),
|
||||
),
|
||||
('server', models.CharField(unique=True, max_length=200, verbose_name='Server')),
|
||||
('user', models.CharField(max_length=200, null=True, verbose_name='User', blank=True)),
|
||||
(
|
||||
'password',
|
||||
models.CharField(max_length=200, null=True, verbose_name='Password', blank=True),
|
||||
),
|
||||
('base', models.CharField(max_length=200, verbose_name='Base')),
|
||||
('port', models.IntegerField(default=389, verbose_name='Port')),
|
||||
('ldaps', models.BooleanField(default=False, verbose_name='LDAPS')),
|
||||
('certificate', models.TextField(verbose_name='Certificate', blank=True)),
|
||||
(
|
||||
'is_auth_backend',
|
||||
models.BooleanField(default=False, verbose_name='Is it used for authentication?'),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'ldap attribute source',
|
||||
'verbose_name_plural': 'ldap attribute sources',
|
||||
},
|
||||
bases=('attribute_aggregator.attributesource',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='UserAliasInSource',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
|
||||
),
|
||||
('name', models.CharField(max_length=200, verbose_name='Name')),
|
||||
(
|
||||
'source',
|
||||
models.ForeignKey(
|
||||
verbose_name='attribute source',
|
||||
to='attribute_aggregator.AttributeSource',
|
||||
on_delete=models.CASCADE,
|
||||
),
|
||||
),
|
||||
(
|
||||
'user',
|
||||
models.ForeignKey(
|
||||
related_name='user_alias_in_source',
|
||||
verbose_name='user',
|
||||
to='auth.User',
|
||||
on_delete=models.CASCADE,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'user alias from source',
|
||||
'verbose_name_plural': 'user aliases from source',
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='UserAttributeProfile',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
|
||||
),
|
||||
('data', models.TextField(null=True, blank=True)),
|
||||
(
|
||||
'user',
|
||||
models.OneToOneField(
|
||||
related_name='user_attribute_profile',
|
||||
null=True,
|
||||
blank=True,
|
||||
to='auth.User',
|
||||
on_delete=models.CASCADE,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'user attribute profile',
|
||||
'verbose_name_plural': 'user attribute profiles',
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='useraliasinsource',
|
||||
unique_together={('name', 'source')},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='attributeitem',
|
||||
name='source',
|
||||
field=models.ForeignKey(
|
||||
verbose_name='Attribute source',
|
||||
blank=True,
|
||||
to='attribute_aggregator.AttributeSource',
|
||||
null=True,
|
||||
on_delete=models.CASCADE,
|
||||
),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
|
@ -1,35 +0,0 @@
|
|||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('attribute_aggregator', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='useraliasinsource',
|
||||
name='user',
|
||||
field=models.ForeignKey(
|
||||
related_name='user_alias_in_source',
|
||||
verbose_name='user',
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
on_delete=models.CASCADE,
|
||||
),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='userattributeprofile',
|
||||
name='user',
|
||||
field=models.OneToOneField(
|
||||
related_name='user_attribute_profile',
|
||||
null=True,
|
||||
blank=True,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
on_delete=models.CASCADE,
|
||||
),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
|
@ -1,25 +0,0 @@
|
|||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('attribute_aggregator', '0002_auto_20150409_1840'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='attributelist',
|
||||
name='attributes',
|
||||
field=models.ManyToManyField(
|
||||
to='attribute_aggregator.AttributeItem', verbose_name='Attributes', blank=True
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='useraliasinsource',
|
||||
name='user',
|
||||
field=models.ForeignKey(
|
||||
verbose_name='user', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE
|
||||
),
|
||||
),
|
||||
]
|
|
@ -1,57 +0,0 @@
|
|||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('idp', '0003_auto_20150915_2041'),
|
||||
('attribute_aggregator', '0003_auto_20150526_2239'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='attributeitem',
|
||||
name='source',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='attributelist',
|
||||
name='attributes',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='AttributeItem',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='AttributeList',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='ldapsource',
|
||||
name='attributesource_ptr',
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='useraliasinsource',
|
||||
unique_together=None,
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='useraliasinsource',
|
||||
name='source',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='LdapSource',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='AttributeSource',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='useraliasinsource',
|
||||
name='user',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='UserAliasInSource',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='userattributeprofile',
|
||||
name='user',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='UserAttributeProfile',
|
||||
),
|
||||
]
|
|
@ -14,10 +14,10 @@
|
|||
# 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/>.
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from authentic2.a2_rbac.models import Role
|
||||
from authentic2.custom_user.models import User
|
||||
|
||||
from ...decorators import to_list
|
||||
from ...models import Attribute, AttributeValue
|
||||
|
@ -33,7 +33,6 @@ def get_instances(ctx):
|
|||
|
||||
@to_list
|
||||
def get_attribute_names(instance, ctx):
|
||||
User = get_user_model()
|
||||
for field in User._meta.fields:
|
||||
if field.name == 'ou':
|
||||
continue
|
||||
|
@ -69,7 +68,6 @@ def get_dependencies(instance, ctx):
|
|||
|
||||
def get_attributes(instance, ctx):
|
||||
user = ctx.get('user')
|
||||
User = get_user_model()
|
||||
if not user or not isinstance(user, User):
|
||||
return ctx
|
||||
for field in User._meta.fields:
|
||||
|
|
|
@ -1,135 +0,0 @@
|
|||
from django.core import validators
|
||||
from django.db import migrations, models
|
||||
from django.utils import timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('contenttypes', '__first__'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Permission',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
|
||||
),
|
||||
('name', models.CharField(max_length=50, verbose_name='name')),
|
||||
(
|
||||
'content_type',
|
||||
models.ForeignKey(to='contenttypes.ContentType', to_field='id', on_delete=models.CASCADE),
|
||||
),
|
||||
('codename', models.CharField(max_length=100, verbose_name='codename')),
|
||||
],
|
||||
options={
|
||||
'ordering': ('content_type__app_label', 'content_type__model', 'codename'),
|
||||
'verbose_name': 'permission',
|
||||
'verbose_name_plural': 'permissions',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Group',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
|
||||
),
|
||||
('name', models.CharField(unique=True, max_length=80, verbose_name='name')),
|
||||
(
|
||||
'permissions',
|
||||
models.ManyToManyField(to='auth.Permission', verbose_name='permissions', blank=True),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'group',
|
||||
'verbose_name_plural': 'groups',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='User',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
|
||||
),
|
||||
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||
('last_login', models.DateTimeField(default=timezone.now, verbose_name='last login')),
|
||||
(
|
||||
'is_superuser',
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
help_text=(
|
||||
'Designates that this user has all permissions without explicitly assigning them.'
|
||||
),
|
||||
verbose_name='superuser status',
|
||||
),
|
||||
),
|
||||
(
|
||||
'username',
|
||||
models.CharField(
|
||||
help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.',
|
||||
unique=True,
|
||||
max_length=30,
|
||||
verbose_name='username',
|
||||
validators=[
|
||||
validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username.', 'invalid')
|
||||
],
|
||||
),
|
||||
),
|
||||
('first_name', models.CharField(max_length=30, verbose_name='first name', blank=True)),
|
||||
('last_name', models.CharField(max_length=30, verbose_name='last name', blank=True)),
|
||||
('email', models.EmailField(max_length=75, verbose_name='email address', blank=True)),
|
||||
(
|
||||
'is_staff',
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
help_text='Designates whether the user can log into this admin site.',
|
||||
verbose_name='staff status',
|
||||
),
|
||||
),
|
||||
(
|
||||
'is_active',
|
||||
models.BooleanField(
|
||||
default=True,
|
||||
help_text=(
|
||||
'Designates whether this user should be treated as active. Unselect this instead'
|
||||
' of deleting accounts.'
|
||||
),
|
||||
verbose_name='active',
|
||||
),
|
||||
),
|
||||
('date_joined', models.DateTimeField(default=timezone.now, verbose_name='date joined')),
|
||||
(
|
||||
'groups',
|
||||
models.ManyToManyField(
|
||||
to='auth.Group',
|
||||
verbose_name='groups',
|
||||
blank=True,
|
||||
help_text=(
|
||||
'The groups this user belongs to. A user will get all permissions granted to each'
|
||||
' of his/her group.'
|
||||
),
|
||||
related_name='+',
|
||||
related_query_name='+',
|
||||
),
|
||||
),
|
||||
(
|
||||
'user_permissions',
|
||||
models.ManyToManyField(
|
||||
to='auth.Permission',
|
||||
verbose_name='user permissions',
|
||||
blank=True,
|
||||
help_text='Specific permissions for this user.',
|
||||
related_name='+',
|
||||
related_query_name='+',
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'user',
|
||||
'verbose_name_plural': 'users',
|
||||
},
|
||||
),
|
||||
]
|
|
@ -1,30 +0,0 @@
|
|||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('auth', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='user',
|
||||
name='username',
|
||||
field=models.CharField(
|
||||
help_text=(
|
||||
'Required, 255 characters or fewer. Only letters, numbers, and @, ., +, -, or _'
|
||||
' characters.'
|
||||
),
|
||||
unique=True,
|
||||
max_length=255,
|
||||
verbose_name='username',
|
||||
validators=[
|
||||
django.core.validators.RegexValidator(
|
||||
'^[\\w.@+-]+$', 'Enter a valid username.', 'invalid'
|
||||
)
|
||||
],
|
||||
),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
|
@ -1,13 +0,0 @@
|
|||
from django.conf import settings
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('auth', '0002_auto_20150323_1720'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.DeleteModel('User'),
|
||||
]
|
|
@ -1,111 +0,0 @@
|
|||
import django.core.validators
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('auth', '0003_auto_20150410_1657'),
|
||||
('authentic2', '__first__'),
|
||||
('authentic2_idp_cas', '__first__'),
|
||||
('saml', '__first__'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='User',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
|
||||
),
|
||||
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||
(
|
||||
'last_login',
|
||||
models.DateTimeField(default=django.utils.timezone.now, verbose_name='last login'),
|
||||
),
|
||||
(
|
||||
'is_superuser',
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
help_text=(
|
||||
'Designates that this user has all permissions without explicitly assigning them.'
|
||||
),
|
||||
verbose_name='superuser status',
|
||||
),
|
||||
),
|
||||
(
|
||||
'username',
|
||||
models.CharField(
|
||||
help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.',
|
||||
unique=True,
|
||||
max_length=30,
|
||||
verbose_name='username',
|
||||
validators=[
|
||||
django.core.validators.RegexValidator(
|
||||
'^[\\w.@+-]+$', 'Enter a valid username.', 'invalid'
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
('first_name', models.CharField(max_length=30, verbose_name='first name', blank=True)),
|
||||
('last_name', models.CharField(max_length=30, verbose_name='last name', blank=True)),
|
||||
('email', models.EmailField(max_length=75, verbose_name='email address', blank=True)),
|
||||
(
|
||||
'is_staff',
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
help_text='Designates whether the user can log into this admin site.',
|
||||
verbose_name='staff status',
|
||||
),
|
||||
),
|
||||
(
|
||||
'is_active',
|
||||
models.BooleanField(
|
||||
default=True,
|
||||
help_text=(
|
||||
'Designates whether this user should be treated as active. Unselect this instead'
|
||||
' of deleting accounts.'
|
||||
),
|
||||
verbose_name='active',
|
||||
),
|
||||
),
|
||||
(
|
||||
'date_joined',
|
||||
models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined'),
|
||||
),
|
||||
(
|
||||
'groups',
|
||||
models.ManyToManyField(
|
||||
related_query_name='user',
|
||||
related_name='user_set',
|
||||
to='auth.Group',
|
||||
blank=True,
|
||||
help_text=(
|
||||
'The groups this user belongs to. A user will get all permissions granted to each'
|
||||
' of his/her group.'
|
||||
),
|
||||
verbose_name='groups',
|
||||
),
|
||||
),
|
||||
(
|
||||
'user_permissions',
|
||||
models.ManyToManyField(
|
||||
related_query_name='user',
|
||||
related_name='user_set',
|
||||
to='auth.Permission',
|
||||
blank=True,
|
||||
help_text='Specific permissions for this user.',
|
||||
verbose_name='user permissions',
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'verbose_name': 'user',
|
||||
'swappable': 'AUTH_USER_MODEL',
|
||||
'verbose_name_plural': 'users',
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
]
|
|
@ -1,79 +0,0 @@
|
|||
import django.contrib.auth.models
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('auth', '0004_user'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelManagers(
|
||||
name='group',
|
||||
managers=[
|
||||
('objects', django.contrib.auth.models.GroupManager()),
|
||||
],
|
||||
),
|
||||
migrations.AlterModelManagers(
|
||||
name='permission',
|
||||
managers=[
|
||||
('objects', django.contrib.auth.models.PermissionManager()),
|
||||
],
|
||||
),
|
||||
migrations.AlterModelManagers(
|
||||
name='user',
|
||||
managers=[
|
||||
('objects', django.contrib.auth.models.UserManager()),
|
||||
],
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='permission',
|
||||
name='name',
|
||||
field=models.CharField(max_length=255, verbose_name='name'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='user',
|
||||
name='email',
|
||||
field=models.EmailField(max_length=254, verbose_name='email address', blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='user',
|
||||
name='groups',
|
||||
field=models.ManyToManyField(
|
||||
related_query_name='user',
|
||||
related_name='user_set',
|
||||
to='auth.Group',
|
||||
blank=True,
|
||||
help_text=(
|
||||
'The groups this user belongs to. A user will get all permissions granted to each of'
|
||||
' their groups.'
|
||||
),
|
||||
verbose_name='groups',
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='user',
|
||||
name='last_login',
|
||||
field=models.DateTimeField(null=True, verbose_name='last login', blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='user',
|
||||
name='username',
|
||||
field=models.CharField(
|
||||
error_messages={'unique': 'A user with that username already exists.'},
|
||||
max_length=30,
|
||||
validators=[
|
||||
django.core.validators.RegexValidator(
|
||||
'^[\\w.@+-]+$',
|
||||
'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_'
|
||||
' characters.',
|
||||
'invalid',
|
||||
)
|
||||
],
|
||||
help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.',
|
||||
unique=True,
|
||||
verbose_name='username',
|
||||
),
|
||||
),
|
||||
]
|
|
@ -14,13 +14,11 @@
|
|||
# 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/>.
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
from authentic2 import app_settings
|
||||
|
||||
|
||||
def get_user_queryset():
|
||||
User = get_user_model()
|
||||
from authentic2.custom_user.models import User
|
||||
|
||||
qs = User.objects.all()
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@ import ldap.modlist
|
|||
import ldap.sasl
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import Group
|
||||
from django.core.cache import cache
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
|
@ -52,6 +51,7 @@ from authentic2.a2_rbac.models import OrganizationalUnit, Role
|
|||
from authentic2.a2_rbac.utils import get_default_ou
|
||||
from authentic2.backends import is_user_authenticable
|
||||
from authentic2.compat_lasso import lasso
|
||||
from authentic2.custom_user.models import User
|
||||
from authentic2.ldap_utils import FilterFormatter
|
||||
from authentic2.middleware import StoreRequestMiddleware
|
||||
from authentic2.models import Lock, UserExternalId
|
||||
|
@ -65,8 +65,6 @@ from authentic2.utils.misc import PasswordChangeError, get_password_authenticato
|
|||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
DEFAULT_CA_BUNDLE = ''
|
||||
|
||||
CA_BUNDLE_PATHS = [
|
||||
|
@ -393,24 +391,24 @@ class LDAPUser(User):
|
|||
log.warning('ldap: check_password failed, could not get a connection')
|
||||
return False
|
||||
|
||||
def set_password(self, new_password):
|
||||
def set_password(self, raw_password):
|
||||
# Allow change password to work in all cases, as the form does a check_password() first
|
||||
# if the verify pass, we have the old password stored in self._current_password
|
||||
_current_password = getattr(self, '_current_password', None) or self.get_password_in_session()
|
||||
if _current_password != new_password:
|
||||
if _current_password != raw_password:
|
||||
conn = self.get_connection()
|
||||
if not conn:
|
||||
log.warning('ldap: set_password failed, could not get a connection')
|
||||
return
|
||||
try:
|
||||
self.ldap_backend.modify_password(conn, self.block, self.dn, _current_password, new_password)
|
||||
self.ldap_backend.modify_password(conn, self.block, self.dn, _current_password, raw_password)
|
||||
except ldap.LDAPError as e:
|
||||
log.warning('ldap: set_password failed (%s)', ldap_error_str(e))
|
||||
raise PasswordChangeError(_('LDAP directory refused the password change.'))
|
||||
self._current_password = new_password
|
||||
self.keep_password_in_session(new_password)
|
||||
self._current_password = raw_password
|
||||
self.keep_password_in_session(raw_password)
|
||||
if self.block['keep_password']:
|
||||
super().set_password(new_password)
|
||||
super().set_password(raw_password)
|
||||
else:
|
||||
self.set_unusable_password()
|
||||
|
||||
|
|
|
@ -17,13 +17,13 @@
|
|||
|
||||
import functools
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.backends import ModelBackend as BaseModelBackend
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db import models
|
||||
from phonenumbers import PhoneNumberFormat, format_number, is_valid_number
|
||||
|
||||
from authentic2.backends import get_user_queryset
|
||||
from authentic2.custom_user.models import User
|
||||
from authentic2.models import AttributeValue
|
||||
from authentic2.user_login_failure import user_login_failure, user_login_success
|
||||
from authentic2.utils.misc import get_password_authenticator, parse_phone_number
|
||||
|
@ -40,15 +40,11 @@ PROXY_USER_MODEL = None
|
|||
|
||||
|
||||
class ModelBackend(BaseModelBackend):
|
||||
"""
|
||||
Authenticates against settings.AUTH_USER_MODEL.
|
||||
"""
|
||||
|
||||
def get_query(self, username, realm=None, ou=None):
|
||||
username_field = 'username'
|
||||
queries = []
|
||||
password_authenticator = get_password_authenticator()
|
||||
user_ct = ContentType.objects.get_for_model(get_user_model())
|
||||
user_ct = ContentType.objects.get_for_model(User)
|
||||
if password_authenticator.accept_email_authentication:
|
||||
queries.append(models.Q(**{'email__iexact': username}))
|
||||
if password_authenticator.is_phone_authn_active:
|
||||
|
@ -82,14 +78,13 @@ class ModelBackend(BaseModelBackend):
|
|||
return bool(a2_models.PasswordReset.filter(user=user).count())
|
||||
|
||||
def authenticate(self, request, username=None, password=None, realm=None, ou=None):
|
||||
UserModel = get_user_model()
|
||||
if not username:
|
||||
return
|
||||
query = self.get_query(username=username, realm=realm, ou=ou)
|
||||
users = get_user_queryset().filter(query)
|
||||
# order by username to make username without realm come before usernames with realms
|
||||
# i.e. "toto" should come before "toto@example.com"
|
||||
users = users.order_by('-is_active', UserModel.USERNAME_FIELD, 'id')
|
||||
users = users.order_by('-is_active', User.USERNAME_FIELD, 'id')
|
||||
for user in users:
|
||||
if user.check_password(password):
|
||||
user_login_success(user.get_username())
|
||||
|
@ -100,10 +95,9 @@ class ModelBackend(BaseModelBackend):
|
|||
request.failed_logins.update({user: {}})
|
||||
|
||||
def get_user(self, user_id):
|
||||
UserModel = get_user_model()
|
||||
try:
|
||||
user = UserModel._default_manager.get(pk=user_id)
|
||||
except UserModel.DoesNotExist:
|
||||
user = User._default_manager.get(pk=user_id)
|
||||
except User.DoesNotExist:
|
||||
return None
|
||||
return user
|
||||
|
||||
|
|
|
@ -38,12 +38,12 @@ class CustomUserConfig(AppConfig):
|
|||
self, app_config, verbosity=2, interactive=True, using=DEFAULT_DB_ALIAS, **kwargs
|
||||
):
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils import translation
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from authentic2.attribute_kinds import get_kind
|
||||
from authentic2.custom_user.models import User
|
||||
from authentic2.models import Attribute, AttributeValue
|
||||
|
||||
if not router.allow_migrate(using, Attribute):
|
||||
|
@ -53,7 +53,6 @@ class CustomUserConfig(AppConfig):
|
|||
return
|
||||
|
||||
translation.activate(settings.LANGUAGE_CODE)
|
||||
User = get_user_model()
|
||||
content_type = ContentType.objects.get_for_model(User)
|
||||
|
||||
attrs = {}
|
||||
|
|
|
@ -17,13 +17,14 @@
|
|||
|
||||
import getpass
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.exceptions import MultipleObjectsReturned
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.db import DEFAULT_DB_ALIAS
|
||||
from django.db.models.query import Q
|
||||
from django.utils.encoding import force_str
|
||||
|
||||
from authentic2.custom_user.models import User
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Change a user's password for django.contrib.auth."
|
||||
|
@ -51,13 +52,11 @@ class Command(BaseCommand):
|
|||
if not username:
|
||||
username = getpass.getuser()
|
||||
|
||||
UserModel = get_user_model()
|
||||
|
||||
qs = UserModel._default_manager.using(options.get('database'))
|
||||
qs = User._default_manager.using(options.get('database'))
|
||||
qs = qs.filter(Q(uuid=username) | Q(username=username) | Q(email__iexact=username))
|
||||
try:
|
||||
u = qs.get()
|
||||
except UserModel.DoesNotExist:
|
||||
except User.DoesNotExist:
|
||||
raise CommandError("user '%s' does not exist" % username)
|
||||
except MultipleObjectsReturned:
|
||||
while True:
|
||||
|
|
|
@ -5,80 +5,6 @@ import authentic2.utils.misc
|
|||
import authentic2.validators
|
||||
|
||||
|
||||
def noop(apps, schema_editor):
|
||||
pass
|
||||
|
||||
|
||||
def copy_old_users_to_custom_user_model(apps, schema_editor):
|
||||
OldUser = apps.get_model('auth', 'User')
|
||||
NewUser = apps.get_model('custom_user', 'User')
|
||||
fields = [
|
||||
'id',
|
||||
'username',
|
||||
'email',
|
||||
'first_name',
|
||||
'last_name',
|
||||
'is_staff',
|
||||
'is_active',
|
||||
'date_joined',
|
||||
'is_superuser',
|
||||
'last_login',
|
||||
'password',
|
||||
]
|
||||
old_users = OldUser.objects.prefetch_related('groups', 'user_permissions').order_by('id')
|
||||
new_users = []
|
||||
for old_user in old_users:
|
||||
new_user = NewUser()
|
||||
for field in fields:
|
||||
setattr(new_user, field, getattr(old_user, field))
|
||||
new_users.append(new_user)
|
||||
# mass create of new users
|
||||
NewUser.objects.bulk_create(new_users)
|
||||
new_groups = []
|
||||
new_permissions = []
|
||||
GroupThrough = NewUser.groups.through
|
||||
PermissionThrough = NewUser.user_permissions.through
|
||||
new_users = NewUser.objects.order_by('id')
|
||||
for old_user, new_user in zip(old_users, new_users):
|
||||
assert old_user.id == new_user.id
|
||||
for group in old_user.groups.all():
|
||||
new_groups.append(GroupThrough(user_id=new_user.id, group_id=group.id))
|
||||
for dummy in old_user.user_permissions.all():
|
||||
new_permissions.append(PermissionThrough(user_id=new_user.id, group_id=group.id))
|
||||
# mass create group and permission relations
|
||||
GroupThrough.objects.bulk_create(new_groups)
|
||||
PermissionThrough.objects.bulk_create(new_permissions)
|
||||
# Reset sequences
|
||||
if schema_editor.connection.vendor == 'postgresql':
|
||||
schema_editor.execute(
|
||||
'SELECT setval(pg_get_serial_sequence(\'"custom_user_user_groups"\',\'id\'), coalesce(max("id"),'
|
||||
' 1), max("id") IS NOT null) FROM "custom_user_user_groups";'
|
||||
)
|
||||
schema_editor.execute(
|
||||
'SELECT setval(pg_get_serial_sequence(\'"custom_user_user_user_permissions"\',\'id\'),'
|
||||
' coalesce(max("id"), 1), max("id") IS NOT null) FROM "custom_user_user_user_permissions";'
|
||||
)
|
||||
schema_editor.execute(
|
||||
'SELECT setval(pg_get_serial_sequence(\'"custom_user_user"\',\'id\'), coalesce(max("id"), 1),'
|
||||
' max("id") IS NOT null) FROM "custom_user_user";'
|
||||
)
|
||||
elif schema_editor.connection.vendor == 'sqlite':
|
||||
schema_editor.execute(
|
||||
'UPDATE sqlite_sequence SET seq = (SELECT MAX(id) FROM custom_user_user) WHERE name ='
|
||||
' "custom_user_user";'
|
||||
)
|
||||
schema_editor.execute(
|
||||
'UPDATE sqlite_sequence SET seq = (SELECT MAX(id) FROM custom_user_user_groups) WHERE name ='
|
||||
' "custom_user_user_groups";'
|
||||
)
|
||||
schema_editor.execute(
|
||||
'UPDATE sqlite_sequence SET seq = (SELECT MAX(id) FROM custom_user_user_user_permissions) WHERE'
|
||||
' name = "custom_user_user_permissions";'
|
||||
)
|
||||
else:
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('auth', '__first__'),
|
||||
|
@ -187,5 +113,4 @@ class Migration(migrations.Migration):
|
|||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.RunPython(copy_old_users_to_custom_user_model, reverse_code=noop),
|
||||
]
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
@ -37,11 +36,6 @@ class ThirdPartyAlterField(migrations.AlterField):
|
|||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('custom_user', '0001_initial'),
|
||||
('admin', '__first__'),
|
||||
]
|
||||
|
||||
run_before = [
|
||||
('auth', '0003_auto_20150410_1657'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
|
@ -50,7 +44,7 @@ class Migration(migrations.Migration):
|
|||
app_label='admin',
|
||||
model_name='logentry',
|
||||
name='user',
|
||||
field=models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE),
|
||||
field=models.ForeignKey(to='custom_user.User', on_delete=models.CASCADE),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
||||
|
|
|
@ -9,7 +9,6 @@ class Migration(migrations.Migration):
|
|||
dependencies = [
|
||||
('contenttypes', '__first__'),
|
||||
('custom_user', '0010_auto_20160307_1418'),
|
||||
('authentic2', '0015_auto_20160621_1711'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
|
|
|
@ -4,7 +4,6 @@ import uuid
|
|||
|
||||
import django
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
from django.db.models import JSONField
|
||||
|
||||
|
@ -64,7 +63,7 @@ class Migration(migrations.Migration):
|
|||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name='profiles',
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
to='custom_user.User',
|
||||
verbose_name='user',
|
||||
),
|
||||
),
|
||||
|
|
|
@ -6,7 +6,6 @@ from django.db import migrations, models
|
|||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('authentic2', '0035_service_home_url'),
|
||||
('custom_user', '0029_profile_profiletype'),
|
||||
]
|
||||
|
||||
|
|
|
@ -0,0 +1,358 @@
|
|||
# Generated by Django 3.2.23 on 2023-12-14 21:01
|
||||
|
||||
import uuid
|
||||
|
||||
import django.contrib.postgres.fields
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
import authentic2.utils.misc
|
||||
import authentic2.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
replaces = [
|
||||
('custom_user', '0001_initial'),
|
||||
('custom_user', '0002_auto_20150410_1823'),
|
||||
('custom_user', '0003_auto_20150504_1410'),
|
||||
('custom_user', '0004_user_ou'),
|
||||
('custom_user', '0005_auto_20150522_1527'),
|
||||
('custom_user', '0006_auto_20150527_1212'),
|
||||
('custom_user', '0007_auto_20150610_1527'),
|
||||
('custom_user', '0008_auto_20150617_1606'),
|
||||
('custom_user', '0009_auto_20150810_1953'),
|
||||
('custom_user', '0010_auto_20160307_1418'),
|
||||
('custom_user', '0011_manual_attribute_values_for_name_fields'),
|
||||
('custom_user', '0012_user_modified'),
|
||||
('custom_user', '0013_user_email_verified'),
|
||||
('custom_user', '0014_set_email_verified'),
|
||||
('custom_user', '0015_auto_20170707_1653'),
|
||||
('custom_user', '0016_auto_20180925_1107'),
|
||||
('custom_user', '0017_auto_20200305_1645'),
|
||||
('custom_user', '0018_user_last_account_deletion_alert'),
|
||||
('custom_user', '0019_add_user_deleted'),
|
||||
('custom_user', '0020_deleteduser'),
|
||||
('custom_user', '0021_set_unusable_password'),
|
||||
('custom_user', '0022_index_email'),
|
||||
('custom_user', '0023_index_username'),
|
||||
('custom_user', '0024_index_email_by_trigrams'),
|
||||
('custom_user', '0025_user_deactivation'),
|
||||
('custom_user', '0026_remove_user_deleted'),
|
||||
('custom_user', '0027_user_deactivation_reason'),
|
||||
('custom_user', '0028_user_email_verified_date'),
|
||||
('custom_user', '0029_profile_profiletype'),
|
||||
('custom_user', '0030_auto_20220304_1136'),
|
||||
('custom_user', '0031_profile_email'),
|
||||
('custom_user', '0032_auto_20220919_1230'),
|
||||
('custom_user', '0032_index_deleteduser_old_email'),
|
||||
('custom_user', '0032_index_deleteduser_old_uuid'),
|
||||
('custom_user', '0033_user_keepalive'),
|
||||
('custom_user', '0034_user_email_verified_sources'),
|
||||
('custom_user', '0035_alter_user_username'),
|
||||
('custom_user', '0036_remove_user_constraint_at_least_one_identifier'),
|
||||
]
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('auth', '0012_alter_user_first_name_max_length'),
|
||||
('a2_rbac', '0040_replace'),
|
||||
('authentic2', '0051_replace'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='DeletedUser',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('deleted', models.DateTimeField(auto_now_add=True, verbose_name='Deletion date')),
|
||||
('old_uuid', models.TextField(blank=True, db_index=True, null=True, verbose_name='Old UUID')),
|
||||
(
|
||||
'old_user_id',
|
||||
models.PositiveIntegerField(blank=True, null=True, verbose_name='Old user id'),
|
||||
),
|
||||
(
|
||||
'old_email',
|
||||
models.EmailField(
|
||||
blank=True, db_index=True, max_length=254, null=True, verbose_name='Old email adress'
|
||||
),
|
||||
),
|
||||
(
|
||||
'old_phone',
|
||||
models.CharField(blank=True, max_length=64, null=True, verbose_name='Old phone number'),
|
||||
),
|
||||
('old_data', models.JSONField(blank=True, null=True, verbose_name='Old data')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'deleted user',
|
||||
'verbose_name_plural': 'deleted users',
|
||||
'ordering': ('deleted', 'id'),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ProfileType',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
(
|
||||
'uuid',
|
||||
models.UUIDField(default=uuid.uuid4, editable=False, unique=True, verbose_name='UUID'),
|
||||
),
|
||||
('name', models.CharField(max_length=64, verbose_name='name')),
|
||||
('slug', models.SlugField(max_length=64, unique=True, verbose_name='slug')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'profile type',
|
||||
'verbose_name_plural': 'profile types',
|
||||
'ordering': ('name', 'slug'),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='User',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
|
||||
(
|
||||
'uuid',
|
||||
models.CharField(
|
||||
default=authentic2.utils.misc.get_hex_uuid,
|
||||
editable=False,
|
||||
max_length=32,
|
||||
unique=True,
|
||||
verbose_name='uuid',
|
||||
),
|
||||
),
|
||||
(
|
||||
'username',
|
||||
models.CharField(
|
||||
blank=True, db_index=True, max_length=256, null=True, verbose_name='username'
|
||||
),
|
||||
),
|
||||
('first_name', models.CharField(blank=True, max_length=128, verbose_name='first name')),
|
||||
('last_name', models.CharField(blank=True, max_length=128, verbose_name='last name')),
|
||||
(
|
||||
'email',
|
||||
models.EmailField(
|
||||
blank=True,
|
||||
max_length=254,
|
||||
validators=[authentic2.validators.EmailValidator()],
|
||||
verbose_name='email address',
|
||||
),
|
||||
),
|
||||
('email_verified', models.BooleanField(default=False, verbose_name='email verified')),
|
||||
(
|
||||
'email_verified_date',
|
||||
models.DateTimeField(
|
||||
blank=True, default=None, null=True, verbose_name='email verified date'
|
||||
),
|
||||
),
|
||||
(
|
||||
'email_verified_sources',
|
||||
django.contrib.postgres.fields.ArrayField(
|
||||
base_field=models.CharField(max_length=63),
|
||||
blank=True,
|
||||
default=list,
|
||||
null=True,
|
||||
size=None,
|
||||
verbose_name='email verification sources',
|
||||
),
|
||||
),
|
||||
(
|
||||
'is_superuser',
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
help_text='Designates that this user has all permissions without explicitly assigning them.',
|
||||
verbose_name='superuser status',
|
||||
),
|
||||
),
|
||||
(
|
||||
'phone',
|
||||
models.CharField(
|
||||
blank=True,
|
||||
max_length=64,
|
||||
null=True,
|
||||
validators=[authentic2.validators.PhoneNumberValidator],
|
||||
verbose_name='phone number',
|
||||
),
|
||||
),
|
||||
(
|
||||
'phone_verified_on',
|
||||
models.DateTimeField(
|
||||
blank=True, default=None, null=True, verbose_name='phone verification date'
|
||||
),
|
||||
),
|
||||
(
|
||||
'is_staff',
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
help_text='Designates whether the user can log into this admin site.',
|
||||
verbose_name='staff status',
|
||||
),
|
||||
),
|
||||
(
|
||||
'is_active',
|
||||
models.BooleanField(
|
||||
default=True,
|
||||
help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.',
|
||||
verbose_name='active',
|
||||
),
|
||||
),
|
||||
(
|
||||
'date_joined',
|
||||
models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined'),
|
||||
),
|
||||
(
|
||||
'modified',
|
||||
models.DateTimeField(auto_now=True, db_index=True, verbose_name='Last modification time'),
|
||||
),
|
||||
(
|
||||
'last_account_deletion_alert',
|
||||
models.DateTimeField(blank=True, null=True, verbose_name='Last account deletion alert'),
|
||||
),
|
||||
(
|
||||
'deactivation',
|
||||
models.DateTimeField(blank=True, null=True, verbose_name='Deactivation datetime'),
|
||||
),
|
||||
(
|
||||
'deactivation_reason',
|
||||
models.TextField(blank=True, null=True, verbose_name='Deactivation reason'),
|
||||
),
|
||||
(
|
||||
'keepalive',
|
||||
models.DateTimeField(blank=True, null=True, verbose_name='Keepalive timestamp'),
|
||||
),
|
||||
(
|
||||
'groups',
|
||||
models.ManyToManyField(
|
||||
blank=True,
|
||||
help_text='The groups this user belongs to. A user will get all permissions granted to each of his/her group.',
|
||||
related_name='user_set',
|
||||
related_query_name='user',
|
||||
to='auth.Group',
|
||||
verbose_name='groups',
|
||||
),
|
||||
),
|
||||
(
|
||||
'ou',
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to='a2_rbac.organizationalunit',
|
||||
verbose_name='organizational unit',
|
||||
),
|
||||
),
|
||||
(
|
||||
'user_permissions',
|
||||
models.ManyToManyField(
|
||||
blank=True,
|
||||
help_text='Specific permissions for this user.',
|
||||
related_name='user_set',
|
||||
related_query_name='user',
|
||||
to='auth.Permission',
|
||||
verbose_name='user permissions',
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'user',
|
||||
'verbose_name_plural': 'users',
|
||||
'ordering': ('last_name', 'first_name', 'email', 'username'),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ServiceProfileType',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
(
|
||||
'profile_type',
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, to='custom_user.profiletype'
|
||||
),
|
||||
),
|
||||
(
|
||||
'service',
|
||||
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='authentic2.service'),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('service', 'profile_type')},
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Profile',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('identifier', models.CharField(default='', max_length=256, verbose_name='identifier')),
|
||||
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
|
||||
('data', models.JSONField(blank=True, null=True, verbose_name='data')),
|
||||
(
|
||||
'profile_type',
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name='profiles',
|
||||
to='custom_user.profiletype',
|
||||
verbose_name='profile type',
|
||||
),
|
||||
),
|
||||
(
|
||||
'user',
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name='profiles',
|
||||
to='custom_user.user',
|
||||
verbose_name='user',
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'profile',
|
||||
'verbose_name_plural': 'profiles',
|
||||
'ordering': ('user', 'profile_type'),
|
||||
'unique_together': {('user', 'profile_type', 'identifier')},
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='profiletype',
|
||||
name='services',
|
||||
field=models.ManyToManyField(
|
||||
blank=True,
|
||||
related_name='_custom_user_profiletype_services_+',
|
||||
through='custom_user.ServiceProfileType',
|
||||
to='authentic2.Service',
|
||||
verbose_name='allowed services for this profile type',
|
||||
),
|
||||
),
|
||||
migrations.RunSQL(
|
||||
sql=[
|
||||
'CREATE EXTENSION IF NOT EXISTS unaccent SCHEMA public',
|
||||
'CREATE EXTENSION IF NOT EXISTS pg_trgm SCHEMA public',
|
||||
'CREATE OR REPLACE FUNCTION public.immutable_unaccent(text) RETURNS varchar AS $$ SELECT'
|
||||
" public.unaccent('public.unaccent',$1::text); $$ LANGUAGE 'sql' IMMUTABLE",
|
||||
'CREATE INDEX custom_user_name_gist_idx ON custom_user_user USING gist'
|
||||
" (LOWER(public.immutable_unaccent(first_name || ' ' || last_name)) public.gist_trgm_ops)",
|
||||
],
|
||||
reverse_sql=[
|
||||
'DROP INDEX IF EXISTS custom_user_name_gist_idx',
|
||||
'DROP FUNCTION IF EXISTS public.immutable_unaccent(text)',
|
||||
'DROP EXTENSION IF EXISTS pg_trgm',
|
||||
'DROP EXTENSION IF EXISTS unaccent',
|
||||
],
|
||||
),
|
||||
]
|
|
@ -19,13 +19,13 @@ from collections import OrderedDict
|
|||
|
||||
from django import forms
|
||||
from django.contrib.auth import forms as auth_forms
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.forms import Form
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from authentic2.backends.ldap_backend import LDAPUser
|
||||
from authentic2.custom_user.models import User
|
||||
from authentic2.journal import journal
|
||||
from authentic2.passwords import validate_password
|
||||
from authentic2.utils.misc import get_password_authenticator
|
||||
|
@ -92,7 +92,7 @@ class PasswordResetForm(HoneypotForm):
|
|||
|
||||
def clean_phone(self):
|
||||
phone = self.cleaned_data.get('phone')
|
||||
user_ct = ContentType.objects.get_for_model(get_user_model())
|
||||
user_ct = ContentType.objects.get_for_model(User)
|
||||
if phone:
|
||||
user_ids = models.AttributeValue.objects.filter(
|
||||
attribute=self.authenticator.phone_identifier_field,
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
import re
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import BaseUserManager
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import RegexValidator
|
||||
|
@ -26,6 +25,7 @@ from django.utils.translation import gettext
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from authentic2.a2_rbac.models import OrganizationalUnit
|
||||
from authentic2.custom_user.models import User
|
||||
from authentic2.forms.fields import CharField, CheckPasswordField, NewPasswordField
|
||||
from authentic2.passwords import validate_password
|
||||
|
||||
|
@ -36,8 +36,6 @@ from .fields import PhoneField, ValidatedEmailField
|
|||
from .honeypot import HoneypotForm
|
||||
from .utils import NextUrlFormMixin
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class RegistrationForm(HoneypotForm):
|
||||
error_css_class = 'form-field-error'
|
||||
|
|
|
@ -31,7 +31,6 @@ import uuid
|
|||
import phonenumbers
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.forms.widgets import ClearableFileInput, DateInput, DateTimeInput
|
||||
from django.forms.widgets import EmailInput as BaseEmailInput
|
||||
from django.forms.widgets import MultiWidget
|
||||
|
@ -377,9 +376,11 @@ class SelectAttributeWidget(forms.Select):
|
|||
|
||||
@staticmethod
|
||||
def get_options():
|
||||
from authentic2.custom_user.models import User
|
||||
|
||||
choices = {}
|
||||
for name in ('email', 'username', 'first_name', 'last_name'):
|
||||
field = get_user_model()._meta.get_field(name)
|
||||
field = User._meta.get_field(name)
|
||||
choices[name] = '%s (%s)' % (capfirst(field.verbose_name), name)
|
||||
for attribute in Attribute.objects.exclude(name__in=choices):
|
||||
choices[attribute.name] = '%s (%s)' % (attribute.label, attribute.name)
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
# authentic2 - versatile identity manager
|
||||
# Copyright (C) 2010-2019 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import render
|
||||
|
||||
|
||||
@login_required
|
||||
def consent_federation(request, nonce='', provider_id=None):
|
||||
"""On a GET produce a form asking for consentment,
|
||||
On a POST handle the form and redirect to next"""
|
||||
if request.method == 'GET':
|
||||
return render(
|
||||
request,
|
||||
'interaction/consent_federation.html',
|
||||
{
|
||||
'provider_id': request.GET.get('provider_id', ''),
|
||||
'nonce': request.GET.get('nonce', ''),
|
||||
'next': request.GET.get('next', ''),
|
||||
},
|
||||
)
|
||||
else:
|
||||
next_url = '/'
|
||||
if 'next' in request.POST:
|
||||
next_url = request.POST['next']
|
||||
if 'accept' in request.POST:
|
||||
next_url = next_url + '&consent_answer=accepted'
|
||||
return HttpResponseRedirect(next_url)
|
||||
else:
|
||||
next_url = next_url + '&consent_answer=refused'
|
||||
return HttpResponseRedirect(next)
|
|
@ -1,122 +0,0 @@
|
|||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('attribute_aggregator', '__first__'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='AttributePolicy',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
|
||||
),
|
||||
('name', models.CharField(unique=True, max_length=100)),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Enabled')),
|
||||
(
|
||||
'ask_consent_attributes',
|
||||
models.BooleanField(
|
||||
default=True, verbose_name='Ask the user consent before forwarding attributes'
|
||||
),
|
||||
),
|
||||
(
|
||||
'allow_attributes_selection',
|
||||
models.BooleanField(
|
||||
default=True, verbose_name='Allow the user to select the forwarding attributes'
|
||||
),
|
||||
),
|
||||
(
|
||||
'forward_attributes_from_push_sources',
|
||||
models.BooleanField(default=False, verbose_name='Forward pushed attributes'),
|
||||
),
|
||||
(
|
||||
'map_attributes_from_push_sources',
|
||||
models.BooleanField(default=False, verbose_name='Map forwarded pushed attributes'),
|
||||
),
|
||||
(
|
||||
'output_name_format',
|
||||
models.CharField(
|
||||
default=('urn:oasis:names:tc:SAML:2.0:attrname-format:uri', 'SAMLv2 URI'),
|
||||
max_length=100,
|
||||
verbose_name='Output name format',
|
||||
choices=[
|
||||
('urn:oasis:names:tc:SAML:2.0:attrname-format:uri', 'SAMLv2 URI'),
|
||||
('urn:oasis:names:tc:SAML:2.0:attrname-format:basic', 'SAMLv2 BASIC'),
|
||||
],
|
||||
),
|
||||
),
|
||||
(
|
||||
'output_namespace',
|
||||
models.CharField(
|
||||
default=('Default', 'Default'),
|
||||
max_length=100,
|
||||
verbose_name='Output namespace',
|
||||
choices=[
|
||||
('Default', 'Default'),
|
||||
(
|
||||
'http://schemas.xmlsoap.org/ws/2005/05/identity/claims',
|
||||
'http://schemas.xmlsoap.org/ws/2005/05/identity/claims',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
(
|
||||
'filter_source_of_filtered_attributes',
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
verbose_name='Filter by source and per attribute the forwarded pushed attributes',
|
||||
),
|
||||
),
|
||||
(
|
||||
'map_attributes_of_filtered_attributes',
|
||||
models.BooleanField(default=False, verbose_name='Map filtered attributes'),
|
||||
),
|
||||
(
|
||||
'send_error_and_no_attrs_if_missing_required_attrs',
|
||||
models.BooleanField(
|
||||
default=False, verbose_name='Send an error when a required attribute is missing'
|
||||
),
|
||||
),
|
||||
(
|
||||
'attribute_filter_for_sso_from_push_sources',
|
||||
models.ForeignKey(
|
||||
related_name='filter attributes of push sources with list',
|
||||
verbose_name='Filter by attribute names the forwarded pushed attributes',
|
||||
blank=True,
|
||||
to='attribute_aggregator.AttributeList',
|
||||
null=True,
|
||||
on_delete=models.CASCADE,
|
||||
),
|
||||
),
|
||||
(
|
||||
'attribute_list_for_sso_from_pull_sources',
|
||||
models.ForeignKey(
|
||||
related_name='attributes from pull sources',
|
||||
verbose_name='Pull attributes list',
|
||||
blank=True,
|
||||
to='attribute_aggregator.AttributeList',
|
||||
null=True,
|
||||
on_delete=models.CASCADE,
|
||||
),
|
||||
),
|
||||
(
|
||||
'source_filter_for_sso_from_push_sources',
|
||||
models.ManyToManyField(
|
||||
related_name='filter attributes of push sources with sources',
|
||||
null=True,
|
||||
verbose_name='Filter by source the forwarded pushed attributes',
|
||||
to='attribute_aggregator.AttributeSource',
|
||||
blank=True,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'attribute policy',
|
||||
'verbose_name_plural': 'attribute policies',
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
]
|
|
@ -1,43 +0,0 @@
|
|||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('idp', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='attributepolicy',
|
||||
name='attribute_filter_for_sso_from_push_sources',
|
||||
field=models.ForeignKey(
|
||||
related_name='+',
|
||||
verbose_name='Filter by attribute names the forwarded pushed attributes',
|
||||
blank=True,
|
||||
to='attribute_aggregator.AttributeList',
|
||||
null=True,
|
||||
on_delete=models.CASCADE,
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='attributepolicy',
|
||||
name='attribute_list_for_sso_from_pull_sources',
|
||||
field=models.ForeignKey(
|
||||
related_name='+',
|
||||
verbose_name='Pull attributes list',
|
||||
blank=True,
|
||||
to='attribute_aggregator.AttributeList',
|
||||
null=True,
|
||||
on_delete=models.CASCADE,
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='attributepolicy',
|
||||
name='source_filter_for_sso_from_push_sources',
|
||||
field=models.ManyToManyField(
|
||||
to='attribute_aggregator.AttributeSource',
|
||||
verbose_name='Filter by source the forwarded pushed attributes',
|
||||
blank=True,
|
||||
),
|
||||
),
|
||||
]
|
|
@ -1,26 +0,0 @@
|
|||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('saml', '0016_auto_20150915_2041'),
|
||||
('idp', '0002_auto_20150526_2239'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='attributepolicy',
|
||||
name='attribute_filter_for_sso_from_push_sources',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='attributepolicy',
|
||||
name='attribute_list_for_sso_from_pull_sources',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='attributepolicy',
|
||||
name='source_filter_for_sso_from_push_sources',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='AttributePolicy',
|
||||
),
|
||||
]
|
|
@ -44,7 +44,7 @@ from urllib.parse import quote, urlencode
|
|||
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth import BACKEND_SESSION_KEY, REDIRECT_FIELD_NAME, get_user_model, load_backend
|
||||
from django.contrib.auth import BACKEND_SESSION_KEY, REDIRECT_FIELD_NAME, load_backend
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseRedirect
|
||||
|
@ -62,6 +62,7 @@ from authentic2 import views as a2_views
|
|||
from authentic2.attributes_ng.engine import get_attributes
|
||||
from authentic2.compat_lasso import lasso
|
||||
from authentic2.constants import NONCE_FIELD_NAME
|
||||
from authentic2.custom_user.models import User
|
||||
from authentic2.idp.saml.common import kill_django_sessions
|
||||
from authentic2.saml import saml2utils
|
||||
from authentic2.saml.common import (
|
||||
|
@ -118,8 +119,6 @@ from authentic2.views import passive_login
|
|||
|
||||
from . import app_settings
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
# authentic2 - versatile identity manager
|
||||
# Copyright (C) 2010-2019 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
from django.urls import re_path
|
||||
|
||||
from authentic2.idp.interactions import consent_federation
|
||||
|
||||
urlpatterns = [
|
||||
re_path(r'^consent_federation', consent_federation, name='a2-consent-federation'),
|
||||
]
|
|
@ -20,7 +20,6 @@ import urllib.parse
|
|||
from datetime import timedelta
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db import transaction
|
||||
from django.db.models import F, Q
|
||||
|
@ -30,14 +29,13 @@ from authentic2 import app_settings
|
|||
from authentic2.a2_rbac.models import OrganizationalUnit
|
||||
from authentic2.backends import get_user_queryset
|
||||
from authentic2.backends.ldap_backend import LDAPBackend
|
||||
from authentic2.custom_user.models import User
|
||||
from authentic2.journal_event_types import UserDeletionForInactivity, UserNotificationInactivity
|
||||
from authentic2.utils import sms as utils_sms
|
||||
from authentic2.utils.misc import get_password_authenticator, send_templated_mail
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = '''Clean unused accounts'''
|
||||
|
|
|
@ -19,10 +19,10 @@ import json
|
|||
import logging
|
||||
|
||||
import ldif
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db.transaction import atomic
|
||||
|
||||
from authentic2.custom_user.models import User
|
||||
from authentic2.hashers import olap_password_to_dj
|
||||
from authentic2.models import Attribute
|
||||
|
||||
|
@ -44,7 +44,6 @@ class DjangoUserLDIFParser(ldif.LDIFParser):
|
|||
ldif.LDIFParser.__init__(self, *args, **kwargs)
|
||||
|
||||
def handle(self, dn, entry):
|
||||
User = get_user_model()
|
||||
if self.object_class not in entry['objectClass']:
|
||||
if self.verbosity >= 2:
|
||||
self.command.stdout.write('Ignoring entry %r' % dn)
|
||||
|
|
|
@ -16,15 +16,13 @@
|
|||
|
||||
import getpass
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.db import DEFAULT_DB_ALIAS
|
||||
|
||||
from authentic2.custom_user.models import User
|
||||
from authentic2.models import PasswordReset
|
||||
from authentic2.utils.misc import generate_password
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Reset a user's password for django.contrib.auth."
|
||||
|
|
|
@ -20,11 +20,12 @@ import logging
|
|||
import re
|
||||
import sys
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.management.base import BaseCommand
|
||||
from ldap.dn import escape_dn_chars
|
||||
from ldif import LDIFWriter
|
||||
|
||||
from authentic2.custom_user.models import User
|
||||
|
||||
COMMAND = 1
|
||||
ATTR = 2
|
||||
|
||||
|
@ -49,7 +50,7 @@ class Command(BaseCommand):
|
|||
if command == 'SEARCH':
|
||||
out = io.BytesIO()
|
||||
ldif_writer = LDIFWriter(out)
|
||||
qs = get_user_model().objects.all()
|
||||
qs = User.objects.all()
|
||||
if attrs['filter'] != '(objectClass=*)':
|
||||
m = re.match(r'\((\w*)=(.*)\)', attrs['filter'])
|
||||
if not m:
|
||||
|
|
|
@ -22,7 +22,6 @@ from collections import defaultdict
|
|||
from io import StringIO
|
||||
|
||||
from django import forms
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import validate_slug
|
||||
|
@ -36,6 +35,7 @@ from authentic2 import app_settings as a2_app_settings
|
|||
from authentic2.a2_rbac.models import OrganizationalUnit, Role
|
||||
from authentic2.a2_rbac.utils import generate_slug, get_default_ou
|
||||
from authentic2.custom_user.backends import DjangoRBACBackend
|
||||
from authentic2.custom_user.models import User
|
||||
from authentic2.forms.fields import (
|
||||
CheckPasswordField,
|
||||
CommaSeparatedCharField,
|
||||
|
@ -57,7 +57,6 @@ from authentic2.validators import EmailValidator
|
|||
|
||||
from . import app_settings, fields, utils
|
||||
|
||||
User = get_user_model()
|
||||
ChooseRolesField = fields.ChooseRolesField
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -184,7 +183,7 @@ class UserEditForm(LimitQuerysetFormMixin, CssClass, BaseUserForm):
|
|||
if a2_app_settings.A2_PHONE_IS_UNIQUE:
|
||||
if (
|
||||
AttributeValue.objects.filter(
|
||||
content_type=ContentType.objects.get_for_model(get_user_model()),
|
||||
content_type=ContentType.objects.get_for_model(User),
|
||||
attribute=authn.phone_identifier_field,
|
||||
)
|
||||
.exclude(object_id=self.instance.id)
|
||||
|
@ -194,7 +193,7 @@ class UserEditForm(LimitQuerysetFormMixin, CssClass, BaseUserForm):
|
|||
elif getattr(self.instance.ou, 'phone_is_unique', False):
|
||||
other_owners = (
|
||||
AttributeValue.objects.filter(
|
||||
content_type=ContentType.objects.get_for_model(get_user_model()),
|
||||
content_type=ContentType.objects.get_for_model(User),
|
||||
attribute=authn.phone_identifier_field,
|
||||
)
|
||||
.exclude(object_id=self.instance.id)
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
# 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/>.
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from authentic2.a2_rbac.models import Role
|
||||
|
@ -24,11 +23,9 @@ from authentic2.backends.ldap_backend import (
|
|||
LDAP_DEACTIVATION_REASON_NOT_PRESENT,
|
||||
LDAP_DEACTIVATION_REASON_OLD_SOURCE,
|
||||
)
|
||||
from authentic2.custom_user.models import DeletedUser
|
||||
from authentic2.custom_user.models import DeletedUser, User
|
||||
from authentic2.journal_event_types import EventTypeWithService, get_attributes_label
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class ManagerUserCreation(EventTypeDefinition):
|
||||
name = 'manager.user.creation'
|
||||
|
|
|
@ -18,7 +18,6 @@ import functools
|
|||
import uuid
|
||||
|
||||
from django import forms
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import EmailValidator
|
||||
|
@ -33,12 +32,10 @@ from authentic2.apps.journal.forms import JournalForm as BaseJournalForm
|
|||
from authentic2.apps.journal.models import EventType, n_2_pairing
|
||||
from authentic2.apps.journal.search_engine import JournalSearchEngine as BaseJournalSearchEngine
|
||||
from authentic2.apps.journal.views import JournalView
|
||||
from authentic2.custom_user.models import DeletedUser
|
||||
from authentic2.custom_user.models import DeletedUser, User
|
||||
|
||||
from . import views
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class JournalSearchEngine(BaseJournalSearchEngine):
|
||||
def search_by_uuid(self, lexem):
|
||||
|
|
|
@ -14,14 +14,12 @@
|
|||
# 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/>.
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from import_export.fields import Field
|
||||
from import_export.resources import ModelResource
|
||||
from import_export.widgets import Widget
|
||||
|
||||
from authentic2.a2_rbac.models import Role
|
||||
|
||||
User = get_user_model()
|
||||
from authentic2.custom_user.models import User
|
||||
|
||||
|
||||
class ListWidget(Widget):
|
||||
|
|
|
@ -18,7 +18,6 @@ import json
|
|||
from functools import reduce
|
||||
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import PermissionDenied, ValidationError
|
||||
from django.core.paginator import EmptyPage, Paginator
|
||||
|
@ -37,6 +36,7 @@ from authentic2 import data_transfer
|
|||
from authentic2.a2_rbac.models import OrganizationalUnit, Permission, Role, RoleParenting
|
||||
from authentic2.a2_rbac.utils import get_default_ou
|
||||
from authentic2.apps.journal.views import JournalViewWithContext
|
||||
from authentic2.custom_user.models import User
|
||||
from authentic2.forms.profile import modelform_factory
|
||||
from authentic2.role_summary import get_roles_summary_cache
|
||||
from authentic2.utils import crypto, hooks
|
||||
|
@ -46,8 +46,6 @@ from . import forms, resources, tables, views
|
|||
from .journal_views import BaseJournalView
|
||||
from .utils import has_show_username, label_from_role, label_from_user
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class RolesMixin:
|
||||
service_roles = True
|
||||
|
@ -609,7 +607,7 @@ class RoleRemoveAdminUserView(
|
|||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
self.user = get_user_model().objects.get(pk=kwargs['user_pk'])
|
||||
self.user = User.objects.get(pk=kwargs['user_pk'])
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import django_tables2 as tables
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db.models import CharField, OuterRef, Subquery
|
||||
from django.db.models.expressions import RawSQL
|
||||
|
@ -28,13 +27,12 @@ from django.utils.translation import gettext_noop
|
|||
from django_tables2.utils import A
|
||||
|
||||
from authentic2.a2_rbac.models import OrganizationalUnit, Role
|
||||
from authentic2.custom_user.models import User
|
||||
from authentic2.middleware import StoreRequestMiddleware
|
||||
from authentic2.models import AttributeValue, Service
|
||||
from authentic2.utils.misc import get_password_authenticator
|
||||
from authentic2_idp_oidc.models import OIDCAuthorization
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
TABLES_MAJOR_VERSION = int(tables.__version__.split('.', maxsplit=1)[0])
|
||||
|
||||
|
||||
|
|
|
@ -20,10 +20,10 @@ import os
|
|||
import uuid
|
||||
|
||||
import tablib
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.files.storage import default_storage
|
||||
|
||||
from authentic2.custom_user.models import User
|
||||
from authentic2.manager.resources import UserResource
|
||||
from authentic2.models import Attribute, AttributeValue
|
||||
from authentic2.utils.misc import batch_queryset
|
||||
|
@ -37,7 +37,7 @@ def get_user_dataset(qs):
|
|||
|
||||
at_mapping = {a.id: a for a in Attribute.objects.all()}
|
||||
avs = (
|
||||
AttributeValue.objects.filter(content_type=ContentType.objects.get_for_model(get_user_model()))
|
||||
AttributeValue.objects.filter(content_type=ContentType.objects.get_for_model(User))
|
||||
.filter(attribute__disabled=False)
|
||||
.values()
|
||||
)
|
||||
|
@ -125,7 +125,7 @@ class UserExport:
|
|||
|
||||
def export_users_to_file(uuid, query):
|
||||
export = UserExport(uuid)
|
||||
qs = get_user_model().objects.all()
|
||||
qs = User.objects.all()
|
||||
qs.set_trigram_similarity_threshold()
|
||||
qs.query = query
|
||||
qs = qs.select_related('ou')
|
||||
|
|
|
@ -20,7 +20,7 @@ import datetime
|
|||
import operator
|
||||
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth import REDIRECT_FIELD_NAME, get_user_model
|
||||
from django.contrib.auth import REDIRECT_FIELD_NAME
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.mail import EmailMultiAlternatives
|
||||
from django.db import models, transaction
|
||||
|
@ -43,6 +43,7 @@ from authentic2.a2_rbac.models import OrganizationalUnit, Role, RoleParenting
|
|||
from authentic2.a2_rbac.utils import get_default_ou
|
||||
from authentic2.apps.journal.views import JournalViewWithContext
|
||||
from authentic2.backends.ldap_backend import LDAPBackend
|
||||
from authentic2.custom_user.models import User
|
||||
from authentic2.models import Attribute, PasswordReset, Setting
|
||||
from authentic2.utils import hooks, spooler, switch_user
|
||||
from authentic2.utils.misc import (
|
||||
|
@ -93,12 +94,10 @@ from .views import (
|
|||
TitleMixin,
|
||||
)
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class UsersView(HideOUColumnMixin, BaseTableView):
|
||||
template_name = 'authentic2/manager/users.html'
|
||||
model = get_user_model()
|
||||
model = User
|
||||
table_class = UserTable
|
||||
permissions = ['custom_user.search_user']
|
||||
search_form_class = UserSearchForm
|
||||
|
@ -175,7 +174,7 @@ users = UsersView.as_view()
|
|||
|
||||
|
||||
class UserAddView(ActionMixin, BaseAddView):
|
||||
model = get_user_model()
|
||||
model = User
|
||||
title = _('Create user')
|
||||
action = _('Create')
|
||||
fields = [
|
||||
|
@ -307,7 +306,7 @@ user_add_choose_ou = UserAddChooseOU.as_view()
|
|||
|
||||
|
||||
class UserDetailView(OtherActionsMixin, BaseDetailView):
|
||||
model = get_user_model()
|
||||
model = User
|
||||
fields = ['username', 'ou', 'first_name', 'last_name', 'email']
|
||||
form_class = UserEditForm
|
||||
template_name = 'authentic2/manager/user_detail.html'
|
||||
|
@ -504,7 +503,7 @@ user_detail = UserDetailView.as_view()
|
|||
|
||||
|
||||
class UserEditView(OtherActionsMixin, ActionMixin, BaseEditView):
|
||||
model = get_user_model()
|
||||
model = User
|
||||
template_name = 'authentic2/manager/user_edit.html'
|
||||
form_class = UserEditForm
|
||||
permissions = ['custom_user.change_user']
|
||||
|
@ -623,7 +622,7 @@ users_export_progress = UsersExportProgressView.as_view()
|
|||
|
||||
class UserChangePasswordView(ActionMixin, BaseEditView):
|
||||
template_name = 'authentic2/manager/form.html'
|
||||
model = get_user_model()
|
||||
model = User
|
||||
form_class = UserChangePasswordForm
|
||||
permissions = ['custom_user.change_password_user']
|
||||
title = _('Change user password')
|
||||
|
@ -651,7 +650,7 @@ user_change_password = UserChangePasswordView.as_view()
|
|||
|
||||
class UserChangeEmailView(BaseEditView):
|
||||
template_name = 'authentic2/manager/user_change_email.html'
|
||||
model = get_user_model()
|
||||
model = User
|
||||
form_class = UserChangeEmailForm
|
||||
permissions = ['custom_user.change_email_user']
|
||||
success_url = '..'
|
||||
|
@ -681,7 +680,7 @@ user_change_email = UserChangeEmailView.as_view()
|
|||
|
||||
|
||||
class UserRolesView(HideOUColumnMixin, BaseSubTableView):
|
||||
model = get_user_model()
|
||||
model = User
|
||||
form_class = ChooseUserRoleForm
|
||||
search_form_class = UserRoleSearchForm
|
||||
success_url = '.'
|
||||
|
@ -778,7 +777,7 @@ roles = UserRolesView.as_view()
|
|||
|
||||
|
||||
class UserDeleteView(BaseDeleteView):
|
||||
model = get_user_model()
|
||||
model = User
|
||||
title = _('Delete user')
|
||||
template_name = 'authentic2/manager/user_delete.html'
|
||||
success_url = reverse_lazy('a2-manager-users')
|
||||
|
@ -1004,7 +1003,7 @@ class UserAuthorizationsView(
|
|||
permissions = ['custom_user.view_user']
|
||||
template_name = 'authentic2/manager/user_authorizations.html'
|
||||
title = pgettext_lazy('manager', 'Consent Management')
|
||||
model = get_user_model()
|
||||
model = User
|
||||
table_class = UserAuthorizationsTable
|
||||
form_class = ChooseUserAuthorizationsForm
|
||||
success_url = '.'
|
||||
|
|
|
@ -19,11 +19,11 @@ import functools
|
|||
import operator
|
||||
import pickle
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.utils.encoding import force_str
|
||||
from django_select2.forms import ModelSelect2MultipleWidget, ModelSelect2Widget
|
||||
|
||||
from authentic2.a2_rbac.models import Role
|
||||
from authentic2.custom_user.models import User
|
||||
from authentic2.utils import crypto
|
||||
from authentic2_idp_oidc.models import OIDCAuthorization
|
||||
|
||||
|
@ -100,7 +100,7 @@ class SimpleModelSelect2MultipleWidget(Select2Mixin, ModelSelect2MultipleWidget)
|
|||
|
||||
|
||||
class SearchUserWidgetMixin(SplitTermMixin):
|
||||
model = get_user_model()
|
||||
model = User
|
||||
search_fields = [
|
||||
'username__icontains',
|
||||
'first_name__icontains',
|
||||
|
|
|
@ -3,7 +3,6 @@ from django.db import migrations, models
|
|||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('auth', '0002_auto_20150323_1720'),
|
||||
('contenttypes', '0001_initial'),
|
||||
]
|
||||
|
||||
|
@ -98,7 +97,10 @@ class Migration(migrations.Migration):
|
|||
models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
|
||||
),
|
||||
('creation', models.DateTimeField(auto_now_add=True, verbose_name='creation date')),
|
||||
('user', models.ForeignKey(verbose_name='user', to='auth.User', on_delete=models.CASCADE)),
|
||||
(
|
||||
'user',
|
||||
models.ForeignKey(verbose_name='user', to='custom_user.User', on_delete=models.CASCADE),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'user to delete',
|
||||
|
@ -183,7 +185,10 @@ class Migration(migrations.Migration):
|
|||
'id',
|
||||
models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
|
||||
),
|
||||
('user', models.ForeignKey(verbose_name='user', to='auth.User', on_delete=models.CASCADE)),
|
||||
(
|
||||
'user',
|
||||
models.ForeignKey(verbose_name='user', to='custom_user.User', on_delete=models.CASCADE),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'password reset',
|
||||
|
@ -202,7 +207,10 @@ class Migration(migrations.Migration):
|
|||
('external_id', models.CharField(max_length=256, verbose_name='external id')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='creation date')),
|
||||
('updated', models.DateTimeField(auto_now=True, verbose_name='last update date')),
|
||||
('user', models.ForeignKey(verbose_name='user', to='auth.User', on_delete=models.CASCADE)),
|
||||
(
|
||||
'user',
|
||||
models.ForeignKey(verbose_name='user', to='custom_user.User', on_delete=models.CASCADE),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'user external id',
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('authentic2', '0002_auto_20150320_1418'),
|
||||
]
|
||||
|
||||
|
@ -12,25 +10,19 @@ class Migration(migrations.Migration):
|
|||
migrations.AlterField(
|
||||
model_name='deleteduser',
|
||||
name='user',
|
||||
field=models.ForeignKey(
|
||||
verbose_name='user', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE
|
||||
),
|
||||
field=models.ForeignKey(verbose_name='user', to='custom_user.User', on_delete=models.CASCADE),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='passwordreset',
|
||||
name='user',
|
||||
field=models.ForeignKey(
|
||||
verbose_name='user', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE
|
||||
),
|
||||
field=models.ForeignKey(verbose_name='user', to='custom_user.User', on_delete=models.CASCADE),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='userexternalid',
|
||||
name='user',
|
||||
field=models.ForeignKey(
|
||||
verbose_name='user', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE
|
||||
),
|
||||
field=models.ForeignKey(verbose_name='user', to='custom_user.User', on_delete=models.CASCADE),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
@ -12,7 +11,7 @@ class Migration(migrations.Migration):
|
|||
model_name='passwordreset',
|
||||
name='user',
|
||||
field=models.ForeignKey(
|
||||
verbose_name='user', to=settings.AUTH_USER_MODEL, unique=True, on_delete=models.CASCADE
|
||||
verbose_name='user', to='custom_user.User', unique=True, on_delete=models.CASCADE
|
||||
),
|
||||
preserve_default=True,
|
||||
),
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
@ -11,8 +10,6 @@ class Migration(migrations.Migration):
|
|||
migrations.AlterField(
|
||||
model_name='passwordreset',
|
||||
name='user',
|
||||
field=models.OneToOneField(
|
||||
verbose_name='user', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE
|
||||
),
|
||||
field=models.OneToOneField(verbose_name='user', to='custom_user.User', on_delete=models.CASCADE),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -4,7 +4,6 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('authentic2', '0015_auto_20160621_1711'),
|
||||
('custom_user', '0011_manual_attribute_values_for_name_fields'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
|
|
|
@ -5,7 +5,6 @@ from django.db import migrations, models
|
|||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('custom_user', '0016_auto_20180925_1107'),
|
||||
('authentic2', '0022_attribute_scopes'),
|
||||
]
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ from django.db import migrations
|
|||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('custom_user', '0016_auto_20180925_1107'),
|
||||
('authentic2', '0023_auto_20181031_0900'),
|
||||
]
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# Generated by Django 1.11.20 on 2019-10-09 08:47
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
@ -17,7 +16,7 @@ class Migration(migrations.Migration):
|
|||
field=models.OneToOneField(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name='deletion',
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
to='custom_user.User',
|
||||
verbose_name='user',
|
||||
),
|
||||
),
|
||||
|
|
|
@ -16,11 +16,6 @@ def fill_deleted(apps, schema_editor):
|
|||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('authentic2', '0026_token'),
|
||||
('custom_user', '0019_add_user_deleted'),
|
||||
]
|
||||
|
||||
run_before = [
|
||||
('custom_user', '0026_remove_user_deleted'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
|
|
|
@ -5,7 +5,6 @@ from django.db import migrations, models
|
|||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('custom_user', '0030_auto_20220304_1136'),
|
||||
('authentic2', '0035_service_home_url'),
|
||||
]
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ import authentic2.a2_rbac.utils
|
|||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('a2_rbac', '0036_delete_roleattribute'),
|
||||
('authentic2', '0045_smscode'),
|
||||
]
|
||||
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
# Generated by Django 2.2.26 on 2023-01-17 14:13
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('authentic2', '0047_initialize_services_runtime_settings'),
|
||||
]
|
||||
|
||||
|
@ -23,7 +21,7 @@ class Migration(migrations.Migration):
|
|||
field=models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
to='custom_user.User',
|
||||
verbose_name='user',
|
||||
),
|
||||
),
|
||||
|
|
|
@ -0,0 +1,393 @@
|
|||
# Generated by Django 3.2.23 on 2023-12-14 21:01
|
||||
|
||||
import uuid
|
||||
|
||||
import django.contrib.postgres.fields
|
||||
import django.contrib.postgres.search
|
||||
import django.db.models.manager
|
||||
from django.db import migrations, models
|
||||
|
||||
import authentic2.utils.sms
|
||||
import authentic2.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
replaces = [
|
||||
('authentic2', '0001_initial'),
|
||||
('authentic2', '0002_auto_20150320_1418'),
|
||||
('authentic2', '0003_auto_20150409_1840'),
|
||||
('authentic2', '0004_service'),
|
||||
('authentic2', '0005_service_ou'),
|
||||
('authentic2', '0006_conditional_slug_index'),
|
||||
('authentic2', '0007_auto_20150523_0028'),
|
||||
('authentic2', '0008_auto_20160204_1415'),
|
||||
('authentic2', '0009_auto_20160211_2247'),
|
||||
('authentic2', '0010_attributevalue_multiple'),
|
||||
('authentic2', '0011_auto_20160211_2253'),
|
||||
('authentic2', '0012_auto_20160211_2255'),
|
||||
('authentic2', '0013_auto_20160211_2258'),
|
||||
('authentic2', '0014_attributevalue_verified'),
|
||||
('authentic2', '0015_auto_20160621_1711'),
|
||||
('authentic2', '0016_attribute_disabled'),
|
||||
('authentic2', '0017_modify_attribute_serialization'),
|
||||
('authentic2', '0018_auto_20170524_0842'),
|
||||
('authentic2', '0019_auto_20170309_1529'),
|
||||
('authentic2', '0020_delete_federatedid'),
|
||||
('authentic2', '0021_attribute_order'),
|
||||
('authentic2', '0022_attribute_scopes'),
|
||||
('authentic2', '0023_auto_20181031_0900'),
|
||||
('authentic2', '0024_auto_20190617_1113'),
|
||||
('authentic2', '0025_auto_20191009_1047'),
|
||||
('authentic2', '0026_token'),
|
||||
('authentic2', '0027_remove_deleteduser'),
|
||||
('authentic2', '0028_trigram_unaccent_index'),
|
||||
('authentic2', '0029_auto_20201013_1614'),
|
||||
('authentic2', '0030_clean_admin_tools_tables'),
|
||||
('authentic2', '0031_add_search_vector_to_attributes'),
|
||||
('authentic2', '0032_initialize_search_vectors'),
|
||||
('authentic2', '0033_recreate_immutable_unaccent'),
|
||||
('authentic2', '0034_attribute_required_on_login'),
|
||||
('authentic2', '0035_service_home_url'),
|
||||
('authentic2', '0036_service_profile_types'),
|
||||
('authentic2', '0037_auto_20220331_1513'),
|
||||
('authentic2', '0038_make_service_ou_non_null'),
|
||||
('authentic2', '0039_add_unique_attribute_constraint'),
|
||||
('authentic2', '0040_add_external_guid'),
|
||||
('authentic2', '0041_lock'),
|
||||
('authentic2', '0042_api_client'),
|
||||
('authentic2', '0043_api_client_description'),
|
||||
('authentic2', '0044_apiclient_ou'),
|
||||
('authentic2', '0044_auto_20220530_1426'),
|
||||
('authentic2', '0045_auto_20221222_1013'),
|
||||
('authentic2', '0045_auto_20230117_1513'),
|
||||
('authentic2', '0045_smscode'),
|
||||
('authentic2', '0046_runtimesetting'),
|
||||
('authentic2', '0047_initialize_services_runtime_settings'),
|
||||
('authentic2', '0048_rename_services_runtime_settings'),
|
||||
('authentic2', '0049_apiclient_allowed_user_attributes'),
|
||||
('authentic2', '0050_initialize_users_advanced_configuration'),
|
||||
]
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='APIClient',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('name', models.CharField(max_length=128, verbose_name='Name')),
|
||||
('description', models.TextField(blank=True, verbose_name='Description')),
|
||||
('identifier', models.CharField(max_length=256, verbose_name='Identifier')),
|
||||
('password', models.CharField(max_length=256, verbose_name='Password')),
|
||||
(
|
||||
'restrict_to_anonymised_data',
|
||||
models.BooleanField(default=False, verbose_name='Restrict to anonymised data'),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'APIClient',
|
||||
'verbose_name_plural': 'APIClient',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Attribute',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('label', models.CharField(max_length=63, unique=True, verbose_name='label')),
|
||||
('description', models.TextField(blank=True, verbose_name='description')),
|
||||
('name', models.SlugField(max_length=256, unique=True, verbose_name='name')),
|
||||
('required', models.BooleanField(blank=True, default=False, verbose_name='required')),
|
||||
(
|
||||
'asked_on_registration',
|
||||
models.BooleanField(blank=True, default=False, verbose_name='asked on registration'),
|
||||
),
|
||||
(
|
||||
'user_editable',
|
||||
models.BooleanField(blank=True, default=False, verbose_name='user editable'),
|
||||
),
|
||||
('user_visible', models.BooleanField(blank=True, default=False, verbose_name='user visible')),
|
||||
('multiple', models.BooleanField(blank=True, default=False, verbose_name='multiple')),
|
||||
('kind', models.CharField(max_length=16, verbose_name='kind')),
|
||||
('disabled', models.BooleanField(blank=True, default=False, verbose_name='disabled')),
|
||||
('searchable', models.BooleanField(blank=True, default=False, verbose_name='searchable')),
|
||||
(
|
||||
'required_on_login',
|
||||
models.BooleanField(blank=True, default=False, verbose_name='required on login'),
|
||||
),
|
||||
(
|
||||
'scopes',
|
||||
models.CharField(
|
||||
blank=True,
|
||||
default='',
|
||||
help_text='scopes separated by spaces',
|
||||
max_length=256,
|
||||
verbose_name='scopes',
|
||||
),
|
||||
),
|
||||
('order', models.PositiveIntegerField(default=0, verbose_name='order')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'attribute definition',
|
||||
'verbose_name_plural': 'attribute definitions',
|
||||
'ordering': ('order', 'id'),
|
||||
'base_manager_name': 'all_objects',
|
||||
},
|
||||
managers=[
|
||||
('all_objects', django.db.models.manager.Manager()),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AttributeValue',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('object_id', models.PositiveIntegerField(db_index=True, verbose_name='object identifier')),
|
||||
('multiple', models.BooleanField(default=False, null=True)),
|
||||
('content', models.TextField(db_index=True, verbose_name='content')),
|
||||
(
|
||||
'search_vector',
|
||||
django.contrib.postgres.search.SearchVectorField(editable=False, null=True),
|
||||
),
|
||||
('verified', models.BooleanField(default=False)),
|
||||
(
|
||||
'verification_sources',
|
||||
django.contrib.postgres.fields.ArrayField(
|
||||
base_field=models.CharField(max_length=63),
|
||||
null=True,
|
||||
size=None,
|
||||
verbose_name='verification sources',
|
||||
),
|
||||
),
|
||||
(
|
||||
'last_verified_on',
|
||||
models.DateTimeField(null=True, verbose_name='last verification timestamp'),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'attribute value',
|
||||
'verbose_name_plural': 'attribute values',
|
||||
'ordering': ('attribute__order', 'id'),
|
||||
},
|
||||
managers=[
|
||||
('all_objects', django.db.models.manager.Manager()),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AuthenticationEvent',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('when', models.DateTimeField(auto_now=True, verbose_name='when')),
|
||||
('who', models.CharField(max_length=80, verbose_name='who')),
|
||||
('how', models.CharField(max_length=32, verbose_name='how')),
|
||||
('nonce', models.CharField(max_length=255, verbose_name='nonce')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'authentication log',
|
||||
'verbose_name_plural': 'authentication logs',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AuthorizedRole',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Lock',
|
||||
fields=[
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Creation date')),
|
||||
('name', models.TextField(primary_key=True, serialize=False, verbose_name='Name')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Lock',
|
||||
'verbose_name_plural': 'Lock',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='LogoutUrl',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
(
|
||||
'logout_url',
|
||||
models.URLField(
|
||||
blank=True,
|
||||
help_text='you can use a {} to pass the URL of the success icon, ex.: http://example.com/logout?next={}',
|
||||
max_length=255,
|
||||
null=True,
|
||||
verbose_name='url',
|
||||
),
|
||||
),
|
||||
(
|
||||
'logout_use_iframe',
|
||||
models.BooleanField(
|
||||
default=False, verbose_name='use an iframe instead of an img tag for logout'
|
||||
),
|
||||
),
|
||||
(
|
||||
'logout_use_iframe_timeout',
|
||||
models.PositiveIntegerField(
|
||||
default=300,
|
||||
help_text="if iframe logout is used, it's the time between the onload event for this iframe and the moment we "
|
||||
'consider its loading to be really finished',
|
||||
verbose_name='iframe logout timeout (ms)',
|
||||
),
|
||||
),
|
||||
('object_id', models.PositiveIntegerField(verbose_name='object identifier')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'logout URL',
|
||||
'verbose_name_plural': 'logout URL',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='PasswordReset',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'password reset',
|
||||
'verbose_name_plural': 'password reset',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Service',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('name', models.CharField(max_length=128, verbose_name='name')),
|
||||
('slug', models.SlugField(max_length=128, verbose_name='slug')),
|
||||
(
|
||||
'unauthorized_url',
|
||||
models.URLField(
|
||||
blank=True, max_length=256, null=True, verbose_name='callback url when unauthorized'
|
||||
),
|
||||
),
|
||||
('home_url', models.URLField(blank=True, max_length=256, null=True, verbose_name='Home URL')),
|
||||
('logo', models.ImageField(blank=True, upload_to='services/logos', verbose_name='Logo')),
|
||||
(
|
||||
'colour',
|
||||
models.CharField(
|
||||
blank=True,
|
||||
max_length=32,
|
||||
null=True,
|
||||
validators=[authentic2.validators.HexaColourValidator()],
|
||||
verbose_name='Colour',
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'base service model',
|
||||
'verbose_name_plural': 'base service models',
|
||||
'base_manager_name': 'objects',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Setting',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('key', models.CharField(max_length=128, unique=True, verbose_name='key')),
|
||||
('value', models.JSONField(blank=True, verbose_name='value')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SMSCode',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
(
|
||||
'value',
|
||||
models.CharField(
|
||||
default=authentic2.utils.sms.create_sms_code,
|
||||
editable=False,
|
||||
max_length=32,
|
||||
verbose_name='Identifier',
|
||||
),
|
||||
),
|
||||
('kind', models.CharField(max_length=32, verbose_name='Kind')),
|
||||
(
|
||||
'phone',
|
||||
models.CharField(
|
||||
blank=True,
|
||||
max_length=64,
|
||||
null=True,
|
||||
validators=[authentic2.validators.PhoneNumberValidator],
|
||||
verbose_name='phone number',
|
||||
),
|
||||
),
|
||||
('url_token', models.UUIDField(default=uuid.uuid4, verbose_name='URL token')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Creation date')),
|
||||
('expires', models.DateTimeField(verbose_name='Expires')),
|
||||
('sent', models.BooleanField(default=False, verbose_name='SMS code sent')),
|
||||
('fake', models.BooleanField(default=False, verbose_name='Is a fake code')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Token',
|
||||
fields=[
|
||||
(
|
||||
'uuid',
|
||||
models.UUIDField(
|
||||
default=uuid.uuid4,
|
||||
editable=False,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name='Identifier',
|
||||
),
|
||||
),
|
||||
('kind', models.CharField(max_length=32, verbose_name='Kind')),
|
||||
('content', models.JSONField(blank=True, verbose_name='Content')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Creation date')),
|
||||
('expires', models.DateTimeField(verbose_name='Expires')),
|
||||
],
|
||||
options={
|
||||
'ordering': ('-expires', 'kind', 'uuid'),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='UserExternalId',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('source', models.CharField(max_length=256, verbose_name='source')),
|
||||
('external_id', models.CharField(max_length=256, null=True, verbose_name='external id')),
|
||||
('external_guid', models.UUIDField(null=True, verbose_name='External GUID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='creation date')),
|
||||
('updated', models.DateTimeField(auto_now=True, verbose_name='last update date')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'user external id',
|
||||
'verbose_name_plural': 'user external ids',
|
||||
},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,292 @@
|
|||
# Generated by Django 3.2.23 on 2023-12-14 21:01
|
||||
|
||||
import django.contrib.postgres.indexes
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
import authentic2.a2_rbac.utils
|
||||
|
||||
|
||||
def create_trigger(apps, schema_editor):
|
||||
with schema_editor.connection.cursor() as cursor:
|
||||
cursor.execute('SHOW default_text_search_config')
|
||||
assert cursor.fetchone()
|
||||
cursor.execute(
|
||||
'''CREATE OR REPLACE FUNCTION authentic2_update_atv_search_vector() RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
IF TG_OP = 'INSERT' OR (TG_OP = 'UPDATE' AND NEW.content <> OLD.content) THEN
|
||||
NEW.search_vector = to_tsvector(NEW.content);
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END; $$ LANGUAGE plpgsql'''
|
||||
)
|
||||
cursor.execute(
|
||||
'''CREATE TRIGGER authentic2_attributevalue_search_vector_trigger
|
||||
BEFORE INSERT OR UPDATE OF content
|
||||
ON authentic2_attributevalue
|
||||
FOR EACH ROW EXECUTE PROCEDURE authentic2_update_atv_search_vector()'''
|
||||
)
|
||||
|
||||
|
||||
def drop_trigger(apps, schema_editor):
|
||||
with schema_editor.connection.cursor() as cursor:
|
||||
cursor.execute(
|
||||
'DROP TRIGGER IF EXISTS authentic2_attributevalue_search_vector_trigger ON'
|
||||
' authentic2_attributevalue'
|
||||
)
|
||||
cursor.execute('DROP FUNCTION IF EXISTS authentic2_update_atv_search_vector')
|
||||
|
||||
|
||||
def initialize_services_runtime_settings(apps, schema_editor):
|
||||
from authentic2.utils.misc import RUNTIME_SETTINGS
|
||||
|
||||
Setting = apps.get_model('authentic2', 'Setting')
|
||||
for key, data in RUNTIME_SETTINGS.items():
|
||||
Setting.objects.get_or_create(
|
||||
key=key,
|
||||
defaults={
|
||||
'value': data['value'],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
replaces = [
|
||||
('authentic2', '0001_initial'),
|
||||
('authentic2', '0002_auto_20150320_1418'),
|
||||
('authentic2', '0003_auto_20150409_1840'),
|
||||
('authentic2', '0004_service'),
|
||||
('authentic2', '0005_service_ou'),
|
||||
('authentic2', '0006_conditional_slug_index'),
|
||||
('authentic2', '0007_auto_20150523_0028'),
|
||||
('authentic2', '0008_auto_20160204_1415'),
|
||||
('authentic2', '0009_auto_20160211_2247'),
|
||||
('authentic2', '0010_attributevalue_multiple'),
|
||||
('authentic2', '0011_auto_20160211_2253'),
|
||||
('authentic2', '0012_auto_20160211_2255'),
|
||||
('authentic2', '0013_auto_20160211_2258'),
|
||||
('authentic2', '0014_attributevalue_verified'),
|
||||
('authentic2', '0015_auto_20160621_1711'),
|
||||
('authentic2', '0016_attribute_disabled'),
|
||||
('authentic2', '0017_modify_attribute_serialization'),
|
||||
('authentic2', '0018_auto_20170524_0842'),
|
||||
('authentic2', '0019_auto_20170309_1529'),
|
||||
('authentic2', '0020_delete_federatedid'),
|
||||
('authentic2', '0021_attribute_order'),
|
||||
('authentic2', '0022_attribute_scopes'),
|
||||
('authentic2', '0023_auto_20181031_0900'),
|
||||
('authentic2', '0024_auto_20190617_1113'),
|
||||
('authentic2', '0025_auto_20191009_1047'),
|
||||
('authentic2', '0026_token'),
|
||||
('authentic2', '0027_remove_deleteduser'),
|
||||
('authentic2', '0028_trigram_unaccent_index'),
|
||||
('authentic2', '0029_auto_20201013_1614'),
|
||||
('authentic2', '0030_clean_admin_tools_tables'),
|
||||
('authentic2', '0031_add_search_vector_to_attributes'),
|
||||
('authentic2', '0032_initialize_search_vectors'),
|
||||
('authentic2', '0033_recreate_immutable_unaccent'),
|
||||
('authentic2', '0034_attribute_required_on_login'),
|
||||
('authentic2', '0035_service_home_url'),
|
||||
('authentic2', '0036_service_profile_types'),
|
||||
('authentic2', '0037_auto_20220331_1513'),
|
||||
('authentic2', '0038_make_service_ou_non_null'),
|
||||
('authentic2', '0039_add_unique_attribute_constraint'),
|
||||
('authentic2', '0040_add_external_guid'),
|
||||
('authentic2', '0041_lock'),
|
||||
('authentic2', '0042_api_client'),
|
||||
('authentic2', '0043_api_client_description'),
|
||||
('authentic2', '0044_apiclient_ou'),
|
||||
('authentic2', '0044_auto_20220530_1426'),
|
||||
('authentic2', '0045_auto_20221222_1013'),
|
||||
('authentic2', '0045_auto_20230117_1513'),
|
||||
('authentic2', '0045_smscode'),
|
||||
('authentic2', '0046_runtimesetting'),
|
||||
('authentic2', '0047_initialize_services_runtime_settings'),
|
||||
('authentic2', '0048_rename_services_runtime_settings'),
|
||||
('authentic2', '0049_apiclient_allowed_user_attributes'),
|
||||
('authentic2', '0050_initialize_users_advanced_configuration'),
|
||||
]
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('a2_rbac', '0041_replace'),
|
||||
('custom_user', '0037_replace'),
|
||||
('contenttypes', '0002_remove_content_type_name'),
|
||||
('authentic2', '0051_replace'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='LDAPUser',
|
||||
fields=[],
|
||||
options={
|
||||
'proxy': True,
|
||||
'indexes': [],
|
||||
'constraints': [],
|
||||
},
|
||||
bases=('custom_user.user',),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='userexternalid',
|
||||
name='user',
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, to='custom_user.user', verbose_name='user'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='smscode',
|
||||
name='user',
|
||||
field=models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to='custom_user.user',
|
||||
verbose_name='user',
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='service',
|
||||
name='authorized_roles',
|
||||
field=models.ManyToManyField(
|
||||
blank=True,
|
||||
related_name='allowed_services',
|
||||
through='authentic2.AuthorizedRole',
|
||||
to='a2_rbac.Role',
|
||||
verbose_name='authorized services',
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='service',
|
||||
name='ou',
|
||||
field=models.ForeignKey(
|
||||
default=authentic2.a2_rbac.utils.get_default_ou_pk,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to='a2_rbac.organizationalunit',
|
||||
verbose_name='organizational unit',
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='service',
|
||||
name='profile_types',
|
||||
field=models.ManyToManyField(
|
||||
blank=True,
|
||||
related_name='_authentic2_service_profile_types_+',
|
||||
through='custom_user.ServiceProfileType',
|
||||
to='custom_user.ProfileType',
|
||||
verbose_name='allowed services for this profile type',
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='passwordreset',
|
||||
name='user',
|
||||
field=models.OneToOneField(
|
||||
on_delete=django.db.models.deletion.CASCADE, to='custom_user.user', verbose_name='user'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='logouturl',
|
||||
name='content_type',
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to='contenttypes.contenttype',
|
||||
verbose_name='content type',
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='authorizedrole',
|
||||
name='role',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='a2_rbac.role'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='authorizedrole',
|
||||
name='service',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='authentic2.service'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='attributevalue',
|
||||
name='attribute',
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to='authentic2.attribute',
|
||||
verbose_name='attribute',
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='attributevalue',
|
||||
name='content_type',
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to='contenttypes.contenttype',
|
||||
verbose_name='content type',
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='apiclient',
|
||||
name='allowed_user_attributes',
|
||||
field=models.ManyToManyField(
|
||||
blank=True,
|
||||
related_name='apiclients',
|
||||
to='authentic2.Attribute',
|
||||
verbose_name='allowed user attributes',
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='apiclient',
|
||||
name='apiclient_roles',
|
||||
field=models.ManyToManyField(
|
||||
blank=True, related_name='apiclients', to='a2_rbac.Role', verbose_name='roles'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='apiclient',
|
||||
name='ou',
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
default=authentic2.a2_rbac.utils.get_default_ou_pk,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to='a2_rbac.organizationalunit',
|
||||
verbose_name='organizational unit',
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='userexternalid',
|
||||
constraint=models.CheckConstraint(
|
||||
check=models.Q(
|
||||
('external_id__isnull', False), ('external_guid__isnull', False), _connector='OR'
|
||||
),
|
||||
name='at_least_one_id',
|
||||
),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='userexternalid',
|
||||
unique_together={('source', 'external_id'), ('source', 'external_guid')},
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='service',
|
||||
unique_together={('slug', 'ou')},
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='attributevalue',
|
||||
index=django.contrib.postgres.indexes.GinIndex(
|
||||
fields=['search_vector'], name='authentic2_atv_tsvector_idx'
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='attributevalue',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(('multiple', False)),
|
||||
fields=('content_type', 'object_id', 'attribute'),
|
||||
name='unique_attribute_idx',
|
||||
),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='attributevalue',
|
||||
unique_together={('content_type', 'object_id', 'attribute', 'multiple', 'content')},
|
||||
),
|
||||
migrations.RunPython(create_trigger, drop_trigger),
|
||||
migrations.RunPython(
|
||||
initialize_services_runtime_settings,
|
||||
reverse_code=migrations.RunPython.noop,
|
||||
),
|
||||
]
|
|
@ -53,7 +53,7 @@ from .utils.sms import create_sms_code
|
|||
|
||||
|
||||
class UserExternalId(models.Model):
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_('user'), on_delete=models.CASCADE)
|
||||
user = models.ForeignKey('custom_user.User', verbose_name=_('user'), on_delete=models.CASCADE)
|
||||
source = models.CharField(max_length=256, verbose_name=_('source'))
|
||||
external_id = models.CharField(max_length=256, verbose_name=_('external id'), null=True)
|
||||
external_guid = models.UUIDField(verbose_name=_('External GUID'), null=True)
|
||||
|
@ -435,7 +435,7 @@ class AttributeValue(models.Model):
|
|||
|
||||
|
||||
class PasswordReset(models.Model):
|
||||
user = models.OneToOneField(settings.AUTH_USER_MODEL, verbose_name=_('user'), on_delete=models.CASCADE)
|
||||
user = models.OneToOneField('custom_user.User', verbose_name=_('user'), on_delete=models.CASCADE)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.user_id and not self.user.has_usable_password():
|
||||
|
@ -836,9 +836,7 @@ class SMSCode(models.Model):
|
|||
phone = models.CharField(
|
||||
_('phone number'), null=True, blank=True, max_length=64, validators=[PhoneNumberValidator]
|
||||
)
|
||||
user = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL, verbose_name=_('user'), on_delete=models.CASCADE, null=True
|
||||
)
|
||||
user = models.ForeignKey('custom_user.User', verbose_name=_('user'), on_delete=models.CASCADE, null=True)
|
||||
url_token = models.UUIDField(
|
||||
verbose_name=_('URL token'),
|
||||
default=uuid.uuid4,
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
Nonce are value which should be used only once for a certain period or
|
||||
eventually forever. The nonce application allows any Django application to
|
||||
implement this behaviour, by taking care of the storage implementation to keep around invalidated nonce.
|
||||
|
||||
For nonce which should not be kept forever the application also provide a
|
||||
cleanup_nonce() function to delete the no longer invalid nonces.
|
|
@ -1,19 +0,0 @@
|
|||
# authentic2 - versatile identity manager
|
||||
# Copyright (C) 2010-2019 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
from authentic2.nonce.utils import accept_nonce, cleanup_nonces
|
||||
|
||||
__all__ = ('accept_nonce', 'cleanup_nonces')
|
|
@ -0,0 +1,13 @@
|
|||
# Generated by Django 3.2.18 on 2023-12-13 20:00
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
replaces = [('nonce', '0001_initial'), ('nonce', '0002_delete_nonce')]
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = []
|
||||
|
||||
operations = []
|
|
@ -0,0 +1,15 @@
|
|||
# Generated by Django 3.2.18 on 2023-12-13 19:03
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('nonce', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.DeleteModel(
|
||||
name='Nonce',
|
||||
),
|
||||
]
|
|
@ -1,39 +0,0 @@
|
|||
# authentic2 - versatile identity manager
|
||||
# Copyright (C) 2010-2019 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
|
||||
__all__ = ('Nonce',)
|
||||
|
||||
_NONCE_LENGTH_CONSTANT = 256
|
||||
|
||||
|
||||
class NonceManager(models.Manager):
|
||||
def cleanup(self, now=None):
|
||||
now = now or timezone.now()
|
||||
self.filter(not_on_or_after__lt=now).delete()
|
||||
|
||||
|
||||
class Nonce(models.Model):
|
||||
value = models.CharField(max_length=_NONCE_LENGTH_CONSTANT)
|
||||
context = models.CharField(max_length=_NONCE_LENGTH_CONSTANT, blank=True, null=True)
|
||||
not_on_or_after = models.DateTimeField(blank=True, null=True)
|
||||
|
||||
objects = NonceManager()
|
||||
|
||||
def __str__(self):
|
||||
return str(self.value)
|
|
@ -1,200 +0,0 @@
|
|||
# authentic2 - versatile identity manager
|
||||
# Copyright (C) 2010-2019 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
import datetime as dt
|
||||
import errno
|
||||
import glob
|
||||
import os.path
|
||||
import tempfile
|
||||
from calendar import timegm
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
__all__ = ('accept_nonce', 'cleanup_nonces')
|
||||
|
||||
STORAGE_MODEL = 'model'
|
||||
STORAGE_FILESYSTEM = 'fs:'
|
||||
|
||||
|
||||
def compute_not_on_or_after(now, not_on_or_after):
|
||||
try: # first try integer semantic
|
||||
seconds = int(not_on_or_after)
|
||||
not_on_or_after = now + dt.timedelta(seconds=seconds)
|
||||
except ValueError:
|
||||
try: # try timedelta semantic
|
||||
not_on_or_after = now + not_on_or_after
|
||||
except TypeError: # datetime semantic
|
||||
pass
|
||||
return not_on_or_after
|
||||
|
||||
|
||||
# For the nonce filesystem storage the policy is to catch any OSerror when
|
||||
# errno == ENOENT and to handle this case gracefully as there can be many race
|
||||
# condition errors. But any other OSError is problematic and should be
|
||||
# reported to the administrator by mail and so we let it unroll the stack
|
||||
|
||||
|
||||
def unlink_if_exists(path):
|
||||
try:
|
||||
os.unlink(path)
|
||||
except OSError as e:
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
|
||||
|
||||
def accept_nonce_file_storage(path, now, value, context=None, not_on_or_after=None):
|
||||
"""
|
||||
Use a directory as a storage for nonce-context values. The last
|
||||
modification time is used to store the expiration timestamp.
|
||||
"""
|
||||
now = dt.datetime.now()
|
||||
filename = '%s_%s' % (value.encode('base64'), context.encode('base64'))
|
||||
file_path = os.path.join(path, filename)
|
||||
# test if the file exists
|
||||
try:
|
||||
stat = os.stat(file_path)
|
||||
except OSError as e:
|
||||
# test if it doesnt exit or if another error happened
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
else:
|
||||
# if it exists, test if it is too old
|
||||
if stat.st_mtime < timegm(now.utctimetuple()):
|
||||
# if it is too old delete it
|
||||
unlink_if_exists(file_path)
|
||||
else:
|
||||
# not too old, the nonce is unacceptable
|
||||
return False
|
||||
|
||||
# pylint: disable=consider-using-with
|
||||
temp_file = tempfile.NamedTemporaryFile(dir=path, delete=False)
|
||||
temp_file.close()
|
||||
|
||||
if not_on_or_after:
|
||||
not_on_or_after = compute_not_on_or_after(now, not_on_or_after)
|
||||
mtime = timegm(not_on_or_after.utctimetuple())
|
||||
else:
|
||||
mtime = 0x7FFF
|
||||
try:
|
||||
os.utime(temp_file.name, (mtime, mtime))
|
||||
except OSError:
|
||||
unlink_if_exists(temp_file.name)
|
||||
raise
|
||||
try:
|
||||
os.link(temp_file.name, file_path)
|
||||
except OSError as e:
|
||||
if e.errno == errno.EEXIST:
|
||||
unlink_if_exists(temp_file.name)
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def accept_nonce_model(now, value, context=None, not_on_or_after=None):
|
||||
from authentic2.nonce.models import Nonce
|
||||
|
||||
if not_on_or_after:
|
||||
not_on_or_after = compute_not_on_or_after(now, not_on_or_after)
|
||||
nonce, created = Nonce.objects.get_or_create(value=value, context=context)
|
||||
if created or (nonce.not_on_or_after and nonce.not_on_or_after < now):
|
||||
nonce.not_on_or_after = not_on_or_after
|
||||
nonce.save()
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def cleanup_nonces_file_storage(dir_path, now):
|
||||
for nonce_path in glob.iglob(os.path.join(dir_path, '*')):
|
||||
now_time = timegm(now.utctimetuple())
|
||||
try:
|
||||
stat = os.stat(nonce_path)
|
||||
except OSError as e:
|
||||
if e.errno == errno.ENOENT:
|
||||
continue
|
||||
raise
|
||||
if stat.st_mtime < now_time:
|
||||
try:
|
||||
os.unlink(nonce_path)
|
||||
except OSError as e:
|
||||
if e.errno == errno.ENOENT:
|
||||
continue
|
||||
raise
|
||||
|
||||
|
||||
def cleanup_nonces(now=None):
|
||||
"""
|
||||
Cleanup stored nonce whose timestamp has expired, i.e.
|
||||
nonce.not_on_or_after < now.
|
||||
|
||||
:param now:
|
||||
a datetime value to define what is the current time, if None is
|
||||
given, datetime.now() is used. It can be used for unit testing.
|
||||
"""
|
||||
from authentic2.nonce.models import Nonce
|
||||
|
||||
now = now or dt.datetime.now()
|
||||
mode = getattr(settings, 'NONCE_STORAGE', STORAGE_MODEL)
|
||||
# the model always exists, so we always clean it
|
||||
Nonce.objects.cleanup(now)
|
||||
if mode == STORAGE_MODEL:
|
||||
pass
|
||||
if mode.startswith(STORAGE_FILESYSTEM):
|
||||
dir_path = mode[len(STORAGE_FILESYSTEM) :]
|
||||
return cleanup_nonces_file_storage(dir_path, now)
|
||||
else:
|
||||
raise ValueError('Invalid NONCE_STORAGE setting: %r' % mode)
|
||||
|
||||
|
||||
def accept_nonce(value, context=None, not_on_or_after=None, now=None):
|
||||
"""
|
||||
Verify that the given nonce value has not already been seen in the
|
||||
context. If not, remember it for ever or until not_on_or_after if is
|
||||
not None.
|
||||
|
||||
Depending on the backend storage used there can be limitation on the
|
||||
acceptable length for the value and the context. For example the model
|
||||
storage backend limits the length of those strings to 256 bytes.
|
||||
|
||||
:param value:
|
||||
a string representing a nonce value.
|
||||
:param context:
|
||||
a string giving context to the nonce value
|
||||
:param not_on_or_after:
|
||||
an integer, a datetime.timedelta or datetime.datetime value. If not
|
||||
none it is used to compute the expiration time for remembering this
|
||||
nonce value. If an integer is given it is interpreted as relative
|
||||
number of seconds since now, if a timedelta object is given it is
|
||||
used as an offset from now, and if a datetime is given it is used
|
||||
as an absolute value for the expiration time.
|
||||
:param now:
|
||||
a datetime value to define what is the current time, if None is
|
||||
given, datetime.now() is used. It can be used for unit testing.
|
||||
:returns:
|
||||
a boolean, if True the nonce has never been seen before, or it
|
||||
expired since the last time seen, otherwise the nonce has already
|
||||
been seen and is invalid.
|
||||
"""
|
||||
now = now or dt.datetime.now()
|
||||
mode = getattr(settings, 'NONCE_STORAGE', STORAGE_MODEL)
|
||||
if mode == STORAGE_MODEL:
|
||||
return accept_nonce_model(now, value, context=context, not_on_or_after=not_on_or_after)
|
||||
elif mode.startswith(STORAGE_FILESYSTEM):
|
||||
dir_path = mode[len(STORAGE_FILESYSTEM) :]
|
||||
return accept_nonce_file_storage(
|
||||
dir_path, now, value, context=context, not_on_or_after=not_on_or_after
|
||||
)
|
||||
else:
|
||||
raise ValueError('Invalid NONCE_STORAGE setting: %r' % mode)
|
|
@ -7,8 +7,6 @@ import authentic2.saml.models
|
|||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('auth', '__first__'),
|
||||
('idp', '__first__'),
|
||||
('contenttypes', '0001_initial'),
|
||||
]
|
||||
|
||||
|
@ -474,17 +472,6 @@ class Migration(migrations.Migration):
|
|||
'users_can_manage_federations',
|
||||
models.BooleanField(default=True, verbose_name='users can manage federation'),
|
||||
),
|
||||
(
|
||||
'attribute_policy',
|
||||
models.ForeignKey(
|
||||
related_name='attribute_policy',
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
verbose_name='attribute policy',
|
||||
blank=True,
|
||||
to='idp.AttributePolicy',
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'SAML service provider',
|
||||
|
@ -757,7 +744,7 @@ class Migration(migrations.Migration):
|
|||
model_name='libertyfederation',
|
||||
name='user',
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.SET_NULL, blank=True, to='auth.User', null=True
|
||||
on_delete=django.db.models.deletion.SET_NULL, blank=True, to='custom_user.User', null=True
|
||||
),
|
||||
preserve_default=True,
|
||||
),
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('saml', '0003_merge'),
|
||||
]
|
||||
|
||||
|
@ -16,7 +14,7 @@ class Migration(migrations.Migration):
|
|||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
blank=True,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
to='custom_user.User',
|
||||
null=True,
|
||||
),
|
||||
preserve_default=True,
|
||||
|
|
|
@ -3,7 +3,6 @@ from django.db import migrations, models
|
|||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('authentic2', '0004_service'),
|
||||
('saml', '0004_auto_20150410_1438'),
|
||||
]
|
||||
|
||||
|
|
|
@ -56,10 +56,6 @@ class Migration(migrations.Migration):
|
|||
migrations.DeleteModel(
|
||||
name='LibertyIdentityProvider',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='libertyserviceprovider',
|
||||
name='attribute_policy',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='libertyserviceprovider',
|
||||
name='enable_following_attribute_policy',
|
||||
|
|
|
@ -0,0 +1,417 @@
|
|||
# Generated by Django 3.2.23 on 2023-12-14 21:01
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
import authentic2.saml.fields
|
||||
import authentic2.saml.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
replaces = [
|
||||
('saml', '0001_initial'),
|
||||
('saml', '0002_auto_20150320_1245'),
|
||||
('saml', '0002_ease_federation_migration'),
|
||||
('saml', '0003_merge'),
|
||||
('saml', '0004_auto_20150410_1438'),
|
||||
('saml', '0005_make_liberty_provider_inherit_from_service'),
|
||||
('saml', '0006_restore_foreign_keys'),
|
||||
('saml', '0007_copy_service_ptr_id_to_old_id'),
|
||||
('saml', '0008_alter_foreign_keys'),
|
||||
('saml', '0009_auto'),
|
||||
('saml', '0010_auto'),
|
||||
('saml', '0011_auto'),
|
||||
('saml', '0012_auto_20150526_2239'),
|
||||
('saml', '0013_auto_20150617_1004'),
|
||||
('saml', '0014_auto_20150617_1216'),
|
||||
('saml', '0015_auto_20150915_2032'),
|
||||
('saml', '0016_auto_20150915_2041'),
|
||||
('saml', '0017_auto_20170710_1738'),
|
||||
('saml', '0018_truncate_saml_keyvalue'),
|
||||
('saml', '0019_auto_20200621_1558'),
|
||||
('saml', '0020_libertysession_saml_libert_provide_39bb6c_idx'),
|
||||
]
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('authentic2', '0052_replace'),
|
||||
('custom_user', '0037_replace'),
|
||||
('contenttypes', '0002_remove_content_type_name'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='KeyValue',
|
||||
fields=[
|
||||
('key', models.CharField(max_length=128, primary_key=True, serialize=False)),
|
||||
('value', authentic2.saml.fields.PickledObjectField()),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'key value association',
|
||||
'verbose_name_plural': 'key value associations',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='LibertyArtifact',
|
||||
fields=[
|
||||
('creation', models.DateTimeField(auto_now_add=True)),
|
||||
('artifact', models.CharField(max_length=128, primary_key=True, serialize=False)),
|
||||
('content', models.TextField()),
|
||||
('provider_id', models.CharField(max_length=256)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'SAML artifact',
|
||||
'verbose_name_plural': 'SAML artifacts',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='LibertyFederation',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
(
|
||||
'name_id_format',
|
||||
models.CharField(blank=True, max_length=100, null=True, verbose_name='NameIDFormat'),
|
||||
),
|
||||
('name_id_content', models.CharField(max_length=100, verbose_name='NameID')),
|
||||
(
|
||||
'name_id_qualifier',
|
||||
models.CharField(blank=True, max_length=256, null=True, verbose_name='NameQualifier'),
|
||||
),
|
||||
(
|
||||
'name_id_sp_name_qualifier',
|
||||
models.CharField(blank=True, max_length=256, null=True, verbose_name='SPNameQualifier'),
|
||||
),
|
||||
('termination_notified', models.BooleanField(blank=True, default=False)),
|
||||
('creation', models.DateTimeField(auto_now_add=True)),
|
||||
('last_modification', models.DateTimeField(auto_now=True)),
|
||||
(
|
||||
'user',
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
to='custom_user.user',
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'SAML federation',
|
||||
'verbose_name_plural': 'SAML federations',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='LibertyProvider',
|
||||
fields=[
|
||||
(
|
||||
'service_ptr',
|
||||
models.OneToOneField(
|
||||
auto_created=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
parent_link=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to='authentic2.service',
|
||||
),
|
||||
),
|
||||
('entity_id', models.URLField(max_length=256, unique=True, verbose_name='Entity ID')),
|
||||
(
|
||||
'entity_id_sha1',
|
||||
models.CharField(blank=True, max_length=40, verbose_name='Entity ID SHA1'),
|
||||
),
|
||||
('metadata_url', models.URLField(blank=True, max_length=256, verbose_name='Metadata URL')),
|
||||
(
|
||||
'protocol_conformance',
|
||||
models.IntegerField(choices=[(3, 'SAML 2.0')], verbose_name='Protocol conformance'),
|
||||
),
|
||||
('metadata', models.TextField(validators=[authentic2.saml.models.metadata_validator])),
|
||||
(
|
||||
'federation_source',
|
||||
models.CharField(blank=True, max_length=64, null=True, verbose_name='Federation source'),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'SAML provider',
|
||||
'verbose_name_plural': 'SAML providers',
|
||||
'ordering': ('service_ptr__name',),
|
||||
},
|
||||
bases=('authentic2.service',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SPOptionsIdPPolicy',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('name', models.CharField(max_length=80, unique=True, verbose_name='name')),
|
||||
('enabled', models.BooleanField(db_index=True, default=False, verbose_name='Enabled')),
|
||||
(
|
||||
'prefered_assertion_consumer_binding',
|
||||
models.CharField(
|
||||
choices=[
|
||||
('meta', 'Use the default from the metadata file'),
|
||||
('art', 'Artifact binding'),
|
||||
('post', 'POST binding'),
|
||||
],
|
||||
default='meta',
|
||||
max_length=4,
|
||||
verbose_name='Prefered assertion consumer binding',
|
||||
),
|
||||
),
|
||||
('encrypt_nameid', models.BooleanField(default=False, verbose_name='Encrypt NameID')),
|
||||
('encrypt_assertion', models.BooleanField(default=False, verbose_name='Encrypt Assertion')),
|
||||
(
|
||||
'authn_request_signed',
|
||||
models.BooleanField(default=False, verbose_name='Authentication request signed'),
|
||||
),
|
||||
(
|
||||
'idp_initiated_sso',
|
||||
models.BooleanField(db_index=True, default=False, verbose_name='Allow IdP initiated SSO'),
|
||||
),
|
||||
(
|
||||
'default_name_id_format',
|
||||
models.CharField(
|
||||
choices=[
|
||||
('none', 'None'),
|
||||
('persistent', 'Persistent'),
|
||||
('transient', 'Transient'),
|
||||
('email', 'Email'),
|
||||
('username', 'Username (use with Google Apps)'),
|
||||
('uuid', 'UUID'),
|
||||
('edupersontargetedid', 'Use eduPersonTargetedID attribute'),
|
||||
],
|
||||
default='none',
|
||||
max_length=256,
|
||||
),
|
||||
),
|
||||
(
|
||||
'accepted_name_id_format',
|
||||
authentic2.saml.fields.MultiSelectField(
|
||||
blank=True,
|
||||
choices=[
|
||||
('none', 'None'),
|
||||
('persistent', 'Persistent'),
|
||||
('transient', 'Transient'),
|
||||
('email', 'Email'),
|
||||
('username', 'Username (use with Google Apps)'),
|
||||
('uuid', 'UUID'),
|
||||
('edupersontargetedid', 'Use eduPersonTargetedID attribute'),
|
||||
],
|
||||
max_length=1024,
|
||||
verbose_name='NameID formats accepted',
|
||||
),
|
||||
),
|
||||
(
|
||||
'ask_user_consent',
|
||||
models.BooleanField(
|
||||
default=False, verbose_name='Ask user for consent when creating a federation'
|
||||
),
|
||||
),
|
||||
(
|
||||
'accept_slo',
|
||||
models.BooleanField(
|
||||
db_index=True, default=True, verbose_name='Accept to receive Single Logout requests'
|
||||
),
|
||||
),
|
||||
(
|
||||
'forward_slo',
|
||||
models.BooleanField(default=True, verbose_name='Forward Single Logout requests'),
|
||||
),
|
||||
(
|
||||
'needs_iframe_logout',
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
help_text='logout URL are normally loaded inside an <img> HTML tag, some service provider need to use an iframe',
|
||||
verbose_name='needs iframe logout',
|
||||
),
|
||||
),
|
||||
(
|
||||
'iframe_logout_timeout',
|
||||
models.PositiveIntegerField(
|
||||
default=300,
|
||||
help_text="if iframe logout is used, it's the time between the onload event for this iframe and the moment we "
|
||||
'consider its loading to be really finished',
|
||||
verbose_name='iframe logout timeout',
|
||||
),
|
||||
),
|
||||
(
|
||||
'http_method_for_slo_request',
|
||||
models.IntegerField(
|
||||
choices=[(4, 'Redirect binding'), (5, 'SOAP binding')],
|
||||
default=4,
|
||||
verbose_name='HTTP binding for the SLO requests',
|
||||
),
|
||||
),
|
||||
(
|
||||
'federation_mode',
|
||||
models.PositiveIntegerField(
|
||||
choices=[(0, 'explicit'), (1, 'implicit')], default=0, verbose_name='federation mode'
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'service provider options policy',
|
||||
'verbose_name_plural': 'service provider options policies',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='LibertyServiceProvider',
|
||||
fields=[
|
||||
(
|
||||
'liberty_provider',
|
||||
models.OneToOneField(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
primary_key=True,
|
||||
related_name='service_provider',
|
||||
serialize=False,
|
||||
to='saml.libertyprovider',
|
||||
),
|
||||
),
|
||||
('enabled', models.BooleanField(db_index=True, default=False, verbose_name='Enabled')),
|
||||
(
|
||||
'enable_following_sp_options_policy',
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
verbose_name='The following options policy will apply except if a policy for all service provider is defined.',
|
||||
),
|
||||
),
|
||||
(
|
||||
'users_can_manage_federations',
|
||||
models.BooleanField(
|
||||
blank=True, db_index=True, default=True, verbose_name='users can manage federation'
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'SAML service provider',
|
||||
'verbose_name_plural': 'SAML service providers',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='LibertySessionDump',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('django_session_key', models.CharField(max_length=128)),
|
||||
('session_dump', models.TextField(blank=True)),
|
||||
('kind', models.IntegerField(choices=[(0, 'sp'), (1, 'idp')])),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'SAML session dump',
|
||||
'verbose_name_plural': 'SAML session dumps',
|
||||
'unique_together': {('django_session_key', 'kind')},
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='LibertySession',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('django_session_key', models.CharField(max_length=128)),
|
||||
('session_index', models.CharField(max_length=80)),
|
||||
('provider_id', models.CharField(max_length=256)),
|
||||
('name_id_qualifier', models.CharField(max_length=256, null=True, verbose_name='Qualifier')),
|
||||
('name_id_format', models.CharField(max_length=100, null=True, verbose_name='NameIDFormat')),
|
||||
('name_id_content', models.CharField(max_length=100, verbose_name='NameID')),
|
||||
(
|
||||
'name_id_sp_name_qualifier',
|
||||
models.CharField(max_length=256, null=True, verbose_name='SPNameQualifier'),
|
||||
),
|
||||
('creation', models.DateTimeField(auto_now_add=True)),
|
||||
(
|
||||
'federation',
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to='saml.libertyfederation',
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'SAML session',
|
||||
'verbose_name_plural': 'SAML sessions',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SAMLAttribute',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('object_id', models.PositiveIntegerField(verbose_name='object identifier')),
|
||||
(
|
||||
'name_format',
|
||||
models.CharField(
|
||||
choices=[('basic', 'Basic'), ('uri', 'URI'), ('unspecified', 'Unspecified')],
|
||||
default='basic',
|
||||
max_length=64,
|
||||
verbose_name='name format',
|
||||
),
|
||||
),
|
||||
(
|
||||
'name',
|
||||
models.CharField(
|
||||
blank=True,
|
||||
help_text='the local attribute name is used if left blank',
|
||||
max_length=128,
|
||||
verbose_name='name',
|
||||
),
|
||||
),
|
||||
('friendly_name', models.CharField(blank=True, max_length=64, verbose_name='friendly name')),
|
||||
('attribute_name', models.CharField(max_length=64, verbose_name='attribute name')),
|
||||
('enabled', models.BooleanField(blank=True, default=True, verbose_name='enabled')),
|
||||
(
|
||||
'content_type',
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to='contenttypes.contenttype',
|
||||
verbose_name='content type',
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'unique_together': {
|
||||
('content_type', 'object_id', 'name_format', 'name', 'friendly_name', 'attribute_name')
|
||||
},
|
||||
},
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='libertysession',
|
||||
index=models.Index(
|
||||
fields=['provider_id', 'django_session_key'], name='saml_libert_provide_39bb6c_idx'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='libertyserviceprovider',
|
||||
name='sp_options_policy',
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name='sp_options_policy',
|
||||
to='saml.spoptionsidppolicy',
|
||||
verbose_name='service provider options policy',
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='libertyfederation',
|
||||
name='sp',
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to='saml.libertyserviceprovider',
|
||||
),
|
||||
),
|
||||
]
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue