コード例 #1
0
    def create(self, validated_data):
        logger.debug('inside ListingSerializer.create')
        title = validated_data['title']
        user = generic_model_access.get_profile(
            self.context['request'].user.username)
        logger.info('creating listing %s for user %s' % (title,
            user.user.username))

        # assign a default security_marking level if none is provided

        if not validated_data.get('security_marking', None):
            validated_data['security_marking'] = constants.DEFAULT_SECURITY_MARKING

        # TODO required_listings
        listing = models.Listing(title=title,
            agency=validated_data['agency'],
            description=validated_data['description'],
            launch_url=validated_data['launch_url'],
            version_name=validated_data['version_name'],
            unique_name=validated_data['unique_name'],
            what_is_new=validated_data['what_is_new'],
            description_short=validated_data['description_short'],
            requirements=validated_data['requirements'],
            security_marking=validated_data['security_marking'],
            listing_type=validated_data['listing_type'],
            is_private=validated_data['is_private'])

        image_keys = ['small_icon', 'large_icon', 'banner_icon', 'large_banner_icon']
        for image_key in image_keys:
            if validated_data[image_key]:
                new_value_image = image_model_access.get_image_by_id(validated_data[image_key].get('id'))

                if new_value_image is None:
                    raise errors.InvalidInput('Error while saving, can not find image by id')

                if image_key == 'small_icon':
                    listing.small_icon = new_value_image
                elif image_key == 'large_icon':
                    listing.large_icon = new_value_image
                elif image_key == 'banner_icon':
                    listing.banner_icon = new_value_image
                elif image_key == 'large_banner_icon':
                    listing.large_banner_icon = new_value_image

        listing.save()

        if validated_data.get('contacts', None) is not None:
            for contact in validated_data['contacts']:
                new_contact, created = models.Contact.objects.get_or_create(name=contact['name'],
                    email=contact['email'],
                    secure_phone=contact['secure_phone'],
                    unsecure_phone=contact['unsecure_phone'],
                    organization=contact.get('organization', None),
                    contact_type=contact_type_model_access.get_contact_type_by_name(contact['contact_type']['name']))
                new_contact.save()
                listing.contacts.add(new_contact)

        if validated_data.get('owners', None) is not None:
            if validated_data['owners']:
                for owner in validated_data['owners']:
                    listing.owners.add(owner)
            else:
                # if no owners are specified, just add the current user
                listing.owners.add(user)

        if validated_data.get('categories', None) is not None:
            for category in validated_data['categories']:
                listing.categories.add(category)

        # tags will be automatically created if necessary
        if validated_data.get('tags', None) is not None:
            for tag in validated_data['tags']:
                obj, created = models.Tag.objects.get_or_create(
                    name=tag['name'])
                listing.tags.add(obj)

        if validated_data.get('intents', None) is not None:
            for intent in validated_data['intents']:
                listing.intents.add(intent)

        # doc_urls will be automatically created
        if validated_data.get('doc_urls', None) is not None:
            for d in validated_data['doc_urls']:
                doc_url = models.DocUrl(name=d['name'], url=d['url'], listing=listing)
                doc_url.save()

        # screenshots will be automatically created
        if validated_data.get('screenshots', None) is not None:
            for s in validated_data['screenshots']:
                screenshot = models.Screenshot(
                    small_image=image_model_access.get_image_by_id(s['small_image']['id']),
                    large_image=image_model_access.get_image_by_id(s['large_image']['id']),
                    listing=listing)
                screenshot.save()

        # create a new activity
        model_access.create_listing(user, listing)

        return listing
コード例 #2
0
    def update(self, instance, validated_data):
        logger.debug('inside ListingSerializer.update')
        user = generic_model_access.get_profile(
            self.context['request'].user.username)

        if user.highest_role() not in ['APPS_MALL_STEWARD', 'ORG_STEWARD']:
            if user not in instance.owners.all():
                raise errors.PermissionDenied(
                    'User is not an owner of this listing')

        change_details = []

        simple_fields = ['title', 'description', 'description_short',
            'launch_url', 'version_name', 'requirements', 'unique_name',
            'what_is_new', 'security_marking']

        for i in simple_fields:
            if getattr(instance, i) != validated_data[i]:
                change_details.append({'old_value': getattr(instance, i),
                    'new_value': validated_data[i], 'field_name': i})
                setattr(instance, i, validated_data[i])

        if validated_data['is_enabled'] != instance.is_enabled:
            if validated_data['is_enabled']:
                model_access.enable_listing(user, instance)
                change_details.append({'field_name': 'is_enabled',
                    'old_value': 'false', 'new_value': 'true'})
            else:
                model_access.disable_listing(user, instance)
                change_details.append({'field_name': 'is_enabled',
                    'old_value': 'true', 'new_value': 'false'})

            instance.is_enabled = validated_data['is_enabled']

        if validated_data['is_private'] != instance.is_private:
            change_details.append({'old_value': model_access.bool_to_string(instance.is_private),
                    'new_value': model_access.bool_to_string(validated_data['is_private']), 'field_name': 'is_private'})
            instance.is_private = validated_data['is_private']

        if validated_data['is_featured'] != instance.is_featured:
            if user.highest_role() not in ['APPS_MALL_STEWARD', 'ORG_STEWARD']:
                raise errors.PermissionDenied('Only stewards can change is_featured setting of a listing')
            change_details.append({'old_value': model_access.bool_to_string(instance.is_featured),
                    'new_value': model_access.bool_to_string(validated_data['is_featured']), 'field_name': 'is_featured'})
            instance.is_featured = validated_data['is_featured']

        s = validated_data['approval_status']
        if s and s != instance.approval_status:
            if s == models.Listing.APPROVED and user.highest_role() != 'APPS_MALL_STEWARD':
                raise errors.PermissionDenied('Only an APPS_MALL_STEWARD can mark a listing as APPROVED')
            if s == models.Listing.APPROVED_ORG and user.highest_role() not in ['APPS_MALL_STEWARD', 'ORG_STEWARD']:
                raise errors.PermissionDenied('Only stewards can mark a listing as APPROVED_ORG')

            if s == models.Listing.PENDING:
                model_access.submit_listing(user, instance)
            if s == models.Listing.APPROVED_ORG:
                model_access.approve_listing_by_org_steward(user, instance)
            if s == models.Listing.APPROVED:
                model_access.approve_listing(user, instance)
            if s == models.Listing.REJECTED:
                # TODO: need to get the rejection text from somewhere
                model_access.reject_listing(user, instance, 'TODO: rejection reason')

        if instance.listing_type != validated_data['listing_type']:
            if instance.listing_type:
                old_value = instance.listing_type.title
            else:
                old_value = None
            if validated_data['listing_type']:
                new_value = validated_data['listing_type'].title
            else:
                new_value = None
            change_details.append({'old_value': old_value,
                    'new_value': new_value, 'field_name': 'listing_type'})
            instance.listing_type = validated_data['listing_type']

        image_keys = ['small_icon', 'large_icon', 'banner_icon', 'large_banner_icon']
        for image_key in image_keys:
            if validated_data[image_key]:
                old_value = model_access.image_to_string(getattr(instance, image_key), True, 'old_value(%s)'%image_key)
                new_value = model_access.image_to_string(validated_data[image_key], False, 'new_value(%s)'%image_key)

                if old_value != new_value:
                    new_value_image = None

                    old_image_id = None
                    if old_value is not None:
                        old_image_id = getattr(instance, image_key).id
                    if validated_data[image_key].get('id') == old_image_id:
                        new_value_image = getattr(instance, image_key)
                        new_value_image.security_marking = validated_data[image_key].get('security_marking')
                        new_value_image.save()
                    else:
                        new_value_image = image_model_access.get_image_by_id(validated_data[image_key].get('id'))

                        if new_value_image is None:
                            raise errors.InvalidInput('Error while saving, can not find image by id')

                    change_details.append({'old_value': old_value,
                            'new_value': new_value, 'field_name': image_key})

                    if image_key == 'small_icon':
                        instance.small_icon = new_value_image
                    elif image_key == 'large_icon':
                        instance.large_icon = new_value_image
                    elif image_key == 'banner_icon':
                        instance.banner_icon = new_value_image
                    elif image_key == 'large_banner_icon':
                        instance.large_banner_icon = new_value_image

        if 'contacts' in validated_data:
            old_contact_instances = instance.contacts.all()
            old_contacts = model_access.contacts_to_string(
                old_contact_instances, True)
            new_contacts = model_access.contacts_to_string(
                validated_data['contacts'])

            if old_contacts != new_contacts:
                change_details.append({'old_value': old_contacts,
                    'new_value': new_contacts, 'field_name': 'contacts'})
                instance.contacts.clear()
                for contact in validated_data['contacts']:
                    # TODO: Smarter Handling of Duplicates Contact Records
                    # A contact with the same name and email should be the same contact
                    # in the backend.
                    # Person1(name='N1',email='*****@*****.**') and
                    #    Person1' (name='N1',email='*****@*****.**',secure_phone = '414-444-444')
                    # The two people above should be one contact
                    # if approval_status: "IN_PROGRESS" then it should be using
                    # contact model ids' since it is temporary contacts
                    obj, created = models.Contact.objects.get_or_create(
                        name=contact['name'],
                        email=contact['email'],
                        secure_phone=contact['secure_phone'],
                        unsecure_phone=contact['unsecure_phone'],
                        organization=contact.get('organization', None),
                        contact_type=contact_type_model_access.get_contact_type_by_name(
                            contact['contact_type']['name'])
                    )
                    instance.contacts.add(obj)

        if 'categories' in validated_data:
            old_category_instances = instance.categories.all()
            old_categories = model_access.categories_to_string(
                old_category_instances, True)
            new_categories = model_access.categories_to_string(
                validated_data['categories'], True)
            if old_categories != new_categories:
                change_details.append({'old_value': old_categories,
                    'new_value': new_categories, 'field_name': 'categories'})
                instance.categories.clear()
                for category in validated_data['categories']:
                    instance.categories.add(category)

        if 'owners' in validated_data:
            old_owner_instances = instance.owners.all()
            old_owners = model_access.owners_to_string(
                old_owner_instances, True)
            new_owners = model_access.owners_to_string(
                validated_data['owners'], True)
            if old_owners != new_owners:
                change_details.append({'old_value': old_owners,
                    'new_value': new_owners, 'field_name': 'owners'})
                instance.owners.clear()
                for owner in validated_data['owners']:
                    instance.owners.add(owner)

        # tags will be automatically created if necessary
        if 'tags' in validated_data:
            old_tag_instances = instance.tags.all()
            old_tags = model_access.tags_to_string(old_tag_instances, True)
            new_tags = model_access.tags_to_string(validated_data['tags'])
            if old_tags != new_tags:
                change_details.append({'old_value': old_tags,
                    'new_value': new_tags, 'field_name': 'tags'})
                instance.tags.clear()
                for tag in validated_data['tags']:
                    obj, created = models.Tag.objects.get_or_create(
                        name=tag['name'])
                    instance.tags.add(obj)

        if 'intents' in validated_data:
            old_intent_instances = instance.intents.all()
            old_intents = model_access.intents_to_string(old_intent_instances,
                True)
            new_intents = model_access.intents_to_string(
                validated_data['intents'], True)
            if old_intents != new_intents:
                change_details.append({'old_value': old_intents,
                    'new_value': new_intents, 'field_name': 'intents'})
                instance.intents.clear()
                for intent in validated_data['intents']:
                    instance.intents.add(intent)

        # doc_urls will be automatically created
        if 'doc_urls' in validated_data:
            old_doc_url_instances = model_access.get_doc_urls_for_listing(instance)
            old_doc_urls = model_access.doc_urls_to_string(
                old_doc_url_instances, True)
            new_doc_urls = model_access.doc_urls_to_string(
                validated_data['doc_urls'])
            if old_doc_urls != new_doc_urls:
                change_details.append({
                    'old_value': old_doc_urls,
                    'new_value': new_doc_urls,
                    'field_name': 'doc_urls'})

                new_doc_url_instances = []
                for d in validated_data['doc_urls']:
                    obj, created = models.DocUrl.objects.get_or_create(
                        name=d['name'], url=d['url'], listing=instance)
                    new_doc_url_instances.append(obj)
                for i in old_doc_url_instances:
                    if i not in new_doc_url_instances:
                        logger.info('Deleting doc_url: %s' % i.id)
                        i.delete()

        # screenshots will be automatically created
        if 'screenshots' in validated_data:
            old_screenshot_instances = model_access.get_screenshots_for_listing(instance)
            old_screenshots = model_access.screenshots_to_string(old_screenshot_instances, True)
            new_screenshots = model_access.screenshots_to_string(validated_data['screenshots'])
            if old_screenshots != new_screenshots:
                change_details.append({'old_value': old_screenshots,
                    'new_value': new_screenshots, 'field_name': 'screenshots'})

            new_screenshot_instances = []

            for s in validated_data['screenshots']:

                new_small_image = image_model_access.get_image_by_id(s['small_image']['id'])
                new_small_image.security_marking = s['small_image']['security_marking']
                new_small_image.save()

                new_large_image = image_model_access.get_image_by_id(s['large_image']['id'])
                new_large_image.security_marking = s['large_image']['security_marking']
                new_large_image.save()

                obj, created = models.Screenshot.objects.get_or_create(
                    small_image=new_small_image,
                    large_image=new_large_image,
                    listing=instance)


                new_screenshot_instances.append(obj)

            for i in old_screenshot_instances:
                if i not in new_screenshot_instances:
                    logger.info('Deleting screenshot: %s' % i.id)
                    i.delete()

        if 'agency' in validated_data:
            if instance.agency != validated_data['agency']:
                change_details.append({'old_value': instance.agency.title,
                    'new_value': validated_data['agency'].title, 'field_name': 'agency'})
                instance.agency = validated_data['agency']

        instance.save()

        model_access.log_listing_modification(user, instance, change_details)
        instance.edited_date = datetime.datetime.now(pytz.utc)
        return instance
