Esempio n. 1
0
def entity_edit(collection_path, entity_id, form_data, git_name, git_mail, agent=''):
    """The time-consuming parts of entity-edit.
    
    @param collection_path: str Absolute path to collection
    @param entity_id: str
    @param form_data: dict
    @param git_name: Username of git committer.
    @param git_mail: Email of git committer.
    @param agent: (optional) Name of software making the change.
    """
    logger.debug('tasks.entity.entity_edit(%s,%s,%s,%s,%s)' % (
        git_name, git_mail, collection_path, entity_id, agent))
    collection = Collection.from_identifier(Identifier(path=collection_path))
    entity = Entity.from_identifier(Identifier(id=entity_id))
    gitstatus.lock(settings.MEDIA_BASE, 'entity_edit')
    
    exit,status,updated_files = entity.save(
        git_name, git_mail,
        collection,
        form_data
    )
    
    dvcs_tasks.gitstatus_update.apply_async(
        (collection.path,),
        countdown=2
    )
    return status,collection_path,entity_id
Esempio n. 2
0
def delete_file( git_name, git_mail, collection_path, entity_id, file_basename, agent='' ):
    """
    @param collection_path: string
    @param entity_id: string
    @param file_basename: string
    @param git_name: Username of git committer.
    @param git_mail: Email of git committer.
    @param agent: (optional) Name of software making the change.
    """
    logger.debug('delete_file(%s,%s,%s,%s,%s,%s)' % (git_name, git_mail, collection_path, entity_id, file_basename, agent))
    gitstatus.lock(settings.MEDIA_BASE, 'delete_file')
    file_id = os.path.splitext(file_basename)[0]
    file_ = DDRFile.from_identifier(Identifier(file_id))
    entity = Entity.from_identifier(Identifier(entity_id))
    collection = Collection.from_identifier(Identifier(path=collection_path))
    logger.debug('delete from repository')
    rm_files,updated_files = entity.prep_rm_file(file_)
    status,message = commands.file_destroy(
        git_name, git_mail,
        collection, entity,
        rm_files, updated_files,
        agent
    )
    logger.debug('delete from search index')
    try:
        docstore.delete(settings.DOCSTORE_HOSTS, settings.DOCSTORE_INDEX, file_.id)
    except ConnectionError:
        logger.error('Could not delete document from Elasticsearch.')
    return status,message,collection_path,file_basename
Esempio n. 3
0
def changelog( request, eid ):
    entity = Entity.from_identifier(Identifier(eid))
    check_object(entity, request, check_locks=False)
    collection = entity.collection()
    return render(request, 'webui/entities/changelog.html', {
        'collection': collection,
        'entity': entity,
    })
Esempio n. 4
0
 def after_return(self, status, retval, task_id, args, kwargs, einfo):
     logger.debug('EntityReloadTask.after_return(%s, %s, %s, %s, %s)' % (status, retval, task_id, args, kwargs))
     collection_path = args[0]
     collection = Collection.from_identifier(Identifier(path=collection_path))
     entity_id = args[1]
     entity = Entity.from_identifier(Identifier(id=entity_id))
     lockstatus = entity.unlock(task_id)
     gitstatus.update(settings.MEDIA_BASE, collection_path)
     gitstatus.unlock(settings.MEDIA_BASE, 'reload_files')
Esempio n. 5
0
def unlock( request, eid, task_id ):
    """Provides a way to remove entity lockfile through the web UI.
    """
    git_name,git_mail = enforce_git_credentials(request)
    entity = Entity.from_identifier(Identifier(eid))
    check_object(entity, request)
    collection = entity.collection()
    
    if task_id and entity.locked() and (task_id == entity.locked()):
        entity.unlock(task_id)
        messages.success(request, 'Object <b>%s</b> unlocked.' % entity.id)
    return HttpResponseRedirect(entity.absolute_url())
