<commit_before># -*- coding: utf-8; -*-
#
# This file is part of Superdesk.
#
# Copyright 2013, 2014 Sourcefabric z.u. and contributors.
#
# For the full copyright and license information, please see the
# AUTHORS and LICENSE files distributed with this source code, or
# at https://www.sourcefabric.org/superdesk/license
import json

from eve.utils import config, ParsedRequest
from flask import request

import superdesk
from apps.archive.archive import SOURCE as ARCHIVE
from apps.auth import get_user, get_user_id
from apps.content import push_content_notification
from apps.tasks import send_to
from superdesk import get_resource_service
from superdesk.errors import SuperdeskApiError, InvalidStateTransitionError
from superdesk.metadata.item import CONTENT_STATE, ITEM_STATE
from superdesk.metadata.utils import item_url
from superdesk.resource import Resource
from superdesk.services import BaseService
from superdesk.workflow import is_workflow_state_transition_valid
from superdesk.utc import utcnow
from flask_babel import _


class DuplicateResource(Resource):
    endpoint_name = 'duplicate'
    resource_title = endpoint_name

    schema = {
        'desk': Resource.rel('desks', False, required=True),
        'stage': Resource.rel('stages', False, required=False),
        'type': {
            'type': 'string',
            'required': True
        },
        'item_id': {
            'type': 'string',
            'required': False
        }
    }

    url = 'archive/<{0}:guid>/duplicate'.format(item_url)

    resource_methods = ['POST']
    item_methods = []

    privileges = {'POST': 'duplicate'}