コード例 #3
0
    def update(self, instance, validated_data):
        user = generic_model_access.get_profile(
            self.context['request'].user.username)

        if user.highest_role() not in ['APPS_MALL_STEWARD', 'ORG_STEWARD']:
            if user not in instance.owners.all():
                raise errors.PermissionDenied(
                    'User is not an owner of this listing')

        change_details = []

        simple_fields = ['title', 'description', 'description_short',
            'launch_url', 'version_name', 'requirements', 'unique_name',
            'what_is_new', 'security_marking']

        for i in simple_fields:
            if getattr(instance, i) != validated_data[i]:
                change_details.append({'old_value': getattr(instance, i),
                    'new_value': validated_data[i], 'field_name': i})
                setattr(instance, i, validated_data[i])

        if validated_data['is_enabled'] != instance.is_enabled:
            if validated_data['is_enabled']:
                model_access.enable_listing(user, instance)
                change_details.append({'field_name': 'is_enabled',
                    'old_value': 'false', 'new_value': 'true'})
            else:
                model_access.disable_listing(user, instance)
                change_details.append({'field_name': 'is_enabled',
                    'old_value': 'true', 'new_value': 'false'})

            instance.is_enabled = validated_data['is_enabled']

        if validated_data['is_private'] != instance.is_private:
            change_details.append({'old_value': model_access.bool_to_string(instance.is_private),
                    'new_value': model_access.bool_to_string(validated_data['is_private']), 'field_name': 'is_private'})
            instance.is_private = validated_data['is_private']

        if validated_data['is_featured'] != instance.is_featured:
            if user.highest_role() not in ['APPS_MALL_STEWARD', 'ORG_STEWARD']:
                raise errors.PermissionDenied('Only stewards can change is_featured setting of a listing')
            change_details.append({'old_value': model_access.bool_to_string(instance.is_featured),
                    'new_value': model_access.bool_to_string(validated_data['is_featured']), 'field_name': 'is_featured'})
            instance.is_featured = validated_data['is_featured']

        s = validated_data['approval_status']
        if s and s != instance.approval_status:
            if s == models.Listing.APPROVED and user.highest_role() != 'APPS_MALL_STEWARD':
                raise errors.PermissionDenied('Only an APPS_MALL_STEWARD can mark a listing as APPROVED')
            if s == models.Listing.APPROVED_ORG and user.highest_role() not in ['APPS_MALL_STEWARD', 'ORG_STEWARD']:
                raise errors.PermissionDenied('Only stewards can mark a listing as APPROVED_ORG')

            if s == models.Listing.PENDING:
                model_access.submit_listing(user, instance)
            if s == models.Listing.APPROVED_ORG:
                model_access.approve_listing_by_org_steward(user, instance)
            if s == models.Listing.APPROVED:
                model_access.approve_listing(user, instance)
            if s == models.Listing.REJECTED:
                # TODO: need to get the rejection text from somewhere
                model_access.reject_listing(user, instance, 'TODO: rejection reason')

        if instance.listing_type != validated_data['listing_type']:
            if instance.listing_type:
                old_value = instance.listing_type.title
            else:
                old_value = None
            if validated_data['listing_type']:
                new_value = validated_data['listing_type'].title
            else:
                new_value = None
            change_details.append({'old_value': old_value,
                    'new_value': new_value, 'field_name': 'listing_type'})
            instance.listing_type = validated_data['listing_type']

        if instance.small_icon != validated_data['small_icon']:
            if instance.small_icon:
                old_value = instance.small_icon.id
            else:
                old_value = None
            if validated_data['small_icon']:
                new_value = validated_data['small_icon'].id
            else:
                new_value = None

            change_details.append({'old_value': old_value,
                    'new_value': new_value, 'field_name': 'small_icon'})
            instance.small_icon = validated_data['small_icon']

        if instance.large_icon != validated_data['large_icon']:
            if instance.large_icon:
                old_value = instance.large_icon.id
            else:
                old_value = None
            if validated_data['large_icon']:
                new_value = validated_data['large_icon'].id
            else:
                new_value = None
            change_details.append({'old_value': old_value,
                    'new_value': new_value, 'field_name': 'large_icon'})
            instance.large_icon = validated_data['large_icon']

        if instance.banner_icon != validated_data['banner_icon']:
            if instance.banner_icon:
                old_value = instance.banner_icon.id
            else:
                old_value = None
            if validated_data['banner_icon']:
                new_value = validated_data['banner_icon'].id
            else:
                new_value = None
            change_details.append({'old_value': old_value,
                    'new_value': new_value, 'field_name': 'banner_icon'})
            instance.banner_icon = validated_data['banner_icon']

        if instance.large_banner_icon != validated_data['large_banner_icon']:
            if instance.large_banner_icon:
                old_value = instance.large_banner_icon.id
            else:
                old_value = None
            if validated_data['large_banner_icon']:
                new_value = validated_data['large_banner_icon'].id
            else:
                new_value = None
            change_details.append({'old_value': old_value,
                    'new_value': new_value, 'field_name': 'large_banner_icon'})
            instance.large_banner_icon = validated_data['large_banner_icon']

        if 'contacts' in validated_data:
            old_contact_instances = instance.contacts.all()
            old_contacts = model_access.contacts_to_string(
                old_contact_instances, True)
            new_contacts = model_access.contacts_to_string(
                validated_data['contacts'])
            if old_contacts != new_contacts:
                change_details.append({'old_value': old_contacts,
                    'new_value': new_contacts, 'field_name': 'contacts'})
                instance.contacts.clear()
                for contact in validated_data['contacts']:
                    obj, created = models.Contact.objects.get_or_create(
                        name=contact['name'],
                        email=contact['email'],
                        secure_phone=contact['secure_phone'],
                        unsecure_phone=contact['unsecure_phone'],
                        organization=contact.get('organization', None),
                        contact_type=contact_type_model_access.get_contact_type_by_name(
                            contact['contact_type']['name'])
                    )
                    instance.contacts.add(obj)

        if 'categories' in validated_data:
            old_category_instances = instance.categories.all()
            old_categories = model_access.categories_to_string(
                old_category_instances, True)
            new_categories = model_access.categories_to_string(
                validated_data['categories'], True)
            if old_categories != new_categories:
                change_details.append({'old_value': old_categories,
                    'new_value': new_categories, 'field_name': 'categories'})
                instance.categories.clear()
                for category in validated_data['categories']:
                    instance.categories.add(category)

        if 'owners' in validated_data:
            old_owner_instances = instance.owners.all()
            old_owners = model_access.owners_to_string(
                old_owner_instances, True)
            new_owners = model_access.owners_to_string(
                validated_data['owners'], True)
            if old_owners != new_owners:
                change_details.append({'old_value': old_owners,
                    'new_value': new_owners, 'field_name': 'owners'})
                instance.owners.clear()
                for owner in validated_data['owners']:
                    instance.owners.add(owner)

        # tags will be automatically created if necessary
        if 'tags' in validated_data:
            old_tag_instances = instance.tags.all()
            old_tags = model_access.tags_to_string(old_tag_instances, True)
            new_tags = model_access.tags_to_string(validated_data['tags'])
            if old_tags != new_tags:
                change_details.append({'old_value': old_tags,
                    'new_value': new_tags, 'field_name': 'tags'})
                instance.tags.clear()
                for tag in validated_data['tags']:
                    obj, created = models.Tag.objects.get_or_create(
                        name=tag['name'])
                    instance.tags.add(obj)

        if 'intents' in validated_data:
            old_intent_instances = instance.intents.all()
            old_intents = model_access.intents_to_string(old_intent_instances,
                True)
            new_intents = model_access.intents_to_string(
                validated_data['intents'], True)
            if old_intents != new_intents:
                change_details.append({'old_value': old_intents,
                    'new_value': new_intents, 'field_name': 'intents'})
                instance.intents.clear()
                for intent in validated_data['intents']:
                    instance.intents.add(intent)

        # doc_urls will be automatically created
        if 'doc_urls' in validated_data:
            old_doc_url_instances = model_access.get_doc_urls_for_listing(instance)
            old_doc_urls = model_access.doc_urls_to_string(
                old_doc_url_instances, True)
            new_doc_urls = model_access.doc_urls_to_string(
                validated_data['doc_urls'])
            if old_doc_urls != new_doc_urls:
                change_details.append({
                    'old_value': old_doc_urls,
                    'new_value': new_doc_urls,
                    'field_name': 'doc_urls'})

                new_doc_url_instances = []
                for d in validated_data['doc_urls']:
                    obj, created = models.DocUrl.objects.get_or_create(
                        name=d['name'], url=d['url'], listing=instance)
                    new_doc_url_instances.append(obj)
                for i in old_doc_url_instances:
                    if i not in new_doc_url_instances:
                        logger.info('Deleting doc_url: %s' % i.id)
                        i.delete()

        # screenshots will be automatically created
        if 'screenshots' in validated_data:
            old_screenshot_instances = model_access.get_screenshots_for_listing(instance)
            old_screenshots = model_access.screenshots_to_string(old_screenshot_instances, True)
            new_screenshots = model_access.screenshots_to_string(
                validated_data['screenshots'])
            if old_screenshots != new_screenshots:
                change_details.append({'old_value': old_screenshots,
                    'new_value': new_screenshots, 'field_name': 'screenshots'})

            new_screenshot_instances = []
            for s in validated_data['screenshots']:
                obj, created = models.Screenshot.objects.get_or_create(
                    small_image=image_model_access.get_image_by_id(
                        s['small_image']['id']),
                    large_image=image_model_access.get_image_by_id(
                        s['large_image']['id']),
                    listing=instance)
                new_screenshot_instances.append(obj)
            for i in old_screenshot_instances:
                if i not in new_screenshot_instances:
                    logger.info('Deleting screenshot: %s' % i.id)
                    i.delete()

        if 'agency' in validated_data:
            if instance.agency != validated_data['agency']:
                change_details.append({'old_value': instance.agency.title,
                    'new_value': validated_data['agency'].title, 'field_name': 'agency'})
                instance.agency = validated_data['agency']

        instance.save()

        model_access.log_listing_modification(user, instance, change_details)
        instance.edited_date = datetime.datetime.now(pytz.utc)
        return instance
