mirror of
https://github.com/omaha-consulting/winget.pro.git
synced 2026-10-24 12:52:26 +00:00
Allow multiple users per tenant
This commit is contained in:
+1
-1
@@ -7,7 +7,7 @@ def can_pick_tenant(user):
|
||||
|
||||
def filter_for_user(model, user):
|
||||
tenant_accessor = get_tenant_accessor(model)
|
||||
query = {tenant_accessor + '__user': user}
|
||||
query = {tenant_accessor + '__users': user}
|
||||
return model.objects.filter(**query)
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -4,6 +4,6 @@ from django.contrib.admin import ModelAdmin
|
||||
from .models import Tenant
|
||||
|
||||
class TenantAdmin(ModelAdmin):
|
||||
list_display = ('user', 'uuid')
|
||||
list_display = ('__str__', 'uuid')
|
||||
|
||||
admin.site.register(Tenant, TenantAdmin)
|
||||
+1
-1
@@ -14,7 +14,7 @@ class TenantModelForm(ModelForm):
|
||||
def full_clean(self):
|
||||
super().full_clean()
|
||||
if not can_pick_tenant(self.user) and self.instance:
|
||||
self.instance.tenant = Tenant.objects.get(user=self.user)
|
||||
self.instance.tenant = Tenant.objects.get(users=self.user)
|
||||
self.validate_unique_for_tenant()
|
||||
|
||||
def validate_unique_for_tenant(self):
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
# Generated by Django 3.2.10 on 2023-08-03 10:45
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('tenants', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='tenant',
|
||||
name='users',
|
||||
field=models.ManyToManyField(related_name='users', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 3.2.10 on 2023-08-03 10:45
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
def migrate_existing_users(apps, _):
|
||||
Tenant = apps.get_model('tenants', 'Tenant')
|
||||
for tenant in Tenant.objects.all():
|
||||
tenant.users.add(tenant.user)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('tenants', '0002_tenant_users'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(migrate_existing_users)
|
||||
]
|
||||
@@ -0,0 +1,24 @@
|
||||
# Generated by Django 3.2.10 on 2023-08-03 10:49
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('tenants', '0003_migrate_existing_users'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='tenant',
|
||||
name='user',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tenant',
|
||||
name='users',
|
||||
field=models.ManyToManyField(to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
+10
-3
@@ -1,13 +1,20 @@
|
||||
from uuid import uuid4
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models import Model, ForeignKey, CASCADE, UUIDField
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.db.models import Model, UUIDField, ManyToManyField
|
||||
|
||||
|
||||
class Tenant(Model):
|
||||
|
||||
user = ForeignKey(User, on_delete=CASCADE)
|
||||
users = ManyToManyField(User)
|
||||
uuid = UUIDField(unique=True, default=uuid4, editable=False)
|
||||
|
||||
def __str__(self):
|
||||
return self.user.username
|
||||
# We have to check that `id` is set to avoid a `RecursionError`.
|
||||
if self.id:
|
||||
try:
|
||||
return self.users.earliest('date_joined').username
|
||||
except ObjectDoesNotExist:
|
||||
pass
|
||||
return str(self.uuid)
|
||||
@@ -1,11 +1,10 @@
|
||||
from base64 import b64encode
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.files import File
|
||||
from django.urls import reverse
|
||||
from rest_framework.test import APIClient
|
||||
from tenants.models import Tenant
|
||||
from winget.models import Package, Version, Installer
|
||||
from winget.tests.util import TestCaseThatUploadsFiles, MultiUploadInMemoryFile
|
||||
from winget.tests.util import TestCaseThatUploadsFiles, \
|
||||
MultiUploadInMemoryFile, create_tenant
|
||||
|
||||
import json
|
||||
|
||||
@@ -15,9 +14,9 @@ class APITest(TestCaseThatUploadsFiles):
|
||||
super().setUp()
|
||||
self.client = APIClient()
|
||||
self.credentials = ('user', 'pw')
|
||||
self.tenant = self._create_user_tenant(self.credentials)
|
||||
self.tenant = create_tenant(*self.credentials)
|
||||
self.other_credentials = ('user2', 'pw2')
|
||||
self._create_user_tenant(self.other_credentials)
|
||||
create_tenant(*self.other_credentials)
|
||||
def test_create_package(self):
|
||||
response = self._check_unauthorized_and_request(
|
||||
'post', 'package-list', _PACKAGE_PAYLOAD, self.credentials
|
||||
@@ -128,9 +127,6 @@ class APITest(TestCaseThatUploadsFiles):
|
||||
self.test_create_version(use_correct_credentials=False)
|
||||
def test_cannot_create_installer_for_other_tenants_version(self):
|
||||
self.test_create_installer(use_correct_credentials=False)
|
||||
def _create_user_tenant(self, credentials):
|
||||
user = User.objects.create_user(credentials[0], password=credentials[1])
|
||||
return Tenant.objects.create(user=user)
|
||||
def _check_unauthorized_and_request(
|
||||
self, method, view_name, data, credentials=None, view_kwargs=None
|
||||
):
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.test import TestCase, Client
|
||||
from django.urls import reverse
|
||||
|
||||
from tenants.models import Tenant
|
||||
from winget.models import Package, Version, Installer
|
||||
from winget.tests.util import create_tenant
|
||||
|
||||
|
||||
class APITest(TestCase):
|
||||
@@ -12,9 +11,7 @@ class APITest(TestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.client = Client()
|
||||
self.tenant = Tenant.objects.create(
|
||||
user=User.objects.create_user('user@gmail.com')
|
||||
)
|
||||
self.tenant = create_tenant()
|
||||
|
||||
def test_information_required_parts(self):
|
||||
data = self._get('information')['Data']
|
||||
|
||||
+10
-1
@@ -1,7 +1,10 @@
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.test import TestCase, override_settings
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
from tenants.models import Tenant
|
||||
|
||||
"""
|
||||
When a test case uploads files, they by default get placed into media/. This
|
||||
folder (out of the box) is not cleaned up after the test case is run.
|
||||
@@ -24,4 +27,10 @@ class MultiUploadInMemoryFile(SimpleUploadedFile):
|
||||
"""
|
||||
def read(self):
|
||||
self.seek(0)
|
||||
return super().read()
|
||||
return super().read()
|
||||
|
||||
def create_tenant(username='user@gmail.com', password=None):
|
||||
user = User.objects.create_user(username, password=password)
|
||||
tenant = Tenant.objects.create()
|
||||
tenant.users.add(user)
|
||||
return tenant
|
||||
Reference in New Issue
Block a user