Compare commits

...

45 Commits

Author SHA1 Message Date
2eb2d7fe98 update scripts 2023-03-18 23:10:07 +01:00
5cdd623e6a update scripts 2023-03-18 23:08:43 +01:00
740c744fc1 Supprimer 'scripts/mailconfig' 2022-12-23 13:23:49 +01:00
5fdee1d5ae correction config.py 2022-12-23 09:00:30 +01:00
37600d8bf2 Fautes d'orthographes ... :/ 2022-09-16 04:00:16 +02:00
cb49a4417d Travaux sur les messages aux utilisateurs 2022-09-16 03:56:11 +02:00
35c20b20e0 Corrections des fautes orthographes et déplacement de certaines messages 2022-09-16 03:18:58 +02:00
4e525f5d79 Correction d'un bug 2022-09-01 10:32:31 +02:00
1ac275c415 Travaux sur la validité des mails et des mots de passes 2022-09-01 07:29:49 +02:00
b8f03b77da Ajout de la licence du programme 2022-08-26 04:10:47 +02:00
f10523e706 Ajouter 'LICENSE' 2022-08-26 04:06:04 +02:00
c03142fe71 Suppression fichiers et variables inutiles 2022-08-22 05:43:55 +02:00
4bb19ff8a9 Correction de bugs 2022-08-22 05:34:56 +02:00
f5cd7021c5 Merge branch 'master' of https://kitoy.me/git/kitoy/pywallter
Simple oubli
2022-08-13 04:40:02 +02:00
bfb4cca7d3 modifié : README.md 2022-08-13 04:39:18 +02:00
kitoy
2fee7bef88 modified: config.py.example 2022-08-13 04:32:09 +02:00
5c1cc0a650 renommé : config.py -> config.py.example 2022-08-13 04:21:32 +02:00
6ee1b4decb modifié : .gitignore 2022-08-13 04:19:48 +02:00
3c149711f5 modifié : config.py 2022-08-13 04:18:11 +02:00
8cb8806673 Mise à jour de 'scripts/set_mail_passwd' 2022-08-13 01:42:12 +02:00
7c56207b4e Mise à jour de 'scripts/set_mail_passwd' 2022-08-13 01:41:38 +02:00
0d36ba7dcb Mise à jour de 'scripts/set_mail_passwd'
Oublie d'update une table
2022-08-13 01:41:01 +02:00
ecb3d4ac50 Mise à jour de 'Todo' 2022-08-12 16:35:41 +02:00
101f363293 Mise à jour de 'scripts/mailconfig' 2022-08-12 16:34:04 +02:00
kitoy
4f7afa21e8 modified: templates/accueil.html 2022-08-12 16:31:41 +02:00
kitoy
9d71b83218 modified: .gitignore 2022-08-12 16:25:34 +02:00
kitoy
a5b4ee42ed modified: config.py 2022-08-12 16:24:48 +02:00
kitoy
dfebabe92d modified: scripts/set_mail_alias
modified:   templates/myalias.html
	modified:   views/inscription.py
	modified:   views/profil.py
2022-08-12 16:18:46 +02:00
265e6d5f65 supprimé : sqlite
modifié :         views/loginlogout.py
2022-08-07 18:32:07 +02:00
f33e9f611a modifié : views/inscription.py 2022-08-07 18:25:37 +02:00
78227870bc Ajout fonction première connexion et correction base de donnée 2022-08-07 17:36:20 +02:00
kitoy
3451259a57 modified: templates/blog.html
modified:   templates/board.html
	modified:   templates/profil.html
	modified:   templates/up_up.html
	modified:   views/blog.py
	modified:   views/profil.py
2022-08-07 08:32:21 +02:00
kitoy
aef308e3fd modified: templates/profil.html
modified:   views/profil.py
2022-08-07 07:32:42 +02:00
kitoy
87a088f54d Correction de bugs inscription et changements de MDP 2022-08-07 06:10:36 +02:00
kitoy
4a278699d9 modified: scripts/set_mail_alias 2022-08-07 04:06:29 +02:00
kitoy
73002b5fb3 Correction des scripts d'exemple 2022-08-07 04:03:55 +02:00
kitoy
9094654956 supprimé : #README.md#
supprimé :        #wsgi.py#
2022-08-06 23:50:28 +02:00
kitoy
b34695a41b Work to flask derrière Nginx 2022-08-06 23:49:16 +02:00
083a7147ff Correction profil.py 2022-08-06 20:12:50 +02:00
d7a44c04a3 modifié : README.md 2022-08-06 19:25:27 +02:00
e42fdfd83e modifié : README.md
supprimé :        base.db.bkp
2022-08-06 19:04:38 +02:00
d923a5eb97 Ajout support serveur MAIL et XMPP 2022-08-06 18:22:24 +02:00
beb1e65ca7 Ajout d'un fichiers de configuration 2022-07-11 00:38:03 +02:00
66375d272f remplacement des menu et ajout d'un fichiers de configuration 2022-07-11 00:36:31 +02:00
6b264cd46b Suppression du blog par les post-it 2022-07-10 15:09:03 +02:00
54 changed files with 2674 additions and 1412 deletions

2
.gitignore vendored
View File

@@ -1,4 +1,6 @@
__pycache__/ __pycache__/
base.db base.db
log.txt log.txt
config.py
users/ users/

27
LICENSE Normal file
View File

@@ -0,0 +1,27 @@
BSD 2-Clause License
Copyright (c) 2015, Kitoy
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,27 +1,53 @@
# Pywallter est un projet pour partager des fichiers avec ses potes. # Pywallter est un projet de portail communautaire pour les utilisateurs d'un serveur.
Ça demande juste un identifiant et un mot de passe et voila. Ça demande juste un identifiant et un mot de passe et voila.
Si les serveurs Mail et/ou XMPP sont configurer pywallter peut à gerer les alias et le mot de passe pour son compte mail et XMPP
On peut y importer des fichiers que l'on pourra rendre accèssible en public par la suite.
Je voulais tester cette idée de post-it pour que les utilisateur puisse s'échanger des messages
ou que les admins puisse faire des annonces...
On verra
on pourrait ajoute de la double authentification mais bon ... on pourrait ajoute de la double authentification mais bon ...
## Pour démarrer le programme ## Installer le programme
### Sur OpenBSD (7.1) ### Sur OpenBSD (7.1)
Il faut installé FLask et quelques dépendances Il faut installer FLask et quelques dépendances
pkg_add py3-werkzeug py3-jinja2 py3-Pillow py3-wtforms py3-flask-wtf py3-flask \ pkg_add py3-werkzeug py3-jinja2 py3-Pillow py3-wtforms py3-flask-wtf py3-flask \
py3-bcrypt py3-markdown py3-bcrypt py3-markdown py3-gevent py3-zopeinterface
Il reste malheuresment une dépendances sur flask-bcrypt a installé avec pip:
pip install flask-bcrypt
### Sur Debian ### Sur Debian
apt install python3-flask python3-flask-bcrypt python3-wtforms python3-pil python3-markdown apt install python3-flask python3-flask-bcrypt python3-wtforms python3-pil python3-markdown \
### Ensuite dans le dossier du projet tu fais : python3-gevent python3-zope.interface
$ export FLASK_APP=pywallter.py ## Démarrer le programme :
$ flask run
# cp config.py.example config.py
$ python3 pywallter.py
#### En serveur de production
$ python3 wsgi.py
Et ça devrait démarrer sans soucis. Et ça devrait démarrer sans soucis.
Au premier démarage il créé un dossier pour les données et la base de données sqlite puis il s'arrête, ## Support serveru MAIL et XMPP
il faut donc le redémarrer (c'est un peu con faudra changer ça )
$ flask run Le logiciel a besoin de opensmtpd et prosody pour fonctionner.
Le serveur mail et xmmp se base sur le domaine de la machine.
Les scripts dans le dossier scripts sont la à titre d'exemple et peuvent être copié dans /usr/local/bin
Une configuration fonctionnelle de prosody et opensmtpd est disponible dans le wiki.
Suffit pour le faire redémarrer ## Comment ça fonctionne ?
Globalement le programme stocke les fichiers des utilisateurs dans un dossiers, les fichiers de tous types
sont stocker dans le dossier files et les images sont mis dans le dossier images et son consultable dans le menu gallerie.
Pour les comptes XMPP le programme fait un appel à prosodyctl.
Pour les comptes mail vous devez avoir deux programmes set_mail_alias et set_mail_passwd.
Les appels pour le compte mail se font ainsi :
set_mail_passwd example@votredomaine.fr 'le mot de passe'
set_mail_alias example@votredomaine.fr add monalias@votredomaine.fr
set_mail_alias example@votredomaine.fr del monalias@votredomaine.fr

54
Todo
View File

@@ -3,9 +3,9 @@ Bugs:
Liste d'améliorations à coder Liste d'améliorations à coder
- Vérifier et valider les requêtes envoyées via les formulaires avec WTForms
- Réorganiser le code en utilisant Blueprint
- Réorganiser le code en utilisant Blueprint (Fait)
- À l'inscription d'un membre, créer dossiers : - À l'inscription d'un membre, créer dossiers :
@@ -14,49 +14,15 @@ Liste d'améliorations à coder
/<user>/files/ /<user>/files/
/<user>/images/ /<user>/images/
/<user>/posts/ /<user>/posts/
/<user>/public/image/
/<user>/public/file/
- Faire un fichier de config. (Fait)
- Il faudrait aussi limiter la taille du dossier /<user>/ à 1 ou 2 Go maxi par exemple. (Plus tard)
Il faudrait aussi limiter la taille du dossier /<user>/ à 1 ou 2 Go maxi par exemple.
Mais du coup, si les fichiers, images, et posts sont stockés dans ces dossiers,
il faut stocker leurs chemins respectifs dans la bdd ? Et la consulter quand on veut afficher
ces fichiers dans des vues ?
Quand on aura fait ça déjà on sera pas mal. Quand on aura fait ça déjà on sera pas mal.
- Faciliter l'intégration d'un certificat let's encrypt (ça serait vraiment bon ça)
# Architecture future en construction/réflexion
#######################
pywallter/
__init__.py
views/
inscription.py
login.py
blog.py
upload.py
filelist.py
gallery.py
templates/
accueil.html
inscription.html
login.html
squelette.html
fileupload.html
blog.html
postedit.html
privateblog.html
publicblog.html
filelist.html
gallery.html
logs.html
parametres.html
profil.html
static/
js/
css/
fonts/
#######################
Un truc dans le genre ça pourrait le faire ?

31
config.py.example Normal file
View File

@@ -0,0 +1,31 @@
# L'adresse de base de votre site.
# example BASE_URL="https://example.com"
# BASE_URL="http://localhost:8000/" # si vous lancez pywallter avec flask run"
BASE_URL="https://example.com/"
# Essentiels pour les cookies
SECRET_KEY="CHANGE-ME"
# Dossier où seront stocker les fichiers
DOSSIER_APP = "./users/"
# Fichiers sqlite
DATABASE = "./base.db"
# Extension des images accepter
EXT_IMG= {'.jpg', '.JPG', '.png', '.PNG', '.gif', '.GIF', '.bmp', '.BMP', '.jpeg', '.JPEG' }
# Service
# XMPP = True => Le service est installé et lancer
# XMMP = False => Le service est désactivé
XMPP_SERVER = False
# Service Mail
# MAIL_SERVER = True => Le service est installé et lancer
# MAIL_SERVER = False => Le service est désactivé
MAIL_SERVER = False
# Doas or sudo
SETUID='doas'

View File

@@ -8,138 +8,76 @@ from flask_bcrypt import Bcrypt
from views.blog import blog from views.blog import postit
from views.filesupload import filesupload from views.filesupload import filesupload
from views.inscription import inscription from views.inscription import inscription
from views.profil import profil from views.profil import profil
from views.logs import logs from views.logs import logs
from views.loginlogout import loginlogout from views.loginlogout import loginlogout
from views.gallery import mygallery
from tools.databaseinit import init_db, init_dir from tools.databaseinit import init_db, init_dir, db_migrate
import glob, os, sys, time import glob, os, sys, time
app = Flask( 'pywallter' ) app = Flask( 'pywallter' )
app.config.from_pyfile('config.py')
bcrypt = Bcrypt(app) bcrypt = Bcrypt(app)
if init_db(): init_db()
print ("La base de données a été créer") db_migrate()
exit()
if init_dir(): if init_dir():
print ("Le repertoire des utilisateurs a été créer") print ("Le repertoire des utilisateurs a été créer")
exit()
# Set the secret key. Keep this really secret
app.secret_key = 'klfkdlfkdslfkln234325;cx!' # Chiffre les cookies si j'ai bien capté.
# À générer aléatoirement impérativement avant de mettre en ligne.
#### Variables #################################################################################### #### Variables ####################################################################################
DOSSIER_PERSO='users/' DOSSIER_PERSO= app.config['DOSSIER_APP']
extensionimg = {'.jpg', '.JPG', '.png', '.PNG', '.gif', '.GIF', '.bmp', '.BMP', '.jpeg', '.JPEG' } extensionimg = app.config['EXT_IMG']
################################################################################################## ##################################################################################################
app.register_blueprint(inscription) app.register_blueprint(inscription)
app.register_blueprint(blog) app.register_blueprint(postit)
app.register_blueprint(filesupload) app.register_blueprint(filesupload)
app.register_blueprint(profil) app.register_blueprint(profil)
app.register_blueprint(logs) app.register_blueprint(logs)
app.register_blueprint(loginlogout) app.register_blueprint(loginlogout)
app.register_blueprint(mygallery)
@app.route( '/gallery/')
def gallery():
if 'username' in session :
UTILISATEUR='%s' % escape(session['username'])
THUMBNAILS=DOSSIER_PERSO + UTILISATEUR + '/images/thumbnails/'
fichiers = [fich for fich in os.listdir(THUMBNAILS)]
return render_template('gallery.html', THUMBNAILS=THUMBNAILS, fichiers=fichiers)
else :
return redirect(url_for('loginlogout.login'))
@app.route( '/parametres/', methods=['GET','POST'] )
def parametres() :
if 'username' in session :
return render_template('parametres.html')
else:
return redirect(url_for('loginlogout.login'))
@app.route('/up/view/<nom>')
def download(nom):
if 'username' in session :
UTILISATEUR='%s' % escape(session['username'])
nom = secure_filename(nom)
if os.path.isfile(DOSSIER_PERSO + UTILISATEUR + '/files/' + nom): # si le fichier existe
return send_file(DOSSIER_PERSO + UTILISATEUR + '/files/' + nom, as_attachment=True) # on l'envoie
else:
flash(u'Fichier {nom} inexistant.'.format(nom=nom), 'error')
return redirect(url_for('list')) # sinon on redirige vers la liste, avec un message d'erreur
else :
return redirect(url_for('loginlogout.login'))
@app.route('/remove/<nom>')
def remove(nom):
if 'username' in session :
UTILISATEUR='%s' % escape(session['username'])
nom = secure_filename(nom)
if os.path.isfile(DOSSIER_PERSO + UTILISATEUR + '/files/' + nom): # si le fichier existe
os.remove(DOSSIER_PERSO + UTILISATEUR + '/files/' + nom) # on le supprime
return redirect(url_for('filesupload.list', _external=True))
else:
if os.path.isfile(DOSSIER_PERSO + UTILISATEUR + '/images/thumbnails/' + nom): # si le fichier existe
os.remove(DOSSIER_PERSO + UTILISATEUR + '/images/thumbnails/' + nom) # on le supprime
os.remove(DOSSIER_PERSO + UTILISATEUR + '/images/' + nom) # on le supprime
return redirect(url_for('gallery'))
else:
flash(u'Fichier {nom} inexistant.'.format(nom=nom), 'error')
return redirect(url_for('filesupload.list', _external=True)) # sinon on redirige vers la liste, avec un message d'erreur
else :
return redirect(url_for('loginlogout.login'))
@app.route('/myfiles/<filename>')
def myfiles(filename):
if 'username' in session :
UTILISATEUR='%s' % escape(session['username'])
return send_from_directory(
os.path.join(DOSSIER_PERSO, UTILISATEUR, 'files'), filename )
else :
return redirect(url_for('loginlogout.login'))
@app.route('/myfiles/images/<filename>')
def myimg(filename):
if 'username' in session :
UTILISATEUR='%s' % escape(session['username'])
return send_from_directory(
os.path.join(DOSSIER_PERSO, UTILISATEUR, 'images'), filename )
else :
return redirect(url_for('loginlogout.login'))
@app.route('/myfiles/images/thumbnails/<filename>')
def mythumbnails(filename):
if 'username' in session :
UTILISATEUR='%s' % escape(session['username'])
return send_from_directory(
os.path.join(DOSSIER_PERSO, UTILISATEUR, 'images/thumbnails'), filename )
else :
return redirect(url_for('loginlogout.login'))
@app.route( '/' )
def index():
if 'username' in session :
return redirect(url_for('filesupload.uploadfiles'))
else :
return redirect(url_for('loginlogout.login', _external=True))
def create_app():
app = Flask( 'pywallter' )
app.config.from_pyfile('config.py')
bcrypt = Bcrypt(app)
init_db()
db_migrate()
if init_dir():
print ("Le repertoire des utilisateurs a été créer")
DOSSIER_PERSO= app.config['DOSSIER_APP']
extensionimg = app.config['EXT_IMG']
app.register_blueprint(inscription)
app.register_blueprint(postit)
app.register_blueprint(filesupload)
app.register_blueprint(profil)
app.register_blueprint(logs)
app.register_blueprint(loginlogout)
app.register_blueprint(mygallery)
return app
if __name__ == '__main__' : if __name__ == '__main__' :
app.run(host='127.0.0.1', port=8080, debug=True) app.run(host='127.0.0.1', port=8000, debug=False)

9
scripts/etc/mailconfig Normal file
View File

@@ -0,0 +1,9 @@
# Password file
PASSWD_FILE="/etc/mail/passwd"
# Alias File
ALIAS_FILE="/etc/mail/virtuals"
# APPLICATIONS MAIL ADDRESS
APP_MAIL="/etc/mail/reserved"

115
scripts/set_mail_alias Executable file
View File

@@ -0,0 +1,115 @@
#!/bin/sh
. /etc/mailconfig
exit_failure(){
mess=$1
code_exit=$2
echo "$mess";
exit "$code_exit";
}
check_domain()
{
mail=$1
alias=$2
domain_mail=`echo $mail | awk -F '@' '{ print $2 }'`
domain_alias=`echo $alias | awk -F '@' '{ print $2 }'`
[[ "$domain_mail" = `hostname` && "$domain_alias" = `hostname` ]] || exit_failure "Bad domain" 1;
grep -q "$mail" "$PASSWD_FILE" && true || exit_failure "Mail doesn't exist" 1;
}
check_mail_exist()
{
mail=$1
grep -q "$mail" "$PASSWD_FILE" && exit_failure " This e-mail address already exist" 2 || true
}
check_alias()
{
alias=$1
grep -q "$alias" "$ALIAS_FILE" && exit_failure "This e- mail address already exist in alias" 2 || true
}
check_app_mail()
{
alias=$1
grep -q "$alias" "$APP_MAIL" && exit_failure "Address already exist in app mail" 2 || true
}
add_alias()
{
print "$2":" $1" >> "$ALIAS_FILE"
}
check_alias_exist(){
alias_c="$1: $2"
grep -q "$alias_c" "$ALIAS_FILE" && true || exit_failure "This alias doesn't exist" 3
}
del_alias()
{
alias_line="$1: $2"
egrep -v "$alias_line" "$ALIAS_FILE" > /tmp/alias.tmp
mv /tmp/alias.tmp "$ALIAS_FILE"
}
usage(){
print "This program ask 3 arguments : \n"
print "First is email with domain name of this host second is add or del for \n"
print "add or delete an alias "
print "\t$0 email-adresse del alias@`hostname`\n"
print "Other example:\n\t $0 test@`hostname` add myalias@`hostname` "
print "This script require root privilèges"
}
if [ `id -u` -ne 0 ]; then
usage
exit 4;
fi
if [ -z $1 ];
then
usage
exit 3;
fi
if [ -z $2 ];
then
usage
exit 3;
fi
if [ -z $3 ];
then
usage
exit 3;
fi
check_domain $1 $3
case $2 in
"add")
check_mail_exist $3
check_alias $3
check_app_mail $3
add_alias $1 $3
smtpctl update table virtuals
;;
"del")
check_alias_exist $3 $1
del_alias $3 $1
smtpctl update table virtuals
;;
*)
usage
exit 4;
;;
esac

