model changes, user institution history, style changes, forgot passowrd functionality, etc.

This commit is contained in:
msinkec
2021-09-02 14:40:54 +02:00
parent 7da73f7d6a
commit 788f3bc3eb
25 changed files with 551 additions and 176 deletions

View File

@@ -25,7 +25,7 @@ import jwt
from werkzeug.security import generate_password_hash
from . model import db, UploadRegular, UploadSolar, RegisteredUser, UserInstitutionMapping, Institution, InstitutionContract, CorpusAccess
from . model import *
#REGEX_EMAIL = re.compile('^[a-z0-9]+[\._]?[a-z0-9]+[@]\w+[.]\w{2,3}$')
@@ -248,6 +248,33 @@ def get_user_institution(user_id):
return None
def get_institution_contract(institution_id):
return InstitutionContract.query.filter_by(institution=institution_id).first()
def get_institution_cooperation_history(institution_id):
#return CooperationToken.query.join(UserCooperationTokenMapping,
# UserCooperationTokenMapping.cooperation_token == CooperationToken.id).filter(UserCooperationTokenMapping.user == user_id).all()
#
res = dict()
uch_rows = UserCooperationHistory.query.filter_by(institution=institution_id).order_by(UserCooperationHistory.school_year.desc()).all()
for row in uch_rows:
if row.user not in res:
res[row.user] = {
'coordinator': [],
'moderator': [],
'other': []
}
res[row.user][row.role].append(row.school_year)
return res
def get_cooperation_history():
return UserCooperationHistory.query.all()
def has_user_corpus_access(user_id, corpus_name):
user = RegisteredUser.query.filter_by(id=user_id).first()
@@ -281,6 +308,10 @@ def get_institution_obj(institution_id):
return Institution.query.filter_by(id=institution_id).first()
def get_institution_obj_by_name(institution_name):
return Institution.query.filter_by(name=institution_name).first()
def register_new_user(name, email, password, active=True, admin=False):
model_obj = RegisteredUser(
name=name,
@@ -334,11 +365,18 @@ def activate_user(user_id):
def update_user_password(user_id, new_password):
phash = generate_password_hash(new_password)
rowcount = db.session.query(RegisteredUser).filter_by(id=user_id).update({'pass_hash': pass_hash})
rowcount = db.session.query(RegisteredUser).filter_by(id=user_id).update({'pass_hash': phash})
db.session.commit()
return rowcount
def del_user(user_id):
db.session.query(UserCooperationHistory).filter(UserCooperationHistory.user == user_id).delete()
db.session.query(UserInstitutionMapping).filter(UserInstitutionMapping.user == user_id).delete()
db.session.query(RegisteredUser).filter(RegisteredUser.id == user_id).delete()
db.session.commit()
def del_user_from_institution(user_id, institution_id):
db.session.query(UserInstitutionMapping).filter(UserInstitutionMapping.institution == institution_id).filter(UserInstitutionMapping.user == user_id).delete()
db.session.commit()
@@ -347,24 +385,28 @@ def del_user_from_institution(user_id, institution_id):
def get_all_active_users():
return RegisteredUser.query.filter_by(active=True).order_by(RegisteredUser.id).all()
def get_all_inactive_users():
return RegisteredUser.query.filter_by(active=False).order_by(RegisteredUser.id).all()
def get_all_active_users_join_institutions():
def get_all_users_join_institutions(active=True):
#return RegisteredUser.query.filter_by(active=True).order_by(RegisteredUser.id).all()
return db.session.query(RegisteredUser, UserInstitutionMapping).outerjoin(UserInstitutionMapping,
RegisteredUser.id == UserInstitutionMapping.user).order_by(RegisteredUser.id).all()
RegisteredUser.id == UserInstitutionMapping.user).filter(RegisteredUser.active == active).order_by(RegisteredUser.id).all()
def get_all_active_institution_users(institution_id):
return RegisteredUser.query.filter_by(active=True).join(UserInstitutionMapping,
RegisteredUser.id == UserInstitutionMapping.user).filter(UserInstitutionMapping.institution == institution_id).all()
def is_institution_moderator(user_id, institution_id):
def is_institution_coordinator(user_id, institution_id):
user_inst_mapping = UserInstitutionMapping.query.filter_by(user=user_id).filter_by(institution=institution_id).first()
if not user_inst_mapping:
return False
if user_inst_mapping.role != 'moderator':
if user_inst_mapping.role != 'coordinator':
return False
return True
@@ -376,15 +418,34 @@ def is_institution_member(user_id, institution_id):
return True
def get_password_reset_token(email, expires=500):
return jwt.encode({'reset_password': email,
'exp': time() + expires},
key=os.getenv('APP_SECRET_KEY'), algorithm='HS256')
def get_actual_institution_contract_filename(f_hash):
contract = InstitutionContract.query.filter_by(file_contract=f_hash).first()
if contract:
return contract.original_filename
return None
def verify_reset_token(token):
def get_actual_studentparent_contract_filename(f_hash):
contract = ContractsSolar.query.filter_by(file_contract=f_hash).first()
if contract:
return contract.original_filename
return None
def get_password_reset_token(email, key, expires=600):
return jwt.encode({'reset_password': email,
'exp': int(time.time()) + expires},
key=key, algorithm='HS256')
def verify_reset_token(token, key):
try:
email = jwt.decode(token,
key=os.getenv('APP_SECRET_KEY'), algorithms=["HS256"])['reset_password']
message = jwt.decode(token,
key=key, algorithms=["HS256"])
email = message['reset_password']
exp = message['exp']
if int(time.time()) >= exp:
# Token timed out
return None
except Exception as e:
logging.error(e)
return
@@ -392,13 +453,12 @@ def verify_reset_token(token):
def send_resetpass_mail(email, config):
jwt_token = get_password_reset_token(email)
jwt_token = get_password_reset_token(email, config['APP_SECRET_KEY'])
text = '''
Zahtevali ste ponastavitev gesla vašega uporabniškega računa.
Geslo lahko ponastavite na naslednji povezavi: https://zbiranje.slovenscina.eu/solar/resetpass/{}'''.format(
'https://zbiranje.slovenscina.eu/solar/resetpass/{}'.format(jwt_token))
Geslo lahko ponastavite na naslednji povezavi: https://zbiranje.slovenscina.eu/solar/resetpass/{}'''.format(jwt_token)
# Create a secure SSL context
context = ssl.create_default_context()

