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
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
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, })
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')
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())
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, })
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)), })
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
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())
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, })
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
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, })
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
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())
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, })