Initial commit

This commit is contained in:
2024-08-27 20:33:44 +02:00
commit 1f1832267d
14794 changed files with 1599592 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
import random
from django.db import models
LOWER_BOUND = -2147483648
UPPER_BOUND = 2147483647
SHIFT = 92147483647
class ConvertedValue(str):
def __new__(cls, value):
value = int(value)
if UPPER_BOUND < value:
display_value = value
db_value = value - SHIFT
else:
db_value = value
display_value = value + SHIFT
self = super().__new__(cls, display_value)
self.db_value = db_value
return self
def __repr__(self):
return f"<{self.__class__.__name__}: {self.db_value}>"
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.db_value == other.db_value
return self.db_value == other
def __hash__(self):
return hash(self.db_value)
class ConvertedValueField(models.IntegerField):
"""
Roughly copied from https://github.com/django/django/blob/d6eaf7c0183cd04b78f2a55e1d60bb7e59598310/tests/custom_pk/fields.py
"""
def pre_save(self, instance, add):
value = getattr(instance, self.attname, None)
if not value:
value = ConvertedValue(random.randint(LOWER_BOUND, UPPER_BOUND))
setattr(instance, self.attname, value)
return value
def to_python(self, value):
if not value:
return
if not isinstance(value, ConvertedValue):
value = ConvertedValue(value)
return value
def get_prep_value(self, value):
if value is None:
return None
if not isinstance(value, ConvertedValue):
value = ConvertedValue(value)
return super().get_prep_value(value.db_value)
def from_db_value(self, value, expression, connection):
if not value:
return
return ConvertedValue(value)
def get_db_prep_save(self, value, connection):
if not value:
return
return ConvertedValue(value).db_value
def get_db_prep_value(self, value, connection, prepared=False):
if not value:
return
return ConvertedValue(value).db_value
def get_searchable_content(self, value):
if not value:
return
return ConvertedValue(value).db_value

View File

@@ -0,0 +1,114 @@
[
{
"pk": 1,
"model": "customuser.customuser",
"fields": {
"username": "superuser",
"first_name": "",
"last_name": "",
"is_active": true,
"is_superuser": true,
"is_staff": true,
"groups": [],
"user_permissions": [],
"password": "md5$seasalt$1e9bf2bf5606aa5c39852cc30f0f6f22",
"email": "superuser@example.com"
}
},
{
"pk": 2,
"model": "customuser.customuser",
"fields": {
"username": "eventeditor",
"first_name": "",
"last_name": "",
"is_active": true,
"is_superuser": false,
"is_staff": false,
"groups": [["Event editors"]],
"user_permissions": [],
"password": "md5$seasalt$1e9bf2bf5606aa5c39852cc30f0f6f22",
"email": "eventeditor@example.com"
}
},
{
"pk": 3,
"model": "customuser.customuser",
"fields": {
"username": "eventmoderator",
"first_name": "",
"last_name": "",
"is_active": true,
"is_superuser": false,
"is_staff": false,
"groups": [["Event moderators"]],
"user_permissions": [],
"password": "md5$seasalt$1e9bf2bf5606aa5c39852cc30f0f6f22",
"email": "eventmoderator@example.com"
}
},
{
"pk": 4,
"model": "customuser.customuser",
"fields": {
"username": "inactiveuser",
"first_name": "",
"last_name": "",
"is_active": false,
"is_superuser": false,
"is_staff": false,
"groups": [["Event moderators"]],
"user_permissions": [],
"password": "md5$seasalt$1e9bf2bf5606aa5c39852cc30f0f6f22",
"email": "inactiveuser@example.com"
}
},
{
"pk": 5,
"model": "customuser.customuser",
"fields": {
"username": "siteeditor",
"first_name": "",
"last_name": "",
"is_active": true,
"is_superuser": false,
"is_staff": false,
"groups": [["Site-wide editors"]],
"user_permissions": [],
"password": "md5$seasalt$1e9bf2bf5606aa5c39852cc30f0f6f22",
"email": "siteeditor@example.com"
}
},
{
"pk": 6,
"model": "customuser.customuser",
"fields": {
"username": "admin_only_user",
"first_name": "",
"last_name": "",
"is_active": true,
"is_superuser": false,
"is_staff": false,
"groups": [["Admin non-editors"]],
"user_permissions": [],
"password": "md5$seasalt$1e9bf2bf5606aa5c39852cc30f0f6f22",
"email": "admin_only_user@example.com"
}
},
{
"pk": 7,
"model": "customuser.customuser",
"fields": {
"username": "corporateeditor",
"first_name": "",
"last_name": "",
"is_active": true,
"is_superuser": false,
"is_staff": false,
"groups": [["Corporate Editor"]],
"user_permissions": [],
"password": "md5$seasalt$1e9bf2bf5606aa5c39852cc30f0f6f22",
"email": "corporateeditor@example.com"
}
}
]

