add article and pubications
This commit is contained in:
111
server/routes/articles.py
Normal file
111
server/routes/articles.py
Normal file
@@ -0,0 +1,111 @@
|
||||
from flask import Blueprint, request, jsonify, render_template
|
||||
from flask_jwt_extended import jwt_required, get_jwt_identity
|
||||
from models.publications.articles import Articles, ArticleModel
|
||||
from models.users import Users
|
||||
from models.audit import Audit, AuditModel
|
||||
|
||||
articles_bp = Blueprint("articles", __name__)
|
||||
audit = Audit()
|
||||
|
||||
@articles_bp.route("/editor", methods=["GET"])
|
||||
@jwt_required()
|
||||
def show_editor():
|
||||
token = request.args.get("token", "")
|
||||
article_id = request.args.get("article_id", "None")
|
||||
return render_template("editor.html", token=token, article_id=article_id)
|
||||
|
||||
@articles_bp.route("/", methods=["GET"])
|
||||
@jwt_required()
|
||||
def get_all_articles():
|
||||
articles_repo = Articles()
|
||||
articles = articles_repo.get_all_articles()
|
||||
return jsonify([vars(a) for a in articles]), 200
|
||||
|
||||
@articles_bp.route("/<int:article_id>", methods=["GET"])
|
||||
@jwt_required()
|
||||
def get_article(article_id):
|
||||
articles_repo = Articles()
|
||||
article = articles_repo.get_article(article_id)
|
||||
if not article:
|
||||
return jsonify({"error": "Articolul nu a fost gasit"}), 404
|
||||
return jsonify(vars(article)), 200
|
||||
|
||||
@articles_bp.route("/add", methods=["POST"])
|
||||
@jwt_required()
|
||||
def add_article():
|
||||
current_user_id = int(get_jwt_identity())
|
||||
user_repo = Users()
|
||||
user = user_repo.get_user(current_user_id)
|
||||
|
||||
if not user:
|
||||
return jsonify({"error": "Utilizatorul nu a fost gasit"}), 404
|
||||
|
||||
# Verifică dacă utilizatorul are permisiunea de a crea articole
|
||||
if not getattr(user, 'can_create_articles', 0) == 1:
|
||||
audit.new_entry(AuditModel(user_id=current_user_id, action="Attempt to add article without permission", status="403 - Forbidden"))
|
||||
return jsonify({"error": "Nu aveti permisiunea de a publica articole"}), 403
|
||||
|
||||
data = request.get_json()
|
||||
title = data.get("title")
|
||||
content = data.get("content")
|
||||
|
||||
if not title or not content:
|
||||
return jsonify({"error": "Titlul si continutul sunt obligatorii"}), 400
|
||||
|
||||
articles_repo = Articles()
|
||||
article_id = articles_repo.add_article(title, content, current_user_id)
|
||||
|
||||
if article_id:
|
||||
audit.new_entry(AuditModel(user_id=current_user_id, action=f"Added article: {title}", status="201 - Created"))
|
||||
return jsonify({"message": "Articol adaugat cu succes", "id": article_id}), 201
|
||||
|
||||
return jsonify({"error": "Eroare la adaugarea articolului"}), 500
|
||||
|
||||
@articles_bp.route("/update/<int:article_id>", methods=["PUT"])
|
||||
@jwt_required()
|
||||
def update_article(article_id):
|
||||
current_user_id = int(get_jwt_identity())
|
||||
articles_repo = Articles()
|
||||
article = articles_repo.get_article(article_id)
|
||||
|
||||
if not article:
|
||||
return jsonify({"error": "Articolul nu a fost gasit"}), 404
|
||||
|
||||
# Permite modificarea doar dacă utilizatorul curent este autorul articolului
|
||||
if article.author_id != current_user_id:
|
||||
audit.new_entry(AuditModel(user_id=current_user_id, action=f"Attempt to update article ID {article_id} owned by other user", status="403 - Forbidden"))
|
||||
return jsonify({"error": "Puteti modifica doar articolele scrise de dumneavoastra"}), 403
|
||||
|
||||
data = request.get_json()
|
||||
title = data.get("title")
|
||||
content = data.get("content")
|
||||
|
||||
if not title or not content:
|
||||
return jsonify({"error": "Titlul si continutul sunt obligatorii"}), 400
|
||||
|
||||
if articles_repo.update_article(article_id, title, content):
|
||||
audit.new_entry(AuditModel(user_id=current_user_id, action=f"Updated article ID: {article_id}", status="200 - OK"))
|
||||
return jsonify({"message": "Articol modificat cu succes"}), 200
|
||||
|
||||
return jsonify({"error": "Nu s-a putut modifica articolul"}), 500
|
||||
|
||||
@articles_bp.route("/delete/<int:article_id>", methods=["DELETE"])
|
||||
@jwt_required()
|
||||
def delete_article(article_id):
|
||||
current_user_id = int(get_jwt_identity())
|
||||
articles_repo = Articles()
|
||||
article = articles_repo.get_article(article_id)
|
||||
|
||||
if not article:
|
||||
return jsonify({"error": "Articolul nu a fost gasit"}), 404
|
||||
|
||||
# Permite ștergerea doar dacă utilizatorul curent este autorul articolului
|
||||
if article.author_id != current_user_id:
|
||||
audit.new_entry(AuditModel(user_id=current_user_id, action=f"Attempt to delete article ID {article_id} owned by other user", status="403 - Forbidden"))
|
||||
return jsonify({"error": "Puteti sterge doar articolele scrise de dumneavoastra"}), 403
|
||||
|
||||
if articles_repo.delete_article(article_id):
|
||||
audit.new_entry(AuditModel(user_id=current_user_id, action=f"Deleted article ID: {article_id}", status="200 - OK"))
|
||||
return jsonify({"message": "Articol sters cu succes"}), 200
|
||||
|
||||
return jsonify({"error": "Nu s-a putut sterge articolul"}), 500
|
||||
@@ -94,9 +94,7 @@ def verify_code():
|
||||
return jsonify({"error": "Missing email or verification code"}), 400
|
||||
|
||||
user = users.get_user_by_email(email)
|
||||
#-----------------------------------------------> for testing only remove in prod
|
||||
#if email != 'test@test.com':
|
||||
#-----------------------------------------------> for testing only remove in prod
|
||||
|
||||
if not user or user.otp_code != code:
|
||||
entry = AuditModel(user_id=user.id, action=f"Attempt to verify code: {email}", status='401 - Invalid code!')
|
||||
audit.new_entry(entry)
|
||||
@@ -235,7 +233,8 @@ def me():
|
||||
'profile_pic': user.profile_pic,
|
||||
'created_at': user.created_at,
|
||||
'otp_code': user.otp_code,
|
||||
'otp_expiration': user.otp_expiration
|
||||
'otp_expiration': user.otp_expiration,
|
||||
'can_create_articles': user.can_create_articles
|
||||
}), 200
|
||||
|
||||
|
||||
|
||||
@@ -207,6 +207,8 @@ def add_standard():
|
||||
# Sursa este folderul unde Flet salvează implicit upload-urile
|
||||
source_path = os.path.join(BASE_DIR, "client", "assets", "uploads", os.path.basename(path))
|
||||
dest_path = os.path.join(DOCUMENTS_ROOT, path)
|
||||
print(source_path)
|
||||
print(dest_path)
|
||||
|
||||
if os.path.exists(source_path):
|
||||
os.makedirs(os.path.dirname(dest_path), exist_ok=True)
|
||||
@@ -265,8 +267,8 @@ def delete_standard(id):
|
||||
def add_custom():
|
||||
user_id = get_jwt_identity()
|
||||
data = request.get_json()
|
||||
name = data.get("name")
|
||||
path = data.get("path")
|
||||
name = data.get("name", "").strip()
|
||||
path = data.get("path", "").strip()
|
||||
access = data.get("access")
|
||||
|
||||
if not name or not path:
|
||||
@@ -274,17 +276,31 @@ def add_custom():
|
||||
audit.new_entry(entry)
|
||||
return jsonify({"error": "Missing name or path"}), 400
|
||||
|
||||
# Physical file move from upload folder to documents root
|
||||
source_path = os.path.join(BASE_DIR, "client", "assets", "uploads", os.path.basename(path))
|
||||
dest_path = os.path.join(DOCUMENTS_ROOT, path)
|
||||
# Physical file move from upload folder to documents/Custom folder
|
||||
filename = os.path.basename(path)
|
||||
# The 'path' variable here is the filename from the client, not the full path.
|
||||
# We construct the full path for the database entry later.
|
||||
|
||||
source_path = os.path.join(BASE_DIR, "client", "assets", "uploads", os.path.basename(path))
|
||||
dest_dir = os.path.normpath(os.path.join(DOCUMENTS_ROOT, "Custom"))
|
||||
dest_path = os.path.join(dest_dir, filename) # This is the actual destination path for shutil.move
|
||||
print(source_path)
|
||||
print(dest_path)
|
||||
if os.path.exists(source_path):
|
||||
# Ensure the destination directory exists (for custom docs we usually put them in root or a 'custom' folder)
|
||||
os.makedirs(os.path.dirname(dest_path), exist_ok=True)
|
||||
os.makedirs(dest_dir, exist_ok=True) # Ensure the destination directory exists
|
||||
shutil.move(source_path, dest_path)
|
||||
# Update the 'path' variable to be stored in the database to reflect its new location
|
||||
db_path = f"Custom/{filename}"
|
||||
else:
|
||||
# Log an error and return a response if the source file doesn't exist
|
||||
error_message = f"Source file not found for custom document: {source_path}"
|
||||
print(f"ERROR: {error_message}") # For immediate debug visibility
|
||||
entry = AuditModel(user_id=user_id, action=f"Failed to create custom document (file not found): {name}", status="404 - File not found")
|
||||
audit.new_entry(entry)
|
||||
return jsonify({"error": "Uploaded file not found on server."}), 404
|
||||
|
||||
docs_custom = DocumentsCustom()
|
||||
custom = DocumentsCustomModel(user_id=user_id, name=name, path=path, access=access)
|
||||
custom = DocumentsCustomModel(user_id=user_id, name=name, path=db_path, access=access) # Use db_path here
|
||||
result = docs_custom.new_entry(custom)
|
||||
|
||||
if result:
|
||||
@@ -292,6 +308,10 @@ def add_custom():
|
||||
audit.new_entry(entry)
|
||||
return jsonify({"message": "Custom document created successfully", "id": result}), 201
|
||||
|
||||
# If we reach here, it means the DB entry failed after the file was moved.
|
||||
# This is a potential issue, as the file is moved but not recorded.
|
||||
entry = AuditModel(user_id=user_id, action=f"Failed to create custom document (DB entry failed): {name}", status="500 - DB error")
|
||||
audit.new_entry(entry)
|
||||
return jsonify({"error": "Failed to create custom document"}), 500
|
||||
|
||||
@documents_bp.route("/customs", methods=["GET"])
|
||||
|
||||
@@ -86,7 +86,8 @@ def update_user(user_id):
|
||||
role=data.get("role"),
|
||||
status=data.get("status"),
|
||||
profile_pic=data.get("profile_pic"),
|
||||
active=data.get("active")
|
||||
active=data.get("active"),
|
||||
can_create_articles=data.get("can_create_articles")
|
||||
)
|
||||
|
||||
if success:
|
||||
|
||||
Reference in New Issue
Block a user