108
scripts/set_mail_passwd Executable file
View File

@@ -0,0 +1,108 @@
#!/bin/sh
. /etc/mailconfig
exit_failure(){
mess=$1
code_exit=$2
echo "$mess";
exit "$code_exit";
}
check_domain()
{
mail=$1
domain=`echo $mail | awk -F '@' '{ print $2 }'`
[[ "$domain" = `hostname` ]] || exit_failure "Bad domain " 1
}
check_alias()
{
mail=$1
aliases=$(grep -v "$mail" $ALIAS_FILE)
echo "$aliases" | grep -q "$mail" && exit_failure "Address already exist in alias" 2 || true
}
check_app_mail()
{
alias=$1
grep -q "$alias" "$APP_MAIL" && exit_failure "This e-mail address already exist in app mail" 2 || true
}
set_password()
{
mail=$1
password=$2
cat $PASSWD_FILE | grep -w -v -e "$mail" > /tmp/passwd.tmp
print "$mail":`encrypt "$password"` >> /tmp/passwd.tmp
mv /tmp/passwd.tmp $PASSWD_FILE
}
add_mailbox()
{
mail=$1
cat $ALIAS_FILE | grep -w -v -e "$mail: vmail" > /tmp/virtuals.tmp
print "$1: vmail" >> /tmp/virtuals.tmp
mv /tmp/virtuals.tmp $ALIAS_FILE
}
delete_mail_account()
{
mail=$1
cat $PASSWD_FILE | grep -w -v -e "$mail" > /tmp/passwd.tmp
mv /tmp/passwd.tmp $PASSWD_FILE
cat $ALIAS_FILE | grep -v "$mail" >> /tmp/virtuals.tmp
mv /tmp/virtuals.tmp $ALIAS_FILE
# rm -fr repertoir mail.
}
usage(){
print "This program ask 2 arguments : \n"
print "For add or change password of mail account :\: "
print "First is email with domain name of this host second is password \n:"
print "\t$0 email-adresse 'password'\n"
print "Example:\n\t $0 add example@`hostname` 'yourverysecurepassword' "
print "For delete a mail account:\n"
print "$0 del test@`hostname`"
print "This script require root privilèges"
}
if [ `id -u` -ne 0 ]; then
usage
exit 4;
fi
if [ -z "$1" ]; then
usage
exit 3;
fi
if [ -z "$2" ]; then
usage
exit 3;
fi
case $1 in
"del")
check_domain "$2"
delete_mail_account "$2"
smtpctl update table passwd
smtpctl update table virtuals
;;
*)
check_domain "$1"
check_alias "$1"
check_app_mail "$1"
set_password "$1" "$2"
add_mailbox "$1"
smtpctl update table passwd
smtpctl update table virtuals
;;
esac