View File

@@ -0,0 +1,98 @@
[
{
"pk": 1,
"model": "customuser.customuser",
"fields": {
"username": "superman",
"first_name": "Clark",
"last_name": "Kent",
"is_active": true,
"is_superuser": true,
"is_staff": true,
"groups": [],
"user_permissions": [],
"password": "md5$seasalt$1e9bf2bf5606aa5c39852cc30f0f6f22",
"email": "superman@example.com"
}
},
{
"pk": 2,
"model": "customuser.customuser",
"fields": {
"username": "jane",
"first_name": "Jane",
"last_name": "Smith",
"is_active": true,
"is_superuser": false,
"is_staff": true,
"groups": [["Group 1"]],
"user_permissions": [],
"password": "md5$seasalt$1e9bf2bf5606aa5c39852cc30f0f6f22",
"email": "jane@example.com"
}
},
{
"pk": 3,
"model": "customuser.customuser",
"fields": {
"username": "bob",
"first_name": "Bob",
"last_name": "Smith",
"is_active": true,
"is_superuser": false,
"is_staff": true,
"groups": [["Group 2"]],
"user_permissions": [],
"password": "md5$seasalt$1e9bf2bf5606aa5c39852cc30f0f6f22",
"email": "bob@example.com"
}
},
{
"pk": 4,
"model": "customuser.customuser",
"fields": {
"username": "sam",
"first_name": "Sam",
"last_name": "Smith",
"is_active": true,
"is_superuser": false,
"is_staff": true,
"groups": [["Group 1"], ["Group 2"]],
"user_permissions": [],
"password": "md5$seasalt$1e9bf2bf5606aa5c39852cc30f0f6f22",
"email": "sam@example.com"
}
},
{
"pk": 5,
"model": "customuser.customuser",
"fields": {
"username": "mary",
"first_name": "Mary",
"last_name": "Smith",
"is_active": true,
"is_superuser": false,
"is_staff": true,
"groups": [],
"user_permissions": [["access_admin", "wagtailadmin", "admin"]],
"password": "md5$seasalt$1e9bf2bf5606aa5c39852cc30f0f6f22",
"email": "mary@example.com"
}
},
{
"pk": 6,
"model": "customuser.customuser",
"fields": {
"username": "josh",
"first_name": "Josh",
"last_name": "Smith",
"is_active": true,
"is_superuser": false,
"is_staff": true,
"groups": [["Group 2"], ["Group 3"]],
"user_permissions": [],
"password": "md5$seasalt$1e9bf2bf5606aa5c39852cc30f0f6f22",
"email": "josh@example.com"
}
}
]

View File

@@ -0,0 +1,18 @@
[
{
"pk": 1,
"model": "customuser.customuser",
"fields": {
"username": "superuser",
"first_name": "",
"last_name": "",
"is_active": true,
"is_superuser": true,
"is_staff": true,
"groups": [],
"user_permissions": [],
"password": "md5$seasalt$1e9bf2bf5606aa5c39852cc30f0f6f22",
"email": "superuser@example.com"
}
}
]

View File

@@ -0,0 +1,113 @@
from django.db import migrations, models
from ..fields import ConvertedValueField
class Migration(migrations.Migration):
dependencies = [
("auth", "0001_initial"),
]
operations = [
migrations.CreateModel(
name="CustomUser",
fields=[
("identifier", ConvertedValueField(serialize=False, primary_key=True)),
("password", models.CharField(max_length=128, verbose_name="password")),
(
"last_login",
models.DateTimeField(
null=True, verbose_name="last login", blank=True
),
),
(
"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(unique=True, max_length=100)),
("email", models.EmailField(max_length=255, blank=True)),
("is_staff", models.BooleanField(default=True)),
("is_active", models.BooleanField(default=True)),
("first_name", models.CharField(max_length=50, blank=True)),
("last_name", models.CharField(max_length=50, blank=True)),
("country", models.CharField(max_length=100, blank=True)),
(
"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 their groups."
),
verbose_name="groups",
),
),
(
"user_permissions",
models.ManyToManyField(
to="auth.Permission",
verbose_name="user permissions",
help_text="Specific permissions for this user.",
related_name="user_set",
blank=True,
related_query_name="user",
),
),
],
options={
"abstract": False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name="EmailUser",
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(
null=True, verbose_name="last login", blank=True
),
),
("email", models.EmailField(unique=True, max_length=255)),
("is_staff", models.BooleanField(default=True)),
("is_active", models.BooleanField(default=True)),
("first_name", models.CharField(max_length=50, blank=True)),
("last_name", models.CharField(max_length=50, blank=True)),
("is_superuser", models.BooleanField(default=False)),
(
"groups",
models.ManyToManyField(
related_name="+", to="auth.Group", blank=True
),
),
(
"user_permissions",
models.ManyToManyField(
related_name="+", to="auth.Permission", blank=True
),
),
],
options={
"abstract": False,
},
bases=(models.Model,),
),
]

