Exemple #1
0
def pending_delete_listing(author, listing, pending_description):
    """
    Submit a listing for Deletion

    Args:
        author
        listing

    Return:
        listing
    """
    # TODO: check that all required fields are set
    old_approval_status = listing.approval_status
    listing = _add_listing_activity(author, listing, models.ListingActivity.PENDING_DELETION,
                                    description=pending_description)
    listing.approval_status = models.Listing.PENDING_DELETION
    listing.is_enabled = False
    listing.edited_date = utils.get_now_utc()
    listing.save()

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

    return listing
Exemple #2
0
def reject_listing(steward, listing, rejection_description):
    """
    Reject a submitted listing

    Args:
        steward
        listing
        rejection_description

    Return:
        Listing
    """
    old_approval_status = listing.approval_status
    listing = _add_listing_activity(steward, listing, models.ListingActivity.REJECTED, description=rejection_description)
    listing.approval_status = models.Listing.REJECTED
    listing.edited_date = utils.get_now_utc()
    listing.save()

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

    return listing
def delete_bookmark_entry_for_profile(request_profile, bookmark_entry_instance):
    """
    Delete Bookmark Entry for profile
    Validate make sure user has access

    Deleting a BookmarkEntry that is a folder will have this behavior
        BookmarkEntry.manager.get(id=5).delete()

        DELETE FROM "bookmark_parents" WHERE "bookmark_parents"."from_bookmarkentry_id" IN (5)
        DELETE FROM "bookmark_parents" WHERE "bookmark_parents"."to_bookmarkentry_id" IN (5)
        DELETE FROM "ozpcenter_bookmarkpermission" WHERE "ozpcenter_bookmarkpermission"."bookmark_id" IN (5)
        DELETE FROM "ozpcenter_bookmarkentry" WHERE "ozpcenter_bookmarkentry"."id" IN (5)

        (5,
         {'ozpcenter.BookmarkEntry': 1,
          'ozpcenter.BookmarkEntry_bookmark_parent': 3,
          'ozpcenter.BookmarkPermission': 1})
    """
    check_permission_for_bookmark_entry(request_profile, bookmark_entry_instance)

    if bookmark_entry_instance.type == FOLDER_TYPE:
        # root_folder = create_get_user_root_bookmark_folder(request_profile)
        folder_queries = build_folder_queries_recursive_flatten(request_profile, bookmark_entry_instance, is_start=True)

        dispatcher.publish('remove_bookmark_folder', bookmark_entry=bookmark_entry_instance, folder_queries=folder_queries)

        for current_query in folder_queries:
            current_query.delete()

    elif bookmark_entry_instance.type == LISTING_TYPE:
        # If bookmark_entry_instance type is LISTING_TYPE then just delete
        bookmark_entry_instance.delete()
Exemple #4
0
def _get_profile_by_dn(dn, issuer_dn='default issuer dn'):
    """
    Returns a user profile for a given DN

    If a profile isn't found with the given DN, create one
    """
    # look up the user with this dn. if the user doesn't exist, create them
    profile = models.Profile.objects.filter(dn__iexact=dn).first()
    if profile:
        if not profile.user.is_active:
            logger.warning(
                'User {0!s} tried to login but is inactive'.format(dn))
            return None
        # update the issuer_dn
        if profile.issuer_dn != issuer_dn:
            logger.info('updating issuer dn for user {0!s}'.format(
                profile.user.username))
            profile.issuer_dn = issuer_dn
            profile.save()
        return profile
    else:
        logger.info('creating new user for dn: {0!s}'.format(dn))
        if 'CN=' in dn:
            cn = utils.find_between(dn, 'CN=', ',')
        else:
            cn = dn

        kwargs = {'display_name': cn, 'dn': dn, 'issuer_dn': issuer_dn}
        # sanitize username
        username = cn[0:30]
        username = username.replace(' ', '_')  # no spaces
        username = username.replace("'", "")  # no apostrophes
        username = username.lower()  # all lowercase
        # make sure this username doesn't exist
        count = User.objects.filter(username=username).count()
        if count != 0:
            new_username = username[0:27]
            count = User.objects.filter(
                username__startswith=new_username).count()
            new_username = '******'.format(new_username, count + 1)
            username = new_username

        # now check again - if this username exists, we have a problemce
        count = User.objects.filter(username=username).count()
        if count != 0:
            logger.error(
                'Cannot create new user for dn {0!s}, username {1!s} already exists'
                .format(dn, username))
            return None

        profile = models.Profile.create_user(username, **kwargs)
        logger.info('created new profile for user {0!s}'.format(
            profile.user.username))
        dispatcher.publish('profile_created', profile=profile)
        return profile