Esempio n. 6
0
def files_dedupe( request, eid ):
    git_name,git_mail = enforce_git_credentials(request)
    entity = Entity.from_identifier(Identifier(eid))
    check_object(entity, request)
    collection = entity.collection()
    check_parent(collection)
    
    duplicate_masters = entity.detect_file_duplicates('master')
    duplicate_mezzanines = entity.detect_file_duplicates('mezzanine')
    duplicates = duplicate_masters + duplicate_mezzanines
    
    if request.method == 'POST':
        form = RmDuplicatesForm(request.POST)
        if form.is_valid() and form.cleaned_data.get('confirmed',None) \
                and (form.cleaned_data['confirmed'] == True):
            # remove duplicates
            entity.rm_file_duplicates()
            # update metadata files
            entity.write_json()
            entity.write_mets()
            updated_files = [entity.json_path, entity.mets_path,]
            success_msg = WEBUI_MESSAGES['VIEWS_ENT_UPDATED']
            exit,status = commands.entity_update(
                git_name, git_mail,
                collection, entity,
                updated_files,
                agent=settings.AGENT
            )
            collection.cache_delete()
            if exit:
                messages.error(request, WEBUI_MESSAGES['ERROR'].format(status))
            else:
                # update search index
                try:
                    entity.post_json()
                except ConnectionError:
                    logger.error('Could not post to Elasticsearch.')
                dvcs_tasks.gitstatus_update.apply_async(
                    (collection.path,),
                    countdown=2
                )
                # positive feedback
                messages.success(request, success_msg)
                return HttpResponseRedirect(entity.absolute_url())
    else:
        data = {}
        form = RmDuplicatesForm()
    return render(request, 'webui/entities/files-dedupe.html', {
        'collection': collection,
        'entity': entity,
        'duplicates': duplicates,
        'form': form,
    })
Esempio n. 7
0
def detail( request, eid ):
    entity = Entity.from_identifier(Identifier(eid))
    check_object(entity, request, check_locks=False)
    collection = entity.collection()
    entity.model_def_commits()
    entity.model_def_fields()
    tasks = request.session.get('celery-tasks', [])
    return render(request, 'webui/entities/detail.html', {
        'collection': collection,
        'entity': entity,
        'children_urls': entity.children_urls(),
        'tasks': tasks,
        'entity_unlock_url': entity.unlock_url(entity.locked()),
        # cache this for later
        'annex_info': annex_info(repository(collection.path_abs)),
    })
Esempio n. 8
0
def reload_files(collection_path, entity_id, git_name, git_mail, agent=''):
    """Regenerate entity.json's list of child files.
    
    @param collection_path: string
    @param entity_id: string
    @param git_name: Username of git committer.
    @param git_mail: Email of git committer.
    @param agent: (optional) Name of software making the change.
    """
    logger.debug('tasks.entity.reload_files(%s,%s,%s,%s,%s)' % (collection_path, entity_id, git_name, git_mail, agent))
    gitstatus.lock(settings.MEDIA_BASE, 'reload_files')
    entity = Entity.from_identifier(Identifier(entity_id))
    collection = Collection.from_identifier(Identifier(path=collection_path))
    
    exit,status,updated_files = entity.save(
        git_name, git_mail,
        collection,
        {}
    )

    return status,collection_path,entity_id
Esempio n. 9
0
def files_reload( request, eid ):
    """Regenerates list of file info dicts with list of File objects
    """
    git_name,git_mail = enforce_git_credentials(request)
    entity = Entity.from_identifier(Identifier(eid))
    check_object(entity, request)
    collection = entity.collection()
    check_parent(collection)
    
    entity_tasks.reload_files(
        request,
        collection, entity,
        git_name, git_mail, settings.AGENT
    )
    
    messages.success(
        request,
        'Regenerating files list for <a href="%s">%s</a>.' % (
            entity.absolute_url(), entity.id
        )
    )
    return HttpResponseRedirect(entity.absolute_url())
Esempio n. 10
0
def delete( request, eid, confirm=False ):
    """Delete the requested entity from the collection.
    """
    git_name,git_mail = enforce_git_credentials(request)
    entity = Entity.from_identifier(Identifier(eid))
    check_object(entity, request)
    collection = entity.collection()
    check_parent(collection)
    
    if request.method == 'POST':
        form = DeleteEntityForm(request.POST)
        if form.is_valid() and form.cleaned_data['confirmed']:
            entity_tasks.delete(
                collection, entity, git_name, git_mail, settings.AGENT
            )
            return HttpResponseRedirect(collection.absolute_url())
    else:
        form = DeleteEntityForm()
    return render(request, 'webui/entities/delete.html', {
        'entity': entity,
        'form': form,
    })
