Introduce workspace tenancy boundaries
This commit is contained in:
+46
-11
@@ -3,7 +3,7 @@ from django.contrib.auth.forms import UserCreationForm
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models import Q
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from .models import ApiKey, Attachment, Collection, Item, Kanban, Tag, Team, TeamInvite, UserInvite, UserPreference
|
||||
from .models import ApiKey, Attachment, Collection, Item, Kanban, Tag, Team, TeamInvite, UserInvite, UserPreference, Workspace, get_or_create_personal_workspace
|
||||
|
||||
|
||||
class MultipleFileInput(forms.ClearableFileInput):
|
||||
@@ -73,6 +73,20 @@ class UserPreferenceForm(forms.ModelForm):
|
||||
}
|
||||
|
||||
|
||||
class WorkspaceForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Workspace
|
||||
fields = ['name', 'slug']
|
||||
labels = {'name': _('Workspace name'), 'slug': _('Short name')}
|
||||
widgets = {
|
||||
'name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': _('Company or workspace name')}),
|
||||
'slug': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'firma'}),
|
||||
}
|
||||
|
||||
def clean_slug(self):
|
||||
return self.cleaned_data['slug'].strip().lower()
|
||||
|
||||
|
||||
class UserInviteForm(forms.ModelForm):
|
||||
email = forms.EmailField(required=True, label=_('Email'), widget=forms.EmailInput(attrs={'class': 'form-control', 'placeholder': 'person@example.com', 'required': True}))
|
||||
|
||||
@@ -96,6 +110,11 @@ class InviteRegistrationForm(UserCreationForm):
|
||||
|
||||
|
||||
class TeamForm(forms.ModelForm):
|
||||
def __init__(self, *args, user=None, workspace=None, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.user = user
|
||||
self.workspace = workspace or (get_or_create_personal_workspace(user) if user and user.is_authenticated else None)
|
||||
|
||||
class Meta:
|
||||
model = Team
|
||||
fields = ['name', 'slug']
|
||||
@@ -106,7 +125,15 @@ class TeamForm(forms.ModelForm):
|
||||
}
|
||||
|
||||
def clean_slug(self):
|
||||
return self.cleaned_data['slug'].strip().lstrip('#').lower()
|
||||
slug = self.cleaned_data['slug'].strip().lstrip('#').lower()
|
||||
if self.workspace and Team.objects.filter(workspace=self.workspace, slug=slug).exclude(pk=self.instance.pk).exists():
|
||||
raise forms.ValidationError(_('This team tag is already used in this workspace.'))
|
||||
return slug
|
||||
|
||||
def save(self, commit=True):
|
||||
if self.workspace:
|
||||
self.instance.workspace = self.workspace
|
||||
return super().save(commit=commit)
|
||||
|
||||
|
||||
class TeamInviteForm(forms.ModelForm):
|
||||
@@ -120,6 +147,11 @@ class TeamInviteForm(forms.ModelForm):
|
||||
class KanbanForm(forms.ModelForm):
|
||||
tag_name = forms.CharField(label=_('Tag'), widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'my2dos'}))
|
||||
|
||||
def __init__(self, *args, user=None, workspace=None, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.user = user
|
||||
self.workspace = workspace or (get_or_create_personal_workspace(user) if user and user.is_authenticated else None)
|
||||
|
||||
class Meta:
|
||||
model = Kanban
|
||||
fields = ['name', 'tag_name']
|
||||
@@ -127,7 +159,8 @@ class KanbanForm(forms.ModelForm):
|
||||
|
||||
def save(self, commit=True):
|
||||
tag_name = self.cleaned_data['tag_name'].strip().lstrip('#').lower()
|
||||
tag, _ = Tag.objects.get_or_create(name=tag_name)
|
||||
tag, _ = Tag.objects.get_or_create(workspace=self.workspace, name=tag_name)
|
||||
self.instance.workspace = self.workspace
|
||||
self.instance.tag = tag
|
||||
return super().save(commit=commit)
|
||||
|
||||
@@ -135,19 +168,20 @@ class KanbanForm(forms.ModelForm):
|
||||
class CollectionForm(forms.ModelForm):
|
||||
team = forms.ModelChoiceField(queryset=Team.objects.none(), required=False, label=_('Team'), widget=forms.Select(attrs={'class': 'form-select'}))
|
||||
|
||||
def __init__(self, *args, user=None, **kwargs):
|
||||
def __init__(self, *args, user=None, workspace=None, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['visibility'].choices = [
|
||||
(Item.Visibility.PRIVATE, _('Private')),
|
||||
(Item.Visibility.PUBLIC, _('Public')),
|
||||
]
|
||||
if user and user.is_authenticated:
|
||||
team_ids = user.team_memberships.values_list('team_id', flat=True)
|
||||
self.fields['team'].queryset = Team.objects.filter(pk__in=team_ids).order_by('name')
|
||||
workspace = self.instance.workspace if self.instance and self.instance.pk else (workspace or get_or_create_personal_workspace(user))
|
||||
team_ids = user.team_memberships.filter(team__workspace=workspace).values_list('team_id', flat=True)
|
||||
self.fields['team'].queryset = Team.objects.filter(workspace=workspace, pk__in=team_ids).order_by('name')
|
||||
self.fields['team'].initial = self.instance.team_id if self.instance and self.instance.pk else None
|
||||
item_scope = Q(items__owner=user) | Q(items__team_id__in=team_ids)
|
||||
team_slugs = Team.objects.values_list('slug', flat=True)
|
||||
self.fields['filter_tags'].queryset = Tag.objects.filter(item_scope).exclude(name__in=team_slugs).distinct().order_by('name')
|
||||
item_scope = Q(items__workspace=workspace) & (Q(items__owner=user) | Q(items__team_id__in=team_ids))
|
||||
team_slugs = Team.objects.filter(workspace=workspace).values_list('slug', flat=True)
|
||||
self.fields['filter_tags'].queryset = Tag.objects.filter(workspace=workspace).filter(item_scope).exclude(name__in=team_slugs).distinct().order_by('name')
|
||||
else:
|
||||
self.fields['team'].queryset = Team.objects.none()
|
||||
self.fields['filter_tags'].queryset = Tag.objects.none()
|
||||
@@ -189,10 +223,11 @@ class CollectionForm(forms.ModelForm):
|
||||
|
||||
|
||||
class ApiKeyForm(forms.ModelForm):
|
||||
def __init__(self, *args, user=None, **kwargs):
|
||||
def __init__(self, *args, user=None, workspace=None, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
if user and user.is_authenticated:
|
||||
self.fields['tags'].queryset = Tag.objects.filter(items__owner=user).distinct().order_by('name')
|
||||
workspace = workspace or get_or_create_personal_workspace(user)
|
||||
self.fields['tags'].queryset = Tag.objects.filter(workspace=workspace, items__owner=user).distinct().order_by('name')
|
||||
else:
|
||||
self.fields['tags'].queryset = Tag.objects.none()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user