コード例 #4
0
 def test_get_non_existent_contact_type_by_name(self):
     contact_type = model_access.get_contact_type_by_name('Not Existent', False)
     self.assertIsNone(contact_type)
コード例 #5
0
def create_listing(serializer_instance, validated_data):
    # TODO Put in listing model_access.py
    title = validated_data['title']
    user = generic_model_access.get_profile(serializer_instance.context['request'].user.username)

    logger.info('creating listing {0!s} for user {1!s}'.format(title,
        user.user.username), extra={'request': serializer_instance.context.get('request')})

    # TODO required_listings
    listing = models.Listing(title=title,
        agency=validated_data['agency'],
        description=validated_data['description'],
        launch_url=validated_data['launch_url'],
        version_name=validated_data['version_name'],
        unique_name=validated_data['unique_name'],
        what_is_new=validated_data['what_is_new'],
        description_short=validated_data['description_short'],
        usage_requirements=validated_data['usage_requirements'],
        system_requirements=validated_data['system_requirements'],
        security_marking=validated_data['security_marking'],
        listing_type=validated_data['listing_type'])

    # is_enabled = models.BooleanField(default=True)
    if validated_data['is_enabled'] is not None:
        listing.is_enabled = validated_data['is_enabled']
    # is_featured = models.BooleanField(default=False)
    if validated_data['is_featured'] is not None:
        listing.is_featured = validated_data['is_featured']
    # is_private = models.BooleanField(default=False)
    if validated_data['is_private'] is not None:
        listing.is_private = validated_data['is_private']
    # is_508_compliant = models.BooleanField(default=False)
    if validated_data['is_508_compliant'] is not None:
        listing.is_508_compliant = validated_data['is_508_compliant']

    image_keys = ['small_icon', 'large_icon', 'banner_icon', 'large_banner_icon']
    for image_key in image_keys:
        if validated_data[image_key]:
            new_value_image = image_model_access.get_image_by_id(validated_data[image_key].get('id'))

            if new_value_image is None:
                raise errors.InvalidInput('Error while saving, can not find image by id')
            if image_key == 'small_icon':
                listing.small_icon = new_value_image
            elif image_key == 'large_icon':
                listing.large_icon = new_value_image
            elif image_key == 'banner_icon':
                listing.banner_icon = new_value_image
            elif image_key == 'large_banner_icon':
                listing.large_banner_icon = new_value_image

    listing.save()

    if validated_data.get('contacts') is not None:
        for contact in validated_data['contacts']:
            contact_type_instance = contact_type_model_access.get_contact_type_by_name(contact['contact_type']['name'])
            new_contact, created = models.Contact.objects.get_or_create(name=contact['name'],
                email=contact['email'],
                secure_phone=contact['secure_phone'],
                unsecure_phone=contact['unsecure_phone'],
                organization=contact.get('organization', None),
                contact_type=contact_type_instance)
            new_contact.save()
            listing.contacts.add(new_contact)

    if validated_data.get('owners') is not None:
        if validated_data['owners']:
            for owner in validated_data['owners']:
                listing.owners.add(owner)
        else:
            # if no owners are specified, just add the current user
            listing.owners.add(user)

    if validated_data.get('categories') is not None:
        for category in validated_data['categories']:
            listing.categories.add(category)

    # tags will be automatically created if necessary
    if validated_data.get('tags') is not None:
        for tag in validated_data['tags']:
            obj, created = models.Tag.objects.get_or_create(
                name=tag['name'])
            listing.tags.add(obj)

    if validated_data.get('intents') is not None:
        for intent in validated_data['intents']:
            listing.intents.add(intent)

    # doc_urls will be automatically created
    if validated_data.get('doc_urls') is not None:
        for d in validated_data['doc_urls']:
            doc_url = models.DocUrl(name=d['name'], url=d['url'], listing=listing)
            doc_url.save()

    # screenshots will be automatically created
    if validated_data.get('screenshots') is not None:
        for screenshot_dict in validated_data['screenshots']:
            screenshot = models.Screenshot(
                order=screenshot_dict.get('order'),
                small_image=image_model_access.get_image_by_id(screenshot_dict['small_image']['id']),
                large_image=image_model_access.get_image_by_id(screenshot_dict['large_image']['id']),
                description=screenshot_dict.get('description'),
                listing=listing)
            screenshot.save()

    # create a new activity
    model_access.create_listing(user, listing)

    dispatcher.publish('listing_created', listing=listing, profile=user)
    return listing
