@ -5,7 +5,7 @@ import configparser
from pathlib import Path
from werkzeug . security import check_password_hash
from flask import Flask , render_template , request , redirect , flash , safe_join , send_file
from flask import Flask , render_template , request , redirect , flash , safe_join , send_file , jsonify , url_for
from flask_dropzone import Dropzone
from flask_migrate import Migrate , MigrateCommand
from flask_script import Manager
@ -15,7 +15,6 @@ from portal.model import db, RegisteredUser
import portal . base
import portal . solar
import portal . regular
import portal . predavanja
# TODO: Implement user registration.
@ -44,12 +43,9 @@ MAX_FILES_PER_UPLOAD = int(config['MAX_FILES_PER_UPLOAD'])
CONTRACT_CLIENT_CONTACT = config [ ' CONTRACT_CLIENT_CONTACT ' ]
MAIL_SUBJECT = config [ ' MAIL_SUBJECT ' ]
MAIL_BODY = config [ ' MAIL_BODY ' ]
MAIL_SUBJECT_PREDAVANJA = config [ ' MAIL_SUBJECT_PREDAVANJA ' ]
MAIL_BODY_PREDAVANJA = config [ ' MAIL_BODY_PREDAVANJA ' ]
SQL_CONN_STR = config [ ' SQL_CONN_STR ' ]
DESC_PREVODI = config [ ' DESC_PREVODI ' ]
DESC_GIGAFIDA = config [ ' DESC_GIGAFIDA ' ]
DESC_PREDAVANJA = config [ ' DESC_PREDAVANJA ' ]
if ' UPLOADS_DIR ' in config :
UPLOADS_DIR = Path ( config [ ' UPLOADS_DIR ' ] )
@ -83,10 +79,6 @@ if 'PORTALDS4DS1_MAIL_SUBJECT' in os.environ:
MAIL_SUBJECT = os . environ [ ' PORTALDS4DS1_MAIL_SUBJECT ' ]
if ' PORTALDS4DS1_MAIL_BODY ' in os . environ :
MAIL_BODY = os . environ [ ' PORTALDS4DS1_MAIL_BODY ' ]
if ' PORTALDS4DS1_MAIL_SUBJECT_PREDAVANJA ' in os . environ :
MAIL_SUBJECT_PREDAVANJA = os . environ [ ' PORTALDS4DS1_MAIL_SUBJECT_PREDAVANJA ' ]
if ' PORTALDS4DS1_MAIL_BODY_PREDAVANJA ' in os . environ :
MAIL_BODY_PREDAVANJA = os . environ [ ' PORTALDS4DS1_MAIL_BODY_PREDAVANJA ' ]
if ' PORTALDS4DS1_SQL_CONN_STR ' in os . environ :
SQL_CONN_STR = os . environ [ ' PORTALDS4DS1_SQL_CONN_STR ' ]
if ' PORTALDS4DS1_DESC_PREVODI ' in os . environ :
@ -94,7 +86,7 @@ if 'PORTALDS4DS1_DESC_PREVODI' in os.environ:
if ' PORTALDS4DS1_DESC_GIGAFIDA ' in os . environ :
DESC_GIGAFIDA = os . environ [ ' PORTALDS4DS1_DESC_GIGAFIDA ' ]
ENABLED_CORPUSES = [ ' prevodi ' , ' gigafida ' , ' solar ' , ' predavanja ' ]
ENABLED_CORPUSES = [ ' prevodi ' , ' gigafida ' , ' solar ' ]
CORPUSES_LOGIN_REQUIRED = [ ' solar ' ]
@ -147,25 +139,18 @@ upload_handler_solar = portal.solar.UploadHandlerSolar(
MAX_FILES_PER_UPLOAD = MAX_FILES_PER_UPLOAD
)
upload_handler_predavanja = portal . predavanja . UploadHandlerPredavanja (
UPLOADS_DIR = UPLOADS_DIR ,
MAIL_HOST = MAIL_HOST ,
MAIL_LOGIN = MAIL_LOGIN ,
MAIL_PASS = MAIL_PASS ,
SMTP_PORT = SMTP_PORT ,
IMAP_PORT = IMAP_PORT ,
MAIL_SUBJECT = MAIL_SUBJECT_PREDAVANJA ,
MAIL_BODY = MAIL_BODY_PREDAVANJA ,
CONTRACT_CLIENT_CONTACT = CONTRACT_CLIENT_CONTACT ,
MAX_FILES_PER_UPLOAD = MAX_FILES_PER_UPLOAD
)
# Use flask-login to manage user sessions where they are required.
login_manager = LoginManager ( app )
login_manager . init_app ( app )
def redirect_url ( default = ' / ' ) :
return request . args . get ( ' next ' ) or \
request . referrer or \
url_for ( default )
@app.route ( ' / ' )
def index ( ) :
return render_template ( ' index.html ' )
@ -180,8 +165,6 @@ def index_corpus(corpus_name):
description = DESC_PREVODI
elif corpus_name == ' gigafida ' :
description = DESC_GIGAFIDA
elif corpus_name == ' predavanja ' :
return render_template ( ' basic-predavanja.html ' , description = DESC_PREDAVANJA , max_files = MAX_FILES_PER_UPLOAD )
elif corpus_name == ' solar ' :
if current_user . is_authenticated :
return redirect ( ' /solar/oddaja ' )
@ -198,15 +181,17 @@ def load_user(user_id):
@app.route ( ' /solar/login ' )
def login_get( ) :
return render_template ( ' login.html' , corpus_name = ' solar ' , title = ' ŠOLAR ' )
def solar_ login_get( ) :
return render_template ( ' solar- login.html' )
@app.route ( ' /<corpus_name>/login ' , methods = [ ' POST ' ] )
def login_post ( corpus_name ) :
if corpus_name not in ENABLED_CORPUSES or corpus_name not in CORPUSES_LOGIN_REQUIRED :
return ' ' , 404
@app.route ( ' /solar/register ' )
def solar_register_get ( ) :
return render_template ( ' solar-register.html ' )
@app.route ( ' /solar/login ' , methods = [ ' POST ' ] )
def solar_login_post ( ) :
email = request . form . get ( ' email ' )
password = request . form . get ( ' password ' )
remember = True if request . form . get ( ' remember ' ) else False
@ -215,23 +200,59 @@ def login_post(corpus_name):
if not user or not check_password_hash ( user . pass_hash , password ) :
flash ( ' Napačni podatki za prijavo. Poskusite ponovno. ' )
return redirect ( ' / {} /login ' . format ( corpus_name ) )
return redirect ( ' / solar/login' )
if not user . active :
flash ( ' Vaš uporabniški račun še ni bil aktiviran. ' )
return redirect ( ' / {} /login ' . format ( corpus_name ) )
# Check if user is authorized to log into this corpus. Admins are an exception.
if not portal . base . has_user_corpus_access ( user . id , corpus_name ) :
flash ( ' Nimate dostopa do tega korpusa. ' )
return redirect ( ' / {} /login ' . format ( corpus_name ) )
return redirect ( ' /solar/login ' )
#portal.base.add_user_session(user.id)
login_user ( user , remember = remember )
if corpus_name == ' solar ' :
return redirect ( ' /solar/oddaja ' )
return ' ' , 404
@app.route ( ' /solar/register ' , methods = [ ' POST ' ] )
def solar_register_post ( ) :
name = request . form . get ( ' name ' )
email = request . form . get ( ' email ' )
password = request . form . get ( ' password ' )
user = RegisteredUser . query . filter_by ( email = email ) . first ( )
if user :
flash ( ' Uporabniški račun s tem emailom je že registriran. ' )
return redirect ( ' /solar/register ' )
if not name :
flash ( ' Prazno polje za ime. ' )
return redirect ( ' /solar/register ' )
if len ( name ) > 100 :
flash ( ' Predolgo ime. ' )
return redirect ( ' /solar/register ' )
if not email :
flash ( ' Prazno polje za elektronsko pošto. ' )
return redirect ( ' /solar/register ' )
if len ( email ) > 100 :
flash ( ' Predolgi email naslov ' )
return redirect ( ' /solar/register ' )
elif not re . search ( portal . base . REGEX_EMAIL , email ) :
flash ( ' Email napačnega formata. ' )
return redirect ( ' /solar/register ' )
if not password :
flash ( ' Prazno polje za geslo. ' )
return redirect ( ' /solar/register ' )
if len ( password ) > 100 :
flash ( ' Predolgo geslo. ' )
return redirect ( ' /solar/register ' )
portal . base . register_new_user ( name , email , password , active = False )
flash ( ' Uspešna registracija. ' )
return redirect ( ' /solar/login ' )
# TODO: Move solar stuff to seperate file using Flask blueprints.
@ -247,10 +268,15 @@ def logout():
@app.route ( ' /solar/<path:text> ' )
@login_required
def solar ( text ) :
if not portal . base . has_user_corpus_access ( current_user . id , ' solar ' ) :
return ' ' , 404
is_admin = current_user . role == ' admin '
current_user_institution = portal . base . get_user_institution ( current_user . id )
if current_user_institution :
current_user_institution_moderator = portal . base . is_institution_moderator ( current_user . id , current_user_institution . id )
else :
current_user_institution_moderator = False
if text . startswith ( ' oddaja/ ' ) or text == ' oddaja ' :
return render_template ( ' solar-oddaja.html ' )
return render_template ( ' solar-oddaja.html ' , is_admin = is_admin , is_institution_moderator = current_user_institution_moderator )
elif text . startswith ( ' zgodovina/ ' ) or text == ' zgodovina ' :
upload_items = portal . solar . get_upload_history ( current_user . id )
uploader_names = [ ]
@ -263,7 +289,7 @@ def solar(text):
else :
institution_names . append ( institution . name )
return render_template ( ' solar-zgodovina.html ' , upload_history = upload_items , uploader_names = uploader_names ,
institution_names = institution_names )
institution_names = institution_names , is_admin = is_admin , is_institution_moderator = current_user_institution_moderator )
elif text . startswith ( ' pogodbe/ ' ) or text == ' pogodbe ' :
# Check for ownload contract request.
match = re . match ( ' ^pogodbe/([a-z0-9_]+ \ .pdf)$ ' , text )
@ -281,72 +307,154 @@ def solar(text):
return ' ' , 404
user_obj = portal . base . get_user_obj ( current_user . get_id ( ) )
institution s = portal . base . get_user_institution s ( user_obj . id )
institution = portal . base . get_user_institution ( user_obj . id )
contracts_students = [ ]
contract_school = [ ]
enable_upload_school_contract = False
show_upload_form = False
if len ( institutions ) > 0 :
collaborators = [ ]
if institution :
collaborators = portal . base . get_all_active_institution_users ( institution . id )
show_upload_form = True
institution = portal . base . get_user_institutions ( user_obj . id ) [ 0 ]
contracts_students = portal . solar . get_institution_student_contracts ( institution . id )
contract_school = portal . solar . get_institution_contract ( institution . id )
if portal . base . is_institution_moderator ( user_obj . id , institution . id ) :
contracts_students = portal . solar . get_institution_student_contracts ( institution . id )
enable_upload_school_contract = True
else :
contracts_students = portal . solar . get_institution_student_contracts ( institution . id , user_obj . id )
return render_template ( ' solar-pogodbe.html ' , contracts_students = contracts_students ,
contract_school = contract_school ,
enable_upload_school_contract = enable_upload_school_contract ,
show_upload_form = show_upload_form )
show_upload_form = show_upload_form ,
collaborators = collaborators ,
is_admin = is_admin , is_institution_moderator = current_user_institution_moderator )
elif text . startswith ( ' admin/ ' ) or text == ' admin ' :
solar_users = portal . base . get_all_active_users ( )
users = portal . base . get_all_active_users_join_institutions ( )
inactive_users = portal . base . get_all_inactive_users ( )
solar_institutions = portal . solar . get_all_institutions ( )
if current_user . role == ' admin ' :
return render_template ( ' solar-admin.html ' , users = solar_users , institutions = solar_institutions )
if is_admin :
return render_template ( ' solar-admin.html ' , users = users ,
institutions = solar_institutions , inactive_users = inactive_users )
elif text . startswith ( ' manage-institution/ ' ) or text == ' manage-institution ' :
institution = portal . base . get_user_institution ( current_user . id )
if portal . base . is_institution_moderator ( current_user . id , institution . id ) :
solar_users = portal . base . get_all_active_users ( )
institution_users = portal . base . get_all_active_institution_users ( institution . id )
return render_template ( ' solar-manage-institution.html ' , users = solar_users ,
institution_users = institution_users )
return ' ' , 404
@app.route ( ' /solar/pogodbe ' , methods = [ ' POST ' ] )
@login_required
def solar_upload_contract ( ) :
if not portal . base . has_user_corpus_access ( current_user . id , ' solar ' ) :
return ' ' , 404
return upload_handler_solar . handle_contract_upload ( request , current_user . get_id ( ) )
@app.route ( ' / <corpus_name> /adduser' , methods = [ ' POST ' ] )
@app.route ( ' / solar /adduser' , methods = [ ' POST ' ] )
@login_required
def solar_add_user ( corpus_name ) :
def solar_add_user ( ) :
if not portal . base . is_admin ( current_user . id ) :
return ' ' , 404
if not corpus_name in ENABLED_CORPUSES :
return ' ' , 404
name = request . form [ ' name ' ]
email = request . form [ ' email ' ]
password = request . form [ ' password ' ]
name = request . form . get ( ' name ' )
email = request . form . get ( ' email ' )
password = request . form . get ( ' password ' )
if not name :
return ' Prazno polje za ime. '
flash ( ' Prazno polje za ime. ' )
return redirect ( redirect_url ( ) )
if len ( name ) > 100 :
return ' Predolgo ime. '
flash ( ' Predolgo ime. ' )
return redirect ( redirect_url ( ) )
if not email :
return ' Prazno polje za elektronsko pošto. '
flash ( ' Prazno polje za elektronsko pošto. ' )
return redirect ( redirect_url ( ) )
if len ( email ) > 100 :
return ' Predolgi email naslov '
flash ( ' Predolg email naslov. ' )
return redirect ( redirect_url ( ) )
elif not re . search ( portal . base . REGEX_EMAIL , email ) :
return ' Email napačnega formata. '
flash ( ' Email napačnega formata. ' )
return redirect ( redirect_url ( ) )
if not password :
return ' Prazno polje za geslo. '
flash ( ' Prazno polje za geslo. ' )
return redirect ( redirect_url ( ) )
if len ( password ) > 100 :
return ' Predolgo geslo. '
flash ( ' Predolgo geslo. ' )
return redirect ( redirect_url ( ) )
portal . base . register_new_user ( name , email , password )
return ' Uporabnik je bil dodan. '
flash ( ' Uporabnik je bil uspešno dodan. ' )
return redirect ( redirect_url ( ) )
@app.route ( ' /solar/activateuser ' , methods = [ ' POST ' ] )
@login_required
def solar_activate_user ( ) :
if not portal . base . is_admin ( current_user . id ) :
return ' ' , 404
user_id = request . form . get ( ' id ' )
if not user_id :
flash ( ' Prazno polje za ID uporabnika. ' )
return redirect ( redirect_url ( ) )
rowcount = portal . base . activate_user ( user_id )
if rowcount == 0 :
return ' ' , 404
flash ( ' Uporabnik je bil aktiviran. ' )
return redirect ( redirect_url ( ) )
@app.route ( ' /solar/forgotpass ' )
def solar_forgotpass ( ) :
return render_template ( ' solar-forgotpass.html ' )
@app.route ( ' /solar/sendresetpass ' , methods = [ ' POST ' ] )
def solar_sendresetpass ( ) :
email = request . form . get ( ' email ' )
portal . base . send_resetpass_mail ( email , upload_handler_regular . config )
flash ( ' Povezava za ponastavitev gesla je bila poslana na vpisan email naslov. ' )
return redirect ( redirect_url ( ) )
@app.route ( ' /solar/resetpass/<token> ' )
def solar_resetpass ( token ) :
user = portal . base . verify_reset_token ( token )
if not user :
return ' ' , 404
return render_template ( ' solar-resetpass.html ' , user = user , token = token )
@app.route ( ' /solar/resetpass/<token> ' , methods = [ ' POST ' ] )
def solar_resetpass_post ( token ) :
new_password = request . form . get ( ' new_password ' )
user = portal . base . verify_reset_token ( token )
if not user :
return ' ' , 404
rowcount = portal . base . update_user_password ( user . id , new_password )
if rowcount == 0 :
return ' ' , 404
return ' Ponastavitev gesla uspešna. '
@app.route ( ' /solar/topuploads ' )
@login_required
def solar_topuploads_srednje ( ) :
return jsonify ( portal . solar . get_top_uploading_institutions ( ) )
@app.route ( ' /solar/deluser ' , methods = [ ' POST ' ] )
@ -364,44 +472,76 @@ def add_institution(corpus_name):
if not corpus_name in ENABLED_CORPUSES :
return ' ' , 404
name = request . form [ ' name ' ]
region = request . form [ ' region ' ]
name = request . form . get ( ' name ' )
region = request . form . get ( ' region ' )
if not name :
return ' Prazno polje za ime. '
flash ( ' Prazno polje za ime. ' )
return redirect ( redirect_url ( ) )
if len ( name ) > 100 :
return ' Predolgo ime. '
flash ( ' Predolgo ime. ' )
return redirect ( redirect_url ( ) )
if not region :
return ' Prazno polje za regijo. '
flash ( ' Prazno polje za regijo. ' )
return redirect ( redirect_url ( ) )
if len ( region ) > 100 :
return ' Predolgi niz za regijo. '
flash ( ' Predolgi niz za regijo. ' )
return redirect ( redirect_url ( ) )
institution_id = portal . base . add_institution ( name , region )
portal . base . grant_institution_corpus_access ( institution_id , corpus_name )
return ' Institucija je bila dodana. '
flash ( ' Institucija je bila dodana. ' )
return redirect ( redirect_url ( ) )
@app.route ( ' /<corpus_name>/addusertoinstitution ' , methods = [ ' POST ' ] )
@login_required
def add_user_institution_mapping ( corpus_name ) :
if not portal . base . is_admin ( current_user . id ) :
return ' ' , 404
if not corpus_name in ENABLED_CORPUSES :
return ' ' , 404
institution_id = request . form . get ( ' institution_id ' )
if not institution_id :
institution = portal . base . get_user_institution ( current_user . id )
if institution :
institution_id = institution . id
if not ( portal . base . is_admin ( current_user . id ) or portal . base . is_institution_moderator ( current_user . id , institution_id ) ) :
return ' ' , 404
user_id = request . form [ ' user_id ' ]
institution_id = request . form [ ' institution_id ' ]
role = request . form [ ' role ' ]
if role not in [ ' moderator ' , ' user ' ] :
return ' ' , 404
# TODO: remove this restriction
if len ( portal . base . get_user_institutions ( user_id ) ) > 0 :
return ' Uporabnik je že dodeljen instituciji. Dodeljevanje večim institucijam ' \
' zaenkrat ni implementirano. '
if portal . base . get_user_institution ( user_id ) :
flash ( ' Uporabnik je že dodeljen instituciji. Dodeljevanje večim institucijam ' \
' zaenkrat ni implementirano. ' )
return redirect ( redirect_url ( ) )
portal . base . add_user_to_institution ( user_id , institution_id , role )
return ' Uporabnik je bil dodeljen instituciji. '
flash ( ' Uporabnik je bil dodeljen instituciji. ' )
return redirect ( redirect_url ( ) )
@app.route ( ' /<corpus_name>/deluserfrominstitution ' , methods = [ ' POST ' ] )
@login_required
def del_user_institution_mapping ( corpus_name ) :
institution = portal . base . get_user_institution ( current_user . id )
if not portal . base . is_admin ( current_user . id ) \
and not portal . base . is_institution_moderator ( current_user . id , institution . id ) :
return ' ' , 404
if not corpus_name in ENABLED_CORPUSES :
return ' ' , 404
user_id = request . form [ ' user_id ' ]
if not portal . base . is_institution_member ( user_id , institution . id ) :
flash ( ' Uporabnik ni član vaše institucije. ' )
return redirect ( redirect_url ( ) )
portal . base . del_user_from_institution ( user_id , institution . id )
flash ( ' Uporabnik je bil odstranjen iz institucije. ' )
return redirect ( redirect_url ( ) )
@app.route ( ' /<corpus_name>/delinstitution ' , methods = [ ' POST ' ] )
@login_required
@ -420,11 +560,9 @@ def handle_upload(corpus_name):
if corpus_name == ' solar ' :
if not current_user . is_authenticated :
return ' ' , 404
if not portal . base . has_user_corpus_access ( current_user . id , corpus_name ) :
return ' ' , 404
#if not portal.base.has_user_corpus_access(current_user.id, corpus_name) :
# return '', 404
return upload_handler_solar . handle_upload ( request , current_user . get_id ( ) )
elif corpus_name == ' predavanja ' :
return upload_handler_predavanja . handle_upload ( request )
else :
return upload_handler_regular . handle_upload ( request , corpus_name )