diff --git a/attendees/persons/admin.py b/attendees/persons/admin.py index 494f269c..0f63d6a8 100644 --- a/attendees/persons/admin.py +++ b/attendees/persons/admin.py @@ -52,7 +52,7 @@ def get_queryset(self, request): requester_permission = {'infos__show_secret__' + request.user.attendee_uuid_str(): True} return qs.filter( Q(organization=request.user.organization), - ( Q(**requester_permission) | Q(infos__show_secret={}) ), + ( Q(**requester_permission) | Q(infos__show_secret={}) | Q(infos__show_secret__isnull=True) ), ) diff --git a/attendees/persons/models/utility.py b/attendees/persons/models/utility.py index 2508c0b7..137e3472 100644 --- a/attendees/persons/models/utility.py +++ b/attendees/persons/models/utility.py @@ -50,7 +50,7 @@ def attendee_infos(): @staticmethod def relationship_infos(): - return {"show_secret": {}} + return {"show_secret": {}, "comment": None} @staticmethod def forever(): # 1923 years from now diff --git a/attendees/persons/serializers/past_serializer.py b/attendees/persons/serializers/past_serializer.py index 88c3a05a..2e9418fa 100644 --- a/attendees/persons/serializers/past_serializer.py +++ b/attendees/persons/serializers/past_serializer.py @@ -4,7 +4,7 @@ class PastSerializer(serializers.ModelSerializer): - class Meta: + class Meta: # It is critical not to have organization in the fields, to let perform_create set it model = Past - fields = '__all__' + fields = ('id', 'display_name', 'category', 'start', 'finish', 'infos', 'content_type', 'object_id') diff --git a/attendees/persons/views/api/categorized_pasts.py b/attendees/persons/views/api/categorized_pasts.py index 4c679701..f86d24a7 100644 --- a/attendees/persons/views/api/categorized_pasts.py +++ b/attendees/persons/views/api/categorized_pasts.py @@ -1,5 +1,7 @@ import time -from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin +from django.contrib.auth.mixins import LoginRequiredMixin +from django.contrib.contenttypes.models import ContentType +from django.http import Http404 from django.shortcuts import get_object_or_404 from rest_framework import viewsets from django.db.models import Q @@ -20,7 +22,7 @@ class ApiCategorizedPastsViewSet(LoginRequiredMixin, SpyGuard, viewsets.ModelVie def get_queryset(self): category__type = self.request.query_params.get('category__type', '') - menu_name = self.__class__.__name__ + category__type.capitalize() + menu_name = self.__class__.__name__ + category__type.capitalize() # self.get_view_name() => Api Categorized Pasts List url_name = Utility.underscore(menu_name) if not MenuAuthGroup.objects.filter( @@ -41,6 +43,8 @@ def get_queryset(self): Q(pk=past_id), Q(category__type=category__type), ( Q(infos__show_secret={}) + | + Q(infos__show_secret__isnull=True) | Q(**requester_permission)), ) @@ -49,9 +53,14 @@ def get_queryset(self): Q(organization=self.request.user.organization), Q(category__type=category__type), ( Q(infos__show_secret={}) + | + Q(infos__show_secret__isnull=True) | Q(**requester_permission)), ) + def perform_create(self, serializer): #SpyGuard ensured requester & target_attendee belongs to the same org. + serializer.save(organization=self.request.user.organization) + api_categorized_pasts_viewset = ApiCategorizedPastsViewSet diff --git a/attendees/static/js/persons/datagrid_attendee_update_view.js b/attendees/static/js/persons/datagrid_attendee_update_view.js index b5c81e88..0a474b7a 100644 --- a/attendees/static/js/persons/datagrid_attendee_update_view.js +++ b/attendees/static/js/persons/datagrid_attendee_update_view.js @@ -2429,7 +2429,7 @@ Attendees.datagridUpdate = { }); }, insert: function (values) { - const contentType = { + const subject = { content_type: Attendees.datagridUpdate.attendeeAttrs.dataset.attendeeContenttypeId, object_id: Attendees.datagridUpdate.attendeeId, }; @@ -2438,7 +2438,7 @@ Attendees.datagridUpdate = { method: "POST", dataType: 'json', contentType: "application/json; charset=utf-8", - data: JSON.stringify({...values, ...contentType}), + data: JSON.stringify({...values, ...subject}), success: (result) => { DevExpress.ui.notify( { @@ -2456,13 +2456,13 @@ Attendees.datagridUpdate = { }), }, onRowInserting: (rowData) => { - const infos = {organization: Attendees.datagridUpdate.attendeeFormConfigs.formData.organization_slug, show_secret:{}}; + const infos = {show_secret: {}, comment: rowData.data.infos && rowData.data.infos.comment}; if(rowData.data.infos && rowData.data.infos.show_secret){ - infos.show_secret = {[Attendees.utilities.userAttendeeId]: true}; + infos.show_secret[Attendees.utilities.userAttendeeId] = true; } rowData.data.infos = infos; }, - onInitNewRow: (e) => { + onInitNewRow: (e) => { // don't assign e.data or show_secret somehow messed up DevExpress.ui.notify( { message: "Let's create a " + type + ", click away or hit Enter to save. Hit Esc to quit without save", @@ -2495,15 +2495,23 @@ Attendees.datagridUpdate = { allowDeleting: false, }, onRowUpdating: (rowData) => { - if (rowData.newData.infos && 'show_secret' in rowData.newData.infos) { // value could be intentionally false to prevent someone seeing it - const showSecret = rowData.oldData.infos.show_secret; - const isRelationshipSecretForCurrentUser = rowData.newData.infos.show_secret; - if (isRelationshipSecretForCurrentUser) { - showSecret[Attendees.utilities.userAttendeeId] = true; - } else { - delete showSecret[Attendees.utilities.userAttendeeId]; + if(rowData.newData.infos){ + const updatingInfos = rowData.oldData.infos; // may contains both keys of show_secret and comment + if('show_secret' in rowData.newData.infos){ + const isRelationshipSecretForCurrentUser = rowData.newData.infos.show_secret; + if(isRelationshipSecretForCurrentUser){ + if (typeof(updatingInfos.show_secret)==="object") { + updatingInfos.show_secret[Attendees.utilities.userAttendeeId] = true; + } else { + updatingInfos.show_secret = {[Attendees.utilities.userAttendeeId]: true}; + } + } else { + delete updatingInfos.show_secret[Attendees.utilities.userAttendeeId]; + } + rowData.newData.infos = updatingInfos; + } else { // for updating infos.comment + rowData.newData.infos = {...updatingInfos, ...rowData.newData.infos}; } - rowData.newData.infos.show_secret = showSecret; } }, columns: [ diff --git a/attendees/whereabouts/views/api/datagrid_data_place.py b/attendees/whereabouts/views/api/datagrid_data_place.py index 4309a490..73ebe6c5 100644 --- a/attendees/whereabouts/views/api/datagrid_data_place.py +++ b/attendees/whereabouts/views/api/datagrid_data_place.py @@ -27,5 +27,8 @@ def get_queryset(self): # Todo: check if current user are allowed to query this querying_place_id = self.kwargs.get('place_id') return Place.objects.filter(pk=querying_place_id, organization=self.request.user.organization) + # def perform_create(self, serializer): #forget SpyGuard ?? + # serializer.save(organization=self.request.user.organization) + api_datagrid_data_place_viewset = ApiDatagridDataPlaceViewSet diff --git a/fixtures/db_seed.json b/fixtures/db_seed.json index 9f8d15e0..6b952e57 100644 --- a/fixtures/db_seed.json +++ b/fixtures/db_seed.json @@ -2197,6 +2197,7 @@ "display_order": 30000, "display_name": "secret to hagar(if user#2 created)", "infos": { + "comment": null, "show_secret": { "22c29cd5-a5ab-46a3-afe6-d5a600c33fc9": true } @@ -2219,6 +2220,7 @@ "display_order": 30000, "display_name": "where and major", "infos": { + "comment": null, "show_secret": {} } } @@ -2239,6 +2241,7 @@ "display_order": 30000, "display_name": "baptized at where by whom", "infos": { + "comment": null, "show_secret": {} } } @@ -2259,6 +2262,7 @@ "display_order": 30000, "display_name": "accept at where by whom", "infos": { + "comment": null, "show_secret": {} } } @@ -2279,6 +2283,7 @@ "display_order": 30000, "display_name": "believe at where by whom", "infos": { + "comment": null, "show_secret": {} } } @@ -3027,6 +3032,7 @@ "start": null, "finish": "3937-05-24T03:35:37Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3047,6 +3053,7 @@ "start": null, "finish": "3936-11-05T17:12:21Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3067,6 +3074,7 @@ "start": null, "finish": "3936-11-05T17:02:42Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3087,6 +3095,7 @@ "start": null, "finish": "3937-05-24T04:02:59Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3107,6 +3116,7 @@ "start": null, "finish": "3936-11-05T17:13:12Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3127,6 +3137,7 @@ "start": null, "finish": "3936-11-15T00:47:08Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3147,6 +3158,7 @@ "start": null, "finish": "3936-11-05T17:00:50Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3167,6 +3179,7 @@ "start": null, "finish": "3936-11-15T01:01:20Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3187,6 +3200,7 @@ "start": null, "finish": "3936-11-05T16:58:34Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3207,6 +3221,7 @@ "start": null, "finish": "3936-11-05T16:52:12Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3227,6 +3242,7 @@ "start": null, "finish": "3936-11-05T17:07:48Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3247,6 +3263,7 @@ "start": null, "finish": "3937-06-12T17:58:04Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3267,6 +3284,7 @@ "start": null, "finish": "3937-05-24T04:02:59Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3287,6 +3305,7 @@ "start": null, "finish": "3937-05-24T04:02:59Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3307,6 +3326,7 @@ "start": null, "finish": "3936-11-05T17:02:11Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3327,6 +3347,7 @@ "start": null, "finish": "3936-11-05T17:07:24Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3347,6 +3368,7 @@ "start": null, "finish": "3936-11-15T01:01:20Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3367,6 +3389,7 @@ "start": null, "finish": "3936-11-05T16:59:13Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3387,6 +3410,7 @@ "start": null, "finish": "3937-05-24T04:04:10Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3407,6 +3431,7 @@ "start": null, "finish": "3937-05-24T03:34:52Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3427,6 +3452,7 @@ "start": null, "finish": "3937-06-12T17:58:04Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3447,6 +3473,7 @@ "start": null, "finish": "3936-11-15T00:59:22Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3467,6 +3494,7 @@ "start": null, "finish": "3936-11-15T00:46:42Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3487,6 +3515,7 @@ "start": null, "finish": "3937-05-24T02:08:07Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3507,6 +3536,7 @@ "start": null, "finish": "3936-11-05T16:59:44Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3527,6 +3557,7 @@ "start": null, "finish": "3937-05-24T03:35:37Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3547,6 +3578,7 @@ "start": null, "finish": "3937-05-24T04:03:44Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3567,6 +3599,7 @@ "start": null, "finish": "3937-05-24T04:04:24Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3587,6 +3620,7 @@ "start": null, "finish": "3936-11-05T17:09:17Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3607,6 +3641,7 @@ "start": null, "finish": "3936-11-05T17:08:29Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3627,6 +3662,7 @@ "start": null, "finish": "3937-05-24T03:34:15Z", "infos": { + "comment": null, "show_secret": {} } } @@ -3647,6 +3683,7 @@ "start": null, "finish": "3937-05-24T03:34:52Z", "infos": { + "comment": null, "show_secret": {} } }