View File

@@ -28,25 +28,6 @@ class UploadRegular(db.Model):
corpus_name = db.Column(db.String, nullable=False)
class UploadPredavanja(db.Model):
__tablename__ = 'upload_predavanja'
id = db.Column(db.Integer, primary_key=True)
upload_hash = db.Column(db.String, nullable=False)
timestamp = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
name = db.Column(db.String, nullable=False)
address = db.Column(db.String, nullable=False)
subject = db.Column(db.String, nullable=False)
faculty = db.Column(db.String, nullable=False)
email = db.Column(db.String, nullable=False)
phone = db.Column(db.String, nullable=True)
keywords = db.Column(db.String, nullable=False)
agree_publish_future = db.Column(db.String, nullable=False)
agree_machine_translation = db.Column(db.Boolean, default=False, nullable=False)
agree_news_cjvt = db.Column(db.Boolean, default=False, nullable=False)
file_contract = db.Column(db.String, nullable=True)
upload_file_hashes = db.Column(sqlalchemy.types.ARRAY(db.String), nullable=True)
class UploadSolar(db.Model):
__tablename__ = 'upload_solar'
id = db.Column(db.Integer, primary_key=True)
@@ -65,14 +46,6 @@ class UploadSolar(db.Model):
upload_file_hashes = db.Column(sqlalchemy.types.ARRAY(db.String), nullable=True)
class StampsSolar(db.Model):
__tablename__ = 'stamps_solar'
id = db.Column(db.Integer, primary_key=True)
institution = db.Column(db.Integer, sqlalchemy.ForeignKey('institution.id'), nullable=True)
name = db.Column(db.String, nullable=False)
file_logo = db.Column(db.String, nullable=True)
class ContractsSolar(db.Model):
__tablename__ = 'contracts_solar'
id = db.Column(db.Integer, primary_key=True)
@@ -80,6 +53,7 @@ class ContractsSolar(db.Model):
upload_user = db.Column(db.Integer, sqlalchemy.ForeignKey('registered_user.id'), nullable=True)
timestamp = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
file_contract = db.Column(db.String, nullable=False)
original_filename = db.Column(db.String, nullable=True)
contract_type = db.Column(db.String, nullable=False)
@@ -100,7 +74,29 @@ class UserInstitutionMapping(db.Model):
id = db.Column(db.Integer, primary_key=True)
user = db.Column(db.Integer, sqlalchemy.ForeignKey('registered_user.id'), nullable=False)
institution = db.Column(db.Integer, sqlalchemy.ForeignKey('institution.id'), nullable=False)
role =db.Column(db.String, nullable=False)
role = db.Column(db.String, nullable=False)
#class CooperationToken(db.Model):
# __tablename__ = 'cooperation_token'
# id = db.Column(db.Integer, primary_key=True)
# name = db.Column(db.String, nullable=False)
#
#
#class UserCooperationTokenMapping(db.Model):
# __tablename__ = 'user_cooperation_token_mapping'
# id = db.Column(db.Integer, primary_key=True)
# user = db.Column(db.Integer, sqlalchemy.ForeignKey('registered_user.id'), nullable=False)
# cooperation_token = db.Column(db.Integer, sqlalchemy.ForeignKey('cooperation_token.id'), nullable=False)
class UserCooperationHistory(db.Model):
__tablename__ = 'user_cooperation'
id = db.Column(db.Integer, primary_key=True)
user = db.Column(db.Integer, sqlalchemy.ForeignKey('registered_user.id'), nullable=False)
institution = db.Column(db.Integer, sqlalchemy.ForeignKey('institution.id'), nullable=False)
role = db.Column(db.String, nullable=False)
school_year = db.Column(db.String, nullable=False)
badge_text = db.Column(db.String, nullable=True)
class Institution(db.Model):
@@ -124,4 +120,5 @@ class InstitutionContract(db.Model):
corpus = db.Column(db.String, nullable=False)
timestamp = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
file_contract = db.Column(db.String, nullable=True)
original_filename = db.Column(db.String, nullable=True)

