From c6cf298a66156e270eb5ffa3c478171ae13d2b84 Mon Sep 17 00:00:00 2001 From: Simen Sandhaug Date: Mon, 7 Nov 2022 18:12:33 +0100 Subject: [PATCH 01/26] change hr_group and primary_group to admin_group and member_group in models --- backend/apps/organizations/models.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/backend/apps/organizations/models.py b/backend/apps/organizations/models.py index d0f66d32a..a3ade904f 100644 --- a/backend/apps/organizations/models.py +++ b/backend/apps/organizations/models.py @@ -4,7 +4,7 @@ from django.db import models from django.db.models import UniqueConstraint -from apps.permissions.constants import HR_TYPE, PRIMARY_TYPE +from apps.permissions.constants import ADMIN_GROUP_TYPE, MEMBER_GROUP_TYPE from apps.permissions.models import ResponsibleGroup @@ -42,22 +42,22 @@ class Organization(models.Model): ) @property - def hr_group(self) -> Optional["ResponsibleGroup"]: + def admin_group(self) -> Optional["ResponsibleGroup"]: try: - return self.permission_groups.get(group_type=HR_TYPE) + return self.permission_groups.get(group_type=ADMIN_GROUP_TYPE) except ResponsibleGroup.DoesNotExist: return None @property - def primary_group(self) -> Optional["ResponsibleGroup"]: + def member_group(self) -> Optional["ResponsibleGroup"]: try: - return self.permission_groups.get(group_type=PRIMARY_TYPE) + return self.permission_groups.get(group_type=MEMBER_GROUP_TYPE) except ResponsibleGroup.DoesNotExist: return None class Meta: constraints = [UniqueConstraint(fields=["parent", "name"], name="unique_child_organization_name")] - permissions = [("manage_organization", "Can manage organizations, used for admins")] + # permissions = [("manage_organization", "Can manage organizations, used for admins")] def __str__(self): return f"{self.name}" From d800ba4c941abc466166ef84831822f57d366710 Mon Sep 17 00:00:00 2001 From: Simen Sandhaug Date: Mon, 7 Nov 2022 18:13:03 +0100 Subject: [PATCH 02/26] update group constants --- backend/apps/permissions/constants.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/apps/permissions/constants.py b/backend/apps/permissions/constants.py index 230f8a70c..77d632f61 100644 --- a/backend/apps/permissions/constants.py +++ b/backend/apps/permissions/constants.py @@ -3,14 +3,14 @@ DefaultPermissionsType = Final[list[tuple[str, str]]] # Default ResponsibleGroup types -PRIMARY_TYPE: Literal["PRIMARY"] = "PRIMARY" -HR_TYPE: Literal["HR"] = "HR" +MEMBER_GROUP_TYPE: Literal["MEMBER"] = "MEMBER" +ADMIN_GROUP_TYPE: Literal["ADMIN"] = "ADMIN" ORGANIZATION: Final = "Organization member" INDOK: Final = "Indøk" REGISTERED_USER: Final = "Registered user" -PRIMARY_GROUP_NAME: Final = "Medlem" -HR_GROUP_NAME: Final = "HR" +MEMBER_GROUP_NAME: Final = "Medlem" +ADMIN_GROUP_NAME: Final = "Administrator" DEFAULT_ORGANIZATION_PERMISSIONS: DefaultPermissionsType = [ ("events", "add_event"), From 5faef2558956cbbe0808b3093282af292708d900 Mon Sep 17 00:00:00 2001 From: Simen Sandhaug Date: Mon, 7 Nov 2022 18:13:32 +0100 Subject: [PATCH 03/26] change instances of hr_group and primary_group --- backend/apps/organizations/signals.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/backend/apps/organizations/signals.py b/backend/apps/organizations/signals.py index d7dfb07a5..3dd14f99a 100644 --- a/backend/apps/organizations/signals.py +++ b/backend/apps/organizations/signals.py @@ -7,11 +7,11 @@ from apps.organizations.models import Membership, Organization from apps.permissions.constants import ( - HR_GROUP_NAME, - HR_TYPE, + ADMIN_GROUP_NAME, + ADMIN_GROUP_TYPE, ORGANIZATION, - PRIMARY_GROUP_NAME, - PRIMARY_TYPE, + MEMBER_GROUP_NAME, + MEMBER_GROUP_TYPE, ) from apps.permissions.models import ResponsibleGroup @@ -44,19 +44,20 @@ def handle_removed_member(instance: Membership, **kwargs): @receiver(post_save, sender=Organization) def create_default_groups(instance: Organization, created, **kwargs): """ - Creates and assigns a primary group and HR group to members of the organization. + Creates and assigns a primary group and ADMIN group to members of the organization. """ if created: ResponsibleGroup.objects.create( - name=PRIMARY_GROUP_NAME, + name=MEMBER_GROUP_NAME, description=f"Medlemmer av {instance.name}.", organization=instance, - group_type=PRIMARY_TYPE, + group_type=MEMBER_GROUP_TYPE, ) - hr_group = ResponsibleGroup.objects.create( - name=HR_GROUP_NAME, - description=f"HR-gruppen til {instance.name}. Tillatelser for å se og behandle søknader.", + admin_group = ResponsibleGroup.objects.create( + name=ADMIN_GROUP_NAME, + description=f"ADMIN-gruppen til {instance.name}. Tillatelser for å se og behandle søknader.", organization=instance, - group_type=HR_TYPE, + group_type=ADMIN_GROUP_TYPE, ) - assign_perm("forms.add_form", hr_group.group) + assign_perm("forms.add_form", admin_group.group) + assign_perm("organizations.manage_organization", admin_group.group) From 1d6e42bf3fe1f649cad69929d3dfe4195499f5ed Mon Sep 17 00:00:00 2001 From: Simen Sandhaug Date: Mon, 7 Nov 2022 18:40:38 +0100 Subject: [PATCH 04/26] fix query error --- backend/apps/ecommerce/tests.py | 2 +- backend/apps/forms/signals.py | 2 +- backend/apps/forms/tests.py | 2 +- .../migrations/0024_auto_20210422_2020.py | 2 +- .../migrations/0025_auto_20210426_1735.py | 8 ++--- .../migrations/0026_auto_20210426_1802.py | 20 ++++++------ .../migrations/0028_auto_20210426_1948.py | 6 ++-- .../migrations/0029_auto_20210426_2129.py | 4 +-- .../migrations/0030_auto_20210426_2129.py | 2 +- .../migrations/0031_auto_20210824_1446.py | 6 ++-- .../migrations/0032_auto_20210824_1457.py | 4 +-- backend/apps/organizations/signals.py | 4 +-- backend/apps/organizations/types.py | 8 ++--- .../migrations/0003_auto_20210824_1213.py | 14 ++++---- .../migrations/0005_auto_20210824_1446.py | 32 ++++++++++--------- backend/schema.json | 18 +++-------- .../pages/organization/OrgMembers.tsx | 4 +-- frontend/src/generated/graphql.tsx | 16 +++++----- frontend/src/graphql/orgs/fragments.graphql | 4 +-- 19 files changed, 76 insertions(+), 82 deletions(-) diff --git a/backend/apps/ecommerce/tests.py b/backend/apps/ecommerce/tests.py index a161cad1b..8846542ca 100644 --- a/backend/apps/ecommerce/tests.py +++ b/backend/apps/ecommerce/tests.py @@ -112,7 +112,7 @@ def setUp(self) -> None: MembershipFactory( user=self.staff_user, organization=self.organization, - group=self.organization.primary_group, + group=self.organization.member_group, ) self.total_quantity = 5 self.max_buyable_quantity = 2 diff --git a/backend/apps/forms/signals.py b/backend/apps/forms/signals.py index d94907b67..ffe107665 100644 --- a/backend/apps/forms/signals.py +++ b/backend/apps/forms/signals.py @@ -9,6 +9,6 @@ def handle_new_form(sender, instance: Form, created: bool, **kwargs) -> None: if created: perms = ["forms.manage_form", "forms.change_form", "forms.delete_form"] - group = instance.organization.hr_group.group + group = instance.organization.admin_group.group for perm in perms: assign_perm(perm, group, instance) diff --git a/backend/apps/forms/tests.py b/backend/apps/forms/tests.py index b079384a2..8090061b7 100644 --- a/backend/apps/forms/tests.py +++ b/backend/apps/forms/tests.py @@ -31,7 +31,7 @@ def setUp(self) -> None: MembershipFactory( user=self.authorized_user, organization=self.organization, - group=self.organization.hr_group, + group=self.organization.admin_group, ) # Create the form diff --git a/backend/apps/organizations/migrations/0024_auto_20210422_2020.py b/backend/apps/organizations/migrations/0024_auto_20210422_2020.py index e7e688a03..2a57cdb09 100644 --- a/backend/apps/organizations/migrations/0024_auto_20210422_2020.py +++ b/backend/apps/organizations/migrations/0024_auto_20210422_2020.py @@ -23,7 +23,7 @@ class Migration(migrations.Migration): ), migrations.AddField( model_name="organization", - name="primary_group", + name="member_group", field=models.OneToOneField( on_delete=django.db.models.deletion.CASCADE, to="permissions.responsiblegroup", null=True ), diff --git a/backend/apps/organizations/migrations/0025_auto_20210426_1735.py b/backend/apps/organizations/migrations/0025_auto_20210426_1735.py index 2562b82a2..e9021674e 100644 --- a/backend/apps/organizations/migrations/0025_auto_20210426_1735.py +++ b/backend/apps/organizations/migrations/0025_auto_20210426_1735.py @@ -3,16 +3,16 @@ from django.db import migrations -def set_primary_groups(apps, schema_editor): +def set_member_groups(apps, schema_editor): Organization = apps.get_model("organizations", "Organization") ResponsibleGroup = apps.get_model("permissions", "ResponsibleGroup") for organization in Organization.objects.all(): - if organization.primary_group is None: + if organization.member_group is None: rg = ResponsibleGroup.objects.create( name=organization.name, description=f"Medlemmer av {organization.name}" ) - organization.primary_group = rg + organization.member_group = rg organization.save() @@ -22,4 +22,4 @@ class Migration(migrations.Migration): ("organizations", "0024_auto_20210422_2020"), ] - operations = [migrations.RunPython(set_primary_groups, lambda apps, schema_editor: None)] + operations = [migrations.RunPython(set_member_groups, lambda apps, schema_editor: None)] diff --git a/backend/apps/organizations/migrations/0026_auto_20210426_1802.py b/backend/apps/organizations/migrations/0026_auto_20210426_1802.py index 7fa684902..160d571e3 100644 --- a/backend/apps/organizations/migrations/0026_auto_20210426_1802.py +++ b/backend/apps/organizations/migrations/0026_auto_20210426_1802.py @@ -4,23 +4,23 @@ import django.db.models.deletion -def set_primary_groups(apps, schema_editor): +def set_member_groups(apps, schema_editor): Organization = apps.get_model("organizations", "Organization") ResponsibleGroup = apps.get_model("permissions", "ResponsibleGroup") for organization in Organization.objects.all(): created = False - if organization.primary_group is None: - primary_group = ResponsibleGroup.objects.create( + if organization.member_group is None: + member_group = ResponsibleGroup.objects.create( name=organization.name, description=f"Medlemmer av {organization.name}" ) - organization.primary_group = primary_group + organization.member_group = member_group created = True - if organization.hr_group is None: - hr_group = ResponsibleGroup.objects.create( + if organization.admin_group is None: + admin_group = ResponsibleGroup.objects.create( name="HR", description=f"HR-gruppen til {organization.name}. Tillatelser for å se og behandle søknader." ) - organization.hr_group = hr_group + organization.admin_group = admin_group created = True if created: @@ -41,7 +41,7 @@ class Migration(migrations.Migration): ), migrations.AddField( model_name="organization", - name="hr_group", + name="admin_group", field=models.OneToOneField( null=True, on_delete=django.db.models.deletion.CASCADE, @@ -51,12 +51,12 @@ class Migration(migrations.Migration): ), migrations.AlterField( model_name="organization", - name="primary_group", + name="member_group", field=models.OneToOneField( on_delete=django.db.models.deletion.CASCADE, related_name="organization", to="permissions.responsiblegroup", ), ), - migrations.RunPython(set_primary_groups, lambda apps, schema_editor: None), + migrations.RunPython(set_member_groups, lambda apps, schema_editor: None), ] diff --git a/backend/apps/organizations/migrations/0028_auto_20210426_1948.py b/backend/apps/organizations/migrations/0028_auto_20210426_1948.py index b80ab6d96..46d82a781 100644 --- a/backend/apps/organizations/migrations/0028_auto_20210426_1948.py +++ b/backend/apps/organizations/migrations/0028_auto_20210426_1948.py @@ -3,11 +3,11 @@ from django.db import migrations -def add_existing_members_to_primary_group(apps, schema_editor): +def add_existing_members_to_member_group(apps, schema_editor): Membership = apps.get_model("organizations", "Membership") for membership in Membership.objects.all(): - group = membership.organization.primary_group.group + group = membership.organization.member_group.group user = membership.user user.groups.add(group) @@ -18,4 +18,4 @@ class Migration(migrations.Migration): ("organizations", "0027_auto_20210426_1843"), ] - operations = [migrations.RunPython(add_existing_members_to_primary_group, lambda apps, schema_editor: None)] + operations = [migrations.RunPython(add_existing_members_to_member_group, lambda apps, schema_editor: None)] diff --git a/backend/apps/organizations/migrations/0029_auto_20210426_2129.py b/backend/apps/organizations/migrations/0029_auto_20210426_2129.py index fda4ea409..556502abc 100644 --- a/backend/apps/organizations/migrations/0029_auto_20210426_2129.py +++ b/backend/apps/organizations/migrations/0029_auto_20210426_2129.py @@ -14,7 +14,7 @@ class Migration(migrations.Migration): operations = [ migrations.AlterField( model_name="organization", - name="hr_group", + name="admin_group", field=models.OneToOneField( null=True, on_delete=django.db.models.deletion.DO_NOTHING, @@ -24,7 +24,7 @@ class Migration(migrations.Migration): ), migrations.AlterField( model_name="organization", - name="primary_group", + name="member_group", field=models.OneToOneField( on_delete=django.db.models.deletion.DO_NOTHING, related_name="organization", diff --git a/backend/apps/organizations/migrations/0030_auto_20210426_2129.py b/backend/apps/organizations/migrations/0030_auto_20210426_2129.py index 5071b49c0..1f70fb462 100644 --- a/backend/apps/organizations/migrations/0030_auto_20210426_2129.py +++ b/backend/apps/organizations/migrations/0030_auto_20210426_2129.py @@ -14,7 +14,7 @@ class Migration(migrations.Migration): operations = [ migrations.AlterField( model_name="organization", - name="hr_group", + name="admin_group", field=models.OneToOneField( on_delete=django.db.models.deletion.DO_NOTHING, related_name="hr_organization", diff --git a/backend/apps/organizations/migrations/0031_auto_20210824_1446.py b/backend/apps/organizations/migrations/0031_auto_20210824_1446.py index f7f3ffb2c..50e2a5158 100644 --- a/backend/apps/organizations/migrations/0031_auto_20210824_1446.py +++ b/backend/apps/organizations/migrations/0031_auto_20210824_1446.py @@ -14,18 +14,18 @@ class Migration(migrations.Migration): operations = [ migrations.AlterField( model_name="organization", - name="hr_group", + name="admin_group", field=models.OneToOneField( blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, - related_name="hr_organization", + related_name="admin_organization", to="permissions.responsiblegroup", ), ), migrations.AlterField( model_name="organization", - name="primary_group", + name="member_group", field=models.OneToOneField( blank=True, null=True, diff --git a/backend/apps/organizations/migrations/0032_auto_20210824_1457.py b/backend/apps/organizations/migrations/0032_auto_20210824_1457.py index 7c76740af..36ac49eec 100644 --- a/backend/apps/organizations/migrations/0032_auto_20210824_1457.py +++ b/backend/apps/organizations/migrations/0032_auto_20210824_1457.py @@ -13,10 +13,10 @@ class Migration(migrations.Migration): operations = [ migrations.RemoveField( model_name="organization", - name="hr_group", + name="admin_group", ), migrations.RemoveField( model_name="organization", - name="primary_group", + name="member_group", ), ] diff --git a/backend/apps/organizations/signals.py b/backend/apps/organizations/signals.py index 3dd14f99a..3c477e5dc 100644 --- a/backend/apps/organizations/signals.py +++ b/backend/apps/organizations/signals.py @@ -19,7 +19,7 @@ @receiver(post_save, sender=Membership) def handle_new_member(instance: Membership, **kwargs): optional_group: Optional[ResponsibleGroup] = instance.group - group: Group = instance.organization.primary_group.group + group: Group = instance.organization.member_group.group org_group: Group = Group.objects.get(name=ORGANIZATION) user = instance.user user.groups.add(org_group) @@ -31,7 +31,7 @@ def handle_new_member(instance: Membership, **kwargs): @receiver(pre_delete, sender=Membership) def handle_removed_member(instance: Membership, **kwargs): - group: Group = instance.organization.primary_group.group + group: Group = instance.organization.member_group.group org_group: Group = Group.objects.get(name=ORGANIZATION) user = instance.user if group: diff --git a/backend/apps/organizations/types.py b/backend/apps/organizations/types.py index 0afeb43cd..2c9f10b4e 100644 --- a/backend/apps/organizations/types.py +++ b/backend/apps/organizations/types.py @@ -14,8 +14,8 @@ class OrganizationType(DjangoObjectType): absolute_slug = graphene.String() listings = graphene.List(NonNull(ListingType)) - primary_group = graphene.Field(source="primary_group", type=ResponsibleGroupType) - hr_group = graphene.Field(source="hr_group", type=ResponsibleGroupType) + member_group = graphene.Field(source="member_group", type=ResponsibleGroupType) + admin_group = graphene.Field(source="admin_group", type=ResponsibleGroupType) class Meta: model = Organization @@ -30,8 +30,8 @@ class Meta: "users", "events", "logo_url", - "primary_group", - "hr_group", + "member_group", + "admin_group", ] @staticmethod diff --git a/backend/apps/permissions/migrations/0003_auto_20210824_1213.py b/backend/apps/permissions/migrations/0003_auto_20210824_1213.py index ad55b6550..a0f6e5250 100644 --- a/backend/apps/permissions/migrations/0003_auto_20210824_1213.py +++ b/backend/apps/permissions/migrations/0003_auto_20210824_1213.py @@ -4,7 +4,7 @@ from django.db import migrations from django.db.models.query_utils import Q -from apps.permissions.constants import PRIMARY_GROUP_NAME, HR_GROUP_NAME +from apps.permissions.constants import MEMBER_GROUP_NAME, ADMIN_GROUP_NAME if TYPE_CHECKING: from apps.organizations import models @@ -19,14 +19,14 @@ def improve_group_legibility(apps, _): responsible_group: "ResponsibleGroup" = group.responsiblegroup try: organization: "models.Organization" = Organization.objects.get( - Q(primary_group=responsible_group) | Q(hr_group=responsible_group) + Q(member_group=responsible_group) | Q(admin_group=responsible_group) ) responsible_group_name = responsible_group.name - if organization.primary_group == responsible_group: - responsible_group_name = PRIMARY_GROUP_NAME - elif organization.hr_group == responsible_group: - responsible_group_name = HR_GROUP_NAME + if organization.member_group == responsible_group: + responsible_group_name = MEMBER_GROUP_NAME + elif organization.admin_group == responsible_group: + responsible_group_name = ADMIN_GROUP_NAME if responsible_group.name != responsible_group_name: responsible_group.name = responsible_group_name responsible_group.save() @@ -50,7 +50,7 @@ def reverse_legible_group_names(apps, _): responsible_group = group.responsiblegroup try: organization = responsible_group.organization - if organization.primary_group == responsible_group: + if organization.member_group == responsible_group: responsible_group.name = organization.name responsible_group.save() except Organization.DoesNotExist: diff --git a/backend/apps/permissions/migrations/0005_auto_20210824_1446.py b/backend/apps/permissions/migrations/0005_auto_20210824_1446.py index 1e93c7960..50d86b448 100644 --- a/backend/apps/permissions/migrations/0005_auto_20210824_1446.py +++ b/backend/apps/permissions/migrations/0005_auto_20210824_1446.py @@ -3,7 +3,7 @@ from typing import TYPE_CHECKING, Type from django.db import migrations -from apps.permissions.constants import HR_TYPE, PRIMARY_TYPE +from apps.permissions.constants import ADMIN_GROUP_TYPE, MEMBER_GROUP_TYPE if TYPE_CHECKING: from apps.organizations import models as org_models @@ -15,22 +15,22 @@ def move_permission_groups_to_fk(apps, _): Organization: Type["org_models.Organization"] = apps.get_model("organizations", "Organization") for organization in Organization.objects.all(): - primary_group = organization.primary_group - hr_group = organization.hr_group + member_group = organization.member_group + admin_group = organization.admin_group - if primary_group and hr_group: - primary_group.group_type = PRIMARY_TYPE - hr_group.group_type = HR_TYPE + if member_group and admin_group: + member_group.group_type = MEMBER_GROUP_TYPE + admin_group.group_type = ADMIN_GROUP_TYPE # Name as of this migration - primary_group.temp_organization = organization - hr_group.temp_organization = organization + member_group.temp_organization = organization + admin_group.temp_organization = organization - primary_group.save() - hr_group.save() + member_group.save() + admin_group.save() - organization.primary_group = None - organization.hr_group = None + organization.member_group = None + organization.admin_group = None organization.save() # Delete orphan responsible groups @@ -43,10 +43,12 @@ def move_permission_groups_to_one_to_one_field(apps, _): organization: "org_models.Organization" for organization in Organization.objects.all(): - organization.primary_group = ResponsibleGroup.objects.get( - temp_organization=organization, group_type=PRIMARY_TYPE + organization.member_group = ResponsibleGroup.objects.get( + temp_organization=organization, group_type=MEMBER_GROUP_TYPE + ) + organization.admin_group = ResponsibleGroup.objects.get( + temp_organization=organization, group_type=ADMIN_GROUP_TYPE ) - organization.hr_group = ResponsibleGroup.objects.get(temp_organization=organization, group_type=HR_TYPE) organization.save() diff --git a/backend/schema.json b/backend/schema.json index 7ca001511..0061db6fa 100644 --- a/backend/schema.json +++ b/backend/schema.json @@ -20,11 +20,7 @@ } ], "description": "Directs the executor to include this field or fragment only when the `if` argument is true.", - "locations": [ - "FIELD", - "FRAGMENT_SPREAD", - "INLINE_FRAGMENT" - ], + "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], "name": "include" }, { @@ -45,11 +41,7 @@ } ], "description": "Directs the executor to skip this field or fragment when the `if` argument is true.", - "locations": [ - "FIELD", - "FRAGMENT_SPREAD", - "INLINE_FRAGMENT" - ], + "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], "name": "skip" } ], @@ -1581,7 +1573,7 @@ "deprecationReason": null, "description": null, "isDeprecated": false, - "name": "primaryGroup", + "name": "memberGroup", "type": { "kind": "OBJECT", "name": "ResponsibleGroupType", @@ -1593,7 +1585,7 @@ "deprecationReason": null, "description": null, "isDeprecated": false, - "name": "hrGroup", + "name": "adminGroup", "type": { "kind": "OBJECT", "name": "ResponsibleGroupType", @@ -10900,4 +10892,4 @@ ] } } -} \ No newline at end of file +} diff --git a/frontend/src/components/pages/organization/OrgMembers.tsx b/frontend/src/components/pages/organization/OrgMembers.tsx index 60bbbe27b..5b8bbdf6e 100644 --- a/frontend/src/components/pages/organization/OrgMembers.tsx +++ b/frontend/src/components/pages/organization/OrgMembers.tsx @@ -77,12 +77,12 @@ export const OrgMembers: React.FC = ({ organization }) => { {membership.user.firstName} {membership.user.lastName} - {membership?.group?.uuid == organization.hrGroup?.uuid ? "Administrator" : "Medlem"} + {membership?.group?.uuid == organization.adminGroup?.uuid ? "Administrator" : "Medlem"} @@ -81,10 +95,21 @@ export const OrgMembers: React.FC = ({ organization }) => { - - From aacf92bc55a78855f3ab4c4375f0f80ece1e1ad7 Mon Sep 17 00:00:00 2001 From: Simen Sandhaug Date: Thu, 12 Jan 2023 19:59:36 +0100 Subject: [PATCH 20/26] start on mutations --- backend/apps/organizations/mutations.py | 4 +- .../pages/organization/OrgMembers.tsx | 46 ++++++++-- frontend/src/generated/graphql.tsx | 83 +++++++++++++++++++ frontend/src/graphql/orgs/mutations.graphql | 14 ++++ 4 files changed, 140 insertions(+), 7 deletions(-) create mode 100644 frontend/src/graphql/orgs/mutations.graphql diff --git a/backend/apps/organizations/mutations.py b/backend/apps/organizations/mutations.py index 9b056f676..2b9ba5b83 100644 --- a/backend/apps/organizations/mutations.py +++ b/backend/apps/organizations/mutations.py @@ -47,7 +47,7 @@ class Arguments: id = graphene.ID(required=True) organization_data = OrganizationInput(required=False) - @permission_required("organizations.manage_organization") + @permission_required("organizations.change_organization") def mutate(self, info, id, organization_data=None): organization = Organization.objects.get(pk=id) user = info.context.user @@ -91,7 +91,7 @@ class AssignMembership(graphene.Mutation): class Arguments: membership_data = MembershipInput(required=True) - @permission_required("organizations.manage_organization", fn=get_organization_from_data) + @permission_required("organizations.change_organization", fn=get_organization_from_data) def mutate(self, _, membership_data): organization = Organization.objects.prefetch_related("permission_groups").get( pk=membership_data["organization_id"] diff --git a/frontend/src/components/pages/organization/OrgMembers.tsx b/frontend/src/components/pages/organization/OrgMembers.tsx index 0adc4ced6..6e031012d 100644 --- a/frontend/src/components/pages/organization/OrgMembers.tsx +++ b/frontend/src/components/pages/organization/OrgMembers.tsx @@ -1,4 +1,4 @@ -import { useQuery } from "@apollo/client"; +import { useMutation, useQuery } from "@apollo/client"; import { Delete, GroupAdd, AdminPanelSettings } from "@mui/icons-material"; import { Button, @@ -17,7 +17,12 @@ import { import { useState } from "react"; import { PermissionRequired } from "@/components/Auth"; -import { AdminOrganizationFragment, MembershipsDocument, MembershipType } from "@/generated/graphql"; +import { + AdminOrganizationFragment, + MembershipsDocument, + MembershipType, + AssignMembershipDocument, +} from "@/generated/graphql"; type Props = { organization: AdminOrganizationFragment; @@ -25,6 +30,10 @@ type Props = { export const OrgMembers: React.FC = ({ organization }) => { const { data, loading, error } = useQuery(MembershipsDocument, { variables: { organizationId: organization.id } }); + const [ + AssignMembership, + { data: AssignMembershipData, loading: AssignMembershipLoading, error: AssignMembershipError }, + ] = useMutation(AssignMembershipDocument); const [userInput, setUserInput] = useState(""); @@ -36,14 +45,41 @@ export const OrgMembers: React.FC = ({ organization }) => { const handleAddMembership = () => { //Legg til funksjonalitet for å legge til bruker ved brukernavn - setUserInput(""); //Funker men oppdaterer ikke siden? + console.log("Legger til " + userInput); + setUserInput(""); }; const handleGroupChange = (membership: MembershipType | any) => { if (!membership) return; const role = membership?.group?.uuid == organization.adminGroup?.uuid ? "ADMIN" : "MEMBER"; - if (role == "ADMIN") console.log("Demoterer" + membership.user.firstName + " " + membership.user.lastName); - if (role == "MEMBER") console.log("Promoterer" + membership.user.firstName + " " + membership.user.lastName); + if (role == "ADMIN") console.log("Demoterer " + membership.user.firstName + " " + membership.user.lastName); + if (role == "MEMBER") console.log("Promoterer " + membership.user.firstName + " " + membership.user.lastName); + + if (role == "ADMIN") { + //Legg til funksjonalitet for å demote bruker + AssignMembership({ + variables: { + membershipData: { + organizationId: organization.id, + userId: membership.user.id, + groupId: organization?.memberGroup?.uuid, + }, + }, + }); + } + + if (role == "MEMBER") { + //Legg til funksjonalitet for å promote bruker + AssignMembership({ + variables: { + membershipData: { + organizationId: organization.id, + userId: membership.user.id, + groupId: organization?.adminGroup?.uuid, + }, + }, + }); + } //Legg til funksjonalitet for å endre gruppe }; diff --git a/frontend/src/generated/graphql.tsx b/frontend/src/generated/graphql.tsx index 1024cbece..166781721 100644 --- a/frontend/src/generated/graphql.tsx +++ b/frontend/src/generated/graphql.tsx @@ -3005,6 +3005,24 @@ export type MembershipFragment = { group?: { __typename?: "ResponsibleGroupType"; uuid: string } | null; }; +export type AssignMembershipMutationVariables = Exact<{ + membershipData: MembershipInput; +}>; + +export type AssignMembershipMutation = { + __typename?: "Mutations"; + assignMembership?: { + __typename?: "AssignMembership"; + ok?: boolean | null; + membership?: { + __typename?: "MembershipType"; + id: string; + organization: { __typename?: "OrganizationType"; id: string }; + group?: { __typename?: "ResponsibleGroupType"; uuid: string } | null; + } | null; + } | null; +}; + export type AdminOrganizationQueryVariables = Exact<{ orgId: Scalars["ID"]; }>; @@ -6639,6 +6657,71 @@ export const UserOrganizationsDocument = { ...ListingOrganizationFragmentDoc.definitions, ], } as unknown as DocumentNode; +export const AssignMembershipDocument = { + kind: "Document", + definitions: [ + { + kind: "OperationDefinition", + operation: "mutation", + name: { kind: "Name", value: "assignMembership" }, + variableDefinitions: [ + { + kind: "VariableDefinition", + variable: { kind: "Variable", name: { kind: "Name", value: "membershipData" } }, + type: { kind: "NonNullType", type: { kind: "NamedType", name: { kind: "Name", value: "MembershipInput" } } }, + }, + ], + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "assignMembership" }, + arguments: [ + { + kind: "Argument", + name: { kind: "Name", value: "membershipData" }, + value: { kind: "Variable", name: { kind: "Name", value: "membershipData" } }, + }, + ], + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "membership" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { kind: "Field", name: { kind: "Name", value: "id" } }, + { + kind: "Field", + name: { kind: "Name", value: "organization" }, + selectionSet: { + kind: "SelectionSet", + selections: [{ kind: "Field", name: { kind: "Name", value: "id" } }], + }, + }, + { + kind: "Field", + name: { kind: "Name", value: "group" }, + selectionSet: { + kind: "SelectionSet", + selections: [{ kind: "Field", name: { kind: "Name", value: "uuid" } }], + }, + }, + ], + }, + }, + { kind: "Field", name: { kind: "Name", value: "ok" } }, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode; export const AdminOrganizationDocument = { kind: "Document", definitions: [ diff --git a/frontend/src/graphql/orgs/mutations.graphql b/frontend/src/graphql/orgs/mutations.graphql new file mode 100644 index 000000000..ff0237a0a --- /dev/null +++ b/frontend/src/graphql/orgs/mutations.graphql @@ -0,0 +1,14 @@ +mutation assignMembership($membershipData: MembershipInput!) { + assignMembership(membershipData: $membershipData) { + membership { + id + organization { + id + } + group { + uuid + } + } + ok + } +} From 1415d843abd13f0be884fd1e5848cf84f4fae393 Mon Sep 17 00:00:00 2001 From: Simen Sandhaug Date: Mon, 30 Jan 2023 18:27:41 +0100 Subject: [PATCH 21/26] add removeMembership mutation --- backend/apps/organizations/mutations.py | 14 +++++++++----- backend/apps/organizations/schema.py | 2 ++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/backend/apps/organizations/mutations.py b/backend/apps/organizations/mutations.py index 2b9ba5b83..c809cba74 100644 --- a/backend/apps/organizations/mutations.py +++ b/backend/apps/organizations/mutations.py @@ -2,7 +2,6 @@ from django.utils.text import slugify from decorators import permission_required -from apps.users.types import UserType from apps.permissions.models import ResponsibleGroup from apps.organizations import permissions as perms @@ -112,11 +111,16 @@ def mutate(self, _, membership_data): class RemoveMembership(graphene.Mutation): - removed_member = graphene.Field(UserType) + membership = graphene.Field(MembershipType) ok = graphene.Boolean() class Arguments: - member_id = graphene.ID() + id = graphene.ID() + + @permission_required("organizations.manage_organization") + def mutate(self, info, id): + membership = Membership.objects.get(pk=id) + membership.delete() - def mutate(self, info, member_id): - raise NotImplementedError("Denne funksjonaliteten er ikke implementert.") + ok = True + return RemoveMembership(ok=ok) diff --git a/backend/apps/organizations/schema.py b/backend/apps/organizations/schema.py index 590470737..676e085a1 100644 --- a/backend/apps/organizations/schema.py +++ b/backend/apps/organizations/schema.py @@ -3,6 +3,7 @@ from .mutations import ( AssignMembership, + RemoveMembership, CreateOrganization, DeleteOrganization, UpdateOrganization, @@ -17,6 +18,7 @@ class OrganizationMutations(graphene.ObjectType): delete_organization = DeleteOrganization.Field() assign_membership = AssignMembership.Field() + remove_membership = RemoveMembership.Field() class OrganizationQueries(graphene.ObjectType, OrganizationResolvers, MembershipResolvers): From 6238bd4f2036d24e1c9f871294aa341d8c39924d Mon Sep 17 00:00:00 2001 From: Simen Sandhaug Date: Mon, 30 Jan 2023 18:44:43 +0100 Subject: [PATCH 22/26] fix unused desctructured variables --- .../src/components/pages/organization/OrgMembers.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/pages/organization/OrgMembers.tsx b/frontend/src/components/pages/organization/OrgMembers.tsx index 6e031012d..542334662 100644 --- a/frontend/src/components/pages/organization/OrgMembers.tsx +++ b/frontend/src/components/pages/organization/OrgMembers.tsx @@ -32,7 +32,7 @@ export const OrgMembers: React.FC = ({ organization }) => { const { data, loading, error } = useQuery(MembershipsDocument, { variables: { organizationId: organization.id } }); const [ AssignMembership, - { data: AssignMembershipData, loading: AssignMembershipLoading, error: AssignMembershipError }, + { data: assignMembershipData, loading: assignMembershipLoading, error: assignMembershipError }, ] = useMutation(AssignMembershipDocument); const [userInput, setUserInput] = useState(""); @@ -65,6 +65,9 @@ export const OrgMembers: React.FC = ({ organization }) => { groupId: organization?.memberGroup?.uuid, }, }, + }).then(() => { + console.log("Demoterer " + membership.user.firstName + " " + membership.user.lastName); + console.log(assignMembershipData); }); } @@ -78,8 +81,14 @@ export const OrgMembers: React.FC = ({ organization }) => { groupId: organization?.adminGroup?.uuid, }, }, + }).then(() => { + console.log("Promoterer " + membership.user.firstName + " " + membership.user.lastName); + console.log(assignMembershipData); }); } + + if (assignMembershipError) return