コード例 #6
0
def update_listing(serializer_instance, instance, validated_data):
    # TODO Put in listing model_access.py
    user = generic_model_access.get_profile(serializer_instance.context['request'].user.username)

    if user.highest_role() not in ['APPS_MALL_STEWARD', 'ORG_STEWARD']:
        if user not in instance.owners.all():
            raise errors.PermissionDenied(
                'User ({0!s}) is not an owner of this listing'.format(user.username))

    if instance.is_deleted:
        raise errors.PermissionDenied('Cannot update a previously deleted listing')

    change_details = []

    simple_fields = ['title', 'description', 'description_short',
        'launch_url', 'version_name', 'usage_requirements', 'system_requirements', 'unique_name',
        'what_is_new', 'security_marking']

    for i in simple_fields:
        if getattr(instance, i) != validated_data[i]:
            if validated_data[i] is not None:
                change_details.append({'old_value': getattr(instance, i),
                    'new_value': validated_data[i], 'field_name': i})
                setattr(instance, i, validated_data[i])

    if validated_data['is_enabled'] is not None and validated_data['is_enabled'] != instance.is_enabled:
        if validated_data['is_enabled']:
            model_access.enable_listing(user, instance)
        else:
            model_access.disable_listing(user, instance)

        instance.is_enabled = validated_data['is_enabled']

        if validated_data['approval_status'] == models.Listing.APPROVED:
            dispatcher.publish('listing_enabled_status_changed',
                               listing=instance,
                               profile=user,
                               is_enabled=validated_data['is_enabled'])

    if validated_data['is_508_compliant'] is not None and validated_data['is_508_compliant'] != instance.is_508_compliant:
        changeset = {'old_value': model_access.bool_to_string(instance.is_508_compliant),
                'new_value': model_access.bool_to_string(validated_data['is_508_compliant']), 'field_name': 'is_508_compliant'}
        change_details.append(changeset)
        instance.is_508_compliant = validated_data['is_508_compliant']

    if validated_data['is_private'] is not None and validated_data['is_private'] != instance.is_private:
        changeset = {'old_value': model_access.bool_to_string(instance.is_private),
                'new_value': model_access.bool_to_string(validated_data['is_private']), 'field_name': 'is_private'}
        change_details.append(changeset)
        instance.is_private = validated_data['is_private']

        if validated_data['approval_status'] == models.Listing.APPROVED:
            dispatcher.publish('listing_private_status_changed',
                               listing=instance,
                               profile=user,
                               is_private=validated_data['is_private'])

    if validated_data['is_featured'] is not None and validated_data['is_featured'] != instance.is_featured:
        if user.highest_role() not in ['APPS_MALL_STEWARD', 'ORG_STEWARD']:
            raise errors.PermissionDenied('Only stewards can change is_featured setting of a listing')

        change_details.append({'old_value': model_access.bool_to_string(instance.is_featured),
                'new_value': model_access.bool_to_string(validated_data['is_featured']), 'field_name': 'is_featured'})
        instance.is_featured = validated_data['is_featured']
        instance.featured_date = datetime.datetime.now(pytz.utc) if validated_data['is_featured'] else None

    s = validated_data['approval_status']
    if s and s != instance.approval_status:  # Check to see if approval_status has changed
        old_approval_status = instance.approval_status
        if s == models.Listing.APPROVED and user.highest_role() != 'APPS_MALL_STEWARD':
            raise errors.PermissionDenied('Only an APPS_MALL_STEWARD can mark a listing as APPROVED')
        if s == models.Listing.APPROVED_ORG and user.highest_role() not in ['APPS_MALL_STEWARD', 'ORG_STEWARD']:
            raise errors.PermissionDenied('Only stewards can mark a listing as APPROVED_ORG')
        if s == models.Listing.PENDING:
            model_access.submit_listing(user, instance)
        if s == models.Listing.PENDING_DELETION:
            # pending deletion should be handled through ListingPendingDeletionViewSet
            # keeping this here for now for backwards compatibility
            model_access.pending_delete_listing(user, instance, 'Unknown reason')
        if s == models.Listing.APPROVED_ORG:
            model_access.approve_listing_by_org_steward(user, instance)
        if s == models.Listing.APPROVED:
            model_access.approve_listing(user, instance)
        if s == models.Listing.REJECTED:
            # TODO: need to get the rejection text from somewhere
            model_access.reject_listing(user, instance, 'TODO: rejection reason')

        dispatcher.publish('listing_approval_status_changed',
                           listing=instance,
                           profile=user,
                           old_approval_status=old_approval_status,
                           new_approval_status=instance.approval_status)

    if instance.listing_type != validated_data['listing_type']:
        if instance.listing_type:
            old_value = instance.listing_type.title
        else:
            old_value = None
        if validated_data['listing_type']:
            new_value = validated_data['listing_type'].title
        else:
            new_value = None
        change_details.append({'old_value': old_value,
                'new_value': new_value, 'field_name': 'listing_type'})
        instance.listing_type = validated_data['listing_type']

    image_keys = ['small_icon', 'large_icon', 'banner_icon', 'large_banner_icon']
    for image_key in image_keys:
        if validated_data[image_key]:
            old_value = model_access.image_to_string(getattr(instance, image_key), True, 'old_value({0!s})'.format(image_key))
            new_value = model_access.image_to_string(validated_data[image_key], False, 'new_value({0!s})'.format(image_key))

            if old_value != new_value:
                new_value_image = None

                old_image_id = None
                if old_value is not None:
                    old_image_id = getattr(instance, image_key).id
                if validated_data[image_key].get('id') == old_image_id:
                    new_value_image = getattr(instance, image_key)
                    new_value_image.security_marking = validated_data[image_key].get('security_marking')
                    new_value_image.save()
                else:
                    new_value_image = image_model_access.get_image_by_id(validated_data[image_key].get('id'))

                    if new_value_image is None:
                        raise errors.InvalidInput('Error while saving, can not find image by id')

                change_details.append({'old_value': old_value,
                        'new_value': new_value, 'field_name': image_key})

                if image_key == 'small_icon':
                    instance.small_icon = new_value_image
                elif image_key == 'large_icon':
                    instance.large_icon = new_value_image
                elif image_key == 'banner_icon':
                    instance.banner_icon = new_value_image
                elif image_key == 'large_banner_icon':
                    instance.large_banner_icon = new_value_image

    if 'contacts' in validated_data:
        old_contact_instances = instance.contacts.all()
        old_contacts = model_access.contacts_to_string(old_contact_instances, True)
        new_contacts = model_access.contacts_to_string(validated_data['contacts'])

        if old_contacts != new_contacts:
            change_details.append({'old_value': old_contacts,
                'new_value': new_contacts, 'field_name': 'contacts'})
            instance.contacts.clear()
            for contact in validated_data['contacts']:
                # TODO: Smarter Handling of Duplicates Contact Records
                # A contact with the same name and email should be the same contact
                # in the backend.
                # Person1(name='N1',email='*****@*****.**') and
                #    Person1' (name='N1',email='*****@*****.**',secure_phone = '414-444-444')
                # The two people above should be one contact
                # if approval_status: "IN_PROGRESS" then it should be using
                # contact model ids' since it is temporary contacts
                obj, created = models.Contact.objects.get_or_create(
                    name=contact['name'],
                    email=contact['email'],
                    secure_phone=contact['secure_phone'],
                    unsecure_phone=contact['unsecure_phone'],
                    organization=contact.get('organization', None),
                    contact_type=contact_type_model_access.get_contact_type_by_name(
                        contact['contact_type']['name'])
                )
                instance.contacts.add(obj)

    if 'categories' in validated_data:
        old_category_instances = instance.categories.all()
        old_categories = model_access.categories_to_string(old_category_instances, True)
        new_categories = model_access.categories_to_string(validated_data['categories'], True)

        if old_categories != new_categories:
            changeset = {'old_value': old_categories,
                'new_value': new_categories, 'field_name': 'categories'}
            change_details.append(changeset)
            instance.categories.clear()
            for category in validated_data['categories']:
                instance.categories.add(category)

            dispatcher.publish('listing_categories_changed',
                               listing=instance,
                               profile=user,
                               old_categories=old_category_instances,
                               new_categories=validated_data['categories'])

    if 'owners' in validated_data:
        old_owner_instances = instance.owners.all()
        old_owners = model_access.owners_to_string(old_owner_instances, True)
        new_owners = model_access.owners_to_string(validated_data['owners'], True)
        if old_owners != new_owners:
            change_details.append({'old_value': old_owners,
                'new_value': new_owners, 'field_name': 'owners'})
            instance.owners.clear()
            for owner in validated_data['owners']:
                instance.owners.add(owner)

    # tags will be automatically created if necessary
    if 'tags' in validated_data:
        old_tag_instances = instance.tags.all()
        old_tags = model_access.tags_to_string(old_tag_instances, True)
        new_tags = model_access.tags_to_string(validated_data['tags'])

        if old_tags != new_tags:
            changeset = {'old_value': old_tags,
                         'new_value': new_tags, 'field_name': 'tags'}
            change_details.append(changeset)
            instance.tags.clear()
            new_tags_instances = []
            for tag in validated_data['tags']:
                obj, created = models.Tag.objects.get_or_create(
                    name=tag['name'])
                instance.tags.add(obj)
                new_tags_instances.append(obj)

            dispatcher.publish('listing_tags_changed',
                               listing=instance,
                               profile=user,
                               old_tags=old_tag_instances,
                               new_tags=new_tags_instances)

    if 'intents' in validated_data:
        old_intent_instances = instance.intents.all()
        old_intents = model_access.intents_to_string(old_intent_instances, True)
        new_intents = model_access.intents_to_string(validated_data['intents'], True)
        if old_intents != new_intents:
            change_details.append({'old_value': old_intents,
                'new_value': new_intents, 'field_name': 'intents'})
            instance.intents.clear()
            for intent in validated_data['intents']:
                instance.intents.add(intent)

    # doc_urls will be automatically created
    if 'doc_urls' in validated_data:
        old_doc_url_instances = model_access.get_doc_urls_for_listing(instance)
        old_doc_urls = model_access.doc_urls_to_string(old_doc_url_instances, True)
        new_doc_urls = model_access.doc_urls_to_string(validated_data['doc_urls'])
        if old_doc_urls != new_doc_urls:
            change_details.append({
                'old_value': old_doc_urls,
                'new_value': new_doc_urls,
                'field_name': 'doc_urls'})

            new_doc_url_instances = []
            for d in validated_data['doc_urls']:
                obj, created = models.DocUrl.objects.get_or_create(
                    name=d['name'], url=d['url'], listing=instance)
                new_doc_url_instances.append(obj)
            for i in old_doc_url_instances:
                if i not in new_doc_url_instances:
                    logger.info('Deleting doc_url: {0!s}'.format(i.id), extra={'request': serializer_instance.context.get('request')})
                    i.delete()

    # screenshots will be automatically created
    if 'screenshots' in validated_data:
        old_screenshot_instances = model_access.get_screenshots_for_listing(instance)
        old_screenshots = model_access.screenshots_to_string(old_screenshot_instances, True)
        new_screenshots = model_access.screenshots_to_string(validated_data['screenshots'])
        if old_screenshots != new_screenshots:
            change_details.append({'old_value': old_screenshots,
                'new_value': new_screenshots, 'field_name': 'screenshots'})

        new_screenshot_instances = []

        for s in validated_data['screenshots']:
            new_small_image = image_model_access.get_image_by_id(s['small_image']['id'])
            new_small_image.security_marking = s['small_image']['security_marking']
            new_small_image.save()

            new_large_image = image_model_access.get_image_by_id(s['large_image']['id'])
            new_large_image.security_marking = s['large_image']['security_marking']
            new_large_image.save()

            obj, created = models.Screenshot.objects.get_or_create(
                order=s.get('order'),
                small_image=new_small_image,
                large_image=new_large_image,
                description=s.get('description'),
                listing=instance)

            new_screenshot_instances.append(obj)

        for i in old_screenshot_instances:
            if i not in new_screenshot_instances:
                logger.info('Deleting screenshot: {0!s}'.format(i.id), extra={'request': serializer_instance.context.get('request')})
                i.delete()

    if 'agency' in validated_data:
        if instance.agency != validated_data['agency']:
            change_details.append({'old_value': instance.agency.title,
                'new_value': validated_data['agency'].title, 'field_name': 'agency'})
            instance.agency = validated_data['agency']

    instance.save()

    # If the listing was modified add an entry showing changes
    if change_details:
        model_access.log_listing_modification(user, instance, change_details)

        new_change_details = []
        field_to_exclude = ['is_private', 'categories', 'tags']
        for change_detail in change_details:
            if change_detail['field_name'] not in field_to_exclude:
                new_change_details.append(change_detail)

        if new_change_details:
            dispatcher.publish('listing_changed',
                               listing=instance,
                               profile=user,
                               change_details=new_change_details)

    instance.edited_date = datetime.datetime.now(pytz.utc)
    return instance