1221
static/bootstrap.css vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -9,11 +9,13 @@ a:hover {
color: #fff; color: #fff;
}*/ }*/
/* Custom default button */ /* Custom default button */
.btn-default, .btn-default,
.btn-default:hover, .btn-default:hover,
.btn-default:focus { .btn-default:focus {
color: #333; color: #fff;
text-shadow: none; /* Prevent inheritence from `body` */ text-shadow: none; /* Prevent inheritence from `body` */
/*background-color: #fff;*/ /*background-color: #fff;*/
border: 1px solid #fff; border: 1px solid #fff;
@@ -35,6 +37,19 @@ body {
text-shadow: 0 1px 3px rgba(0,0,0,.5); text-shadow: 0 1px 3px rgba(0,0,0,.5);
} }
a {
color: #428bca;
}
a:focus, a:hover {
color: #6cbdbd;
text-decoration: underline;
}
/* Extra markup and styles for table-esque vertical and horizontal centering */ /* Extra markup and styles for table-esque vertical and horizontal centering */
.site-wrapper { .site-wrapper {
display: table; display: table;
@@ -58,6 +73,29 @@ body {
padding: 30px; padding: 30px;
} }
.panel-body {
background-color: #444;
}
.row {
margin-top: 5vw;
}
.container a {
color #00abff;
}
.panel-body a {
color: #00abff;
}
.well {
margin-top : 7em;
}
.well a {
color: #00abff;
}
/* /*
* Header * Header

View File

@@ -1,11 +1,11 @@
function divhider() { function divhider() {
var x = document.getElementsByClassName("msginfo"); var x = document.getElementsByClassName("flashed");
x[0].style.visibility = "hidden"; x[0].style.visibility = "hidden";
} }
function animation() { function animation() {
var x = document.getElementsByClassName("msginfo"); var x = document.getElementsByClassName("flashed");
x[0].style.animation = "disparition 0.2s 1"; x[0].style.animation = "disparition 0.2s 1";
} }

View File

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Binary file not shown.

View File

@@ -16,3 +16,14 @@ body {
.theme-showcase .navbar .container { .theme-showcase .navbar .container {
width: auto; width: auto;
} }
a {
color: #3cbdbd;
}
a:focus, a:hover {
color: #6cbdbd;
text-decoration: underline;
}

View File

@@ -37,7 +37,7 @@
margin: auto; margin: auto;
margin-top: 5%; margin-top: 5%;
width: 50%; width: 50%;
background-color: #333;
} }
.flashed p { .flashed p {
@@ -182,6 +182,7 @@
#gallery img:hover { #gallery img:hover {
filter:none; filter:none;
transform: scale(1.2);
} }
@media (max-width: 1200px) { @media (max-width: 1200px) {

18
templates/_head.html Normal file
View File

@@ -0,0 +1,18 @@
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="../../favicon.ico">
<title>Un serveur et des ...</title>
<!-- Bootstrap core CSS -->
<link href="{{ url_for('static', filename='bootstrap.min.css') }}" rel="stylesheet">
<!-- Bootstrap theme -->
<link href="{{ url_for('static', filename='bootstrap-theme.min.css') }}" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="{{ url_for('static', filename='up.css') }}" rel="stylesheet">
<link href="{{ url_for('static', filename='cover.css') }}" rel="stylesheet">
<script type="text/javascript" src="{{ url_for('static', filename='divhider.js') }}"></script>
</head>

6
templates/_js.html Normal file
View File

@@ -0,0 +1,6 @@
<!-- Bootstrap core JavaScript -->
<!--================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="{{ url_for('static', filename='jquery.min.js') }}"></script>
<script src="{{ url_for('static', filename='bootstrap.min.js') }}"></script>
<script src="{{ url_for('static', filename='docs.min.js') }}"></script>

View File

@@ -0,0 +1,73 @@
<!-- Fixed navbar -->
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!--<li class="active"><a href="/blog/">Blog</a></li>-->
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li {% if section == "Post-it" %} class="active" {% endif %}>
<a href="/post-it/">
<span class="glyphicon glyphicon-globe" aria-hidden="true"></span>
Post-it !
</a>
</li>
<li{% if section == "Files" %} class="active" {% endif %} >
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<span class="glyphicon glyphicon-folder-open" aria-hidden="true"></span> Mes Fichiers</a>
<ul class="dropdown-menu" role="menu">
<li><a href="/view/"> <span class="glyphicon glyphicon-cloud-download" aria-hidden="true"></span>
Fichiers envoyés </a></li>
<li><a href="/filesupload/"><span class="glyphicon glyphicon-cloud-upload" aria-hidden="true"></span>
Envoyer des fichiers</a></li>
<li><a href="/gallery/"><span class="glyphicon glyphicon-cog" aria-hidden="true"></span>
Gallerie d'images
</a></li>
</ul>
<li{% if section == "mailbox" %} class="active" {% endif %} >
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<span class="glyphicon glyphicon-comment" aria-hidden="true"></span> Ma Messagerie </a>
<ul class="dropdown-menu" role="menu">
<li><a href="/mymailbox/alias"><span class="glyphicon glyphicon-sunglasses" aria-hidden="true"></span>
Gerer mes alias</a></li>
</ul>
</li>
<li{% if section == "Logs" %} class="active" {% endif %}>
<a href="/logs/"><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span>
Logs
</a>
</li>
<li {% if section == "Profil" %} class="dropdown active" {% else %} class="dropdown" {% endif %}>
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-home" aria-hidden="true"></span> <span id="majuscule">{{ session['username'] }} </span><span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="/profil/"><span class="glyphicon glyphicon-user" aria-hidden="true"></span> Profil</a></li>
<li><a href="/profil/change-password/"> <span class="glyphicon glyphicon-lock" aria-hidden="true"></span>
Changer mon mot de passe </a></li>
<li><a href="/invitation/"><span class="glyphicon glyphicon-cog" aria-hidden="true"></span> Inviter une personne</a></li>
<!--<li class="dropdown-header">Nav header</li>-->
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li>
<a href="/logout/">
<span class="glyphicon glyphicon-off" aria-hidden="true"></span>
Se déconnecter
</a>
</li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
<br/>
<br/>

View File

@@ -1,26 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html class="no-js" lang="fr"> <html class="no-js" lang="fr">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="../../favicon.ico">
<title>MaPagePerso</title>
<!-- Bootstrap core CSS -->
<link href="{{ url_for('static', filename='bootstrap.min.css') }}" rel="stylesheet">
<!-- Bootstrap theme -->
<link href="{{ url_for('static', filename='bootstrap-theme.min.css') }}" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="{{ url_for('static', filename='up.css') }}" rel="stylesheet">
<link href="{{ url_for('static', filename='cover.css') }}" rel="stylesheet">
<script type="text/javascript" src="{{ url_for('static', filename='divhider.js') }}"></script>
</head>
{% include '_head.html' %}
<body> <body>
{% block main %} {% block main %}
@@ -34,18 +15,18 @@
<div class="masthead clearfix"> <div class="masthead clearfix">
<div class="inner"> <div class="inner">
<h3 class="masthead-brand">Pywallter</h3> <h3 class="masthead-brand">Pywallter</h3>
<ul class="nav masthead-nav">
<li class="active"><a href="/filesupload/"></a></li>
<li><a href="#">Inscription</a></li>
<li><a href="#">Contact</a></li>
</ul>
</div> </div>
</div> </div>
<div class="inner cover"> <div class="inner cover">
<h1 class="cover-heading">Restez libres</h1> <h1 class="cover-heading">Restez libres</h1>
<p class="lead">Bienvenue sur Olala, hébergeur de fichier libre basé sur Flask et hébergé sur une simple petit ordinateur. <p class="lead">Bienvenue sur Olala, un portail utilisateurs libre basé sur Flask à héberger sur un petit ordinateur.
Bientôt disponible, gallerie d'images, blog et d'autres. Site en construction permanente.</p> Tu peux importer des fichiers et dans l'avenir les rendre disponible pour ton site
Tu peux consulter ou participer au tableau des post-its pour communiquer avec les autres membres ou
simplement savoir ce qu'il se passe sur le serveur.<br/>
tu peux gérer ton compte MAIL et XMPP si les serveur mail et XMPP sont actifs.
<br/>
<strong> Site en construction permanente. </strong></p>
<br> <br>
<p class="lead"> <p class="lead">
<form method="POST" action="{{ url_for('loginlogout.login') }}"> <form method="POST" action="{{ url_for('loginlogout.login') }}">
@@ -63,12 +44,7 @@
{% endblock %} {% endblock %}
<!-- Bootstrap core JavaScript --> {% include '_js.html' %}
<!--================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="{{ url_for('static', filename='jquery.min.js') }}"></script>
<script src="{{ url_for('static', filename='bootstrap.min.js') }}"></script>
<script src="{{ url_for('static', filename='docs.min.js') }}"></script>
</body> </body>

View File

@@ -1,43 +1,5 @@
{% extends 'up_squelette.html' %} {% extends 'up_squelette.html' %}
{% block navbar %}
<!-- Fixed navbar -->
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!--<li class="active"><a href="/blog/">Blog</a></li>-->
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="/blog/"><span class="glyphicon glyphicon-globe" aria-hidden="true"></span> Blog</a></li>
<li><a href="/filesupload/"><span class="glyphicon glyphicon-cloud-upload" aria-hidden="true"></span> Upload</a></li>
<li><a href="/view/"><span class="glyphicon glyphicon-cloud-download" aria-hidden="true"></span> Fichiers</a></li>
<li><a href="/gallery/"><span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span> Gallerie</a></li>
<li><a href="/logs/"><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span> Logs</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-home" aria-hidden="true"></span> <span id="majuscule">{{ session['username'] }} </span><span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="/profil/{{ session['username'] }}"><span class="glyphicon glyphicon-user" aria-hidden="true"></span> Profil</a></li>
<li><a href="/parametres/"><span class="glyphicon glyphicon-cog" aria-hidden="true"></span> Paramètres</a></li>
<li class="divider"></li>
<!--<li class="dropdown-header">Nav header</li>-->
<li><a href="/logout/"><span class="glyphicon glyphicon-off" aria-hidden="true"></span> Déconnexion</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="/logout/"><span class="glyphicon glyphicon-off" aria-hidden="true"></span> Exit</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
{% endblock %}
{% block main %} {% block main %}
@@ -51,13 +13,20 @@
<div class="col-sm-1"></div> <div class="col-sm-1"></div>
<div class="col-sm-10"> <div class="col-sm-10">
<br /> <br />
<div class="well"> Hello <span id="majuscule">{{ session['username'] }} ! </span>Bienvenue sur ce blog communautaire. Il vous est possible de poster des articles en tout genre sur cette page. Vous disposez pour cela d'un éditeur de type Markdown. Une page <a href="/blog/{{ session['username'] }}"><span class="glyphicon glyphicon-star" aria-hidden="true"></span> Page publique</a> et une <a href="/privateblog/"><span class="glyphicon glyphicon-star" aria-hidden="true"></span> Page privée</a> vous sont attribuées.<br>Ayez bien conscience que ce site est une expérience est qu'il est indispensable d'avoir une sauvegarde de tous vos articles. Nous ne pourrons, en aucun cas, être tenu responsable de la perte de vos données. Merci de votre compréhension.</div> <div class="well"> Hello <span id="majuscule">{{ session['username'] }} ! </span>
Bienvenue sur le tableau de post-it communautaire.
Il vous est possible de laisser des post-its en tout genre sur cette page.
Vous disposez pour cela d'un éditeur de type Markdown.
Une page <a href="/postit/board"><span class="glyphicon glyphicon-star" aria-hidden="true"></span>
est là pour consulter le tableau public du serveur</a>.
Celui-ci regroupe tout les post-it public des utilisateurs inscrits sur le serveur.<br>
Vous pouvez aussi écrire des post-its privé que vous seul pourrez consulter.</div>
</div> </div>
</div> </div>
<br /> <br />
<form method="POST" action="{{ url_for('blog.racine_blog') }}" id="postform"> <form method="POST" action="{{ url_for('post-it.racine_blog') }}" id="postform">
<!--<input type="text" name="category" id="category" placeholder="Catégorie" class="form-control"><br />--> <!--<input type="text" name="category" id="category" placeholder="Catégorie" class="form-control"><br />-->
<input type="text" name="title" id="title" placeholder="Titre" class="form-control"><br /> <input type="text" name="title" id="title" placeholder="Titre" class="form-control"><br />
<textarea class="form-control" form="postform" name="content" id="content" placeholder="Contenu" style="height:30vw;"></textarea><br /> <textarea class="form-control" form="postform" name="content" id="content" placeholder="Contenu" style="height:30vw;"></textarea><br />
@@ -78,8 +47,8 @@
<div class="row"> <div class="row">
<div class="col-sm-2"> <div class="col-sm-2">
<img src="/static/usersprofil/{{ post.avatar }}" class="img-rounded" alt=""/><br><br> <img src="/profil/{{ post.author }}/{{ post.avatar }}" height="100" width="100" class="img-rounded" alt=""/><br><br>
<p>{{ post.nom }}<br>{{ post.prenom }}<br>{{ post.age }} ans<br>{{ post.profession }}<br></p> <p>{% if post.author != None %}{{ post.author }} {%endif%} <br />{% if post.prenom != None %}{{ post.prenom }}{%endif%} <br/>{% if post.age != None %}{{ post.age }} ans {%endif%}<br /></p>
</div> </div>
<div class="col-sm-9"> <div class="col-sm-9">
@@ -100,8 +69,8 @@
<h4><span class="label label-success">Public</span></h4> <h4><span class="label label-success">Public</span></h4>
{% endif %} {% endif %}
<br /><br> <br /><br>
<a href="{{ url_for('blog.edit', post=post.title) }}"><button type="button" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-edit" aria-hidden="true"></span></button></a><br /><br> <a href="{{ url_for('post-it.edit', post=post.title) }}"><button type="button" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-edit" aria-hidden="true"></span></button></a><br /><br>
<a href="{{ url_for('blog.delete', post=post.title) }}"><button type="button" class="btn btn-sm btn-danger"><span class="glyphicon glyphicon-trash" aria-hidden="true"></span></button></a><br /><br> <a href="{{ url_for('post-it.delete', post=post.title) }}"><button type="button" class="btn btn-sm btn-danger"><span class="glyphicon glyphicon-trash" aria-hidden="true"></span></button></a><br /><br>
{% endif %} {% endif %}
</div> </div>
@@ -110,5 +79,3 @@
{% endfor %} {% endfor %}
{% endblock %} {% endblock %}
</div>

33
templates/board.html Normal file
View File

@@ -0,0 +1,33 @@
{% extends 'up_squelette.html' %}
{% block main %}
{% for post in posts %}
{% if post.nom != None %}
<div class="well">
<div class="row">
<div class="col-sm-2">
<img src="/profil/{{post.author}}/{{ post.avatar }}" height="100" width="100" class="img-rounded" alt=""/><br><br>
<p>{% if post.author != None %}{{ post.author }} {%endif%} <br />{% if post.prenom != None %}{{ post.prenom }}{%endif%} <br/>{% if post.age != None %}{{ post.age }} ans {%endif%}<br /></p>
</div>
<div class="col-sm-9">
<h6>{{ post.time }}</h6>
<h2>{{ post.title }}</h2>
{{ post.content|safe }}
</div>
</div>
</div>
{% endif %}
{% endfor %}
{% endblock %}

View File

@@ -1,43 +1,5 @@
{% extends 'up_squelette.html' %} {% extends 'up_squelette.html' %}
{% block navbar %}
<!-- Fixed navbar -->
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!--<a class="navbar-brand" href="/blog/">Blog</a>-->
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/blog"><span class="glyphicon glyphicon-globe" aria-hidden="true"></span> Blog</a></li>
<li><a href="/filesupload/"><span class="glyphicon glyphicon-cloud-upload" aria-hidden="true"></span> Upload</a></li>
<li><a href="/view/"><span class="glyphicon glyphicon-cloud-download" aria-hidden="true"></span> Fichiers</a></li>
<li class="active"><a href="/gallery/"><span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span> Gallerie</a></li>
<li><a href="/logs/"><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span> Logs</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-home" aria-hidden="true"></span> <span id="majuscule">{{ session['username'] }} <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="/profil/{{ session['username'] }}"><span class="glyphicon glyphicon-user" aria-hidden="true"></span> Profil</a></li>
<li><a href="/parametres/"><span class="glyphicon glyphicon-cog" aria-hidden="true"></span> Paramètres</a></li>
<li class="divider"></li>
<!--<li class="dropdown-header">Nav header</li>-->
<li><a href="/logout/"><span class="glyphicon glyphicon-off" aria-hidden="true"></span> Déconnexion</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="/logout/"><span class="glyphicon glyphicon-off" aria-hidden="true"></span> Exit</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
{% endblock %}
{% block main %} {% block main %}

View File

@@ -10,10 +10,13 @@
<div class="masthead clearfix"> <div class="masthead clearfix">
<div class="inner"> <div class="inner">
<h3 class="masthead-brand">OpenBlogStock</h3> <h3 class="masthead-brand">Pywallter</h3>
<ul class="nav masthead-nav"> <ul class="nav masthead-nav">
<li><a href="/filesupload/">Login</a></li> <li><a href="/login/">Login</a></li>
{% if signin_enable %}
<li class="active"><a href="/inscription/">Inscription</a></li> <li class="active"><a href="/inscription/">Inscription</a></li>
{% endif %}
<li><a href="#">Contact</a></li> <li><a href="#">Contact</a></li>
</ul> </ul>
</div> </div>
@@ -22,16 +25,27 @@
<div class="inner cover"> <div class="inner cover">
<h1 class="cover-heading">Inscription</h1> <h1 class="cover-heading">Inscription</h1>
<br> <br>
<p class="lead">
<form method="POST" action="{{ url_for('inscription.signin') }}"> {% if signin_enable %}
<form method="POST" action="{{ url_inscription }}">
<input type="text" name="user" id="user" placeholder="Pseudo" class="form-control"><br /> <input type="text" name="user" id="user" placeholder="Pseudo" class="form-control"><br />
<input type="mail" name="mail" id="mail" placeholder="Adresse mail" class="form-control"><br /> {% if MAIL_SERVER %}
<div class="col-sm-7">
<input type="text" name="mail" id="mail" placeholder="Adresse mail" class="form-control" size="2"> <br/>
</div>
<h4>@{{hostname}}</h4>
<br/>
{% endif %}
<input type="password" name="passwd" id="passwd" placeholder="Mot de passe" class="form-control"><br /> <input type="password" name="passwd" id="passwd" placeholder="Mot de passe" class="form-control"><br />
<input type="password" name="passwdconfirm" id="passwdconfirm" placeholder="Confirmation du mot de passe" class="form-control"><br /> <input type="password" name="passwdconfirm" id="passwdconfirm" placeholder="Confirmation du mot de passe" class="form-control"><br />
<br> <br>
<button id="tada" class="btn btn-default btn-primary" type="submit">Envoyer</button> <button id="tada" class="btn btn-default btn-primary" type="submit">Envoyer</button>
</form> </form>
{% else %}
<p class="lead">
Désolé les inscriptions ne sont pas activés sur le serveur
</p> </p>
{%endif%}
{% for i in users %} {% for i in users %}
<p>{{i}}</p> <p>{{i}}</p>
{% endfor %} {% endfor %}

53
templates/invitation.html Normal file
View File

@@ -0,0 +1,53 @@
{% extends 'up_squelette.html' %}
{% block main %}
<div class="row">
<div class="well">
Si vous voulez vous pouvez inviter une personne à se crée un compte sur ce serveur
pour cela vous devez crée un lien d'inscription. Ce lien restera valable tant
que la personne ne s'est pas inscrite ou tant que vous ne créez pas un autre lien.
Les invitations se font une par une et sont limité à 20 personnes pour ne pas surcharger notre petit serveur :).
Une fois que la personne s'est incrite votre nombre d'invitations sera mis à jour
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">Création du lien d'inscription</h3>
</div>
<div class="panel-body">
{% if token %}
<h3> Votre lien d'inscription en cours: </h3>
<a href="{{ url_invitation }}">
{{ url_invitation }}
</a>
{% else %}
<h3> Pas d'invitation en attente </h3>
{% endif %}
<p> Il vous reste : {{ nb_invitation }} invitations à envoyer </p>
<a href="/gen_token/">
<button type="submit" id="tada" class="btn btn btn-success"> Créer un nouveau lien </button></a>
<div class="msginfo">
{# on affiche les messages d'erreur puis les messages de succes #}
{% for categorie in ['error', 'succes'] %}
{% with msgs = get_flashed_messages(category_filter=[categorie]) %}
{% if msgs %}
<div class="flashed {{ categorie }}">
{% for m in msgs %}
<p>{{ m|safe }}</p>
{% endfor %}
</div>
{% endif %}
{% endwith %}
{% endfor %}
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -1,63 +0,0 @@
{% extends 'accueil.html' %}
{% block main %}
<div class="site-wrapper">
<div class="site-wrapper-inner">
<div class="cover-container">
<div class="masthead clearfix">
<div class="inner">
<h3 class="masthead-brand">OpenBlogSotck</h3>
<ul class="nav masthead-nav">
<li class="active"><a href="/uploadfiles/">Login</a></li>
<li><a href="/inscription/">Inscription</a></li>
<li><a href="#">Contact</a></li>
</ul>
</div>
</div>
<div class="inner cover">
<h1 class="cover-heading">Restez libres</h1>
<p class="lead">Bienvenue sur Olala, hébergeur de fichier libre basé sur Flask et hébergé sur une simple Orange Pi. Bientôt disponible, gallerie d'images, blog et d'autres. Site en construction.</p>
<br>
<p class="lead">
<form method="POST" action="{{ url_for('loginlogout.login') }}">
<input type="text" name="user" id="user" placeholder="Utilisateur" class="form-control"><br />
<input type="password" name="passwd" id="passwd" placeholder="Mot de passe" class="form-control"><br />
<br>
<button id="tada" class="btn btn-default btn-primary" type="submit">Login</button>
</form>
</p>
</div>
<div class="msginfo">
{# On affiche les messages d'erreur puis les messages de succés #}
{% for categorie in ['error', 'succes'] %}
{% with msgs = get_flashed_messages(category_filter=[categorie]) %}
{% if msgs %}
<div class="flashed {{ categorie }}">
{% for m in msgs %}
<p>{{ m|safe }}</p>
{% endfor %}
</div>
{% endif %}
{% endwith %}
{% endfor %}
</div>
<div class="mastfoot">
<div class="inner">
<p>Cover template for <a href="http://getbootstrap.com">Bootstrap</a>, by <a href="https://twitter.com/mdo">@mdo</a>.</p>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -1,49 +1,11 @@
{% extends 'up_squelette.html' %} {% extends 'up_squelette.html' %}
{% block navbar %}
<!-- Fixed navbar -->
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!--<a class="navbar-brand" href="/blog/">Blog</a>-->
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/blog"><span class="glyphicon glyphicon-globe" aria-hidden="true"></span> Blog</a></li>
<li><a href="/filesupload/"><span class="glyphicon glyphicon-cloud-upload" aria-hidden="true"></span> Upload</a></li>
<li><a href="/view/"><span class="glyphicon glyphicon-cloud-download" aria-hidden="true"></span> Fichiers</a></li>
<li><a href="/gallery/"><span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span> Gallerie</a></li>
<li class="active"><a href="/logs/"><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span> Logs</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-home" aria-hidden="true"></span> <span id="majuscule">{{ session['username'] }} <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="/profil/{{ session['username'] }}"><span class="glyphicon glyphicon-user" aria-hidden="true"></span> Profil</a></li>
<li><a href="/parametres/"><span class="glyphicon glyphicon-cog" aria-hidden="true"></span> Paramètres</a></li>
<li class="divider"></li>
<!--<li class="dropdown-header">Nav header</li>-->
<li><a href="/logout/"><span class="glyphicon glyphicon-off" aria-hidden="true"></span> Déconnexion</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="/logout/"><span class="glyphicon glyphicon-off" aria-hidden="true"></span> Exit</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
{% endblock %}
{% block main %} {% block main %}
<!--<div class="page-header"> <div class="page-header">
<p class="text-center"><h1>Logs</h1></p> <p class="text-center"><h1>Logs</h1></p>
</div>--> </div>
<br /> <br />

49
templates/mailbox.html Normal file
View File

@@ -0,0 +1,49 @@
{% extends 'up_squelette.html' %}
{% block main %}
<!--<div class="page-header">
<h1>Profil</h1>
</div>-->
<div class="row">
<div class="col-sm-3"></div>
<div class="col-sm-6">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"> Changer mon mot de passe </h3>
</div>
<div class="panel-body">
<form method="POST" action="" enctype="multipart/form-data">
<p> Votre Adresse e-mail sur ce serveur : {{ address }} </p>
<label> Mot de passe </label>
<input type="password" name="password" id="password" placeholder="Votre mot de passe" class="form-control"><br />
<input type="password" name="passwd_confirm" id="passwd_confirm" placeholder="Confirmation du mot de passe" class="form-control"><br />
<button id="tada" class="btn btn-default btn-primary" type="submit">Envoyer</button>
</form>
{# on affiche les messages d'erreur puis les messages de succes #}
{% for categorie in ['error', 'succes'] %}
{% with msgs = get_flashed_messages(category_filter=[categorie]) %}
{% if msgs %}
<div class="flashed {{ categorie }}">
{% for m in msgs %}
<p>{{ m|safe }}</p>
{% endfor %}
</div>
{% endif %}
{% endwith %}
{% endfor %}
</div>
</div>
</div>
</div>
{% endblock %}

91
templates/myalias.html Normal file
View File

@@ -0,0 +1,91 @@
{% extends 'up_squelette.html' %}
{% block main %}
<div class="row">
{% if MAIL_SERVER %}
<div class="col-md-12">
<h3> A quoi ca sert les alias ? </h3>
<p> Les alias c'est utile quand vous ne voulez pas donner votre vrai adresse e-mail.
Vous pouvez creer une adresse que vous pouvez supprimer rapidemment, cela permet personnaliser une adresse pour un destinataire
si vous n'avez pas confiance en lui ou de trier plus facilement les e-mails venant de ce destinataire.
</p>
<p> Vous n'avez pas besoin de configurer un autre compte mail sur vos applications, tous les e-mails
arriveront sur votre adresse e-mail principale déjà configuré
</p>
<table class="table">
<thead>
<tr>
<th>Mes Alias <span class="badge">{{ i }}</span></th>
<th></th>
</tr>
</thead>
<tbody>
{% if aliases %}
{% for alias in aliases %}
<tr>
<td>{{ alias }}</td>
<td><a href="{{ url_for('profil.remove_alias', aliasrm=alias) }}"><button type="button" class="btn btn-sm btn-danger">Supprimer</button></a></td>
</tr>
{% endfor %}
{% endif %}
</tbody>
</table>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"> Mes identités </h3>
</div>
<div class="panel-body">
<form method="POST" action="" enctype="multipart/form-data">
<p> Votre Adresse e-mail sur ce serveur : {{ email }} </p>
<label> Nouvelle identité </label>
<br/>
<div class="col-sm-7">
<input type="text" name="alias" id="alias" placeholder="Nouvel_identité" class="form-control"><br />
</div>
<h4>@{{ hostname }}</h4>
<br/>
<br/>
<button id="tada" class="btn btn-default btn-primary" type="submit">Ajouter</button>
</form>
</div>
</div>
{% else %}
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"> Mes identitées </h3>
</div>
<div class="panel-body">
<h2> Le serveur de mail n'est pas activé cette fonctionnalité est désactivé <h2>
</div>
</div>
{% endif %}
{# on affiche les messages d'erreur puis les messages de succes #}
{% for categorie in ['error', 'succes'] %}
{% with msgs = get_flashed_messages(category_filter=[categorie]) %}
{% if msgs %}
<div class="flashed {{ categorie }}">
{% for m in msgs %}
<p>{{ m|safe }}</p>
{% endfor %}
</div>
{% endif %}
{% endwith %}
{% endfor %}
{% endblock %}

View File

@@ -1,44 +1,5 @@
{% extends 'up_squelette.html' %} {% extends 'up_squelette.html' %}
{% block navbar %}
<!-- Fixed navbar -->
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!--<li class="active"><a href="/blog/">Blog</a></li>-->
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/blog"><span class="glyphicon glyphicon-globe" aria-hidden="true"></span> Blog</a></li>
<li><a href="/upload/"><span class="glyphicon glyphicon-cloud-upload" aria-hidden="true"></span> Upload</a></li>
<li><a href="/view/"><span class="glyphicon glyphicon-cloud-download" aria-hidden="true"></span> Fichiers</a></li>
<li><a href="/gallery/"><span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span> Gallerie</a></li>
<li><a href="/logs/"><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span> Logs</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-home" aria-hidden="true"></span> {{ session['username'] }} <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="/profil/{{ session['username'] }}"><span class="glyphicon glyphicon-user" aria-hidden="true"></span> Profil</a></li>
<li><a href="/parametres/"><span class="glyphicon glyphicon-cog" aria-hidden="true"></span> Paramètres</a></li>
<li class="divider"></li>
<!--<li class="dropdown-header">Nav header</li>-->
<li><a href="/logout/"><span class="glyphicon glyphicon-off" aria-hidden="true"></span> Déconnexion</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="/logout/"><span class="glyphicon glyphicon-off" aria-hidden="true"></span> Exit</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
{% endblock %}
{% block main %} {% block main %}
<div class="page-header"> <div class="page-header">

View File

@@ -1,53 +1,9 @@
{% extends 'up_squelette.html' %} {% extends 'up_squelette.html' %}
{% block navbar %} {% include '_nav_userlogin.html' %}
<!-- Fixed navbar -->
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!--<li class="active"><a href="/blog/">Blog</a></li>-->
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="/blog"><span class="glyphicon glyphicon-globe" aria-hidden="true"></span> Blog</a></li>
<li><a href="/upload/"><span class="glyphicon glyphicon-cloud-upload" aria-hidden="true"></span> Upload</a></li>
<li><a href="/view/"><span class="glyphicon glyphicon-cloud-download" aria-hidden="true"></span> Fichiers</a></li>
<li><a href="/gallery/"><span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span> Gallerie</a></li>
<li><a href="/logs/"><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span> Logs</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-home" aria-hidden="true"></span> <span id="majuscule">{{ session['username'] }} </span><span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="/profil/{{ session['username'] }}"><span class="glyphicon glyphicon-user" aria-hidden="true"></span> Profil</a></li>
<li><a href="/parametres/"><span class="glyphicon glyphicon-cog" aria-hidden="true"></span> Paramètres</a></li>
<li class="divider"></li>
<!--<li class="dropdown-header">Nav header</li>-->
<li><a href="/logout/"><span class="glyphicon glyphicon-off" aria-hidden="true"></span> Déconnexion</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="/logout/"><span class="glyphicon glyphicon-off" aria-hidden="true"></span> Exit</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
{% endblock %}
{% block main %} {% block main %}
<!-- Main jumbotron for a primary marketing message or call to action
<div class="jumbotron">
<h1>Blog</h1>
<p><span id="majuscule">Hello {{ session['username'] }} ! </span>Bienvenue sur ce blog communautaire. Les articles de tous les auteurs du site sont actuellement disponibles sur cette page. Une page personnelle vous est fournie à l'adresse : <a href="/blog/{{ session['username'] }}">Page perso</a></p>
<p><a href="http://flask.pocoo.org/" class="btn btn-primary btn-lg" role="button">En savoir plus &raquo;</a></p>
</div>-->
<div class="row"> <div class="row">
<div class="col-sm-1"></div> <div class="col-sm-1"></div>
<div class="col-sm-10"> <div class="col-sm-10">

View File

@@ -1,57 +0,0 @@
{% extends 'up_squelette.html' %}
{% block main %}
<div class="jumbotron">
<div class="row">
<div class="col-sm-4">
<p id="majuscule" class="text-center"><h3>Articles privés de <span id="majuscule">{{ UTILISATEUR }}</span></h3>
<br />
<h5>Articles visibles par vous seul ...</h5></p>
</div>
<div class="col-sm-6">
</div>
<div class="col-sm-2">
<img src="/static/usersprofil/{{ usersinfos[0] }}" class="img-rounded" alt=""/>
</div>
</div>
</div>
<br>
{% for post in posts %}
<div class="row">
<div class="col-sm-2">
</div>
<div class="col-sm-8">
<div class="well">
<div class="row">
<div class="col-sm-10">
<div class="well">
<h6>{{ post.time }}</h6>
<h2>{{ post.title }}</h2>
{{ post.content|safe }}
<h6>Auteur : {{ post.author }}</h6>
</div>
</div>
<div class="col-sm-1">
{% if post.author == session['username'] %}
{% if post.status == 'prive' %}
<h4><span class="label label-danger">Privé</span></h4>
{% else %}
<h4><span class="label label-success">Public</span></h4>
{% endif %}
<br /><br>
<a href="{{ url_for('blog.edit', post=post.title) }}"><button type="button" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-edit" aria-hidden="true"></span></button></a><br /><br>
<a href="{{ url_for('blog.delete', post=post.title) }}"><button type="button" class="btn btn-sm btn-danger"><span class="glyphicon glyphicon-trash" aria-hidden="true"></span></button></a>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endfor %}
{% endblock %}
</div>

View File

@@ -1,43 +1,5 @@
{% extends 'up_squelette.html' %} {% extends 'up_squelette.html' %}
{% block navbar %}
<!-- Fixed navbar -->
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!--<li class="active"><a href="/blog/">Blog</a></li>-->
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/blog"><span class="glyphicon glyphicon-globe" aria-hidden="true"></span> Blog</a></li>
<li><a href="/filesupload/"><span class="glyphicon glyphicon-cloud-upload" aria-hidden="true"></span> Upload</a></li>
<li><a href="/view/"><span class="glyphicon glyphicon-cloud-download" aria-hidden="true"></span> Fichiers</a></li>
<li><a href="/gallery/"><span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span> Gallerie</a></li>
<li><a href="/logs/"><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span> Logs</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-home" aria-hidden="true"></span> <span id="majuscule">{{ session['username'] }} <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="/profil/{{ session['username'] }}"><span class="glyphicon glyphicon-user" aria-hidden="true"></span> Profil</a></li>
<li><a href="/parametres/"><span class="glyphicon glyphicon-cog" aria-hidden="true"></span> Paramètres</a></li>
<li class="divider"></li>
<!--<li class="dropdown-header">Nav header</li>-->
<li><a href="/logout/"><span class="glyphicon glyphicon-off" aria-hidden="true"></span> Déconnexion</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="/logout/"><span class="glyphicon glyphicon-off" aria-hidden="true"></span> Exit</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
{% endblock %}
{% block main %} {% block main %}
@@ -46,57 +8,48 @@
</div>--> </div>-->
<div class="row"> <div class="row">
<!-- <div class="col-sm-6"> <h3> Bienvenue </h3>
<div class="panel panel-primary"> <p> Si vous êtes sur cette page, c'est que vous diposez d'un compte sur ce serveur.
<div class="panel-heading"> Du coup, vous avez une adresse e-mail et une adresse XMPP que vous pouvez utiliser
<h3 class="panel-title">Image de profil</h3> avec un client mail et avec un client XMPP (Bien évidemment)
</div> </p>
<div class="panel-body">
<form method="post" action="" enctype="multipart/form-data"> <p> Voici un exemple de <a href="https://www.thunderbird.net/fr/"> client mail </a>
<label for="fic">Choisissez une image de profil :</label><input type="file" name="fic" id="fic"/> et <a href="https://gajim.org/">client XMPP </a> pour un ordinateur </p>
<br>
<button type="submit" id="tada" class="btn btn btn-success">Envoyer</button>
</form>
<div> <p> un exemple de <a href="https://k9mail.app/"> client mail </a> et <a href="https://conversations.im/">client XMPP</a>
<img src="/static/usersprofil/{{ imageprofil[0] }}" class="img-rounded" alt=""/> pour un téléphone sous Android </p>
</div>
<div class="msginfo"> <p> et un un exemple de<a href="https://support.apple.com/fr-fr/mail"> client mail</a> et <a href="https://monal.im/"> client XMPP </a>sous iOS </p>
{# on affiche les messages d'erreur puis les messages de succes #}
{% for categorie in ['error', 'succes'] %} <p> Ton profil sert aux autres membres à te reconnaitre si tu met un post-it sur le <a href="/post-it/"> tableau des post-its </a> aucun champs n'est obligatoire,
{% with msgs = get_flashed_messages(category_filter=[categorie]) %} tu mets simplement les informations dont tu as envie </p>
{% if msgs %} <br/>
<div class="flashed {{ categorie }}"> <br/>
{% for m in msgs %}
<p>{{ m|safe }}</p>
{% endfor %}
</div>
{% endif %}
{% endwith %}
{% endfor %}
</div>
</div>
</div>
</div>-->
<div class="col-sm-3"></div> <div class="col-sm-3"></div>
<div class="col-sm-6"> <div class="col-sm-6">
<div class="panel panel-primary"> <div class="panel panel-primary">
<div class="panel-heading"> <div class="panel-heading">
<h3 class="panel-title">Informations personnelles</h3> <h3 class="panel-title">Mon profil</h3>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<form method="POST" action="" enctype="multipart/form-data"> <form method="POST" action="" enctype="multipart/form-data">
<div id="fic"><input type="file" name="fic" id="fic"/><br> <div id="fic">
<img id="fic" src="/static/usersprofil/{{ imageprofil[0] }}" class="img-rounded" alt=""/> <label> Photo de profil </label>
<input type="file" name="fic" id="fic"/><br>
<img id="fic" src="/profil/{{ username }}/{{ profil['avatar'] }}" class="img-rounded" alt=""/>
</div> </div>
<br> <br>
<input type="text" name="nom" id="nom" placeholder="Nom" class="form-control"><br /> <label>Nom </label>
<input type="text" name="prenom" id="prenom" placeholder="Prénom" class="form-control"><br /> <input type="text" name="nom" id="nom" value="{% if profil['nom'] != None %}{{ profil['nom'] }}{%endif%}" class="form-control"><br />
<input type="text" name="age" id="age" placeholder="Âge" class="form-control"><br /> <label>Prenom </label>
<input type="text" name="profession" id="profession" placeholder="Profession" class="form-control"><br /> <input type="text" name="prenom" id="prenom" value="{% if profil['nom'] != None %}{{ profil['prenom'] }}{%endif%}" class="form-control"><br />
<label> Age </label>
<input type="text" name="age" value="{% if profil['age'] != None %}{{ profil['age'] }}{%endif%}" class="form-control"><br />
<label> Mail de secours </label>
<input type="text" name="mail_rescue" id="mail_rescue" value="{% if profil['nom'] != None %}{{ profil['mail_rescue'] }}{%endif%}" class="form-control"><br />
<button id="tada" class="btn btn-default btn-primary" type="submit">Envoyer</button> <button id="tada" class="btn btn-default btn-primary" type="submit">Envoyer</button>
</form> </form>
{# on affiche les messages d'erreur puis les messages de succes #} {# on affiche les messages d'erreur puis les messages de succes #}

View File

@@ -1,53 +0,0 @@
{% extends 'up_squelette.html' %}
{% block main %}
<div class="jumbotron">
<div class="row">
<div class="col-sm-4">
<p id="majuscule" class="text-center"><h3>Blog de <span id="majuscule">{{ username }}</span></h3></p>
</div>
<div class="col-sm-6">
</div>
<div class="col-sm-2">
<img src="/static/usersprofil/{{ usersinfos[0] }}" class="img-rounded" alt=""/>
</div>
</div>
</div>
<br>
{% for post in posts %}
<div class="row">
<div class="col-sm-2">
</div>
<div class="col-sm-8">
<div class="well">
<div class="row">
<div class="col-sm-10">
<h6>{{ post.time }}</h6>
<h2>{{ post.title }}</h2>
{{ post.content|safe }}
<br><h6>Auteur : {{ post.author }}</h6>
</div>
<div class="col-sm-1">
{% if post.author == session['username'] %}
{% if post.status == 'prive' %}
<h4><span class="label label-danger">Privé</span></h4>
{% else %}
<h4><span class="label label-success">Public</span></h4>
{% endif %}
<br /><br>
<a href="{{ url_for('blog.edit', post=post.title) }}"><button type="button" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-edit" aria-hidden="true"></span></button></a><br /><br>
<a href="{{ url_for('blog.delete', post=post.title) }}"><button type="button" class="btn btn-sm btn-danger"><span class="glyphicon glyphicon-trash" aria-hidden="true"></span></button></a><br /><br>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endfor %}
{% endblock %}
</div>

30
templates/rmalias.html Normal file
View File

@@ -0,0 +1,30 @@
{% extends 'up_squelette.html' %}
az
{% block main %}
<br>
<div class="row">
<div class="col-md-12">
<table class="table">
<thead>
<tr>
<th>Alias <span class="badge">{{ i }}</span></th>
<th></th>
</tr>
</thead>
<tbody>
{% if aliases %}
{% for alias in aliases %}
<tr>
<td>{{ alias }}</td>
<td><a href="{{ url_for('rmalias', alias=alias) }}"><button type="button" class="btn btn-sm btn-danger">Supprimer</button></a></td>
</tr>
{% endfor %}
{% endif %}
</tbody>
</table>
</div>
{% endblock %}

View File

@@ -1,49 +1,9 @@
{% extends 'up_squelette.html' %} {% extends 'up_squelette.html' %}
{% block navbar %} {% include '_nav_userlogin.html' %}
<!-- Fixed navbar -->
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!--<a class="navbar-brand" href="/blog/">Blog</a>-->
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/blog"><span class="glyphicon glyphicon-globe" aria-hidden="true"></span> Blog</a></li>
<li><a href="/filesupload/"><span class="glyphicon glyphicon-cloud-upload" aria-hidden="true"></span> Upload</a></li>
<li class="active"><a href="/view/"><span class="glyphicon glyphicon-cloud-download" aria-hidden="true"></span> Fichiers</a></li>
<li><a href="/gallery/"><span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span> Gallerie</a></li>
<li><a href="/logs/"><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span> Logs</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-home" aria-hidden="true"></span> <span id="majuscule">{{ session['username'] }} <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="/profil/{{ session['username'] }}"><span class="glyphicon glyphicon-user" aria-hidden="true"></span> Profil</a></li>
<li><a href="/parametres/"><span class="glyphicon glyphicon-cog" aria-hidden="true"></span> Paramètres</a></li>
<li class="divider"></li>
<!--<li class="dropdown-header">Nav header</li>-->
<li><a href="/logout/"><span class="glyphicon glyphicon-off" aria-hidden="true"></span> Déconnexion</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="/logout/"><span class="glyphicon glyphicon-off" aria-hidden="true"></span> Exit</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
{% endblock %}
{% block main %} {% block main %}
<!--<div class="page-header">
<h1>Liste des fichiers uploadés</h1>
</div>-->
<br> <br>
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
@@ -63,7 +23,7 @@
<td>{{ fichier[0] }}</td> <td>{{ fichier[0] }}</td>
<td><a href="/myfiles/{{ fichier[1] }}">{{ fichier[1] }}</a></td> <td><a href="/myfiles/{{ fichier[1] }}">{{ fichier[1] }}</a></td>
<td>{{ fichier[2] }}</td> <td>{{ fichier[2] }}</td>
<td><a href="{{ url_for('remove', nom=fichier[1]) }}"><button type="button" class="btn btn-sm btn-danger">Supprimer</button></a></td> <td><a href="{{ url_for('filesupload.remove', nom=fichier[1]) }}"><button type="button" class="btn btn-sm btn-danger">Supprimer</button></a></td>
</tr> </tr>
{% endfor %} {% endfor %}
{% endif %} {% endif %}

View File

@@ -1,71 +1,17 @@
<!DOCTYPE html> <!DOCTYPE html>
<html class="no-js" lang="fr"> <html class="no-js" lang="fr">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}">
<title>OpenBlogStock</title>
<!-- Bootstrap core CSS -->
<link href="{{ url_for('static', filename='bootstrap.min.css') }}" rel="stylesheet">
<!-- Bootstrap theme -->
<link href="{{ url_for('static', filename='bootstrap-theme.min.css') }}" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="{{ url_for('static', filename='theme.css') }}" rel="stylesheet">
<!-- Mon CSS avec animations -->
<link href="{{ url_for('static', filename='up.css') }}" rel="stylesheet">
<script src="{{ url_for('static', filename='bootstrap.js') }}"></script>
<!-- Just for debugging purposes. Don't actually copy these 2 lines! -->
<!--[if lt IE 9]><script src="../../assets/js/ie8-responsive-file-warning.js"></script><![endif]-->
<!--<script src="../../assets/js/ie-emulation-modes-warning.js"></script>-->
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<!--<script src="../../assets/js/ie10-viewport-bug-workaround.js"></script>-->
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<script type="text/javascript" src="{{ url_for('static', filename='divhider.js') }}"></script>
</head>
{% include '_head.html' %}
<body role="document"> <body role="document">
{% block navbar %}{% endblock %} {% include '_nav_userlogin.html'%}
<!--<div class="msginfo">
{# on affiche les messages d'erreur puis les messages de succes #}
{% for categorie in ['error', 'succes'] %}
{% with msgs = get_flashed_messages(category_filter=[categorie]) %}
{% if msgs %}
<div class="flashed {{ categorie }}">
{% for m in msgs %}
<p>{{ m|safe }}</p>
{% endfor %}
</div>
{% endif %}
{% endwith %}
{% endfor %}
</div>-->
<div class="container theme-showcase" role="main"> <div class="container theme-showcase" role="main">
{% block main %}{% endblock %} {% block main %}{% endblock %}
</div> </div>
<!-- Bootstrap core JavaScript --> {% include '_js.html' %}
<!--================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="{{ url_for('static', filename='jquery.min.js') }}"></script>
<script src="{{ url_for('static', filename='bootstrap.min.js') }}"></script>
<script src="{{ url_for('static', filename='docs.min.js') }}"></script>
</body> </body>
</html> </html>

View File

@@ -1,60 +1,9 @@
{% extends 'up_squelette.html' %} {% extends 'up_squelette.html' %}
{% block navbar %} {% include '_nav_userlogin.html' %}
<!-- Fixed navbar -->
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!--<a class="navbar-brand" href="/blog/">Blog</a>-->
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/blog/"><span class="glyphicon glyphicon-globe" aria-hidden="true"></span> Blog</a></li>
<li class="active"><a href="/uploadfiles/"><span class="glyphicon glyphicon-cloud-upload" aria-hidden="true"></span> Upload</a></li>
<li><a href="/view/"><span class="glyphicon glyphicon-cloud-download" aria-hidden="true"></span> Fichiers</a></li>
<li><a href="/gallery/"><span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span> Gallerie</a></li>
<li><a href="/logs/"><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span> Logs</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-home" aria-hidden="true"></span> <span id="majuscule">{{ session['username'] }} <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="/profil/{{ session['username'] }}"><span class="glyphicon glyphicon-user" aria-hidden="true"></span> Profil</a></li>
<li><a href="/parametres/"><span class="glyphicon glyphicon-cog" aria-hidden="true"></span> Paramètres</a></li>
<li class="divider"></li>
<!--<li class="dropdown-header">Nav header</li>-->
<li><a href="/logout/"><span class="glyphicon glyphicon-off" aria-hidden="true"></span> Déconnexion</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="/logout/"><span class="glyphicon glyphicon-off" aria-hidden="true"></span> Exit</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
{% endblock %}
{% block main %} {% block main %}
<div class="container theme-showcase" role="main">
<!-- Main jumbotron for a primary marketing message or call to action -->
<!--<div class="jumbotron">
<h1>Hello, {{ session['username'] }} !</h1>
<p>Hébergeur de fichiers basé sur Flask + Bootstrap 3 et hébergé sur une Orange Pi, vise à promouvoir l'informatique libre. Site en construction.</p>
<p><a href="http://flask.pocoo.org/" class="btn btn-primary btn-lg" role="button">En savoir plus &raquo;</a></p>
</div>-->
<!--<div class="page-header">
<h1>Upload</h1>
</div>-->
<div class="row"> <div class="row">
<div class="col-sm-3"></div> <div class="col-sm-3"></div>
@@ -100,6 +49,5 @@
</div> <!-- /container -->
{% endblock %} {% endblock %}

View File

65
tools/databaseinit.py Normal file → Executable file
View File

@@ -1,29 +1,40 @@
#!venv/bin/python from flask import Flask
import sqlite3 import sqlite3
import os.path import os
from tools.utils import gen_token
from flask_bcrypt import Bcrypt
app = Flask( 'pywallter' )
app.config.from_pyfile('config.py')
bcrypt = Bcrypt(app)
DATABASE = app.config['DATABASE']
DOSSIER_PERSO = app.config['DOSSIER_APP']
DATABASE = app.config['DATABASE']
def init_db(): def init_db():
if os.path.isfile('base.db'): conn = sqlite3.connect(DATABASE)
return False
else:
conn = sqlite3.connect('base.db')
cursor = conn.cursor() cursor = conn.cursor()
cursor.execute(""" cursor.execute("""
CREATE TABLE IF NOT EXISTS users( CREATE TABLE IF NOT EXISTS users(
id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, Mail TEXT UNIQUE,
name TEXT, name TEXT primary KEY UNIQUE NOT NULL,
mail TEXT, alias TEXT,
xmpp TEXT,
passwd TEXT, passwd TEXT,
avatar TEXT, avatar TEXT,
nom, TEXT, nom TEXT,
prenom TEXT, prenom TEXT,
age TEXT, age TEXT,
profession TEXT website TEXT,
) Token CHAR(30),
invitations INTEGER DEFAULT (20),
Mail_rescue TEXT )
""") """)
conn.commit() conn.commit()
print ('table users OK') print ('table users Ok')
cursor.execute(""" cursor.execute("""
CREATE TABLE IF NOT EXISTS posts( CREATE TABLE IF NOT EXISTS posts(
@@ -37,9 +48,18 @@ def init_db():
) )
""") """)
conn.commit() conn.commit()
cursor.execute("""select * from users""")
accounts = cursor.fetchall()
# Si aucun account n'est crée on créé l'utilisateur
# pywallter qui permet la première inscription
if not(accounts) :
user = "pywallter"
token = gen_token()
passwd_bcrypt = bcrypt.generate_password_hash(token)
cursor.execute("""INSERT INTO users(name, passwd, token) VALUES(?, ?, ?)""", (user, passwd_bcrypt, token))
conn.commit()
conn.close() conn.close()
print ('table posts OK') print ('table posts OK')
return True
def init_dir(): def init_dir():
if os.path.isdir('users'): if os.path.isdir('users'):
@@ -47,3 +67,18 @@ def init_dir():
else: else:
os.makedirs('./users/') os.makedirs('./users/')
def db_migrate():
conn = sqlite3.connect(DATABASE)
cursor = conn.cursor()
cursor.execute("""SELECT name FROM PRAGMA_TABLE_INFO('users');""")
db_columns = cursor.fetchall()
present = False
for col in db_columns:
if "invitations" == col[0]:
present = True
if not(present):
cursor.execute("""ALTER TABLE users ADD COLUMN invitations INTEGER DEFAULT (20);""")
conn.commit()
print ("Ajout du champ invitations")

97
tools/utils.py Normal file
View File

@@ -0,0 +1,97 @@
from flask import Flask
import sqlite3
import os
import string
import random
app = Flask( 'pywallter' )
app.config.from_pyfile('config.py')
DATABASE = app.config['DATABASE']
DOSSIER_PERSO = app.config['DOSSIER_APP']
DATABASE = app.config['DATABASE']
def append_to_log(log_line, user):
log_file=os.path.join(DOSSIER_PERSO, user, "log.txt")
logs=open(log_file, "r")
tmp=logs.read()
logs.close()
log=open(log_file, "w")
log.write(log_line)
log.write(tmp)
log.close()
def email_disp(email):
disp = True
unique_at = len(email.split('@'))
if len(email) < 80 and unique_at == 2:
conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur"
# Caractères non autorisés dans la RFC #822
invalid_char = { '(', ')', '<', '>', ',', ';', ':', '"', '[', ']', '|', 'ç', '%', '&' }
for character in invalid_char:
if character in email:
disp=False
cursor.execute("""SELECT mail FROM users WHERE mail=?""", (email,))
testmail = cursor.fetchall()
if testmail and disp:
disp = False
if disp:
cursor.execute("""SELECT alias FROM users""")
aliases = cursor.fetchall()
for alist in aliases:
for alias in alist:
if alias:
if email in alias:
disp=False
else:
disp = False
return disp
def valid_passwd(password):
if '"' in password or "&" in password:
return False
else:
return True
def valid_token_register(token):
valid = True
print(token)
if len(token) != 30:
valid = False
if valid:
conn = sqlite3.connect(DATABASE)
cursor = conn.cursor()
cursor.execute("""SELECT name, invitations FROM users where Token=?""", (token,))
tmp = cursor.fetchone()
conn.close()
print (tmp)
if tmp:
valid = True
else:
valid = False
print(valid)
return valid
#Génère un token de 30 caratères aléatoires
def gen_token():
letters = random.choices(string.ascii_letters, k=20)
digits = random.choices(string.digits, k=10)
sample = ''.join(random.sample(digits + letters, 30))
return sample

View File

@@ -1,104 +1,119 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from flask import Blueprint, escape, render_template, session, redirect, url_for, request, flash, abort from flask import Blueprint, escape, render_template, session, redirect, url_for, request, flash, abort, Flask
import time import time
import sqlite3 import sqlite3
from markdown import markdown from markdown import markdown
blog = Blueprint('blog', __name__, template_folder='templates') postit = Blueprint('post-it', __name__, template_folder='templates')
# Un bon gros bug de flask il ne faut pas mettre le meme nom d'une parti ici app = Flask( 'pywallter' )
# a une fonction sinon ca fait une erreur app.config.from_pyfile('config.py')
# k/app.py", line 958, in register_blueprint
# if blueprint.name in self.blueprints:
#https://github.com/pallets/flask/issues/1327
@blog.route('/blog/', methods=['GET', 'POST'])
#### Variables ####################################################################################
DOSSIER_PERSO= app.config['DOSSIER_APP']
extensionimg = app.config['EXT_IMG']
DATABASE = app.config['DATABASE']
BASE_URL = app.config['BASE_URL']
##################################################################################################
@postit.route('/post-it/', methods=['GET', 'POST'])
def racine_blog(): def racine_blog():
if 'username' in session: if 'username' in session:
UTILISATEUR='%s'% escape(session['username']) UTILISATEUR='%s'% escape(session['username'])
if request.method == 'POST': if request.method == 'POST':
title= request.form['title'] title= request.form['title']
content = markdown(request.form['content']) content = request.form['content']
#category = request.form['category'] #category = request.form['category']
status = request.form['status'] status = request.form['status']
TIME=time.strftime("%A %d %B %Y %H:%M:%S") TIME=time.strftime("%A %d %B %Y %H:%M:%S")
conn = sqlite3.connect('base.db') # Connexion la base de donne conn = sqlite3.connect(DATABASE) # Connexion la base de donne
cursor = conn.cursor() # Création de l'objet "curseur" cursor = conn.cursor() # Création de l'objet "curseur"
cursor.execute("""INSERT INTO posts(title, content, time, author, status) VALUES(?, ?, ?, ?, ?)""", (title, content, TIME, UTILISATEUR, status)) # Insérer des valeurs cursor.execute("""INSERT INTO posts(title, content, time, author, status) VALUES(?, ?, ?, ?, ?)""",
(title, content, TIME, UTILISATEUR, status)) # Insérer des valeurs
conn.commit() conn.commit()
cursor.execute("""SELECT title, content, time, author, status, avatar, nom, prenom, age, profession FROM posts INNER JOIN users ON author = name AND status='public'""") cursor.execute("""SELECT title, content, time, author, status, avatar, nom, prenom, age FROM posts INNER JOIN users ON author = name""")
posts = [dict(title=row[0], content=row[1], time=row[2], author=row[3], status=row[4], avatar=row[5], nom=row[6], prenom=row[7], age=row[8], profession=row[9]) for row in reversed(cursor.fetchall())] posts = [dict(title=row[0], content=row[1], time=row[2], author=row[3],
status=row[4], avatar=row[5], nom=row[6], prenom=row[7], age=row[8])
for row in reversed(cursor.fetchall())]
conn.close() conn.close()
return render_template('blog.html', posts=posts) return render_template('blog.html', posts=posts)
else: else:
conn = sqlite3.connect('base.db') # Connexion à la base de donnée conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur" cursor = conn.cursor() # Création de l'objet "curseur"
cursor.execute("""SELECT title, content, time, author, status, avatar, nom, prenom, age, profession FROM posts INNER JOIN users ON author = name AND status='public'""") cursor.execute("""SELECT title, content, time, author, status, avatar, nom, prenom, age FROM posts INNER JOIN users ON author = name""")
posts = [dict(title=row[0], content=row[1], time=row[2], author=row[3], status=row[4], avatar=row[5], nom=row[6], prenom=row[7], age=row[8], profession=row[9]) for row in reversed(cursor.fetchall())] posts = [dict(title=row[0], content=row[1], time=row[2], author=row[3],
status=row[4], avatar=row[5], nom=row[6], prenom=row[7], age=row[8])
for row in reversed(cursor.fetchall())]
conn.close() conn.close()
return render_template('blog.html', posts=posts) for post in posts:
post['content'] = markdown(post['content'])
return render_template('blog.html', section='Post-it', posts=posts)
else: else:
return redirect(url_for('loginlogout.login', _external=True)) return redirect(BASE_URL, code=401)
@blog.route('/blog/<username>')
def members(username):
conn = sqlite3.connect('base.db') # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur"
cursor.execute("""SELECT title, content, time, author, status FROM posts WHERE author=? AND status='public'""", (username,))
posts = [dict(title=row[0], content=row[1], time=row[2], author=row[3], status=row[4]) for row in reversed(cursor.fetchall())]
cursor.execute("""SELECT avatar, nom, prenom, age, profession FROM users WHERE name=?""", (username,))
usersinfos = (cursor.fetchone())
conn.close()
return render_template('publicblog.html', username=username, posts=posts, usersinfos=usersinfos)
@blog.route('/privateblog/')
def privateblog():
UTILISATEUR='%s'% escape(session['username'])
if 'username' in session :
conn = sqlite3.connect('base.db') # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur"
cursor.execute("""SELECT title, content, time, author, status FROM posts WHERE author=? AND status='prive'""", (UTILISATEUR,))
posts = [dict(title=row[0], content=row[1], time=row[2], author=row[3], status=row[4]) for row in reversed(cursor.fetchall())]
cursor.execute("""SELECT avatar, nom, prenom, age, profession FROM users WHERE name=?""", (UTILISATEUR,))
usersinfos = (cursor.fetchone())
conn.close()
return render_template('privateblog.html', UTILISATEUR=UTILISATEUR, posts=posts, usersinfos=usersinfos)
else:
return redirect(url_for('loginlogout.login', _external=True)) # sinon on redirige vers login
@blog.route('/delete/<post>') @postit.route('/delete/<post>')
def delete(post): def delete(post):
if 'username' in session : if 'username' in session :
conn = sqlite3.connect('base.db') # Connexion à la base de donnée conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur" cursor = conn.cursor() # Création de l'objet "curseur"
cursor.execute("""DELETE FROM posts WHERE title=?""", (post,)) cursor.execute("""DELETE FROM posts WHERE title=?""", (post,))
conn.commit() conn.commit()
conn.close() conn.close()
return redirect(url_for('blog.racine_blog')) return redirect(url_for('post-it.racine_blog'))
else: else:
return redirect(url_for('loginlogout.login', _external=True)) # sinon on redirige vers login return redirect(BASE_URL, code=401) # sinon on redirige vers login
@blog.route('/edit/<post>', methods=['GET', 'POST']) @postit.route('/edit/<post>', methods=['GET', 'POST'])
def edit(post): def edit(post):
if 'username' in session : if 'username' in session :
if request.method == 'POST' : if request.method == 'POST' :
newtitle = request.form['title'] newtitle = request.form['title']
newcontent = markdown(request.form['content']) newcontent = request.form['content']
newstatus = request.form['status'] newstatus = request.form['status']
conn = sqlite3.connect('base.db') conn = sqlite3.connect(DATABASE)
cursor = conn.cursor() cursor = conn.cursor()
cursor.execute("""UPDATE posts SET title=?, content=?, status=? WHERE title=?""", cursor.execute("""UPDATE posts SET title=?, content=?, status=? WHERE title=?""",
(newtitle, newcontent, newstatus, post,)) (newtitle, newcontent, newstatus, post,))
conn.commit() conn.commit()
conn.close() conn.close()
return redirect(url_for('blog.racine_blog')) return redirect(url_for('post-it.racine_blog'))
else: else:
conn = sqlite3.connect('base.db') # Connexion à la base de donnée conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur" cursor = conn.cursor() # Création de l'objet "curseur"
cursor.execute("""SELECT title, content FROM posts WHERE title=?""", (post,)) cursor.execute("""SELECT title, content FROM posts WHERE title=?""", (post,))
oldpost = (cursor.fetchone()) oldpost = cursor.fetchone()
conn.close() conn.close()
return render_template('postedit.html', oldpost=oldpost) return render_template('postedit.html',
section='Post-it',
oldpost=oldpost)
else: else:
return redirect(url_for('loginlogout.login', _external=True)) # sinon on redirige vers login)
return redirect(BASE_URL, code=401)
@postit.route('/postit/board', methods=['GET'])
def viewsheet():
if 'username' in session:
conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur"
cursor.execute("""SELECT title, content, time, author, status, avatar, nom, prenom, age FROM posts INNER JOIN users where status='public' """)
posts = [dict(title=row[0], content=row[1], time=row[2], author=row[3],
status=row[4], avatar=row[5], nom=row[6], prenom=row[7], age=row[8])
for row in reversed(cursor.fetchall())]
conn.close()
for post in posts:
post['content'] = markdown(post['content'])
return render_template('board.html', section='Post-it', posts=posts)
else:
return redirect(BASE_URL, code=401)

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from flask import Blueprint, Flask, request, flash, render_template, url_for, session, redirect, abort, make_response, send_file, escape, flash, abort from flask import Blueprint, Flask, request, flash, render_template, url_for, session, redirect, abort, make_response, escape, flash, abort, send_file, escape, send_from_directory
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
from PIL import Image from PIL import Image
import time import time
@@ -8,12 +8,22 @@ import sqlite3
import os import os
filesupload = Blueprint('filesupload', __name__, template_folder='templates') filesupload = Blueprint('filesupload', __name__, template_folder='templates')
DOSSIER_PERSO='users/' app = Flask( 'pywallter' )
extensionimg = {'.jpg', '.JPG', '.png', '.PNG', '.gif', '.GIF', '.bmp', '.BMP', '.jpeg', '.JPEG' } app.config.from_pyfile('config.py')
#### Variables ####################################################################################
DOSSIER_PERSO= app.config['DOSSIER_APP']
extensionimg = app.config['EXT_IMG']
DATABASE = app.config['DATABASE']
BASE_URL= app.config['BASE_URL']
##################################################################################################
@filesupload.route( '/filesupload/', methods=['GET', 'POST']) @filesupload.route( '/filesupload/', methods=['GET', 'POST'])
def uploadfiles(): def uploadfiles():
@@ -42,7 +52,8 @@ def uploadfiles():
TIME=time.strftime("%A %d %B %Y %H:%M:%S") TIME=time.strftime("%A %d %B %Y %H:%M:%S")
IP=request.environ['REMOTE_ADDR'] IP=request.environ['REMOTE_ADDR']
CLIENT_PLATFORM=request.headers.get('User-Agent') CLIENT_PLATFORM=request.headers.get('User-Agent')
LOG=open("log.txt", "a") log_file=os.path.join(DOSSIER_PERSO, UTILISATEUR, "log.txt")
LOG=open(log_file, "a")
LOG.write (TIME + ' - ' + IP + ' - ' + UTILISATEUR + ' - ' + CLIENT_PLATFORM + '\n' + '---> ' + nom + '\n') LOG.write (TIME + ' - ' + IP + ' - ' + UTILISATEUR + ' - ' + CLIENT_PLATFORM + '\n' + '---> ' + nom + '\n')
LOG.close() LOG.close()
flash(u'Image envoyée et traitée avec succés', 'succes') flash(u'Image envoyée et traitée avec succés', 'succes')
@@ -68,11 +79,11 @@ def uploadfiles():
else: else:
flash(u'Error : Vous avez oublié le fichier !', 'error') flash(u'Error : Vous avez oublié le fichier !', 'error')
return redirect(url_for('filesupload.uploadfiles')) return redirect(url_for('filesupload.uploadfiles'))
resp = make_response(render_template('up_up.html')) resp = make_response(render_template('up_up.html', section="Upload"))
resp.set_cookie('username', session['username']) resp.set_cookie('username', session['username'])
return resp return resp
else : else :
return redirect(url_for('loginlogout.login', _external=True)) return redirect(BASE_URL, code=401)
@filesupload.route('/view/') @filesupload.route('/view/')
@@ -87,9 +98,42 @@ def list():
i += 1 i += 1
size = os.path.getsize(DOSSIER_PERSO + UTILISATEUR + '/files/' + fich) # size = taille des fichiers size = os.path.getsize(DOSSIER_PERSO + UTILISATEUR + '/files/' + fich) # size = taille des fichiers
listeFichiers.append([i, fich, size]) # On implémente la listeFichiers avec le num le ficier et sa taille listeFichiers.append([i, fich, size]) # On implémente la listeFichiers avec le num le ficier et sa taille
return render_template('up_list.html',size=size, i=i, listeFichiers=listeFichiers) return render_template('up_list.html',
section="Files",
size=size,
i=i,
listeFichiers=listeFichiers)
else : else :
flash(u'Aucun fichier uploadé ! Redirection vers Upload', 'error') flash(u'Aucun fichier uploadé ! Redirection vers Upload', 'error')
return redirect(url_for('filesupload.uploadfiles', external=True)) return redirect(url_for('filesupload.uploadfiles'))
else : else :
return redirect(url_for('loginlogout.login', _external=True)) return redirect(BASE_URL, code=401)
@filesupload.route('/myfiles/<filename>')
def myfiles(filename):
if 'username' in session :
UTILISATEUR='%s' % escape(session['username'])
return send_from_directory(
os.path.join(DOSSIER_PERSO, UTILISATEUR, 'files'), filename )
else :
return redirect(BASE_URL, code=401)
@filesupload.route('/remove/<nom>')
def remove(nom):
if 'username' in session :
UTILISATEUR='%s' % escape(session['username'])
nom = secure_filename(nom)
if os.path.isfile(DOSSIER_PERSO + UTILISATEUR + '/files/' + nom): # si le fichier existe
os.remove(DOSSIER_PERSO + UTILISATEUR + '/files/' + nom) # on le supprime
return redirect(url_for('filesupload.list', _external=True))
else:
if os.path.isfile(DOSSIER_PERSO + UTILISATEUR + '/images/thumbnails/' + nom): # si le fichier existe
os.remove(DOSSIER_PERSO + UTILISATEUR + '/images/thumbnails/' + nom) # on le supprime
os.remove(DOSSIER_PERSO + UTILISATEUR + '/images/' + nom) # on le supprime
return redirect(url_for('gallery'))
else:
flash(u'Fichier {nom} inexistant.'.format(nom=nom), 'error')
return redirect(url_for('filesupload.list', _external=True)) # sinon on redirige vers la liste, avec un message d'erreur
else :
return redirect(BASE_URL, code=401)

55
views/gallery.py Normal file
View File

@@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
from flask import Blueprint, Flask, request, flash, render_template, url_for, session, redirect, abort, make_response, send_file, escape, flash, abort, send_file, send_from_directory
from werkzeug.utils import secure_filename
from PIL import Image
import time
import sqlite3
import os
mygallery = Blueprint('mygallery', __name__, template_folder='templates')
app = Flask( 'pywallter' )
app.config.from_pyfile('config.py')
#### Variables ####################################################################################
DOSSIER_PERSO= app.config['DOSSIER_APP']
extensionimg = app.config['EXT_IMG']
DATABASE = app.config['DATABASE']
##################################################################################################
@mygallery.route( '/gallery/')
def gallery():
if 'username' in session :
UTILISATEUR='%s' % escape(session['username'])
THUMBNAILS=DOSSIER_PERSO + UTILISATEUR + '/images/thumbnails/'
fichiers = [fich for fich in os.listdir(THUMBNAILS)]
return render_template('gallery.html',
section='Gallery',
THUMBNAILS=THUMBNAILS,
fichiers=fichiers)
else :
return redirect(url_for('loginlogout.login'), code=401)
@mygallery.route('/myfiles/images/<filename>')
def myimg(filename):
if 'username' in session :
UTILISATEUR='%s' % escape(session['username'])
return send_from_directory(
os.path.join(DOSSIER_PERSO, UTILISATEUR, 'images'), filename )
else :
return redirect(BASE_URL, code=401)
@mygallery.route('/myfiles/images/thumbnails/<filename>')
def mythumbnails(filename):
if 'username' in session :
UTILISATEUR='%s' % escape(session['username'])
return send_from_directory(
os.path.join(DOSSIER_PERSO, UTILISATEUR, 'images/thumbnails'), filename )
else :
return redirect(BASE_URL, code=401)

View File

@@ -2,62 +2,163 @@ from flask import Blueprint, Flask, request, flash, render_template, url_for, se
from flask_bcrypt import Bcrypt from flask_bcrypt import Bcrypt
import sqlite3 import sqlite3
import glob, os, sys, time import glob, os, sys, time
from tools.utils import email_disp, valid_token_register, valid_passwd
from socket import gethostname
app = Flask( 'pywallter' ) app = Flask( 'pywallter' )
app.config.from_pyfile('config.py')
bcrypt = Bcrypt(app) bcrypt = Bcrypt(app)
DOSSIER_PERSO='users/' #### Variables ##################################################################################
DOSSIER_PERSO= app.config['DOSSIER_APP']
extensionimg = app.config['EXT_IMG']
DATABASE = app.config['DATABASE']
MAIL_SERVER = app.config['MAIL_SERVER']
XMMP_SERVER = app.config['XMPP_SERVER']
SETUID = app.config['SETUID']
BASE_URL = app.config['BASE_URL']
#################################################################################################
inscription = Blueprint('inscription', __name__, template_folder='templates') inscription = Blueprint('inscription', __name__, template_folder='templates')
@inscription.route( '/inscription/', methods=['GET','POST'] ) @inscription.route( '/inscription/<token>', methods=['GET','POST'] )
def signin() : def signin(token) :
hostname = gethostname()
url_inscription = BASE_URL+'inscription/'+token
resp = None
if valid_token_register(token):
if 'username' in session : if 'username' in session :
return redirect(url_for('filesupload')) resp = redirect(url_for('profil.profile', _external=True))
else : else :
# Réponse si la requete est de type GET ou si la requete POST echoue
resp = render_template('inscription.html',
signin_enable=app.config['SIGNIN_ENABLE'],
token=token, hostname=hostname,
url_inscription=url_inscription,
MAIL_SERVER=MAIL_SERVER)
if request.method == 'POST': if request.method == 'POST':
conn = sqlite3.connect('base.db') # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur" #On test si aucun champs du formulaire n'est vide.
if MAIL_SERVER:
if len(request.form['user']) == 0 or \
len(request.form['passwd']) == 0 or \
len(request.form['passwdconfirm']) == 0 or \
len(request.form['mail']) == 0 :
flash(u'Il faut remplir le formulaire en entier, les champs ne peuvent pas etre vide ', 'error')
return render_template('inscription.html',
signin_enable=app.config['SIGNIN_ENABLE'],
token=token, hostname=hostname,
url_inscription=url_inscription,
MAIL_SERVER=MAIL_SERVER)
else:
if len(request.form['user']) == 0 or \
len(request.form['passwd']) == 0 or \
len(request.form['passwdconfirm']) == 0:
flash(u'Il faut remplir le formulaire en entier, les champs ne peuvent pas etre vide ', 'error')
return render_template('inscription.html',
signin_enable=app.config['SIGNIN_ENABLE'],
token=token, hostname=hostname,
url_inscription=url_inscription,
MAIL_SERVER=MAIL_SERVER)
user = request.form['user'] user = request.form['user']
mail = request.form['mail'] passwd = request.form['passwd']
passwd = bcrypt.generate_password_hash(request.form['passwd']) mail = ""
passwdconfirm = request.form['passwdconfirm'] passwdconfirm = request.form['passwdconfirm']
bcrypt_passwd = bcrypt.generate_password_hash(request.form['passwd'])
mail_passwd_change = 0
password_valid = valid_passwd(passwd)
not_error = True
conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur"
cursor.execute("""SELECT name FROM users WHERE name=?""", (user,)) cursor.execute("""SELECT name FROM users WHERE name=?""", (user,))
testuser = cursor.fetchone() testuser = cursor.fetchone()
cursor.execute("""SELECT mail FROM users WHERE mail=?""", (mail,))
testmail=cursor.fetchone()
conn.close() conn.close()
if testuser or testmail:
flash(u'Non d\'utilisateur ou email déjà utilisé, merci d\'en choisir un autre', 'error') if testuser:
return render_template('inscription.html') flash(u'Non d\'utilisateur déjà utilisé, merci d\'en choisir un autre', 'error')
not_error = False
if not(password_valid):
flash (u'Les caractère & et " ne sont pas autorisé dans les mots de passe', 'error')
not_error = False
if MAIL_SERVER:
mail = request.form['mail'].lower()+'@'+hostname
if not(email_disp(mail)) :
flash(u'Adresse email déjà utilisé ou invalide, merci d\'en choisir une autre', 'error')
not_error = False
if not_error:
confirmation = bcrypt.check_password_hash(bcrypt_passwd, passwdconfirm)
if confirmation is False:
flash(u'Les mots de passe ne sont pas identiques !', 'error')
else: else:
confirmation = bcrypt.check_password_hash(passwd, passwdconfirm) conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée
if confirmation is True:
conn = sqlite3.connect('base.db') # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur" cursor = conn.cursor() # Création de l'objet "curseur"
cursor.execute("""INSERT INTO users(name, mail, passwd) VALUES(?, ?, ?)""", (user, mail, passwd)) # Insérer des valeurs cursor.execute("""INSERT INTO users(name, mail, passwd) VALUES(?, ?, ?)""", (user, mail, bcrypt_passwd)) # Insérer des valeurs
conn.commit() # Sauvegarder valeurs dans la bdd conn.commit() # Sauvegarder valeurs dans la bdd
cursor.execute("""SELECT name, mail, passwd FROM users""")
users = cursor.fetchall() # On change le mot de passe du compte mail
for i in users: if MAIL_SERVER:
i = print('{0} - {1} - {2}'.format(i[0], i[1], i[2])) cmd = SETUID + ' set_mail_passwd ' + '"'+mail+'" ' + '"'+passwd+'"'
conn.close() mail_passwd_change = os.system(cmd)
if mail_passwd_change != 0:
flash(u'Il y a eu une problème lors du changement de mot passe pour le compte Mail', 'error')
# On change le mot de passe du compte XMPP
if XMMP_SERVER:
tmp = mail.split('@')
cmd = SETUID+ ' prosodyctl register ' "'"+tmp[0]+"' " + "'"+tmp[1]+"' " + "'"+passwd+"'"
res = os.system(cmd)
if res != 0:
flash(u'Il y a eu un problème pour la création du compte XMPP !', 'error')
# on créé les dossier de l'utilisateur
userracine = DOSSIER_PERSO + user userracine = DOSSIER_PERSO + user
userfiles = userracine + '/files' userfiles = userracine + '/files'
userimages = userracine + '/images' userimages = userracine + '/images'
userthumbnails = userracine + '/images/thumbnails' userthumbnails = userracine + '/images/thumbnails'
userprofile = userracine + '/profile' userprofile = userracine + '/profile'
userlog = userracine + '/log.txt'
if not os.path.exists(userracine): if not os.path.exists(userracine):
os.makedirs(userracine) os.makedirs(userracine)
os.makedirs(userfiles) os.makedirs(userfiles)
os.makedirs(userimages) os.makedirs(userimages)
os.makedirs(userthumbnails) os.makedirs(userthumbnails)
os.makedirs(userprofile) os.makedirs(userprofile)
fp = open(userlog, 'x')
fp.close()
# Une fois que tout c'est bien passé pour l'inscription on détruit le jeton.
cursor.execute("""SELECT name, invitations FROM users where Token=?""", (token,))
tmp = cursor.fetchone()
username = tmp[0]
invitations_count=tmp[1] - 1
if username == "pywallter":
cursor.execute("""DELETE from users where name = ?""", (username,))
else:
cursor.execute("""UPDATE users set invitations=?, Token='' where name=?""", (invitations_count, username,))
conn.commit()
flash(u'Inscription réalisée avec succés !', 'succes') flash(u'Inscription réalisée avec succés !', 'succes')
return render_template('login.html') resp = redirect(url_for('loginlogout.login'))
else: else:
flash(u'Les mots de passe ne sont pas identiques !', 'error') resp = redirect(BASE_URL, code=401)
return render_template('inscription.html')
else : return resp
return render_template('inscription.html')

View File

@@ -1,33 +1,82 @@
from flask import Blueprint, Flask, request, flash, render_template, url_for, session, redirect, abort, make_response, send_file, escape from flask import Blueprint, Flask, request, flash, render_template, url_for, session, redirect, abort, make_response, send_file, escape
import sqlite3 import sqlite3
from flask_bcrypt import Bcrypt from flask_bcrypt import Bcrypt
from socket import gethostname
app = Flask( 'pywallter' ) app = Flask( 'pywallter' )
app.config.from_pyfile('config.py')
bcrypt = Bcrypt(app) bcrypt = Bcrypt(app)
#### Variables ####################################################################################
bcrypt = Bcrypt(app)
DOSSIER_PERSO= app.config['DOSSIER_APP']
extensionimg = app.config['EXT_IMG']
DATABASE = app.config['DATABASE']
BASE_URL = app.config['BASE_URL']
MAIL_SERVER = app.config['MAIL_SERVER']
##################################################################################################
loginlogout = Blueprint('loginlogout', __name__, template_folder='templates') loginlogout = Blueprint('loginlogout', __name__, template_folder='templates')
@loginlogout.route( '/login/', methods=['GET','POST'] ) @loginlogout.route( '/login/', methods=['GET','POST'] )
def login() : def login() :
if 'username' in session : if 'username' in session :
return redirect(url_for('filesupload.uploadfiles', _external=True)) resp = redirect(url_for('filesupload.uploadfiles', _external=True))
else : else :
resp = redirect(url_for('loginlogout.login', _external=True))
if request.method == 'POST' : if request.method == 'POST' :
conn = sqlite3.connect('base.db') # Connexion à la base de donnée conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur" cursor = conn.cursor() # Création de l'objet "curseur"
cursor.execute("""SELECT name, passwd FROM users""") cursor.execute("""SELECT name, passwd FROM users""")
users = cursor.fetchall() users = cursor.fetchall()
conn.close() conn.close()
password = request.form['passwd'] password = request.form['passwd']
for i in users: for user in users:
if i[0] == request.form['user'] and bcrypt.check_password_hash(i[1], password) is True: print (user[0])
passwd = str(user[1] )
print ( passwd[2:(len(passwd)-1 )] )
if user[0] == request.form['user'] and bcrypt.check_password_hash(user[1], password) is True:
session['username'] = request.form['user'] session['username'] = request.form['user']
return redirect(url_for('filesupload.uploadfiles', _external=True)) resp = redirect(url_for('profil.profile', _external=True))
return redirect(url_for('loginlogout.login', _external=True))
else: else:
return render_template('login.html') resp = render_template('accueil.html', signin_enable=app.config['SIGNIN_ENABLE'])
return resp
@loginlogout.route( '/logout/' ) @loginlogout.route( '/logout/' )
def logout(): def logout():
session.pop('username', None) # Supprimer username de la session s'il s'y trouve session.pop('username', None) # Supprimer username de la session s'il s'y trouve
return redirect(url_for('index')) return redirect(url_for('loginlogout.index'))
@loginlogout.route( '/' )
def index():
conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur"
cursor.execute("""SELECT token passwd FROM users where name=? """, ("pywallter", ))
tmp = cursor.fetchone()
conn.close
if tmp:
token = tmp[0]
else:
token = None
if 'username' in session :
return redirect(url_for('profil.profile'))
else :
if token:
hostname = gethostname()
url_inscription = BASE_URL+'inscription/'+token
return render_template('inscription.html', signin_enable=app.config['SIGNIN_ENABLE'],
token=token, hostname=hostname,
url_inscription=url_inscription,
MAIL_SERVER=MAIL_SERVER)
else:
return redirect(url_for('loginlogout.login', _external=True))

View File

@@ -3,14 +3,29 @@ import glob, os, sys
logs = Blueprint('logs', __name__, template_folder='templates') logs = Blueprint('logs', __name__, template_folder='templates')
app = Flask( 'pywallter' )
app.config.from_pyfile('config.py')
#### Variables ####################################################################################
DOSSIER_PERSO= app.config['DOSSIER_APP']
extensionimg = app.config['EXT_IMG']
DATABASE = app.config['DATABASE']
##################################################################################################
@logs.route('/logs/') @logs.route('/logs/')
def logfile(): def logfile():
if 'username' in session: if 'username' in session:
with open('log.txt', 'r') as log: UTILISATEUR='%s'% escape(session['username'])
log_file=os.path.join(DOSSIER_PERSO, UTILISATEUR, "log.txt")
with open(log_file, 'r') as log:
print("on passe ici")
logs=log.readlines() logs=log.readlines()
log.close() log.close()
for line in logs: return render_template('logs.html', section="Logs", logs=logs)
return render_template('logs.html', logs=logs, line=line)
else : else :
return redirect(url_for('loginlogout.login', _external=True)) return redirect(url_for('loginlogout.login', _external=True), code=401)

View File

@@ -1,80 +1,314 @@
from flask import Blueprint, Flask, request, flash, render_template, url_for, session, redirect, abort, make_response, send_file, escape, flash, abort from flask import Blueprint, Flask, request, flash, render_template, url_for, session, redirect, abort, make_response, send_file, escape, flash, abort, send_from_directory
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
from PIL import Image from PIL import Image
import time import time
import sqlite3 import sqlite3
import os import os
from socket import gethostname
from flask_bcrypt import Bcrypt
from tools.utils import email_disp, append_to_log, gen_token, valid_passwd
profil = Blueprint('profil', __name__, template_folder='templates') profil = Blueprint('profil', __name__, template_folder='templates')
DOSSIER_PERSO='users/' app = Flask( 'pywallter' )
extensionimg = {'.jpg', '.JPG', '.png', '.PNG', '.gif', '.GIF', '.bmp', '.BMP', '.jpeg', '.JPEG' } app.config.from_pyfile('config.py')
@profil.route('/profil/<username>/', methods=['GET','POST'] )
def profile(username=None) : #### Variables ####################################################################################
bcrypt = Bcrypt(app)
DOSSIER_PERSO = app.config['DOSSIER_APP']
extensionimg = app.config['EXT_IMG']
DATABASE = app.config['DATABASE']
MAIL_SERVER = app.config['MAIL_SERVER']
XMPP_SERVER = app.config['XMPP_SERVER']
SETUID = app.config['SETUID']
BASE_URL = app.config['BASE_URL']
##################################################################################################
@profil.route( '/profil/<user>/<img>', methods=['GET'] )
def profil_img(user, img) :
if 'username' in session :
return send_from_directory( os.path.join(DOSSIER_PERSO, user, 'profile'), img )
else:
return redirect(BASE_URL, code=401)
@profil.route('/profil/', methods=['GET','POST'] )
def profile() :
if 'username' in session : if 'username' in session :
UTILISATEUR='%s' % escape(session['username']) UTILISATEUR='%s' % escape(session['username'])
conn = sqlite3.connect('base.db') # Connexion à la base de donnée conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur" cursor = conn.cursor() # Création de l'objet "curseur"
cursor.execute("""SELECT avatar FROM users WHERE name=?""", (username,)) cursor.execute("""SELECT avatar, nom, prenom, age, mail_rescue FROM users WHERE name=?""", (UTILISATEUR,))
imageprofil = cursor.fetchone() tmp = (cursor.fetchone())
profil_user = dict()
profil_user['avatar'] = tmp[0]
profil_user['nom'] = tmp[1]
profil_user['prenom'] = tmp[2]
profil_user['age'] = tmp[3]
profil_user['mail_rescue'] = tmp[4]
conn.close() conn.close()
if request.method == 'POST' : if request.method == 'POST' :
f = request.files['fic'] f = request.files['fic']
nom = request.form['nom'] if request.form['nom']:
prenom = request.form['prenom'] profil_user['nom'] = request.form['nom']
age = request.form['age'] if request.form['prenom']:
profession = request.form['profession'] profil_user['prenom'] = request.form['prenom']
if request.form['age']:
profil_user['age'] = request.form['age']
if '@' in request.form['mail_rescue']:
if len(request.form['mail_rescue']) > 4:
profil_user['mail_rescue'] = request.form['mail_rescue']
else:
flash(u'Adresse de courriel invalide', 'error')
else:
flash(u'Adresse de courriel invalide', 'error')
if f: # On vérifie qu'un fichier a bien été envoyé if f: # On vérifie qu'un fichier a bien été envoyé
nom = secure_filename(f.filename) nom = secure_filename(f.filename)
f.save(DOSSIER_PERSO + UTILISATEUR + '/profile/' + nom) f.save(DOSSIER_PERSO + UTILISATEUR + '/profile/' + nom)
image = DOSSIER_PERSO + UTILISATEUR + '/profile/' + nom image = DOSSIER_PERSO + UTILISATEUR + '/profile/' + nom
with Image.open(image) as img: with Image.open(image) as img:
img.tumbnails(resize='80x80') img.thumbnail((300,200))
img.save(filename = DOSSIER_PERSO + UTILISATEUR + '/profile/' + nom) img.save( DOSSIER_PERSO + UTILISATEUR + '/profile/' + nom)
imagelocation = DOSSIER_PERSO + UTILISATEUR + '/profile/' + nom filename = nom
conn = sqlite3.connect('base.db') # Connexion à la base de donnée conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur" cursor = conn.cursor() # Création de l'objet "curseur"
cursor.execute("UPDATE users SET avatar=? WHERE name=?", (imagelocation, username)) cursor.execute("UPDATE users SET avatar=? WHERE name=?",
(filename, UTILISATEUR))
conn.commit() conn.commit()
cursor.execute("""SELECT avatar FROM users WHERE name=?""", (username,)) cursor = conn.cursor() # Création de l'objet "curseur"
imageprofil = cursor.fetchone()
conn.close() conn.close()
flash(u'Image de profil mise à jour', 'succes') flash(u'Image de profil mise à jour', 'succes')
return render_template('profil.html', imageprofil=imageprofil, username=username)
else:
# return render_template('profil.html', imageprofil=imageprofil, username=username)
####### Informations personnelles #######
if nom:
if prenom:
if age:
if profession:
conn = sqlite3.connect('base.db') # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur"
cursor.execute("UPDATE users SET nom=?, prenom=?, age=?, profession=? WHERE name=?""", (nom, prenom, age, profession, username,))
conn.commit()
conn.close()
flash(u'Informations transmisent à la base', 'succes')
return render_template('profil.html', imageprofil=imageprofil, username=username)
else:
flash(u'Veuillez renseigner une profession', 'error')
return render_template('profil.html', imageprofil=imageprofil, username=username)
else:
flash(u'Veuillez renseigner votre âge', 'error')
return render_template('profil.html', imageprofil=imageprofil, username=username)
else:
flash(u'Veuillez renseigner votre prénom', 'error')
return render_template('profil.html', imageprofil=imageprofil, username=username)
else:
flash(u'Veuillez renseigner votre nom', 'error')
return render_template('profil.html', imageprofil=imageprofil, username=username)
else:
conn = sqlite3.connect('base.db') # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur"
cursor.execute("""SELECT avatar FROM users WHERE name=?""", (username,))
imageprofil = cursor.fetchone()
conn.close()
return render_template('profil.html', imageprofil=imageprofil, username=username)
else: else:
return redirect(url_for('loginlogout.login', _external=True)) conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée
cursor = conn.cursor() # Création de l\'objet "curseur"
cursor.execute("UPDATE users SET nom=?, prenom=?, age=?, mail_rescue=? WHERE name=?",
(profil_user['nom'], profil_user['prenom'], profil_user['age'], profil_user['mail_rescue'],
UTILISATEUR))
conn.commit()
flash(u'Le profil a été mis à jour', 'succes')
return render_template('profil.html',
section="Profil",
profil=profil_user,
username=UTILISATEUR)
else :
return redirect(BASE_URL, code=401)
@profil.route('/profil/change-password/', methods=['GET','POST'] )
def change_passwd() :
if 'username' in session:
UTILISATEUR='%s' % escape(session['username'])
conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur"
cursor.execute("""SELECT Mail, alias, xmpp FROM users WHERE name=?""", (UTILISATEUR,))
tmp = cursor.fetchone()
mailbox = dict()
mailbox['Mail'] = tmp[0]
mailbox['alias'] = tmp[1]
mailbox['xmpp'] = tmp[2]
if request.method == 'POST' :
password = request.form['password']
password_confirm = request.form['passwd_confirm']
if password == password_confirm and valid_passwd(password):
mail_passwd_change = 0
xmmp_passwd_change = 0
passwd = request.form['password']
if MAIL_SERVER:
cmd = SETUID+ ' set_mail_passwd ' + '"'+mailbox['Mail']+'" '+ '"'+passwd+'"'
mail_passwd_change = os.system(cmd)
if XMPP_SERVER:
tmp = mailbox['Mail'].split('@')
cmd = SETUID+ " prosodyctl register '"+tmp[0]+"' " + "'"+tmp[1]+"' " + "'"+passwd+"'"
res = os.system(cmd)
if res != 0:
flash(u'Il y a eu un problème pour le changement du mot de passe du compte XMPP !', 'error')
if mail_passwd_change == 0:
passwd_bcrypt = bcrypt.generate_password_hash(passwd)
cursor.execute("UPDATE users SET passwd=? WHERE name=?",
(passwd_bcrypt, UTILISATEUR))
conn.commit()
TIME=time.strftime("%A %d %B %Y %H:%M:%S")
IP=request.environ['REMOTE_ADDR']
CLIENT_PLATFORM=request.headers.get('User-Agent')
log=TIME + ' - ' + IP + ' - ' + UTILISATEUR + ' - ' + CLIENT_PLATFORM + '\n' + '---> ' + "Changement du mot de passe" + '\n'
append_to_log(log, UTILISATEUR)
flash(u'Votre mot de passe a été changé', 'succes')
else:
if not( valid_passwd(password) ):
flash(u'Le mot de passe ne peut pas contenir les caractères " et &', 'error')
else:
flash(u'Les mot de passes ne sont pas identique :/ ', 'error')
conn.close()
return render_template('mailbox.html',
section="Profil",
address=mailbox['Mail'],
alias=mailbox['alias'],
username=UTILISATEUR)
else :
return redirect(BASE_URL, code=401)
@profil.route('/mymailbox/alias', methods=['GET', 'POST'] )
def myalias():
hostname=gethostname()
if 'username' in session:
UTILISATEUR='%s' % escape(session['username'])
conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur"
if request.method == 'POST' and MAIL_SERVER:
if request.form['alias']:
alias = request.form['alias'].lower()+'@'+hostname
else:
flash(u'Addresse invalide')
if email_disp(alias):
cursor.execute("""SELECT Mail, alias FROM users where name=?""", (UTILISATEUR,))
tmp = cursor.fetchone()
mail = tmp[0]
if tmp[1]:
alias_list = tmp[1]
aliases = alias_list + "," +alias
else:
aliases = alias
cmd = SETUID+ " set_mail_alias " + "'"+mail+"'"+" add "+"'"+alias+"'"
res = os.system(cmd)
if res == 0:
cursor.execute("UPDATE users SET alias=? WHERE name=?",
(aliases, UTILISATEUR))
conn.commit()
TIME=time.strftime("%A %d %B %Y %H:%M:%S")
IP=request.environ['REMOTE_ADDR']
CLIENT_PLATFORM=request.headers.get('User-Agent')
log=TIME + ' - ' + IP + ' - ' + UTILISATEUR + ' - ' + CLIENT_PLATFORM + '\n' + '---> ' + "Ajout de l'alias "+ alias + '\n'
append_to_log(log, UTILISATEUR)
flash(u'Votre alias a été ajouté', 'succes')
else:
flash(u'Adresse indisponible', 'error')
else:
flash(u'Adresse indisponible', 'error')
cursor.execute("""SELECT Mail, alias FROM users WHERE name=?""",
(UTILISATEUR,))
tmp = cursor.fetchone()
mailbox = dict()
mailbox['Mail'] = tmp[0]
if tmp[1]:
mailbox['alias'] = tmp[1].split(',')
else:
mailbox['alias'] = list()
conn.close()
return render_template('myalias.html',
section="mailbox",
email=mailbox['Mail'],
aliases=mailbox['alias'],
hostname=hostname,
MAIL_SERVER=MAIL_SERVER,
username=UTILISATEUR )
else:
return redirect(BASE_URL, code=401)
@profil.route('/mymailbox/rmalias/<aliasrm>')
def remove_alias(aliasrm):
if 'username' in session:
if MAIL_SERVER:
UTILISATEUR='%s' % escape(session['username'])
conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur"
cursor.execute("""SELECT Mail, alias FROM users WHERE name=?""", (UTILISATEUR,))
tmp = cursor.fetchone()
mail = tmp[0]
alias_list = tmp[1].split(',')
aliases = ""
for alias in alias_list:
if alias != aliasrm:
if aliases:
aliases = aliases + "," + alias
else:
aliases = alias
cmd = SETUID + " set_mail_alias " + "'"+mail+"'"+" del "+"'"+alias+"'"
res = os.system(cmd)
if res == 0:
cursor.execute("UPDATE users SET alias=? WHERE name=?",
(aliases, UTILISATEUR))
conn.commit()
TIME=time.strftime("%A %d %B %Y %H:%M:%S")
IP=request.environ['REMOTE_ADDR']
CLIENT_PLATFORM=request.headers.get('User-Agent')
log = TIME + ' - ' + IP + ' - ' + UTILISATEUR + ' - ' + CLIENT_PLATFORM + '\n' + '---> ' + "Suppression de l'alias "+ alias + '\n'
append_to_log(log, UTILISATEUR)
flash(u'Votre alias a été supprimé', 'succes')
else:
flash(u'Il y a eu une erreur', 'error')
return redirect(url_for('profil.myalias', _external=True))
else:
return redirect(BASE_URL, code=401)
@profil.route('/invitation/', methods=['GET'])
def invitation():
if 'username' in session:
UTILISATEUR='%s' % escape(session['username'])
conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur"
cursor.execute("""SELECT Token, invitations FROM users WHERE name=?""", (UTILISATEUR,))
tmp = cursor.fetchone()
token = tmp[0]
if token:
url_invitation = BASE_URL + 'inscription/' + token
else:
url_invitation = ""
invitations_count = tmp[1]
conn.close()
return render_template('invitation.html',
section='Profil',
nb_invitation=invitations_count,
token=token,
url_invitation=url_invitation)
else:
return redirect(BASE_URL, code=401)
@profil.route('/gen_token/', methods=['GET'])
def generate_token():
if 'username' in session:
UTILISATEUR='%s' % escape(session['username'])
conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée
cursor = conn.cursor() # Création de l'objet "curseur"
token = gen_token()
cursor.execute("UPDATE users SET Token=? WHERE name=?",
(token, UTILISATEUR))
conn.commit()
conn.close()
return redirect(BASE_URL+'invitation/')
else:
return redirect(BASE_URL, code=401)

6
wsgi.py Normal file
View File

@@ -0,0 +1,6 @@
from gevent.pywsgi import WSGIServer
from pywallter import create_app
app = create_app()
http_server = WSGIServer(("127.0.0.1", 8000), app)
http_server.serve_forever()