View File

@@ -0,0 +1,16 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("customuser", "0001_initial"),
]
operations = [
migrations.AddField(
model_name="CustomUser",
name="attachment",
field=models.FileField(blank=True),
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 3.1 on 2020-08-13 21:28
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("customuser", "0002_added_file_field"),
]
operations = [
migrations.DeleteModel(
name="EmailUser",
),
]

View File

@@ -0,0 +1,83 @@
from django.contrib.auth.models import (
AbstractBaseUser,
BaseUserManager,
PermissionsMixin,
)
from django.db import models
# Custom user models are a common source of circular import errors, since the user model is often
# referenced in Wagtail core code that we may want to import here. To prevent this, Wagtail should
# avoid importing the user model at load time.
# wagtail.admin.auth and wagtail.admin.views.generic are imported here as these have been
# previously identified as sources of circular imports.
from wagtail.admin.auth import permission_denied # noqa: F401
from wagtail.admin.panels import FieldPanel
from wagtail.admin.views.generic import chooser as chooser_views # noqa: F401
from .fields import ConvertedValueField
class CustomUserManager(BaseUserManager):
def _create_user(
self,
username,
email,
password,
is_staff,
is_superuser,
is_active=True,
**extra_fields,
):
"""
Creates and saves a User with the given username, email and password.
"""
if not username:
raise ValueError("The given username must be set")
email = self.normalize_email(email)
user = self.model(
username=username,
email=email,
is_staff=is_staff,
is_active=is_active,
is_superuser=is_superuser,
**extra_fields,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, username, email=None, password=None, **extra_fields):
return self._create_user(
username, email, password, False, False, **extra_fields
)
def create_superuser(self, username, email, password, **extra_fields):
return self._create_user(username, email, password, True, True, **extra_fields)
class CustomUser(AbstractBaseUser, PermissionsMixin):
identifier = ConvertedValueField(primary_key=True)
username = models.CharField(max_length=100, unique=True)
email = models.EmailField(max_length=255, blank=True)
is_staff = models.BooleanField(default=True)
is_active = models.BooleanField(default=True)
first_name = models.CharField(max_length=50, blank=True)
last_name = models.CharField(max_length=50, blank=True)
country = models.CharField(max_length=100, blank=True)
attachment = models.FileField(blank=True)
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ["email"]
objects = CustomUserManager()
def get_full_name(self):
return self.first_name + " " + self.last_name
def get_short_name(self):
return self.first_name
panels = [
FieldPanel("first_name"),
FieldPanel("last_name"),
]

View File

@@ -0,0 +1,47 @@
import json
import unittest
from django.conf import settings
from django.db import connections
from django.test import TestCase
from wagtail.test.utils import WagtailTestUtils
from .fields import ConvertedValue, ConvertedValueField
@unittest.skipUnless(
settings.AUTH_USER_MODEL == "customuser.CustomUser", "Only applicable to CustomUser"
)
class TestConvertedValueField(WagtailTestUtils, TestCase):
def setUp(self):
self.user = self.login()
User = self.user.__class__
self.pk_field = User._meta.get_field(User._meta.pk.name)
self.pk_db_value = self.pk_field.get_db_prep_value(
self.user.pk, connections["default"]
)
def test_db_value_is_different(self):
self.assertEqual(self.user.pk, self.pk_db_value)
self.assertNotEqual(str(self.user.pk), str(self.pk_db_value))
def test_custom_user_primary_key_is_hashable(self):
hash(self.user.pk)
def test_custom_user_primary_key_is_jsonable(self):
json_str = json.dumps({"pk": self.user.pk}, separators=(",", ":"))
self.assertEqual(json_str, '{"pk":"%s"}' % self.user.pk)
# verify the json string uses the display value and not the db value
self.assertNotEqual(json_str, '{"pk":"%s"}' % self.pk_db_value)
def test_custom_user_primary_key(self):
self.assertIsInstance(self.user.pk, ConvertedValue)
def test_custom_user_primary_key_is_converted_value_field(self):
self.assertIsInstance(self.pk_field, ConvertedValueField)
def test_get_prep_value_returns_integer_for_db_query(self):
self.assertIsInstance(self.pk_field.get_prep_value(1234), int)