diff --git a/.env.example b/.env.example index 642a81fa9..f405ea03d 100644 --- a/.env.example +++ b/.env.example @@ -222,20 +222,10 @@ STRIPE_WEBHOOK_SECRET= # Make sure to follow https://edgeguides.rubyonrails.org/active_storage_overview.html#cross-origin-resource-sharing-cors-configuration on the cloud storage after setting this to true. DIRECT_UPLOADS_ENABLED= -# MS OAUTH creds +#MS OAUTH creds AZURE_APP_ID= AZURE_APP_SECRET= -## MS Azure Tenant ID -# Set the following id to the id of your Azure 'tenant'. -# This will enable single tenant applications to work. -# If the following id is set, Chatwoot will use the Microsoft Graph API -# to send and receive emails, as that seems to be required for single -# tenant applications. -# -# https://learn.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-how-to-find-tenant -AZURE_TENANT_ID= - ## Advanced configurations ## Change these values to fine tune performance # control the concurrency setting of sidekiq diff --git a/app/controllers/api/v1/accounts/microsoft/authorizations_controller.rb b/app/controllers/api/v1/accounts/microsoft/authorizations_controller.rb index 7bdd88aa2..bee47b213 100644 --- a/app/controllers/api/v1/accounts/microsoft/authorizations_controller.rb +++ b/app/controllers/api/v1/accounts/microsoft/authorizations_controller.rb @@ -4,7 +4,13 @@ class Api::V1::Accounts::Microsoft::AuthorizationsController < Api::V1::Accounts def create email = params[:authorization][:email] - redirect_url = microsoft_client.auth_code.authorize_url(auth_params) + redirect_url = microsoft_client.auth_code.authorize_url( + { + redirect_uri: "#{base_url}/microsoft/callback", + scope: 'offline_access https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send openid profile', + prompt: 'consent' + } + ) if redirect_url email = email.downcase ::Redis::Alfred.setex(email, Current.account.id, 5.minutes) @@ -19,31 +25,4 @@ class Api::V1::Accounts::Microsoft::AuthorizationsController < Api::V1::Accounts def check_authorization raise Pundit::NotAuthorizedError unless Current.account_user.administrator? end - - # SMTP, Pop and IMAP are being deprecated by Outlook. - # https://learn.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/deprecation-of-basic-authentication-exchange-online - # - # As such, Microsoft has made it a real pain to use them. - # If AZURE_TENANT_ID is set, we will use the MS Graph API instead. - def auth_params - return graph_auth_params if ENV.fetch('AZURE_TENANT_ID', false) - - standard_auth_params - end - - def standard_auth_params - { - redirect_uri: "#{base_url}/microsoft/callback", - scope: 'offline_access https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send openid profile', - prompt: 'consent' - } - end - - def graph_auth_params - { - redirect_uri: "#{base_url}/microsoft/callback", - scope: 'offline_access https://graph.microsoft.com/Mail.Read https://graph.microsoft.com/Mail.Send openid profile', - prompt: 'consent' - } - end end diff --git a/app/controllers/concerns/microsoft_concern.rb b/app/controllers/concerns/microsoft_concern.rb index d1bcb49a6..3aa3e4e81 100644 --- a/app/controllers/concerns/microsoft_concern.rb +++ b/app/controllers/concerns/microsoft_concern.rb @@ -5,8 +5,8 @@ module MicrosoftConcern ::OAuth2::Client.new(ENV.fetch('AZURE_APP_ID', nil), ENV.fetch('AZURE_APP_SECRET', nil), { site: 'https://login.microsoftonline.com', - authorize_url: "https://login.microsoftonline.com/#{azure_tenant_id}/oauth2/v2.0/authorize", - token_url: "https://login.microsoftonline.com/#{azure_tenant_id}/oauth2/v2.0/token" + authorize_url: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize', + token_url: 'https://login.microsoftonline.com/common/oauth2/v2.0/token' }) end @@ -19,8 +19,4 @@ module MicrosoftConcern def base_url ENV.fetch('FRONTEND_URL', 'http://localhost:3000') end - - def azure_tenant_id - MicrosoftGraphAuth.azure_tenant_id - end end diff --git a/app/javascript/dashboard/constants/globals.js b/app/javascript/dashboard/constants/globals.js index 1074810ad..2ef50e732 100644 --- a/app/javascript/dashboard/constants/globals.js +++ b/app/javascript/dashboard/constants/globals.js @@ -39,5 +39,7 @@ export default { UNTIL_NEXT_MONTH: 'until_next_month', UNTIL_CUSTOM_TIME: 'until_custom_time', }, + EXAMPLE_URL: 'https://example.com', + EXAMPLE_WEBHOOK_URL: 'https://example/api/webhook', }; export const DEFAULT_REDIRECT_URL = '/app/'; diff --git a/app/javascript/dashboard/helper/snoozeHelpers.js b/app/javascript/dashboard/helper/snoozeHelpers.js index 07cb3a20f..60954364b 100644 --- a/app/javascript/dashboard/helper/snoozeHelpers.js +++ b/app/javascript/dashboard/helper/snoozeHelpers.js @@ -8,6 +8,8 @@ import { isMonday, isToday, setHours, + setMinutes, + setSeconds, } from 'date-fns'; import wootConstants from 'dashboard/constants/globals'; @@ -36,7 +38,7 @@ export const findNextDay = currentDate => { }; export const setHoursToNine = date => { - return setHours(date, 9, 0, 0); + return setSeconds(setMinutes(setHours(date, 9), 0), 0); }; export const findSnoozeTime = (snoozeType, currentDate = new Date()) => { diff --git a/app/javascript/dashboard/helper/specs/snoozeHelpers.spec.js b/app/javascript/dashboard/helper/specs/snoozeHelpers.spec.js index 6da35d02c..31c07ae65 100644 --- a/app/javascript/dashboard/helper/specs/snoozeHelpers.spec.js +++ b/app/javascript/dashboard/helper/specs/snoozeHelpers.spec.js @@ -40,6 +40,11 @@ describe('#Snooze Helpers', () => { nextDay.setHours(9, 0, 0, 0); expect(setHoursToNine(nextDay)).toEqual(nextDay); }); + it('should return date with 9.00AM time if date with 10am is passes', () => { + const nextDay = new Date('06/17/2023 10:00:00'); + nextDay.setHours(9, 0, 0, 0); + expect(setHoursToNine(nextDay)).toEqual(nextDay); + }); }); describe('findSnoozeTime', () => { diff --git a/app/javascript/dashboard/i18n/locale/en/cannedMgmt.json b/app/javascript/dashboard/i18n/locale/en/cannedMgmt.json index e3391967d..0cd52986e 100644 --- a/app/javascript/dashboard/i18n/locale/en/cannedMgmt.json +++ b/app/javascript/dashboard/i18n/locale/en/cannedMgmt.json @@ -9,11 +9,7 @@ "404": "There are no canned responses available in this account.", "TITLE": "Manage canned responses", "DESC": "Canned Responses are predefined reply templates which can be used to quickly send out replies to tickets.", - "TABLE_HEADER": [ - "Short Code", - "Content", - "Actions" - ] + "TABLE_HEADER": ["Short Code", "Content", "Actions"] }, "ADD": { "TITLE": "Add Canned Response", @@ -34,7 +30,7 @@ }, "API": { "SUCCESS_MESSAGE": "Canned Response added successfully", - "ERROR_MESSAGE": "Could not create canned response, Please try again later" + "ERROR_MESSAGE": "Could not create canned response. Please try again later." } }, "EDIT": { @@ -56,14 +52,14 @@ "BUTTON_TEXT": "Edit", "API": { "SUCCESS_MESSAGE": "Canned Response updated successfully", - "ERROR_MESSAGE": "Could not update canned response, Please try again later" + "ERROR_MESSAGE": "Could not update canned response. Please try again later." } }, "DELETE": { "BUTTON_TEXT": "Delete", "API": { "SUCCESS_MESSAGE": "Canned response deleted successfully", - "ERROR_MESSAGE": "Could not delete canned response, Please try again later" + "ERROR_MESSAGE": "Could not delete canned response. Please try again later." }, "CONFIRM": { "TITLE": "Confirm Deletion", diff --git a/app/javascript/dashboard/i18n/locale/en/contact.json b/app/javascript/dashboard/i18n/locale/en/contact.json index b96b76fb0..2ed17e3bf 100644 --- a/app/javascript/dashboard/i18n/locale/en/contact.json +++ b/app/javascript/dashboard/i18n/locale/en/contact.json @@ -78,7 +78,7 @@ "BUTTON_LABEL": "Export", "TITLE": "Export Contacts", "DESC": "Export contacts to a CSV file.", - "SUCCESS_MESSAGE": "Export is in progress, You will be notified via email when export file is ready to dowanlod.", + "SUCCESS_MESSAGE": "Export is in progress. You will be notified on email when the export file is ready to download.", "ERROR_MESSAGE": "There was an error, please try again" }, "DELETE_NOTE": { diff --git a/app/javascript/dashboard/i18n/locale/en/helpCenter.json b/app/javascript/dashboard/i18n/locale/en/helpCenter.json index 55c406fa9..65e80ad64 100644 --- a/app/javascript/dashboard/i18n/locale/en/helpCenter.json +++ b/app/javascript/dashboard/i18n/locale/en/helpCenter.json @@ -179,7 +179,8 @@ } }, "ADD": { - "CREATE_FLOW": [{ + "CREATE_FLOW": [ + { "title": "Help center information", "route": "new_portal_information", "body": "Basic information about portal", @@ -235,13 +236,13 @@ "DOMAIN": { "LABEL": "Custom Domain", "PLACEHOLDER": "Portal custom domain", - "HELP_TEXT": "Add only If you want to use a custom domain for your portals. Eg: https://example.com", + "HELP_TEXT": "Add only If you want to use a custom domain for your portals. Eg: %{exampleURL}", "ERROR": "Enter a valid domain URL" }, "HOME_PAGE_LINK": { "LABEL": "Home Page Link", "PLACEHOLDER": "Portal home page link", - "HELP_TEXT": "The link used to return from the portal to the home page. Eg: https://example.com", + "HELP_TEXT": "The link used to return from the portal to the home page. Eg: %{exampleURL}", "ERROR": "Enter a valid home page URL" }, "THEME_COLOR": { diff --git a/app/javascript/dashboard/i18n/locale/en/integrations.json b/app/javascript/dashboard/i18n/locale/en/integrations.json index 3821fe6e8..e3104bd4b 100644 --- a/app/javascript/dashboard/i18n/locale/en/integrations.json +++ b/app/javascript/dashboard/i18n/locale/en/integrations.json @@ -21,7 +21,7 @@ }, "END_POINT": { "LABEL": "Webhook URL", - "PLACEHOLDER": "Example: https://example/api/webhook", + "PLACEHOLDER": "Example: %{webhookExampleURL}", "ERROR": "Please enter a valid URL" }, "EDIT_SUBMIT": "Update webhook", diff --git a/app/javascript/dashboard/routes/dashboard/helpcenter/components/PortalSettingsBasicForm.vue b/app/javascript/dashboard/routes/dashboard/helpcenter/components/PortalSettingsBasicForm.vue index dbd662b1d..255e1acc5 100644 --- a/app/javascript/dashboard/routes/dashboard/helpcenter/components/PortalSettingsBasicForm.vue +++ b/app/javascript/dashboard/routes/dashboard/helpcenter/components/PortalSettingsBasicForm.vue @@ -61,7 +61,7 @@ :class="{ error: $v.domain.$error }" :label="$t('HELP_CENTER.PORTAL.ADD.DOMAIN.LABEL')" :placeholder="$t('HELP_CENTER.PORTAL.ADD.DOMAIN.PLACEHOLDER')" - :help-text="$t('HELP_CENTER.PORTAL.ADD.DOMAIN.HELP_TEXT')" + :help-text="domainExampleHelpText" :error="domainError" @blur="$v.domain.$touch" /> @@ -86,6 +86,9 @@ import { isDomain } from 'shared/helpers/Validators'; import thumbnail from 'dashboard/components/widgets/Thumbnail'; import { convertToCategorySlug } from 'dashboard/helper/commons.js'; import { buildPortalURL } from 'dashboard/helper/portalHelper'; +import wootConstants from 'dashboard/constants/globals'; + +const { EXAMPLE_URL } = wootConstants; export default { components: { @@ -147,6 +150,11 @@ export default { domainHelpText() { return buildPortalURL(this.slug); }, + domainExampleHelpText() { + return this.$t('HELP_CENTER.PORTAL.ADD.DOMAIN.HELP_TEXT', { + exampleURL: EXAMPLE_URL, + }); + }, }, mounted() { const portal = this.portal || {}; diff --git a/app/javascript/dashboard/routes/dashboard/helpcenter/components/PortalSettingsCustomizationForm.vue b/app/javascript/dashboard/routes/dashboard/helpcenter/components/PortalSettingsCustomizationForm.vue index 4d72fa791..ba055a419 100644 --- a/app/javascript/dashboard/routes/dashboard/helpcenter/components/PortalSettingsCustomizationForm.vue +++ b/app/javascript/dashboard/routes/dashboard/helpcenter/components/PortalSettingsCustomizationForm.vue @@ -41,7 +41,7 @@ :placeholder=" $t('HELP_CENTER.PORTAL.ADD.HOME_PAGE_LINK.PLACEHOLDER') " - :help-text="$t('HELP_CENTER.PORTAL.ADD.HOME_PAGE_LINK.HELP_TEXT')" + :help-text="homepageExampleHelpText" :error=" $v.homePageLink.$error ? $t('HELP_CENTER.PORTAL.ADD.HOME_PAGE_LINK.ERROR') @@ -74,6 +74,9 @@ import { url } from 'vuelidate/lib/validators'; import { getRandomColor } from 'dashboard/helper/labelColor'; import alertMixin from 'shared/mixins/alertMixin'; +import wootConstants from 'dashboard/constants/globals'; + +const { EXAMPLE_URL } = wootConstants; export default { components: {}, @@ -102,6 +105,13 @@ export default { url, }, }, + computed: { + homepageExampleHelpText() { + return this.$t('HELP_CENTER.PORTAL.ADD.HOME_PAGE_LINK.HELP_TEXT', { + exampleURL: EXAMPLE_URL, + }); + }, + }, mounted() { this.color = getRandomColor(); this.updateDataFromStore(); diff --git a/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/WebhookForm.vue b/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/WebhookForm.vue index 0463dd07b..1bb111d84 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/WebhookForm.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/WebhookForm.vue @@ -7,9 +7,7 @@ v-model.trim="url" type="text" name="url" - :placeholder=" - $t('INTEGRATION_SETTINGS.WEBHOOK.FORM.END_POINT.PLACEHOLDER') - " + :placeholder="webhookURLInputPlaceholder" @input="$v.url.$touch" /> @@ -53,6 +51,9 @@