2023-10-25 23:34:57 +05:30

469 lines
14 KiB
Python

from os import mkdir, path
import json
from flask import Flask, request, send_file, abort, Response
from werkzeug.datastructures import ImmutableMultiDict
import appdirs
from data_handler import DataHandler
app: Flask = Flask(__name__)
def handle_first_launched():
"""
Makes sure everything is initialized correctly
"""
folder_path: str = appdirs.user_data_dir()
folder_path = path.join(folder_path, "Unnamed_Password_Manager")
if not path.exists(folder_path):
mkdir(folder_path)
@app.route('/favicon.ico')
def favicon() -> Response:
favicon_path: str = path.join(app.root_path, '../frontend/static', 'favicon.ico')
return send_file(favicon_path, mimetype='image/vnd.microsoft.icon')
@app.route("/index.html")
def handle_index() -> Response:
index_path: str = path.join(app.root_path, "../frontend/html", "index.html")
return send_file(index_path, mimetype="text/html")
@app.get("/")
@app.get("/<path:url_path>")
def handle_get(url_path: str = "html/index.html") -> Response:
"""
Handle all get requests that are made.
"""
handle_first_launched()
requested_file_path: str = \
path.abspath(path.join(path.curdir, "..", "frontend", url_path))
response: Response = send_file(requested_file_path)
response.status = 200
if path.isfile(requested_file_path):
return send_file(requested_file_path)
abort(404)
class QueryHandler:
"""
This is the bridge between the frontend and DataHandler class
"""
__data_handler: DataHandler| None = None
@staticmethod
@app.post("/login")
def login() -> Response:
"""
Logs the user in
"""
data: ImmutableMultiDict[str, str] = request.form
if "user_name" not in data:
return Response(
"user_name not given",
400,
content_type="text/plain"
)
if "password" not in data:
return Response(
"password is not given",
400,
content_type="text/plain"
)
try:
QueryHandler.__data_handler = \
DataHandler(data["user_name"], data["password"])
except ValueError as value_error:
return Response(
str(value_error),
403,
content_type="text/plain"
)
return Response(status=200)
@staticmethod
@app.post("/logout")
def logout() -> Response:
"""
Logs the user out
"""
if QueryHandler.__data_handler is None:
return Response(
"Not logged in",
403,
content_type="text/plain"
)
QueryHandler.__data_handler = None
return Response(status=200)
@staticmethod
@app.post("/add_user")
def add_user() -> Response:
"""
Adds a new user
"""
data: ImmutableMultiDict[str, str] = request.form
if "user_name" not in data:
return Response(
"user_name not given",
400,
content_type="text/plain"
)
if "password" not in data:
return Response(
"password is not given",
400,
content_type="text/plain"
)
try:
DataHandler.create_user(data["user_name"], data["password"])
except ValueError as value_error:
return Response(
str(value_error),
403,
content_type="text/plain"
)
return Response(status=200)
@staticmethod
@app.post("/get_data")
def get_data() -> Response:
"""
Return all user data
"""
if QueryHandler.__data_handler is None:
return Response(
"Not logged in",
403,
content_type="text/plain"
)
return Response(
json.dumps(QueryHandler.__data_handler.get_data()),
200,
content_type="text/json"
)
@staticmethod
@app.post("/change_password")
def change_password() -> Response:
"""
Change the password of the user.
"""
if QueryHandler.__data_handler is None:
return Response(
"Not logged in",
403,
content_type="text/plain"
)
data: ImmutableMultiDict[str, str] = request.form
if "password" not in data:
return Response(
"password is not given",
400,
content_type="text/plain"
)
QueryHandler.__data_handler.change_password(data["password"])
return Response(status=200)
@staticmethod
@app.post("/add_entry")
def add_entry() -> Response:
"""
Add a new entry to the data
"""
if QueryHandler.__data_handler is None:
return Response(
"Not logged in",
403,
content_type="text/plain"
)
data: ImmutableMultiDict[str, str] = request.form
if "entry_name" not in data:
return Response(
"entry_name is not given",
400,
content_type="text/plain"
)
if "fields" not in data:
return Response(
"fields is not given",
400,
content_type="text/plain"
)
entry_name: str = data["entry_name"]
try:
fields: dict = json.loads(data["fields"])
except json.decoder.JSONDecodeError:
return Response(
f"The json-string provided is wrong {data['fields']}",
400,
content_type="text/plain"
)
try:
QueryHandler.__data_handler.add_entry(entry_name, fields)
except ValueError as value_error:
return Response(
str(value_error),
403,
content_type="text/plain"
)
return Response(status=200)
@staticmethod
@app.post("/delete_entry")
def delete_entry() -> Response:
"""
Delete Entry for the logged in user
"""
if QueryHandler.__data_handler is None:
return Response(
"Not logged in",
403,
content_type="text/plain"
)
data: ImmutableMultiDict[str, str] = request.form
if "entry_name" not in data:
return Response(
"entry_name is not given",
400,
content_type="text/plain"
)
entry_name: str = data["entry_name"]
try:
QueryHandler.__data_handler.delete_entry(entry_name)
except ValueError as value_error:
return Response(
str(value_error),
403,
content_type="text/plain"
)
return Response(status=200)
@staticmethod
@app.post("/edit_entry_name")
def edit_entry_name() -> Response:
"""
Delete Entry for the logged in user
"""
if QueryHandler.__data_handler is None:
return Response(
"Not logged in",
403,
content_type="text/plain"
)
data: ImmutableMultiDict[str, str] = request.form
if "old_entry_name" not in data:
return Response(
"old_entry_name is not given",
400,
content_type="text/plain"
)
if "new_entry_name" not in data:
return Response(
"new_entry_name is not given",
400,
content_type="text/plain"
)
try:
QueryHandler.__data_handler.edit_entry_name(
data["old_entry_name"], data["new_entry_name"]
)
except ValueError as value_error:
return Response(
str(value_error),
403,
content_type="text/plain"
)
return Response(status=200)
@staticmethod
@app.post("/add_field")
def add_field() -> Response:
"""
Add a field to the entry
"""
if QueryHandler.__data_handler is None:
return Response(
"Not logged in",
403,
content_type="text/plain"
)
data: ImmutableMultiDict[str, str] = request.form
if "entry_name" not in data:
return Response(
"entry_name is not given",
400,
content_type="text/plain"
)
if "field_name" not in data:
return Response(
"field_name is not given",
400,
content_type="text/plain"
)
if "field_value" not in data:
return Response(
"field_value is not given",
400,
content_type="text/plain"
)
try:
QueryHandler.__data_handler.add_field(
data["entry_name"],
data["field_name"],
data["field_value"]
)
except ValueError as value_error:
return Response(
str(value_error),
403,
content_type="text/plain"
)
return Response(status=200)
@staticmethod
@app.post("/delete_field")
def delete_field() -> Response:
"""
Delete a field from a entry
"""
if QueryHandler.__data_handler is None:
return Response(
"Not logged in",
403,
content_type="text/plain"
)
data: ImmutableMultiDict[str, str] = request.form
if "entry_name" not in data:
return Response(
"entry_name is not given",
400,
content_type="text/plain"
)
if "field_name" not in data:
return Response(
"field_name is not given",
400,
content_type="text/plain"
)
try:
QueryHandler.__data_handler.delete_field(
data["entry_name"],
data["field_name"]
)
except ValueError as value_error:
return Response(
str(value_error),
403,
content_type="text/plain"
)
return Response(status=200)
@staticmethod
@app.post("/edit_field_name")
def edit_field_name() -> Response:
"""
Change the field name in a entry
"""
if QueryHandler.__data_handler is None:
return Response(
"Not logged in",
403,
content_type="text/plain"
)
data: ImmutableMultiDict[str, str] = request.form
if "entry_name" not in data:
return Response(
"entry_name is not given",
400,
content_type="text/plain"
)
if "old_field_name" not in data:
return Response(
"old_field_name is not given",
400,
content_type="text/plain"
)
if "new_field_name" not in data:
return Response(
"new_field_name is not given",
400,
content_type="text/plain"
)
try:
QueryHandler.__data_handler.edit_field_name(
data["entry_name"],
data["old_field_name"],
data["new_field_name"]
)
except ValueError as value_error:
return Response(
str(value_error),
403,
content_type="text/plain"
)
return Response(status=200)
@staticmethod
@app.post("/edit_field_value")
def edit_field_value() -> Response:
"""
Change the value of a field
"""
if QueryHandler.__data_handler is None:
return Response(
"Not logged in",
403,
content_type="text/plain"
)
data: ImmutableMultiDict[str, str] = request.form
if "entry_name" not in data:
return Response(
"entry_name is not given",
400,
content_type="text/plain"
)
if "field_name" not in data:
return Response(
"field_name is not given",
400,
content_type="text/plain"
)
if "field_value" not in data:
return Response(
"field_value is not given",
400,
content_type="text/plain"
)
try:
QueryHandler.__data_handler.edit_field_value(
data["entry_name"],
data["field_name"],
data["field_value"]
)
except ValueError as value_error:
return Response(
str(value_error),
403,
content_type="text/plain"
)
return Response(status=200)