From 3c67c415442ea115dc0b1bc142875ff43eb65695 Mon Sep 17 00:00:00 2001
From: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Date: Fri, 22 May 2026 11:09:27 +0530
Subject: [PATCH 1/3] chore: support PFX filetype in attachment uploads
(#14456)
# Pull Request Template
## Description
This PR expands the default upload rules to support PFX certificate
files (`application/x-pkcs12`, `application/pkcs12`, `.pfx`) across
private notes, Website, Email, and Telegram channels.
Also adds `.xls` / `.xlsx` extension fallbacks for cases where browsers
upload Excel files with an empty or generic MIME type.
### Utils Repo PR: https://github.com/chatwoot/utils/pull/61
Fixes
https://linear.app/chatwoot/issue/CW-7085/support-more-file-types-in-private-notes-and-in-app
## Type of change
- [x] New feature (non-breaking change which adds functionality)
## How Has This Been Tested?
### Screenshots
## Checklist:
- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] 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
- [ ] Any dependent changes have been merged and published in downstream
modules
---------
Co-authored-by: aakashb95
---
.../components-next/icon/FileIcon.vue | 1 +
.../widgets/WootWriter/ReplyBottomPanel.vue | 10 +---------
app/javascript/shared/helpers/FileHelper.js | 4 +---
app/models/attachment.rb | 18 ++++++++++++++++--
package.json | 2 +-
pnpm-lock.yaml | 10 +++++-----
theme/icons.js | 17 +++++++++++++++++
7 files changed, 42 insertions(+), 20 deletions(-)
diff --git a/app/javascript/dashboard/components-next/icon/FileIcon.vue b/app/javascript/dashboard/components-next/icon/FileIcon.vue
index 8dd9e7ce1..d82be3e69 100644
--- a/app/javascript/dashboard/components-next/icon/FileIcon.vue
+++ b/app/javascript/dashboard/components-next/icon/FileIcon.vue
@@ -18,6 +18,7 @@ const fileTypeIcon = computed(() => {
json: 'i-woot-file-txt',
odt: 'i-woot-file-doc',
pdf: 'i-woot-file-pdf',
+ pfx: 'i-woot-file-pfx',
ppt: 'i-woot-file-ppt',
pptx: 'i-woot-file-ppt',
rar: 'i-woot-file-zip',
diff --git a/app/javascript/dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue b/app/javascript/dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue
index ff569d763..2e5a9aab2 100644
--- a/app/javascript/dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue
+++ b/app/javascript/dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue
@@ -7,7 +7,6 @@ import * as ActiveStorage from 'activestorage';
import inboxMixin from 'shared/mixins/inboxMixin';
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
import { getAllowedFileTypesByChannel } from '@chatwoot/utils';
-import { ALLOWED_FILE_TYPES } from 'shared/constants/messages';
import VideoCallButton from '../VideoCallButton.vue';
import { INBOX_TYPES } from 'dashboard/helper/inbox';
import { mapGetters } from 'vuex';
@@ -166,11 +165,6 @@ export default {
uploadRef,
};
},
- data() {
- return {
- ALLOWED_FILE_TYPES,
- };
- },
computed: {
...mapGetters({
accountId: 'getCurrentAccountId',
@@ -212,13 +206,11 @@ export default {
return this.conversationType === 'instagram_direct_message';
},
allowedFileTypes() {
- // Use default file types for private notes
if (this.isOnPrivateNote) {
- return this.ALLOWED_FILE_TYPES;
+ return getAllowedFileTypesByChannel();
}
let channelType = this.channelType || this.inbox?.channel_type;
-
if (this.isAnInstagramChannel || this.isInstagramDM) {
channelType = INBOX_TYPES.INSTAGRAM;
}
diff --git a/app/javascript/shared/helpers/FileHelper.js b/app/javascript/shared/helpers/FileHelper.js
index 2616c868a..93c8a7156 100644
--- a/app/javascript/shared/helpers/FileHelper.js
+++ b/app/javascript/shared/helpers/FileHelper.js
@@ -1,6 +1,5 @@
import { getAllowedFileTypesByChannel } from '@chatwoot/utils';
import { INBOX_TYPES } from 'dashboard/helper/inbox';
-import { ALLOWED_FILE_TYPES } from 'shared/constants/messages';
export const DEFAULT_MAXIMUM_FILE_UPLOAD_SIZE = 40;
@@ -58,9 +57,8 @@ export const isFileTypeAllowedForChannel = (file, options = {}) => {
isOnPrivateNote,
} = options;
- // Use broader file types for private notes (matches file picker behavior)
const allowedFileTypes = isOnPrivateNote
- ? ALLOWED_FILE_TYPES
+ ? getAllowedFileTypesByChannel()
: getAllowedFileTypesByChannel({
channelType:
isInstagramChannel || conversationType === 'instagram_direct_message'
diff --git a/app/models/attachment.rb b/app/models/attachment.rb
index 2d46f3b7e..102d90beb 100644
--- a/app/models/attachment.rb
+++ b/app/models/attachment.rb
@@ -33,7 +33,10 @@ class Attachment < ApplicationRecord
application/vnd.openxmlformats-officedocument.presentationml.presentation
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
application/vnd.openxmlformats-officedocument.wordprocessingml.document
+ application/x-pkcs12 application/pkcs12
].freeze
+ ACCEPTABLE_FILE_EXTENSIONS = %w[pfx].freeze
+ GENERIC_FILE_CONTENT_TYPES = %w[application/octet-stream].freeze
belongs_to :account
belongs_to :message
has_one_attached :file
@@ -195,7 +198,10 @@ class Attachment < ApplicationRecord
end
def validate_file_content_type(file_content_type)
- errors.add(:file, 'type not supported') unless media_file?(file_content_type) || ACCEPTABLE_FILE_TYPES.include?(file_content_type)
+ return if media_file?(file_content_type) || ACCEPTABLE_FILE_TYPES.include?(file_content_type)
+ return if generic_file_content_type?(file_content_type) && ACCEPTABLE_FILE_EXTENSIONS.include?(file_extension)
+
+ errors.add(:file, 'type not supported')
end
def validate_file_size(byte_size)
@@ -206,7 +212,15 @@ class Attachment < ApplicationRecord
end
def media_file?(file_content_type)
- file_content_type.start_with?('image/', 'video/', 'audio/')
+ file_content_type.to_s.start_with?('image/', 'video/', 'audio/')
+ end
+
+ def generic_file_content_type?(file_content_type)
+ file_content_type.blank? || GENERIC_FILE_CONTENT_TYPES.include?(file_content_type)
+ end
+
+ def file_extension
+ File.extname(file.filename.to_s).delete_prefix('.').downcase
end
end
diff --git a/package.json b/package.json
index ed8bbf00f..1e506d6c5 100644
--- a/package.json
+++ b/package.json
@@ -35,7 +35,7 @@
"@breezystack/lamejs": "^1.2.7",
"@chatwoot/ninja-keys": "1.2.3",
"@chatwoot/prosemirror-schema": "1.3.13",
- "@chatwoot/utils": "^0.0.52",
+ "@chatwoot/utils": "^0.0.55",
"@formkit/core": "^1.7.2",
"@formkit/vue": "^1.7.2",
"@hcaptcha/vue3-hcaptcha": "^1.3.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 3f1e9e2cf..3a9efa7eb 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -29,8 +29,8 @@ importers:
specifier: 1.3.13
version: 1.3.13
'@chatwoot/utils':
- specifier: ^0.0.52
- version: 0.0.52
+ specifier: ^0.0.55
+ version: 0.0.55
'@formkit/core':
specifier: ^1.7.2
version: 1.7.2
@@ -462,8 +462,8 @@ packages:
'@chatwoot/prosemirror-schema@1.3.13':
resolution: {integrity: sha512-T6FBUinMJbwDCD7975g8M/Tsn2+G3O2pTGIXdcLkMRpbAAC6mVdl4ZcZektlt5y/PVmPVqNHPsfee1XB/C3vAw==}
- '@chatwoot/utils@0.0.52':
- resolution: {integrity: sha512-e57uVqyVW4tj1gql4YJPNMykqMJPkETn5Y9AmHdhc6Y7oxDXfRXBq27fZrrDadLkZdn5RYVCZjfIhXOumyYv2Q==}
+ '@chatwoot/utils@0.0.55':
+ resolution: {integrity: sha512-8G6HYQe1ZEYfJEsSYfDVvE+uhf98JDRjtGlpB+bzMko+yltbrk4yACSo/ImC3jSaJ6K8yPTSjJToSRmsQbL2iQ==}
engines: {node: '>=10'}
'@codemirror/commands@6.7.0':
@@ -5011,7 +5011,7 @@ snapshots:
prosemirror-utils: 1.2.2(prosemirror-model@1.22.3)(prosemirror-state@1.4.3)
prosemirror-view: 1.34.1
- '@chatwoot/utils@0.0.52':
+ '@chatwoot/utils@0.0.55':
dependencies:
date-fns: 2.30.0
diff --git a/theme/icons.js b/theme/icons.js
index 266c7ddfa..281e21c23 100644
--- a/theme/icons.js
+++ b/theme/icons.js
@@ -113,6 +113,23 @@ export const icons = {
width: 16,
height: 20,
},
+ 'file-pfx': {
+ body: `
+
+
+
+
+
+
+
+
+
+
+
+ `,
+ width: 16,
+ height: 20,
+ },
bin: {
body: ``,
width: 16,
From 1d7a9093d227cc7d1627bda9408a050e78cd3d66 Mon Sep 17 00:00:00 2001
From: Sojan Jose
Date: Fri, 22 May 2026 11:33:19 +0530
Subject: [PATCH 2/3] fix: clarify agent availability swagger fields (#14533)
Clarifies the agent availability API documentation so request payloads
use the writable `availability` field, while `availability_status`
remains documented as a read-only response field.
## Closes
Closes #13873
## Why
The backend already supports updating an agent's configured availability
through `availability`, but the Swagger request payloads documented
`availability_status`. That made clients follow a read-only response
field and see successful requests without the intended availability
change.
## What changed
- Replaces `availability_status` with `availability` in agent
create/update request schemas.
- Updates the availability enum to `online`, `busy`, and `offline`.
- Marks response `availability_status` as read-only and explains that it
is derived from configured availability, auto-offline, and presence.
- Regenerates the combined and tag-group Swagger JSON files.
## Validation
- `bundle exec rails swagger:build`
- `bundle exec rspec spec/swagger/openapi_spec.rb`
- `git diff --check`
---
.../request/agent/create_payload.yml | 10 +++----
.../request/agent/update_payload.yml | 10 +++----
swagger/definitions/resource/agent.yml | 10 ++++---
swagger/swagger.json | 27 ++++++++++---------
swagger/tag_groups/application_swagger.json | 27 ++++++++++---------
swagger/tag_groups/client_swagger.json | 27 ++++++++++---------
swagger/tag_groups/other_swagger.json | 27 ++++++++++---------
swagger/tag_groups/platform_swagger.json | 27 ++++++++++---------
8 files changed, 87 insertions(+), 78 deletions(-)
diff --git a/swagger/definitions/request/agent/create_payload.yml b/swagger/definitions/request/agent/create_payload.yml
index 1daeae83a..77180d282 100644
--- a/swagger/definitions/request/agent/create_payload.yml
+++ b/swagger/definitions/request/agent/create_payload.yml
@@ -17,12 +17,12 @@ properties:
enum: ['agent', 'administrator']
description: Whether its administrator or agent
example: 'agent'
- availability_status:
+ availability:
type: string
- enum: ['available', 'busy', 'offline']
- description: The availability setting of the agent.
- example: 'available'
+ enum: ['online', 'busy', 'offline']
+ description: The configured availability of the agent.
+ example: 'online'
auto_offline:
type: boolean
- description: Whether the availability status of agent is configured to go offline automatically when away.
+ description: Whether the agent is automatically marked offline when they are away.
example: true
diff --git a/swagger/definitions/request/agent/update_payload.yml b/swagger/definitions/request/agent/update_payload.yml
index fc8d1457d..168d46f49 100644
--- a/swagger/definitions/request/agent/update_payload.yml
+++ b/swagger/definitions/request/agent/update_payload.yml
@@ -7,12 +7,12 @@ properties:
enum: ['agent', 'administrator']
description: Whether its administrator or agent
example: 'agent'
- availability_status:
+ availability:
type: string
- enum: ['available', 'busy', 'offline']
- description: The availability status of the agent.
- example: 'available'
+ enum: ['online', 'busy', 'offline']
+ description: The configured availability of the agent.
+ example: 'online'
auto_offline:
type: boolean
- description: Whether the availability status of agent is configured to go offline automatically when away.
+ description: Whether the agent is automatically marked offline when they are away.
example: true
diff --git a/swagger/definitions/resource/agent.yml b/swagger/definitions/resource/agent.yml
index 1d7b2b4c3..cabd1ee27 100644
--- a/swagger/definitions/resource/agent.yml
+++ b/swagger/definitions/resource/agent.yml
@@ -6,11 +6,15 @@ properties:
type: integer
availability_status:
type: string
- enum: ['available', 'busy', 'offline']
- description: The availability status of the agent computed by Chatwoot.
+ enum: ['online', 'busy', 'offline']
+ readOnly: true
+ description: >-
+ The effective availability status of the agent, derived from the configured availability,
+ auto-offline setting, and current presence. To update an agent's configured availability,
+ use the availability field in create or update requests.
auto_offline:
type: boolean
- description: Whether the availability status of agent is configured to go offline automatically when away.
+ description: Whether the agent is automatically marked offline when they are away.
confirmed:
type: boolean
description: Whether the agent has confirmed their email address.
diff --git a/swagger/swagger.json b/swagger/swagger.json
index 94d1f04d3..b8b64b009 100644
--- a/swagger/swagger.json
+++ b/swagger/swagger.json
@@ -9892,15 +9892,16 @@
"availability_status": {
"type": "string",
"enum": [
- "available",
+ "online",
"busy",
"offline"
],
- "description": "The availability status of the agent computed by Chatwoot."
+ "readOnly": true,
+ "description": "The effective availability status of the agent, derived from the configured availability, auto-offline setting, and current presence. To update an agent's configured availability, use the availability field in create or update requests."
},
"auto_offline": {
"type": "boolean",
- "description": "Whether the availability status of agent is configured to go offline automatically when away."
+ "description": "Whether the agent is automatically marked offline when they are away."
},
"confirmed": {
"type": "boolean",
@@ -11595,19 +11596,19 @@
"description": "Whether its administrator or agent",
"example": "agent"
},
- "availability_status": {
+ "availability": {
"type": "string",
"enum": [
- "available",
+ "online",
"busy",
"offline"
],
- "description": "The availability setting of the agent.",
- "example": "available"
+ "description": "The configured availability of the agent.",
+ "example": "online"
},
"auto_offline": {
"type": "boolean",
- "description": "Whether the availability status of agent is configured to go offline automatically when away.",
+ "description": "Whether the agent is automatically marked offline when they are away.",
"example": true
}
}
@@ -11627,19 +11628,19 @@
"description": "Whether its administrator or agent",
"example": "agent"
},
- "availability_status": {
+ "availability": {
"type": "string",
"enum": [
- "available",
+ "online",
"busy",
"offline"
],
- "description": "The availability status of the agent.",
- "example": "available"
+ "description": "The configured availability of the agent.",
+ "example": "online"
},
"auto_offline": {
"type": "boolean",
- "description": "Whether the availability status of agent is configured to go offline automatically when away.",
+ "description": "Whether the agent is automatically marked offline when they are away.",
"example": true
}
}
diff --git a/swagger/tag_groups/application_swagger.json b/swagger/tag_groups/application_swagger.json
index a013b3694..17e015139 100644
--- a/swagger/tag_groups/application_swagger.json
+++ b/swagger/tag_groups/application_swagger.json
@@ -8399,15 +8399,16 @@
"availability_status": {
"type": "string",
"enum": [
- "available",
+ "online",
"busy",
"offline"
],
- "description": "The availability status of the agent computed by Chatwoot."
+ "readOnly": true,
+ "description": "The effective availability status of the agent, derived from the configured availability, auto-offline setting, and current presence. To update an agent's configured availability, use the availability field in create or update requests."
},
"auto_offline": {
"type": "boolean",
- "description": "Whether the availability status of agent is configured to go offline automatically when away."
+ "description": "Whether the agent is automatically marked offline when they are away."
},
"confirmed": {
"type": "boolean",
@@ -10102,19 +10103,19 @@
"description": "Whether its administrator or agent",
"example": "agent"
},
- "availability_status": {
+ "availability": {
"type": "string",
"enum": [
- "available",
+ "online",
"busy",
"offline"
],
- "description": "The availability setting of the agent.",
- "example": "available"
+ "description": "The configured availability of the agent.",
+ "example": "online"
},
"auto_offline": {
"type": "boolean",
- "description": "Whether the availability status of agent is configured to go offline automatically when away.",
+ "description": "Whether the agent is automatically marked offline when they are away.",
"example": true
}
}
@@ -10134,19 +10135,19 @@
"description": "Whether its administrator or agent",
"example": "agent"
},
- "availability_status": {
+ "availability": {
"type": "string",
"enum": [
- "available",
+ "online",
"busy",
"offline"
],
- "description": "The availability status of the agent.",
- "example": "available"
+ "description": "The configured availability of the agent.",
+ "example": "online"
},
"auto_offline": {
"type": "boolean",
- "description": "Whether the availability status of agent is configured to go offline automatically when away.",
+ "description": "Whether the agent is automatically marked offline when they are away.",
"example": true
}
}
diff --git a/swagger/tag_groups/client_swagger.json b/swagger/tag_groups/client_swagger.json
index 763e090b1..7bc7227fb 100644
--- a/swagger/tag_groups/client_swagger.json
+++ b/swagger/tag_groups/client_swagger.json
@@ -1664,15 +1664,16 @@
"availability_status": {
"type": "string",
"enum": [
- "available",
+ "online",
"busy",
"offline"
],
- "description": "The availability status of the agent computed by Chatwoot."
+ "readOnly": true,
+ "description": "The effective availability status of the agent, derived from the configured availability, auto-offline setting, and current presence. To update an agent's configured availability, use the availability field in create or update requests."
},
"auto_offline": {
"type": "boolean",
- "description": "Whether the availability status of agent is configured to go offline automatically when away."
+ "description": "Whether the agent is automatically marked offline when they are away."
},
"confirmed": {
"type": "boolean",
@@ -3367,19 +3368,19 @@
"description": "Whether its administrator or agent",
"example": "agent"
},
- "availability_status": {
+ "availability": {
"type": "string",
"enum": [
- "available",
+ "online",
"busy",
"offline"
],
- "description": "The availability setting of the agent.",
- "example": "available"
+ "description": "The configured availability of the agent.",
+ "example": "online"
},
"auto_offline": {
"type": "boolean",
- "description": "Whether the availability status of agent is configured to go offline automatically when away.",
+ "description": "Whether the agent is automatically marked offline when they are away.",
"example": true
}
}
@@ -3399,19 +3400,19 @@
"description": "Whether its administrator or agent",
"example": "agent"
},
- "availability_status": {
+ "availability": {
"type": "string",
"enum": [
- "available",
+ "online",
"busy",
"offline"
],
- "description": "The availability status of the agent.",
- "example": "available"
+ "description": "The configured availability of the agent.",
+ "example": "online"
},
"auto_offline": {
"type": "boolean",
- "description": "Whether the availability status of agent is configured to go offline automatically when away.",
+ "description": "Whether the agent is automatically marked offline when they are away.",
"example": true
}
}
diff --git a/swagger/tag_groups/other_swagger.json b/swagger/tag_groups/other_swagger.json
index 50bf2212b..6dbfbdd8e 100644
--- a/swagger/tag_groups/other_swagger.json
+++ b/swagger/tag_groups/other_swagger.json
@@ -1079,15 +1079,16 @@
"availability_status": {
"type": "string",
"enum": [
- "available",
+ "online",
"busy",
"offline"
],
- "description": "The availability status of the agent computed by Chatwoot."
+ "readOnly": true,
+ "description": "The effective availability status of the agent, derived from the configured availability, auto-offline setting, and current presence. To update an agent's configured availability, use the availability field in create or update requests."
},
"auto_offline": {
"type": "boolean",
- "description": "Whether the availability status of agent is configured to go offline automatically when away."
+ "description": "Whether the agent is automatically marked offline when they are away."
},
"confirmed": {
"type": "boolean",
@@ -2782,19 +2783,19 @@
"description": "Whether its administrator or agent",
"example": "agent"
},
- "availability_status": {
+ "availability": {
"type": "string",
"enum": [
- "available",
+ "online",
"busy",
"offline"
],
- "description": "The availability setting of the agent.",
- "example": "available"
+ "description": "The configured availability of the agent.",
+ "example": "online"
},
"auto_offline": {
"type": "boolean",
- "description": "Whether the availability status of agent is configured to go offline automatically when away.",
+ "description": "Whether the agent is automatically marked offline when they are away.",
"example": true
}
}
@@ -2814,19 +2815,19 @@
"description": "Whether its administrator or agent",
"example": "agent"
},
- "availability_status": {
+ "availability": {
"type": "string",
"enum": [
- "available",
+ "online",
"busy",
"offline"
],
- "description": "The availability status of the agent.",
- "example": "available"
+ "description": "The configured availability of the agent.",
+ "example": "online"
},
"auto_offline": {
"type": "boolean",
- "description": "Whether the availability status of agent is configured to go offline automatically when away.",
+ "description": "Whether the agent is automatically marked offline when they are away.",
"example": true
}
}
diff --git a/swagger/tag_groups/platform_swagger.json b/swagger/tag_groups/platform_swagger.json
index f1e471e79..952813f62 100644
--- a/swagger/tag_groups/platform_swagger.json
+++ b/swagger/tag_groups/platform_swagger.json
@@ -1840,15 +1840,16 @@
"availability_status": {
"type": "string",
"enum": [
- "available",
+ "online",
"busy",
"offline"
],
- "description": "The availability status of the agent computed by Chatwoot."
+ "readOnly": true,
+ "description": "The effective availability status of the agent, derived from the configured availability, auto-offline setting, and current presence. To update an agent's configured availability, use the availability field in create or update requests."
},
"auto_offline": {
"type": "boolean",
- "description": "Whether the availability status of agent is configured to go offline automatically when away."
+ "description": "Whether the agent is automatically marked offline when they are away."
},
"confirmed": {
"type": "boolean",
@@ -3543,19 +3544,19 @@
"description": "Whether its administrator or agent",
"example": "agent"
},
- "availability_status": {
+ "availability": {
"type": "string",
"enum": [
- "available",
+ "online",
"busy",
"offline"
],
- "description": "The availability setting of the agent.",
- "example": "available"
+ "description": "The configured availability of the agent.",
+ "example": "online"
},
"auto_offline": {
"type": "boolean",
- "description": "Whether the availability status of agent is configured to go offline automatically when away.",
+ "description": "Whether the agent is automatically marked offline when they are away.",
"example": true
}
}
@@ -3575,19 +3576,19 @@
"description": "Whether its administrator or agent",
"example": "agent"
},
- "availability_status": {
+ "availability": {
"type": "string",
"enum": [
- "available",
+ "online",
"busy",
"offline"
],
- "description": "The availability status of the agent.",
- "example": "available"
+ "description": "The configured availability of the agent.",
+ "example": "online"
},
"auto_offline": {
"type": "boolean",
- "description": "Whether the availability status of agent is configured to go offline automatically when away.",
+ "description": "Whether the agent is automatically marked offline when they are away.",
"example": true
}
}
From bef25781dede466ba4613fb88d4292faf4cdddb2 Mon Sep 17 00:00:00 2001
From: Aakash Bakhle <48802744+aakashb95@users.noreply.github.com>
Date: Fri, 22 May 2026 11:55:16 +0530
Subject: [PATCH 3/3] feat(attachments): add XML and PFX file support (#14539)
Update frontend allowed file types and FileIcon mapping, and backend
Attachment constants to accept .xml and .pfx files
# Pull Request Template
## Description
Customer also wanted XML support along with .pfx
Following up on #14456
## Type of change
- [x] New feature (non-breaking change which adds functionality)
## How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.
locally
## 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
- [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
---
app/javascript/dashboard/components-next/icon/FileIcon.vue | 1 +
app/javascript/shared/constants/messages.js | 4 +++-
app/models/attachment.rb | 5 +++--
3 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/app/javascript/dashboard/components-next/icon/FileIcon.vue b/app/javascript/dashboard/components-next/icon/FileIcon.vue
index d82be3e69..66a971bc6 100644
--- a/app/javascript/dashboard/components-next/icon/FileIcon.vue
+++ b/app/javascript/dashboard/components-next/icon/FileIcon.vue
@@ -27,6 +27,7 @@ const fileTypeIcon = computed(() => {
txt: 'i-woot-file-txt',
xls: 'i-woot-file-xls',
xlsx: 'i-woot-file-xls',
+ xml: 'i-woot-file-txt',
zip: 'i-woot-file-zip',
};
diff --git a/app/javascript/shared/constants/messages.js b/app/javascript/shared/constants/messages.js
index 989aa12ca..18bc380ec 100644
--- a/app/javascript/shared/constants/messages.js
+++ b/app/javascript/shared/constants/messages.js
@@ -39,12 +39,14 @@ export const ALLOWED_FILE_TYPES =
'audio/*,' +
'video/*,' +
'.3gpp,' +
+ '.xls, .xlsx, .xml, .pfx,' +
'text/csv, text/plain, application/json, application/pdf, text/rtf,' +
'application/xml, text/xml,' +
'application/zip, application/x-7z-compressed application/vnd.rar application/x-tar,' +
'application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/vnd.oasis.opendocument.text,' +
'application/vnd.openxmlformats-officedocument.presentationml.presentation, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,' +
- 'application/vnd.openxmlformats-officedocument.wordprocessingml.document,';
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document,' +
+ 'application/x-pkcs12, application/pkcs12,';
export const CSAT_RATINGS = [
{
diff --git a/app/models/attachment.rb b/app/models/attachment.rb
index 102d90beb..79a8021b3 100644
--- a/app/models/attachment.rb
+++ b/app/models/attachment.rb
@@ -25,8 +25,9 @@ class Attachment < ApplicationRecord
include Rails.application.routes.url_helpers
ACCEPTABLE_FILE_TYPES = %w[
- text/csv text/plain text/rtf
+ text/csv text/plain text/rtf text/xml
application/json application/pdf
+ application/xml
application/zip application/x-7z-compressed application/vnd.rar application/x-tar
application/msword application/vnd.ms-excel application/vnd.ms-powerpoint application/rtf
application/vnd.oasis.opendocument.text
@@ -35,7 +36,7 @@ class Attachment < ApplicationRecord
application/vnd.openxmlformats-officedocument.wordprocessingml.document
application/x-pkcs12 application/pkcs12
].freeze
- ACCEPTABLE_FILE_EXTENSIONS = %w[pfx].freeze
+ ACCEPTABLE_FILE_EXTENSIONS = %w[pfx xml].freeze
GENERIC_FILE_CONTENT_TYPES = %w[application/octet-stream].freeze
belongs_to :account
belongs_to :message