Esempio n. 11
0
def _create_entity(request, eidentifier, collection, git_name, git_mail):
    """used by both new_idservice and new_manual
    """
    # load Entity object, inherit values from parent, write back to file
    exit,status = Entity.new(eidentifier, git_name, git_mail, agent=settings.AGENT)
    entity = Entity.from_identifier(eidentifier)
    
    collection.cache_delete()
    if exit:
        logger.error(exit)
        logger.error(status)
        messages.error(request, WEBUI_MESSAGES['ERROR'].format(status))
    else:
        # update search index
        try:
            entity.post_json()
        except ConnectionError:
            logger.error('Could not post to Elasticsearch.')
        dvcs_tasks.gitstatus_update.apply_async(
            (collection.path,),
            countdown=2
        )
    return entity
Esempio n. 12
0
def children(request, eid):
    entity = Entity.from_identifier(Identifier(eid))
    check_object(entity, request, check_locks=False)
    collection = entity.collection()
    
    # models that are under entity but are not nodes (i.e. files)
    
    # paginate
    thispage = request.GET.get('page', 1)
    paginator = Paginator(
        [c for c in entity.children() if c.identifier.model != 'file'],
        settings.RESULTS_PER_PAGE
    )
    page = paginator.page(thispage)
    return render(request, 'webui/entities/children.html', {
        'collection': collection,
        'entity': entity,
        'children_models': [m for m in CHILDREN['entity'] if m not in NODES],
        'children_urls': entity.children_urls(active='children'),
        'paginator': paginator,
        'page': page,
        'thispage': thispage,
    })
Esempio n. 13
0
def delete_entity( git_name, git_mail, collection_path, entity_id, agent='' ):
    """
    @param collection_path: string
    @param entity_id: string
    @param git_name: Username of git committer.
    @param git_mail: Email of git committer.
    @param agent: (optional) Name of software making the change.
    """
    gitstatus.lock(settings.MEDIA_BASE, 'delete_entity')
    logger.debug('collection_delete_entity(%s,%s,%s,%s,%s)' % (git_name, git_mail, collection_path, entity_id, agent))
    # remove the entity
    collection = Collection.from_identifier(Identifier(collection_path))
    entity = Entity.from_identifier(Identifier(entity_id))
    status,message = commands.entity_destroy(
        git_name, git_mail,
        collection, entity,
        agent
    )
    # update search index
    try:
        docstore.delete(settings.DOCSTORE_HOSTS, settings.DOCSTORE_INDEX, entity_id)
    except ConnectionError:
        logger.error('Could not delete document from Elasticsearch.')
    return status,message,collection_path,entity_id
Esempio n. 14
0
def new( request, repo, org, cid ):
    """Gets new EID from workbench, creates new entity record.
    
    If it messes up, goes back to collection.
    """
    git_name = request.session.get('git_name')
    git_mail = request.session.get('git_mail')
    if not (git_name and git_mail):
        messages.error(request, WEBUI_MESSAGES['LOGIN_REQUIRED'])
    collection = Collection.from_request(request)
    if collection.locked():
        messages.error(request, WEBUI_MESSAGES['VIEWS_COLL_LOCKED'].format(collection.id))
        return HttpResponseRedirect(collection.absolute_url())
    collection.repo_fetch()
    if collection.repo_behind():
        messages.error(request, WEBUI_MESSAGES['VIEWS_COLL_BEHIND'].format(collection.id))
        return HttpResponseRedirect(collection.absolute_url())
    
    ic = idservice.IDServiceClient()
    # resume session
    auth_status,auth_reason = ic.resume(request.session['idservice_token'])
    if auth_status != 200:
        request.session['idservice_username'] = None
        request.session['idservice_token'] = None
        messages.warning(
            request,
            'Session resume failed: %s %s (%s)' % (
                auth_status,auth_reason,settings.IDSERVICE_API_BASE
            )
        )
        return HttpResponseRedirect(collection.absolute_url())
    # get new entity ID
    http_status,http_reason,new_entity_id = ic.next_object_id(
        collection.identifier,
        'entity'
    )
    if http_status not in [200,201]:
        err = '%s %s' % (http_status, http_reason)
        msg = WEBUI_MESSAGES['VIEWS_ENT_ERR_NO_IDS'] % (settings.IDSERVICE_API_BASE, err)
        logger.error(msg)
        messages.error(request, msg)
        return HttpResponseRedirect(collection.absolute_url())
    
    eidentifier = Identifier(id=new_entity_id)
    # create new entity
    entity_path = eidentifier.path_abs()
    # write entity.json template to entity location
    fileio.write_text(
        Entity(entity_path).dump_json(template=True),
        settings.TEMPLATE_EJSON
    )
    
    # commit files
    exit,status = commands.entity_create(
        git_name, git_mail,
        collection, eidentifier,
        [collection.json_path_rel, collection.ead_path_rel],
        [settings.TEMPLATE_EJSON, settings.TEMPLATE_METS],
        agent=settings.AGENT
    )
    
    # load Entity object, inherit values from parent, write back to file
    entity = Entity.from_identifier(eidentifier)
    entity.inherit(collection)
    entity.write_json()
    updated_files = [entity.json_path]
    exit,status = commands.entity_update(
        git_name, git_mail,
        collection, entity,
        updated_files,
        agent=settings.AGENT
    )
    
    collection.cache_delete()
    if exit:
        logger.error(exit)
        logger.error(status)
        messages.error(request, WEBUI_MESSAGES['ERROR'].format(status))
    else:
        # update search index
        try:
            entity.post_json(settings.DOCSTORE_HOSTS, settings.DOCSTORE_INDEX)
        except ConnectionError:
            logger.error('Could not post to Elasticsearch.')
        gitstatus_update.apply_async((collection.path,), countdown=2)
        # positive feedback
        return HttpResponseRedirect(reverse('webui-entity-edit', args=entity.idparts))
    
    # something happened...
    logger.error('Could not create new entity!')
    messages.error(request, WEBUI_MESSAGES['VIEWS_ENT_ERR_CREATE'])
    return HttpResponseRedirect(collection.absolute_url())
