fix: portals#create returns 500 when custom_domain is omitted (#14400)
## Description
`POST /api/v1/accounts/:account_id/portals` returns a generic 500
(`{"status":500,"error":"Internal Server Error"}`) whenever the request
body omits `custom_domain`. Root cause: `parsed_custom_domain` calls
`URI.parse(@portal.custom_domain)` and `URI.parse(nil)` raises
`URI::InvalidURIError`. Existing callers either had to know to pass
`"custom_domain": ""` as a workaround or hit a 500 with no useful
diagnostic.
This PR guards `parsed_custom_domain` against blank values so the
existing fall-through (`else @portal.custom_domain`) applies —
equivalent to passing an empty string.
It also moves the `process_attached_logo` guard from the helper into the
`create` call site so `create` mirrors `update` (`process_attached_logo
if params[:blob_id].present?`) and avoids an unnecessary signed-blob
lookup on every create that doesn't include a logo.
Fixes #14397
## Type of change
- [x] Bug fix (non-breaking change which fixes an issue)
## How Has This Been Tested?
Two new request specs in
`spec/controllers/api/v1/accounts/portals_controller_spec.rb` covering
the regression:
- `creates portal when custom_domain is omitted from request body` — the
previously-broken case, now returns 200.
- `creates portal when custom_domain is blank` — verifies the existing
workaround (`"custom_domain": ""`) still works after the change.
Manually verified against `chatwoot/chatwoot:latest` Docker image before
the fix (500) and against this branch (200) using the curl repro from
the issue.
```bash
curl -X POST "https://<host>/api/v1/accounts/<account_id>/portals" \
-H "Content-Type: application/json" \
-H "api_access_token: <token>" \
-d '{"name":"Test Portal","slug":"test-portal","color":"#3b82f6"}'
```
Before: `{"status":500,"error":"Internal Server Error"}`
After: `200 OK` with the portal payload.
## Checklist
- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation (no doc
change needed — controller behaviour, fully backward-compatible)
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream
modules
---------
Co-authored-by: Sojan Jose <sojan@pepalo.com>
This commit is contained in:
co-authored by
Sojan Jose
parent
cfc7699b7e
commit
5f6bd951b9
@@ -18,7 +18,7 @@ class Api::V1::Accounts::PortalsController < Api::V1::Accounts::BaseController
|
||||
@portal = Current.account.portals.build(portal_params.merge(live_chat_widget_params))
|
||||
@portal.custom_domain = parsed_custom_domain
|
||||
@portal.save!
|
||||
process_attached_logo
|
||||
process_attached_logo if params[:blob_id].present?
|
||||
end
|
||||
|
||||
def update
|
||||
@@ -98,6 +98,8 @@ class Api::V1::Accounts::PortalsController < Api::V1::Accounts::BaseController
|
||||
end
|
||||
|
||||
def parsed_custom_domain
|
||||
return @portal.custom_domain if @portal.custom_domain.blank?
|
||||
|
||||
domain = URI.parse(@portal.custom_domain)
|
||||
domain.is_a?(URI::HTTP) ? domain.host : @portal.custom_domain
|
||||
end
|
||||
|
||||
@@ -100,6 +100,41 @@ RSpec.describe 'Api::V1::Accounts::Portals', type: :request do
|
||||
expect(json_response['name']).to eql('test_portal')
|
||||
expect(json_response['custom_domain']).to eql('support.chatwoot.dev')
|
||||
end
|
||||
|
||||
it 'creates portal when custom_domain is omitted from request body' do
|
||||
portal_params = {
|
||||
portal: {
|
||||
name: 'test_portal_no_domain',
|
||||
slug: 'test_kbase_no_domain'
|
||||
}
|
||||
}
|
||||
post "/api/v1/accounts/#{account.id}/portals",
|
||||
params: portal_params,
|
||||
headers: admin.create_new_auth_token
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
json_response = response.parsed_body
|
||||
expect(json_response['name']).to eql('test_portal_no_domain')
|
||||
expect(json_response['custom_domain']).to be_nil
|
||||
end
|
||||
|
||||
it 'creates portal when custom_domain is blank' do
|
||||
portal_params = {
|
||||
portal: {
|
||||
name: 'test_portal_blank_domain',
|
||||
slug: 'test_kbase_blank_domain',
|
||||
custom_domain: ''
|
||||
}
|
||||
}
|
||||
post "/api/v1/accounts/#{account.id}/portals",
|
||||
params: portal_params,
|
||||
headers: admin.create_new_auth_token
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
json_response = response.parsed_body
|
||||
expect(json_response['name']).to eql('test_portal_blank_domain')
|
||||
expect(json_response['custom_domain']).to be_blank
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user