First_agent_template / tools /gdpr_data_record.py
Dave67350's picture
Update tools/gdpr_data_record.py
720e4b6 verified
Raw
History Blame Contribute Delete
5.02 kB
# tools/gdpr_data_record.py
import datetime
import re
from fpdf import FPDF
from langdetect import detect
import gradio as gr
from tools.common import prepend_metadata_questions # 👈 import metadata logic
# === PDF Export Function ===
def export_text_to_pdf(text, metadata=None, output_path=None, language="en"):
if output_path is None:
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
output_path = f"gdpr_data_processing_record_{timestamp}.pdf"
pdf = FPDF()
pdf.add_page()
pdf.set_auto_page_break(auto=True, margin=15)
# Title
pdf.set_font("Arial", 'B', 16)
pdf.set_text_color(0, 51, 102)
title = "GDPR Data Processing Record" if language == "en" else "Registre de Traitement des Données (RGPD)"
pdf.cell(0, 15, title, ln=True, align='C')
pdf.ln(10)
# Metadata section
if metadata:
pdf.set_font("Arial", '', 12)
pdf.set_text_color(90, 90, 90)
pdf.multi_cell(0, 10, f"Organization: {metadata.get('organization', 'N/A')}")
pdf.multi_cell(0, 10, f"Completed by: {metadata.get('completed_by', 'N/A')} ({metadata.get('role', 'N/A')})")
pdf.multi_cell(0, 10, f"Timestamp: {metadata.get('timestamp', 'N/A')}")
pdf.ln(5)
# Main content
pdf.set_font("Arial", '', 12)
pdf.set_text_color(0, 0, 0)
for line in text.strip().split('\n'):
line = line.strip()
if line.startswith("## "):
section_title = line.replace("## ", "").strip()
pdf.set_font("Arial", 'B', 13)
pdf.set_text_color(30, 30, 120)
pdf.ln(8)
pdf.cell(0, 10, section_title, ln=True)
pdf.set_font("Arial", '', 12)
pdf.set_text_color(0, 0, 0)
elif line.startswith("- **"):
match = re.match(r"- \*\*(.+?)\*\*: (.+)", line)
if match:
label, value = match.groups()
pdf.set_font("Arial", 'B', 12)
pdf.cell(0, 10, f"{label}:", ln=True)
pdf.set_font("Arial", '', 12)
pdf.multi_cell(0, 10, value)
else:
pdf.multi_cell(0, 10, line)
pdf.output(output_path)
return output_path
# === GDPR-Specific Questions (excluding metadata) ===
BASE_QUESTIONS = [
("purpose", "What is the purpose of the data processing activity?"),
("data_categories", "What categories of personal data are processed?"),
("data_subjects", "What types of data subjects are affected?"),
("recipients", "Who receives or processes the data?"),
("transfers", "Are there any international data transfers involved?"),
("retention", "What is the data retention period?"),
("security", "What security measures are in place?"),
("dpo", "Who is the Data Protection Officer (if any)?"),
]
# Inject metadata
QUESTIONS = prepend_metadata_questions(BASE_QUESTIONS)
def get_questions():
return QUESTIONS
def run_tool():
state = {"step": 0, "answers": {}}
def step_by_step_agent(user_input, state):
step = state["step"]
answers = state["answers"]
if step > 0:
key, _ = QUESTIONS[step - 1]
answers[key] = user_input
if step < len(QUESTIONS):
next_q = QUESTIONS[step][1]
state["step"] += 1
return next_q, state, None
content = "\n".join([f"- **{label}**: {answers.get(key, '')}" for key, label in QUESTIONS])
detected_lang = detect(content)
metadata = {
"organization": answers.get("organization", "N/A"),
"completed_by": answers.get("completed_by", "N/A"),
"role": answers.get("role", "N/A"),
"timestamp": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
pdf_path = export_text_to_pdf(content, metadata=metadata, language=detected_lang)
return "✅ Record complete. Download your GDPR processing record below.", {"done": True}, pdf_path
# Gradio UI
with gr.Blocks(title="GDPR Data Processing Record Tool") as demo:
chatbot = gr.Chatbot(label="🔐 GDPR Assistant", value=[{"role": "assistant", "content": QUESTIONS[0][1]}], type="messages")
msg = gr.Textbox(label="Your answer")
state_var = gr.State(state)
file_output = gr.File(label="Download PDF")
reset_btn = gr.Button("🔁 Restart")
def chat_logic(msg_in, state_in):
reply, updated_state, file = step_by_step_agent(msg_in, state_in)
messages = [{"role": "user", "content": msg_in}]
if reply:
messages.append({"role": "assistant", "content": reply})
return messages, updated_state, file
def reset():
return [{"role": "assistant", "content": QUESTIONS[0][1]}], {"step": 0, "answers": {}}, None
msg.submit(chat_logic, [msg, state_var], [chatbot, state_var, file_output])
reset_btn.click(reset, outputs=[chatbot, state_var, file_output])
demo.launch(show_api=False)