Esempio n. 15
0
def edit( request, eid ):
    """
    UI for Entity topics uses TagManager to represent topics as tags,
    and typeahead.js so users only have to type part of a topic.
    """
    git_name,git_mail = enforce_git_credentials(request)
    entity = Entity.from_identifier(Identifier(eid))
    check_object(entity, request)
    module = entity.identifier.fields_module()
    collection = entity.collection()
    check_parent(collection)
    
    # load topics choices data
    # TODO This should be baked into models somehow.
    topics_terms = tagmanager_terms('topics')
    facility_terms = tagmanager_terms('facility')
    entity.model_def_commits()
    entity.model_def_fields()
    if request.method == 'POST':
        form = DDRForm(request.POST, fields=module.FIELDS)
        if form.is_valid():
            
            # clean up after TagManager
            hidden_topics = request.POST.get('hidden-topics', None)
            hidden_facility = request.POST.get('hidden-facility', None)
            if hidden_topics:
                form.cleaned_data['topics'] = tagmanager_process_tags(hidden_topics)
            if hidden_facility:
                form.cleaned_data['facility'] = tagmanager_process_tags(hidden_facility)

            entity.form_post(form.cleaned_data)
            # write these so we see a change on refresh
            # will be rewritten in entity.save()
            entity.write_json()
            
            # do the rest in the background:
            # update inheriable fields, commit files, delete cache,
            # update search index, update git status
            entity_tasks.edit(
                request,
                collection, entity, form.cleaned_data,
                git_name, git_mail, settings.AGENT
            )
            
            return HttpResponseRedirect(entity.absolute_url())
    else:
        form = DDRForm(entity.form_prep(), fields=module.FIELDS)

    # coerce term:id dicts into old-style "term [id]" strings
    entity_topics = [
        converters.dict_to_textbracketid(item, ['term','id'])
        for item in entity.topics
    ]
    entity_facility = [
        converters.dict_to_textbracketid(item, ['term','id'])
        for item in entity.facility
    ]

    topics_prefilled = tagmanager_prefilled_terms(entity_topics, topics_terms)
    facility_prefilled = tagmanager_prefilled_terms(entity_facility, facility_terms)
    # selected terms that don't appear in field_terms
    topics_legacy = tagmanager_legacy_terms(entity_topics, topics_terms)
    facility_legacy = tagmanager_legacy_terms(entity_facility, facility_terms)
    return render(request, 'webui/entities/edit-json.html', {
        'collection': collection,
        'entity': entity,
        'form': form,
        # data for TagManager
        'topics_terms': topics_terms,
        'facility_terms': facility_terms,
        'topics_prefilled': topics_prefilled,
        'facility_prefilled': facility_prefilled,
    })