コード例 #7
0
ファイル: serializers.py プロジェクト: nssbu/ozp-backend
    def create(self, validated_data):
        # logger.debug('inside ListingSerializer.create', extra={'request':self.context.get('request')})
        title = validated_data['title']
        user = generic_model_access.get_profile(
            self.context['request'].user.username)

        logger.info('creating listing {0!s} for user {1!s}'.format(
            title, user.user.username),
                    extra={'request': self.context.get('request')})

        # TODO required_listings
        listing = models.Listing(
            title=title,
            agency=validated_data['agency'],
            description=validated_data['description'],
            launch_url=validated_data['launch_url'],
            version_name=validated_data['version_name'],
            unique_name=validated_data['unique_name'],
            what_is_new=validated_data['what_is_new'],
            description_short=validated_data['description_short'],
            requirements=validated_data['requirements'],
            security_marking=validated_data['security_marking'],
            listing_type=validated_data['listing_type'],
            is_private=validated_data['is_private'])

        image_keys = [
            'small_icon', 'large_icon', 'banner_icon', 'large_banner_icon'
        ]
        for image_key in image_keys:
            if validated_data[image_key]:
                new_value_image = image_model_access.get_image_by_id(
                    validated_data[image_key].get('id'))

                if new_value_image is None:
                    raise errors.InvalidInput(
                        'Error while saving, can not find image by id')

                if image_key == 'small_icon':
                    listing.small_icon = new_value_image
                elif image_key == 'large_icon':
                    listing.large_icon = new_value_image
                elif image_key == 'banner_icon':
                    listing.banner_icon = new_value_image
                elif image_key == 'large_banner_icon':
                    listing.large_banner_icon = new_value_image

        listing.save()

        if validated_data.get('contacts') is not None:
            for contact in validated_data['contacts']:
                contact_type_instance = contact_type_model_access.get_contact_type_by_name(
                    contact['contact_type']['name'])
                new_contact, created = models.Contact.objects.get_or_create(
                    name=contact['name'],
                    email=contact['email'],
                    secure_phone=contact['secure_phone'],
                    unsecure_phone=contact['unsecure_phone'],
                    organization=contact.get('organization', None),
                    contact_type=contact_type_instance)
                new_contact.save()
                listing.contacts.add(new_contact)

        if validated_data.get('owners') is not None:
            if validated_data['owners']:
                for owner in validated_data['owners']:
                    listing.owners.add(owner)
            else:
                # if no owners are specified, just add the current user
                listing.owners.add(user)

        if validated_data.get('categories') is not None:
            for category in validated_data['categories']:
                listing.categories.add(category)

        # tags will be automatically created if necessary
        if validated_data.get('tags') is not None:
            for tag in validated_data['tags']:
                obj, created = models.Tag.objects.get_or_create(
                    name=tag['name'])
                listing.tags.add(obj)

        if validated_data.get('intents') is not None:
            for intent in validated_data['intents']:
                listing.intents.add(intent)

        # doc_urls will be automatically created
        if validated_data.get('doc_urls') is not None:
            for d in validated_data['doc_urls']:
                doc_url = models.DocUrl(name=d['name'],
                                        url=d['url'],
                                        listing=listing)
                doc_url.save()

        # screenshots will be automatically created
        if validated_data.get('screenshots') is not None:
            for screenshot_dict in validated_data['screenshots']:
                screenshot = models.Screenshot(
                    small_image=image_model_access.get_image_by_id(
                        screenshot_dict['small_image']['id']),
                    large_image=image_model_access.get_image_by_id(
                        screenshot_dict['large_image']['id']),
                    listing=listing)
                screenshot.save()

        # create a new activity
        model_access.create_listing(user, listing)

        return listing
