"Base"
This commit is contained in:
parent
7332af1dc0
commit
738596a13f
296
participate.py
296
participate.py
@ -41,6 +41,7 @@ class Tetawebapp_users(db.Model):
|
|||||||
name = db.Column(db.Text, nullable=True)
|
name = db.Column(db.Text, nullable=True)
|
||||||
phone = db.Column(db.Text, nullable=True)
|
phone = db.Column(db.Text, nullable=True)
|
||||||
diet = db.Column(db.Text, nullable=True)
|
diet = db.Column(db.Text, nullable=True)
|
||||||
|
is_admin = db.Column(db.Integer, nullable=False, default=0)
|
||||||
|
|
||||||
class Tetawebapp_roles(db.Model):
|
class Tetawebapp_roles(db.Model):
|
||||||
__tablename__ = 'participer_thsf_roles'
|
__tablename__ = 'participer_thsf_roles'
|
||||||
@ -48,6 +49,15 @@ class Tetawebapp_roles(db.Model):
|
|||||||
role = db.Column(db.Text, nullable=False)
|
role = db.Column(db.Text, nullable=False)
|
||||||
description = db.Column(db.Text, nullable=False)
|
description = db.Column(db.Text, nullable=False)
|
||||||
|
|
||||||
|
class Tetawebapp_turns(db.Model):
|
||||||
|
__tablename__ = 'participer_thsf_turns'
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
role_id = db.Column(db.Integer, db.ForeignKey('participer_thsf_roles.id'), nullable=False)
|
||||||
|
user_id = db.Column(db.Integer, db.ForeignKey('participer_thsf_users.id'), nullable=True)
|
||||||
|
wday = db.Column(db.Enum('J', 'V', 'S', 'D'), nullable=False)
|
||||||
|
start_time = db.Column(db.Time, nullable=False)
|
||||||
|
end_time = db.Column(db.Time, nullable=False)
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# Menu and navigation management
|
# Menu and navigation management
|
||||||
########################################################################
|
########################################################################
|
||||||
@ -62,14 +72,17 @@ def get_menu(page):
|
|||||||
- The int 0 is used to determine which menu entry is actally called.
|
- The int 0 is used to determine which menu entry is actally called.
|
||||||
The value MUST be 0."""
|
The value MUST be 0."""
|
||||||
menu = [[u'Accueil', {u'/': [u'/']}, 0],
|
menu = [[u'Accueil', {u'/': [u'/']}, 0],
|
||||||
[u'Mon compte', {u'/account': [u'/account', u'/account/<ID>']}, 0],
|
[u'Mon compte', {u'/account': [u'/account', u'/account/update']}, 0],
|
||||||
[u'Mes quarts', {u'/turn': [u'/turn']}, 0],
|
[u'Mes tours de staff', {u'/turn': [u'/turn']}, 0],
|
||||||
[u'Feuille de staff', {u'/staff_sheet': [u'/staff_sheet']}, 0],
|
[u'Feuilles de staff', {u'/staff_sheets': [u'/staff_sheet']}, 0],
|
||||||
|
[u'Déconnexion', {u'/logout': [u'/logout']}, 0],
|
||||||
|
]
|
||||||
|
if session['is_admin']:
|
||||||
|
menu = [[u'Accueil', {u'/': [u'/']}, 0],
|
||||||
|
[u'Tours de staff', {u'/staff': [u'/staff']}, 0],
|
||||||
|
[u'Feuilles de staff', {u'/staff_sheets': [u'/staff_sheet']}, 0],
|
||||||
|
[u'Liste des staffers', {u'/users': [u'/users', u'/account/<ID>']}, 0],
|
||||||
[u'Déconnexion', {u'/logout': [u'/logout']}, 0],
|
[u'Déconnexion', {u'/logout': [u'/logout']}, 0],
|
||||||
[u'Inputs', {u'/inputs': [u'/inputs']}, 0],
|
|
||||||
[u'Ajax', {u'/ajax': [u'/ajax']}, 0],
|
|
||||||
[u'Database', {u'/database': [u'/database']}, 0],
|
|
||||||
[u'Todo', {u'/todo': [u'/todo']}, 0],
|
|
||||||
]
|
]
|
||||||
for item in menu:
|
for item in menu:
|
||||||
for url in item[1]:
|
for url in item[1]:
|
||||||
@ -122,29 +135,153 @@ def check_session(func):
|
|||||||
def check(*args, **kwargs):
|
def check(*args, **kwargs):
|
||||||
try:
|
try:
|
||||||
if session['token'] == request.cookies['token'] and len(session['token']) > 0:
|
if session['token'] == request.cookies['token'] and len(session['token']) > 0:
|
||||||
|
# User is logged in and identified
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
else:
|
else:
|
||||||
|
# User is not logged in or session expired
|
||||||
session['token'] = ''
|
session['token'] = ''
|
||||||
response = app.make_response(render_template('login_or_register.html', message=''))
|
response = app.make_response(render_template('login_or_register.html', message=''))
|
||||||
sync_cookies(response, session)
|
sync_cookies(response, session)
|
||||||
return response
|
return response
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
# User is not logged in
|
||||||
return render_template('login_or_register.html', message='')
|
return render_template('login_or_register.html', message='')
|
||||||
return check
|
return check
|
||||||
|
|
||||||
def check_login(login, password):
|
def check_login(login, password):
|
||||||
""" Puts the login verification code here """
|
""" Puts the login verification code here """
|
||||||
password = password.encode('utf-8')
|
|
||||||
hashed_password = bcrypt.hashpw(password, bcrypt.gensalt())
|
hashed_password = bcrypt.hashpw(password, bcrypt.gensalt())
|
||||||
stored_hash = Tetawebapp_users.query.filter_by(mail=login).with_entities(Tetawebapp_users.password).first()
|
stored_hash = Tetawebapp_users.query.filter_by(mail=login).with_entities(Tetawebapp_users.password).first()
|
||||||
|
is_admin = Tetawebapp_users.query.filter_by(mail=login).with_entities(Tetawebapp_users.is_admin).first()
|
||||||
if stored_hash:
|
if stored_hash:
|
||||||
if bcrypt.checkpw(password, stored_hash[0].encode('utf-8')):
|
if bcrypt.checkpw(password, stored_hash[0].encode('utf-8')):
|
||||||
|
session['is_admin'] = is_admin[0]
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def register_user(login, password, confirm):
|
||||||
|
""" Register new user """
|
||||||
|
if password != confirm:
|
||||||
|
# Password does not match confirmation
|
||||||
|
print "[+] Password mismatch confirmation"
|
||||||
|
return False
|
||||||
|
check_user = Tetawebapp_users.query.filter_by(mail=login).count()
|
||||||
|
if check_user != 0:
|
||||||
|
# User already exists
|
||||||
|
print "[+] User already exists"
|
||||||
|
return False
|
||||||
|
hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
|
||||||
|
user = Tetawebapp_users(mail=login.encode('utf8'), password=hashed_password)
|
||||||
|
try:
|
||||||
|
db.session.add(user)
|
||||||
|
commit = db.session.commit()
|
||||||
|
except Exception as e:
|
||||||
|
db.session.rollback()
|
||||||
|
print "[+] Error at register_user:"
|
||||||
|
print "------------------------------"
|
||||||
|
print "%s" % e.message
|
||||||
|
print "------------------------------"
|
||||||
|
return False
|
||||||
|
if commit != None:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def update_user(login, password, confirm, name, phone, diet):
|
||||||
|
""" Update user infos with provided data """
|
||||||
|
if password != confirm:
|
||||||
|
# Password does not match confirmation
|
||||||
|
print "[+] Password mismatch confirmation"
|
||||||
|
return False
|
||||||
|
check_user = Tetawebapp_users.query.filter_by(mail=login).count()
|
||||||
|
if check_user == 0:
|
||||||
|
# User does not exist
|
||||||
|
print "[+] User does not exist"
|
||||||
|
return False
|
||||||
|
user = Tetawebapp_users.query.filter_by(mail=login).first()
|
||||||
|
if len(password) > 0:
|
||||||
|
# User requested password modification
|
||||||
|
hashed_password = bcrypt.hashpw(password, bcrypt.gensalt())
|
||||||
|
setattr(user, 'password', hashed_password)
|
||||||
|
# Password has been updated if necessary
|
||||||
|
# Now let's update other data
|
||||||
|
setattr(user, 'name', name)
|
||||||
|
setattr(user, 'phone', phone)
|
||||||
|
setattr(user, 'diet', diet)
|
||||||
|
try:
|
||||||
|
db.session.add(user)
|
||||||
|
commit = db.session.commit()
|
||||||
|
except Exception as e:
|
||||||
|
db.session.rollback()
|
||||||
|
print "[+] Error at update_user:"
|
||||||
|
print "------------------------------"
|
||||||
|
print "%s" % e.message
|
||||||
|
print "------------------------------"
|
||||||
|
return False
|
||||||
|
if commit != None:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def update_user_by_id(user_id, login, password, confirm, name, phone, diet):
|
||||||
|
""" Update user infos with provided data """
|
||||||
|
if password != confirm:
|
||||||
|
# Password does not match confirmation
|
||||||
|
print "[+] Password mismatch confirmation"
|
||||||
|
return False
|
||||||
|
check_user = Tetawebapp_users.query.filter_by(id=user_id).count()
|
||||||
|
if check_user == 0:
|
||||||
|
# User does not exist
|
||||||
|
print "[+] User does not exist"
|
||||||
|
return False
|
||||||
|
user = Tetawebapp_users.query.filter_by(id=user_id).first()
|
||||||
|
if len(password) > 0:
|
||||||
|
# User requested password modification
|
||||||
|
hashed_password = bcrypt.hashpw(password, bcrypt.gensalt())
|
||||||
|
setattr(user, 'password', hashed_password)
|
||||||
|
# Password has been updated if necessary
|
||||||
|
# Now let's update other data
|
||||||
|
setattr(user, 'name', name)
|
||||||
|
setattr(user, 'phone', phone)
|
||||||
|
setattr(user, 'diet', diet)
|
||||||
|
try:
|
||||||
|
db.session.add(user)
|
||||||
|
commit = db.session.commit()
|
||||||
|
except Exception as e:
|
||||||
|
db.session.rollback()
|
||||||
|
print "[+] Error at update_user:"
|
||||||
|
print "------------------------------"
|
||||||
|
print "%s" % e.message
|
||||||
|
print "------------------------------"
|
||||||
|
return False
|
||||||
|
if commit != None:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def delete_user(user_id):
|
||||||
|
""" Delete user """
|
||||||
|
try:
|
||||||
|
Tetawebapp_users.query.filter_by(id=int(user_id)).delete()
|
||||||
|
db.session.commit()
|
||||||
|
return True
|
||||||
|
except ValueError as e:
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
db.session.rollback()
|
||||||
|
print "[+] Error at delete_user:"
|
||||||
|
print "------------------------------"
|
||||||
|
print "%s" % e.message
|
||||||
|
print "------------------------------"
|
||||||
|
return False
|
||||||
|
|
||||||
def check_user_info():
|
def check_user_info():
|
||||||
""" Check user info and send appropriate message if info are not complete"""
|
""" Check user info and send appropriate message if info are not complete"""
|
||||||
message = "Vos informations personnelles ne sont pas totalement renseignées. N'oubliez pas de remplir votre fiche située dans la section 'Mon compte'"
|
message = ''
|
||||||
|
user = Tetawebapp_users.query.filter_by(mail=session['login']).first()
|
||||||
|
name = user.name
|
||||||
|
phone = user.phone
|
||||||
|
diet = user.diet
|
||||||
|
if name == None or phone == None or diet == None or \
|
||||||
|
len(name) == 0 or len(phone) == 0 or len(diet) == 0:
|
||||||
|
message = "Vos informations personnelles ne sont pas complètement renseignées. N'oubliez pas de remplir votre fiche située dans la section 'Mon compte'"
|
||||||
return message.decode('utf-8')
|
return message.decode('utf-8')
|
||||||
|
|
||||||
def gen_token():
|
def gen_token():
|
||||||
@ -165,44 +302,55 @@ def page_not_found(e):
|
|||||||
|
|
||||||
@app.route("/login", methods=['GET', 'POST'])
|
@app.route("/login", methods=['GET', 'POST'])
|
||||||
def login():
|
def login():
|
||||||
login = request.form.get('login')
|
try:
|
||||||
password = request.form.get('password')
|
login = request.form.get('login').encode('utf-8')
|
||||||
|
password = request.form.get('password').encode('utf-8')
|
||||||
if check_login(login, password):
|
if check_login(login, password):
|
||||||
# Generate and store a token in session
|
# Generate and store a token in session
|
||||||
session['token'] = gen_token()
|
session['token'] = gen_token()
|
||||||
|
session['login'] = login
|
||||||
# Return user to index page
|
# Return user to index page
|
||||||
page = '/'
|
page = '/'
|
||||||
menu = get_menu(page)
|
menu = get_menu(page)
|
||||||
message = check_user_info()
|
message = check_user_info()
|
||||||
response = app.make_response(render_template('index.html', menu=menu, message=message))
|
response = app.make_response(render_template('index.html', menu=menu, message=message, login=login))
|
||||||
# Push token to cookie
|
# Push token to cookie
|
||||||
sync_cookies(response, session)
|
sync_cookies(response, session)
|
||||||
return response
|
return response
|
||||||
# Credentials are not valid
|
# Credentials are not valid
|
||||||
response = app.make_response(render_template('login_or_register.html', message='Invalid user or password'))
|
response = app.make_response(render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide"))
|
||||||
session['token'] = ''
|
session['token'] = ''
|
||||||
sync_cookies(response, session)
|
sync_cookies(response, session)
|
||||||
return response
|
return response
|
||||||
|
except AttributeError:
|
||||||
|
return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
|
||||||
|
|
||||||
@app.route("/register", methods=['GET', 'POST'])
|
@app.route("/register", methods=['GET', 'POST'])
|
||||||
def register():
|
def register():
|
||||||
login = request.form.get('login')
|
try:
|
||||||
password = request.form.get('password')
|
login = request.form.get('login').encode('utf-8')
|
||||||
if check_login(login, password):
|
password = request.form.get('password').encode('utf-8')
|
||||||
|
confirm = request.form.get('confirm').encode('utf-8')
|
||||||
|
if register_user(login, password, confirm):
|
||||||
# Generate and store a token in session
|
# Generate and store a token in session
|
||||||
session['token'] = gen_token()
|
session['token'] = gen_token()
|
||||||
|
session['login'] = login
|
||||||
# Return user to index page
|
# Return user to index page
|
||||||
page = '/'
|
page = '/'
|
||||||
menu = get_menu(page)
|
menu = get_menu(page)
|
||||||
response = app.make_response(render_template('index.html', menu=menu))
|
message = check_user_info()
|
||||||
|
response = app.make_response(render_template('index.html', menu=menu, login=login, message=message))
|
||||||
# Push token to cookie
|
# Push token to cookie
|
||||||
sync_cookies(response, session)
|
sync_cookies(response, session)
|
||||||
return response
|
return response
|
||||||
# Credentials are not valid
|
# Error while registering user
|
||||||
response = app.make_response(render_template('login_or_register.html', message='Invalid user or password'))
|
message = "Erreur lors de l'enregsitrement: L'utilisateur existe t-il déjà ?".decode('utf-8')
|
||||||
|
response = app.make_response(render_template('login_or_register.html', message=message))
|
||||||
session['token'] = ''
|
session['token'] = ''
|
||||||
sync_cookies(response, session)
|
sync_cookies(response, session)
|
||||||
return response
|
return response
|
||||||
|
except AttributeError:
|
||||||
|
return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
|
||||||
|
|
||||||
@app.route("/", methods=['GET', 'POST'])
|
@app.route("/", methods=['GET', 'POST'])
|
||||||
@check_session
|
@check_session
|
||||||
@ -211,25 +359,122 @@ def index():
|
|||||||
page = str(request.url_rule)
|
page = str(request.url_rule)
|
||||||
menu = get_menu(page)
|
menu = get_menu(page)
|
||||||
message = check_user_info()
|
message = check_user_info()
|
||||||
return render_template('index.html', menu=menu, message=message)
|
return render_template('index.html', menu=menu, message=message, login=session['login'])
|
||||||
|
|
||||||
@app.route("/account", methods=['GET', 'POST'])
|
@app.route("/account", methods=['GET', 'POST'])
|
||||||
@check_session
|
@check_session
|
||||||
def account():
|
def account():
|
||||||
""" Arcticles page """
|
""" Account page """
|
||||||
page = str(request.url_rule)
|
page = str(request.url_rule)
|
||||||
menu = get_menu(page)
|
menu = get_menu(page)
|
||||||
return render_template('account.html', menu=menu)
|
user = Tetawebapp_users.query.filter_by(mail=session['login']).first()
|
||||||
|
mail = '' if user.mail == None else user.mail
|
||||||
|
name = '' if user.name == None else user.name
|
||||||
|
phone = '' if user.phone == None else user.phone
|
||||||
|
diet = '' if user.diet == None else user.diet
|
||||||
|
message = check_user_info()
|
||||||
|
return render_template('account.html', menu=menu, mail=mail, name=name, phone=phone, diet=diet, message=message)
|
||||||
|
|
||||||
|
@app.route("/account/update", methods=['GET', 'POST'])
|
||||||
|
@check_session
|
||||||
|
def update_account():
|
||||||
|
""" Update current account """
|
||||||
|
try:
|
||||||
|
page = str(request.url_rule)
|
||||||
|
menu = get_menu(page)
|
||||||
|
login = session['login']
|
||||||
|
password = request.form.get('password').encode('utf-8')
|
||||||
|
confirm = request.form.get('confirm').encode('utf-8')
|
||||||
|
name = request.form.get('name').encode('utf-8')
|
||||||
|
phone = request.form.get('phone').encode('utf-8')
|
||||||
|
diet = request.form.get('diet').encode('utf-8')
|
||||||
|
if update_user(login, password, confirm, name, phone, diet):
|
||||||
|
message = check_user_info()
|
||||||
|
else:
|
||||||
|
message = "Erreur lors de l'enregistrement des données."
|
||||||
|
return render_template('account.html',
|
||||||
|
menu=menu,
|
||||||
|
mail=login.decode('utf-8'),
|
||||||
|
name=name.decode('utf-8'),
|
||||||
|
phone=phone.decode('utf-8'),
|
||||||
|
diet=diet.decode('utf-8'),
|
||||||
|
message=message)
|
||||||
|
except AttributeError:
|
||||||
|
return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
|
||||||
|
|
||||||
|
@app.route("/users", methods=['GET', 'POST'])
|
||||||
|
@check_session
|
||||||
|
def list_users():
|
||||||
|
""" Users list """
|
||||||
|
page = str(request.url_rule)
|
||||||
|
menu = get_menu(page)
|
||||||
|
message = check_user_info()
|
||||||
|
staffers = Tetawebapp_users.query.filter_by(is_admin=0).order_by(Tetawebapp_users.name).all()
|
||||||
|
return render_template('list_users.html', menu=menu, staffers=staffers, message=message)
|
||||||
|
|
||||||
@app.route("/account/<ID>", methods=['GET', 'POST'])
|
@app.route("/account/<ID>", methods=['GET', 'POST'])
|
||||||
@check_session
|
@check_session
|
||||||
def account_by_id(ID):
|
def account_by_id(ID):
|
||||||
""" Arcticles page """
|
""" Arcticles page """
|
||||||
|
try:
|
||||||
|
if session['is_admin']:
|
||||||
page = str(request.url_rule)
|
page = str(request.url_rule)
|
||||||
menu = get_menu(page)
|
menu = get_menu(page)
|
||||||
selected = page.replace('<ID>', ID)
|
user = Tetawebapp_users.query.filter_by(id=ID).first()
|
||||||
navbar = get_navbar(page, selected)
|
return render_template('account_by_id.html', menu=menu, user=user)
|
||||||
return render_template('account_by_id.html', menu=menu, navbar=navbar, ID=ID)
|
# User is not admin
|
||||||
|
return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
|
||||||
|
except AttributeError:
|
||||||
|
# User is not logged in
|
||||||
|
return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
|
||||||
|
|
||||||
|
@app.route("/account/update/<ID>", methods=['GET', 'POST'])
|
||||||
|
@check_session
|
||||||
|
def update_account_by_id(ID):
|
||||||
|
""" Update given account """
|
||||||
|
try:
|
||||||
|
if session['is_admin']:
|
||||||
|
page = str(request.url_rule)
|
||||||
|
menu = get_menu(page)
|
||||||
|
login = session['login']
|
||||||
|
password = request.form.get('password').encode('utf-8')
|
||||||
|
confirm = request.form.get('confirm').encode('utf-8')
|
||||||
|
name = request.form.get('name').encode('utf-8')
|
||||||
|
phone = request.form.get('phone').encode('utf-8')
|
||||||
|
diet = request.form.get('diet').encode('utf-8')
|
||||||
|
if update_user_by_id(ID, login, password, confirm, name, phone, diet):
|
||||||
|
user = Tetawebapp_users.query.filter_by(id=ID).first()
|
||||||
|
message = check_user_info()
|
||||||
|
else:
|
||||||
|
message = "Erreur lors de l'enregistrement des données."
|
||||||
|
return render_template('account_by_id.html',
|
||||||
|
menu=menu,
|
||||||
|
user=user,
|
||||||
|
message=message)
|
||||||
|
# User is not admin
|
||||||
|
return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
|
||||||
|
except AttributeError:
|
||||||
|
# User is not logged in
|
||||||
|
return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
|
||||||
|
|
||||||
|
@app.route("/account/delete/<ID>", methods=['GET', 'POST'])
|
||||||
|
@check_session
|
||||||
|
def delete_account(ID):
|
||||||
|
""" Delete given account """
|
||||||
|
try:
|
||||||
|
if session['is_admin']:
|
||||||
|
message = "Erreur lors de la suppression.".decode('utf-8')
|
||||||
|
if delete_user(ID):
|
||||||
|
message = ''
|
||||||
|
page = str(request.url_rule)
|
||||||
|
menu = get_menu(page)
|
||||||
|
staffers = Tetawebapp_users.query.filter_by(is_admin=0).order_by(Tetawebapp_users.name).all()
|
||||||
|
return render_template('list_users.html', menu=menu, staffers=staffers, message=message)
|
||||||
|
# User is not admin
|
||||||
|
return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
|
||||||
|
except AttributeError:
|
||||||
|
# User is not logged in
|
||||||
|
return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
|
||||||
|
|
||||||
@app.route("/logout", methods=['GET', 'POST'])
|
@app.route("/logout", methods=['GET', 'POST'])
|
||||||
@check_session
|
@check_session
|
||||||
@ -237,6 +482,7 @@ def logout():
|
|||||||
""" Logout user """
|
""" Logout user """
|
||||||
# Remove session token
|
# Remove session token
|
||||||
session['token'] = None
|
session['token'] = None
|
||||||
|
session['login'] = None
|
||||||
# Return user to index page
|
# Return user to index page
|
||||||
response = app.make_response(render_template('login_or_register.html', message=''))
|
response = app.make_response(render_template('login_or_register.html', message=''))
|
||||||
# Push token to cookie
|
# Push token to cookie
|
||||||
|
@ -36,25 +36,64 @@ CREATE TABLE participer_thsf_users (
|
|||||||
password text not NULL,
|
password text not NULL,
|
||||||
name text,
|
name text,
|
||||||
phone text,
|
phone text,
|
||||||
diet text
|
diet text,
|
||||||
|
is_admin integer not NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
\echo *********************************
|
||||||
|
\echo * Creating participer_thsf_roles table
|
||||||
|
\echo *********************************
|
||||||
|
|
||||||
CREATE TABLE participer_thsf_roles (
|
CREATE TABLE participer_thsf_roles (
|
||||||
id serial primary key,
|
id serial primary key,
|
||||||
role text not NULL,
|
role text not NULL,
|
||||||
description text not NULL
|
description text not NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
\echo *********************************
|
||||||
|
\echo * Creating participer_thsf_turns table
|
||||||
|
\echo *********************************
|
||||||
|
CREATE TYPE dow AS ENUM ('J', 'V', 'S', 'D');
|
||||||
|
CREATE TABLE participer_thsf_turns (
|
||||||
|
id serial primary key,
|
||||||
|
role_id integer not NULL,
|
||||||
|
user_id integer,
|
||||||
|
wday dow not NULL,
|
||||||
|
start_time time not NULL,
|
||||||
|
end_time time not NULL,
|
||||||
|
constraint fk_turns_role
|
||||||
|
foreign key (role_id)
|
||||||
|
REFERENCES participer_thsf_roles (id),
|
||||||
|
constraint fk_turns_user
|
||||||
|
foreign key (user_id)
|
||||||
|
REFERENCES participer_thsf_users (id)
|
||||||
|
);
|
||||||
|
|
||||||
\echo *************************************************
|
\echo *************************************************
|
||||||
\echo * Giving participer_thsf_users ownership to participer_thsf
|
\echo * Giving participer_thsf_users ownership to participer_thsf
|
||||||
\echo *************************************************
|
\echo *************************************************
|
||||||
alter table participer_thsf_users owner to participer_thsf;
|
alter table participer_thsf_users owner to participer_thsf;
|
||||||
|
|
||||||
|
\echo *************************************************
|
||||||
|
\echo * Giving participer_thsf_roles ownership to participer_thsf
|
||||||
|
\echo *************************************************
|
||||||
|
alter table participer_thsf_roles owner to participer_thsf;
|
||||||
|
|
||||||
|
\echo *************************************************
|
||||||
|
\echo * Giving participer_thsf_turns ownership to participer_thsf
|
||||||
|
\echo *************************************************
|
||||||
|
alter table participer_thsf_turns owner to participer_thsf;
|
||||||
|
|
||||||
\echo *********************************************************************
|
\echo *********************************************************************
|
||||||
\echo * Inserting user demo identified by password demo to participer_thsf_users
|
\echo * Inserting user demo identified by password demo to participer_thsf_users
|
||||||
\echo *********************************************************************
|
\echo *********************************************************************
|
||||||
insert into participer_thsf_users (mail, password, name) values ('demo', '$2b$12$yjv4QMctGJFj2HmmbF6u5uDq9ATIl/Y9Z96MbaqRrcG6AE0CGHKSS', 'demo');
|
insert into participer_thsf_users (mail, password, name, phone, diet, is_admin) values ('bofh@tetalab.org',
|
||||||
|
'$2b$12$wm7PQ9IE7TYGYk1XB11mPusq7HsjYLYxt5G4v5Wz.jZbh5iWDHP5q',
|
||||||
|
'BOFH',
|
||||||
|
'0000000000',
|
||||||
|
'Omnivore',
|
||||||
|
1);
|
||||||
|
|
||||||
\echo *********************************************************************
|
\echo *********************************************************************
|
||||||
\echo * Inserting roles to participer_thsf_roles
|
\echo * Inserting roles to participer_thsf_roles
|
@ -17,3 +17,23 @@ function register() {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function update_account() {
|
||||||
|
var password = document.getElementById('password').value;
|
||||||
|
var confirm = document.getElementById('confirm').value;
|
||||||
|
if (password != confirm){
|
||||||
|
alert("Confirmation mot de passe incohérente");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (password.length > 0 && password.length < 8){
|
||||||
|
alert("Le mot de passe doit avoir une longueur d'au moins 8 caractères");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function delete_account(id) {
|
||||||
|
if (confirm("La suppression d'un compte est définitive.\n\nConfirmer ?")) {
|
||||||
|
document.location='/account/delete/'+id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -370,7 +370,7 @@ input.upload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
form {
|
form {
|
||||||
width: 350px;
|
width: 400px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
}
|
}
|
||||||
@ -382,3 +382,49 @@ form > label {
|
|||||||
form > input[type='text'], form > input[type='password'] {
|
form > input[type='text'], form > input[type='password'] {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.table_header {
|
||||||
|
background-color: var(--coloured-bg);
|
||||||
|
text-align: left;
|
||||||
|
width: 910px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table_row {
|
||||||
|
text-align: left;
|
||||||
|
width: 910px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table_header > div, div.table_row > div {
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table_row > div {
|
||||||
|
border-color: var(--coloured-bg);
|
||||||
|
border-width: 1px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.even {
|
||||||
|
background-color: var(--light-coloured-bg);
|
||||||
|
border-color: var(--coloured-bg);
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: none none solid none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.odd {
|
||||||
|
background-color: var(--white);
|
||||||
|
border-color: var(--coloured-bg);
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: none none solid none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table_row > div.border_left {
|
||||||
|
border-style: none none none solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table_row > div.border_right {
|
||||||
|
border-style: none solid none none;
|
||||||
|
}
|
||||||
|
@ -16,13 +16,13 @@
|
|||||||
<li>Aucune des données que vous nous transmettrez ne sera fournie à un tiers</li>
|
<li>Aucune des données que vous nous transmettrez ne sera fournie à un tiers</li>
|
||||||
</ul>
|
</ul>
|
||||||
</p>
|
</p>
|
||||||
<form method='POST' action='/account'>
|
<form method='POST' action='/account/update'>
|
||||||
<label>Adresse email: </label><input id='login' name='login' type='text' /><br/>
|
<label>Adresse email: </label><input id='login' name='login' type='text' value='{{ mail }}' disabled='disabled'/><br/>
|
||||||
<label>Prénom ou pseudo: </label><input id='pseudo' name='pseudo' type='text' /><br/>
|
<label>Prénom ou pseudo: </label><input id='name' name='name' type='text' value='{{ name }}'/><br/>
|
||||||
<label>Nouveau mot de passe: </label><input id='password' name='password' type='password'/><br/>
|
<label>Nouveau mot de passe: </label><input id='password' name='password' type='password'/><br/>
|
||||||
<label>Répetez mot de passe: </label><input id='confirm' name='confirm' type='password' /><br/>
|
<label>Confirmation mot de passe: </label><input id='confirm' name='confirm' type='password'/><br/>
|
||||||
<label>Numéro de téléphone: </label><input id='phone' name='phone' type='text' /><br/>
|
<label>Numéro de téléphone: </label><input id='phone' name='phone' type='text' value='{{ phone }}'/><br/>
|
||||||
<label>Régime alimentaire: </label><input id='diet' name='diet' type='text' /><br/>
|
<label>Régime alimentaire et remarques: </label><input id='diet' name='diet' type='text' value='{{ diet }}'/><br/>
|
||||||
<input type='submit' value='Update' onclick='javascript:return update_account();'>
|
<input type='submit' value='Update' onclick='javascript:return update_account();'>
|
||||||
</article>
|
</article>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
15
templates/account_by_id.html
Normal file
15
templates/account_by_id.html
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{% extends "index.html" %}
|
||||||
|
{% block title %}Articles{% endblock %}
|
||||||
|
{% block main %}
|
||||||
|
<article>
|
||||||
|
<h3>Informations du compte</h3>
|
||||||
|
<form method='POST' action='/account/update/{{ user.id }}'>
|
||||||
|
<label>Adresse email: </label><input id='login' name='login' type='text' value='{{ user.mail }}' disabled='disabled'/><br/>
|
||||||
|
<label>Prénom ou pseudo: </label><input id='name' name='name' type='text' value='{{ user.name }}'/><br/>
|
||||||
|
<label>Nouveau mot de passe: </label><input id='password' name='password' type='password'/><br/>
|
||||||
|
<label>Confirmation mot de passe: </label><input id='confirm' name='confirm' type='password'/><br/>
|
||||||
|
<label>Numéro de téléphone: </label><input id='phone' name='phone' type='text' value='{{ user.phone }}'/><br/>
|
||||||
|
<label>Régime alimentaire et remarques: </label><input id='diet' name='diet' type='text' value='{{ user.diet }}'/><br/>
|
||||||
|
<input type='submit' value='Update' onclick='javascript:return update_account();'>
|
||||||
|
</article>
|
||||||
|
{% endblock %}
|
@ -46,12 +46,13 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% block main %}
|
{% if message and message != '' %}
|
||||||
<article class='right'>
|
|
||||||
{% if message != '' %}
|
|
||||||
<pre>{{ message }}</pre>
|
<pre>{{ message }}</pre>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% block main %}
|
||||||
|
<article class='right'>
|
||||||
<h3>We Make THSF</h3>
|
<h3>We Make THSF</h3>
|
||||||
|
<p>Bonjour {{ login }},</p>
|
||||||
<p>
|
<p>
|
||||||
Comme chaque année le <a href='https://www.thsf.net>'>Toulouse Hacker Space Factory</a> aura lieu à
|
Comme chaque année le <a href='https://www.thsf.net>'>Toulouse Hacker Space Factory</a> aura lieu à
|
||||||
<a href='http://mixart-myrys.org'>Mix'Art Myrys</a>.
|
<a href='http://mixart-myrys.org'>Mix'Art Myrys</a>.
|
||||||
@ -71,7 +72,7 @@
|
|||||||
de sélectionner le poste et les créneaux horaires pendant lesquels vous souhaitez vous rendre disponible.
|
de sélectionner le poste et les créneaux horaires pendant lesquels vous souhaitez vous rendre disponible.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
d'être tenu informé des évolutions de l'organisation et du déroulement du THSF via la mailing list du staff.
|
de poser vos questions, obtenir des réponses et être tenu informé des évolutions de l'organisation et du déroulement du THSF via la mailing list du staff.
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</p>
|
</p>
|
||||||
|
29
templates/list_users.html
Normal file
29
templates/list_users.html
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{% extends "index.html" %}
|
||||||
|
{% block title %}Articles{% endblock %}
|
||||||
|
{% block main %}
|
||||||
|
<article>
|
||||||
|
<h3>Liste des staffers enregistrés</h3>
|
||||||
|
<div class='table_header'>
|
||||||
|
<div class='border_right' style='width: 40px;'>ID</div>
|
||||||
|
<div class='border_right'>Mail</div>
|
||||||
|
<div class='border_right'>Nom</div>
|
||||||
|
<div class='border_right'>Téléphone</div>
|
||||||
|
<div class='border_right'>Régime / Remarques</div>
|
||||||
|
<div style='width: 50px;'>Action</div>
|
||||||
|
</div>
|
||||||
|
{% set row_class = cycler('odd', 'even') %}
|
||||||
|
{% for staffer in staffers %}
|
||||||
|
<div class='table_row {{ row_class.next() }}'>
|
||||||
|
<div class='border_right' style='width: 40px;'>{{ staffer.id }}</div>
|
||||||
|
<div class='border_right'>{{ staffer.mail }}</div>
|
||||||
|
<div class='border_right'>{{ staffer.name }}</div>
|
||||||
|
<div class='border_right'>{{ staffer.phone }}</div>
|
||||||
|
<div class='border_right'>{{ staffer.diet }}</div>
|
||||||
|
<div style='width: 50px;'>
|
||||||
|
<input class='edit' value='' onclick='javascript:document.location="/account/{{ staffer.id }}"' title='Éditer'/>
|
||||||
|
<input class='trash' value='' onclick='javascript:delete_account({{ staffer.id }});' title='Supprimer'/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</article>
|
||||||
|
{% endblock %}
|
@ -40,9 +40,6 @@
|
|||||||
<p class='note'>Aucun électron n'a été maltraité lors de la mise au point de ce site.
|
<p class='note'>Aucun électron n'a été maltraité lors de la mise au point de ce site.
|
||||||
Par ailleurs ce site n'utilise ni ressources hébergées par des tiers, ni bullshitwares, ni trackers.</p>
|
Par ailleurs ce site n'utilise ni ressources hébergées par des tiers, ni bullshitwares, ni trackers.</p>
|
||||||
</article>
|
</article>
|
||||||
{% if message != '' %}
|
|
||||||
<pre>{{ message }}</pre>
|
|
||||||
{% endif %}
|
|
||||||
<hr/>
|
<hr/>
|
||||||
<article class='login'>
|
<article class='login'>
|
||||||
<h3>Connexion</h3>
|
<h3>Connexion</h3>
|
||||||
@ -53,6 +50,9 @@
|
|||||||
<label>Mot de passe: </label><input id='password' name='password' type='password' /><br/>
|
<label>Mot de passe: </label><input id='password' name='password' type='password' /><br/>
|
||||||
<input type='submit' value='Log me in' onclick='javascript:return verify_login();'>
|
<input type='submit' value='Log me in' onclick='javascript:return verify_login();'>
|
||||||
</form>
|
</form>
|
||||||
|
<p class='note'>
|
||||||
|
Mot de passe oublié ? Envoyez une <a href='https://bofh.tetalab.org/?do=newtask&project=2'>demande de réinitialisation de votre mot de passe</a>.
|
||||||
|
</p>
|
||||||
</article>
|
</article>
|
||||||
<hr/>
|
<hr/>
|
||||||
<article class='login'>
|
<article class='login'>
|
||||||
|
Loading…
Reference in New Issue
Block a user