class DuplicateService(BaseService):
    def create(self, docs, **kwargs):
        guid_of_item_to_be_duplicated = request.view_args['guid']

        guid_of_duplicated_items = []

        for doc in docs:
            archive_service = get_resource_service(ARCHIVE)
            archived_doc = {}

            if doc.get('type') == 'archived':
                archived_service = get_resource_service('archived')
                req = ParsedRequest()
                query = {'query':
                         {'filtered':
                          {'filter':
                           {'bool':
                            {'must': [
                                {'term': {'item_id': doc.get('item_id')}}
                            ]}}}}, "sort": [{"_current_version": "desc"}], "size": 1}
                req.args = {'source': json.dumps(query)}
                archived_docs = archived_service.get(req=req, lookup=None)
                if archived_docs.count() > 0:
                    archived_doc = archived_docs[0]

            else:
                archived_doc = archive_service.find_one(req=None, _id=guid_of_item_to_be_duplicated)

            self._validate(archived_doc, doc, guid_of_item_to_be_duplicated)

            # reset timestamps
            archived_doc['versioncreated'] = archived_doc['firstcreated'] = utcnow()
            archived_doc['firstpublished'] = None

            send_to(doc=archived_doc, desk_id=doc.get('desk'), stage_id=doc.get('stage'),
                    default_stage='working_stage', user_id=get_user_id())
            new_guid = archive_service.duplicate_content(archived_doc)
            guid_of_duplicated_items.append(new_guid)

        if kwargs.get('notify', True):
            push_content_notification([archived_doc])

        return guid_of_duplicated_items

    def _validate(self, doc_in_archive, doc, guid_to_duplicate):
        """Validates if the given archived_doc is still eligible to be duplicated.

        Rules:
            1. Is the item requested found in archive collection?
            2. Is workflow transition valid?
            3. Is item locked by another user?

        :param doc_in_archive: object representing the doc in archive collection
        :type doc_in_archive: dict
        :param doc: object received as part of request
        :type doc: dict
        :param guid_to_duplicate: GUID of the item to duplicate<commit_msg>use duplicate endpoint for duplicate to personal (#2051)<commit_after># -*- coding: utf-8; -*-
#
# This file is part of Superdesk.
#
# Copyright 2013, 2014 Sourcefabric z.u. and contributors.
#
# For the full copyright and license information, please see the
# AUTHORS and LICENSE files distributed with this source code, or
# at https://www.sourcefabric.org/superdesk/license
import json

from eve.utils import config, ParsedRequest
from flask import request, current_app as app

import superdesk
from apps.archive.archive import SOURCE as ARCHIVE
from apps.auth import get_user, get_user_id
from apps.content import push_content_notification
from apps.tasks import send_to
from superdesk import get_resource_service
from superdesk.errors import SuperdeskApiError, InvalidStateTransitionError
from superdesk.metadata.item import CONTENT_STATE, ITEM_STATE
from superdesk.metadata.utils import item_url
from superdesk.resource import Resource
from superdesk.services import BaseService
from superdesk.workflow import is_workflow_state_transition_valid
from superdesk.utc import utcnow
from flask_babel import _


class DuplicateResource(Resource):
    endpoint_name = 'duplicate'
    resource_title = endpoint_name

    schema = {
        'desk': Resource.rel('desks', False, required=True, nullable=True),
        'stage': Resource.rel('stages', False, required=False),
        'type': {
            'type': 'string',
            'required': True
        },
        'item_id': {
            'type': 'string',
            'required': False
        }
    }

    url = 'archive/<{0}:guid>/duplicate'.format(item_url)

    resource_methods = ['POST']
    item_methods = []

    privileges = {'POST': 'duplicate'}


class DuplicateService(BaseService):

    def on_create(self, docs):
        for doc in docs:
            if not doc.get('desk') and not app.config['WORKFLOW_ALLOW_COPY_TO_PERSONAL']:
                raise SuperdeskApiError.forbiddenError(message=_("Duplicate to Personal space is not allowed."))

    def create(self, docs, **kwargs):
        guid_of_item_to_be_duplicated = request.view_args['guid']

        guid_of_duplicated_items = []

        for doc in docs:
            archive_service = get_resource_service(ARCHIVE)
            archived_doc = {}

            if doc.get('type') == 'archived':
                archived_service = get_resource_service('archived')
                req = ParsedRequest()
                query = {'query':
                         {'filtered':
                          {'filter':
                           {'bool':
                            {'must': [
                                {'term': {'item_id': doc.get('item_id')}}
                            ]}}}}, "sort": [{"_current_version": "desc"}], "size": 1}
                req.args = {'source': json.dumps(query)}
                archived_docs = archived_service.get(req=req, lookup=None)
                if archived_docs.count() > 0:
                    archived_doc = archived_docs[0]

            else:
                archived_doc = archive_service.find_one(req=None, _id=guid_of_item_to_be_duplicated)

            self._validate(archived_doc, doc, guid_of_item_to_be_duplicated)

            # reset timestamps
            archived_doc['versioncreated'] = archived_doc['firstcreated'] = utcnow()
            archived_doc['firstpublished'] = None

            send_to(doc=archived_doc, desk_id=doc.get('desk'), stage_id=doc.get('stage'),
                    default_stage='working_stage', user_id=get_user_id())

            if not doc.get('desk'):  # item copied to personal space
                archived_doc['state'] = CONTENT_STATE.PROGRESS

            new_guid = archive_service.duplicate_content(archived_doc)
            guid_of_duplicated_items.append(new_guid)

        if kwargs.get('notify', True):
            push_content_notification([archived_doc])

        return guid_of_duplicated_items

    def _validate(self, doc_in_archive, doc, guid_to_duplicate):
        """Validates if the given archived_doc is still eligible to be duplicated.

        Rules:
            1. Is the item requested found in archive collection?
            2. Is workflow transition valid?
            3. Is item locked by another user?

        :param doc_in_archive: object representing the doc in archive collection
        :type doc_in_archive: dict
        :param doc: object received as part of request
        :type doc: dict
        :param guid_to_duplicate: GUID of the item to duplicate
{'fraction_non_alphanumeric': 0.09332864345175285, 'fraction_numerical': 0.004220893422441084, 'mean_word_length': 2.5601001669449084, 'pattern_counts': {'":': 6, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6256799', 'n_tokens_mistral': 2454, 'n_tokens_neox': 2341, 'n_words': 611}