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 image ## 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 CleanShot 2026-05-22 at 11 43 20@2x CleanShot 2026-05-22 at 11 44 03@2x ## 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