mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2024-11-15 01:05:42 +00:00
make is_administrator a property, add back db events
This commit is contained in:
parent
d0d2a8abd6
commit
ccf484c9bc
@ -77,7 +77,7 @@ def delete_job(job_id):
|
|||||||
job = Job.query.get(job_id)
|
job = Job.query.get(job_id)
|
||||||
if job is None:
|
if job is None:
|
||||||
abort(404)
|
abort(404)
|
||||||
if not (job.user == current_user or current_user.is_administrator()):
|
if not (job.user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
try:
|
try:
|
||||||
job.delete()
|
job.delete()
|
||||||
@ -97,6 +97,6 @@ def get_job(job_id):
|
|||||||
job = Job.query.get(job_id)
|
job = Job.query.get(job_id)
|
||||||
if job is None:
|
if job is None:
|
||||||
abort(404)
|
abort(404)
|
||||||
if not (job.user == current_user or current_user.is_administrator()):
|
if not (job.user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
return job
|
return job
|
||||||
|
@ -60,7 +60,7 @@ def delete_user(user_id):
|
|||||||
user = User.query.get(user_id)
|
user = User.query.get(user_id)
|
||||||
if user is None:
|
if user is None:
|
||||||
abort(404)
|
abort(404)
|
||||||
if not (user == current_user or current_user.is_administrator()):
|
if not (user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
user.delete()
|
user.delete()
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
@ -78,7 +78,7 @@ def get_user(user_id):
|
|||||||
user = User.query.get(user_id)
|
user = User.query.get(user_id)
|
||||||
if user is None:
|
if user is None:
|
||||||
abort(404)
|
abort(404)
|
||||||
if not (user == current_user or current_user.is_administrator()):
|
if not (user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
return user
|
return user
|
||||||
|
|
||||||
@ -94,6 +94,6 @@ def get_user_by_username(username):
|
|||||||
user = User.query.filter(User.username == username).first()
|
user = User.query.filter(User.username == username).first()
|
||||||
if user is None:
|
if user is None:
|
||||||
abort(404)
|
abort(404)
|
||||||
if not (user == current_user or current_user.is_administrator()):
|
if not (user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
return user
|
return user
|
||||||
|
@ -17,7 +17,7 @@ def delete_spacy_model(spacy_nlp_pipeline_model_id):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
snpm = SpaCyNLPPipelineModel.query.get_or_404(spacy_nlp_pipeline_model_id)
|
snpm = SpaCyNLPPipelineModel.query.get_or_404(spacy_nlp_pipeline_model_id)
|
||||||
if not (snpm.user == current_user or current_user.is_administrator()):
|
if not (snpm.user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
thread = Thread(
|
thread = Thread(
|
||||||
target=_delete_spacy_model,
|
target=_delete_spacy_model,
|
||||||
@ -39,7 +39,7 @@ def update_spacy_nlp_pipeline_model_is_public(spacy_nlp_pipeline_model_id):
|
|||||||
if not isinstance(is_public, bool):
|
if not isinstance(is_public, bool):
|
||||||
abort(400)
|
abort(400)
|
||||||
snpm = SpaCyNLPPipelineModel.query.get_or_404(spacy_nlp_pipeline_model_id)
|
snpm = SpaCyNLPPipelineModel.query.get_or_404(spacy_nlp_pipeline_model_id)
|
||||||
if not (snpm.user == current_user or current_user.is_administrator()):
|
if not (snpm.user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
snpm.is_public = is_public
|
snpm.is_public = is_public
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
@ -58,7 +58,7 @@ def create_spacy_nlp_pipeline_model():
|
|||||||
@register_breadcrumb(bp, '.spacy_nlp_pipeline_models.entity', '', dynamic_list_constructor=spacy_nlp_pipeline_model_dlc)
|
@register_breadcrumb(bp, '.spacy_nlp_pipeline_models.entity', '', dynamic_list_constructor=spacy_nlp_pipeline_model_dlc)
|
||||||
def spacy_nlp_pipeline_model(spacy_nlp_pipeline_model_id):
|
def spacy_nlp_pipeline_model(spacy_nlp_pipeline_model_id):
|
||||||
snpm = SpaCyNLPPipelineModel.query.get_or_404(spacy_nlp_pipeline_model_id)
|
snpm = SpaCyNLPPipelineModel.query.get_or_404(spacy_nlp_pipeline_model_id)
|
||||||
if not (snpm.user == current_user or current_user.is_administrator()):
|
if not (snpm.user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
form = UpdateSpaCyNLPPipelineModelForm(data=snpm.to_json_serializeable())
|
form = UpdateSpaCyNLPPipelineModelForm(data=snpm.to_json_serializeable())
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
|
@ -17,7 +17,7 @@ def delete_tesseract_model(tesseract_ocr_pipeline_model_id):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
topm = TesseractOCRPipelineModel.query.get_or_404(tesseract_ocr_pipeline_model_id)
|
topm = TesseractOCRPipelineModel.query.get_or_404(tesseract_ocr_pipeline_model_id)
|
||||||
if not (topm.user == current_user or current_user.is_administrator()):
|
if not (topm.user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
thread = Thread(
|
thread = Thread(
|
||||||
target=_delete_tesseract_ocr_pipeline_model,
|
target=_delete_tesseract_ocr_pipeline_model,
|
||||||
@ -39,7 +39,7 @@ def update_tesseract_ocr_pipeline_model_is_public(tesseract_ocr_pipeline_model_i
|
|||||||
if not isinstance(is_public, bool):
|
if not isinstance(is_public, bool):
|
||||||
abort(400)
|
abort(400)
|
||||||
topm = TesseractOCRPipelineModel.query.get_or_404(tesseract_ocr_pipeline_model_id)
|
topm = TesseractOCRPipelineModel.query.get_or_404(tesseract_ocr_pipeline_model_id)
|
||||||
if not (topm.user == current_user or current_user.is_administrator()):
|
if not (topm.user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
topm.is_public = is_public
|
topm.is_public = is_public
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
@ -57,7 +57,7 @@ def create_tesseract_ocr_pipeline_model():
|
|||||||
@register_breadcrumb(bp, '.tesseract_ocr_pipeline_models.entity', '', dynamic_list_constructor=tesseract_ocr_pipeline_model_dlc)
|
@register_breadcrumb(bp, '.tesseract_ocr_pipeline_models.entity', '', dynamic_list_constructor=tesseract_ocr_pipeline_model_dlc)
|
||||||
def tesseract_ocr_pipeline_model(tesseract_ocr_pipeline_model_id):
|
def tesseract_ocr_pipeline_model(tesseract_ocr_pipeline_model_id):
|
||||||
topm = TesseractOCRPipelineModel.query.get_or_404(tesseract_ocr_pipeline_model_id)
|
topm = TesseractOCRPipelineModel.query.get_or_404(tesseract_ocr_pipeline_model_id)
|
||||||
if not (topm.user == current_user or current_user.is_administrator()):
|
if not (topm.user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
form = UpdateTesseractOCRPipelineModelForm(data=topm.to_json_serializeable())
|
form = UpdateTesseractOCRPipelineModelForm(data=topm.to_json_serializeable())
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
|
@ -99,7 +99,7 @@ class CQiNamespace(Namespace):
|
|||||||
return {'code': 404, 'msg': 'Not Found'}
|
return {'code': 404, 'msg': 'Not Found'}
|
||||||
if not (db_corpus.user == current_user
|
if not (db_corpus.user == current_user
|
||||||
or current_user.is_following_corpus(db_corpus)
|
or current_user.is_following_corpus(db_corpus)
|
||||||
or current_user.is_administrator()):
|
or current_user.is_administrator):
|
||||||
return {'code': 403, 'msg': 'Forbidden'}
|
return {'code': 403, 'msg': 'Forbidden'}
|
||||||
if db_corpus.status not in [
|
if db_corpus.status not in [
|
||||||
CorpusStatus.BUILT,
|
CorpusStatus.BUILT,
|
||||||
|
@ -10,7 +10,7 @@ def corpus_follower_permission_required(*permissions):
|
|||||||
def decorated_function(*args, **kwargs):
|
def decorated_function(*args, **kwargs):
|
||||||
corpus_id = kwargs.get('corpus_id')
|
corpus_id = kwargs.get('corpus_id')
|
||||||
corpus = Corpus.query.get_or_404(corpus_id)
|
corpus = Corpus.query.get_or_404(corpus_id)
|
||||||
if not (corpus.user == current_user or current_user.is_administrator()):
|
if not (corpus.user == current_user or current_user.is_administrator):
|
||||||
cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=current_user.id).first()
|
cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=current_user.id).first()
|
||||||
if cfa is None:
|
if cfa is None:
|
||||||
abort(403)
|
abort(403)
|
||||||
@ -26,7 +26,7 @@ def corpus_owner_or_admin_required(f):
|
|||||||
def decorated_function(*args, **kwargs):
|
def decorated_function(*args, **kwargs):
|
||||||
corpus_id = kwargs.get('corpus_id')
|
corpus_id = kwargs.get('corpus_id')
|
||||||
corpus = Corpus.query.get_or_404(corpus_id)
|
corpus = Corpus.query.get_or_404(corpus_id)
|
||||||
if not (corpus.user == current_user or current_user.is_administrator()):
|
if not (corpus.user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
return decorated_function
|
return decorated_function
|
||||||
|
@ -15,7 +15,7 @@ def get_corpus(corpus_hashid):
|
|||||||
if not (
|
if not (
|
||||||
corpus.is_public
|
corpus.is_public
|
||||||
or corpus.user == current_user
|
or corpus.user == current_user
|
||||||
or current_user.is_administrator()
|
or current_user.is_administrator
|
||||||
):
|
):
|
||||||
return {'options': {'status': 403, 'statusText': 'Forbidden'}}
|
return {'options': {'status': 403, 'statusText': 'Forbidden'}}
|
||||||
return {
|
return {
|
||||||
@ -38,7 +38,7 @@ def subscribe_corpus(corpus_hashid):
|
|||||||
if not (
|
if not (
|
||||||
corpus.is_public
|
corpus.is_public
|
||||||
or corpus.user == current_user
|
or corpus.user == current_user
|
||||||
or current_user.is_administrator()
|
or current_user.is_administrator
|
||||||
):
|
):
|
||||||
return {'options': {'status': 403, 'statusText': 'Forbidden'}}
|
return {'options': {'status': 403, 'statusText': 'Forbidden'}}
|
||||||
join_room(f'/corpora/{corpus.hashid}')
|
join_room(f'/corpora/{corpus.hashid}')
|
||||||
|
@ -58,7 +58,7 @@ def delete_corpus_follower(corpus_id, follower_id):
|
|||||||
current_user.id == follower_id
|
current_user.id == follower_id
|
||||||
or current_user == cfa.corpus.user
|
or current_user == cfa.corpus.user
|
||||||
or CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=current_user.id).first().role.has_permission('MANAGE_FOLLOWERS')
|
or CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=current_user.id).first().role.has_permission('MANAGE_FOLLOWERS')
|
||||||
or current_user.is_administrator()):
|
or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
if current_user.id == follower_id:
|
if current_user.id == follower_id:
|
||||||
flash(f'You are no longer following "{cfa.corpus.title}"', 'corpus')
|
flash(f'You are no longer following "{cfa.corpus.title}"', 'corpus')
|
||||||
|
@ -55,13 +55,13 @@ def corpus(corpus_id):
|
|||||||
users = User.query.filter(User.is_public == True, User.id != current_user.id, User.id != corpus.user.id, User.role_id < 4).all()
|
users = User.query.filter(User.is_public == True, User.id != current_user.id, User.id != corpus.user.id, User.role_id < 4).all()
|
||||||
cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=current_user.id).first()
|
cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=current_user.id).first()
|
||||||
if cfa is None:
|
if cfa is None:
|
||||||
if corpus.user == current_user or current_user.is_administrator():
|
if corpus.user == current_user or current_user.is_administrator:
|
||||||
cfr = CorpusFollowerRole.query.filter_by(name='Administrator').first()
|
cfr = CorpusFollowerRole.query.filter_by(name='Administrator').first()
|
||||||
else:
|
else:
|
||||||
cfr = CorpusFollowerRole.query.filter_by(name='Anonymous').first()
|
cfr = CorpusFollowerRole.query.filter_by(name='Anonymous').first()
|
||||||
else:
|
else:
|
||||||
cfr = cfa.role
|
cfr = cfa.role
|
||||||
if corpus.user == current_user or current_user.is_administrator():
|
if corpus.user == current_user or current_user.is_administrator:
|
||||||
return render_template(
|
return render_template(
|
||||||
'corpora/corpus.html.j2',
|
'corpora/corpus.html.j2',
|
||||||
title=corpus.title,
|
title=corpus.title,
|
||||||
|
@ -17,7 +17,7 @@ def delete_job(job_id):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
job = Job.query.get_or_404(job_id)
|
job = Job.query.get_or_404(job_id)
|
||||||
if not (job.user == current_user or current_user.is_administrator()):
|
if not (job.user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
thread = Thread(
|
thread = Thread(
|
||||||
target=_delete_job,
|
target=_delete_job,
|
||||||
@ -56,7 +56,7 @@ def restart_job(job_id):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
job = Job.query.get_or_404(job_id)
|
job = Job.query.get_or_404(job_id)
|
||||||
if not (job.user == current_user or current_user.is_administrator()):
|
if not (job.user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
if job.status == JobStatus.FAILED:
|
if job.status == JobStatus.FAILED:
|
||||||
response = {'errors': {'message': 'Job status is not "failed"'}}
|
response = {'errors': {'message': 'Job status is not "failed"'}}
|
||||||
|
@ -22,7 +22,7 @@ def corpora():
|
|||||||
@register_breadcrumb(bp, '.entity', '', dynamic_list_constructor=job_dlc)
|
@register_breadcrumb(bp, '.entity', '', dynamic_list_constructor=job_dlc)
|
||||||
def job(job_id):
|
def job(job_id):
|
||||||
job = Job.query.get_or_404(job_id)
|
job = Job.query.get_or_404(job_id)
|
||||||
if not (job.user == current_user or current_user.is_administrator()):
|
if not (job.user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
return render_template(
|
return render_template(
|
||||||
'jobs/job.html.j2',
|
'jobs/job.html.j2',
|
||||||
@ -34,7 +34,7 @@ def job(job_id):
|
|||||||
@bp.route('/<hashid:job_id>/inputs/<hashid:job_input_id>/download')
|
@bp.route('/<hashid:job_id>/inputs/<hashid:job_input_id>/download')
|
||||||
def download_job_input(job_id, job_input_id):
|
def download_job_input(job_id, job_input_id):
|
||||||
job_input = JobInput.query.filter_by(job_id=job_id, id=job_input_id).first_or_404()
|
job_input = JobInput.query.filter_by(job_id=job_id, id=job_input_id).first_or_404()
|
||||||
if not (job_input.job.user == current_user or current_user.is_administrator()):
|
if not (job_input.job.user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
return send_from_directory(
|
return send_from_directory(
|
||||||
job_input.path.parent,
|
job_input.path.parent,
|
||||||
@ -48,7 +48,7 @@ def download_job_input(job_id, job_input_id):
|
|||||||
@bp.route('/<hashid:job_id>/results/<hashid:job_result_id>/download')
|
@bp.route('/<hashid:job_id>/results/<hashid:job_result_id>/download')
|
||||||
def download_job_result(job_id, job_result_id):
|
def download_job_result(job_id, job_result_id):
|
||||||
job_result = JobResult.query.filter_by(job_id=job_id, id=job_result_id).first_or_404()
|
job_result = JobResult.query.filter_by(job_id=job_id, id=job_result_id).first_or_404()
|
||||||
if not (job_result.job.user == current_user or current_user.is_administrator()):
|
if not (job_result.job.user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
return send_from_directory(
|
return send_from_directory(
|
||||||
job_result.path.parent,
|
job_result.path.parent,
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
from enum import Enum
|
||||||
|
from app import db, login, mail, socketio
|
||||||
|
from app.email import create_message
|
||||||
from .avatar import *
|
from .avatar import *
|
||||||
from .corpus_file import *
|
from .corpus_file import *
|
||||||
from .corpus_follower_association import *
|
from .corpus_follower_association import *
|
||||||
@ -11,7 +14,132 @@ from .spacy_nlp_pipeline_model import *
|
|||||||
from .tesseract_ocr_pipeline_model import *
|
from .tesseract_ocr_pipeline_model import *
|
||||||
from .token import *
|
from .token import *
|
||||||
from .user import *
|
from .user import *
|
||||||
from app import login
|
|
||||||
|
|
||||||
|
@db.event.listens_for(Corpus, 'after_delete')
|
||||||
|
@db.event.listens_for(CorpusFile, 'after_delete')
|
||||||
|
@db.event.listens_for(Job, 'after_delete')
|
||||||
|
@db.event.listens_for(JobInput, 'after_delete')
|
||||||
|
@db.event.listens_for(JobResult, 'after_delete')
|
||||||
|
@db.event.listens_for(SpaCyNLPPipelineModel, 'after_delete')
|
||||||
|
@db.event.listens_for(TesseractOCRPipelineModel, 'after_delete')
|
||||||
|
def resource_after_delete(mapper, connection, resource):
|
||||||
|
print('[START] resource_after_delete')
|
||||||
|
jsonpatch = [
|
||||||
|
{
|
||||||
|
'op': 'remove',
|
||||||
|
'path': resource.jsonpatch_path
|
||||||
|
}
|
||||||
|
]
|
||||||
|
room = f'/users/{resource.user_hashid}'
|
||||||
|
print('[EMIT] PATCH', jsonpatch)
|
||||||
|
socketio.emit('PATCH', jsonpatch, room=room)
|
||||||
|
print('[END] resource_after_delete')
|
||||||
|
|
||||||
|
|
||||||
|
@db.event.listens_for(CorpusFollowerAssociation, 'after_delete')
|
||||||
|
def cfa_after_delete_handler(mapper, connection, cfa):
|
||||||
|
jsonpatch_path = f'/users/{cfa.corpus.user.hashid}/corpora/{cfa.corpus.hashid}/corpus_follower_associations/{cfa.hashid}'
|
||||||
|
jsonpatch = [
|
||||||
|
{
|
||||||
|
'op': 'remove',
|
||||||
|
'path': jsonpatch_path
|
||||||
|
}
|
||||||
|
]
|
||||||
|
room = f'/users/{cfa.corpus.user.hashid}'
|
||||||
|
socketio.emit('PATCH', jsonpatch, room=room)
|
||||||
|
|
||||||
|
|
||||||
|
@db.event.listens_for(Corpus, 'after_insert')
|
||||||
|
@db.event.listens_for(CorpusFile, 'after_insert')
|
||||||
|
@db.event.listens_for(Job, 'after_insert')
|
||||||
|
@db.event.listens_for(JobInput, 'after_insert')
|
||||||
|
@db.event.listens_for(JobResult, 'after_insert')
|
||||||
|
@db.event.listens_for(SpaCyNLPPipelineModel, 'after_insert')
|
||||||
|
@db.event.listens_for(TesseractOCRPipelineModel, 'after_insert')
|
||||||
|
def resource_after_insert_handler(mapper, connection, resource):
|
||||||
|
jsonpatch_value = resource.to_json_serializeable()
|
||||||
|
for attr in mapper.relationships:
|
||||||
|
jsonpatch_value[attr.key] = {}
|
||||||
|
jsonpatch = [
|
||||||
|
{
|
||||||
|
'op': 'add',
|
||||||
|
'path': resource.jsonpatch_path,
|
||||||
|
'value': jsonpatch_value
|
||||||
|
}
|
||||||
|
]
|
||||||
|
room = f'/users/{resource.user_hashid}'
|
||||||
|
socketio.emit('PATCH', jsonpatch, room=room)
|
||||||
|
|
||||||
|
|
||||||
|
@db.event.listens_for(CorpusFollowerAssociation, 'after_insert')
|
||||||
|
def cfa_after_insert_handler(mapper, connection, cfa):
|
||||||
|
jsonpatch_value = cfa.to_json_serializeable()
|
||||||
|
jsonpatch_path = f'/users/{cfa.corpus.user.hashid}/corpora/{cfa.corpus.hashid}/corpus_follower_associations/{cfa.hashid}'
|
||||||
|
jsonpatch = [
|
||||||
|
{
|
||||||
|
'op': 'add',
|
||||||
|
'path': jsonpatch_path,
|
||||||
|
'value': jsonpatch_value
|
||||||
|
}
|
||||||
|
]
|
||||||
|
room = f'/users/{cfa.corpus.user.hashid}'
|
||||||
|
socketio.emit('PATCH', jsonpatch, room=room)
|
||||||
|
|
||||||
|
|
||||||
|
@db.event.listens_for(Corpus, 'after_update')
|
||||||
|
@db.event.listens_for(CorpusFile, 'after_update')
|
||||||
|
@db.event.listens_for(Job, 'after_update')
|
||||||
|
@db.event.listens_for(JobInput, 'after_update')
|
||||||
|
@db.event.listens_for(JobResult, 'after_update')
|
||||||
|
@db.event.listens_for(SpaCyNLPPipelineModel, 'after_update')
|
||||||
|
@db.event.listens_for(TesseractOCRPipelineModel, 'after_update')
|
||||||
|
def resource_after_update_handler(mapper, connection, resource):
|
||||||
|
jsonpatch = []
|
||||||
|
for attr in db.inspect(resource).attrs:
|
||||||
|
if attr.key in mapper.relationships:
|
||||||
|
continue
|
||||||
|
if not attr.load_history().has_changes():
|
||||||
|
continue
|
||||||
|
jsonpatch_path = f'{resource.jsonpatch_path}/{attr.key}'
|
||||||
|
if isinstance(attr.value, datetime):
|
||||||
|
jsonpatch_value = f'{attr.value.isoformat()}Z'
|
||||||
|
elif isinstance(attr.value, Enum):
|
||||||
|
jsonpatch_value = attr.value.name
|
||||||
|
else:
|
||||||
|
jsonpatch_value = attr.value
|
||||||
|
jsonpatch.append(
|
||||||
|
{
|
||||||
|
'op': 'replace',
|
||||||
|
'path': jsonpatch_path,
|
||||||
|
'value': jsonpatch_value
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if jsonpatch:
|
||||||
|
room = f'/users/{resource.user_hashid}'
|
||||||
|
socketio.emit('PATCH', jsonpatch, room=room)
|
||||||
|
|
||||||
|
|
||||||
|
@db.event.listens_for(Job, 'after_update')
|
||||||
|
def job_after_update_handler(mapper, connection, job):
|
||||||
|
for attr in db.inspect(job).attrs:
|
||||||
|
if attr.key != 'status':
|
||||||
|
continue
|
||||||
|
if not attr.load_history().has_changes():
|
||||||
|
return
|
||||||
|
if job.user.setting_job_status_mail_notification_level == UserSettingJobStatusMailNotificationLevel.NONE:
|
||||||
|
return
|
||||||
|
if job.user.setting_job_status_mail_notification_level == UserSettingJobStatusMailNotificationLevel.END:
|
||||||
|
if job.status not in [JobStatus.COMPLETED, JobStatus.FAILED]:
|
||||||
|
return
|
||||||
|
msg = create_message(
|
||||||
|
job.user.email,
|
||||||
|
f'Status update for your Job "{job.title}"',
|
||||||
|
'tasks/email/notification',
|
||||||
|
job=job
|
||||||
|
)
|
||||||
|
mail.send(msg)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@login.user_loader
|
@login.user_loader
|
||||||
|
@ -132,6 +132,10 @@ class User(HashidMixin, UserMixin, db.Model):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'<User {self.username}>'
|
return f'<User {self.username}>'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_administrator(self):
|
||||||
|
return self.can(Permission.ADMINISTRATE)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def jsonpatch_path(self):
|
def jsonpatch_path(self):
|
||||||
return f'/users/{self.hashid}'
|
return f'/users/{self.hashid}'
|
||||||
@ -294,9 +298,6 @@ class User(HashidMixin, UserMixin, db.Model):
|
|||||||
algorithm='HS256'
|
algorithm='HS256'
|
||||||
)
|
)
|
||||||
|
|
||||||
def is_administrator(self):
|
|
||||||
return self.can(Permission.ADMINISTRATE)
|
|
||||||
|
|
||||||
def ping(self):
|
def ping(self):
|
||||||
self.last_seen = datetime.utcnow()
|
self.last_seen = datetime.utcnow()
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@
|
|||||||
{% block modals %}
|
{% block modals %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
|
|
||||||
{% if current_user == corpus.user or current_user.is_administrator() %}
|
{% if current_user == corpus.user or current_user.is_administrator %}
|
||||||
<div class="modal" id="publishing-modal">
|
<div class="modal" id="publishing-modal">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<h4>Change your Corpus publishing status</h4>
|
<h4>Change your Corpus publishing status</h4>
|
||||||
@ -247,7 +247,7 @@
|
|||||||
});
|
});
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if current_user == corpus.user or current_user.is_administrator() %}
|
{% if current_user == corpus.user or current_user.is_administrator %}
|
||||||
// #region Publishing
|
// #region Publishing
|
||||||
let publishingModalIsPublicSwitchElement = document.querySelector('#publishing-modal-is-public-switch');
|
let publishingModalIsPublicSwitchElement = document.querySelector('#publishing-modal-is-public-switch');
|
||||||
publishingModalIsPublicSwitchElement.addEventListener('change', (event) => {
|
publishingModalIsPublicSwitchElement.addEventListener('change', (event) => {
|
||||||
|
@ -77,7 +77,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-action right-align">
|
<div class="card-action right-align">
|
||||||
{% if current_user.is_administrator() %}
|
{% if current_user.is_administrator %}
|
||||||
<a class="action-button btn disabled waves-effect waves-light modal-trigger" data-action="get-log-request" id="job-log-button" href="#job-log-modal"><i class="material-icons left">text_snippet</i>Log</a>
|
<a class="action-button btn disabled waves-effect waves-light modal-trigger" data-action="get-log-request" id="job-log-button" href="#job-log-modal"><i class="material-icons left">text_snippet</i>Log</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a class="btn disabled waves-effect waves-light modal-trigger" href="#restart-job-modal"><i class="material-icons left">repeat</i>Restart</a>
|
<a class="btn disabled waves-effect waves-light modal-trigger" href="#restart-job-modal"><i class="material-icons left">repeat</i>Restart</a>
|
||||||
@ -159,7 +159,7 @@
|
|||||||
nopaque.requests.jobs.entity.restart({{ job.hashid|tojson }});
|
nopaque.requests.jobs.entity.restart({{ job.hashid|tojson }});
|
||||||
});
|
});
|
||||||
|
|
||||||
if ({{ current_user.is_administrator()|tojson }}) {
|
if ({{ current_user.is_administrator|tojson }}) {
|
||||||
let jobLogButtonElement = document.querySelector('#job-log-button');
|
let jobLogButtonElement = document.querySelector('#job-log-button');
|
||||||
jobLogButtonElement.addEventListener('click', (event) => {
|
jobLogButtonElement.addEventListener('click', (event) => {
|
||||||
nopaque.requests.jobs.entity.log({{ job.hashid|tojson }})
|
nopaque.requests.jobs.entity.log({{ job.hashid|tojson }})
|
||||||
|
@ -12,7 +12,7 @@ def get_user(user_hashid):
|
|||||||
user = User.query.get(user_id)
|
user = User.query.get(user_id)
|
||||||
if user is None:
|
if user is None:
|
||||||
return {'status': 404, 'statusText': 'Not found'}
|
return {'status': 404, 'statusText': 'Not found'}
|
||||||
if not (user == current_user or current_user.is_administrator()):
|
if not (user == current_user or current_user.is_administrator):
|
||||||
return {'status': 403, 'statusText': 'Forbidden'}
|
return {'status': 403, 'statusText': 'Forbidden'}
|
||||||
return {
|
return {
|
||||||
'body': user.to_json_serializeable(backrefs=True, relationships=True),
|
'body': user.to_json_serializeable(backrefs=True, relationships=True),
|
||||||
@ -28,7 +28,7 @@ def subscribe_user(user_hashid):
|
|||||||
user = User.query.get(user_id)
|
user = User.query.get(user_id)
|
||||||
if user is None:
|
if user is None:
|
||||||
return {'status': 404, 'statusText': 'Not found'}
|
return {'status': 404, 'statusText': 'Not found'}
|
||||||
if not (user == current_user or current_user.is_administrator()):
|
if not (user == current_user or current_user.is_administrator):
|
||||||
return {'status': 403, 'statusText': 'Forbidden'}
|
return {'status': 403, 'statusText': 'Forbidden'}
|
||||||
join_room(f'/users/{user.hashid}')
|
join_room(f'/users/{user.hashid}')
|
||||||
return {'status': 200, 'statusText': 'OK'}
|
return {'status': 200, 'statusText': 'OK'}
|
||||||
@ -41,7 +41,7 @@ def unsubscribe_user(user_hashid):
|
|||||||
user = User.query.get(user_id)
|
user = User.query.get(user_id)
|
||||||
if user is None:
|
if user is None:
|
||||||
return {'status': 404, 'statusText': 'Not found'}
|
return {'status': 404, 'statusText': 'Not found'}
|
||||||
if not (user == current_user or current_user.is_administrator()):
|
if not (user == current_user or current_user.is_administrator):
|
||||||
return {'status': 403, 'statusText': 'Forbidden'}
|
return {'status': 403, 'statusText': 'Forbidden'}
|
||||||
leave_room(f'/users/{user.hashid}')
|
leave_room(f'/users/{user.hashid}')
|
||||||
return {'status': 200, 'statusText': 'OK'}
|
return {'status': 200, 'statusText': 'OK'}
|
||||||
|
@ -17,7 +17,7 @@ def delete_user(user_id):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
user = User.query.get_or_404(user_id)
|
user = User.query.get_or_404(user_id)
|
||||||
if not (user == current_user or current_user.is_administrator()):
|
if not (user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
thread = Thread(
|
thread = Thread(
|
||||||
target=_delete_user,
|
target=_delete_user,
|
||||||
@ -44,7 +44,7 @@ def delete_user_avatar(user_id):
|
|||||||
user = User.query.get_or_404(user_id)
|
user = User.query.get_or_404(user_id)
|
||||||
if user.avatar is None:
|
if user.avatar is None:
|
||||||
abort(404)
|
abort(404)
|
||||||
if not (user == current_user or current_user.is_administrator()):
|
if not (user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
thread = Thread(
|
thread = Thread(
|
||||||
target=_delete_avatar,
|
target=_delete_avatar,
|
||||||
|
@ -33,7 +33,7 @@ def get_user(user_hashid):
|
|||||||
user = User.query.get(user_id)
|
user = User.query.get(user_id)
|
||||||
if user is None:
|
if user is None:
|
||||||
return {'options': {'status': 404, 'statusText': 'Not found'}}
|
return {'options': {'status': 404, 'statusText': 'Not found'}}
|
||||||
if not (user == current_user or current_user.is_administrator()):
|
if not (user == current_user or current_user.is_administrator):
|
||||||
return {'options': {'status': 403, 'statusText': 'Forbidden'}}
|
return {'options': {'status': 403, 'statusText': 'Forbidden'}}
|
||||||
return {
|
return {
|
||||||
'body': user.to_json_serializable(),
|
'body': user.to_json_serializable(),
|
||||||
@ -52,7 +52,7 @@ def subscribe_user(user_hashid):
|
|||||||
user = User.query.get(user_id)
|
user = User.query.get(user_id)
|
||||||
if user is None:
|
if user is None:
|
||||||
return {'options': {'status': 404, 'statusText': 'Not found'}}
|
return {'options': {'status': 404, 'statusText': 'Not found'}}
|
||||||
if not (user == current_user or current_user.is_administrator()):
|
if not (user == current_user or current_user.is_administrator):
|
||||||
return {'options': {'status': 403, 'statusText': 'Forbidden'}}
|
return {'options': {'status': 403, 'statusText': 'Forbidden'}}
|
||||||
join_room(f'/users/{user.hashid}')
|
join_room(f'/users/{user.hashid}')
|
||||||
return {'options': {'status': 200, 'statusText': 'OK'}}
|
return {'options': {'status': 200, 'statusText': 'OK'}}
|
||||||
@ -89,7 +89,7 @@ def get_user(user_hashid):
|
|||||||
user = User.query.filter_by(id=user_id, is_public=True).first()
|
user = User.query.filter_by(id=user_id, is_public=True).first()
|
||||||
if user is None:
|
if user is None:
|
||||||
return {'options': {'status': 404, 'statusText': 'Not found'}}
|
return {'options': {'status': 404, 'statusText': 'Not found'}}
|
||||||
if not (user == current_user or current_user.is_administrator()):
|
if not (user == current_user or current_user.is_administrator):
|
||||||
return {'options': {'status': 403, 'statusText': 'Forbidden'}}
|
return {'options': {'status': 403, 'statusText': 'Forbidden'}}
|
||||||
return {
|
return {
|
||||||
'body': user.to_json_serializable(filter_by_privacy_settings=True),
|
'body': user.to_json_serializable(filter_by_privacy_settings=True),
|
||||||
@ -108,7 +108,7 @@ def subscribe_user(user_hashid):
|
|||||||
user = User.query.filter_by(id=user_id, is_public=True).first()
|
user = User.query.filter_by(id=user_id, is_public=True).first()
|
||||||
if user is None:
|
if user is None:
|
||||||
return {'options': {'status': 404, 'statusText': 'Not found'}}
|
return {'options': {'status': 404, 'statusText': 'Not found'}}
|
||||||
if not (user == current_user or current_user.is_administrator()):
|
if not (user == current_user or current_user.is_administrator):
|
||||||
return {'options': {'status': 403, 'statusText': 'Forbidden'}}
|
return {'options': {'status': 403, 'statusText': 'Forbidden'}}
|
||||||
join_room(f'/public_users/{user.hashid}')
|
join_room(f'/public_users/{user.hashid}')
|
||||||
return {'options': {'status': 200, 'statusText': 'OK'}}
|
return {'options': {'status': 200, 'statusText': 'OK'}}
|
||||||
|
@ -22,7 +22,7 @@ def users():
|
|||||||
@register_breadcrumb(bp, '.entity', '', dynamic_list_constructor=user_dlc)
|
@register_breadcrumb(bp, '.entity', '', dynamic_list_constructor=user_dlc)
|
||||||
def user(user_id):
|
def user(user_id):
|
||||||
user = User.query.get_or_404(user_id)
|
user = User.query.get_or_404(user_id)
|
||||||
if not (user.is_public or user == current_user or current_user.is_administrator()):
|
if not (user.is_public or user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
return render_template(
|
return render_template(
|
||||||
'users/user.html.j2',
|
'users/user.html.j2',
|
||||||
@ -34,7 +34,7 @@ def user(user_id):
|
|||||||
@bp.route('/<hashid:user_id>/avatar')
|
@bp.route('/<hashid:user_id>/avatar')
|
||||||
def user_avatar(user_id):
|
def user_avatar(user_id):
|
||||||
user = User.query.get_or_404(user_id)
|
user = User.query.get_or_404(user_id)
|
||||||
if not (user.is_public or user == current_user or current_user.is_administrator()):
|
if not (user.is_public or user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
if user.avatar is None:
|
if user.avatar is None:
|
||||||
return redirect(url_for('static', filename='images/user_avatar.png'))
|
return redirect(url_for('static', filename='images/user_avatar.png'))
|
||||||
|
@ -10,7 +10,7 @@ from . import bp
|
|||||||
@content_negotiation(consumes='application/json', produces='application/json')
|
@content_negotiation(consumes='application/json', produces='application/json')
|
||||||
def update_user_profile_privacy_setting_is_public(user_id):
|
def update_user_profile_privacy_setting_is_public(user_id):
|
||||||
user = User.query.get_or_404(user_id)
|
user = User.query.get_or_404(user_id)
|
||||||
if not (user == current_user or current_user.is_administrator()):
|
if not (user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
enabled = request.json
|
enabled = request.json
|
||||||
if not isinstance(enabled, bool):
|
if not isinstance(enabled, bool):
|
||||||
@ -32,7 +32,7 @@ def update_user_profile_privacy_settings(user_id, profile_privacy_setting_name):
|
|||||||
profile_privacy_setting = ProfilePrivacySettings[profile_privacy_setting_name]
|
profile_privacy_setting = ProfilePrivacySettings[profile_privacy_setting_name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
abort(404)
|
abort(404)
|
||||||
if not (user == current_user or current_user.is_administrator()):
|
if not (user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
enabled = request.json
|
enabled = request.json
|
||||||
if not isinstance(enabled, bool):
|
if not isinstance(enabled, bool):
|
||||||
|
@ -18,7 +18,7 @@ from .forms import (
|
|||||||
@register_breadcrumb(bp, '.entity.settings', '<i class="material-icons left">settings</i>Settings', endpoint_arguments_constructor=user_eac)
|
@register_breadcrumb(bp, '.entity.settings', '<i class="material-icons left">settings</i>Settings', endpoint_arguments_constructor=user_eac)
|
||||||
def settings(user_id):
|
def settings(user_id):
|
||||||
user = User.query.get_or_404(user_id)
|
user = User.query.get_or_404(user_id)
|
||||||
if not (user == current_user or current_user.is_administrator()):
|
if not (user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
|
|
||||||
redirect_location_on_post = g.pop(
|
redirect_location_on_post = g.pop(
|
||||||
|
58
wsgi.py
58
wsgi.py
@ -3,23 +3,25 @@
|
|||||||
import eventlet
|
import eventlet
|
||||||
eventlet.monkey_patch()
|
eventlet.monkey_patch()
|
||||||
|
|
||||||
from app import create_app, db, scheduler, socketio # noqa
|
|
||||||
from app.models import (
|
|
||||||
Avatar,
|
|
||||||
Corpus,
|
|
||||||
CorpusFile,
|
|
||||||
CorpusFollowerAssociation,
|
|
||||||
CorpusFollowerRole,
|
|
||||||
Job,
|
|
||||||
JobInput,
|
|
||||||
JobResult,
|
|
||||||
Role,
|
|
||||||
TesseractOCRPipelineModel,
|
|
||||||
SpaCyNLPPipelineModel,
|
|
||||||
User
|
|
||||||
) # noqa
|
|
||||||
from flask import Flask # noqa
|
from flask import Flask # noqa
|
||||||
from typing import Any, Dict # noqa
|
from typing import Any, Dict # noqa
|
||||||
|
from app import create_app, db, scheduler, socketio # noqa
|
||||||
|
from app import models # noqa
|
||||||
|
# from app.models import (
|
||||||
|
# Avatar,
|
||||||
|
# Corpus,
|
||||||
|
# CorpusFile,
|
||||||
|
# CorpusFollowerAssociation,
|
||||||
|
# CorpusFollowerRole,
|
||||||
|
# Job,
|
||||||
|
# JobInput,
|
||||||
|
# JobResult,
|
||||||
|
# Role,
|
||||||
|
# TesseractOCRPipelineModel,
|
||||||
|
# SpaCyNLPPipelineModel,
|
||||||
|
# User
|
||||||
|
# ) # noqa
|
||||||
|
|
||||||
|
|
||||||
app: Flask = create_app()
|
app: Flask = create_app()
|
||||||
@ -30,25 +32,25 @@ def make_shell_context() -> Dict[str, Any]:
|
|||||||
''' Adds variables to the shell context. '''
|
''' Adds variables to the shell context. '''
|
||||||
return {
|
return {
|
||||||
'db': db,
|
'db': db,
|
||||||
'Avatar': Avatar,
|
'Avatar': models.Avatar,
|
||||||
'Corpus': Corpus,
|
'Corpus': models.Corpus,
|
||||||
'CorpusFile': CorpusFile,
|
'CorpusFile': models.CorpusFile,
|
||||||
'CorpusFollowerAssociation': CorpusFollowerAssociation,
|
'CorpusFollowerAssociation': models.CorpusFollowerAssociation,
|
||||||
'CorpusFollowerRole': CorpusFollowerRole,
|
'CorpusFollowerRole': models.CorpusFollowerRole,
|
||||||
'Job': Job,
|
'Job': models.Job,
|
||||||
'JobInput': JobInput,
|
'JobInput': models.JobInput,
|
||||||
'JobResult': JobResult,
|
'JobResult': models.JobResult,
|
||||||
'Role': Role,
|
'Role': models.Role,
|
||||||
'TesseractOCRPipelineModel': TesseractOCRPipelineModel,
|
'TesseractOCRPipelineModel': models.TesseractOCRPipelineModel,
|
||||||
'SpaCyNLPPipelineModel': SpaCyNLPPipelineModel,
|
'SpaCyNLPPipelineModel': models.SpaCyNLPPipelineModel,
|
||||||
'User': User
|
'User': models.User
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
if app.config['NOPAQUE_IS_PRIMARY_INSTANCE']:
|
if app.config['NOPAQUE_IS_PRIMARY_INSTANCE']:
|
||||||
for corpus in Corpus.query.filter(Corpus.num_analysis_sessions > 0).all():
|
for corpus in models.Corpus.query.filter(models.Corpus.num_analysis_sessions > 0).all():
|
||||||
corpus.num_analysis_sessions = 0
|
corpus.num_analysis_sessions = 0
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
scheduler.start()
|
scheduler.start()
|
||||||
|
Loading…
Reference in New Issue
Block a user