def update_bookmark_entry_for_profile(request_profile, bookmark_entry_instance, bookmark_parent_object, title):
    """
    Update Bookmark Entries

    Method Responsibilities:
        * Rename folder bookmark titles
        * Moving folder/listing bookmarks under different folders

    Args:
        request_profile
        bookmark_entry_instance
        bookmark_parent_object:
            `BookmarkEntry` bookmark instance where request_profile want to put bookmark_entry_instance in that folder
        title
    """
    if bookmark_parent_object is None and title is None:
        raise errors.PermissionDenied('Need at least the bookmark_parent or title field')
    # Check to see if request profile has access to bookmark_entry_instance
    # (bookmark_entry_instance can be folder or listing bookmark)
    check_permission_for_bookmark_entry(request_profile, bookmark_entry_instance)

    folder_title_changed = False
    bookmark_entry_moved = False

    if bookmark_parent_object:
        if bookmark_parent_object.type != FOLDER_TYPE:
            raise errors.PermissionDenied('bookmark_parent_object needs to be a folder type')
        # make sure user has owner access on bookmark_parent_object
        check_permission_for_bookmark_entry(request_profile, bookmark_parent_object)

        # get bookmark entries to folder relationships for request_profile
        bookmark_entry_folder_relationships = bookmark_entry_instance.bookmark_parent.filter(
            bookmark_permission__profile=request_profile)
        bookmark_entry_instance.bookmark_parent.remove(*bookmark_entry_folder_relationships)

        bookmark_entry_instance.bookmark_parent.add(bookmark_parent_object)
        bookmark_entry_moved = True

    if bookmark_entry_instance.type == FOLDER_TYPE:
        if title:
            bookmark_entry_instance.title = title
            folder_title_changed = True

    bookmark_entry_instance.save()

    if bookmark_entry_moved or folder_title_changed:
        dispatcher.publish('update_bookmark_entry',
            bookmark_entry_instance=bookmark_entry_instance,
            bookmark_parent_object=bookmark_parent_object,
            folder_title_changed=folder_title_changed,
            bookmark_entry_moved=bookmark_entry_moved)

    return bookmark_entry_instance
Exemple #6
0
def create_listing_review(username, listing, rating, text=None, review_parent=None, create_day_delta=None):
    """
    Create a new review for a listing

    Args:
        username (str): author's username
        rating (int): rating, 1-5
        text (Optional(str)): review text
        create_date_delta(Optional(int)): Create date in days delta
            example: 0 = Now, -1 = Minus one day, 1 = plus one day

    Returns:
        {
            "rate": rate,
            "text": text,
            "author": author.id,
            "listing": listing.id,
            "id": review.id
        }
    """
    author = generic_model_access.get_profile(username)
    review = models.Review(listing=listing, author=author, rate=rating, text=text, review_parent=review_parent)

    if create_day_delta:
        # created_date = models.DateTimeField(default=utils.get_now_utc)
        review.created_date = utils.get_now_utc(days_delta=create_day_delta)

    review.save()

    # add this action to the log
    change_details = [
        {
            'field_name': 'rate',
            'old_value': None,
            'new_value': rating
        },
        {
            'field_name': 'text',
            'old_value': None,
            'new_value': text
        }
    ]
    listing = review.listing
    listing = _add_listing_activity(author, listing,
        models.ListingActivity.REVIEWED, change_details=change_details)

    # update this listing's rating
    _update_rating(username, listing)

    if review.review_parent is None:
        dispatcher.publish('listing_review_created', listing=listing, profile=author, rating=rating, text=text)
    return review
def _get_profile_by_dn(dn, issuer_dn='default issuer dn'):
    """
    Returns a user profile for a given DN

    If a profile isn't found with the given DN, create one
    """
    # look up the user with this dn. if the user doesn't exist, create them
    profile = models.Profile.objects.filter(dn__iexact=dn).first()
    if profile:
        if not profile.user.is_active:
            logger.warning('User {0!s} tried to login but is inactive'.format(dn))
            return None
        # update the issuer_dn
        if profile.issuer_dn != issuer_dn:
            logger.info('updating issuer dn for user {0!s}'.format(profile.user.username))
            profile.issuer_dn = issuer_dn
            profile.save()
        return profile
    else:
        logger.info('creating new user for dn: {0!s}'.format(dn))
        if 'CN=' in dn:
            cn = utils.find_between(dn, 'CN=', ',')
        else:
            cn = dn

        kwargs = {'display_name': cn, 'dn': dn, 'issuer_dn': issuer_dn}
        # sanitize username
        username = cn[0:30]
        username = username.replace(' ', '_')  # no spaces
        username = username.replace("'", "")  # no apostrophes
        username = username.lower()  # all lowercase
        # make sure this username doesn't exist
        count = User.objects.filter(username=username).count()
        if count != 0:
            new_username = username[0:27]
            count = User.objects.filter(username__startswith=new_username).count()
            new_username = '******'.format(new_username, count + 1)
            username = new_username

        # now check again - if this username exists, we have a problemce
        count = User.objects.filter(username=username).count()
        if count != 0:
            logger.error('Cannot create new user for dn {0!s}, username {1!s} already exists'.format(dn, username))
            return None

        profile = models.Profile.create_user(username, **kwargs)
        logger.info('created new profile for user {0!s}'.format(profile.user.username))
        dispatcher.publish('profile_created', profile=profile)
        return profile
