mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-10-31 10:42:43 +00:00 
			
		
		
		
	Add delete corpora function and function to view an delete foreign jobs and corpora.
This commit is contained in:
		| @@ -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')) | ||||||
|   | |||||||
| @@ -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 application’s custom anonymous user by setting | ' Flask-Login is told to use the application’s custom anonymous user by setting | ||||||
|   | |||||||
| @@ -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"> | ||||||
|   | |||||||
| @@ -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"); | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								app/utils.py
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								app/utils.py
									
									
									
									
									
								
							| @@ -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() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user