diff --git a/config.py b/config.py index d87a23a..0eef69b 100644 --- a/config.py +++ b/config.py @@ -25,6 +25,9 @@ bcrypt_rounds = 14 # sqlite3 database path db_path = "./local_storage.db" +# Set to true to allow guests to search any directory +allow_guests = False + try: import cairosvg cairosvg = True diff --git a/indexer.py b/indexer.py index f7676fb..ff5c0f2 100644 --- a/indexer.py +++ b/indexer.py @@ -23,7 +23,7 @@ class Indexer: t.daemon = True t.start() - time.sleep(15) + time.sleep(25) if self.es.indices.exists(self.index_name): print("Index is already setup") diff --git a/run.py b/run.py index c12d7be..8382efa 100644 --- a/run.py +++ b/run.py @@ -38,19 +38,16 @@ def get_dir_size(path): def user_manage(user): if "admin" in session and session["admin"]: - pass + return render_template("user_manage.html", directories=storage.dirs(), user=storage.users()[user]) else: - flash("You are not authorized to access this page", "warning") + flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") return redirect("/") - return user - - @app.route("/logout") def logout(): session.pop("username") session.pop("admin") - flash("Successfully logged out", "success") + flash("Déconnection réussie", "success") return redirect("/") @@ -63,9 +60,9 @@ def login(): session["username"] = username session["admin"] = storage.users()[username].admin - flash("Successfully logged in", "success") + flash("Connexion réussie", "success") else: - flash("Invalid username or password", "danger") + flash("Nom d'utilisateur ou mot de passe invalide", "danger") return redirect("/") @@ -83,10 +80,50 @@ def user_page(): if not admin_account_present or ("admin" in session and session["admin"]): return render_template("user.html", users=storage.users(), admin_account_present=admin_account_present) else: - flash("You are not authorized to access this page", "warning") + flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") return redirect("/") +@app.route("/user//set_access") +def user_set_access(username): + + if "admin" in session and session["admin"]: + dir_id = request.args["dir_id"] + user = storage.users()[username] + + if request.args["access"] == "1": + user.readable_directories.add(int(dir_id)) + else: + if int(dir_id) in user.readable_directories: + user.readable_directories.remove(int(dir_id)) + + storage.update_user(user) + + flash("Permissions mises à jour", "success") + return redirect("/user/" + username) + else: + flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") + return redirect("/") + + +@app.route("/user//set_admin") +def user_set_admin(username): + + if "admin" in session and session["admin"]: + + user = storage.users()[username] + + if user.username == session["username"]: + flash("Vous n'êtes pas autorisé à changer votre propre type de compte", "warning") + else: + user.admin = request.args["admin"] == "1" + storage.update_user(user) + + flash("Permissions mises à jour", "success") + + return redirect("/user/" + username) + + @app.route("/user/add", methods=['POST']) def user_add(): @@ -104,21 +141,38 @@ def user_add(): try: storage.save_user(User(username, password, is_admin)) - flash("Created new user", "success") + flash("Nouvel utilisateur créé", "success") except DuplicateUserException: - flash("Couldn't create user Make sure that the username is unique", "danger") + flash("L'utilisateur n'as pas pu être créé Assurez vous que le nom d'utilisateur est unique", "danger") return redirect("/user") else: - flash("You are not authorized to access this page", "warning") + flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") return redirect("/") +@app.route("/user//del") +def user_del(username): + + if "admin" in session and session["admin"]: + + if session["username"] == username: + flash("Vous ne pouvez pas supprimer votre propre compte", "warning") + return redirect("/user/" + username) + else: + storage.remove_user(username) + flash("Utilisateur supprimé", "success") + return redirect("/user") + else: + flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") + return redirect("/") + @app.route("/suggest") def suggest(): return json.dumps(search.suggest(request.args.get("prefix"))) + @app.route("/document/") def document(doc_id): @@ -171,14 +225,12 @@ def thumb(doc_id): if os.path.isfile(tn_path): return send_file(tn_path) else: - print("tn not found") default_thumbnail = BytesIO() Image.new("RGB", (255, 128), (0, 0, 0)).save(default_thumbnail, "JPEG") default_thumbnail.seek(0) return send_file(default_thumbnail, "image/jpeg") else: - print("doc is none") default_thumbnail = BytesIO() Image.new("RGB", (255, 128), (0, 0, 0)).save(default_thumbnail, "JPEG") default_thumbnail.seek(0) @@ -189,9 +241,13 @@ def thumb(doc_id): def search_page(): mime_map = search.get_mime_map() - mime_map.append({"id": "any", "text": "Any"}) + mime_map.append({"id": "any", "text": "Tous"}) - return render_template("search.html", directories=storage.dirs(), mime_map=mime_map) + directories = [storage.dirs()[x] for x in get_allowed_dirs(session["username"] if "username" in session else None)] + + return render_template("search.html", + directories=directories, + mime_map=mime_map) @app.route("/list") @@ -199,6 +255,18 @@ def search_liste_page(): return render_template("searchList.html") +def get_allowed_dirs(username): + + if config.allow_guests: + return [x for x in storage.dirs() if x.enabled] + else: + if username: + user = storage.users()[username] + return [x for x in storage.dirs() if storage.dirs()[x].enabled and x in user.readable_directories] + else: + return list() + + @app.route("/search", methods=['POST']) def search_route(): @@ -212,19 +280,8 @@ def search_route(): directories = request.json["directories"] # Remove disabled & non-existing directories - for search_directory in directories: - directory_exists = False - - for dir_id in storage.dirs(): - if search_directory == dir_id: - directory_exists = True - - if not storage.dirs()[dir_id].enabled: - directories.remove(search_directory) - break - - if not directory_exists: - directories.remove(search_directory) + allowed_dirs = get_allowed_dirs(session["username"] if "username" in session else None) + directories = [x for x in directories if x in allowed_dirs] path = request.json["path"] @@ -249,7 +306,7 @@ def dir_list(): if "admin" in session and session["admin"]: return render_template("directory.html", directories=storage.dirs()) else: - flash("You are not authorized to access this page", "warning") + flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") return redirect("/") @@ -266,13 +323,13 @@ def directory_add(): try: d.set_default_options() storage.save_directory(d) - flash("Created directory", "success") + flash("Dossier créé", "success") except DuplicateDirectoryException: - flash("Couldn't create directory Make sure that the path is unique", "danger") + flash("Le dossier n'a pas pu être créé Assurer vous de choisir un nom unique", "danger") return redirect("/directory") else: - flash("You are not authorized to access this page", "warning") + flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") return redirect("/") @@ -287,7 +344,7 @@ def directory_manage(dir_id): return render_template("directory_manage.html", directory=directory, tn_size=tn_size, tn_size_formatted=tn_size_formatted) else: - flash("You are not authorized to access this page", "warning") + flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") return redirect("/") @@ -312,14 +369,14 @@ def directory_update(dir_id): try: storage.update_directory(updated_dir) - flash("Updated directory", "success") + flash("Dossier mis à jour", "success") except DuplicateDirectoryException: - flash("Couldn't update directory Make sure that the path is unique", "danger") + flash("Le dossier n'a pas pu être mis à jour Assurez vous que le chemin est unique", "danger") return redirect("/directory/" + str(dir_id)) else: - flash("You are not authorized to access this page", "warning") + flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") return redirect("/") @@ -335,7 +392,7 @@ def directory_update_opt(dir_id): return redirect("/directory/" + str(dir_id)) else: - flash("You are not authorized to access this page", "warning") + flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") return redirect("/") @@ -347,11 +404,11 @@ def directory_del(dir_id): shutil.rmtree("static/thumbnails/" + str(dir_id)) storage.remove_directory(dir_id) - flash("Deleted directory", "success") + flash("Dossier supprimé", "success") return redirect("/directory") else: - flash("You are not authorized to access this page", "warning") + flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") return redirect("/") @@ -374,10 +431,10 @@ def directory_reset(dir_id): search.delete_directory(dir_id) - flash("Reset directory options to default settings", "success") + flash("Options du dossier réinitialisés", "success") return redirect("directory/" + str(dir_id)) else: - flash("You are not authorized to access this page", "warning") + flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") return redirect("/") @@ -387,7 +444,7 @@ def task(): return render_template("task.html", tasks=storage.tasks(), directories=storage.dirs(), task_list=json.dumps(list(storage.tasks().keys()))) else: - flash("You are not authorized to access this page", "warning") + flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") return redirect("/") @@ -400,7 +457,7 @@ def get_current_task(): else: return "" else: - flash("You are not authorized to access this page", "warning") + flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") return redirect("/") @@ -410,11 +467,18 @@ def task_add(): task_type = request.args.get("type") directory = request.args.get("directory") - storage.save_task(Task(task_type, directory)) + if task_type not in ("1", "2"): + flash("Vous devez choisir un type de tâche", "danger") + return redirect("/task") + + if directory.isdigit() and int(directory) in storage.dirs(): + storage.save_task(Task(task_type, directory)) + else: + flash("Vous devez choisir un dossier", "danger") return redirect("/task") else: - flash("You are not authorized to access this page", "warning") + flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") return redirect("/") @@ -428,14 +492,14 @@ def task_del(task_id): return redirect("/task") else: - flash("You are not authorized to access this page", "warning") + flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") return redirect("/") @app.route("/reset_es") def reset_es(): if "admin" in session and session["admin"]: - flash("Elasticsearch index has been reset. Modifications made in config.py have been applied.", "success") + flash("Elasticsearch a été réinitialisé, les changements dans config.py ont été appliqués", "success") tm.indexer.init() if os.path.exists("static/thumbnails"): @@ -443,7 +507,7 @@ def reset_es(): return redirect("/dashboard") else: - flash("You are not authorized to access this page", "warning") + flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") return redirect("/") @@ -470,7 +534,7 @@ def dashboard(): index_size=humanfriendly.format_size(search.get_index_size())) else: - flash("You are not authorized to access this page", "warning") + flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") return redirect("/") diff --git a/static/js/search.js b/static/js/search.js index 8e9d2bd..e013798 100644 --- a/static/js/search.js +++ b/static/js/search.js @@ -73,7 +73,7 @@ function makeStatsCard(searchResult) { statsCardBody.setAttribute("class", "card-body"); let stat = document.createElement("p"); - stat.appendChild(document.createTextNode(searchResult["hits"]["total"] + " results in " + searchResult["took"] + "ms")); + stat.appendChild(document.createTextNode(searchResult["hits"]["total"] + " résultats en " + searchResult["took"] + "ms")); let sizeStat = document.createElement("span"); sizeStat.appendChild(document.createTextNode(humanFileSize(searchResult["aggregations"]["total_size"]["value"]))); @@ -173,8 +173,8 @@ function gifOver(thumbnail, documentId) { function downloadPopover(element, documentId) { element.setAttribute("data-content", - ' Download' + - ' View'); + ' Télécharger' + + ' Consulter'); element.setAttribute("data-toggle", "popover"); element.addEventListener("mouseover", function() { element.focus(); @@ -267,7 +267,7 @@ function createDocCard(hit) { } thumbnailOverlay.appendChild(resolutionBadge); - var format = hit["_source"]["format"]; + var format = hit["_source"]["format_name"]; //Hover if(format === "GIF") { @@ -592,4 +592,4 @@ document.getElementById("pathBar").addEventListener("keyup", function () { searchQueued = true; }); -window.setInterval(search, 150); \ No newline at end of file +window.setInterval(search, 300); \ No newline at end of file diff --git a/storage.py b/storage.py index 62f3ba1..a90add7 100644 --- a/storage.py +++ b/storage.py @@ -28,6 +28,7 @@ class User: self.username = username self.hashed_password = hashed_password self.admin = admin + self.readable_directories = set() class Option: @@ -224,7 +225,15 @@ class LocalStorage: db_users = c.fetchall() for db_user in db_users: - self.cached_users[db_user[0]] = User(db_user[0], b"", bool(db_user[1])) + user = User(db_user[0], b"", bool(db_user[1])) + + c.execute("SELECT username, directory_id FROM User_canRead_Directory WHERE username=?", (db_user[0],)) + db_accesses = c.fetchall() + + for db_access in db_accesses: + user.readable_directories.add(db_access[1]) + + self.cached_users[db_user[0]] = user conn.close() @@ -256,6 +265,12 @@ class LocalStorage: c = conn.cursor() c.execute("UPDATE User SET is_admin=? WHERE username=?", (user.admin, user.username)) + c.execute("DELETE FROM User_canRead_Directory WHERE username=?", (user.username, )) + conn.commit() + + for access in user.readable_directories: + c.execute("INSERT INTO User_canRead_Directory VALUES (?,?)", (user.username, access)) + c.close() conn.commit() conn.close() diff --git a/templates/dashboard.html b/templates/dashboard.html index 74cb443..75b47f8 100644 --- a/templates/dashboard.html +++ b/templates/dashboard.html @@ -5,7 +5,7 @@
-
Global Information
+
Information globale
@@ -14,45 +14,45 @@ - + - + - + - + - + - + - +
{{ version }}
Total thumbnail cache sizeTaille totale des miniatures
{{ tn_size_total }}
Total document countNombre de documents totals
{{ doc_count }}
Total size of indexed documentsTaille totale des documents indexés
{{ doc_size }}
Total index sizeTaille totale de l'index
{{ index_size }}
User countNombre d'utilisateurs
1
SQLite database pathChemin de la base de donnée SQLite
{{ db_path }}
Elasticsearch URLAdresse Elasticsearch
{{ elasticsearch_url }}
- +
Actions
@@ -60,8 +60,8 @@
-
Ongoing tasks
+
Tâches en cours
{% for task_id in tasks | sort() %}
{{ directories[tasks[task_id].dir_id].name }} - {% if tasks[task_id].type == 1 %} - Indexing + Indexation {% else %} - Thumbnail generation + Génération des miniatures {% endif %} @@ -124,12 +124,12 @@
- Queued + En attente
- +
{% endfor %} diff --git a/templates/user.html b/templates/user.html index 3bf9658..0d67788 100644 --- a/templates/user.html +++ b/templates/user.html @@ -1,16 +1,16 @@ {% extends "layout.html" %} {% set active_page = "user" %} +{% block title %}Liste des utilisateurs{% endblock title %} {% block body %} -
-
-
Create user
+
+
Créer un utilisateur
{% if not admin_account_present %} -

This page is unlocked because there are no admin accounts

+

Cette page est débloquée parce qu'il n'y a aucun compte administrateur

{% endif %}
@@ -18,39 +18,37 @@
- - + +
- +
- +
- +
-
Users
+
Utilisateurs
- - + + - - + - {% for user in users %} - + {% for user in users %} - + {% endfor %} diff --git a/templates/user_manage.html b/templates/user_manage.html index ff8ba93..94dd39b 100644 --- a/templates/user_manage.html +++ b/templates/user_manage.html @@ -1,19 +1,72 @@ {% extends "layout.html" %} {% set active_page = "user" %} +{% block title %}Gestion utilisateur{% endblock title %} {% block body %}
-
Manage permission of {{ session["username"] }}
+
Gérer les permission de {{ user.username }}
+
+
+
Administrateur:
+
+
+
+ + + + +
+
+
+ +
UserAdminUtilisateurAdministrateur Actions
{% if session["username"] == user %}{{ user }}{% else %}{{ user }}{% endif %} ManageGérer
+ + + + + + + + {% for dir_id in directories %} + + + + + {% endfor %} + +
DossierAccès
{{ directories[dir_id].name }}
+ + + +
+ +
+ +
+ +
{% endblock body %} \ No newline at end of file