Enable pricing (#151)

* Enable Pro plan - WIP

* no pricing page if have no paid plans

* Set pricing ids in env

* views & submissions FREE for all

* extra param for env

* form password FREE for all

* Custom Code is PRO feature

* Replace codeinput prism with codemirror

* Better form Cleaning message

* Added risky user email spam protection

* fix form cleaning

* Pricing page new UI

* form cleaner

* Polish changes

* Fixed tests

---------

Co-authored-by: Julien Nahum <julien@nahum.net>
This commit is contained in:
formsdev
2023-08-30 13:28:29 +05:30
committed by GitHub
parent 29b153bd76
commit fb79a5bf3e
48 changed files with 1011 additions and 269 deletions

View File

@@ -11,7 +11,6 @@ use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Stevebauman\Purify\Facades\Purify;
use function App\Service\str_starts_with;
use function collect;
class FormCleaner
@@ -26,76 +25,34 @@ class FormCleaner
private array $formDefaults = [
'notifies' => false,
'color' => '#3B82F6',
'hide_title' => false,
'no_branding' => false,
'transparent_background' => false,
'uppercase_labels' => true,
'webhook_url' => null,
'cover_picture' => null,
'logo_picture' => null,
'database_fields_update' => null,
'theme' => 'default',
'use_captcha' => false,
'password' => null,
'slack_webhook_url' => null,
'discord_webhook_url' => null,
'editable_submissions' => false,
'custom_code' => null,
];
private array $fieldDefaults = [
// 'name' => '' TODO: prevent name changing, use alias for column and keep original name as it is
'hide_field_name' => false,
'prefill' => null,
'placeholder' => null,
'help' => null,
'file_upload' => false,
'with_time' => null,
'width' => 'full',
'generates_uuid' => false,
'generates_auto_increment_id' => false,
'logic' => null,
'allow_creation' => false
];
private array $cleaningMessages = [
// For form
'notifies' => "Email notification were disabled.",
'color' => "Form color set to default blue.",
'hide_title' => "Title is not hidden.",
'no_branding' => "OpenForm branding is not hidden.",
'transparent_background' => "Transparent background was disabled.",
'uppercase_labels' => "Labels use uppercase letters",
'webhook_url' => "Webhook disabled.",
'cover_picture' => 'The cover picture was removed.',
'logo_picture' => 'The logo was removed.',
'database_fields_update' => 'Form submission will only create new records (no updates).',
'theme' => 'Default theme was applied.',
'slack_webhook_url' => "Slack webhook disabled.",
'discord_webhook_url' => "Discord webhook disabled.",
'editable_submissions' => 'Users will not be able to edit their submissions.',
'custom_code' => 'Custom code was disabled',
// For fields
'hide_field_name' => 'Hide field name removed.',
'prefill' => "Field prefill removed.",
'placeholder' => "Empty text (placeholder) removed",
'help' => "Help text removed.",
'file_upload' => "Link field is not a file upload.",
'with_time' => "Time was removed from date input.",
'custom_block' => 'The custom block was removed.',
'files' => 'The file upload file was hidden.',
'relation' => 'The relation file was hidden.',
'width' => 'The field width was set to full width',
'allow_creation' => 'Select option creation was disabled.',
// Advanced fields
'generates_uuid' => 'ID generation disabled.',
'generates_auto_increment_id' => 'ID generation disabled.',
'use_captcha' => 'Captcha form protection was disabled.',
// Security & Privacy
'password' => 'Password protection was disabled',
'logic' => 'Logic disabled for this property'
];
/**
@@ -144,7 +101,8 @@ class FormCleaner
/**
* Create form cleaner instance from existing form
*/
public function processForm(Request $request, Form $form) : FormCleaner {
public function processForm(Request $request, Form $form) : FormCleaner
{
$data = (new FormResource($form))->toArray($request);
$this->data = $this->commonCleaning($data);
@@ -159,10 +117,11 @@ class FormCleaner
* Dry run celanings
* @param User|null $user
*/
public function simulateCleaning(Workspace $workspace): FormCleaner {
if($this->isPro($workspace)) return $this;
$this->data = $this->removeProFeatures($this->data, true);
public function simulateCleaning(Workspace $workspace): FormCleaner
{
if (!$this->isPro($workspace)) {
$this->data = $this->removeProFeatures($this->data, true);
}
return $this;
}
@@ -174,9 +133,9 @@ class FormCleaner
*/
public function performCleaning(Workspace $workspace): FormCleaner
{
if($this->isPro($workspace)) return $this;
$this->data = $this->removeProFeatures($this->data);
if (!$this->isPro($workspace)) {
$this->data = $this->removeProFeatures($this->data);
}
return $this;
}
@@ -212,6 +171,7 @@ class FormCleaner
private function cleanProperties(array &$data, $simulation = false): void
{
foreach ($data['properties'] as $key => &$property) {
/*
// Remove pro custom blocks
if (\Str::of($property['type'])->startsWith('nf-')) {
$this->cleanings[$property['name']][] = 'custom_block';
@@ -221,6 +181,15 @@ class FormCleaner
continue;
}
// Remove logic
if (($property['logic']['conditions'] ?? null) != null || ($property['logic']['actions'] ?? []) != []) {
$this->cleanings[$property['name']][] = 'logic';
if (!$simulation) {
unset($data['properties'][$key]['logic']);
}
}
*/
// Clean pro field options
$this->cleanField($property, $this->fieldDefaults, $simulation);
}
@@ -229,8 +198,18 @@ class FormCleaner
private function clean(array &$data, array $defaults, $simulation = false): void
{
foreach ($defaults as $key => $value) {
if (Arr::get($data, $key) !== $value) {
if (!isset($this->cleanings['form'])) $this->cleanings['form'] = [];
// Get value from form
$formVal = Arr::get($data, $key);
// Transform boolean values
$formVal = (($formVal === 0 || $formVal === "0") ? false : $formVal);
$formVal = (($formVal === 1 || $formVal === "1") ? true : $formVal);
if (!is_null($formVal) && $formVal !== $value) {
if (!isset($this->cleanings['form'])) {
$this->cleanings['form'] = [];
}
$this->cleanings['form'][] = $key;
// If not a simulation, do the cleaning
@@ -253,14 +232,14 @@ class FormCleaner
}
// Remove pro types columns
foreach (['files'] as $proType) {
/*foreach (['files'] as $proType) {
if ($data['type'] == $proType && (!isset($data['hidden']) || !$data['hidden'])) {
$this->cleanings[$data['name']][] = $proType;
if (!$simulation) {
$data['hidden'] = true;
}
}
}
}*/
}
}