opnform-host-nginx/api/app/Http/Controllers/Forms/FormController.php

288 lines
9.3 KiB
PHP
Raw Normal View History

2022-09-20 21:59:52 +02:00
<?php
namespace App\Http\Controllers\Forms;
use App\Http\Controllers\Controller;
use App\Http\Requests\StoreFormRequest;
use App\Http\Requests\UpdateFormRequest;
use App\Http\Requests\UploadAssetRequest;
use App\Http\Resources\FormResource;
use App\Models\Forms\Form;
use App\Models\Workspace;
use App\Notifications\Forms\MobileEditorEmail;
2022-09-20 21:59:52 +02:00
use App\Service\Forms\FormCleaner;
use App\Service\Storage\StorageFileNameParser;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class FormController extends Controller
{
2024-02-23 11:54:12 +01:00
public const ASSETS_UPLOAD_PATH = 'assets/forms';
2022-09-20 21:59:52 +02:00
private FormCleaner $formCleaner;
public function __construct()
{
$this->middleware('auth', ['except' => ['uploadAsset']]);
2022-09-20 21:59:52 +02:00
$this->formCleaner = new FormCleaner();
}
public function index($workspaceId)
{
$workspace = Workspace::findOrFail($workspaceId);
$this->authorize('view', $workspace);
$this->authorize('viewAny', Form::class);
$workspaceIsPro = $workspace->is_pro;
$forms = $workspace->forms()
->orderByDesc('updated_at')
2024-02-23 11:54:12 +01:00
->paginate(10)->through(function (Form $form) use ($workspace, $workspaceIsPro) {
// Add attributes for faster loading
$form->extra = (object) [
'loadedWorkspace' => $workspace,
'workspaceIsPro' => $workspaceIsPro,
'userIsOwner' => true,
'cleanings' => $this->formCleaner
->processForm(request(), $form)
->simulateCleaning($workspace)
->getPerformedCleanings(),
];
return $form;
});
return FormResource::collection($forms);
2022-09-20 21:59:52 +02:00
}
public function show($slug)
{
$form = Form::whereSlug($slug)->firstOrFail();
$this->authorize('view', $form);
// Add attributes for faster loading
$workspace = $form->workspace;
$form->extra = (object)[
'loadedWorkspace' => $workspace,
'workspaceIsPro' => $workspace->is_pro,
'userIsOwner' => true,
'cleanings' => $this->formCleaner
->processForm(request(), $form)
->simulateCleaning($workspace)
->getPerformedCleanings(),
];
return new FormResource($form);
}
2022-09-20 21:59:52 +02:00
/**
* Return all user forms, used for zapier
2024-02-23 11:54:12 +01:00
*
2022-09-20 21:59:52 +02:00
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function indexAll()
{
$forms = collect();
foreach (Auth::user()->workspaces as $workspace) {
$this->authorize('view', $workspace);
$this->authorize('viewAny', Form::class);
$workspaceIsPro = $workspace->is_pro;
2024-02-23 11:54:12 +01:00
$newForms = $workspace->forms()->get()->map(function (Form $form) use ($workspace, $workspaceIsPro) {
// Add attributes for faster loading
$form->extra = (object) [
'loadedWorkspace' => $workspace,
'workspaceIsPro' => $workspaceIsPro,
'userIsOwner' => true,
];
2024-02-23 11:54:12 +01:00
return $form;
});
$forms = $forms->merge($newForms);
2022-09-20 21:59:52 +02:00
}
2024-02-23 11:54:12 +01:00
2022-09-20 21:59:52 +02:00
return FormResource::collection($forms);
}
public function store(StoreFormRequest $request)
{
$workspace = Workspace::findOrFail($request->get('workspace_id'));
$this->authorize('view', $workspace);
Readonly User (#637) * Readonly User * Refactor FormPolicy and TemplatePolicy to centralize write operation logic - Introduced a private method `canPerformWriteOperation` in both FormPolicy and TemplatePolicy to encapsulate the logic for determining if a user can perform write operations on the respective models. - Updated the `update`, `delete`, `restore`, and `forceDelete` methods in FormPolicy to use the new method for improved readability and maintainability. - Simplified the `update` and `delete` methods in TemplatePolicy to leverage the centralized write operation logic. This refactoring enhances code clarity and reduces duplication across policy classes. * Refactor user and workspace permissions handling - Updated FormController to authorize form creation based on workspace context. - Removed the `is_readonly` attribute from UserResource and integrated it into WorkspaceResource for better encapsulation. - Refactored User model to eliminate the `getIsReadonlyAttribute` method, shifting readonly logic to the Workspace model. - Adjusted FormPolicy and TemplatePolicy to utilize workspace readonly checks for user permissions. - Updated various frontend components to reference workspace readonly status instead of user readonly status, enhancing clarity and consistency in permission handling. These changes improve the management of user permissions in relation to workspaces, ensuring a more robust and maintainable authorization system. * Fix isReadonlyUser * fix pint --------- Co-authored-by: Julien Nahum <julien@nahum.net>
2024-12-30 14:35:23 +01:00
$this->authorize('create', [Form::class, $workspace]);
2022-09-20 21:59:52 +02:00
$formData = $this->formCleaner
->processRequest($request)
->simulateCleaning($workspace)
->getData();
$form = Form::create(array_merge($formData, [
2024-02-23 11:54:12 +01:00
'creator_id' => $request->user()->id,
2022-09-20 21:59:52 +02:00
]));
if ($this->formCleaner->hasCleaned()) {
$formStatus = $form->workspace->is_trialing ? 'Non-trial' : 'Pro';
$message = 'Form successfully created, but the ' . $formStatus . ' features you used will be disabled when sharing your form:';
} else {
$message = 'Form created.';
}
2022-09-20 21:59:52 +02:00
return $this->success([
'message' => $message . ($form->visibility == 'draft' ? ' But other people won\'t be able to see the form since it\'s currently in draft mode' : ''),
'form' => (new FormResource($form))->setCleanings($this->formCleaner->getPerformedCleanings()),
2024-02-23 11:54:12 +01:00
'users_first_form' => $request->user()->forms()->count() == 1,
2022-09-20 21:59:52 +02:00
]);
}
public function update(UpdateFormRequest $request, string $id)
{
$form = Form::findOrFail($id);
$this->authorize('update', $form);
$formData = $this->formCleaner
->processRequest($request)
->simulateCleaning($form->workspace)
->getData();
2023-10-13 11:43:53 +02:00
2022-09-20 21:59:52 +02:00
// Set Removed Properties
$formData['removed_properties'] = array_merge($form->removed_properties, collect($form->properties)->filter(function ($field) use ($formData) {
return !Str::of($field['type'])->startsWith('nf-') && !in_array($field['id'], collect($formData['properties'])->pluck('id')->toArray());
2022-09-20 21:59:52 +02:00
})->toArray());
$form->update($formData);
if ($this->formCleaner->hasCleaned()) {
$formSubscription = $form->is_pro ? 'Enterprise' : 'Pro';
$formStatus = $form->workspace->is_trialing ? 'Non-trial' : $formSubscription;
$message = 'Form successfully updated, but the ' . $formStatus . ' features you used will be disabled when sharing your form.';
} else {
$message = 'Form updated.';
}
2022-09-20 21:59:52 +02:00
return $this->success([
'message' => $message . ($form->visibility == 'draft' ? ' But other people won\'t be able to see the form since it\'s currently in draft mode' : ''),
'form' => (new FormResource($form))->setCleanings($this->formCleaner->getPerformedCleanings()),
2022-09-20 21:59:52 +02:00
]);
}
public function destroy($id)
{
$form = Form::findOrFail($id);
$this->authorize('delete', $form);
$form->delete();
2024-02-23 11:54:12 +01:00
2022-09-20 21:59:52 +02:00
return $this->success([
2024-02-23 11:54:12 +01:00
'message' => 'Form was deleted.',
2022-09-20 21:59:52 +02:00
]);
}
public function duplicate($id)
{
$form = Form::findOrFail($id);
$this->authorize('update', $form);
// Create copy
$formCopy = $form->replicate();
$formCopy->title = 'Copy of ' . $formCopy->title;
$formCopy->removed_properties = [];
2022-09-20 21:59:52 +02:00
$formCopy->save();
return $this->success([
'message' => 'Form successfully duplicated. You are now editing the duplicated version of the form.',
2024-02-23 11:54:12 +01:00
'new_form' => new FormResource($formCopy),
2022-09-20 21:59:52 +02:00
]);
}
public function regenerateLink($id, $option)
{
$form = Form::findOrFail($id);
$this->authorize('update', $form);
2024-02-23 11:54:12 +01:00
if ($option == 'slug') {
2022-09-20 21:59:52 +02:00
$form->generateSlug();
} elseif ($option == 'uuid') {
$form->slug = Str::uuid();
}
$form->save();
return $this->success([
'message' => 'Form url successfully updated. Your new form url now is: ' . $form->share_url . '.',
2024-02-23 11:54:12 +01:00
'form' => new FormResource($form),
2022-09-20 21:59:52 +02:00
]);
}
/**
* Upload a form asset
*/
public function uploadAsset(UploadAssetRequest $request)
{
$fileNameParser = StorageFileNameParser::parse($request->url);
// Make sure we retrieve the file in tmp storage, move it to persistent
$fileName = PublicFormController::TMP_FILE_UPLOAD_PATH . '/' . $fileNameParser->uuid;
if (!Storage::exists($fileName)) {
2022-09-20 21:59:52 +02:00
// File not found, we skip
return null;
}
$newPath = self::ASSETS_UPLOAD_PATH . '/' . $fileNameParser->getMovedFileName();
Storage::move($fileName, $newPath);
2022-09-20 21:59:52 +02:00
return $this->success([
'message' => 'File uploaded.',
2024-02-23 11:54:12 +01:00
'url' => route('forms.assets.show', [$fileNameParser->getMovedFileName()]),
2022-09-20 21:59:52 +02:00
]);
}
/**
* File uploads retrieval
*/
public function viewFile($id, $fileName)
{
$form = Form::findOrFail($id);
$this->authorize('view', $form);
$path = Str::of(PublicFormController::FILE_UPLOAD_PATH)->replace('?', $form->id) . '/' . $fileName;
if (!Storage::exists($path)) {
2022-09-20 21:59:52 +02:00
return $this->error([
2024-02-23 11:54:12 +01:00
'message' => 'File not found.',
2022-09-20 21:59:52 +02:00
]);
}
return redirect()->to(Storage::temporaryUrl($path, now()->addMinutes(5)));
2022-09-20 21:59:52 +02:00
}
/**
* Updates a form's workspace
*/
public function updateWorkspace($id, $workspace_id)
{
$form = Form::findOrFail($id);
$workspace = Workspace::findOrFail($workspace_id);
$this->authorize('update', $form);
$this->authorize('view', $workspace);
$form->workspace_id = $workspace_id;
$form->creator_id = auth()->user()->id;
$form->save();
return $this->success([
'message' => 'Form workspace updated successfully.',
]);
}
public function mobileEditorEmail($id)
{
$form = Form::findOrFail($id);
$this->authorize('update', $form);
$form->creator->notify(new MobileEditorEmail($form->slug));
return $this->success([
'message' => 'Email sent.',
]);
}
2022-09-20 21:59:52 +02:00
}