feat: disable custom script for trial users (#371)
* feat: disable custom script for trial users * fix: logic error for trial users --------- Co-authored-by: Julien Nahum <julien@nahum.net>
This commit is contained in:
parent
75c2107b6c
commit
8d35fc8b1a
|
|
@ -121,8 +121,15 @@ class FormController extends Controller
|
||||||
'creator_id' => $request->user()->id,
|
'creator_id' => $request->user()->id,
|
||||||
]));
|
]));
|
||||||
|
|
||||||
|
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.';
|
||||||
|
}
|
||||||
|
|
||||||
return $this->success([
|
return $this->success([
|
||||||
'message' => $this->formCleaner->hasCleaned() ? 'Form successfully created, but the Pro features you used will be disabled when sharing your form:' : 'Form created.' . ($form->visibility == 'draft' ? ' But other people won\'t be able to see the form since it\'s currently in draft mode' : ''),
|
'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()),
|
'form' => (new FormResource($form))->setCleanings($this->formCleaner->getPerformedCleanings()),
|
||||||
'users_first_form' => $request->user()->forms()->count() == 1,
|
'users_first_form' => $request->user()->forms()->count() == 1,
|
||||||
]);
|
]);
|
||||||
|
|
@ -145,8 +152,16 @@ class FormController extends Controller
|
||||||
|
|
||||||
$form->update($formData);
|
$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.';
|
||||||
|
}
|
||||||
|
|
||||||
return $this->success([
|
return $this->success([
|
||||||
'message' => $this->formCleaner->hasCleaned() ? 'Form successfully updated, but the Pro features you used will be disabled when sharing your form:' : 'Form updated.' . ($form->visibility == 'draft' ? ' But other people won\'t be able to see the form since it\'s currently in draft mode' : ''),
|
'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()),
|
'form' => (new FormResource($form))->setCleanings($this->formCleaner->getPerformedCleanings()),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ class FormResource extends JsonResource
|
||||||
|
|
||||||
return array_merge(parent::toArray($request), $ownerData, [
|
return array_merge(parent::toArray($request), $ownerData, [
|
||||||
'is_pro' => $this->workspaceIsPro(),
|
'is_pro' => $this->workspaceIsPro(),
|
||||||
|
'is_trialing' => $this->workspaceIsTrialing(),
|
||||||
'workspace_id' => $this->workspace_id,
|
'workspace_id' => $this->workspace_id,
|
||||||
'workspace' => new WorkspaceResource($this->getWorkspace()),
|
'workspace' => new WorkspaceResource($this->getWorkspace()),
|
||||||
'is_closed' => $this->is_closed,
|
'is_closed' => $this->is_closed,
|
||||||
|
|
@ -92,6 +93,11 @@ class FormResource extends JsonResource
|
||||||
return $this->extra?->workspaceIsPro ?? $this->getWorkspace()->is_pro ?? $this->is_pro;
|
return $this->extra?->workspaceIsPro ?? $this->getWorkspace()->is_pro ?? $this->is_pro;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function workspaceIsTrialing()
|
||||||
|
{
|
||||||
|
return $this->getWorkspace()->is_trialing;
|
||||||
|
}
|
||||||
|
|
||||||
private function userIsFormOwner()
|
private function userIsFormOwner()
|
||||||
{
|
{
|
||||||
return $this->extra?->userIsOwner ??
|
return $this->extra?->userIsOwner ??
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ class Workspace extends Model implements CachableAttributes
|
||||||
|
|
||||||
protected $appends = [
|
protected $appends = [
|
||||||
'is_pro',
|
'is_pro',
|
||||||
|
'is_trialing',
|
||||||
'is_enterprise',
|
'is_enterprise',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -107,6 +108,24 @@ class Workspace extends Model implements CachableAttributes
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getIsTrialingAttribute()
|
||||||
|
{
|
||||||
|
if (is_null(config('cashier.key'))) {
|
||||||
|
return false; // If no paid plan so FALSE for ALL
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->remember('is_trialing', 15 * 60, function (): bool {
|
||||||
|
// Make sure at least one owner is pro
|
||||||
|
foreach ($this->owners as $owner) {
|
||||||
|
if ($owner->onTrial()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public function getIsEnterpriseAttribute()
|
public function getIsEnterpriseAttribute()
|
||||||
{
|
{
|
||||||
if (is_null(config('cashier.key'))) {
|
if (is_null(config('cashier.key'))) {
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,10 @@ class FormCleaner
|
||||||
'seo_meta' => [],
|
'seo_meta' => [],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
private array $formNonTrialingDefaults = [
|
||||||
|
'custom_code' => null,
|
||||||
|
];
|
||||||
|
|
||||||
private array $fieldDefaults = [
|
private array $fieldDefaults = [
|
||||||
// 'name' => '' TODO: prevent name changing, use alias for column and keep original name as it is
|
// 'name' => '' TODO: prevent name changing, use alias for column and keep original name as it is
|
||||||
'file_upload' => false,
|
'file_upload' => false,
|
||||||
|
|
@ -111,6 +115,10 @@ class FormCleaner
|
||||||
return $workspace->is_pro;
|
return $workspace->is_pro;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function isTrialing(Workspace $workspace)
|
||||||
|
{
|
||||||
|
return $workspace->is_trialing;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Dry run celanings
|
* Dry run celanings
|
||||||
*
|
*
|
||||||
|
|
@ -118,6 +126,10 @@ class FormCleaner
|
||||||
*/
|
*/
|
||||||
public function simulateCleaning(Workspace $workspace): FormCleaner
|
public function simulateCleaning(Workspace $workspace): FormCleaner
|
||||||
{
|
{
|
||||||
|
if ($this->isTrialing($workspace)) {
|
||||||
|
$this->data = $this->removeNonTrialingFeatures($this->data, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (!$this->isPro($workspace)) {
|
if (!$this->isPro($workspace)) {
|
||||||
$this->data = $this->removeProFeatures($this->data, true);
|
$this->data = $this->removeProFeatures($this->data, true);
|
||||||
}
|
}
|
||||||
|
|
@ -133,6 +145,10 @@ class FormCleaner
|
||||||
*/
|
*/
|
||||||
public function performCleaning(Workspace $workspace): FormCleaner
|
public function performCleaning(Workspace $workspace): FormCleaner
|
||||||
{
|
{
|
||||||
|
if ($this->isTrialing($workspace)) {
|
||||||
|
$this->data = $this->removeNonTrialingFeatures($this->data, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (!$this->isPro($workspace)) {
|
if (!$this->isPro($workspace)) {
|
||||||
$this->data = $this->removeProFeatures($this->data);
|
$this->data = $this->removeProFeatures($this->data);
|
||||||
}
|
}
|
||||||
|
|
@ -155,6 +171,12 @@ class FormCleaner
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function removeNonTrialingFeatures(array $data, $simulation = false)
|
||||||
|
{
|
||||||
|
$this->clean($data, $this->formNonTrialingDefaults);
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
private function removeProFeatures(array $data, $simulation = false)
|
private function removeProFeatures(array $data, $simulation = false)
|
||||||
{
|
{
|
||||||
$this->cleanForm($data, $simulation);
|
$this->cleanForm($data, $simulation);
|
||||||
|
|
|
||||||
|
|
@ -168,3 +168,26 @@ it('can create form with dark mode', function () {
|
||||||
->etc();
|
->etc();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('can create form with custom scripts', function () {
|
||||||
|
$user = $this->actingAsTrialingUser();
|
||||||
|
$workspace = $this->createUserWorkspace($user);
|
||||||
|
$form = $this->createForm($user, $workspace, [
|
||||||
|
'custom_code' => "<script>console.log('Hello')</script>",
|
||||||
|
]);
|
||||||
|
$formData = (new \App\Http\Resources\FormResource($form))->toArray(request());
|
||||||
|
$this->postJson(route('open.forms.store', $formData))
|
||||||
|
->assertSuccessful()
|
||||||
|
->assertJson([
|
||||||
|
'type' => 'success',
|
||||||
|
'message' => 'Form successfully created, but the Non-trial features you used will be disabled when sharing your form:',
|
||||||
|
'form' => ['custom_code' => null]
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->getJson(route('forms.show', $form->slug))
|
||||||
|
->assertSuccessful()->assertJson([
|
||||||
|
'id' => $form->id,
|
||||||
|
'title' => $form->title,
|
||||||
|
'custom_code' => null
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -179,6 +179,21 @@ trait TestHelpers
|
||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function createTrialingUser()
|
||||||
|
{
|
||||||
|
$user = $this->createUser();
|
||||||
|
$user->subscriptions()->create([
|
||||||
|
'name' => 'default',
|
||||||
|
'stripe_id' => Str::random(),
|
||||||
|
'stripe_status' => 'trialing',
|
||||||
|
'stripe_price' => Str::random(),
|
||||||
|
'trial_ends_at' => now()->addDays(5),
|
||||||
|
'quantity' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
|
||||||
public function actingAsUser(?User $user = null)
|
public function actingAsUser(?User $user = null)
|
||||||
{
|
{
|
||||||
if ($user == null) {
|
if ($user == null) {
|
||||||
|
|
@ -207,6 +222,15 @@ trait TestHelpers
|
||||||
return $this->actingAsUser($user);
|
return $this->actingAsUser($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function actingAsTrialingUser(User $user = null)
|
||||||
|
{
|
||||||
|
if ($user == null) {
|
||||||
|
$user = $this->createTrialingUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->actingAsUser($user);
|
||||||
|
}
|
||||||
|
|
||||||
public function actingAsGuest()
|
public function actingAsGuest()
|
||||||
{
|
{
|
||||||
if (Auth::check()) {
|
if (Auth::check()) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue