Add delete corpora function and function to view an delete foreign jobs and corpora.

This commit is contained in:
Stephan Porada 2019-09-24 14:04:49 +02:00
parent 4858f36d76
commit ed288598cd
5 changed files with 121 additions and 19 deletions

View File

@ -1,11 +1,11 @@
from app.utils import background_delete_job from app.utils import background_delete_job, background_delete_corpus
from flask import (abort, current_app, flash, redirect, request, from flask import (abort, current_app, flash, redirect, request,
render_template, url_for, send_from_directory) render_template, url_for, send_from_directory)
from flask_login import current_user, login_required from flask_login import current_user, login_required
from . import main from . import main
from .forms import CreateCorpusForm from .forms import CreateCorpusForm
from .. import db from .. import db
from ..models import Corpus from ..models import Corpus, Job
import os import os
import threading import threading
@ -18,13 +18,16 @@ def index():
@main.route('/corpora/<int:corpus_id>') @main.route('/corpora/<int:corpus_id>')
@login_required @login_required
def corpus(corpus_id): def corpus(corpus_id):
corpus = current_user.corpora.filter_by(id=corpus_id).first() if (current_user.is_administrator()):
corpus = Corpus.query.get_or_404(corpus_id)
else:
corpus = current_user.corpora.filter_by(id=corpus_id).first()
if not corpus: if not corpus:
print('Corpus not found.') print('Corpus not found.')
abort(404) abort(404)
dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'], dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'],
str(current_user.id), str(corpus.user_id),
'corpora', 'corpora',
str(corpus.id)) str(corpus.id))
files = {} files = {}
@ -42,12 +45,15 @@ def corpus(corpus_id):
@login_required @login_required
def corpus_download(corpus_id): def corpus_download(corpus_id):
file = request.args.get('file') file = request.args.get('file')
corpus = current_user.corpora.filter_by(id=corpus_id).first() if (current_user.is_administrator()):
corpus = Corpus.query.get_or_404(corpus_id)
else:
corpus = current_user.corpora.filter_by(id=corpus_id).first()
if not file or not corpus: if not file or not corpus:
print('File not found.') print('File not found.')
abort(404) abort(404)
dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'], dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'],
str(current_user.id), str(corpus.user_id),
'corpora', 'corpora',
str(corpus.id)) str(corpus.id))
return send_from_directory(as_attachment=True, return send_from_directory(as_attachment=True,
@ -91,13 +97,16 @@ def dashboard():
@main.route('/jobs/<int:job_id>') @main.route('/jobs/<int:job_id>')
@login_required @login_required
def job(job_id): def job(job_id):
job = current_user.jobs.filter_by(id=job_id).first() if (current_user.is_administrator()):
job = Job.query.get_or_404(job_id)
else:
job = current_user.jobs.filter_by(id=job_id).first()
if not job: if not job:
print('Job not found.') print('Job not found.')
abort(404) abort(404)
dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'], dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'],
str(current_user.id), str(job.user_id),
'jobs', 'jobs',
str(job.id)) str(job.id))
files = {} files = {}
@ -126,12 +135,15 @@ def job(job_id):
@login_required @login_required
def job_download(job_id): def job_download(job_id):
file = request.args.get('file') file = request.args.get('file')
job = current_user.jobs.filter_by(id=job_id).first() if (current_user.is_administrator()):
job = Job.query.get_or_404(job_id)
else:
job = current_user.jobs.filter_by(id=job_id).first()
if not file or not job: if not file or not job:
print('File not found.') print('File not found.')
abort(404) abort(404)
dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'], dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'],
str(current_user.id), str(job.user_id),
'jobs', 'jobs',
str(job.id)) str(job.id))
return send_from_directory(as_attachment=True, return send_from_directory(as_attachment=True,
@ -149,3 +161,15 @@ def delete_job(job_id):
delete_thread.start() delete_thread.start()
flash('Job has been deleted!') flash('Job has been deleted!')
return redirect(url_for('main.dashboard')) return redirect(url_for('main.dashboard'))
@main.route('/corpora/<int:corpus_id>/delete')
@login_required
def delete_corpus(corpus_id):
delete_thread = threading.Thread(
target=background_delete_corpus,
args=(current_app._get_current_object(), corpus_id)
)
delete_thread.start()
flash('Corpus has been deleted!')
return redirect(url_for('main.dashboard'))

View File

@ -8,7 +8,6 @@ from datetime import datetime
import os import os
import shutil import shutil
import logging import logging
import time
class Permission: class Permission:
@ -357,6 +356,20 @@ class Corpus(db.Model):
'title': self.title, 'title': self.title,
'user_id': self.user_id} 'user_id': self.user_id}
def delete_corpus(self):
logger = logging.getLogger(__name__)
delete_path = os.path.join('/mnt/opaque/', str(self.user_id), 'corpora',
str(self.id))
logger.warning('Delete path is: {}'.format(delete_path))
while os.path.exists(delete_path):
try:
shutil.rmtree(delete_path, ignore_errors=True)
logger.warning('Path does still exist.')
except OSError:
pass
db.session.delete(self)
db.session.commit()
''' '''
' Flask-Login is told to use the applications custom anonymous user by setting ' Flask-Login is told to use the applications custom anonymous user by setting

View File

@ -2,18 +2,36 @@
{% block page_content %} {% block page_content %}
<script> <script>
var CORPUS_ID = {{ corpus.id }} var corpus_user_id = {{ corpus.user_id|tojson|safe }}
socket.emit('inspect_user', {{ corpus_user_id }});
</script>
<script>
var CORPUS_ID = {{ corpus.id|tojson|safe }}
var foreignCorpusFlag;
{% if current_user.id == corpus.user_id %}
foreignCorpusFlag = false;
{% else %}
foreignCorpusFlag = true;
{% endif %}
class InformationUpdater { class InformationUpdater {
constructor(corpusId) { constructor(corpusId) {
this.corpusId = corpusId; this.corpusId = corpusId;
corporaSubscribers.push(this); if (foreignCorpusFlag) {
foreignCorpusSubscribers.push(this);
} else {
corporaSubscribers.push(this);
}
} }
_init() { _init() {
var creationDateElement, descriptionElement, titleElement; var creationDateElement, descriptionElement, titleElement;
this.corpus = corpora[this.corpusId]; if (foreignCorpusFlag) {
this.corpus = foreignCorpora[this.corpusId];
} else {
this.corpus = corpora[this.corpusId];
}
creationDateElement = document.getElementById("creation-date"); creationDateElement = document.getElementById("creation-date");
creationDateElement.value = (new Date(this.corpus.creation_date * 1000)).toLocaleString(); creationDateElement.value = (new Date(this.corpus.creation_date * 1000)).toLocaleString();
descriptionElement = document.getElementById("description"); descriptionElement = document.getElementById("description");
@ -62,6 +80,21 @@
<div class="col s12 m4"> <div class="col s12 m4">
<h3 id="title"></h3> <h3 id="title"></h3>
<p id="description"></p> <p id="description"></p>
<h2>Actions:</h2>
<!-- Confirm deletion of job with modal dialogue
Modal Trigger-->
<a href="#modal-confirm-delete" class="waves-effect waves-light btn red modal-trigger"><i class="material-icons left">delete</i>Delete Corpus</a>
<!-- Modal Strucutre -->
<div id="modal-confirm-delete" class="modal">
<div class="modal-content">
<h4>Confirm deletion</h4>
<p>Do you really want to delete the Corpus {{corpus.title}}?
All files will be permanently deleted.</p>
</div>
<div class="modal-footer">
<a href="{{ url_for('main.delete_corpus', corpus_id=corpus.id) }}" class="modal-close waves-effect waves-green btn red"><i class="material-icons left">delete</i>Delete Corpus</a></a>
</div>
</div>
</div> </div>
<div class="col s12 m8"> <div class="col s12 m8">

View File

@ -2,12 +2,26 @@
{% block page_content %} {% block page_content %}
<script> <script>
var JOB_ID = {{ job.id }} var job_user_id = {{ job.user_id|tojson|safe }}
socket.emit('inspect_user', job_user_id);
</script>
<script>
var JOB_ID = {{ job.id|tojson|safe }}
var foreignJobFlag;
{% if current_user.id == job.user_id %}
foreignJobFlag = false;
{% else %}
foreignJobFlag = true;
{% endif %}
class InformationUpdater { class InformationUpdater {
constructor(jobId) { constructor(jobId) {
this.jobId = jobId; this.jobId = jobId;
jobsSubscribers.push(this); if (foreignJobFlag) {
foreignJobsSubscribers.push(this);
} else {
jobsSubscribers.push(this);
}
} }
_init() { _init() {
@ -15,7 +29,11 @@
memMbElement, nCoresElement, serviceElement, serviceArgsElement, memMbElement, nCoresElement, serviceElement, serviceArgsElement,
serviceVersionElement, statusColor, statusElement, titleElement; serviceVersionElement, statusColor, statusElement, titleElement;
this.job = jobs[this.jobId]; if (foreignJobFlag) {
this.job = foreignJobs[this.jobId];
} else {
this.job = jobs[this.jobId];
}
creationDateElement = document.getElementById("creation-date"); creationDateElement = document.getElementById("creation-date");
creationDateElement.value = (new Date(this.job.creation_date * 1000)).toLocaleString(); creationDateElement.value = (new Date(this.job.creation_date * 1000)).toLocaleString();
descriptionElement = document.getElementById("description"); descriptionElement = document.getElementById("description");

View File

@ -1,4 +1,4 @@
from .models import Job, User from .models import Job, User, Corpus
from . import db from . import db
import logging import logging
@ -15,6 +15,7 @@ def background_delete_user(app, current_user_id):
logger.warning('Called by delete_thread.') logger.warning('Called by delete_thread.')
logger.warning('User id is: {}.'.format(current_user_id)) logger.warning('User id is: {}.'.format(current_user_id))
jobs = Job.query.filter_by(user_id=current_user_id).all() jobs = Job.query.filter_by(user_id=current_user_id).all()
corpora = Corpus.query.filter_by(user_id=current_user_id).all()
logger.warning('Jobs to delete are: {}'.format(jobs)) logger.warning('Jobs to delete are: {}'.format(jobs))
user = User.query.get_or_404(current_user_id) user = User.query.get_or_404(current_user_id)
for job in jobs: for job in jobs:
@ -29,7 +30,10 @@ def background_delete_user(app, current_user_id):
logger.warning('Job status is deleted.') logger.warning('Job status is deleted.')
job.delete_job() job.delete_job()
deleted = True deleted = True
logger.warning('Loop has ended.') logger.warning('Job deletion loop has ended.')
for corpus in corpora:
corpus.delete_corpus()
logger.warning('Corpus deletion loop has ended.')
user.delete_user() user.delete_user()
@ -51,3 +55,13 @@ def background_delete_job(app, job_id):
job.delete_job() job.delete_job()
deleted = True deleted = True
logger.warning('Loop has ended.') logger.warning('Loop has ended.')
def background_delete_corpus(app, corpus_id):
logger = logging.getLogger(__name__)
with app.app_context():
logger.warning('Called by delete_thread.')
logger.warning('Corpus id is: {}.'.format(corpus_id))
corpus = Corpus.query.filter_by(id=corpus_id).first()
logger.warning('Corpus object is: {}'.format(corpus))
corpus.delete_corpus()