Add permission levels for linked projects (read-only, request edit, full edit)

Co-authored-by: naielv <109038805+naielv@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-01-31 20:36:55 +00:00
parent 1c3aef8345
commit 88fb053031
2 changed files with 125 additions and 24 deletions

View File

@@ -100,7 +100,13 @@ function list_projects($proyectos_dir, $parent_id = null) {
return $projects; return $projects;
} }
// Function to get linked projects from other aularios /**
* Get linked projects from other aularios based on aulario configuration
*
* @param array $aulario The aulario configuration containing linked_projects array
* @param string $centro_id The centro ID for constructing file paths
* @return array Array of project data arrays with is_linked and source_aulario fields added
*/
function get_linked_projects($aulario, $centro_id) { function get_linked_projects($aulario, $centro_id) {
$linked = []; $linked = [];
$linked_projects = $aulario["linked_projects"] ?? []; $linked_projects = $aulario["linked_projects"] ?? [];
@@ -244,9 +250,25 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
$item_type = $_POST["item_type"] ?? "link"; $item_type = $_POST["item_type"] ?? "link";
$item_name = trim($_POST["item_name"] ?? ""); $item_name = trim($_POST["item_name"] ?? "");
$item_url = trim($_POST["item_url"] ?? ""); $item_url = trim($_POST["item_url"] ?? "");
$source_aulario_param = $_POST["source_aulario"] ?? "";
// Determine which directory to use based on whether this is a linked project
$working_dir = $proyectos_dir;
if (!empty($source_aulario_param)) {
// Validate the link
$linked_projects = $aulario["linked_projects"] ?? [];
foreach ($linked_projects as $link) {
if (($link["source_aulario"] ?? "") === $source_aulario_param &&
($link["project_id"] ?? "") === $project_id &&
(($link["permission"] ?? "read_only") === "full_edit" || ($link["permission"] ?? "read_only") === "request_edit")) {
$working_dir = "/DATA/entreaulas/Centros/$centro_id/Aularios/$source_aulario_param/Proyectos";
break;
}
}
}
if ($project_id !== "" && $item_name !== "") { if ($project_id !== "" && $item_name !== "") {
$project = load_project($proyectos_dir, $project_id); $project = load_project($working_dir, $project_id);
if ($project) { if ($project) {
$item_id = generate_id($item_name); $item_id = generate_id($item_name);
$item = [ $item = [
@@ -262,7 +284,7 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
$item["url"] = $item_url; $item["url"] = $item_url;
} elseif ($item_type === "file" && isset($_FILES["item_file"]) && $_FILES["item_file"]["error"] === UPLOAD_ERR_OK) { } elseif ($item_type === "file" && isset($_FILES["item_file"]) && $_FILES["item_file"]["error"] === UPLOAD_ERR_OK) {
// Handle file upload with validation // Handle file upload with validation
$project_dir = "$proyectos_dir/$project_id"; $project_dir = "$working_dir/$project_id";
if (!is_dir($project_dir)) { if (!is_dir($project_dir)) {
mkdir($project_dir, 0755, true); mkdir($project_dir, 0755, true);
} }
@@ -316,9 +338,13 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
$project["items"][] = $item; $project["items"][] = $item;
$project["updated_at"] = time(); $project["updated_at"] = time();
save_project($proyectos_dir, $project_id, $project); save_project($working_dir, $project_id, $project);
header("Location: /entreaulas/proyectos.php?aulario=" . urlencode($aulario_id) . "&project=" . urlencode($project_id)); $redirect_params = "aulario=" . urlencode($aulario_id) . "&project=" . urlencode($project_id);
if (!empty($source_aulario_param)) {
$redirect_params .= "&source=" . urlencode($source_aulario_param);
}
header("Location: /entreaulas/proyectos.php?" . $redirect_params);
exit; exit;
} }
} }
@@ -328,9 +354,25 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
if ($action === "delete_item") { if ($action === "delete_item") {
$project_id = $_POST["project_id"] ?? ""; $project_id = $_POST["project_id"] ?? "";
$item_id = $_POST["item_id"] ?? ""; $item_id = $_POST["item_id"] ?? "";
$source_aulario_param = $_POST["source_aulario"] ?? "";
// Determine which directory to use based on whether this is a linked project
$working_dir = $proyectos_dir;
if (!empty($source_aulario_param)) {
// Validate the link
$linked_projects = $aulario["linked_projects"] ?? [];
foreach ($linked_projects as $link) {
if (($link["source_aulario"] ?? "") === $source_aulario_param &&
($link["project_id"] ?? "") === $project_id &&
(($link["permission"] ?? "read_only") === "full_edit" || ($link["permission"] ?? "read_only") === "request_edit")) {
$working_dir = "/DATA/entreaulas/Centros/$centro_id/Aularios/$source_aulario_param/Proyectos";
break;
}
}
}
if ($project_id !== "" && $item_id !== "") { if ($project_id !== "" && $item_id !== "") {
$project = load_project($proyectos_dir, $project_id); $project = load_project($working_dir, $project_id);
if ($project && isset($project["items"])) { if ($project && isset($project["items"])) {
$new_items = []; $new_items = [];
foreach ($project["items"] as $item) { foreach ($project["items"] as $item) {
@@ -339,7 +381,7 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
} else { } else {
// Delete file if it's a file type // Delete file if it's a file type
if ($item["type"] === "file" && isset($item["filename"])) { if ($item["type"] === "file" && isset($item["filename"])) {
$file_path = "$proyectos_dir/$project_id/" . $item["filename"]; $file_path = "$working_dir/$project_id/" . $item["filename"];
if (file_exists($file_path)) { if (file_exists($file_path)) {
unlink($file_path); unlink($file_path);
} }
@@ -348,9 +390,13 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
} }
$project["items"] = $new_items; $project["items"] = $new_items;
$project["updated_at"] = time(); $project["updated_at"] = time();
save_project($proyectos_dir, $project_id, $project); save_project($working_dir, $project_id, $project);
header("Location: /entreaulas/proyectos.php?aulario=" . urlencode($aulario_id) . "&project=" . urlencode($project_id)); $redirect_params = "aulario=" . urlencode($aulario_id) . "&project=" . urlencode($project_id);
if (!empty($source_aulario_param)) {
$redirect_params .= "&source=" . urlencode($source_aulario_param);
}
header("Location: /entreaulas/proyectos.php?" . $redirect_params);
exit; exit;
} }
} }
@@ -493,17 +539,45 @@ $view = $current_project ? "project" : "list";
<?php <?php
// Check if this is a linked project from another aulario // Check if this is a linked project from another aulario
$source_aulario_for_project = $_GET["source"] ?? ""; $source_aulario_for_project = $_GET["source"] ?? "";
$is_linked_project = !empty($source_aulario_for_project); $is_linked_project = false;
$linked_permission = "read_only";
if ($is_linked_project) { if (!empty($source_aulario_for_project)) {
// Load from source aulario // Validate that this project is actually linked in the configuration
$project_source_dir = "/DATA/entreaulas/Centros/$centro_id/Aularios/$source_aulario_for_project/Proyectos"; $linked_projects = $aulario["linked_projects"] ?? [];
$project = load_project($project_source_dir, $current_project); $valid_link = false;
foreach ($linked_projects as $link) {
if (($link["source_aulario"] ?? "") === $source_aulario_for_project &&
($link["project_id"] ?? "") === $current_project) {
$valid_link = true;
$linked_permission = $link["permission"] ?? "read_only";
break;
}
}
if ($valid_link) {
$is_linked_project = true;
$project_source_dir = "/DATA/entreaulas/Centros/$centro_id/Aularios/$source_aulario_for_project/Proyectos";
$project = load_project($project_source_dir, $current_project);
} else {
// Invalid link configuration, treat as local project
$project = load_project($proyectos_dir, $current_project);
}
} else { } else {
// Load from local aulario // Load from local aulario
$project = load_project($proyectos_dir, $current_project); $project = load_project($proyectos_dir, $current_project);
} }
// Determine if editing is allowed
$can_edit_linked = false;
if ($is_linked_project) {
if ($linked_permission === "full_edit" || $linked_permission === "request_edit") {
// For now, treat both full_edit and request_edit as allowing edits
// In the future, request_edit could implement an approval workflow
$can_edit_linked = true;
}
}
if (!$project): if (!$project):
?> ?>
<div class="card pad"> <div class="card pad">
@@ -544,8 +618,12 @@ $view = $current_project ? "project" : "list";
</nav> </nav>
<?php if ($is_linked_project): ?> <?php if ($is_linked_project): ?>
<div class="card pad" style="background: #cfe2ff; color: #084298;"> <div class="card pad" style="background: <?= $can_edit_linked ? '#d1e7dd' : '#cfe2ff' ?>; color: <?= $can_edit_linked ? '#0f5132' : '#084298' ?>;">
<strong> Proyecto compartido:</strong> Este es un proyecto compartido desde otro aulario. Solo puedes ver su contenido, pero no editarlo ni eliminarlo. <?php if ($can_edit_linked): ?>
<strong>✏️ Proyecto compartido con permisos de edición:</strong> Este es un proyecto compartido desde otro aulario. Puedes ver y editar su contenido. Los cambios se guardarán en el aulario origen.
<?php else: ?>
<strong> Proyecto compartido (solo lectura):</strong> Este es un proyecto compartido desde otro aulario. Solo puedes ver su contenido, pero no editarlo.
<?php endif; ?>
</div> </div>
<?php endif; ?> <?php endif; ?>
@@ -577,7 +655,7 @@ $view = $current_project ? "project" : "list";
</div> </div>
<!-- Action Buttons --> <!-- Action Buttons -->
<?php if (!$is_linked_project): ?> <?php if (!$is_linked_project || $can_edit_linked): ?>
<div class="card pad"> <div class="card pad">
<div class="d-flex gap-2 flex-wrap"> <div class="d-flex gap-2 flex-wrap">
<button type="button" class="btn btn-success btn-lg" data-bs-toggle="modal" data-bs-target="#addItemModal"> <button type="button" class="btn btn-success btn-lg" data-bs-toggle="modal" data-bs-target="#addItemModal">
@@ -694,11 +772,14 @@ $view = $current_project ? "project" : "list";
Abrir Archivo Abrir Archivo
</a> </a>
<?php endif; ?> <?php endif; ?>
<?php if (!$is_linked_project): ?> <?php if (!$is_linked_project || $can_edit_linked): ?>
<form method="post" style="display: inline;" onsubmit="return confirm('¿Estás seguro de que quieres eliminar este elemento?');"> <form method="post" style="display: inline;" onsubmit="return confirm('¿Estás seguro de que quieres eliminar este elemento?');">
<input type="hidden" name="action" value="delete_item"> <input type="hidden" name="action" value="delete_item">
<input type="hidden" name="project_id" value="<?= htmlspecialchars($current_project) ?>"> <input type="hidden" name="project_id" value="<?= htmlspecialchars($current_project) ?>">
<input type="hidden" name="item_id" value="<?= htmlspecialchars($item["id"]) ?>"> <input type="hidden" name="item_id" value="<?= htmlspecialchars($item["id"]) ?>">
<?php if ($is_linked_project && $can_edit_linked): ?>
<input type="hidden" name="source_aulario" value="<?= htmlspecialchars($source_aulario_for_project) ?>">
<?php endif; ?>
<button type="submit" class="btn btn-danger"> <button type="submit" class="btn btn-danger">
<img src="/static/iconexperience/garbage.png" height="20" style="vertical-align: middle;"> <img src="/static/iconexperience/garbage.png" height="20" style="vertical-align: middle;">
</button> </button>
@@ -727,6 +808,9 @@ $view = $current_project ? "project" : "list";
<div class="modal-body"> <div class="modal-body">
<input type="hidden" name="action" value="add_item"> <input type="hidden" name="action" value="add_item">
<input type="hidden" name="project_id" value="<?= htmlspecialchars($current_project) ?>"> <input type="hidden" name="project_id" value="<?= htmlspecialchars($current_project) ?>">
<?php if ($is_linked_project && $can_edit_linked): ?>
<input type="hidden" name="source_aulario" value="<?= htmlspecialchars($source_aulario_for_project) ?>">
<?php endif; ?>
<div class="mb-3"> <div class="mb-3">
<label for="item_type" class="form-label">Tipo de Elemento *</label> <label for="item_type" class="form-label">Tipo de Elemento *</label>

View File

@@ -44,12 +44,14 @@ switch ($_GET["form"]) {
$linked_projects = []; $linked_projects = [];
$linked_aularios = $_POST["linked_aulario"] ?? []; $linked_aularios = $_POST["linked_aulario"] ?? [];
$linked_project_ids = $_POST["linked_project_id"] ?? []; $linked_project_ids = $_POST["linked_project_id"] ?? [];
$linked_permissions = $_POST["linked_permission"] ?? [];
for ($i = 0; $i < count($linked_aularios); $i++) { for ($i = 0; $i < count($linked_aularios); $i++) {
if (!empty($linked_aularios[$i]) && !empty($linked_project_ids[$i])) { if (!empty($linked_aularios[$i]) && !empty($linked_project_ids[$i])) {
$linked_projects[] = [ $linked_projects[] = [
"source_aulario" => $linked_aularios[$i], "source_aulario" => $linked_aularios[$i],
"project_id" => $linked_project_ids[$i] "project_id" => $linked_project_ids[$i],
"permission" => $linked_permissions[$i] ?? "read_only"
]; ];
} }
} }
@@ -190,14 +192,15 @@ switch ($_GET["action"]) {
$existing_links = $aulario_data['linked_projects'] ?? []; $existing_links = $aulario_data['linked_projects'] ?? [];
if (count($existing_links) === 0) { if (count($existing_links) === 0) {
// Show one empty row // Show one empty row
$existing_links = [["source_aulario" => "", "project_id" => ""]]; $existing_links = [["source_aulario" => "", "project_id" => "", "permission" => "read_only"]];
} }
foreach ($existing_links as $idx => $link): foreach ($existing_links as $idx => $link):
$source_aul = $link['source_aulario'] ?? ''; $source_aul = $link['source_aulario'] ?? '';
$proj_id = $link['project_id'] ?? ''; $proj_id = $link['project_id'] ?? '';
$permission = $link['permission'] ?? 'read_only';
?> ?>
<div class="row mb-2 linked-project-row"> <div class="row mb-2 linked-project-row">
<div class="col-md-5"> <div class="col-md-4">
<select name="linked_aulario[]" class="form-select linked-aulario-select" data-row="<?php echo $idx; ?>"> <select name="linked_aulario[]" class="form-select linked-aulario-select" data-row="<?php echo $idx; ?>">
<option value="">-- Seleccionar aulario origen --</option> <option value="">-- Seleccionar aulario origen --</option>
<?php foreach ($available_aularios as $aul_id => $aul_name): ?> <?php foreach ($available_aularios as $aul_id => $aul_name): ?>
@@ -208,7 +211,7 @@ switch ($_GET["action"]) {
<?php endforeach; ?> <?php endforeach; ?>
</select> </select>
</div> </div>
<div class="col-md-5"> <div class="col-md-3">
<select name="linked_project_id[]" class="form-select linked-project-select" data-row="<?php echo $idx; ?>"> <select name="linked_project_id[]" class="form-select linked-project-select" data-row="<?php echo $idx; ?>">
<option value="">-- Seleccionar proyecto --</option> <option value="">-- Seleccionar proyecto --</option>
<?php if (!empty($source_aul) && isset($available_projects_by_aulario[$source_aul])): ?> <?php if (!empty($source_aul) && isset($available_projects_by_aulario[$source_aul])): ?>
@@ -221,6 +224,13 @@ switch ($_GET["action"]) {
<?php endif; ?> <?php endif; ?>
</select> </select>
</div> </div>
<div class="col-md-3">
<select name="linked_permission[]" class="form-select">
<option value="read_only" <?php echo $permission === 'read_only' ? 'selected' : ''; ?>>Solo lectura</option>
<option value="request_edit" <?php echo $permission === 'request_edit' ? 'selected' : ''; ?>>Solicitar permiso para cambiar</option>
<option value="full_edit" <?php echo $permission === 'full_edit' ? 'selected' : ''; ?>>Cambiar sin solicitar</option>
</select>
</div>
<div class="col-md-2"> <div class="col-md-2">
<button type="button" class="btn btn-danger remove-link-btn" onclick="removeLinkedProject(this)">Eliminar</button> <button type="button" class="btn btn-danger remove-link-btn" onclick="removeLinkedProject(this)">Eliminar</button>
</div> </div>
@@ -240,7 +250,7 @@ switch ($_GET["action"]) {
const newRow = document.createElement('div'); const newRow = document.createElement('div');
newRow.className = 'row mb-2 linked-project-row'; newRow.className = 'row mb-2 linked-project-row';
newRow.innerHTML = ` newRow.innerHTML = `
<div class="col-md-5"> <div class="col-md-4">
<select name="linked_aulario[]" class="form-select linked-aulario-select" data-row="${rowCounter}"> <select name="linked_aulario[]" class="form-select linked-aulario-select" data-row="${rowCounter}">
<option value="">-- Seleccionar aulario origen --</option> <option value="">-- Seleccionar aulario origen --</option>
<?php foreach ($available_aularios as $aul_id => $aul_name): ?> <?php foreach ($available_aularios as $aul_id => $aul_name): ?>
@@ -250,11 +260,18 @@ switch ($_GET["action"]) {
<?php endforeach; ?> <?php endforeach; ?>
</select> </select>
</div> </div>
<div class="col-md-5"> <div class="col-md-3">
<select name="linked_project_id[]" class="form-select linked-project-select" data-row="${rowCounter}"> <select name="linked_project_id[]" class="form-select linked-project-select" data-row="${rowCounter}">
<option value="">-- Seleccionar proyecto --</option> <option value="">-- Seleccionar proyecto --</option>
</select> </select>
</div> </div>
<div class="col-md-3">
<select name="linked_permission[]" class="form-select">
<option value="read_only">Solo lectura</option>
<option value="request_edit">Solicitar permiso para cambiar</option>
<option value="full_edit">Cambiar sin solicitar</option>
</select>
</div>
<div class="col-md-2"> <div class="col-md-2">
<button type="button" class="btn btn-danger remove-link-btn" onclick="removeLinkedProject(this)">Eliminar</button> <button type="button" class="btn btn-danger remove-link-btn" onclick="removeLinkedProject(this)">Eliminar</button>
</div> </div>