Error

; + if (assignMembershipLoading) return ; //Legg til funksjonalitet for å endre gruppe }; From 2b4317801bb327426aefa7eab1b7190abb6511fd Mon Sep 17 00:00:00 2001 From: Simen Sandhaug Date: Mon, 30 Jan 2023 19:12:28 +0100 Subject: [PATCH 23/26] fix graphql schema --- .../pages/organization/OrgMembers.tsx | 25 ++++---- frontend/src/generated/graphql.tsx | 59 +++++++++++++++++++ frontend/src/graphql/orgs/mutations.graphql | 6 ++ 3 files changed, 75 insertions(+), 15 deletions(-) diff --git a/frontend/src/components/pages/organization/OrgMembers.tsx b/frontend/src/components/pages/organization/OrgMembers.tsx index 542334662..587f58889 100644 --- a/frontend/src/components/pages/organization/OrgMembers.tsx +++ b/frontend/src/components/pages/organization/OrgMembers.tsx @@ -22,6 +22,7 @@ import { MembershipsDocument, MembershipType, AssignMembershipDocument, + DeleteMembershipDocument, } from "@/generated/graphql"; type Props = { @@ -30,10 +31,8 @@ type Props = { export const OrgMembers: React.FC = ({ organization }) => { const { data, loading, error } = useQuery(MembershipsDocument, { variables: { organizationId: organization.id } }); - const [ - AssignMembership, - { data: assignMembershipData, loading: assignMembershipLoading, error: assignMembershipError }, - ] = useMutation(AssignMembershipDocument); + const [AssignMembership] = useMutation(AssignMembershipDocument); + const [DeleteMembership] = useMutation(DeleteMembershipDocument); const [userInput, setUserInput] = useState(""); @@ -65,9 +64,6 @@ export const OrgMembers: React.FC = ({ organization }) => { groupId: organization?.memberGroup?.uuid, }, }, - }).then(() => { - console.log("Demoterer " + membership.user.firstName + " " + membership.user.lastName); - console.log(assignMembershipData); }); } @@ -81,21 +77,20 @@ export const OrgMembers: React.FC = ({ organization }) => { groupId: organization?.adminGroup?.uuid, }, }, - }).then(() => { - console.log("Promoterer " + membership.user.firstName + " " + membership.user.lastName); - console.log(assignMembershipData); }); } - - if (assignMembershipError) return

