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, | ||||
|                    render_template, url_for, send_from_directory) | ||||
| from flask_login import current_user, login_required | ||||
| from . import main | ||||
| from .forms import CreateCorpusForm | ||||
| from .. import db | ||||
| from ..models import Corpus | ||||
| from ..models import Corpus, Job | ||||
| import os | ||||
| import threading | ||||
|  | ||||
| @@ -18,13 +18,16 @@ def index(): | ||||
| @main.route('/corpora/<int:corpus_id>') | ||||
| @login_required | ||||
| def corpus(corpus_id): | ||||
|     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: | ||||
|         print('Corpus not found.') | ||||
|         abort(404) | ||||
|  | ||||
|     dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'], | ||||
|                        str(current_user.id), | ||||
|                        str(corpus.user_id), | ||||
|                        'corpora', | ||||
|                        str(corpus.id)) | ||||
|     files = {} | ||||
| @@ -42,12 +45,15 @@ def corpus(corpus_id): | ||||
| @login_required | ||||
| def corpus_download(corpus_id): | ||||
|     file = request.args.get('file') | ||||
|     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: | ||||
|         print('File not found.') | ||||
|         abort(404) | ||||
|     dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'], | ||||
|                        str(current_user.id), | ||||
|                        str(corpus.user_id), | ||||
|                        'corpora', | ||||
|                        str(corpus.id)) | ||||
|     return send_from_directory(as_attachment=True, | ||||
| @@ -91,13 +97,16 @@ def dashboard(): | ||||
| @main.route('/jobs/<int:job_id>') | ||||
| @login_required | ||||
| def job(job_id): | ||||
|     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: | ||||
|         print('Job not found.') | ||||
|         abort(404) | ||||
|  | ||||
|     dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'], | ||||
|                        str(current_user.id), | ||||
|                        str(job.user_id), | ||||
|                        'jobs', | ||||
|                        str(job.id)) | ||||
|     files = {} | ||||
| @@ -126,12 +135,15 @@ def job(job_id): | ||||
| @login_required | ||||
| def job_download(job_id): | ||||
|     file = request.args.get('file') | ||||
|     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: | ||||
|         print('File not found.') | ||||
|         abort(404) | ||||
|     dir = os.path.join(current_app.config['OPAQUE_STORAGE_DIRECTORY'], | ||||
|                        str(current_user.id), | ||||
|                        str(job.user_id), | ||||
|                        'jobs', | ||||
|                        str(job.id)) | ||||
|     return send_from_directory(as_attachment=True, | ||||
| @@ -149,3 +161,15 @@ def delete_job(job_id): | ||||
|     delete_thread.start() | ||||
|     flash('Job has been deleted!') | ||||
|     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 shutil | ||||
| import logging | ||||
| import time | ||||
|  | ||||
|  | ||||
| class Permission: | ||||
| @@ -357,6 +356,20 @@ class Corpus(db.Model): | ||||
|                 'title': self.title, | ||||
|                 '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 | ||||
|   | ||||
| @@ -2,18 +2,36 @@ | ||||
|  | ||||
| {% block page_content %} | ||||
| <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 { | ||||
|     constructor(corpusId) { | ||||
|       this.corpusId = corpusId; | ||||
|       if (foreignCorpusFlag) { | ||||
|         foreignCorpusSubscribers.push(this); | ||||
|       } else { | ||||
|         corporaSubscribers.push(this); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     _init() { | ||||
|       var creationDateElement, descriptionElement, titleElement; | ||||
|  | ||||
|       if (foreignCorpusFlag) { | ||||
|         this.corpus = foreignCorpora[this.corpusId]; | ||||
|       } else { | ||||
|         this.corpus = corpora[this.corpusId]; | ||||
|       } | ||||
|       creationDateElement = document.getElementById("creation-date"); | ||||
|       creationDateElement.value = (new Date(this.corpus.creation_date * 1000)).toLocaleString(); | ||||
|       descriptionElement = document.getElementById("description"); | ||||
| @@ -62,6 +80,21 @@ | ||||
| <div class="col s12 m4"> | ||||
|   <h3 id="title"></h3> | ||||
|   <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 class="col s12 m8"> | ||||
|   | ||||
| @@ -2,20 +2,38 @@ | ||||
|  | ||||
| {% block page_content %} | ||||
| <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 { | ||||
|     constructor(jobId) { | ||||
|       this.jobId = jobId; | ||||
|       if (foreignJobFlag) { | ||||
|         foreignJobsSubscribers.push(this); | ||||
|       } else { | ||||
|         jobsSubscribers.push(this); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     _init() { | ||||
|       var creationDateElement, descriptionElement, endDateElement, | ||||
|           memMbElement, nCoresElement, serviceElement, serviceArgsElement, | ||||
|           serviceVersionElement, statusColor, statusElement, titleElement; | ||||
|  | ||||
|       if (foreignJobFlag) { | ||||
|         this.job = foreignJobs[this.jobId]; | ||||
|       } else { | ||||
|         this.job = jobs[this.jobId]; | ||||
|       } | ||||
|       creationDateElement = document.getElementById("creation-date"); | ||||
|       creationDateElement.value = (new Date(this.job.creation_date * 1000)).toLocaleString(); | ||||
|       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 | ||||
| import logging | ||||
|  | ||||
| @@ -15,6 +15,7 @@ def background_delete_user(app, current_user_id): | ||||
|         logger.warning('Called by delete_thread.') | ||||
|         logger.warning('User id is: {}.'.format(current_user_id)) | ||||
|         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)) | ||||
|         user = User.query.get_or_404(current_user_id) | ||||
|         for job in jobs: | ||||
| @@ -29,7 +30,10 @@ def background_delete_user(app, current_user_id): | ||||
|                     logger.warning('Job status is deleted.') | ||||
|                     job.delete_job() | ||||
|                     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() | ||||
|  | ||||
|  | ||||
| @@ -51,3 +55,13 @@ def background_delete_job(app, job_id): | ||||
|                 job.delete_job() | ||||
|                 deleted = True | ||||
|         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