Skip to content

Commit

Permalink
fix webhook caller with file uploads
Browse files Browse the repository at this point in the history
  • Loading branch information
PhilReinking committed Aug 2, 2024
1 parent fce2e09 commit 84d355f
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 20 deletions.
14 changes: 10 additions & 4 deletions app/Http/Controllers/Api/FormSubmitController.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,21 @@ public function __invoke(Request $request, Form $form)
{
$request->validate([
'token' => 'required|string',
'payload' => 'array',
'is_uploading' => 'boolean',
'payload' => 'array|nullable',
]);

$session = $form->formSessions()
->where('token', $request->input('token'))
->firstOrFail()
->submit($request->input('payload'));
->firstOrFail();

event(new FormSessionCompletedEvent($session));
if (!is_null($request->payload)) {
$session->submit($request->input('payload'));
}

if (!$request->input('is_uploading', false)) {
event(new FormSessionCompletedEvent($session));
}

return response()->json($session->setHidden(['form']), 200);
}
Expand Down
4 changes: 2 additions & 2 deletions app/Models/FormSessionResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ public function formSessionUploads()

public function setValueAttribute($new)
{
$this->attributes['value'] = encrypt($new);
$this->attributes['value'] = config('app.debug') ? $new : encrypt($new);
}

public function getValueAttribute()
{
try {
return decrypt($this->attributes['value']);
return config('app.debug') ? $this->attributes['value'] : decrypt($this->attributes['value']);
} catch (\Throwable $th) {
return $this->attributes['value'];
}
Expand Down
6 changes: 5 additions & 1 deletion app/Providers/AppServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ public function register()
$this->app->bind(
HttpClientInterface::class,
function ($app) {
return new NoPrivateNetworkHttpClient(HttpClient::create());
return new NoPrivateNetworkHttpClient(HttpClient::create([
'headers' => [
'user-agent' => 'Input-App/1.0',
],
]));
}
);

Expand Down
11 changes: 8 additions & 3 deletions resources/js/api/conversation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ export function callCreateFormSession(
export function callSubmitForm(
uuid: string,
token: string,
payload: FormSubmitPayload,
payload: FormSubmitPayload | null,
is_uploading: boolean = false,
): Promise<AxiosResponse<null>> {
return new Promise(async (resolve, reject) => {
try {
Expand All @@ -92,6 +93,7 @@ export function callSubmitForm(
const response = await handler.post(resolvedRoute, {
token,
payload,
is_uploading,
});
resolve(response as AxiosResponse<null>);
} else {
Expand Down Expand Up @@ -138,8 +140,11 @@ export async function callUploadFiles(
"Content-Type": "multipart/form-data",
},
onUploadProgress: (progressEvent) => {
progressCallback(`${value.actionId}[${index}]`, progressEvent);
}
progressCallback(
`${value.actionId}[${index}]`,
progressEvent,
);
},
}),
);
});
Expand Down
57 changes: 47 additions & 10 deletions resources/js/stores/conversation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,32 @@ export const useConversation = defineStore("form", {
return null;
},

submittablePayload(): FormSubmitPayload {
const submittablePayload = Object.assign({}, this.payload);

for (const block in this.payload) {
const blockPayload = this.payload[block];

if (Array.isArray(blockPayload)) {
continue;
}

if (
Array.isArray(blockPayload.payload) &&
blockPayload.payload.some((f) => f instanceof File)
) {
submittablePayload[block] = {
...blockPayload,
payload: blockPayload.payload
.map((f) => f.name)
.join(", "),
};
}
}

return submittablePayload;
},

countCurrentSelections(): number {
if (!this.currentPayload) return 0;

Expand Down Expand Up @@ -153,10 +179,7 @@ export const useConversation = defineStore("form", {
return state.form.cta_link;
},

uploadsPayload(state): Record<
string,
FormBlockUploadPayload
> {
uploadsPayload(state): Record<string, FormBlockUploadPayload> {
const uploads = {};

for (const block in state.payload) {
Expand All @@ -166,7 +189,10 @@ export const useConversation = defineStore("form", {
continue;
}

if (Array.isArray(blockPayload.payload) && blockPayload.payload.some((f) => f instanceof File)) {
if (
Array.isArray(blockPayload.payload) &&
blockPayload.payload.some((f) => f instanceof File)
) {
uploads[block] = blockPayload;
}
}
Expand Down Expand Up @@ -200,7 +226,7 @@ export const useConversation = defineStore("form", {
);

return Math.round((loaded / total) * 100);
}
},
},

actions: {
Expand Down Expand Up @@ -308,12 +334,12 @@ export const useConversation = defineStore("form", {
this.uploads = {};
this.isProcessing = true;


if (this.form?.uuid && this.session?.token) {
await callSubmitForm(
this.form.uuid,
this.session.token,
this.payload,
this.submittablePayload,
this.hasFileUploads,
);

if (this.hasFileUploads) {
Expand All @@ -327,12 +353,23 @@ export const useConversation = defineStore("form", {
this.uploadsPayload,
(action, progressEvent) => {
try {
this.uploads[action].loaded = progressEvent.loaded;
this.uploads[action].loaded =
progressEvent.loaded;
} catch (e) {
console.warn('could not update upload progress', e)
console.warn(
"could not update upload progress",
e,
);
}
},
);

await callSubmitForm(
this.form.uuid,
this.session.token,
null,
false,
);
}

// If a redirect is configured, we redirect the user to the given url
Expand Down
17 changes: 17 additions & 0 deletions tests/Feature/FormSessionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,23 @@
Event::assertListening(FormSessionCompletedEvent::class, FormSubmitWebhookListener::class);
});


test('when submitting a form with is_uploading set to true the form webhook listener is not fired', function () {
Event::fake();

$session = FormSession::factory()->create();

$this->json('POST', route('api.public.forms.submit', [
'form' => $session->form->uuid,
]), [
'token' => $session->token,
'payload' => [],
'is_uploading' => true,
])->assertStatus(200);

Event::assertNotDispatched(FormSessionCompletedEvent::class);
});

it('should delete old submissions if auto delete is enabled for the form after specified time', function ($template) {
$form = Form::factory()->create([
'is_auto_delete_enabled' => true,
Expand Down

0 comments on commit 84d355f

Please sign in to comment.