OneBot: Leantime 改造版源码(BOM/Univer 表格/AI 接管/品牌替换等)
This commit is contained in:
85
app/Domain/Files/Controllers/Browse.php
Normal file
85
app/Domain/Files/Controllers/Browse.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace Leantime\Domain\Files\Controllers;
|
||||
|
||||
use Leantime\Core\Auth\Permissions\RequiresPermission;
|
||||
use Leantime\Core\Controller\Controller;
|
||||
use Leantime\Core\Controller\Frontcontroller;
|
||||
use Leantime\Domain\Files\Permissions\FilesPermissions;
|
||||
use Leantime\Domain\Files\Services\Files as FileService;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class Browse extends Controller
|
||||
{
|
||||
private FileService $filesService;
|
||||
|
||||
/**
|
||||
* Initializes dependencies.
|
||||
*/
|
||||
public function init(
|
||||
FileService $filesService
|
||||
): void {
|
||||
$this->filesService = $filesService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the file browser.
|
||||
*
|
||||
* @param array $params Request parameters
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
#[RequiresPermission(FilesPermissions::VIEW)]
|
||||
public function get(array $params): Response
|
||||
{
|
||||
$this->assignTemplateVars();
|
||||
|
||||
return $this->tpl->display('files.browse');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles file uploads and deletions via POST.
|
||||
*
|
||||
* @param array $params Request parameters
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
#[RequiresPermission(FilesPermissions::VIEW)]
|
||||
public function post(array $params): Response
|
||||
{
|
||||
$result = $this->filesService->handleFileAction($_POST, $_FILES, 'project', session('currentProject'));
|
||||
|
||||
if ($result['action'] === 'delete') {
|
||||
if ($result['success'] === true) {
|
||||
$this->tpl->setNotification($this->language->__('notifications.file_deleted'), 'success', 'file_deleted');
|
||||
|
||||
return Frontcontroller::redirect(BASE_URL.'/files/showAll'.(($_GET['modalPopUp'] ?? '') ? '?modalPopUp=true' : ''));
|
||||
}
|
||||
|
||||
$this->tpl->setNotification($this->language->__('notifications.file_deleted_error'), 'error');
|
||||
}
|
||||
|
||||
if ($result['action'] === 'upload') {
|
||||
if ($result['success'] === true) {
|
||||
$this->tpl->setNotification('notifications.file_upload_success', 'success', 'file_created');
|
||||
} else {
|
||||
$this->tpl->setNotification('notifications.file_upload_error', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
$this->assignTemplateVars();
|
||||
|
||||
return $this->tpl->display('files.browse');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns common template variables.
|
||||
*/
|
||||
private function assignTemplateVars(): void
|
||||
{
|
||||
$this->tpl->assign('currentModule', session('currentProject'));
|
||||
$this->tpl->assign('modules', $this->filesService->getModules(session('userdata.id')));
|
||||
$this->tpl->assign('imgExtensions', $this->filesService->getImageExtensions());
|
||||
$this->tpl->assign('files', $this->filesService->getFilesByModule('project', session('currentProject')));
|
||||
}
|
||||
}
|
||||
44
app/Domain/Files/Controllers/Get.php
Normal file
44
app/Domain/Files/Controllers/Get.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Leantime\Domain\Files\Controllers;
|
||||
|
||||
use Leantime\Core\Controller\Controller;
|
||||
use Leantime\Domain\Files\Services\Files as FileService;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class Get extends Controller
|
||||
{
|
||||
private FileService $filesService;
|
||||
|
||||
/**
|
||||
* Initializes the controller with required dependencies.
|
||||
*
|
||||
* @param FileService $filesService The file service for retrieval and authorization.
|
||||
*/
|
||||
public function init(FileService $filesService): void
|
||||
{
|
||||
$this->filesService = $filesService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles GET requests to download/view a file.
|
||||
*
|
||||
* Validates that the current user has access to the project the file belongs to
|
||||
* before serving the file content.
|
||||
*
|
||||
* @return Response The file content response, 403 if unauthorized, or 404 if not found.
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function get(): Response
|
||||
{
|
||||
$rawEncName = $_GET['encName'] ?? '';
|
||||
$encName = preg_replace('/[^a-zA-Z0-9]+/', '', $rawEncName);
|
||||
|
||||
if (empty($encName)) {
|
||||
return new Response('Bad request', 400);
|
||||
}
|
||||
|
||||
return $this->filesService->getFileForUser($encName, (int) session('userdata.id'));
|
||||
}
|
||||
}
|
||||
90
app/Domain/Files/Controllers/ShowAll.php
Normal file
90
app/Domain/Files/Controllers/ShowAll.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace Leantime\Domain\Files\Controllers;
|
||||
|
||||
use Illuminate\Contracts\Container\BindingResolutionException;
|
||||
use Leantime\Core\Auth\Permissions\RequiresPermission;
|
||||
use Leantime\Core\Controller\Controller;
|
||||
use Leantime\Core\Controller\Frontcontroller;
|
||||
use Leantime\Domain\Files\Permissions\FilesPermissions;
|
||||
use Leantime\Domain\Files\Services\Files as FileService;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class ShowAll extends Controller
|
||||
{
|
||||
private FileService $filesService;
|
||||
|
||||
/**
|
||||
* Initializes dependencies.
|
||||
*/
|
||||
public function init(
|
||||
FileService $filesService
|
||||
): void {
|
||||
$this->filesService = $filesService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays all project files.
|
||||
*
|
||||
* @param array $params Request parameters
|
||||
*
|
||||
* @throws BindingResolutionException
|
||||
*/
|
||||
#[RequiresPermission(FilesPermissions::VIEW)]
|
||||
public function get(array $params): Response
|
||||
{
|
||||
$currentModule = $params['id'] ?? $_GET['id'] ?? '';
|
||||
|
||||
$this->assignTemplateVars($currentModule);
|
||||
|
||||
return $this->tpl->displayPartial('files.showAll');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles file uploads and deletions via POST.
|
||||
*
|
||||
* @param array $params Request parameters
|
||||
*
|
||||
* @throws BindingResolutionException
|
||||
*/
|
||||
#[RequiresPermission(FilesPermissions::VIEW)]
|
||||
public function post(array $params): Response
|
||||
{
|
||||
$currentModule = $params['id'] ?? $_GET['id'] ?? '';
|
||||
|
||||
$result = $this->filesService->handleFileAction($_POST, $_FILES, 'project', session('currentProject'));
|
||||
|
||||
if ($result['action'] === 'delete') {
|
||||
if ($result['success'] === true) {
|
||||
$this->tpl->setNotification($this->language->__('notifications.file_deleted'), 'success', 'file_deleted');
|
||||
|
||||
return Frontcontroller::redirect(BASE_URL.'/files/showAll'.(($_GET['modalPopUp'] ?? '') ? '?modalPopUp=true' : ''));
|
||||
}
|
||||
|
||||
$this->tpl->setNotification($this->language->__('notifications.file_deleted_error'), 'error');
|
||||
}
|
||||
|
||||
if ($result['action'] === 'upload') {
|
||||
if ($result['success'] === true) {
|
||||
$this->tpl->setNotification('notifications.file_upload_success', 'success', 'file_uploaded');
|
||||
} else {
|
||||
$this->tpl->setNotification('notifications.file_upload_error', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
$this->assignTemplateVars($currentModule);
|
||||
|
||||
return $this->tpl->displayPartial('files.showAll');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns common template variables.
|
||||
*/
|
||||
private function assignTemplateVars(string $currentModule): void
|
||||
{
|
||||
$this->tpl->assign('currentModule', $currentModule);
|
||||
$this->tpl->assign('modules', $this->filesService->getModules(session('userdata.id')));
|
||||
$this->tpl->assign('imgExtensions', $this->filesService->getImageExtensions());
|
||||
$this->tpl->assign('files', $this->filesService->getFilesByModule('project', session('currentProject'), session('userdata.id')));
|
||||
}
|
||||
}
|
||||
58
app/Domain/Files/Controllers/Upload.php
Normal file
58
app/Domain/Files/Controllers/Upload.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Leantime\Domain\Files\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Leantime\Domain\Files\Services\Files as FileService;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* Handles multipart file uploads (editor image paste/drop, Uppy file manager).
|
||||
*
|
||||
* A native Laravel controller (constructor DI, route-bound action). Relocated from the
|
||||
* retired Api\Controllers\Files. Bound in Files/routes.php at the canonical /files/upload
|
||||
* plus the backward-compatible /api/files alias used by Tiptap and Uppy. The dead
|
||||
* paste-fallback branch, the unrelated PATCH (user-settings) handler and the 501 stubs
|
||||
* from the old controller are intentionally not carried over.
|
||||
*
|
||||
* The success response MUST stay the raw upload() metadata array — Tiptap reads
|
||||
* data.module/encName/extension/realName and Uppy reads the same off response.body.
|
||||
*/
|
||||
class Upload
|
||||
{
|
||||
public function __construct(private FileService $fileService) {}
|
||||
|
||||
/**
|
||||
* POST — store an uploaded file against a module/moduleId (both from the query string;
|
||||
* the file is the multipart field "file"). Returns the upload() metadata array as JSON.
|
||||
*/
|
||||
public function post(Request $request): Response
|
||||
{
|
||||
$module = $request->query('module');
|
||||
$moduleId = $request->query('moduleId');
|
||||
|
||||
// Missing required parts is a client error, not a server fault.
|
||||
if (! isset($_FILES['file']) || $module === null || $moduleId === null) {
|
||||
return response()->json(['status' => 'error', 'message' => 'Missing file, module or moduleId'], 400);
|
||||
}
|
||||
|
||||
$module = htmlentities($module);
|
||||
$id = (int) $moduleId;
|
||||
|
||||
// The legacy endpoint had no project gate: a logged-in user could attach files to
|
||||
// any module/moduleId by tampering with the query string. Authorize against the
|
||||
// target's project (admins/owners bypass; modules with no project mapping fall back
|
||||
// to the read-path behaviour in Files::getFileForUser()).
|
||||
if (! $this->fileService->userCanUploadToModule($module, $id)) {
|
||||
return response()->json(['status' => 'unauthorized'], 403);
|
||||
}
|
||||
|
||||
$result = $this->fileService->upload($_FILES, $module, $id);
|
||||
|
||||
if (is_string($result)) {
|
||||
return response()->json(['status' => 'error', 'message' => $result], 500);
|
||||
}
|
||||
|
||||
return response()->json($result);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user