コード例 #8
0
def validate_listing(serializer_instance, data):
    # TODO Put in listing model_access.py
    access_control_instance = plugin_manager.get_system_access_control_plugin()
    profile = generic_model_access.get_profile(serializer_instance.context['request'].user.username)

    # This checks to see if value exist as a key and value is not None
    if not data.get('title'):
        raise serializers.ValidationError('Title is required')

    if 'security_marking' not in data:
        raise serializers.ValidationError('Security Marking is Required')

    # Assign a default security_marking level if none is provided
    if not data.get('security_marking'):
        data['security_marking'] = constants.DEFAULT_SECURITY_MARKING

    if not access_control_instance.validate_marking(data['security_marking']):
        raise serializers.ValidationError('Security Marking Format is Invalid')

    # Don't allow user to select a security marking that is above
    # their own access level
    if not system_has_access_control(profile.user.username, data.get('security_marking')):
        raise serializers.ValidationError('Security marking too high for current user')

    # Don't allow 2nd-party user to be an submit/edit a listing
    if system_anonymize_identifiable_data(profile.user.username):
        raise serializers.ValidationError('Permissions are invalid for current profile')

    # TODO: errors.PermissionDenied instead of serializers.ValidationError

    data['description'] = data.get('description')
    data['launch_url'] = data.get('launch_url')
    data['version_name'] = data.get('version_name')
    data['unique_name'] = data.get('unique_name')
    data['what_is_new'] = data.get('what_is_new')
    data['description_short'] = data.get('description_short')
    data['usage_requirements'] = data.get('usage_requirements')
    data['system_requirements'] = data.get('system_requirements')
    data['is_private'] = data.get('is_private')
    data['security_marking'] = data.get('security_marking')

    # only checked on update, not create
    data['is_enabled'] = data.get('is_enabled')
    data['is_508_compliant'] = data.get('is_508_compliant')
    data['is_featured'] = data.get('is_featured')
    data['approval_status'] = data.get('approval_status')

    # Agency
    agency_title = None if data.get('agency') is None else data.get('agency', {}).get('title')
    if agency_title:
        data['agency'] = agency_model_access.get_agency_by_title(agency_title)
        if data['agency'] is None:
            raise serializers.ValidationError('Invalid Agency')
    else:
        data['agency'] = profile.organizations.all()[0]

    # Listing Type
    type_title = None if data.get('listing_type') is None else data.get('listing_type', {}).get('title')
    if type_title:
        data['listing_type'] = model_access.get_listing_type_by_title(type_title)
    else:
        data['listing_type'] = None

    # Images
    image_keys = ['small_icon', 'large_icon', 'banner_icon', 'large_banner_icon']

    for image_key in image_keys:
        current_image_value = data.get(image_key)
        if current_image_value:
            if 'id' not in current_image_value:
                raise serializers.ValidationError('Image({!s}) requires a {!s}'.format(image_key, 'id'))
            if current_image_value.get('security_marking') is None:
                current_image_value['security_marking'] = constants.DEFAULT_SECURITY_MARKING
            if not access_control_instance.validate_marking(current_image_value['security_marking']):
                raise errors.InvalidInput('{!s} Security Marking is invalid'.format(image_key))
        else:
            data[image_key] = None

    # Screenshot
    screenshots = data.get('screenshots')
    if screenshots is not None:
        screenshots_out = []
        image_require_fields = ['id']
        for screenshot_set in screenshots:

            if ('small_image' not in screenshot_set or
                    'large_image' not in screenshot_set):
                raise serializers.ValidationError(
                    'Screenshot Set requires {0!s} fields'.format('small_image, large_icon'))
            screenshot_small_image = screenshot_set.get('small_image')
            screenshot_large_image = screenshot_set.get('large_image')

            for field in image_require_fields:
                if field not in screenshot_small_image:
                    raise serializers.ValidationError('Screenshot Small Image requires a {0!s}'.format(field))

            for field in image_require_fields:
                if field not in screenshot_large_image:
                    raise serializers.ValidationError('Screenshot Large Image requires a {0!s}'.format(field))

            if not screenshot_small_image.get('security_marking'):
                screenshot_small_image['security_marking'] = constants.DEFAULT_SECURITY_MARKING
            if not access_control_instance.validate_marking(screenshot_small_image['security_marking']):
                raise errors.InvalidInput('Security Marking is invalid')

            if not screenshot_large_image.get('security_marking'):
                screenshot_large_image['security_marking'] = constants.DEFAULT_SECURITY_MARKING
            if not access_control_instance.validate_marking(screenshot_large_image['security_marking']):
                raise errors.InvalidInput('Security Marking is invalid')

            screenshots_out.append(screenshot_set)
            data['screenshots'] = screenshots_out
    else:
        data['screenshots'] = None

    # Contacts
    if 'contacts' in data:
        for contact in data['contacts']:
            if 'name' not in contact:
                raise serializers.ValidationError('Contact requires [name] field')
            if 'email' not in contact:
                raise serializers.ValidationError('Contact requires [email] field')
            if 'secure_phone' not in contact:
                contact['secure_phone'] = None
            if 'unsecure_phone' not in contact:
                contact['unsecure_phone'] = None
            if 'contact_type' not in contact:
                raise serializers.ValidationError('Contact requires [contact_type] field')

            contact_type = contact.get('contact_type')
            contact_type_name = None if contact_type is None else contact_type.get('name')

            if not contact_type_name:
                raise serializers.ValidationError('Contact field requires correct format')

            contact_type_instance = contact_type_model_access.get_contact_type_by_name(contact_type_name)
            if not contact_type_instance:
                raise serializers.ValidationError('Contact Type [{}] not found'.format(contact_type_name))

    # owners
    owners = []
    if 'owners' in data:
        for owner in data['owners']:
            user_dict = owner.get('user')
            user_username = None if user_dict is None else user_dict.get('username')

            if not user_username:
                raise serializers.ValidationError('Owner field requires correct format')

            owner_profile = generic_model_access.get_profile(user_username)
            if not owner_profile:
                raise serializers.ValidationError('Owner Profile not found')

            # Don't allow user to select a security marking that is above
            # their own access level
            if not system_has_access_control(owner_profile.user.username, data.get('security_marking')):
                raise serializers.ValidationError('Security marking too high for current owner profile')

            # Don't allow 2nd-party user to be an owner of a listing
            if system_anonymize_identifiable_data(owner_profile.user.username):
                raise serializers.ValidationError('Permissions are invalid for current owner profile')

            owners.append(owner_profile)
    data['owners'] = owners

    # Categories
    categories = []
    if 'categories' in data:
        for category in data['categories']:
            category_title = category.get('title')
            if not category_title:
                raise serializers.ValidationError('Categories field requires correct format')

            category_instance = category_model_access.get_category_by_title(category_title)
            if not category_instance:
                raise serializers.ValidationError('Category [{}] not found'.format(category_title))

            categories.append(category_instance)
    data['categories'] = categories

    # Intents
    intents = []
    if 'intents' in data:
        for intent in data['intents']:
            intent_action = intent.get('action')
            if not intent_action:
                raise serializers.ValidationError('Intent field requires correct format')

            intent_instance = intent_model_access.get_intent_by_action(intent_action)
            if not intent_instance:
                raise serializers.ValidationError('Intent Action [{}] not found'.format(intent_action))

            intents.append(intent_instance)
    data['intents'] = intents

    # doc urls will be created in create()
    if 'doc_urls' in data:
        pass

    # tags will be created (if necessary) in create()
    if 'tags' in data:
        pass

    return data
コード例 #9
0
ファイル: serializers.py プロジェクト: nssbu/ozp-backend
    def validate(self, data):
        access_control_instance = plugin_manager.get_system_access_control_plugin(
        )
        # logger.debug('inside ListingSerializer.validate', extra={'request':self.context.get('request')})
        profile = generic_model_access.get_profile(
            self.context['request'].user.username)

        # This checks to see if value exist as a key and value is not None
        if not data.get('title'):
            raise serializers.ValidationError('Title is required')

        if 'security_marking' not in data:
            raise serializers.ValidationError('Security Marking is Required')

        # Assign a default security_marking level if none is provided
        if not data.get('security_marking'):
            data['security_marking'] = constants.DEFAULT_SECURITY_MARKING

        if not access_control_instance.validate_marking(
                data['security_marking']):
            raise serializers.ValidationError(
                'Security Marking Format is Invalid')

        # Don't allow user to select a security marking that is above
        # their own access level
        if not system_has_access_control(profile.user.username,
                                         data.get('security_marking')):
            raise serializers.ValidationError(
                'Security marking too high for current user')

        data['description'] = data.get('description')
        data['launch_url'] = data.get('launch_url')
        data['version_name'] = data.get('version_name')
        data['unique_name'] = data.get('unique_name')
        data['what_is_new'] = data.get('what_is_new')
        data['description_short'] = data.get('description_short')
        data['requirements'] = data.get('requirements')
        data['is_private'] = data.get('is_private', False)
        data['security_marking'] = data.get('security_marking')

        # only checked on update, not create
        data['is_enabled'] = data.get('is_enabled', False)
        data['is_featured'] = data.get('is_featured', False)
        data['approval_status'] = data.get('approval_status')

        # Agency
        agency_title = None if data.get('agency') is None else data.get(
            'agency', {}).get('title')
        if agency_title:
            data['agency'] = agency_model_access.get_agency_by_title(
                agency_title)
            if data['agency'] is None:
                raise serializers.ValidationError('Invalid Agency')
        else:
            data['agency'] = profile.organizations.all()[0]

        # Listing Type
        type_title = None if data.get('listing_type') is None else data.get(
            'listing_type', {}).get('title')
        if type_title:
            data['listing_type'] = model_access.get_listing_type_by_title(
                type_title)
        else:
            data['listing_type'] = None

        # Images
        image_keys = [
            'small_icon', 'large_icon', 'banner_icon', 'large_banner_icon'
        ]

        for image_key in image_keys:
            current_image_value = data.get(image_key)
            if current_image_value:
                if 'id' not in current_image_value:
                    raise serializers.ValidationError(
                        'Image({!s}) requires a {!s}'.format(image_key, 'id'))
                if current_image_value.get('security_marking') is None:
                    current_image_value[
                        'security_marking'] = constants.DEFAULT_SECURITY_MARKING
                if not access_control_instance.validate_marking(
                        current_image_value['security_marking']):
                    raise errors.InvalidInput(
                        '{!s} Security Marking is invalid'.format(image_key))
            else:
                data[image_key] = None

        # Screenshot
        screenshots = data.get('screenshots')
        if screenshots is not None:
            screenshots_out = []
            image_require_fields = ['id']
            for screenshot_set in screenshots:
                if ('small_image' not in screenshot_set
                        or 'large_image' not in screenshot_set):
                    raise serializers.ValidationError(
                        'Screenshot Set requires {0!s} fields'.format(
                            'small_image, large_icon'))
                screenshot_small_image = screenshot_set.get('small_image')
                screenshot_large_image = screenshot_set.get('large_image')

                for field in image_require_fields:
                    if field not in screenshot_small_image:
                        raise serializers.ValidationError(
                            'Screenshot Small Image requires a {0!s}'.format(
                                field))

                for field in image_require_fields:
                    if field not in screenshot_large_image:
                        raise serializers.ValidationError(
                            'Screenshot Large Image requires a {0!s}'.format(
                                field))

                if not screenshot_small_image.get('security_marking'):
                    screenshot_small_image[
                        'security_marking'] = constants.DEFAULT_SECURITY_MARKING
                if not access_control_instance.validate_marking(
                        screenshot_small_image['security_marking']):
                    raise errors.InvalidInput('Security Marking is invalid')

                if not screenshot_large_image.get('security_marking'):
                    screenshot_large_image[
                        'security_marking'] = constants.DEFAULT_SECURITY_MARKING
                if not access_control_instance.validate_marking(
                        screenshot_large_image['security_marking']):
                    raise errors.InvalidInput('Security Marking is invalid')

                screenshots_out.append(screenshot_set)
                data['screenshots'] = screenshots_out
        else:
            data['screenshots'] = None

        # Contacts
        if 'contacts' in data:
            for contact in data['contacts']:
                if 'name' not in contact:
                    raise serializers.ValidationError(
                        'Contact requires [name] field')
                if 'email' not in contact:
                    raise serializers.ValidationError(
                        'Contact requires [email] field')
                if 'secure_phone' not in contact:
                    contact['secure_phone'] = None
                if 'unsecure_phone' not in contact:
                    contact['unsecure_phone'] = None
                if 'contact_type' not in contact:
                    raise serializers.ValidationError(
                        'Contact requires [contact_type] field')

                contact_type = contact.get('contact_type')
                contact_type_name = None if contact_type is None else contact_type.get(
                    'name')

                if not contact_type_name:
                    raise serializers.ValidationError(
                        'Contact field requires correct format')

                contact_type_instance = contact_type_model_access.get_contact_type_by_name(
                    contact_type_name)
                if not contact_type_instance:
                    raise serializers.ValidationError(
                        'Contact Type [{}] not found'.format(
                            contact_type_name))

        # owners
        owners = []
        if 'owners' in data:
            for owner in data['owners']:
                user_dict = owner.get('user')
                user_username = None if user_dict is None else user_dict.get(
                    'username')

                if not user_username:
                    raise serializers.ValidationError(
                        'Owner field requires correct format')

                owner_profile = generic_model_access.get_profile(user_username)
                if not owner_profile:
                    raise serializers.ValidationError(
                        'Owner Profile not found')

                # Don't allow user to select a security marking that is above
                # their own access level
                if not system_has_access_control(owner_profile.user.username,
                                                 data.get('security_marking')):
                    raise serializers.ValidationError(
                        'Security marking too high for current owner profile')

                owners.append(owner_profile)
        data['owners'] = owners

        # Categories
        categories = []
        if 'categories' in data:
            for category in data['categories']:
                category_title = category.get('title')
                if not category_title:
                    raise serializers.ValidationError(
                        'Categories field requires correct format')

                category_instance = category_model_access.get_category_by_title(
                    category_title)
                if not category_instance:
                    raise serializers.ValidationError(
                        'Category [{}] not found'.format(category_title))

                categories.append(category_instance)
        data['categories'] = categories

        # Intents
        intents = []
        if 'intents' in data:
            for intent in data['intents']:
                intent_action = intent.get('action')
                if not intent_action:
                    raise serializers.ValidationError(
                        'Intent field requires correct format')

                intent_instance = intent_model_access.get_intent_by_action(
                    intent_action)
                if not intent_instance:
                    raise serializers.ValidationError(
                        'Intent Action [{}] not found'.format(intent_action))

                intents.append(intent_instance)
        data['intents'] = intents

        # doc urls will be created in create()
        if 'doc_urls' in data:
            pass

        # tags will be created (if necessary) in create()
        if 'tags' in data:
            pass

        # logger.debug('leaving ListingSerializer.validate', extra={'request':self.context.get('request')})
        return data
