-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #14 from the-deep/fix/project-membership
Fix project memberships issues
- Loading branch information
Showing
12 changed files
with
238 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
Addresses xxxxxx (eg: #1 the-deep/questionnaire-builder-backend#1) \ | ||
Depends on xxxxxx (eg: #1 the-deep/questionnaire-builder-backend#1) | ||
|
||
## Changes | ||
|
||
* Detailed list or prose of changes | ||
* Breaking changes | ||
* Changes to configurations | ||
|
||
**Mention related users here if any.** | ||
|
||
## This PR doesn't introduce any: | ||
|
||
- [ ] temporary files, auto-generated files or secret keys | ||
- [ ] n+1 queries | ||
- [ ] flake8 issues | ||
- [ ] `print` | ||
- [ ] typos | ||
- [ ] unwanted comments | ||
|
||
## This PR contains valid: | ||
|
||
- [ ] tests | ||
- [ ] permission checks (tests here too) | ||
- [ ] translations |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import strawberry | ||
import strawberry_django | ||
from strawberry.types import Info | ||
from django.db import models | ||
from django.db.models.functions import Concat | ||
|
||
from .models import User | ||
|
||
|
||
@strawberry_django.filters.filter(User, lookups=True) | ||
class UserFilter: | ||
id: strawberry.auto | ||
search: str | None | ||
members_exclude_project: strawberry.ID | None | ||
exclude_me: bool = False | ||
|
||
def filter_search(self, queryset): | ||
value = self.search | ||
if value: | ||
queryset = queryset.annotate( | ||
full_name=Concat( | ||
models.F("first_name"), | ||
models.Value(" "), | ||
models.F("last_name"), | ||
output_field=models.CharField(), | ||
) | ||
).filter( | ||
models.Q(full_name__icontains=value) | | ||
models.Q(first_name__icontains=value) | | ||
models.Q(last_name__icontains=value) | | ||
models.Q(email__icontains=value) | ||
) | ||
return queryset | ||
|
||
def filter_members_exclude_project(self, queryset): | ||
value = self.members_exclude_project | ||
if value: | ||
queryset = queryset.filter( | ||
~models.Q(projectmembership__project_id=value) | ||
).distinct() | ||
return queryset | ||
|
||
def filter_exclude_me(self, queryset, info: Info): | ||
value = self.exclude_me | ||
if value: | ||
queryset = queryset.exclude(id=info.context.request.user.id) | ||
return queryset |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,14 @@ | ||
from main.tests import TestCase | ||
|
||
from apps.user.models import User | ||
|
||
from apps.user.factories import UserFactory | ||
from apps.project.factories import ProjectFactory | ||
|
||
|
||
class TestUserQuery(TestCase): | ||
def test_me(self): | ||
query = ''' | ||
class Query: | ||
ME = ''' | ||
query meQuery { | ||
public { | ||
me { | ||
|
@@ -21,21 +23,46 @@ def test_me(self): | |
} | ||
''' | ||
|
||
User.objects.all().delete() # Clear all users if exists | ||
# Create some users | ||
user = UserFactory.create( | ||
USERS = ''' | ||
query MyQuery($filters: UserFilter) { | ||
private { | ||
users(order: {id: ASC}, pagination: {limit: 10, offset: 0}, filters: $filters) { | ||
limit | ||
offset | ||
count | ||
items { | ||
id | ||
firstName | ||
lastName | ||
displayName | ||
} | ||
} | ||
} | ||
} | ||
''' | ||
|
||
@classmethod | ||
def setUpClass(cls): | ||
super().setUpClass() | ||
cls.user = UserFactory.create( | ||
email_opt_outs=[User.OptEmailNotificationType.NEWS_AND_OFFERS], | ||
) | ||
# Some other users as well | ||
UserFactory.create_batch(3) | ||
cls.users = ( | ||
UserFactory.create(first_name='Test', last_name='Hero', email='[email protected]'), | ||
UserFactory.create(first_name='Example', last_name='Villain', email='[email protected]'), | ||
UserFactory.create(first_name='Test', last_name='Hero'), | ||
) | ||
|
||
def test_me(self): | ||
# Without authentication ----- | ||
content = self.query_check(query) | ||
content = self.query_check(self.Query.ME) | ||
assert content['data']['public']['me'] is None | ||
|
||
user = self.user | ||
# With authentication ----- | ||
self.force_login(user) | ||
content = self.query_check(query) | ||
content = self.query_check(self.Query.ME) | ||
assert content['data']['public']['me'] == dict( | ||
id=str(user.id), | ||
email=user.email, | ||
|
@@ -47,3 +74,42 @@ def test_me(self): | |
for opt in user.email_opt_outs | ||
], | ||
) | ||
|
||
def test_users(self): | ||
user1, user2, user3 = self.users | ||
project = ProjectFactory.create(created_by=user1, modified_by=user1) | ||
project.add_member(user1) | ||
|
||
# Without authentication ----- | ||
content = self.query_check(self.Query.USERS, assert_errors=True) | ||
assert content['data'] is None | ||
|
||
# With authentication ----- | ||
self.force_login(self.user) | ||
for filters, expected_users in [ | ||
({'id': {'exact': str(user1.id)}}, [user1]), | ||
# Free text search tests | ||
({'search': 'hero'}, [user1, user3]), | ||
({'search': 'test'}, [user1, user3]), | ||
({'search': '@vil'}, [user2]), | ||
({'search': 'sample'}, [user1, user2]), | ||
({'search': 'sample@'}, [user1, user2]), | ||
({'membersExcludeProject': str(project.pk)}, [self.user, user2, user3]), | ||
({}, [self.user, *self.users]), | ||
({'excludeMe': True}, self.users), | ||
]: | ||
content = self.query_check(self.Query.USERS, variables={'filters': filters}) | ||
assert content['data']['private']['users'] == { | ||
'count': len(expected_users), | ||
'limit': 10, | ||
'offset': 0, | ||
'items': [ | ||
{ | ||
'id': str(user.id), | ||
'firstName': user.first_name, | ||
'lastName': user.last_name, | ||
'displayName': f'{user.first_name} {user.last_name}', | ||
} | ||
for user in expected_users | ||
] | ||
}, (filters, expected_users) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.