Error

; - if (assignMembershipLoading) return ; - //Legg til funksjonalitet for å endre gruppe }; const handleRemoveMembership = (membership: MembershipType | any) => { if (!membership) return; + + DeleteMembership({ + variables: { + membershipId: membership.id, + }, + }); + console.log("Fjerner " + membership.user.firstName + " " + membership.user.lastName); - //Legg til funksjonalitet for å fjerne medlem }; return ( diff --git a/frontend/src/generated/graphql.tsx b/frontend/src/generated/graphql.tsx index 166781721..3b38c4232 100644 --- a/frontend/src/generated/graphql.tsx +++ b/frontend/src/generated/graphql.tsx @@ -98,6 +98,8 @@ export enum ArchiveDocumentTypeDoc { ForeningensLover = "FORENINGENS_LOVER", /** Generalforsamling */ Generalforsamling = "GENERALFORSAMLING", + /** Januscript */ + Januscript = "JANUSCRIPT", /** Støtte fra HS */ StotteFraHs = "STOTTE_FRA_HS", /** Utveksling */ @@ -405,6 +407,12 @@ export type DeleteListing = { ok?: Maybe; }; +export type DeleteMembership = { + __typename?: "DeleteMembership"; + membership?: Maybe; + ok?: Maybe; +}; + export type DeleteOrganization = { __typename?: "DeleteOrganization"; ok?: Maybe; @@ -600,6 +608,7 @@ export type Mutations = { deleteForm?: Maybe; /** Deletes the listing with the given ID */ deleteListing?: Maybe; + deleteMembership?: Maybe; deleteOrganization?: Maybe; deleteQuestion?: Maybe; /** @@ -758,6 +767,10 @@ export type MutationsDeleteListingArgs = { id?: InputMaybe; }; +export type MutationsDeleteMembershipArgs = { + membershipId?: InputMaybe; +}; + export type MutationsDeleteOrganizationArgs = { id: Scalars["ID"]; }; @@ -3023,6 +3036,15 @@ export type AssignMembershipMutation = { } | null; }; +export type DeleteMembershipMutationVariables = Exact<{ + membershipId: Scalars["ID"]; +}>; + +export type DeleteMembershipMutation = { + __typename?: "Mutations"; + deleteMembership?: { __typename?: "DeleteMembership"; ok?: boolean | null } | null; +}; + export type AdminOrganizationQueryVariables = Exact<{ orgId: Scalars["ID"]; }>; @@ -6722,6 +6744,43 @@ export const AssignMembershipDocument = { }, ], } as unknown as DocumentNode; +export const DeleteMembershipDocument = { + kind: "Document", + definitions: [ + { + kind: "OperationDefinition", + operation: "mutation", + name: { kind: "Name", value: "deleteMembership" }, + variableDefinitions: [ + { + kind: "VariableDefinition", + variable: { kind: "Variable", name: { kind: "Name", value: "membershipId" } }, + type: { kind: "NonNullType", type: { kind: "NamedType", name: { kind: "Name", value: "ID" } } }, + }, + ], + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "deleteMembership" }, + arguments: [ + { + kind: "Argument", + name: { kind: "Name", value: "membershipId" }, + value: { kind: "Variable", name: { kind: "Name", value: "membershipId" } }, + }, + ], + selectionSet: { + kind: "SelectionSet", + selections: [{ kind: "Field", name: { kind: "Name", value: "ok" } }], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode; export const AdminOrganizationDocument = { kind: "Document", definitions: [ diff --git a/frontend/src/graphql/orgs/mutations.graphql b/frontend/src/graphql/orgs/mutations.graphql index ff0237a0a..adda4ead8 100644 --- a/frontend/src/graphql/orgs/mutations.graphql +++ b/frontend/src/graphql/orgs/mutations.graphql @@ -12,3 +12,9 @@ mutation assignMembership($membershipData: MembershipInput!) { ok } } + +mutation deleteMembership($membershipId: ID!) { + deleteMembership(membershipId: $membershipId) { + ok + } +} From ca93d1a50c59fd4f06ebfe16d0118cc76c9ff82d Mon Sep 17 00:00:00 2001 From: Simen Sandhaug Date: Mon, 30 Jan 2023 20:09:42 +0100 Subject: [PATCH 24/26] Change role and delete membership fixed --- backend/apps/organizations/mutations.py | 34 ++++- backend/apps/organizations/schema.py | 6 +- backend/schema.json | 171 +++++++++++++++++++++++- frontend/src/generated/graphql.tsx | 122 +++++++++++++---- 4 files changed, 298 insertions(+), 35 deletions(-) diff --git a/backend/apps/organizations/mutations.py b/backend/apps/organizations/mutations.py index c809cba74..bcfed3915 100644 --- a/backend/apps/organizations/mutations.py +++ b/backend/apps/organizations/mutations.py @@ -90,7 +90,7 @@ class AssignMembership(graphene.Mutation): class Arguments: membership_data = MembershipInput(required=True) - @permission_required("organizations.change_organization", fn=get_organization_from_data) + @permission_required("organizations.manage_organization", fn=get_organization_from_data) def mutate(self, _, membership_data): organization = Organization.objects.prefetch_related("permission_groups").get( pk=membership_data["organization_id"] @@ -110,17 +110,39 @@ def mutate(self, _, membership_data): return AssignMembership(membership=membership, ok=True) -class RemoveMembership(graphene.Mutation): +class DeleteMembership(graphene.Mutation): membership = graphene.Field(MembershipType) ok = graphene.Boolean() class Arguments: - id = graphene.ID() + membership_id = graphene.ID() @permission_required("organizations.manage_organization") - def mutate(self, info, id): - membership = Membership.objects.get(pk=id) + def mutate(self, info, membership_id): + membership = Membership.objects.get(pk=membership_id) membership.delete() ok = True - return RemoveMembership(ok=ok) + return DeleteMembership(ok=ok) + + +class ChangeMembershipInput(graphene.InputObjectType): + membership_id = graphene.ID() + group_id = graphene.ID() + + +class ChangeMembership(graphene.Mutation): + membership = graphene.Field(MembershipType) + ok = graphene.Boolean() + + class Arguments: + membership_data = ChangeMembershipInput(required=True) + + @permission_required("organizations.manage_organization") + def mutate(self, info, membership_data): + membership = Membership.objects.get(pk=membership_data["membership_id"]) + membership.group_id = membership_data["group_id"] + membership.save() + + ok = True + return ChangeMembership(membership=membership, ok=ok) diff --git a/backend/apps/organizations/schema.py b/backend/apps/organizations/schema.py index 676e085a1..011b371cf 100644 --- a/backend/apps/organizations/schema.py +++ b/backend/apps/organizations/schema.py @@ -3,10 +3,11 @@ from .mutations import ( AssignMembership, - RemoveMembership, + DeleteMembership, CreateOrganization, DeleteOrganization, UpdateOrganization, + ChangeMembership, ) from .resolvers import MembershipResolvers, OrganizationResolvers from .types import MembershipType, OrganizationType @@ -18,7 +19,8 @@ class OrganizationMutations(graphene.ObjectType): delete_organization = DeleteOrganization.Field() assign_membership = AssignMembership.Field() - remove_membership = RemoveMembership.Field() + delete_membership = DeleteMembership.Field() + change_membership = ChangeMembership.Field() class OrganizationQueries(graphene.ObjectType, OrganizationResolvers, MembershipResolvers): diff --git a/backend/schema.json b/backend/schema.json index 0061db6fa..8d69998b9 100644 --- a/backend/schema.json +++ b/backend/schema.json @@ -20,7 +20,11 @@ } ], "description": "Directs the executor to include this field or fragment only when the `if` argument is true.", - "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], + "locations": [ + "FIELD", + "FRAGMENT_SPREAD", + "INLINE_FRAGMENT" + ], "name": "include" }, { @@ -41,7 +45,11 @@ } ], "description": "Directs the executor to skip this field or fragment when the `if` argument is true.", - "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], + "locations": [ + "FIELD", + "FRAGMENT_SPREAD", + "INLINE_FRAGMENT" + ], "name": "skip" } ], @@ -5001,6 +5009,12 @@ "description": "Annet", "isDeprecated": false, "name": "ANNET" + }, + { + "deprecationReason": null, + "description": "Januscript", + "isDeprecated": false, + "name": "JANUSCRIPT" } ], "fields": null, @@ -5854,6 +5868,56 @@ "ofType": null } }, + { + "args": [ + { + "defaultValue": null, + "description": null, + "name": "membershipId", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } + ], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "deleteMembership", + "type": { + "kind": "OBJECT", + "name": "DeleteMembership", + "ofType": null + } + }, + { + "args": [ + { + "defaultValue": null, + "description": null, + "name": "membershipData", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "ChangeMembershipInput", + "ofType": null + } + } + } + ], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "changeMembership", + "type": { + "kind": "OBJECT", + "name": "ChangeMembership", + "ofType": null + } + }, { "args": [ { @@ -8275,6 +8339,107 @@ "name": "MembershipInput", "possibleTypes": null }, + { + "description": null, + "enumValues": null, + "fields": [ + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "membership", + "type": { + "kind": "OBJECT", + "name": "MembershipType", + "ofType": null + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "ok", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + } + ], + "inputFields": null, + "interfaces": [], + "kind": "OBJECT", + "name": "DeleteMembership", + "possibleTypes": null + }, + { + "description": null, + "enumValues": null, + "fields": [ + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "membership", + "type": { + "kind": "OBJECT", + "name": "MembershipType", + "ofType": null + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "ok", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + } + ], + "inputFields": null, + "interfaces": [], + "kind": "OBJECT", + "name": "ChangeMembership", + "possibleTypes": null + }, + { + "description": null, + "enumValues": null, + "fields": null, + "inputFields": [ + { + "defaultValue": null, + "description": null, + "name": "membershipId", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + { + "defaultValue": null, + "description": null, + "name": "groupId", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } + ], + "interfaces": null, + "kind": "INPUT_OBJECT", + "name": "ChangeMembershipInput", + "possibleTypes": null + }, { "description": "Add a new booking to the database", "enumValues": null, @@ -10892,4 +11057,4 @@ ] } } -} +} \ No newline at end of file diff --git a/frontend/src/generated/graphql.tsx b/frontend/src/generated/graphql.tsx index 3b38c4232..9bd86538e 100644 --- a/frontend/src/generated/graphql.tsx +++ b/frontend/src/generated/graphql.tsx @@ -212,6 +212,17 @@ export type CategoryType = { name: Scalars["String"]; }; +export type ChangeMembership = { + __typename?: "ChangeMembership"; + membership?: Maybe; + ok?: Maybe; +}; + +export type ChangeMembershipInput = { + groupId?: InputMaybe; + membershipId?: InputMaybe; +}; + export type CreateArchiveDocument = { __typename?: "CreateArchiveDocument"; arhiveDocument?: Maybe; @@ -578,6 +589,7 @@ export type Mutations = { assignMembership?: Maybe; attemptCapturePayment?: Maybe; authUser: AuthUser; + changeMembership?: Maybe; createArchivedocument?: Maybe; createBlog?: Maybe; createBlogPost?: Maybe; @@ -667,6 +679,10 @@ export type MutationsAuthUserArgs = { code: Scalars["String"]; }; +export type MutationsChangeMembershipArgs = { + membershipData: ChangeMembershipInput; +}; + export type MutationsCreateArchivedocumentArgs = { date?: InputMaybe; fileLocation?: InputMaybe; @@ -3014,7 +3030,7 @@ export type OrgAdminListingFragment = { __typename?: "ListingType"; id: string; export type MembershipFragment = { __typename?: "MembershipType"; id: string; - user: { __typename?: "UserType"; firstName: string; lastName: string }; + user: { __typename?: "UserType"; id: string; firstName: string; lastName: string }; group?: { __typename?: "ResponsibleGroupType"; uuid: string } | null; }; @@ -3045,6 +3061,23 @@ export type DeleteMembershipMutation = { deleteMembership?: { __typename?: "DeleteMembership"; ok?: boolean | null } | null; }; +export type ChangeMembershipMutationVariables = Exact<{ + membershipData: ChangeMembershipInput; +}>; + +export type ChangeMembershipMutation = { + __typename?: "Mutations"; + changeMembership?: { + __typename?: "ChangeMembership"; + ok?: boolean | null; + membership?: { + __typename?: "MembershipType"; + id: string; + group?: { __typename?: "ResponsibleGroupType"; uuid: string } | null; + } | null; + } | null; +}; + export type AdminOrganizationQueryVariables = Exact<{ orgId: Scalars["ID"]; }>; @@ -3080,7 +3113,7 @@ export type MembershipsQuery = { memberships?: Array<{ __typename?: "MembershipType"; id: string; - user: { __typename?: "UserType"; firstName: string; lastName: string }; + user: { __typename?: "UserType"; id: string; firstName: string; lastName: string }; group?: { __typename?: "ResponsibleGroupType"; uuid: string } | null; }> | null; }; @@ -4297,6 +4330,7 @@ export const MembershipFragmentDoc = { selectionSet: { kind: "SelectionSet", selections: [ + { kind: "Field", name: { kind: "Name", value: "id" } }, { kind: "Field", name: { kind: "Name", value: "firstName" } }, { kind: "Field", name: { kind: "Name", value: "lastName" } }, ], @@ -6781,6 +6815,66 @@ export const DeleteMembershipDocument = { }, ], } as unknown as DocumentNode; +export const ChangeMembershipDocument = { + kind: "Document", + definitions: [ + { + kind: "OperationDefinition", + operation: "mutation", + name: { kind: "Name", value: "changeMembership" }, + variableDefinitions: [ + { + kind: "VariableDefinition", + variable: { kind: "Variable", name: { kind: "Name", value: "membershipData" } }, + type: { + kind: "NonNullType", + type: { kind: "NamedType", name: { kind: "Name", value: "ChangeMembershipInput" } }, + }, + }, + ], + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "changeMembership" }, + arguments: [ + { + kind: "Argument", + name: { kind: "Name", value: "membershipData" }, + value: { kind: "Variable", name: { kind: "Name", value: "membershipData" } }, + }, + ], + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "membership" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { kind: "Field", name: { kind: "Name", value: "id" } }, + { + kind: "Field", + name: { kind: "Name", value: "group" }, + selectionSet: { + kind: "SelectionSet", + selections: [{ kind: "Field", name: { kind: "Name", value: "uuid" } }], + }, + }, + ], + }, + }, + { kind: "Field", name: { kind: "Name", value: "ok" } }, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode; export const AdminOrganizationDocument = { kind: "Document", definitions: [ @@ -6848,33 +6942,13 @@ export const MembershipsDocument = { ], selectionSet: { kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "id" } }, - { - kind: "Field", - name: { kind: "Name", value: "user" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "firstName" } }, - { kind: "Field", name: { kind: "Name", value: "lastName" } }, - ], - }, - }, - { - kind: "Field", - name: { kind: "Name", value: "group" }, - selectionSet: { - kind: "SelectionSet", - selections: [{ kind: "Field", name: { kind: "Name", value: "uuid" } }], - }, - }, - ], + selections: [{ kind: "FragmentSpread", name: { kind: "Name", value: "Membership" } }], }, }, ], }, }, + ...MembershipFragmentDoc.definitions, ], } as unknown as DocumentNode; export const HasPermissionDocument = { From 1e2b663a39c809e4929386533d9bbd482a28a3e6 Mon Sep 17 00:00:00 2001 From: Simen Sandhaug Date: Thu, 2 Feb 2023 16:47:37 +0100 Subject: [PATCH 25/26] add membership_with_username mutation --- backend/apps/organizations/mutations.py | 39 +++++++ backend/apps/organizations/schema.py | 2 + backend/schema.json | 103 ++++++++++++++++++ .../pages/organization/OrgMembers.tsx | 47 +++++--- frontend/src/generated/graphql.tsx | 103 ++++++++++++++++++ frontend/src/graphql/orgs/fragments.graphql | 1 + frontend/src/graphql/orgs/mutations.graphql | 27 +++++ frontend/src/graphql/orgs/queries.graphql | 9 +- 8 files changed, 307 insertions(+), 24 deletions(-) diff --git a/backend/apps/organizations/mutations.py b/backend/apps/organizations/mutations.py index bcfed3915..f8df8287e 100644 --- a/backend/apps/organizations/mutations.py +++ b/backend/apps/organizations/mutations.py @@ -7,6 +7,7 @@ from apps.organizations import permissions as perms from apps.organizations.models import Membership, Organization from apps.organizations.types import MembershipType, OrganizationType +from apps.users.models import User def get_organization_from_data(*_, membership_data, **kwargs) -> Organization: @@ -110,6 +111,44 @@ def mutate(self, _, membership_data): return AssignMembership(membership=membership, ok=True) +class MembershipInputWithUsername(graphene.InputObjectType): + username = graphene.String() + organization_id = graphene.ID() + group_id = graphene.ID() + + +class AssignMembershipWithUsername(graphene.Mutation): + membership = graphene.Field(MembershipType) + ok = graphene.Boolean() + + class Arguments: + membership_data = MembershipInputWithUsername(required=True) + + @permission_required("organizations.manage_organization", fn=get_organization_from_data) + def mutate(self, _, membership_data): + organization = Organization.objects.prefetch_related("permission_groups").get( + pk=membership_data["organization_id"] + ) + + try: + group = organization.permission_groups.get(pk=membership_data.get("group_id")) + except ResponsibleGroup.DoesNotExist: + return AssignMembershipWithUsername(membership=None, ok=False) + + try: + user_id = User.objects.get(username=membership_data["username"]).id + except User.DoesNotExist: + return AssignMembershipWithUsername(membership=None, ok=False) + + membership = Membership( + organization_id=membership_data["organization_id"], + user_id=user_id, + group=group, + ) + membership.save() + return AssignMembershipWithUsername(membership=membership, ok=True) + + class DeleteMembership(graphene.Mutation): membership = graphene.Field(MembershipType) ok = graphene.Boolean() diff --git a/backend/apps/organizations/schema.py b/backend/apps/organizations/schema.py index 011b371cf..353e18da7 100644 --- a/backend/apps/organizations/schema.py +++ b/backend/apps/organizations/schema.py @@ -3,6 +3,7 @@ from .mutations import ( AssignMembership, + AssignMembershipWithUsername, DeleteMembership, CreateOrganization, DeleteOrganization, @@ -21,6 +22,7 @@ class OrganizationMutations(graphene.ObjectType): assign_membership = AssignMembership.Field() delete_membership = DeleteMembership.Field() change_membership = ChangeMembership.Field() + assign_membership_with_username = AssignMembershipWithUsername.Field() class OrganizationQueries(graphene.ObjectType, OrganizationResolvers, MembershipResolvers): diff --git a/backend/schema.json b/backend/schema.json index 8d69998b9..c5f232db9 100644 --- a/backend/schema.json +++ b/backend/schema.json @@ -5918,6 +5918,33 @@ "ofType": null } }, + { + "args": [ + { + "defaultValue": null, + "description": null, + "name": "membershipData", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "MembershipInputWithUsername", + "ofType": null + } + } + } + ], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "assignMembershipWithUsername", + "type": { + "kind": "OBJECT", + "name": "AssignMembershipWithUsername", + "ofType": null + } + }, { "args": [ { @@ -8440,6 +8467,82 @@ "name": "ChangeMembershipInput", "possibleTypes": null }, + { + "description": null, + "enumValues": null, + "fields": [ + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "membership", + "type": { + "kind": "OBJECT", + "name": "MembershipType", + "ofType": null + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "ok", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + } + ], + "inputFields": null, + "interfaces": [], + "kind": "OBJECT", + "name": "AssignMembershipWithUsername", + "possibleTypes": null + }, + { + "description": null, + "enumValues": null, + "fields": null, + "inputFields": [ + { + "defaultValue": null, + "description": null, + "name": "username", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + { + "defaultValue": null, + "description": null, + "name": "organizationId", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + { + "defaultValue": null, + "description": null, + "name": "groupId", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } + ], + "interfaces": null, + "kind": "INPUT_OBJECT", + "name": "MembershipInputWithUsername", + "possibleTypes": null + }, { "description": "Add a new booking to the database", "enumValues": null, diff --git a/frontend/src/components/pages/organization/OrgMembers.tsx b/frontend/src/components/pages/organization/OrgMembers.tsx index 587f58889..c34002fec 100644 --- a/frontend/src/components/pages/organization/OrgMembers.tsx +++ b/frontend/src/components/pages/organization/OrgMembers.tsx @@ -21,8 +21,9 @@ import { AdminOrganizationFragment, MembershipsDocument, MembershipType, - AssignMembershipDocument, + AssignMembershipWithUsernameDocument, DeleteMembershipDocument, + ChangeMembershipDocument, } from "@/generated/graphql"; type Props = { @@ -31,8 +32,9 @@ type Props = { export const OrgMembers: React.FC = ({ organization }) => { const { data, loading, error } = useQuery(MembershipsDocument, { variables: { organizationId: organization.id } }); - const [AssignMembership] = useMutation(AssignMembershipDocument); + const [AssignMembershipWithUsername] = useMutation(AssignMembershipWithUsernameDocument); const [DeleteMembership] = useMutation(DeleteMembershipDocument); + const [ChangeMembership] = useMutation(ChangeMembershipDocument); const [userInput, setUserInput] = useState(""); @@ -44,36 +46,49 @@ export const OrgMembers: React.FC = ({ organization }) => { const handleAddMembership = () => { //Legg til funksjonalitet for å legge til bruker ved brukernavn - console.log("Legger til " + userInput); + + //Get userId from username + + AssignMembershipWithUsername({ + variables: { + membershipData: { + organizationId: organization.id, + username: userInput.toLowerCase(), //Just to make sure + groupId: organization?.memberGroup?.uuid, + }, + }, + }).then((res) => { + console.log("Membership added"); + console.log(res); + //Problem: Clientside cache doesnt get updated + }); setUserInput(""); }; const handleGroupChange = (membership: MembershipType | any) => { if (!membership) return; - const role = membership?.group?.uuid == organization.adminGroup?.uuid ? "ADMIN" : "MEMBER"; - if (role == "ADMIN") console.log("Demoterer " + membership.user.firstName + " " + membership.user.lastName); - if (role == "MEMBER") console.log("Promoterer " + membership.user.firstName + " " + membership.user.lastName); - if (role == "ADMIN") { - //Legg til funksjonalitet for å demote bruker - AssignMembership({ + const currentRole = membership?.group?.uuid == organization.adminGroup?.uuid ? "ADMIN" : "MEMBER"; + if (currentRole == "ADMIN") { + //Legg til funksjonalitet for å demotere bruker + + ChangeMembership({ variables: { membershipData: { - organizationId: organization.id, - userId: membership.user.id, + membershipId: membership?.id, groupId: organization?.memberGroup?.uuid, }, }, }); } - if (role == "MEMBER") { + if (currentRole == "MEMBER") { //Legg til funksjonalitet for å promote bruker - AssignMembership({ + + ChangeMembership({ variables: { membershipData: { - organizationId: organization.id, - userId: membership.user.id, + membershipId: membership?.id, groupId: organization?.adminGroup?.uuid, }, }, @@ -90,7 +105,7 @@ export const OrgMembers: React.FC = ({ organization }) => { }, }); - console.log("Fjerner " + membership.user.firstName + " " + membership.user.lastName); + //Problem: Clientside cache doesnt get updated }; return ( diff --git a/frontend/src/generated/graphql.tsx b/frontend/src/generated/graphql.tsx index 9bd86538e..e23ad7a79 100644 --- a/frontend/src/generated/graphql.tsx +++ b/frontend/src/generated/graphql.tsx @@ -112,6 +112,12 @@ export type AssignMembership = { ok?: Maybe; }; +export type AssignMembershipWithUsername = { + __typename?: "AssignMembershipWithUsername"; + membership?: Maybe; + ok?: Maybe; +}; + export type AttemptCapturePayment = { __typename?: "AttemptCapturePayment"; order?: Maybe; @@ -569,6 +575,12 @@ export type MembershipInput = { userId?: InputMaybe; }; +export type MembershipInputWithUsername = { + groupId?: InputMaybe; + organizationId?: InputMaybe; + username?: InputMaybe; +}; + export type MembershipType = { __typename?: "MembershipType"; group?: Maybe; @@ -587,6 +599,7 @@ export type Mutations = { */ adminEventSignOff?: Maybe; assignMembership?: Maybe; + assignMembershipWithUsername?: Maybe; attemptCapturePayment?: Maybe; authUser: AuthUser; changeMembership?: Maybe; @@ -671,6 +684,10 @@ export type MutationsAssignMembershipArgs = { membershipData: MembershipInput; }; +export type MutationsAssignMembershipWithUsernameArgs = { + membershipData: MembershipInputWithUsername; +}; + export type MutationsAttemptCapturePaymentArgs = { orderId: Scalars["ID"]; }; @@ -3052,6 +3069,24 @@ export type AssignMembershipMutation = { } | null; }; +export type AssignMembershipWithUsernameMutationVariables = Exact<{ + membershipData: MembershipInputWithUsername; +}>; + +export type AssignMembershipWithUsernameMutation = { + __typename?: "Mutations"; + assignMembershipWithUsername?: { + __typename?: "AssignMembershipWithUsername"; + ok?: boolean | null; + membership?: { + __typename?: "MembershipType"; + id: string; + organization: { __typename?: "OrganizationType"; id: string }; + group?: { __typename?: "ResponsibleGroupType"; uuid: string } | null; + } | null; + } | null; +}; + export type DeleteMembershipMutationVariables = Exact<{ membershipId: Scalars["ID"]; }>; @@ -6778,6 +6813,74 @@ export const AssignMembershipDocument = { }, ], } as unknown as DocumentNode; +export const AssignMembershipWithUsernameDocument = { + kind: "Document", + definitions: [ + { + kind: "OperationDefinition", + operation: "mutation", + name: { kind: "Name", value: "assignMembershipWithUsername" }, + variableDefinitions: [ + { + kind: "VariableDefinition", + variable: { kind: "Variable", name: { kind: "Name", value: "membershipData" } }, + type: { + kind: "NonNullType", + type: { kind: "NamedType", name: { kind: "Name", value: "MembershipInputWithUsername" } }, + }, + }, + ], + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "assignMembershipWithUsername" }, + arguments: [ + { + kind: "Argument", + name: { kind: "Name", value: "membershipData" }, + value: { kind: "Variable", name: { kind: "Name", value: "membershipData" } }, + }, + ], + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "membership" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { kind: "Field", name: { kind: "Name", value: "id" } }, + { + kind: "Field", + name: { kind: "Name", value: "organization" }, + selectionSet: { + kind: "SelectionSet", + selections: [{ kind: "Field", name: { kind: "Name", value: "id" } }], + }, + }, + { + kind: "Field", + name: { kind: "Name", value: "group" }, + selectionSet: { + kind: "SelectionSet", + selections: [{ kind: "Field", name: { kind: "Name", value: "uuid" } }], + }, + }, + ], + }, + }, + { kind: "Field", name: { kind: "Name", value: "ok" } }, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode; export const DeleteMembershipDocument = { kind: "Document", definitions: [ diff --git a/frontend/src/graphql/orgs/fragments.graphql b/frontend/src/graphql/orgs/fragments.graphql index 2f6014f06..1b7d47ee2 100644 --- a/frontend/src/graphql/orgs/fragments.graphql +++ b/frontend/src/graphql/orgs/fragments.graphql @@ -36,6 +36,7 @@ fragment OrgAdminListing on ListingType { fragment Membership on MembershipType { id user { + id firstName lastName } diff --git a/frontend/src/graphql/orgs/mutations.graphql b/frontend/src/graphql/orgs/mutations.graphql index adda4ead8..4f508f5a1 100644 --- a/frontend/src/graphql/orgs/mutations.graphql +++ b/frontend/src/graphql/orgs/mutations.graphql @@ -13,8 +13,35 @@ mutation assignMembership($membershipData: MembershipInput!) { } } +mutation assignMembershipWithUsername($membershipData: MembershipInputWithUsername!) { + assignMembershipWithUsername(membershipData: $membershipData) { + membership { + id + organization { + id + } + group { + uuid + } + } + ok + } +} + mutation deleteMembership($membershipId: ID!) { deleteMembership(membershipId: $membershipId) { ok } } + +mutation changeMembership($membershipData: ChangeMembershipInput!) { + changeMembership(membershipData: $membershipData) { + membership { + id + group { + uuid + } + } + ok + } +} diff --git a/frontend/src/graphql/orgs/queries.graphql b/frontend/src/graphql/orgs/queries.graphql index 269a060ba..2db7169a8 100644 --- a/frontend/src/graphql/orgs/queries.graphql +++ b/frontend/src/graphql/orgs/queries.graphql @@ -6,13 +6,6 @@ query adminOrganization($orgId: ID!) { query memberships($organizationId: ID!) { memberships(organizationId: $organizationId) { - id - user { - firstName - lastName - } - group { - uuid - } + ...Membership } } From 8a1678148961cfd500b1b1fd4ef8969949a7ca33 Mon Sep 17 00:00:00 2001 From: Simen Sandhaug Date: Thu, 2 Feb 2023 18:06:11 +0100 Subject: [PATCH 26/26] add comments --- frontend/src/components/pages/organization/OrgMembers.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/frontend/src/components/pages/organization/OrgMembers.tsx b/frontend/src/components/pages/organization/OrgMembers.tsx index c34002fec..93c963bfd 100644 --- a/frontend/src/components/pages/organization/OrgMembers.tsx +++ b/frontend/src/components/pages/organization/OrgMembers.tsx @@ -47,8 +47,6 @@ export const OrgMembers: React.FC = ({ organization }) => { const handleAddMembership = () => { //Legg til funksjonalitet for å legge til bruker ved brukernavn - //Get userId from username - AssignMembershipWithUsername({ variables: { membershipData: { @@ -57,11 +55,8 @@ export const OrgMembers: React.FC = ({ organization }) => { groupId: organization?.memberGroup?.uuid, }, }, - }).then((res) => { - console.log("Membership added"); - console.log(res); - //Problem: Clientside cache doesnt get updated }); + //Problem: Clientside cache doesnt get updated setUserInput(""); };