Exemple #8
0
def create_listing_review(username,
                          listing,
                          rating,
                          text=None,
                          review_parent=None):
    """
    Create a new review for a listing

    Args:
        username (str): author's username
        rating (int): rating, 1-5
        text (Optional(str)): review text

    Returns:
        {
            "rate": rate,
            "text": text,
            "author": author.id,
            "listing": listing.id,
            "id": review.id
        }
    """
    author = generic_model_access.get_profile(username)

    review = models.Review(listing=listing,
                           author=author,
                           rate=rating,
                           text=text,
                           review_parent=review_parent)
    review.save()

    # update this listing's rating
    _update_rating(username, listing)

    #resp = {
    #    "rate": rating,
    #    "text": text,
    #    "author": author.id,
    #    "listing": listing.id,
    #    "id": review.id
    #}

    dispatcher.publish('listing_review_created',
                       listing=listing,
                       profile=author,
                       rating=rating,
                       text=text)
    return review
def edit_listing_review(username, review, rate, text=None):
    """
    Edit an existing review

    Args:
        username: user making this request
        review (models.Review): review to modify
        rate (int): rating (1-5)
        text (Optional(str)): review text

    Returns:
        The modified review
    """
    # only the author of a review can edit it
    user = generic_model_access.get_profile(username)
    if review.author.user.username != username:
        raise errors.PermissionDenied()

    change_details = [{
        'field_name': 'rate',
        'old_value': review.rate,
        'new_value': rate
    }, {
        'field_name': 'text',
        'old_value': review.text,
        'new_value': text
    }]

    listing = review.listing
    listing = _add_listing_activity(user,
                                    listing,
                                    models.ListingActivity.REVIEW_EDITED,
                                    change_details=change_details)

    review.rate = rate
    review.text = text
    review.edited_date = utils.get_now_utc()
    review.save()

    _update_rating(username, listing)

    dispatcher.publish('listing_review_changed',
                       listing=listing,
                       profile=user,
                       rating=rate,
                       text=text)
    return review
def delete_listing(username, listing, delete_description):
    """
    TODO: need a way to keep track of this listing as being deleted.

    for now just remove
    """
    profile = generic_model_access.get_profile(username)
    # app_owners = [i.user.username for i in listing.owners.all()]
    # ensure user is the author of this review, or that user is an org
    # steward or apps mall steward

    # Don't allow 2nd-party user to be an delete a listing
    if system_anonymize_identifiable_data(profile.user.username):
        raise errors.PermissionDenied(
            'Current profile does not have delete permissions')

    priv_roles = ['APPS_MALL_STEWARD', 'ORG_STEWARD']
    if profile.highest_role(
    ) in priv_roles or listing.approval_status == 'IN_PROGRESS':
        pass
    else:
        raise errors.PermissionDenied(
            'Only Org Stewards and admins can delete listings')

    if listing.is_deleted:
        raise errors.PermissionDenied('The listing has already been deleted')

    old_approval_status = listing.approval_status
    listing = _add_listing_activity(profile,
                                    listing,
                                    models.ListingActivity.DELETED,
                                    description=delete_description)
    listing.is_deleted = True
    listing.is_enabled = False
    listing.is_featured = False
    listing.approval_status = models.Listing.DELETED
    # TODO Delete the values of other field
    # Keep lisiting as shell listing for history
    listing.save()
    # listing.delete()

    dispatcher.publish('listing_approval_status_changed',
                       listing=listing,
                       profile=profile,
                       old_approval_status=old_approval_status,
                       new_approval_status=listing.approval_status)
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
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
Exemple #13
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
Exemple #14
0
def create_listing(serializer_instance, validated_data):
    # TODO Put in listing model_access.py
    user = serializer_instance.context['request'].user
    profile = generic_model_access.get_profile(user.username)

    title = validated_data['title']

    logger.info('creating listing {0!s} for user {1!s}'.format(title,
        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_private=validated_data['is_private'],
        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(profile)

    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()

    if 'custom_fields' in validated_data:
        for field_value_dict in validated_data['custom_fields']:
            field_id = field_value_dict['custom_field'].id
            field = models.CustomField.objects.find_by_id(id=field_id)
            value = field_value_dict['value']

            field_value = models.CustomFieldValue(listing=listing,
                                                  custom_field=field,
                                                  value=value)
            field_value.save()

            listing.custom_fields.add(field_value)

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

    dispatcher.publish('listing_created', listing=listing, profile=profile)
    return listing