コード例 #10
0
 def test_get_non_existent_contact_type_by_name(self):
     contact_type = model_access.get_contact_type_by_name(
         'Not Existent', False)
     self.assertIsNone(contact_type)
コード例 #11
0
def update_listing(serializer_instance, instance, validated_data):
    # TODO Put in listing model_access.py
    user = serializer_instance.context['request'].user
    profile = generic_model_access.get_profile(user.username)

    if profile.highest_role() not in ['APPS_MALL_STEWARD', 'ORG_STEWARD']:
        if profile not in instance.owners.all():
            raise errors.PermissionDenied(
                'User ({0!s}) is not an owner of this listing'.format(user.username))

    if instance.is_deleted:
        raise errors.PermissionDenied('Cannot update a previously deleted listing')

    change_details = []

    simple_fields = ['title', 'description', 'description_short',
        'launch_url', 'version_name', 'usage_requirements', 'system_requirements', 'unique_name',
        'what_is_new', 'security_marking']

    for i in simple_fields:
        if getattr(instance, i) != validated_data[i]:
            change_details.append({'old_value': getattr(instance, i),
                'new_value': validated_data[i], 'field_name': i})
            setattr(instance, i, validated_data[i])

    if validated_data['is_enabled'] != instance.is_enabled:
        if validated_data['is_enabled']:
            model_access.enable_listing(profile, instance)
        else:
            model_access.disable_listing(profile, instance)

        instance.is_enabled = validated_data['is_enabled']

        if validated_data['approval_status'] == models.Listing.APPROVED:
            dispatcher.publish('listing_enabled_status_changed',
                               listing=instance,
                               profile=profile,
                               is_enabled=validated_data['is_enabled'])

    if validated_data['is_508_compliant'] != instance.is_508_compliant:
        changeset = {'old_value': model_access.bool_to_string(instance.is_508_compliant),
                'new_value': model_access.bool_to_string(validated_data['is_508_compliant']), 'field_name': 'is_508_compliant'}
        change_details.append(changeset)
        instance.is_508_compliant = validated_data['is_508_compliant']

    if validated_data['is_private'] != instance.is_private:
        changeset = {'old_value': model_access.bool_to_string(instance.is_private),
                'new_value': model_access.bool_to_string(validated_data['is_private']), 'field_name': 'is_private'}
        change_details.append(changeset)
        instance.is_private = validated_data['is_private']

        if validated_data['approval_status'] == models.Listing.APPROVED:
            dispatcher.publish('listing_private_status_changed',
                               listing=instance,
                               profile=profile,
                               is_private=validated_data['is_private'])

    if validated_data['is_featured'] != instance.is_featured:
        if profile.highest_role() not in ['APPS_MALL_STEWARD', 'ORG_STEWARD']:
            raise errors.PermissionDenied('Only stewards can change is_featured setting of a listing')

        change_details.append({'old_value': model_access.bool_to_string(instance.is_featured),
                'new_value': model_access.bool_to_string(validated_data['is_featured']), 'field_name': 'is_featured'})
        instance.is_featured = validated_data['is_featured']
        instance.featured_date = datetime.datetime.now(pytz.utc) if validated_data['is_featured'] else None

    if validated_data['is_exportable'] != instance.is_exportable:
        if profile.highest_role() not in ['APPS_MALL_STEWARD', 'ORG_STEWARD']:
            raise errors.PermissionDenied('Only stewards can change is_exportable setting of a listing')
            
        change_details.append({'old_value': model_access.bool_to_string(instance.is_exportable),
                'new_value': model_access.bool_to_string(validated_data['is_exportable']), 'field_name': 'is_exportable'})
        instance.is_exportable = validated_data['is_exportable']

    s = validated_data['approval_status']
    if s and s != instance.approval_status:  # Check to see if approval_status has changed
        old_approval_status = instance.approval_status
        if s == models.Listing.APPROVED and profile.highest_role() != 'APPS_MALL_STEWARD':
            raise errors.PermissionDenied('Only an APPS_MALL_STEWARD can mark a listing as APPROVED')
        if s == models.Listing.APPROVED_ORG and profile.highest_role() not in ['APPS_MALL_STEWARD', 'ORG_STEWARD']:
            raise errors.PermissionDenied('Only stewards can mark a listing as APPROVED_ORG')
        if s == models.Listing.PENDING:
            model_access.submit_listing(profile, instance)
        if s == models.Listing.PENDING_DELETION:
            # pending deletion should be handled through ListingPendingDeletionViewSet
            # keeping this here for now for backwards compatibility
            model_access.pending_delete_listing(profile, instance, 'Unknown reason')
        if s == models.Listing.APPROVED_ORG:
            model_access.approve_listing_by_org_steward(profile, instance)
        if s == models.Listing.APPROVED:
            model_access.approve_listing(profile, instance)
        if s == models.Listing.REJECTED:
            # TODO: need to get the rejection text from somewhere
            model_access.reject_listing(profile, instance, 'TODO: rejection reason')

        dispatcher.publish('listing_approval_status_changed',
                           listing=instance,
                           profile=profile,
                           old_approval_status=old_approval_status,
                           new_approval_status=instance.approval_status)

    if instance.listing_type != validated_data['listing_type']:
        if instance.listing_type:
            old_value = instance.listing_type.title
        else:
            old_value = None
        if validated_data['listing_type']:
            new_value = validated_data['listing_type'].title
        else:
            new_value = None
        change_details.append({'old_value': old_value,
                'new_value': new_value, 'field_name': 'listing_type'})
        instance.listing_type = validated_data['listing_type']

    image_keys = ['small_icon', 'large_icon', 'banner_icon', 'large_banner_icon']
    for image_key in image_keys:
        if validated_data[image_key]:
            old_value = model_access.image_to_string(getattr(instance, image_key), True, 'old_value({0!s})'.format(image_key))
            new_value = model_access.image_to_string(validated_data[image_key], False, 'new_value({0!s})'.format(image_key))

            if old_value != new_value:
                new_value_image = None

                old_image_id = None
                if old_value is not None:
                    old_image_id = getattr(instance, image_key).id
                if validated_data[image_key].get('id') == old_image_id:
                    new_value_image = getattr(instance, image_key)
                    new_value_image.security_marking = validated_data[image_key].get('security_marking')
                    new_value_image.save()
                else:
                    new_value_image = image_model_access.get_image_by_id(validated_data[image_key].get('id'))

                    if new_value_image is None:
                        raise errors.InvalidInput('Error while saving, can not find image by id')

                change_details.append({'old_value': old_value,
                        'new_value': new_value, 'field_name': image_key})

                if image_key == 'small_icon':
                    instance.small_icon = new_value_image
                elif image_key == 'large_icon':
                    instance.large_icon = new_value_image
                elif image_key == 'banner_icon':
                    instance.banner_icon = new_value_image
                elif image_key == 'large_banner_icon':
                    instance.large_banner_icon = new_value_image

    if 'contacts' in validated_data:
        old_contact_instances = instance.contacts.all()
        old_contacts = model_access.contacts_to_string(old_contact_instances, True)
        new_contacts = model_access.contacts_to_string(validated_data['contacts'])

        if old_contacts != new_contacts:
            change_details.append({'old_value': old_contacts,
                'new_value': new_contacts, 'field_name': 'contacts'})
            instance.contacts.clear()
            for contact in validated_data['contacts']:
                # TODO: Smarter Handling of Duplicates Contact Records
                # A contact with the same name and email should be the same contact
                # in the backend.
                # Person1(name='N1',email='*****@*****.**') and
                #    Person1' (name='N1',email='*****@*****.**',secure_phone = '414-444-444')
                # The two people above should be one contact
                # if approval_status: "IN_PROGRESS" then it should be using
                # contact model ids' since it is temporary contacts
                obj, created = models.Contact.objects.get_or_create(
                    name=contact['name'],
                    email=contact['email'],
                    secure_phone=contact['secure_phone'],
                    unsecure_phone=contact['unsecure_phone'],
                    organization=contact.get('organization', None),
                    contact_type=contact_type_model_access.get_contact_type_by_name(
                        contact['contact_type']['name'])
                )
                instance.contacts.add(obj)

    if 'categories' in validated_data:
        old_category_instances = instance.categories.all()
        old_categories = model_access.categories_to_string(old_category_instances, True)
        new_categories = model_access.categories_to_string(validated_data['categories'], True)

        if old_categories != new_categories:
            changeset = {'old_value': old_categories,
                'new_value': new_categories, 'field_name': 'categories'}
            change_details.append(changeset)
            instance.categories.clear()
            for category in validated_data['categories']:
                instance.categories.add(category)

            dispatcher.publish('listing_categories_changed',
                               listing=instance,
                               profile=profile,
                               old_categories=old_category_instances,
                               new_categories=validated_data['categories'])

    if 'owners' in validated_data:
        old_owner_instances = instance.owners.all()
        old_owners = model_access.owners_to_string(old_owner_instances, True)
        new_owners = model_access.owners_to_string(validated_data['owners'], True)
        if old_owners != new_owners:
            change_details.append({'old_value': old_owners,
                'new_value': new_owners, 'field_name': 'owners'})
            instance.owners.clear()
            for owner in validated_data['owners']:
                instance.owners.add(owner)

    # tags will be automatically created if necessary
    if 'tags' in validated_data:
        old_tag_instances = instance.tags.all()
        old_tags = model_access.tags_to_string(old_tag_instances, True)
        new_tags = model_access.tags_to_string(validated_data['tags'])

        if old_tags != new_tags:
            changeset = {'old_value': old_tags,
                         'new_value': new_tags, 'field_name': 'tags'}
            change_details.append(changeset)
            instance.tags.clear()
            new_tags_instances = []
            for tag in validated_data['tags']:
                obj, created = models.Tag.objects.get_or_create(
                    name=tag['name'])
                instance.tags.add(obj)
                new_tags_instances.append(obj)

            dispatcher.publish('listing_tags_changed',
                               listing=instance,
                               profile=profile,
                               old_tags=old_tag_instances,
                               new_tags=new_tags_instances)

    # tags will be automatically created if necessary
    if 'custom_fields' in validated_data:
        old_custom_field_instances = instance.custom_fields.all()
        custom_fields = model_access.custom_field_values_to_string(old_custom_field_instances, True)
        new_custom_fields = model_access.custom_field_values_to_string(validated_data['custom_fields'])
        if custom_fields != new_custom_fields:
            changeset = {'old_value': custom_fields,
                         'new_value': new_custom_fields,
                         'field_name': 'custom_fields'}
            change_details.append(changeset)
            new_custom_fields_instances = []
            for cfv in validated_data['custom_fields']:
                id = cfv['custom_field'].id
                cf = models.CustomField.objects.find_by_id(id=id)
                obj, created = models.CustomFieldValue.objects.get_or_create(
                    listing=instance,
                    custom_field=cf,
                    value=cfv['value']
                )
                if created:
                    instance.custom_fields.add(obj)
                new_custom_fields_instances.append(obj)

            dispatcher.publish('listing_custom_field_values_changed',
                               listing=instance,
                               profile=profile,
                               old_tags=old_custom_field_instances,
                               new_tags=new_custom_fields_instances)

    if 'intents' in validated_data:
        old_intent_instances = instance.intents.all()
        old_intents = model_access.intents_to_string(old_intent_instances, True)
        new_intents = model_access.intents_to_string(validated_data['intents'], True)
        if old_intents != new_intents:
            change_details.append({'old_value': old_intents,
                'new_value': new_intents, 'field_name': 'intents'})
            instance.intents.clear()
            for intent in validated_data['intents']:
                instance.intents.add(intent)

    # doc_urls will be automatically created
    if 'doc_urls' in validated_data:
        old_doc_url_instances = model_access.get_doc_urls_for_listing(instance)
        old_doc_urls = model_access.doc_urls_to_string(old_doc_url_instances, True)
        new_doc_urls = model_access.doc_urls_to_string(validated_data['doc_urls'])
        if old_doc_urls != new_doc_urls:
            change_details.append({
                'old_value': old_doc_urls,
                'new_value': new_doc_urls,
                'field_name': 'doc_urls'})

            new_doc_url_instances = []
            for d in validated_data['doc_urls']:
                obj, created = models.DocUrl.objects.get_or_create(
                    name=d['name'], url=d['url'], listing=instance)
                new_doc_url_instances.append(obj)
            for i in old_doc_url_instances:
                if i not in new_doc_url_instances:
                    logger.info('Deleting doc_url: {0!s}'.format(i.id), extra={'request': serializer_instance.context.get('request')})
                    i.delete()

    # screenshots will be automatically created
    if 'screenshots' in validated_data:
        old_screenshot_instances = model_access.get_screenshots_for_listing(instance)
        old_screenshots = model_access.screenshots_to_string(old_screenshot_instances, True)
        new_screenshots = model_access.screenshots_to_string(validated_data['screenshots'])
        if old_screenshots != new_screenshots:
            change_details.append({'old_value': old_screenshots,
                'new_value': new_screenshots, 'field_name': 'screenshots'})

        new_screenshot_instances = []

        for s in validated_data['screenshots']:
            new_small_image = image_model_access.get_image_by_id(s['small_image']['id'])
            new_small_image.security_marking = s['small_image']['security_marking']
            new_small_image.save()

            new_large_image = image_model_access.get_image_by_id(s['large_image']['id'])
            new_large_image.security_marking = s['large_image']['security_marking']
            new_large_image.save()

            obj, created = models.Screenshot.objects.get_or_create(
                order=s.get('order'),
                small_image=new_small_image,
                large_image=new_large_image,
                description=s.get('description'),
                listing=instance)

            new_screenshot_instances.append(obj)

        for i in old_screenshot_instances:
            if i not in new_screenshot_instances:
                logger.info('Deleting screenshot: {0!s}'.format(i.id), extra={'request': serializer_instance.context.get('request')})
                i.delete()

    if 'agency' in validated_data:
        if instance.agency != validated_data['agency']:
            change_details.append({'old_value': instance.agency.title,
                'new_value': validated_data['agency'].title, 'field_name': 'agency'})
            instance.agency = validated_data['agency']

    instance.save()

    # If the listing was modified add an entry showing changes
    if change_details:
        model_access.log_listing_modification(profile, instance, change_details)

        new_change_details = []
        field_to_exclude = ['is_private', 'categories', 'tags']
        for change_detail in change_details:
            if change_detail['field_name'] not in field_to_exclude:
                new_change_details.append(change_detail)

        if new_change_details:
            dispatcher.publish('listing_changed',
                               listing=instance,
                               profile=profile,
                               change_details=new_change_details)

    instance.edited_date = datetime.datetime.now(pytz.utc)
    return instance
コード例 #12
0
 def test__get_contact_type_by_name__not_found_raises_error(self):
     with self.assertRaises(ContactType.DoesNotExist):
         model_access.get_contact_type_by_name('Not Existent')
コード例 #13
0
    def test__get_contact_type_by_name(self):
        expected = self.contact_types[0]

        result = model_access.get_contact_type_by_name(expected.name)

        self.assertEqual(result, expected)