View File

@@ -13,6 +13,7 @@ VALID_PROGRAMS = {'OS', 'SSG', 'MGP', 'ZG', 'NPI', 'SPI', 'SSI', 'PTI'}
VALID_SUBJECTS = {'slo', 'drug-jez', 'drug-druz', 'drug-narav', 'drug-strok', 'drug-izb'}
VALID_TEXT_TYPES = {'esej-spis', 'prakticno', 'solski-test', 'delo-v-razredu'}
VALID_GRAMMAR_CORRECTIONS = {'popr-ne', 'brez-popr', 'popr-da'}
VALID_REGIONS = {'CE', 'GO', 'KK', 'KP', 'KR', 'LJ', 'MB', 'MS', 'NM', 'PO', 'SG'}
MAXLEN_FORM = 150
@@ -109,17 +110,18 @@ class UploadHandlerSolar(UploadHandler):
if user_institution_mapping is None:
return 'Vaš uporabnik ni dodeljen nobeni inštituciji.'
institution_id = user_institution_mapping.institution
is_institution_moderator = True if user_institution_mapping.role == 'moderator' else False
is_institution_coordinator = True if user_institution_mapping.role == 'coordinator' else False
if contract_type == 'sola':
if not is_institution_moderator:
if not is_institution_coordinator:
return 'Vaš uporabnik nima pravic za nalaganje pogodbe s šolo.'
# TODO: insert institution contract
model_obj = InstitutionContract(
institution=institution_id,
corpus='solar',
timestamp=timestamp,
file_contract=f_hash
file_contract=f_hash,
original_filename=f_obj.filename
)
self.store_model(model_obj)
else:
@@ -129,6 +131,7 @@ class UploadHandlerSolar(UploadHandler):
timestamp=timestamp,
file_contract=f_hash,
contract_type=contract_type,
original_filename=f_obj.filename
)
self.store_model(model_obj)