From bf559f65d8e8b1bdf960a53c76861f53374b200d Mon Sep 17 00:00:00 2001 From: Dima Grossman Date: Sun, 7 Nov 2021 22:14:11 +0200 Subject: [PATCH] Notification Infrastructure seed release (#73) --- .editorconfig | 11 + .eslintignore | 12 + .eslintrc.js | 64 + .eslintrc.json | 30 - .github/workflows/test-api.yml | 92 + .github/workflows/test-core.yml | 9 + .github/workflows/test-sdk.yml | 50 + .github/workflows/test-web.yml | 105 + .github/workflows/test-widget.yml | 90 + .gitignore | 88 +- .nvmrc | 1 + .prettierrc | 11 + .yarnrc | 1 + Dockerfile.api | 31 + Dockerfile.ws | 28 + _templates/module/new/controller.ejs.t | 9 + _templates/module/new/module.ejs.t | 14 + _templates/module/new/prompt.ejs.t | 10 + _templates/module/new/usecase-index.ejs.t | 7 + _templates/usecase/new/command.ejs.t | 13 + _templates/usecase/new/import-inject.ejs.t | 8 + .../usecase/new/import-row-inject.ejs.t | 8 + _templates/usecase/new/prompt.ejs.t | 15 + _templates/usecase/new/usecase.ejs.t | 14 + apps/api/.eslintrc.js | 7 + apps/api/.gitignore | 120 + apps/api/.mocharc.json | 7 + apps/api/README.md | 79 + .../e2e/api/healthcheck/health-check.e2e.ts | 19 + .../organization/create-organization.e2e.ts | 43 + .../organization/get-my-organization.e2e.ts | 19 + .../members/change-member-role.e2e.ts | 64 + .../organization/members/get-members.e2e.ts | 57 + .../organization/members/remove-member.e2e.ts | 66 + apps/api/e2e/api/user/get-me.e2e.ts | 21 + apps/api/e2e/mocha.e2e.opts | 0 apps/api/e2e/setup.ts | 25 + apps/api/nodemon-debug.json | 6 + apps/api/nodemon.json | 8 + apps/api/package.json | 89 + apps/api/src/.example.env | 32 + apps/api/src/app.module.ts | 71 + .../src/app/activity/activity.controller.ts | 58 + apps/api/src/app/activity/activity.module.ts | 11 + .../app/activity/e2e/get-activity-feed.e2e.ts | 126 + .../activity/e2e/get-activity-stats.e2e.ts | 69 + .../get-activity-feed.command.ts | 29 + .../get-activity-feed.usecase.ts | 53 + .../get-activity-stats.command.ts | 8 + .../get-activity-stats.usecase.ts | 37 + apps/api/src/app/activity/usecases/index.ts | 8 + apps/api/src/app/admin/admin.module.ts | 11 + .../admin/entities/users/users.controller.ts | 21 + .../app/admin/entities/users/users.service.ts | 10 + .../applications/applications.controller.ts | 90 + .../app/applications/applications.module.ts | 12 + .../dto/create-application.dto.ts | 6 + .../e2e/update-branding-details.e2e.ts | 32 + .../create-application.command.ts | 12 + .../create-application.e2e.ts | 34 + .../create-application.usecase.ts | 24 + .../get-api-keys/get-api-keys.command.ts | 8 + .../get-api-keys/get-api-keys.usecase.ts | 12 + .../get-application.command.ts | 8 + .../get-application/get-application.e2e.ts | 18 + .../get-application.usecase.ts | 18 + .../usecases/get-application/index.ts | 2 + .../src/app/applications/usecases/index.ts | 12 + .../update-branding-details.command.ts | 27 + .../update-branding-details.usecase.ts | 22 + apps/api/src/app/auth/auth.controller.ts | 176 + apps/api/src/app/auth/auth.module.ts | 68 + apps/api/src/app/auth/dtos/login.dto.ts | 10 + .../app/auth/dtos/user-registration.dto.ts | 20 + apps/api/src/app/auth/e2e/login.e2e.ts | 49 + .../src/app/auth/e2e/password-reset.e2e.ts | 76 + .../app/auth/e2e/switch-organization.e2e.ts | 72 + .../src/app/auth/e2e/user-registration.e2e.ts | 86 + apps/api/src/app/auth/framework/auth.guard.ts | 34 + .../auth/framework/external-api.decorator.ts | 3 + .../src/app/auth/framework/roles.decorator.ts | 3 + .../api/src/app/auth/framework/roles.guard.ts | 27 + .../framework/subscriber-route.decorator.ts | 3 + .../auth/framework/subscriber-route.guard.ts | 29 + .../src/app/auth/services/auth.interface.ts | 0 .../api/src/app/auth/services/auth.service.ts | 235 + .../auth/services/passport/github.strategy.ts | 45 + .../auth/services/passport/jwt.strategy.ts | 24 + .../passport/subscriber-jwt.strategy.ts | 29 + apps/api/src/app/auth/usecases/index.ts | 16 + .../app/auth/usecases/login/login.command.ts | 16 + .../app/auth/usecases/login/login.usecase.ts | 27 + .../password-reset-request.command.ts | 13 + .../password-reset-request.usecase.ts | 31 + .../password-reset/password-reset.command.ts | 20 + .../password-reset/password-reset.usecase.ts | 43 + .../register/user-register.command.ts | 26 + .../register/user-register.usecase.ts | 74 + .../switch-application.command.ts | 12 + .../switch-application.e2e.ts | 35 + .../switch-application.usecase.ts | 28 + .../switch-organization.command.ts | 12 + .../switch-organization.usecase.ts | 30 + .../src/app/channels/channels.controller.ts | 49 + apps/api/src/app/channels/channels.module.ts | 11 + .../channels/e2e/update-email-settings.e2e.ts | 23 + .../channels/e2e/update-sms-settings.e2e.ts | 25 + apps/api/src/app/channels/usecases/index.ts | 8 + .../update-mail-settings.command.ts | 16 + .../update-mail-settings.usecase.ts | 24 + .../update-sms-settings.command.ts | 24 + .../update-sms-settings.usecase.ts | 25 + .../content-templates.controller.ts | 4 + .../content-templates.module.ts | 12 + .../compile-template.command.ts | 17 + .../compile-template/compile-template.spec.ts | 70 + .../compile-template.usecase.ts | 41 + .../templates/basic.handlebars | 468 + .../app/content-templates/usecases/index.ts | 6 + .../src/app/events/dto/trigger-event.dto.ts | 10 + .../src/app/events/e2e/trigger-event.e2e.ts | 373 + apps/api/src/app/events/events.controller.ts | 29 + apps/api/src/app/events/events.module.ts | 25 + apps/api/src/app/events/usecases/index.ts | 3 + .../events/usecases/trigger-event/index.ts | 2 + .../message-filter.matcher.spec.ts | 239 + .../trigger-event/message-filter.matcher.ts | 58 + .../trigger-event/trigger-event.command.ts | 20 + .../trigger-event/trigger-event.usecase.ts | 566 + apps/api/src/app/health/health.controller.ts | 36 + apps/api/src/app/health/health.module.ts | 11 + .../src/app/invites/e2e/accept-invite.e2e.ts | 75 + .../src/app/invites/e2e/bulk-invite.e2e.ts | 143 + .../api/src/app/invites/e2e/get-invite.e2e.ts | 72 + .../api/src/app/invites/invites.controller.ts | 94 + apps/api/src/app/invites/invites.module.ts | 13 + .../accept-invite/accept-invite.command.ts | 12 + .../accept-invite/accept-invite.usecase.ts | 62 + .../bulk-invite/bulk-invite.command.ts | 14 + .../bulk-invite/bulk-invite.usecase.ts | 59 + .../usecases/get-invite/get-invite.command.ts | 11 + .../usecases/get-invite/get-invite.usecase.ts | 44 + apps/api/src/app/invites/usecases/index.ts | 6 + .../invite-member/invite-member.command.ts | 17 + .../invite-member/invite-member.usecase.ts | 56 + apps/api/src/app/logs/logs.controller.ts | 4 + apps/api/src/app/logs/logs.module.ts | 12 + .../usecases/create-log/create-log.command.ts | 44 + .../usecases/create-log/create-log.usecase.ts | 32 + apps/api/src/app/logs/usecases/index.ts | 6 + .../message-template.controller.ts | 4 + .../message-template.module.ts | 12 + .../shared/sanitizer.service.spec.ts | 27 + .../shared/sanitizer.service.ts | 26 + .../create-message-template.command.ts | 31 + .../create-message-template.usecase.ts | 23 + .../app/message-template/usecases/index.ts | 8 + .../update-message-template.command.ts | 35 + .../update-message-template.usecase.ts | 48 + .../dto/create-notification-group.dto.ts | 7 + .../e2e/create-notification-group.e2e.ts | 22 + .../e2e/get-notification-groups.e2e.ts | 33 + .../notification-groups.controller.ts | 45 + .../notification-groups.module.ts | 11 + .../create-notification-group.command.ts | 12 + .../create-notification-group.usecase.ts | 16 + .../get-notification-groups.command.ts | 8 + .../get-notification-groups.usecase.ts | 34 + .../app/notification-groups/usecases/index.ts | 8 + .../dto/change-template-status.dto.ts | 7 + .../dto/create-notification-template.dto.ts | 89 + .../dto/update-notification-template.dto.ts | 58 + .../e2e/change-template-status.e2e.ts | 33 + .../e2e/create-notification-templates.e2e.ts | 137 + .../e2e/get-notification-template.e2e.ts | 31 + .../e2e/get-notification-templates.e2e.ts | 31 + .../e2e/update-notification-template.e2e.ts | 66 + .../notification-template.controller.ts | 122 + .../notification-template.module.ts | 15 + .../change-template-active-status.command.ts | 17 + .../change-template-active-status.usecase.ts | 36 + .../create-notification-template.command.ts | 106 + .../create-notification-template.usecase.ts | 71 + .../create-notification-template/index.ts | 2 + .../get-notification-template.command.ts | 13 + .../get-notification-template.usecase.ts | 17 + .../get-notification-templates.command.ts | 9 + .../get-notification-templates.usecase.ts | 13 + .../notification-template/usecases/index.ts | 14 + .../update-notification-template.command.ts | 88 + .../update-notification-template.usecase.ts | 118 + .../dtos/bulk-invite-members.dto.ts | 18 + .../dtos/create-organization.dto.ts | 11 + .../app/organization/dtos/get-invite.dto.ts | 0 .../dtos/get-my-organization.dto.ts | 3 + .../organization/dtos/invite-member.dto.ts | 11 + .../organization/organization.controller.ts | 119 + .../app/organization/organization.module.ts | 21 + .../create-organization.command.ts | 12 + .../create-organization.usecase.ts | 73 + .../get-my-organization.command.ts | 12 + .../get-my-organization.usecase.ts | 23 + .../get-organization.command.ts | 10 + .../get-organization.usecase.ts | 16 + .../src/app/organization/usecases/index.ts | 17 + .../add-member/add-member.command.ts | 13 + .../add-member/add-member.usecase.ts | 34 + .../add-member/add-member.command.ts | 13 + .../add-member/add-member.usecase.ts | 34 + .../change-member-role.command.ts | 17 + .../change-member-role.usecase.ts | 36 + .../get-members/get-members.command.ts | 8 + .../get-members/get-members.usecase.ts | 14 + .../remove-member/remove-member.command.ts | 12 + .../remove-member/remove-member.usecase.ts | 25 + .../remove-member/remove-member.command.ts | 12 + .../remove-member/remove-member.usecase.ts | 25 + .../shared/commands/authenticated.command.ts | 6 + .../src/app/shared/commands/command.helper.ts | 21 + .../shared/commands/organization.command.ts | 7 + .../app/shared/commands/project.command.ts | 31 + apps/api/src/app/shared/constants.ts | 2 + .../app/shared/crud/mongoose-crud.service.ts | 168 + .../app/shared/exceptions/api.exception.ts | 3 + .../shared/framework/response.interceptor.ts | 44 + .../app/shared/framework/user.decorator.ts | 50 + .../shared/helpers/content.service.spec.ts | 184 + .../src/app/shared/helpers/content.service.ts | 77 + .../helpers/email-normalization.service.ts | 48 + .../src/app/shared/helpers/regex.service.ts | 5 + .../services/analytics/analytics.service.ts | 51 + .../app/shared/services/cron/cron.service.ts | 30 + .../shared/services/helper/helper.service.ts | 18 + .../app/shared/services/mail/mail.service.ts | 56 + .../src/app/shared/services/queue/index.ts | 1 + .../shared/services/queue/queue.interface.ts | 9 + .../shared/services/queue/queue.service.ts | 38 + .../app/shared/services/sms/sms.service.ts | 19 + .../services/storage/storage.service.ts | 33 + apps/api/src/app/shared/shared.module.ts | 71 + .../src/app/storage/e2e/get-signed-url.e2e.ts | 21 + .../api/src/app/storage/storage.controller.ts | 25 + apps/api/src/app/storage/storage.module.ts | 11 + .../get-signed-url/get-signed-url.command.ts | 13 + .../get-signed-url/get-signed-url.usecase.ts | 27 + apps/api/src/app/storage/usecases/index.ts | 6 + .../src/app/subscribers/subscribers.module.ts | 12 + .../create-subscriber.command.ts | 29 + .../create-subscriber.spec.ts | 60 + .../create-subscriber.usecase.ts | 39 + .../usecases/create-subscriber/index.ts | 2 + .../api/src/app/subscribers/usecases/index.ts | 4 + .../usecases/update-subscriber/index.ts | 2 + .../update-subscriber.command.ts | 26 + .../update-subscriber.spec.ts | 42 + .../update-subscriber.usecase.ts | 45 + .../api/src/app/testing/dtos/seed-data.dto.ts | 8 + .../api/src/app/testing/testing.controller.ts | 48 + apps/api/src/app/testing/testing.module.ts | 12 + .../create-session/create-session.command.ts | 7 + .../create-session/create-session.usecase.ts | 17 + apps/api/src/app/testing/usecases/index.ts | 4 + .../usecases/seed-data/seed-data.command.ts | 7 + .../usecases/seed-data/seed-data.usecase.ts | 27 + apps/api/src/app/user/dtos/get-my-profile.ts | 3 + .../usecases/create-user/create-user.dto.ts | 23 + .../create-user/create-user.usecase.ts | 29 + .../get-my-profile/get-my-profile.dto.ts | 8 + .../get-my-profile/get-my-profile.usecase.ts | 12 + apps/api/src/app/user/usecases/index.ts | 4 + apps/api/src/app/user/user.controller.ts | 24 + apps/api/src/app/user/user.module.ts | 12 + .../widgets/dtos/session-initialize.dto.ts | 24 + .../e2e/initialize-widget-session.e2e.ts | 32 + .../src/app/widgets/e2e/mark-as-seen.e2e.ts | 58 + .../get-application-data.command.ts | 8 + .../get-application-data.usecase.ts | 18 + .../get-notifications-feed.command.ts | 12 + .../get-notifications-feed.usecase.ts | 21 + .../get-unseen-count.command.ts | 8 + .../get-unseen-count.usecase.ts | 21 + .../get-widget-settings.command.ts | 12 + .../get-widget-settings.usecase.ts | 22 + apps/api/src/app/widgets/usecases/index.ts | 16 + .../initialize-session.command.ts | 27 + .../initialize-session.usecase.ts | 45 + .../mark-message-as-seen.command.ts | 12 + .../mark-message-as-seen.usecase.ts | 30 + .../api/src/app/widgets/widgets.controller.ts | 110 + apps/api/src/app/widgets/widgets.module.ts | 14 + apps/api/src/bootstrap.ts | 93 + apps/api/src/config/env-validator.ts | 32 + apps/api/src/config/index.ts | 29 + apps/api/src/main.ts | 3 + apps/api/src/newrelic.js | 68 + apps/api/src/types/env.d.ts | 13 + apps/api/tsconfig.build.json | 20 + apps/api/tsconfig.json | 12 + apps/api/tsconfig.spec.json | 7 + apps/web/.babelrc | 18 + apps/web/.env | 1 + apps/web/.eslintrc.js | 33 + apps/web/.gitignore | 26 + apps/web/.vscode/settings.json | 2 + apps/web/README.md | 46 + apps/web/craco.config.js | 19 + apps/web/cypress.json | 20 + apps/web/cypress/.eslintrc.js | 10 + apps/web/cypress/fixtures/test-logo.png | Bin 0 -> 8713 bytes apps/web/cypress/global.d.ts | 31 + apps/web/cypress/plugins/index.ts | 98 + apps/web/cypress/support/commands.ts | 30 + apps/web/cypress/support/index.ts | 24 + .../web/cypress/tests/activities-page.spec.ts | 69 + apps/web/cypress/tests/auth.spec.ts | 69 + apps/web/cypress/tests/explore.spec.ts | 9 + apps/web/cypress/tests/invites.spec.ts | 43 + apps/web/cypress/tests/layout/header.spec.ts | 41 + .../cypress/tests/layout/side-menu.spec.ts | 14 + .../tests/notifications-editor.spec.ts | 384 + apps/web/cypress/tests/notifications.spec.ts | 27 + .../tests/organization-settings.spec.ts | 11 + apps/web/cypress/tests/settings.spec.ts | 112 + apps/web/cypress/tsconfig.json | 12 + apps/web/netlify.toml | 4 + apps/web/package.json | 109 + apps/web/public/favicon.ico | Bin 0 -> 15086 bytes apps/web/public/index.html | 43 + apps/web/public/logo192.png | Bin 0 -> 5347 bytes apps/web/public/logo512.png | Bin 0 -> 9664 bytes apps/web/public/manifest.json | 25 + apps/web/public/robots.txt | 3 + apps/web/public/static/images/avatar.png | Bin 0 -> 2011 bytes apps/web/public/static/images/login_bg.jpg | Bin 0 -> 44377 bytes apps/web/public/static/images/login_bg.png | Bin 0 -> 762612 bytes .../static/images/login_illustration.png | Bin 0 -> 37475 bytes .../static/images/login_illustration.svg | 1 + .../public/static/images/logo-black-white.png | Bin 0 -> 168496 bytes apps/web/public/static/images/logo-light.png | Bin 0 -> 25516 bytes apps/web/public/static/images/logo.png | Bin 0 -> 27428 bytes apps/web/public/vercel.svg | 4 + apps/web/src/App.test.tsx | 9 + apps/web/src/App.tsx | 149 + apps/web/src/api/activity.ts | 14 + apps/web/src/api/api.client.ts | 45 + apps/web/src/api/application.ts | 21 + apps/web/src/api/hooks/use-application.ts | 13 + apps/web/src/api/hooks/use-templates.ts | 12 + apps/web/src/api/invitation.ts | 5 + apps/web/src/api/notifications.ts | 9 + apps/web/src/api/organization.ts | 17 + apps/web/src/api/storage.ts | 5 + apps/web/src/api/templates.ts | 18 + apps/web/src/api/user.ts | 5 + apps/web/src/components/auth/LoginForm.tsx | 100 + .../src/components/auth/PasswordResetForm.tsx | 113 + .../auth/PasswordResetRequestForm.tsx | 63 + apps/web/src/components/auth/SignUpForm.tsx | 146 + .../web/src/components/layout/LoginLayout.tsx | 13 + .../layout/app-layout/AppLayout.tsx | 116 + .../layout/components/HeaderNav.tsx | 112 + .../layout/components/PageHeader.tsx | 27 + .../components/layout/components/SideNav.tsx | 46 + .../components/layout/components/TopNav.tsx | 20 + .../onboarding/ApplicationCreateForm.tsx | 72 + .../query-builder/components/Builder.tsx | 136 + .../query-builder/components/Button.tsx | 14 + .../components/Component/Component.tsx | 52 + .../components/Component/index.tsx | 135 + .../query-builder/components/Context.tsx | 77 + .../query-builder/components/Form/Input.tsx | 26 + .../query-builder/components/Form/Select.tsx | 32 + .../components/Form/SelectMulti.tsx | 49 + .../query-builder/components/Form/Switch.tsx | 67 + .../query-builder/components/Group/Group.tsx | 56 + .../query-builder/components/Group/Option.tsx | 23 + .../query-builder/components/Group/index.tsx | 163 + .../query-builder/components/Iterator.tsx | 50 + .../query-builder/components/RemoveButton.tsx | 15 + .../components/SecondaryButton.tsx | 7 + .../query-builder/components/Text.tsx | 11 + .../components/Widgets/Boolean.tsx | 33 + .../components/Widgets/FieldSelect.tsx | 102 + .../components/Widgets/Input.tsx | 57 + .../components/Widgets/OperatorSelect.tsx | 57 + .../components/Widgets/Select.tsx | 41 + .../components/Widgets/SelectMulti.tsx | 56 + .../query-builder/constants/colors.ts | 13 + .../query-builder/constants/strings.ts | 63 + .../query-builder/utils/assignIds.ts | 21 + .../components/query-builder/utils/clone.ts | 1 + .../query-builder/utils/denormalizeTree.ts | 40 + .../query-builder/utils/normalizeTree.ts | 39 + .../components/query-builder/utils/types.ts | 33 + .../components/templates/EmailContentCard.tsx | 186 + .../templates/EmailMessagesCards.tsx | 127 + .../components/templates/InAppEditorBlock.tsx | 88 + .../templates/MessageNameEditorHeader.tsx | 75 + .../templates/TemplateInAppEditor.tsx | 40 + .../templates/TemplateSMSEditor.tsx | 26 + .../templates/TemplateTriggerModal.tsx | 22 + .../templates/TriggerSnippetTabs.tsx | 53 + .../email-editor/ButtonRowContent.tsx | 77 + .../templates/email-editor/ContentRow.tsx | 149 + .../templates/email-editor/ControlBar.tsx | 72 + .../email-editor/EmailMessageEditor.tsx | 237 + .../components/widget/InAppWidgetPreview.tsx | 198 + apps/web/src/config/index.ts | 6 + apps/web/src/index.tsx | 19 + apps/web/src/logo.svg | 1 + apps/web/src/pages/HomePage.tsx | 5 + .../src/pages/activities/ActivitiesPage.tsx | 210 + apps/web/src/pages/auth/InvitationScreen.tsx | 70 + apps/web/src/pages/auth/login.tsx | 63 + apps/web/src/pages/auth/password-reset.tsx | 105 + apps/web/src/pages/auth/signup.tsx | 60 + apps/web/src/pages/onboarding/application.tsx | 58 + .../OrganizationSettingsPage.tsx | 103 + .../src/pages/settings/WidgetSettingsPage.tsx | 186 + .../settings/components/BrandingForm.tsx | 322 + .../pages/templates/TemplateTriggerModal.tsx | 39 + .../src/pages/templates/TemplatesListPage.tsx | 85 + .../templates/editor/TemplateEditorPage.tsx | 509 + .../use-status-change-controller.hook.ts | 34 + .../editor/use-template-controller.hook.ts | 400 + .../templates/editor/use-template.fetcher.ts | 21 + apps/web/src/react-app-env.d.ts | 1 + apps/web/src/reportWebVitals.ts | 16 + apps/web/src/setupTests.ts | 5 + apps/web/src/store/authContext.ts | 16 + apps/web/src/store/use-auth-controller.ts | 77 + apps/web/src/styles/index.less | 62 + apps/web/src/styles/theme/layout.less | 110 + apps/web/src/styles/utilities/_aligns.less | 6 + .../web/src/styles/utilities/_background.less | 7 + apps/web/src/styles/utilities/_border.less | 57 + apps/web/src/styles/utilities/_display.less | 237 + apps/web/src/styles/utilities/_flex.less | 857 + apps/web/src/styles/utilities/_float.less | 67 + apps/web/src/styles/utilities/_image.less | 4 + apps/web/src/styles/utilities/_overflow.less | 5 + apps/web/src/styles/utilities/_position.less | 31 + apps/web/src/styles/utilities/_shadow.less | 4 + apps/web/src/styles/utilities/_sizing.less | 25 + apps/web/src/styles/utilities/_spacing.less | 2167 + apps/web/src/styles/utilities/_text.less | 160 + apps/web/src/styles/utilities/utilities.less | 13 + apps/web/src/styles/variables/_colors.less | 61 + apps/web/src/styles/variables/_common.less | 1001 + apps/web/src/styles/variables/_template.less | 14 + apps/web/src/styles/variables/index.less | 3 + apps/web/src/utils/debounce.ts | 18 + apps/web/src/utils/utils.ts | 3 + apps/web/tsconfig.json | 30 + apps/widget/.env | 1 + apps/widget/.gitignore | 26 + apps/widget/README.md | 46 + apps/widget/craco.config.js | 23 + apps/widget/cypress.json | 10 + apps/widget/cypress/.eslintrc.js | 6 + apps/widget/cypress/fixtures/example.json | 5 + apps/widget/cypress/global.d.ts | 37 + .../cypress/integration/branding.spec.ts | 36 + .../integration/initialization.spec.ts | 14 + .../integration/notifications-list.spec.ts | 75 + .../cypress/integration/shell-embed.spec.ts | 61 + apps/widget/cypress/plugins/index.ts | 97 + apps/widget/cypress/support/commands.ts | 115 + apps/widget/cypress/support/index.ts | 20 + .../cypress/test-shell/example/test.html | 10 + apps/widget/cypress/test-shell/index.html | 216 + apps/widget/cypress/tsconfig.json | 20 + apps/widget/netlify.toml | 4 + apps/widget/package.json | 94 + apps/widget/public/favicon.ico | Bin 0 -> 3870 bytes .../public/iframeResizer.contentWindow.js | 1310 + apps/widget/public/index.html | 48 + apps/widget/public/logo192.png | Bin 0 -> 5347 bytes apps/widget/public/logo512.png | Bin 0 -> 9664 bytes apps/widget/public/manifest.json | 25 + apps/widget/public/robots.txt | 3 + apps/widget/src/App.test.tsx | 9 + apps/widget/src/App.tsx | 133 + apps/widget/src/ApplicationShell.tsx | 42 + apps/widget/src/Main.tsx | 81 + apps/widget/src/api/api.service.ts | 10 + apps/widget/src/api/application.ts | 5 + apps/widget/src/api/initialize-session.ts | 16 + apps/widget/src/api/notifications.ts | 14 + apps/widget/src/api/sdk.service.ts | 17 + apps/widget/src/api/shared.ts | 2 + apps/widget/src/api/usage.ts | 8 + .../src/components/NotificationListItem.tsx | 83 + .../src/components/NotificationsList.tsx | 42 + apps/widget/src/components/SeenAllBlock.tsx | 12 + apps/widget/src/components/layout/Footer.tsx | 48 + apps/widget/src/components/layout/Header.tsx | 68 + apps/widget/src/components/layout/Layout.tsx | 43 + apps/widget/src/global.d.ts | 10 + apps/widget/src/hooks/use-auth.hook.ts | 12 + .../src/hooks/use-initialization.hook.ts | 77 + apps/widget/src/hooks/use-socket.hook.ts | 10 + apps/widget/src/index.tsx | 16 + apps/widget/src/logo.svg | 1 + apps/widget/src/react-app-env.d.ts | 1 + apps/widget/src/reportWebVitals.ts | 17 + apps/widget/src/setupTests.ts | 5 + apps/widget/src/store/auth.context.ts | 20 + apps/widget/src/store/socket/socket.store.ts | 16 + .../src/store/socket/use-socket-controller.ts | 38 + apps/widget/src/store/use-auth-controller.ts | 52 + apps/widget/src/styles/theme.less | 5 + apps/widget/tsconfig.json | 31 + apps/ws/.eslintrc.js | 4 + apps/ws/.gitignore | 37 + apps/ws/nest-cli.json | 10 + apps/ws/nodemon.json | 8 + apps/ws/package.json | 72 + apps/ws/src/app.controller.ts | 12 + apps/ws/src/app.module.ts | 31 + apps/ws/src/app.service.ts | 8 + apps/ws/src/bootstrap.ts | 33 + apps/ws/src/config/index.ts | 37 + apps/ws/src/global.d.ts | 5 + apps/ws/src/health/health.controller.ts | 36 + apps/ws/src/health/health.module.ts | 11 + apps/ws/src/main.ts | 3 + apps/ws/src/shared/constants.ts | 2 + .../ws/src/shared/exceptions/api.exception.ts | 3 + apps/ws/src/shared/framework/redis.adapter.ts | 15 + .../shared/framework/response.interceptor.ts | 36 + .../ws/src/shared/framework/user.decorator.ts | 50 + .../helpers/email-normalization.service.ts | 48 + apps/ws/src/shared/helpers/regex.service.ts | 5 + apps/ws/src/shared/queue/index.ts | 1 + apps/ws/src/shared/queue/queue.interface.ts | 9 + apps/ws/src/shared/queue/queue.service.ts | 38 + apps/ws/src/shared/shared.module.ts | 58 + apps/ws/src/socket/socket.module.ts | 19 + apps/ws/src/socket/ws.gateway.ts | 39 + apps/ws/tsconfig.build.json | 20 + apps/ws/tsconfig.json | 12 + environment/test/docker-compose.yml | 18 + lerna.json | 9 +- libs/dal/.dockerignore | 1 + libs/dal/.eslintrc.js | 3 + libs/dal/.gitignore | 115 + libs/dal/nodemon.json | 6 + libs/dal/package.json | 69 + libs/dal/src/dal.service.ts | 32 + libs/dal/src/index.ts | 13 + .../application/application.entity.ts | 42 + .../application/application.repository.ts | 68 + .../application/application.schema.ts | 57 + .../dal/src/repositories/application/index.ts | 2 + libs/dal/src/repositories/base-repository.ts | 94 + libs/dal/src/repositories/log/index.ts | 3 + libs/dal/src/repositories/log/log.entity.ts | 27 + .../src/repositories/log/log.repository.ts | 9 + libs/dal/src/repositories/log/log.schema.ts | 56 + libs/dal/src/repositories/member/index.ts | 2 + .../src/repositories/member/member.entity.ts | 18 + .../repositories/member/member.repository.ts | 161 + .../src/repositories/member/member.schema.ts | 41 + .../repositories/message-template/index.ts | 3 + .../message-template.entity.ts | 40 + .../message-template.repository.ts | 9 + .../message-template.schema.ts | 51 + libs/dal/src/repositories/message/index.ts | 3 + .../repositories/message/message.entity.ts | 57 + .../message/message.repository.ts | 129 + .../repositories/message/message.schema.ts | 87 + .../repositories/notification-group/index.ts | 3 + .../notification-group.entity.ts | 9 + .../notification-group.repository.ts | 9 + .../notification-group.schema.ts | 29 + .../notification-template/index.ts | 3 + .../notification-template.entity.ts | 71 + .../notification-template.repository.ts | 36 + .../notification-template.schema.ts | 102 + .../src/repositories/notification/index.ts | 3 + .../notification/notification.entity.ts | 17 + .../notification/notification.repository.ts | 16 + .../notification/notification.schema.ts | 61 + .../src/repositories/organization/index.ts | 2 + .../organization/organization.entity.ts | 7 + .../organization/organization.repository.ts | 20 + .../organization/organization.schema.ts | 19 + .../repositories/schema-default.options.ts | 7 + libs/dal/src/repositories/subscriber/index.ts | 3 + .../subscriber/subscriber.entity.ts | 17 + .../subscriber/subscriber.repository.ts | 37 + .../subscriber/subscriber.schema.ts | 34 + .../subscription-preference/index.ts | 0 .../subscription-preference.entity.ts | 3 + .../subscription-preference.repository.ts | 9 + .../subscription-preference.schema.ts | 19 + libs/dal/src/repositories/user/index.ts | 2 + libs/dal/src/repositories/user/user.entity.ts | 35 + .../src/repositories/user/user.repository.ts | 52 + libs/dal/src/repositories/user/user.schema.ts | 34 + libs/dal/src/types/env.d.ts | 7 + libs/dal/tsconfig.build.json | 16 + libs/dal/tsconfig.json | 8 + libs/sdk/.editorconfig | 13 + libs/sdk/.gitignore | 12 + libs/sdk/README.md | 169 + libs/sdk/package.json | 130 + libs/sdk/rollup.config.ts | 57 + libs/sdk/src/global.d.ts | 3 + libs/sdk/src/sdk.ts | 302 + libs/sdk/src/shared/errors.js | 24 + libs/sdk/src/shared/eventTypes.js | 8 + libs/sdk/src/shared/helpers.js | 31 + libs/sdk/src/shared/iframeClasses.js | 2 + libs/sdk/src/shared/resources.js | 30 + libs/sdk/test/index.html | 300 + libs/sdk/test/sdk.test.ts | 14 + libs/sdk/tools/gh-pages-publish.ts | 31 + libs/sdk/tools/semantic-release-prepare.ts | 54 + libs/sdk/tsconfig.json | 23 + libs/shared/.dockerignore | 1 + libs/shared/.eslintrc.js | 3 + libs/shared/.gitignore | 115 + libs/shared/nodemon.json | 6 + libs/shared/package.json | 39 + libs/shared/src/dto/index.ts | 3 + .../create-template.dto.ts | 13 + .../src/dto/notification-templates/index.ts | 3 + .../src/dto/notification-templates/shared.ts | 17 + .../update-template.dto.ts | 13 + .../organization/create-organization.dto.ts | 12 + libs/shared/src/dto/organization/index.ts | 3 + .../members/bulk-invite-members.dto.ts | 10 + .../organization/members/get-invite.dto.ts | 14 + libs/shared/src/dto/shared/index.ts | 1 + libs/shared/src/dto/shared/shared.ts | 7 + .../application/application.interface.ts | 29 + libs/shared/src/entities/application/index.ts | 1 + libs/shared/src/entities/log/index.ts | 1 + libs/shared/src/entities/log/log.enums.ts | 19 + .../entities/message-template/channel.enum.ts | 9 + .../src/entities/message-template/index.ts | 2 + .../message-template.interface.ts | 24 + .../entities/messages/messages.interface.ts | 23 + .../entities/notification-template/index.ts | 1 + .../notification-template.interface.ts | 44 + .../shared/src/entities/notification/index.ts | 1 + .../notification/notification.interface.ts | 3 + .../shared/src/entities/organization/index.ts | 3 + .../src/entities/organization/member.enum.ts | 4 + .../entities/organization/member.interface.ts | 13 + .../organization/organization.interface.ts | 16 + libs/shared/src/entities/user/index.ts | 3 + .../user/subscriber-user.interface.ts | 9 + libs/shared/src/entities/user/user.enums.ts | 8 + .../src/entities/user/user.interface.ts | 19 + libs/shared/src/index.ts | 11 + .../shared/src/types/builder/builder.types.ts | 18 + libs/shared/tsconfig.build.json | 15 + libs/shared/tsconfig.json | 7 + libs/testing/.dockerignore | 1 + libs/testing/.eslintrc.js | 3 + libs/testing/.gitignore | 115 + libs/testing/nodemon.json | 6 + libs/testing/package.json | 54 + libs/testing/src/application.service.ts | 15 + .../create-notification-template.interface.ts | 12 + libs/testing/src/index.ts | 5 + .../src/notification-template.service.ts | 101 + libs/testing/src/notifications.service.ts | 24 + libs/testing/src/organization.service.ts | 26 + libs/testing/src/subscribers.service.ts | 19 + libs/testing/src/test-server.service.ts | 21 + libs/testing/src/user.session.ts | 190 + libs/testing/tsconfig.build.json | 16 + libs/testing/tsconfig.json | 8 + package.json | 85 +- packages/core/.eslintrc.json | 2 +- packages/core/package.json | 12 +- packages/core/src/index.ts | 1 - .../core/src/lib/content/content.engine.ts | 16 +- packages/core/src/lib/notifire.spec.ts | 8 +- packages/core/src/lib/notifire.ts | 4 +- .../src/lib/provider/provider.store.spec.ts | 15 +- .../src/lib/template/template.store.spec.ts | 4 +- .../core/src/lib/theme/theme.interface.ts | 1 - .../core/src/lib/theme/theme.store.spec.ts | 6 +- packages/core/src/lib/theme/theme.store.ts | 4 +- .../core/src/lib/trigger/trigger.engine.ts | 2 +- packages/core/tsconfig.json | 7 +- packages/core/tsconfig.module.json | 5 +- providers/emailjs/.eslintrc.json | 2 +- providers/emailjs/package.json | 3 +- providers/emailjs/tsconfig.json | 3 +- providers/mailgun/.eslintrc.json | 2 +- providers/mailgun/src/lib/mailgun.provider.ts | 2 + providers/mailgun/tsconfig.json | 3 +- providers/mailjet/.eslintrc.json | 2 +- providers/mailjet/tsconfig.json | 3 +- providers/mandrill/package.json | 2 - providers/nodemailer/.eslintrc.json | 2 +- providers/nodemailer/package.json | 2 +- .../src/lib/nodemailer.provider.spec.ts | 1 + .../nodemailer/src/lib/nodemailer.provider.ts | 2 + providers/nodemailer/tsconfig.json | 3 +- providers/plivo/.eslintrc.json | 2 +- providers/plivo/tsconfig.json | 3 +- providers/postmark/.eslintrc.json | 2 +- providers/postmark/tsconfig.json | 3 +- providers/sendgrid/.eslintrc.json | 2 +- providers/sendgrid/tsconfig.json | 3 +- providers/twilio/.eslintrc.json | 2 +- providers/twilio/tsconfig.json | 3 +- tsconfig.base.json | 20 + tsconfig.json | 50 +- workspace.code-workspace | 30 +- yarn.lock | 32633 ++++++++++++---- 718 files changed, 57647 insertions(+), 7170 deletions(-) create mode 100644 .editorconfig create mode 100644 .eslintignore create mode 100644 .eslintrc.js delete mode 100644 .eslintrc.json create mode 100644 .github/workflows/test-api.yml create mode 100644 .github/workflows/test-sdk.yml create mode 100644 .github/workflows/test-web.yml create mode 100644 .github/workflows/test-widget.yml create mode 100644 .nvmrc create mode 100644 .prettierrc create mode 100644 .yarnrc create mode 100644 Dockerfile.api create mode 100644 Dockerfile.ws create mode 100644 _templates/module/new/controller.ejs.t create mode 100644 _templates/module/new/module.ejs.t create mode 100644 _templates/module/new/prompt.ejs.t create mode 100644 _templates/module/new/usecase-index.ejs.t create mode 100644 _templates/usecase/new/command.ejs.t create mode 100644 _templates/usecase/new/import-inject.ejs.t create mode 100644 _templates/usecase/new/import-row-inject.ejs.t create mode 100644 _templates/usecase/new/prompt.ejs.t create mode 100644 _templates/usecase/new/usecase.ejs.t create mode 100644 apps/api/.eslintrc.js create mode 100644 apps/api/.gitignore create mode 100644 apps/api/.mocharc.json create mode 100644 apps/api/README.md create mode 100644 apps/api/e2e/api/healthcheck/health-check.e2e.ts create mode 100644 apps/api/e2e/api/organization/create-organization.e2e.ts create mode 100644 apps/api/e2e/api/organization/get-my-organization.e2e.ts create mode 100644 apps/api/e2e/api/organization/members/change-member-role.e2e.ts create mode 100644 apps/api/e2e/api/organization/members/get-members.e2e.ts create mode 100644 apps/api/e2e/api/organization/members/remove-member.e2e.ts create mode 100644 apps/api/e2e/api/user/get-me.e2e.ts create mode 100644 apps/api/e2e/mocha.e2e.opts create mode 100644 apps/api/e2e/setup.ts create mode 100644 apps/api/nodemon-debug.json create mode 100644 apps/api/nodemon.json create mode 100644 apps/api/package.json create mode 100644 apps/api/src/.example.env create mode 100644 apps/api/src/app.module.ts create mode 100644 apps/api/src/app/activity/activity.controller.ts create mode 100644 apps/api/src/app/activity/activity.module.ts create mode 100644 apps/api/src/app/activity/e2e/get-activity-feed.e2e.ts create mode 100644 apps/api/src/app/activity/e2e/get-activity-stats.e2e.ts create mode 100644 apps/api/src/app/activity/usecases/get-activity-feed/get-activity-feed.command.ts create mode 100644 apps/api/src/app/activity/usecases/get-activity-feed/get-activity-feed.usecase.ts create mode 100644 apps/api/src/app/activity/usecases/get-activity-stats/get-activity-stats.command.ts create mode 100644 apps/api/src/app/activity/usecases/get-activity-stats/get-activity-stats.usecase.ts create mode 100644 apps/api/src/app/activity/usecases/index.ts create mode 100644 apps/api/src/app/admin/admin.module.ts create mode 100644 apps/api/src/app/admin/entities/users/users.controller.ts create mode 100644 apps/api/src/app/admin/entities/users/users.service.ts create mode 100644 apps/api/src/app/applications/applications.controller.ts create mode 100644 apps/api/src/app/applications/applications.module.ts create mode 100644 apps/api/src/app/applications/dto/create-application.dto.ts create mode 100644 apps/api/src/app/applications/e2e/update-branding-details.e2e.ts create mode 100644 apps/api/src/app/applications/usecases/create-application/create-application.command.ts create mode 100644 apps/api/src/app/applications/usecases/create-application/create-application.e2e.ts create mode 100644 apps/api/src/app/applications/usecases/create-application/create-application.usecase.ts create mode 100644 apps/api/src/app/applications/usecases/get-api-keys/get-api-keys.command.ts create mode 100644 apps/api/src/app/applications/usecases/get-api-keys/get-api-keys.usecase.ts create mode 100644 apps/api/src/app/applications/usecases/get-application/get-application.command.ts create mode 100644 apps/api/src/app/applications/usecases/get-application/get-application.e2e.ts create mode 100644 apps/api/src/app/applications/usecases/get-application/get-application.usecase.ts create mode 100644 apps/api/src/app/applications/usecases/get-application/index.ts create mode 100644 apps/api/src/app/applications/usecases/index.ts create mode 100644 apps/api/src/app/applications/usecases/update-branding-details/update-branding-details.command.ts create mode 100644 apps/api/src/app/applications/usecases/update-branding-details/update-branding-details.usecase.ts create mode 100644 apps/api/src/app/auth/auth.controller.ts create mode 100644 apps/api/src/app/auth/auth.module.ts create mode 100644 apps/api/src/app/auth/dtos/login.dto.ts create mode 100644 apps/api/src/app/auth/dtos/user-registration.dto.ts create mode 100644 apps/api/src/app/auth/e2e/login.e2e.ts create mode 100644 apps/api/src/app/auth/e2e/password-reset.e2e.ts create mode 100644 apps/api/src/app/auth/e2e/switch-organization.e2e.ts create mode 100644 apps/api/src/app/auth/e2e/user-registration.e2e.ts create mode 100644 apps/api/src/app/auth/framework/auth.guard.ts create mode 100644 apps/api/src/app/auth/framework/external-api.decorator.ts create mode 100644 apps/api/src/app/auth/framework/roles.decorator.ts create mode 100644 apps/api/src/app/auth/framework/roles.guard.ts create mode 100644 apps/api/src/app/auth/framework/subscriber-route.decorator.ts create mode 100644 apps/api/src/app/auth/framework/subscriber-route.guard.ts create mode 100644 apps/api/src/app/auth/services/auth.interface.ts create mode 100644 apps/api/src/app/auth/services/auth.service.ts create mode 100644 apps/api/src/app/auth/services/passport/github.strategy.ts create mode 100644 apps/api/src/app/auth/services/passport/jwt.strategy.ts create mode 100644 apps/api/src/app/auth/services/passport/subscriber-jwt.strategy.ts create mode 100644 apps/api/src/app/auth/usecases/index.ts create mode 100644 apps/api/src/app/auth/usecases/login/login.command.ts create mode 100644 apps/api/src/app/auth/usecases/login/login.usecase.ts create mode 100644 apps/api/src/app/auth/usecases/password-reset-request/password-reset-request.command.ts create mode 100644 apps/api/src/app/auth/usecases/password-reset-request/password-reset-request.usecase.ts create mode 100644 apps/api/src/app/auth/usecases/password-reset/password-reset.command.ts create mode 100644 apps/api/src/app/auth/usecases/password-reset/password-reset.usecase.ts create mode 100644 apps/api/src/app/auth/usecases/register/user-register.command.ts create mode 100644 apps/api/src/app/auth/usecases/register/user-register.usecase.ts create mode 100644 apps/api/src/app/auth/usecases/switch-application/switch-application.command.ts create mode 100644 apps/api/src/app/auth/usecases/switch-application/switch-application.e2e.ts create mode 100644 apps/api/src/app/auth/usecases/switch-application/switch-application.usecase.ts create mode 100644 apps/api/src/app/auth/usecases/switch-organization/switch-organization.command.ts create mode 100644 apps/api/src/app/auth/usecases/switch-organization/switch-organization.usecase.ts create mode 100644 apps/api/src/app/channels/channels.controller.ts create mode 100644 apps/api/src/app/channels/channels.module.ts create mode 100644 apps/api/src/app/channels/e2e/update-email-settings.e2e.ts create mode 100644 apps/api/src/app/channels/e2e/update-sms-settings.e2e.ts create mode 100644 apps/api/src/app/channels/usecases/index.ts create mode 100644 apps/api/src/app/channels/usecases/update-mail-settings/update-mail-settings.command.ts create mode 100644 apps/api/src/app/channels/usecases/update-mail-settings/update-mail-settings.usecase.ts create mode 100644 apps/api/src/app/channels/usecases/update-sms-settings/update-sms-settings.command.ts create mode 100644 apps/api/src/app/channels/usecases/update-sms-settings/update-sms-settings.usecase.ts create mode 100644 apps/api/src/app/content-templates/content-templates.controller.ts create mode 100644 apps/api/src/app/content-templates/content-templates.module.ts create mode 100644 apps/api/src/app/content-templates/usecases/compile-template/compile-template.command.ts create mode 100644 apps/api/src/app/content-templates/usecases/compile-template/compile-template.spec.ts create mode 100644 apps/api/src/app/content-templates/usecases/compile-template/compile-template.usecase.ts create mode 100644 apps/api/src/app/content-templates/usecases/compile-template/templates/basic.handlebars create mode 100644 apps/api/src/app/content-templates/usecases/index.ts create mode 100644 apps/api/src/app/events/dto/trigger-event.dto.ts create mode 100644 apps/api/src/app/events/e2e/trigger-event.e2e.ts create mode 100644 apps/api/src/app/events/events.controller.ts create mode 100644 apps/api/src/app/events/events.module.ts create mode 100644 apps/api/src/app/events/usecases/index.ts create mode 100644 apps/api/src/app/events/usecases/trigger-event/index.ts create mode 100644 apps/api/src/app/events/usecases/trigger-event/message-filter.matcher.spec.ts create mode 100644 apps/api/src/app/events/usecases/trigger-event/message-filter.matcher.ts create mode 100644 apps/api/src/app/events/usecases/trigger-event/trigger-event.command.ts create mode 100644 apps/api/src/app/events/usecases/trigger-event/trigger-event.usecase.ts create mode 100644 apps/api/src/app/health/health.controller.ts create mode 100644 apps/api/src/app/health/health.module.ts create mode 100644 apps/api/src/app/invites/e2e/accept-invite.e2e.ts create mode 100644 apps/api/src/app/invites/e2e/bulk-invite.e2e.ts create mode 100644 apps/api/src/app/invites/e2e/get-invite.e2e.ts create mode 100644 apps/api/src/app/invites/invites.controller.ts create mode 100644 apps/api/src/app/invites/invites.module.ts create mode 100644 apps/api/src/app/invites/usecases/accept-invite/accept-invite.command.ts create mode 100644 apps/api/src/app/invites/usecases/accept-invite/accept-invite.usecase.ts create mode 100644 apps/api/src/app/invites/usecases/bulk-invite/bulk-invite.command.ts create mode 100644 apps/api/src/app/invites/usecases/bulk-invite/bulk-invite.usecase.ts create mode 100644 apps/api/src/app/invites/usecases/get-invite/get-invite.command.ts create mode 100644 apps/api/src/app/invites/usecases/get-invite/get-invite.usecase.ts create mode 100644 apps/api/src/app/invites/usecases/index.ts create mode 100644 apps/api/src/app/invites/usecases/invite-member/invite-member.command.ts create mode 100644 apps/api/src/app/invites/usecases/invite-member/invite-member.usecase.ts create mode 100644 apps/api/src/app/logs/logs.controller.ts create mode 100644 apps/api/src/app/logs/logs.module.ts create mode 100644 apps/api/src/app/logs/usecases/create-log/create-log.command.ts create mode 100644 apps/api/src/app/logs/usecases/create-log/create-log.usecase.ts create mode 100644 apps/api/src/app/logs/usecases/index.ts create mode 100644 apps/api/src/app/message-template/message-template.controller.ts create mode 100644 apps/api/src/app/message-template/message-template.module.ts create mode 100644 apps/api/src/app/message-template/shared/sanitizer.service.spec.ts create mode 100644 apps/api/src/app/message-template/shared/sanitizer.service.ts create mode 100644 apps/api/src/app/message-template/usecases/create-message-template/create-message-template.command.ts create mode 100644 apps/api/src/app/message-template/usecases/create-message-template/create-message-template.usecase.ts create mode 100644 apps/api/src/app/message-template/usecases/index.ts create mode 100644 apps/api/src/app/message-template/usecases/update-message-template/update-message-template.command.ts create mode 100644 apps/api/src/app/message-template/usecases/update-message-template/update-message-template.usecase.ts create mode 100644 apps/api/src/app/notification-groups/dto/create-notification-group.dto.ts create mode 100644 apps/api/src/app/notification-groups/e2e/create-notification-group.e2e.ts create mode 100644 apps/api/src/app/notification-groups/e2e/get-notification-groups.e2e.ts create mode 100644 apps/api/src/app/notification-groups/notification-groups.controller.ts create mode 100644 apps/api/src/app/notification-groups/notification-groups.module.ts create mode 100644 apps/api/src/app/notification-groups/usecases/create-notification-group/create-notification-group.command.ts create mode 100644 apps/api/src/app/notification-groups/usecases/create-notification-group/create-notification-group.usecase.ts create mode 100644 apps/api/src/app/notification-groups/usecases/get-notification-groups/get-notification-groups.command.ts create mode 100644 apps/api/src/app/notification-groups/usecases/get-notification-groups/get-notification-groups.usecase.ts create mode 100644 apps/api/src/app/notification-groups/usecases/index.ts create mode 100644 apps/api/src/app/notification-template/dto/change-template-status.dto.ts create mode 100644 apps/api/src/app/notification-template/dto/create-notification-template.dto.ts create mode 100644 apps/api/src/app/notification-template/dto/update-notification-template.dto.ts create mode 100644 apps/api/src/app/notification-template/e2e/change-template-status.e2e.ts create mode 100644 apps/api/src/app/notification-template/e2e/create-notification-templates.e2e.ts create mode 100644 apps/api/src/app/notification-template/e2e/get-notification-template.e2e.ts create mode 100644 apps/api/src/app/notification-template/e2e/get-notification-templates.e2e.ts create mode 100644 apps/api/src/app/notification-template/e2e/update-notification-template.e2e.ts create mode 100644 apps/api/src/app/notification-template/notification-template.controller.ts create mode 100644 apps/api/src/app/notification-template/notification-template.module.ts create mode 100644 apps/api/src/app/notification-template/usecases/change-template-active-status/change-template-active-status.command.ts create mode 100644 apps/api/src/app/notification-template/usecases/change-template-active-status/change-template-active-status.usecase.ts create mode 100644 apps/api/src/app/notification-template/usecases/create-notification-template/create-notification-template.command.ts create mode 100644 apps/api/src/app/notification-template/usecases/create-notification-template/create-notification-template.usecase.ts create mode 100644 apps/api/src/app/notification-template/usecases/create-notification-template/index.ts create mode 100644 apps/api/src/app/notification-template/usecases/get-notification-template/get-notification-template.command.ts create mode 100644 apps/api/src/app/notification-template/usecases/get-notification-template/get-notification-template.usecase.ts create mode 100644 apps/api/src/app/notification-template/usecases/get-notification-templates/get-notification-templates.command.ts create mode 100644 apps/api/src/app/notification-template/usecases/get-notification-templates/get-notification-templates.usecase.ts create mode 100644 apps/api/src/app/notification-template/usecases/index.ts create mode 100644 apps/api/src/app/notification-template/usecases/update-notification-template/update-notification-template.command.ts create mode 100644 apps/api/src/app/notification-template/usecases/update-notification-template/update-notification-template.usecase.ts create mode 100644 apps/api/src/app/organization/dtos/bulk-invite-members.dto.ts create mode 100644 apps/api/src/app/organization/dtos/create-organization.dto.ts create mode 100644 apps/api/src/app/organization/dtos/get-invite.dto.ts create mode 100644 apps/api/src/app/organization/dtos/get-my-organization.dto.ts create mode 100644 apps/api/src/app/organization/dtos/invite-member.dto.ts create mode 100644 apps/api/src/app/organization/organization.controller.ts create mode 100644 apps/api/src/app/organization/organization.module.ts create mode 100644 apps/api/src/app/organization/usecases/create-organization/create-organization.command.ts create mode 100644 apps/api/src/app/organization/usecases/create-organization/create-organization.usecase.ts create mode 100644 apps/api/src/app/organization/usecases/get-my-organization/get-my-organization.command.ts create mode 100644 apps/api/src/app/organization/usecases/get-my-organization/get-my-organization.usecase.ts create mode 100644 apps/api/src/app/organization/usecases/get-organization/get-organization.command.ts create mode 100644 apps/api/src/app/organization/usecases/get-organization/get-organization.usecase.ts create mode 100644 apps/api/src/app/organization/usecases/index.ts create mode 100644 apps/api/src/app/organization/usecases/membership/add-member/add-member.command.ts create mode 100644 apps/api/src/app/organization/usecases/membership/add-member/add-member.usecase.ts create mode 100644 apps/api/src/app/organization/usecases/membership/membership/add-member/add-member.command.ts create mode 100644 apps/api/src/app/organization/usecases/membership/membership/add-member/add-member.usecase.ts create mode 100644 apps/api/src/app/organization/usecases/membership/membership/change-member-role/change-member-role.command.ts create mode 100644 apps/api/src/app/organization/usecases/membership/membership/change-member-role/change-member-role.usecase.ts create mode 100644 apps/api/src/app/organization/usecases/membership/membership/get-members/get-members.command.ts create mode 100644 apps/api/src/app/organization/usecases/membership/membership/get-members/get-members.usecase.ts create mode 100644 apps/api/src/app/organization/usecases/membership/membership/remove-member/remove-member.command.ts create mode 100644 apps/api/src/app/organization/usecases/membership/membership/remove-member/remove-member.usecase.ts create mode 100644 apps/api/src/app/organization/usecases/membership/remove-member/remove-member.command.ts create mode 100644 apps/api/src/app/organization/usecases/membership/remove-member/remove-member.usecase.ts create mode 100644 apps/api/src/app/shared/commands/authenticated.command.ts create mode 100644 apps/api/src/app/shared/commands/command.helper.ts create mode 100644 apps/api/src/app/shared/commands/organization.command.ts create mode 100644 apps/api/src/app/shared/commands/project.command.ts create mode 100644 apps/api/src/app/shared/constants.ts create mode 100644 apps/api/src/app/shared/crud/mongoose-crud.service.ts create mode 100644 apps/api/src/app/shared/exceptions/api.exception.ts create mode 100644 apps/api/src/app/shared/framework/response.interceptor.ts create mode 100644 apps/api/src/app/shared/framework/user.decorator.ts create mode 100644 apps/api/src/app/shared/helpers/content.service.spec.ts create mode 100644 apps/api/src/app/shared/helpers/content.service.ts create mode 100644 apps/api/src/app/shared/helpers/email-normalization.service.ts create mode 100644 apps/api/src/app/shared/helpers/regex.service.ts create mode 100644 apps/api/src/app/shared/services/analytics/analytics.service.ts create mode 100644 apps/api/src/app/shared/services/cron/cron.service.ts create mode 100644 apps/api/src/app/shared/services/helper/helper.service.ts create mode 100644 apps/api/src/app/shared/services/mail/mail.service.ts create mode 100644 apps/api/src/app/shared/services/queue/index.ts create mode 100644 apps/api/src/app/shared/services/queue/queue.interface.ts create mode 100644 apps/api/src/app/shared/services/queue/queue.service.ts create mode 100644 apps/api/src/app/shared/services/sms/sms.service.ts create mode 100644 apps/api/src/app/shared/services/storage/storage.service.ts create mode 100644 apps/api/src/app/shared/shared.module.ts create mode 100644 apps/api/src/app/storage/e2e/get-signed-url.e2e.ts create mode 100644 apps/api/src/app/storage/storage.controller.ts create mode 100644 apps/api/src/app/storage/storage.module.ts create mode 100644 apps/api/src/app/storage/usecases/get-signed-url/get-signed-url.command.ts create mode 100644 apps/api/src/app/storage/usecases/get-signed-url/get-signed-url.usecase.ts create mode 100644 apps/api/src/app/storage/usecases/index.ts create mode 100644 apps/api/src/app/subscribers/subscribers.module.ts create mode 100644 apps/api/src/app/subscribers/usecases/create-subscriber/create-subscriber.command.ts create mode 100644 apps/api/src/app/subscribers/usecases/create-subscriber/create-subscriber.spec.ts create mode 100644 apps/api/src/app/subscribers/usecases/create-subscriber/create-subscriber.usecase.ts create mode 100644 apps/api/src/app/subscribers/usecases/create-subscriber/index.ts create mode 100644 apps/api/src/app/subscribers/usecases/index.ts create mode 100644 apps/api/src/app/subscribers/usecases/update-subscriber/index.ts create mode 100644 apps/api/src/app/subscribers/usecases/update-subscriber/update-subscriber.command.ts create mode 100644 apps/api/src/app/subscribers/usecases/update-subscriber/update-subscriber.spec.ts create mode 100644 apps/api/src/app/subscribers/usecases/update-subscriber/update-subscriber.usecase.ts create mode 100644 apps/api/src/app/testing/dtos/seed-data.dto.ts create mode 100644 apps/api/src/app/testing/testing.controller.ts create mode 100644 apps/api/src/app/testing/testing.module.ts create mode 100644 apps/api/src/app/testing/usecases/create-session/create-session.command.ts create mode 100644 apps/api/src/app/testing/usecases/create-session/create-session.usecase.ts create mode 100644 apps/api/src/app/testing/usecases/index.ts create mode 100644 apps/api/src/app/testing/usecases/seed-data/seed-data.command.ts create mode 100644 apps/api/src/app/testing/usecases/seed-data/seed-data.usecase.ts create mode 100644 apps/api/src/app/user/dtos/get-my-profile.ts create mode 100644 apps/api/src/app/user/usecases/create-user/create-user.dto.ts create mode 100644 apps/api/src/app/user/usecases/create-user/create-user.usecase.ts create mode 100644 apps/api/src/app/user/usecases/get-my-profile/get-my-profile.dto.ts create mode 100644 apps/api/src/app/user/usecases/get-my-profile/get-my-profile.usecase.ts create mode 100644 apps/api/src/app/user/usecases/index.ts create mode 100644 apps/api/src/app/user/user.controller.ts create mode 100644 apps/api/src/app/user/user.module.ts create mode 100644 apps/api/src/app/widgets/dtos/session-initialize.dto.ts create mode 100644 apps/api/src/app/widgets/e2e/initialize-widget-session.e2e.ts create mode 100644 apps/api/src/app/widgets/e2e/mark-as-seen.e2e.ts create mode 100644 apps/api/src/app/widgets/usecases/get-application-data/get-application-data.command.ts create mode 100644 apps/api/src/app/widgets/usecases/get-application-data/get-application-data.usecase.ts create mode 100644 apps/api/src/app/widgets/usecases/get-notifications-feed/get-notifications-feed.command.ts create mode 100644 apps/api/src/app/widgets/usecases/get-notifications-feed/get-notifications-feed.usecase.ts create mode 100644 apps/api/src/app/widgets/usecases/get-unseen-count/get-unseen-count.command.ts create mode 100644 apps/api/src/app/widgets/usecases/get-unseen-count/get-unseen-count.usecase.ts create mode 100644 apps/api/src/app/widgets/usecases/get-widget-settings/get-widget-settings.command.ts create mode 100644 apps/api/src/app/widgets/usecases/get-widget-settings/get-widget-settings.usecase.ts create mode 100644 apps/api/src/app/widgets/usecases/index.ts create mode 100644 apps/api/src/app/widgets/usecases/initialize-session/initialize-session.command.ts create mode 100644 apps/api/src/app/widgets/usecases/initialize-session/initialize-session.usecase.ts create mode 100644 apps/api/src/app/widgets/usecases/mark-message-as-seen/mark-message-as-seen.command.ts create mode 100644 apps/api/src/app/widgets/usecases/mark-message-as-seen/mark-message-as-seen.usecase.ts create mode 100644 apps/api/src/app/widgets/widgets.controller.ts create mode 100644 apps/api/src/app/widgets/widgets.module.ts create mode 100644 apps/api/src/bootstrap.ts create mode 100644 apps/api/src/config/env-validator.ts create mode 100644 apps/api/src/config/index.ts create mode 100644 apps/api/src/main.ts create mode 100644 apps/api/src/newrelic.js create mode 100644 apps/api/src/types/env.d.ts create mode 100644 apps/api/tsconfig.build.json create mode 100644 apps/api/tsconfig.json create mode 100644 apps/api/tsconfig.spec.json create mode 100644 apps/web/.babelrc create mode 100644 apps/web/.env create mode 100644 apps/web/.eslintrc.js create mode 100644 apps/web/.gitignore create mode 100644 apps/web/.vscode/settings.json create mode 100644 apps/web/README.md create mode 100644 apps/web/craco.config.js create mode 100644 apps/web/cypress.json create mode 100644 apps/web/cypress/.eslintrc.js create mode 100644 apps/web/cypress/fixtures/test-logo.png create mode 100644 apps/web/cypress/global.d.ts create mode 100644 apps/web/cypress/plugins/index.ts create mode 100644 apps/web/cypress/support/commands.ts create mode 100644 apps/web/cypress/support/index.ts create mode 100644 apps/web/cypress/tests/activities-page.spec.ts create mode 100644 apps/web/cypress/tests/auth.spec.ts create mode 100644 apps/web/cypress/tests/explore.spec.ts create mode 100644 apps/web/cypress/tests/invites.spec.ts create mode 100644 apps/web/cypress/tests/layout/header.spec.ts create mode 100644 apps/web/cypress/tests/layout/side-menu.spec.ts create mode 100644 apps/web/cypress/tests/notifications-editor.spec.ts create mode 100644 apps/web/cypress/tests/notifications.spec.ts create mode 100644 apps/web/cypress/tests/organization-settings.spec.ts create mode 100644 apps/web/cypress/tests/settings.spec.ts create mode 100644 apps/web/cypress/tsconfig.json create mode 100644 apps/web/netlify.toml create mode 100644 apps/web/package.json create mode 100644 apps/web/public/favicon.ico create mode 100644 apps/web/public/index.html create mode 100644 apps/web/public/logo192.png create mode 100644 apps/web/public/logo512.png create mode 100644 apps/web/public/manifest.json create mode 100644 apps/web/public/robots.txt create mode 100644 apps/web/public/static/images/avatar.png create mode 100644 apps/web/public/static/images/login_bg.jpg create mode 100644 apps/web/public/static/images/login_bg.png create mode 100644 apps/web/public/static/images/login_illustration.png create mode 100644 apps/web/public/static/images/login_illustration.svg create mode 100644 apps/web/public/static/images/logo-black-white.png create mode 100644 apps/web/public/static/images/logo-light.png create mode 100644 apps/web/public/static/images/logo.png create mode 100644 apps/web/public/vercel.svg create mode 100644 apps/web/src/App.test.tsx create mode 100644 apps/web/src/App.tsx create mode 100644 apps/web/src/api/activity.ts create mode 100644 apps/web/src/api/api.client.ts create mode 100644 apps/web/src/api/application.ts create mode 100644 apps/web/src/api/hooks/use-application.ts create mode 100644 apps/web/src/api/hooks/use-templates.ts create mode 100644 apps/web/src/api/invitation.ts create mode 100644 apps/web/src/api/notifications.ts create mode 100644 apps/web/src/api/organization.ts create mode 100644 apps/web/src/api/storage.ts create mode 100644 apps/web/src/api/templates.ts create mode 100644 apps/web/src/api/user.ts create mode 100644 apps/web/src/components/auth/LoginForm.tsx create mode 100644 apps/web/src/components/auth/PasswordResetForm.tsx create mode 100644 apps/web/src/components/auth/PasswordResetRequestForm.tsx create mode 100644 apps/web/src/components/auth/SignUpForm.tsx create mode 100644 apps/web/src/components/layout/LoginLayout.tsx create mode 100644 apps/web/src/components/layout/app-layout/AppLayout.tsx create mode 100644 apps/web/src/components/layout/components/HeaderNav.tsx create mode 100644 apps/web/src/components/layout/components/PageHeader.tsx create mode 100644 apps/web/src/components/layout/components/SideNav.tsx create mode 100644 apps/web/src/components/layout/components/TopNav.tsx create mode 100644 apps/web/src/components/onboarding/ApplicationCreateForm.tsx create mode 100644 apps/web/src/components/query-builder/components/Builder.tsx create mode 100644 apps/web/src/components/query-builder/components/Button.tsx create mode 100644 apps/web/src/components/query-builder/components/Component/Component.tsx create mode 100644 apps/web/src/components/query-builder/components/Component/index.tsx create mode 100644 apps/web/src/components/query-builder/components/Context.tsx create mode 100644 apps/web/src/components/query-builder/components/Form/Input.tsx create mode 100644 apps/web/src/components/query-builder/components/Form/Select.tsx create mode 100644 apps/web/src/components/query-builder/components/Form/SelectMulti.tsx create mode 100644 apps/web/src/components/query-builder/components/Form/Switch.tsx create mode 100644 apps/web/src/components/query-builder/components/Group/Group.tsx create mode 100644 apps/web/src/components/query-builder/components/Group/Option.tsx create mode 100644 apps/web/src/components/query-builder/components/Group/index.tsx create mode 100644 apps/web/src/components/query-builder/components/Iterator.tsx create mode 100644 apps/web/src/components/query-builder/components/RemoveButton.tsx create mode 100644 apps/web/src/components/query-builder/components/SecondaryButton.tsx create mode 100644 apps/web/src/components/query-builder/components/Text.tsx create mode 100644 apps/web/src/components/query-builder/components/Widgets/Boolean.tsx create mode 100644 apps/web/src/components/query-builder/components/Widgets/FieldSelect.tsx create mode 100644 apps/web/src/components/query-builder/components/Widgets/Input.tsx create mode 100644 apps/web/src/components/query-builder/components/Widgets/OperatorSelect.tsx create mode 100644 apps/web/src/components/query-builder/components/Widgets/Select.tsx create mode 100644 apps/web/src/components/query-builder/components/Widgets/SelectMulti.tsx create mode 100644 apps/web/src/components/query-builder/constants/colors.ts create mode 100644 apps/web/src/components/query-builder/constants/strings.ts create mode 100644 apps/web/src/components/query-builder/utils/assignIds.ts create mode 100644 apps/web/src/components/query-builder/utils/clone.ts create mode 100644 apps/web/src/components/query-builder/utils/denormalizeTree.ts create mode 100644 apps/web/src/components/query-builder/utils/normalizeTree.ts create mode 100644 apps/web/src/components/query-builder/utils/types.ts create mode 100644 apps/web/src/components/templates/EmailContentCard.tsx create mode 100644 apps/web/src/components/templates/EmailMessagesCards.tsx create mode 100644 apps/web/src/components/templates/InAppEditorBlock.tsx create mode 100644 apps/web/src/components/templates/MessageNameEditorHeader.tsx create mode 100644 apps/web/src/components/templates/TemplateInAppEditor.tsx create mode 100644 apps/web/src/components/templates/TemplateSMSEditor.tsx create mode 100644 apps/web/src/components/templates/TemplateTriggerModal.tsx create mode 100644 apps/web/src/components/templates/TriggerSnippetTabs.tsx create mode 100644 apps/web/src/components/templates/email-editor/ButtonRowContent.tsx create mode 100644 apps/web/src/components/templates/email-editor/ContentRow.tsx create mode 100644 apps/web/src/components/templates/email-editor/ControlBar.tsx create mode 100644 apps/web/src/components/templates/email-editor/EmailMessageEditor.tsx create mode 100644 apps/web/src/components/widget/InAppWidgetPreview.tsx create mode 100644 apps/web/src/config/index.ts create mode 100644 apps/web/src/index.tsx create mode 100644 apps/web/src/logo.svg create mode 100644 apps/web/src/pages/HomePage.tsx create mode 100644 apps/web/src/pages/activities/ActivitiesPage.tsx create mode 100644 apps/web/src/pages/auth/InvitationScreen.tsx create mode 100644 apps/web/src/pages/auth/login.tsx create mode 100644 apps/web/src/pages/auth/password-reset.tsx create mode 100644 apps/web/src/pages/auth/signup.tsx create mode 100644 apps/web/src/pages/onboarding/application.tsx create mode 100644 apps/web/src/pages/organization-settings/OrganizationSettingsPage.tsx create mode 100644 apps/web/src/pages/settings/WidgetSettingsPage.tsx create mode 100644 apps/web/src/pages/settings/components/BrandingForm.tsx create mode 100644 apps/web/src/pages/templates/TemplateTriggerModal.tsx create mode 100644 apps/web/src/pages/templates/TemplatesListPage.tsx create mode 100644 apps/web/src/pages/templates/editor/TemplateEditorPage.tsx create mode 100644 apps/web/src/pages/templates/editor/use-status-change-controller.hook.ts create mode 100644 apps/web/src/pages/templates/editor/use-template-controller.hook.ts create mode 100644 apps/web/src/pages/templates/editor/use-template.fetcher.ts create mode 100644 apps/web/src/react-app-env.d.ts create mode 100644 apps/web/src/reportWebVitals.ts create mode 100644 apps/web/src/setupTests.ts create mode 100644 apps/web/src/store/authContext.ts create mode 100644 apps/web/src/store/use-auth-controller.ts create mode 100644 apps/web/src/styles/index.less create mode 100644 apps/web/src/styles/theme/layout.less create mode 100644 apps/web/src/styles/utilities/_aligns.less create mode 100644 apps/web/src/styles/utilities/_background.less create mode 100644 apps/web/src/styles/utilities/_border.less create mode 100644 apps/web/src/styles/utilities/_display.less create mode 100644 apps/web/src/styles/utilities/_flex.less create mode 100644 apps/web/src/styles/utilities/_float.less create mode 100644 apps/web/src/styles/utilities/_image.less create mode 100644 apps/web/src/styles/utilities/_overflow.less create mode 100644 apps/web/src/styles/utilities/_position.less create mode 100644 apps/web/src/styles/utilities/_shadow.less create mode 100644 apps/web/src/styles/utilities/_sizing.less create mode 100644 apps/web/src/styles/utilities/_spacing.less create mode 100644 apps/web/src/styles/utilities/_text.less create mode 100644 apps/web/src/styles/utilities/utilities.less create mode 100644 apps/web/src/styles/variables/_colors.less create mode 100644 apps/web/src/styles/variables/_common.less create mode 100644 apps/web/src/styles/variables/_template.less create mode 100644 apps/web/src/styles/variables/index.less create mode 100644 apps/web/src/utils/debounce.ts create mode 100644 apps/web/src/utils/utils.ts create mode 100644 apps/web/tsconfig.json create mode 100644 apps/widget/.env create mode 100644 apps/widget/.gitignore create mode 100644 apps/widget/README.md create mode 100644 apps/widget/craco.config.js create mode 100644 apps/widget/cypress.json create mode 100644 apps/widget/cypress/.eslintrc.js create mode 100644 apps/widget/cypress/fixtures/example.json create mode 100644 apps/widget/cypress/global.d.ts create mode 100644 apps/widget/cypress/integration/branding.spec.ts create mode 100644 apps/widget/cypress/integration/initialization.spec.ts create mode 100644 apps/widget/cypress/integration/notifications-list.spec.ts create mode 100644 apps/widget/cypress/integration/shell-embed.spec.ts create mode 100644 apps/widget/cypress/plugins/index.ts create mode 100644 apps/widget/cypress/support/commands.ts create mode 100644 apps/widget/cypress/support/index.ts create mode 100644 apps/widget/cypress/test-shell/example/test.html create mode 100644 apps/widget/cypress/test-shell/index.html create mode 100644 apps/widget/cypress/tsconfig.json create mode 100644 apps/widget/netlify.toml create mode 100644 apps/widget/package.json create mode 100644 apps/widget/public/favicon.ico create mode 100644 apps/widget/public/iframeResizer.contentWindow.js create mode 100644 apps/widget/public/index.html create mode 100644 apps/widget/public/logo192.png create mode 100644 apps/widget/public/logo512.png create mode 100644 apps/widget/public/manifest.json create mode 100644 apps/widget/public/robots.txt create mode 100644 apps/widget/src/App.test.tsx create mode 100644 apps/widget/src/App.tsx create mode 100644 apps/widget/src/ApplicationShell.tsx create mode 100644 apps/widget/src/Main.tsx create mode 100644 apps/widget/src/api/api.service.ts create mode 100644 apps/widget/src/api/application.ts create mode 100644 apps/widget/src/api/initialize-session.ts create mode 100644 apps/widget/src/api/notifications.ts create mode 100644 apps/widget/src/api/sdk.service.ts create mode 100644 apps/widget/src/api/shared.ts create mode 100644 apps/widget/src/api/usage.ts create mode 100644 apps/widget/src/components/NotificationListItem.tsx create mode 100644 apps/widget/src/components/NotificationsList.tsx create mode 100644 apps/widget/src/components/SeenAllBlock.tsx create mode 100644 apps/widget/src/components/layout/Footer.tsx create mode 100644 apps/widget/src/components/layout/Header.tsx create mode 100644 apps/widget/src/components/layout/Layout.tsx create mode 100644 apps/widget/src/global.d.ts create mode 100644 apps/widget/src/hooks/use-auth.hook.ts create mode 100644 apps/widget/src/hooks/use-initialization.hook.ts create mode 100644 apps/widget/src/hooks/use-socket.hook.ts create mode 100644 apps/widget/src/index.tsx create mode 100644 apps/widget/src/logo.svg create mode 100644 apps/widget/src/react-app-env.d.ts create mode 100644 apps/widget/src/reportWebVitals.ts create mode 100644 apps/widget/src/setupTests.ts create mode 100644 apps/widget/src/store/auth.context.ts create mode 100644 apps/widget/src/store/socket/socket.store.ts create mode 100644 apps/widget/src/store/socket/use-socket-controller.ts create mode 100644 apps/widget/src/store/use-auth-controller.ts create mode 100644 apps/widget/src/styles/theme.less create mode 100644 apps/widget/tsconfig.json create mode 100644 apps/ws/.eslintrc.js create mode 100644 apps/ws/.gitignore create mode 100644 apps/ws/nest-cli.json create mode 100644 apps/ws/nodemon.json create mode 100644 apps/ws/package.json create mode 100644 apps/ws/src/app.controller.ts create mode 100644 apps/ws/src/app.module.ts create mode 100644 apps/ws/src/app.service.ts create mode 100644 apps/ws/src/bootstrap.ts create mode 100644 apps/ws/src/config/index.ts create mode 100644 apps/ws/src/global.d.ts create mode 100644 apps/ws/src/health/health.controller.ts create mode 100644 apps/ws/src/health/health.module.ts create mode 100644 apps/ws/src/main.ts create mode 100644 apps/ws/src/shared/constants.ts create mode 100644 apps/ws/src/shared/exceptions/api.exception.ts create mode 100644 apps/ws/src/shared/framework/redis.adapter.ts create mode 100644 apps/ws/src/shared/framework/response.interceptor.ts create mode 100644 apps/ws/src/shared/framework/user.decorator.ts create mode 100644 apps/ws/src/shared/helpers/email-normalization.service.ts create mode 100644 apps/ws/src/shared/helpers/regex.service.ts create mode 100644 apps/ws/src/shared/queue/index.ts create mode 100644 apps/ws/src/shared/queue/queue.interface.ts create mode 100644 apps/ws/src/shared/queue/queue.service.ts create mode 100644 apps/ws/src/shared/shared.module.ts create mode 100644 apps/ws/src/socket/socket.module.ts create mode 100644 apps/ws/src/socket/ws.gateway.ts create mode 100644 apps/ws/tsconfig.build.json create mode 100644 apps/ws/tsconfig.json create mode 100644 environment/test/docker-compose.yml create mode 100644 libs/dal/.dockerignore create mode 100644 libs/dal/.eslintrc.js create mode 100644 libs/dal/.gitignore create mode 100644 libs/dal/nodemon.json create mode 100644 libs/dal/package.json create mode 100644 libs/dal/src/dal.service.ts create mode 100644 libs/dal/src/index.ts create mode 100644 libs/dal/src/repositories/application/application.entity.ts create mode 100644 libs/dal/src/repositories/application/application.repository.ts create mode 100644 libs/dal/src/repositories/application/application.schema.ts create mode 100644 libs/dal/src/repositories/application/index.ts create mode 100644 libs/dal/src/repositories/base-repository.ts create mode 100644 libs/dal/src/repositories/log/index.ts create mode 100644 libs/dal/src/repositories/log/log.entity.ts create mode 100644 libs/dal/src/repositories/log/log.repository.ts create mode 100644 libs/dal/src/repositories/log/log.schema.ts create mode 100644 libs/dal/src/repositories/member/index.ts create mode 100644 libs/dal/src/repositories/member/member.entity.ts create mode 100644 libs/dal/src/repositories/member/member.repository.ts create mode 100644 libs/dal/src/repositories/member/member.schema.ts create mode 100644 libs/dal/src/repositories/message-template/index.ts create mode 100644 libs/dal/src/repositories/message-template/message-template.entity.ts create mode 100644 libs/dal/src/repositories/message-template/message-template.repository.ts create mode 100644 libs/dal/src/repositories/message-template/message-template.schema.ts create mode 100644 libs/dal/src/repositories/message/index.ts create mode 100644 libs/dal/src/repositories/message/message.entity.ts create mode 100644 libs/dal/src/repositories/message/message.repository.ts create mode 100644 libs/dal/src/repositories/message/message.schema.ts create mode 100644 libs/dal/src/repositories/notification-group/index.ts create mode 100644 libs/dal/src/repositories/notification-group/notification-group.entity.ts create mode 100644 libs/dal/src/repositories/notification-group/notification-group.repository.ts create mode 100644 libs/dal/src/repositories/notification-group/notification-group.schema.ts create mode 100644 libs/dal/src/repositories/notification-template/index.ts create mode 100644 libs/dal/src/repositories/notification-template/notification-template.entity.ts create mode 100644 libs/dal/src/repositories/notification-template/notification-template.repository.ts create mode 100644 libs/dal/src/repositories/notification-template/notification-template.schema.ts create mode 100644 libs/dal/src/repositories/notification/index.ts create mode 100644 libs/dal/src/repositories/notification/notification.entity.ts create mode 100644 libs/dal/src/repositories/notification/notification.repository.ts create mode 100644 libs/dal/src/repositories/notification/notification.schema.ts create mode 100644 libs/dal/src/repositories/organization/index.ts create mode 100644 libs/dal/src/repositories/organization/organization.entity.ts create mode 100644 libs/dal/src/repositories/organization/organization.repository.ts create mode 100644 libs/dal/src/repositories/organization/organization.schema.ts create mode 100644 libs/dal/src/repositories/schema-default.options.ts create mode 100644 libs/dal/src/repositories/subscriber/index.ts create mode 100644 libs/dal/src/repositories/subscriber/subscriber.entity.ts create mode 100644 libs/dal/src/repositories/subscriber/subscriber.repository.ts create mode 100644 libs/dal/src/repositories/subscriber/subscriber.schema.ts create mode 100644 libs/dal/src/repositories/subscription-preference/index.ts create mode 100644 libs/dal/src/repositories/subscription-preference/subscription-preference.entity.ts create mode 100644 libs/dal/src/repositories/subscription-preference/subscription-preference.repository.ts create mode 100644 libs/dal/src/repositories/subscription-preference/subscription-preference.schema.ts create mode 100644 libs/dal/src/repositories/user/index.ts create mode 100644 libs/dal/src/repositories/user/user.entity.ts create mode 100644 libs/dal/src/repositories/user/user.repository.ts create mode 100644 libs/dal/src/repositories/user/user.schema.ts create mode 100644 libs/dal/src/types/env.d.ts create mode 100644 libs/dal/tsconfig.build.json create mode 100644 libs/dal/tsconfig.json create mode 100644 libs/sdk/.editorconfig create mode 100644 libs/sdk/.gitignore create mode 100644 libs/sdk/README.md create mode 100644 libs/sdk/package.json create mode 100644 libs/sdk/rollup.config.ts create mode 100644 libs/sdk/src/global.d.ts create mode 100644 libs/sdk/src/sdk.ts create mode 100644 libs/sdk/src/shared/errors.js create mode 100644 libs/sdk/src/shared/eventTypes.js create mode 100644 libs/sdk/src/shared/helpers.js create mode 100644 libs/sdk/src/shared/iframeClasses.js create mode 100644 libs/sdk/src/shared/resources.js create mode 100644 libs/sdk/test/index.html create mode 100644 libs/sdk/test/sdk.test.ts create mode 100644 libs/sdk/tools/gh-pages-publish.ts create mode 100644 libs/sdk/tools/semantic-release-prepare.ts create mode 100644 libs/sdk/tsconfig.json create mode 100644 libs/shared/.dockerignore create mode 100644 libs/shared/.eslintrc.js create mode 100644 libs/shared/.gitignore create mode 100644 libs/shared/nodemon.json create mode 100644 libs/shared/package.json create mode 100644 libs/shared/src/dto/index.ts create mode 100644 libs/shared/src/dto/notification-templates/create-template.dto.ts create mode 100644 libs/shared/src/dto/notification-templates/index.ts create mode 100644 libs/shared/src/dto/notification-templates/shared.ts create mode 100644 libs/shared/src/dto/notification-templates/update-template.dto.ts create mode 100644 libs/shared/src/dto/organization/create-organization.dto.ts create mode 100644 libs/shared/src/dto/organization/index.ts create mode 100644 libs/shared/src/dto/organization/members/bulk-invite-members.dto.ts create mode 100644 libs/shared/src/dto/organization/members/get-invite.dto.ts create mode 100644 libs/shared/src/dto/shared/index.ts create mode 100644 libs/shared/src/dto/shared/shared.ts create mode 100644 libs/shared/src/entities/application/application.interface.ts create mode 100644 libs/shared/src/entities/application/index.ts create mode 100644 libs/shared/src/entities/log/index.ts create mode 100644 libs/shared/src/entities/log/log.enums.ts create mode 100644 libs/shared/src/entities/message-template/channel.enum.ts create mode 100644 libs/shared/src/entities/message-template/index.ts create mode 100644 libs/shared/src/entities/message-template/message-template.interface.ts create mode 100644 libs/shared/src/entities/messages/messages.interface.ts create mode 100644 libs/shared/src/entities/notification-template/index.ts create mode 100644 libs/shared/src/entities/notification-template/notification-template.interface.ts create mode 100644 libs/shared/src/entities/notification/index.ts create mode 100644 libs/shared/src/entities/notification/notification.interface.ts create mode 100644 libs/shared/src/entities/organization/index.ts create mode 100644 libs/shared/src/entities/organization/member.enum.ts create mode 100644 libs/shared/src/entities/organization/member.interface.ts create mode 100644 libs/shared/src/entities/organization/organization.interface.ts create mode 100644 libs/shared/src/entities/user/index.ts create mode 100644 libs/shared/src/entities/user/subscriber-user.interface.ts create mode 100644 libs/shared/src/entities/user/user.enums.ts create mode 100644 libs/shared/src/entities/user/user.interface.ts create mode 100644 libs/shared/src/index.ts create mode 100644 libs/shared/src/types/builder/builder.types.ts create mode 100644 libs/shared/tsconfig.build.json create mode 100644 libs/shared/tsconfig.json create mode 100644 libs/testing/.dockerignore create mode 100644 libs/testing/.eslintrc.js create mode 100644 libs/testing/.gitignore create mode 100644 libs/testing/nodemon.json create mode 100644 libs/testing/package.json create mode 100644 libs/testing/src/application.service.ts create mode 100644 libs/testing/src/create-notification-template.interface.ts create mode 100644 libs/testing/src/index.ts create mode 100644 libs/testing/src/notification-template.service.ts create mode 100644 libs/testing/src/notifications.service.ts create mode 100644 libs/testing/src/organization.service.ts create mode 100644 libs/testing/src/subscribers.service.ts create mode 100644 libs/testing/src/test-server.service.ts create mode 100644 libs/testing/src/user.session.ts create mode 100644 libs/testing/tsconfig.build.json create mode 100644 libs/testing/tsconfig.json create mode 100644 tsconfig.base.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000000..4ac4973fb15 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000000..df95e3b5cc1 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,12 @@ +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Dependency directory +# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git +node_modules + +# OSX +.DS_Store diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000000..393a1b14aef --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,64 @@ +module.exports = { + root: true, + extends: [ + 'airbnb-typescript', + 'plugin:import/typescript', + 'plugin:@typescript-eslint/recommended', + 'prettier/@typescript-eslint', + 'plugin:prettier/recommended', + 'plugin:promise/recommended', + ], + ignorePatterns: ['.eslintrc.js'], + plugins: ['import', 'promise', '@typescript-eslint', 'prettier'], + parser: '@typescript-eslint/parser', + settings: { + 'import/parsers': { + '@typescript-eslint/parser': ['.ts', '.tsx'], + }, + }, + parserOptions: { + project: './tsconfig.json', + ecmaVersion: 2020, + sourceType: 'module', + }, + rules: { + '@typescript-eslint/lines-between-class-members': 'off', + 'react/jsx-wrap-multilines': 'off', + 'promise/catch-or-return': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-unused-expressions': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + 'react/jsx-closing-bracket-location': 'off', + '@typescript-eslint/no-var-requires': 'off', + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': ['off'], + 'mocha/no-mocha-arrows': 'off', + 'no-return-await': 'off', + 'no-await-in-loop': 'off', + 'no-continue': 'off', + 'no-prototype-builtins': 'off', + 'import/no-cycle': 'off', + 'class-methods-use-this': 'off', + '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/no-explicit-any': 1, + 'no-restricted-syntax': 'off', + '@typescript-eslint/interface-name-prefix': 'off', + 'no-underscore-dangle': 'off', + 'import/prefer-default-export': 'off', + // A temporary hack related to IDE not resolving correct package.json + 'import/no-extraneous-dependencies': 'off', + 'react/jsx-one-expression-per-line': 'off', + 'react/jsx-no-bind': 'off', + 'lines-between-class-members': 'off', + 'max-classes-per-file': 'off', + 'react/react-in-jsx-scope': 'off', + 'max-len': ['warn', { code: 140 }], + '@typescript-eslint/return-await': 'off', + 'no-restricted-imports': [ + 'error', + { + patterns: ['@notifire/shared/*', '@notifire/dal/*', '!import2/good'], + }, + ], + }, +}; diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index b3c8e844255..00000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "root": true, - "parser": "@typescript-eslint/parser", - "parserOptions": { "project": "./tsconfig.json" }, - "env": { "es6": true }, - "ignorePatterns": ["node_modules", "build", "coverage"], - "plugins": ["import", "eslint-comments", "functional"], - "extends": [ - "eslint:recommended", - "plugin:eslint-comments/recommended", - "plugin:@typescript-eslint/recommended", - "plugin:import/typescript", - "prettier", - "prettier/@typescript-eslint" - ], - "globals": { "BigInt": true, "console": true, "WebAssembly": true }, - "rules": { - "functional/no-class": "off", - "@typescript-eslint/explicit-module-boundary-types": "off", - "eslint-comments/disable-enable-pair": [ - "error", - { "allowWholeFile": true } - ], - "eslint-comments/no-unused-disable": "error", - "sort-imports": [ - "error", - { "ignoreDeclarationSort": true, "ignoreCase": true } - ] - } -} diff --git a/.github/workflows/test-api.yml b/.github/workflows/test-api.yml new file mode 100644 index 00000000000..0e746185323 --- /dev/null +++ b/.github/workflows/test-api.yml @@ -0,0 +1,92 @@ +# This is a basic workflow to help you get started with Actions + +name: Test API + +# Controls when the action will run. Triggers the workflow on push or pull request +# events but only for the master branch +on: + pull_request: + paths: + - 'package.json' + - 'yarn.lock' + - 'apps/api/**' + - 'libs/dal/**' + - 'libs/testing/**' + - 'libs/shared/**' + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + test_api: + # The type of runner that the job will run on + runs-on: ubuntu-latest + timeout-minutes: 80 + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + - name: Setup kernel for react native, increase watchers + run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p + - uses: actions/setup-node@v2 + with: + node-version: '15.11.0' + - name: Start Redis + uses: supercharge/redis-github-action@1.2.0 + + - name: Start MongoDB + uses: supercharge/mongodb-github-action@1.3.0 + with: + mongodb-version: 4.2.8 + + - name: restore lerna + uses: actions/cache@master + with: + path: | + node_modules + */*/node_modules + key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }} + + # Runs a single command using the runners shell + - name: Install project dependencies + run: yarn install + + - name: Start Local Stack + env: + AWS_DEFAULT_REGION: us-east-1 + DEFAULT_REGION: us-east-1 + AWS_ACCOUNT_ID: "000000000000" + AWS_ACCESS_KEY_ID: test + AWS_SECRET_ACCESS_KEY: test + AWS_EC2_METADATA_DISABLED: true + working-directory: environment/test + run: | + docker-compose up -d + sleep 10 + max_retry=30 + counter=0 + until $command + do + sleep 1 + [[ counter -eq $max_retry ]] && echo "Failed!" && exit 1 + aws --endpoint-url=http://localhost:4566 s3 ls + echo "Trying again. Try #$counter" + ((counter++)) + done + docker-compose logs --tail="all" + aws --endpoint-url=http://localhost:4566 s3 mb s3://notifire-test + + # Runs a single command using the runners shell + - name: Bootstrap + run: yarn run bootstrap + + # Runs a single command using the runners shell + - name: Build API + run: CI='' yarn run build:api + + # Runs a set of commands using the runners shell + - name: Run a test + run: | + cd apps/api && yarn run test:e2e + yarn run test + diff --git a/.github/workflows/test-core.yml b/.github/workflows/test-core.yml index e7c83cfceae..d8d617dc387 100644 --- a/.github/workflows/test-core.yml +++ b/.github/workflows/test-core.yml @@ -12,6 +12,15 @@ jobs: with: node-version: "14" - run: rm -rf build + + - name: restore lerna + uses: actions/cache@master + with: + path: | + node_modules + */*/node_modules + key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }} + - run: yarn install - run: yarn bootstrap - name: Test diff --git a/.github/workflows/test-sdk.yml b/.github/workflows/test-sdk.yml new file mode 100644 index 00000000000..087dedda48a --- /dev/null +++ b/.github/workflows/test-sdk.yml @@ -0,0 +1,50 @@ +# This is a basic workflow to help you get started with Actions + +name: Test SDK + +# Controls when the action will run. Triggers the workflow on push or pull request +# events but only for the master branch +on: + pull_request: + paths: + - 'libs/sdk/**' + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + test_sdk: + # The type of runner that the job will run on + runs-on: ubuntu-latest + timeout-minutes: 80 + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + - name: Setup kernel for react native, increase watchers + run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p + - uses: actions/setup-node@v2 + with: + node-version: '15.11.0' + + - name: restore lerna + uses: actions/cache@master + with: + path: | + node_modules + **/node_modules + /home/runner/.cache/Cypress + key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }} + + # Runs a single command using the runners shell + - name: Install project dependencies + run: yarn install + + # Runs a single command using the runners shell + - name: Bootstrap + run: yarn run bootstrap + + # Runs a single command using the runners shell + - name: Build + working-directory: libs/sdk + run: CI='' yarn run build:dev diff --git a/.github/workflows/test-web.yml b/.github/workflows/test-web.yml new file mode 100644 index 00000000000..16413a8ce92 --- /dev/null +++ b/.github/workflows/test-web.yml @@ -0,0 +1,105 @@ +# This is a basic workflow to help you get started with Actions + +name: Test WEB + +# Controls when the action will run. Triggers the workflow on push or pull request +# events but only for the master branch +on: + workflow_dispatch: + inputs: + deploy: + description: 'Should deploy' + required: false + default: "true" + pull_request: + paths: + - 'apps/web/**' + - 'libs/shared/**' + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + test_web: + # The type of runner that the job will run on + runs-on: ubuntu-latest + timeout-minutes: 80 + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + - name: Setup kernel for react native, increase watchers + run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p + - uses: actions/setup-node@v2 + with: + node-version: '15.11.0' + - name: Start Redis + uses: supercharge/redis-github-action@1.2.0 + + - name: Start MongoDB + uses: supercharge/mongodb-github-action@1.3.0 + with: + mongodb-version: 4.2.8 + + - name: restore lerna + uses: actions/cache@master + with: + path: | + node_modules + **/node_modules + /home/runner/.cache/Cypress + key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }} + + + # Runs a single command using the runners shell + - name: Install project dependencies + run: yarn install + + # Runs a single command using the runners shell + - name: Bootstrap + run: yarn run bootstrap + + - name: Start Local Stack + env: + DEFAULT_REGION: us-east-1 + AWS_DEFAULT_REGION: us-east-1 + AWS_ACCOUNT_ID: "000000000000" + AWS_ACCESS_KEY_ID: test + AWS_SECRET_ACCESS_KEY: test + AWS_EC2_METADATA_DISABLED: true + working-directory: environment/test + run: | + docker-compose up -d + sleep 5 + max_retry=30 + counter=0 + until $command + do + sleep 1 + [[ counter -eq $max_retry ]] && echo "Failed!" && exit 1 + aws --endpoint-url=http://localhost:4566 s3 ls + echo "Trying again. Try #$counter" + ((counter++)) + done + aws --endpoint-url=http://localhost:4566 s3 mb s3://notifire-test + + # Runs a single command using the runners shell + - name: Build + run: CI='' yarn run build:web + + # Runs a single command using the runners shell + - name: Start Client + run: yarn run start:web & + + - name: Cypress run + uses: cypress-io/github-action@v2 + env: + NODE_ENV: test + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + record: true + working-directory: apps/web + start: yarn run start:api + wait-on: http://localhost:1336/v1/health-check + browser: chrome + headless: true diff --git a/.github/workflows/test-widget.yml b/.github/workflows/test-widget.yml new file mode 100644 index 00000000000..a3020b4fb7b --- /dev/null +++ b/.github/workflows/test-widget.yml @@ -0,0 +1,90 @@ +# This is a basic workflow to help you get started with Actions + +name: Test WIDGET + +# Controls when the action will run. Triggers the workflow on push or pull request +# events but only for the master branch +on: + workflow_dispatch: + inputs: + deploy: + description: 'Should deploy' + required: false + default: "true" + pull_request: + paths: + - 'apps/widget/**' + - 'apps/ws/**' + - 'libs/shared/**' + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + test_widget: + # The type of runner that the job will run on + runs-on: ubuntu-latest + timeout-minutes: 80 + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + - name: Setup kernel for react native, increase watchers + run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p + - uses: actions/setup-node@v2 + with: + node-version: '15.11.0' + - name: Start Redis + uses: supercharge/redis-github-action@1.2.0 + + - name: Start MongoDB + uses: supercharge/mongodb-github-action@1.3.0 + with: + mongodb-version: 4.2.8 + + - name: restore lerna + uses: actions/cache@master + with: + path: | + node_modules + **/node_modules + /home/runner/.cache/Cypress + key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }} + + # Runs a single command using the runners shell + - name: Install project dependencies + run: yarn install + + # Runs a single command using the runners shell + - name: Bootstrap + run: yarn run bootstrap + + # Runs a single command using the runners shell + - name: Build + run: CI='' yarn run build:widget + + # Runs a single command using the runners shell + - name: Start Client + run: yarn run start:widget & + + # Runs a single command using the runners shell + - name: Start WS + run: yarn run start:ws & + + # Runs a single command using the runners shell + - name: Wait for WS + run: npx wait-on --timeout=30000 http://localhost:1340/v1/health-check + + - name: Cypress run + uses: cypress-io/github-action@v2 + env: + NODE_ENV: test + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + working-directory: apps/widget + start: yarn run start:api + wait-on: http://localhost:3500/v1/health-check + record: true + browser: chrome + headless: true + diff --git a/.gitignore b/.gitignore index 963d5292865..cceadf7d25e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,94 @@ .nyc_output build node_modules -test src/**.js coverage *.log package-lock.json + +node_modules +build +*.log +coverage +.DS_Store +dist +.idea/workspace.xml +.idea/usage.statistics.xml +.idea/tasks.xml +.eslintcache +.idea/codestream.xml +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +# Compiled files +*.tfstate +*.tfstate.backup +.terraform.tfstate.lock.info +# Module directory +.terraform/ diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 00000000000..275f334e87e --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v14.4.0 diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000000..248d44a7299 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,11 @@ +{ + "printWidth": 120, + "trailingComma": "es5", + "singleQuote": true, + "semi": true, + "tabWidth": 2, + "quoteProps": "as-needed", + "jsxSingleQuote": false, + "jsxBracketSameLine": true, + "arrowParens": "always" +} diff --git a/.yarnrc b/.yarnrc new file mode 100644 index 00000000000..e6fe73b6347 --- /dev/null +++ b/.yarnrc @@ -0,0 +1 @@ +network-timeout 60000 diff --git a/Dockerfile.api b/Dockerfile.api new file mode 100644 index 00000000000..e4a040ed071 --- /dev/null +++ b/Dockerfile.api @@ -0,0 +1,31 @@ +FROM node:15.11.0 +ENV NODE_ENV=prod + +WORKDIR /usr/src/app + +RUN npm i yarn -g --loglevel notice --force +RUN npm i pm2 -g + +COPY package.json . + +COPY apps/api ./apps/api +COPY libs/core ./libs/core +COPY libs/shared ./libs/shared + +COPY lerna.json . +COPY tsconfig.json . +COPY tsconfig.base.json . + +RUN yarn install +RUN yarn bootstrap +RUN yarn build:api + +WORKDIR /usr/src/app/apps/api +RUN cp src/.env.test dist/src/.env.test +RUN cp src/.env.development dist/src/.env.development +RUN cp src/.env.production dist/src/.env.production + +RUN mkdir dist/src/app/content-templates/usecases/compile-template/templates +RUN cp src/app/content-templates/usecases/compile-template/templates/* dist/src/app/content-templates/usecases/compile-template/templates/ + +CMD [ "pm2-runtime", "dist/src/main.js" ] diff --git a/Dockerfile.ws b/Dockerfile.ws new file mode 100644 index 00000000000..a3c9fbdb514 --- /dev/null +++ b/Dockerfile.ws @@ -0,0 +1,28 @@ +FROM node:15.11.0 +ENV NODE_ENV=prod + +WORKDIR /usr/src/app + +RUN npm i yarn -g --loglevel notice --force +RUN npm i pm2 -g + +COPY package.json . + +COPY apps/ws ./apps/ws +COPY libs/core ./libs/core +COPY libs/shared ./libs/shared + +COPY lerna.json . +COPY tsconfig.json . +COPY tsconfig.base.json . + +RUN yarn install +RUN yarn bootstrap +RUN yarn build:ws + +WORKDIR /usr/src/app/apps/ws +RUN cp src/.env.test dist/src/.env.test +RUN cp src/.env.development dist/src/.env.development +RUN cp src/.env.production dist/src/.env.production + +CMD [ "pm2-runtime", "dist/src/main.js" ] diff --git a/_templates/module/new/controller.ejs.t b/_templates/module/new/controller.ejs.t new file mode 100644 index 00000000000..bdb3ace4b41 --- /dev/null +++ b/_templates/module/new/controller.ejs.t @@ -0,0 +1,9 @@ +--- +to: apps/api/src/app/<%= name %>/<%= name %>.controller.ts +--- +import { Controller } from '@nestjs/common'; + +@Controller('/<%= name %>') +export class <%= h.changeCase.pascal(name) %>Controller { + constructor() {} +} diff --git a/_templates/module/new/module.ejs.t b/_templates/module/new/module.ejs.t new file mode 100644 index 00000000000..ca03710ee48 --- /dev/null +++ b/_templates/module/new/module.ejs.t @@ -0,0 +1,14 @@ +--- +to: apps/api/src/app/<%= name %>/<%= name %>.module.ts +--- +import { Module } from '@nestjs/common'; +import { USE_CASES } from './usecases'; +import { <%= h.changeCase.pascal(name) %>Controller } from './<%= name %>.controller'; +import { SharedModule } from '../shared/shared.module'; + +@Module({ + imports: [SharedModule], + providers: [...USE_CASES], + controllers: [<%= h.changeCase.pascal(name) %>Controller], +}) +export class <%= h.changeCase.pascal(name) %>Module {} diff --git a/_templates/module/new/prompt.ejs.t b/_templates/module/new/prompt.ejs.t new file mode 100644 index 00000000000..91c8f63d61c --- /dev/null +++ b/_templates/module/new/prompt.ejs.t @@ -0,0 +1,10 @@ +// see types of prompts: +// https://github.com/enquirer/enquirer/tree/master/examples +// +module.exports = [ + { + type: 'input', + name: 'name', + message: "What's the name of the usecase?" + } +] diff --git a/_templates/module/new/usecase-index.ejs.t b/_templates/module/new/usecase-index.ejs.t new file mode 100644 index 00000000000..4eaae734285 --- /dev/null +++ b/_templates/module/new/usecase-index.ejs.t @@ -0,0 +1,7 @@ +--- +to: apps/api/src/app/<%= name %>/usecases/index.ts +--- +export const USE_CASES = [ + // +]; + diff --git a/_templates/usecase/new/command.ejs.t b/_templates/usecase/new/command.ejs.t new file mode 100644 index 00000000000..0bb964f9097 --- /dev/null +++ b/_templates/usecase/new/command.ejs.t @@ -0,0 +1,13 @@ +--- +to: apps/api/src/app/<%= module %>/usecases/<%= name %>/<%= name %>.command.ts +--- +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; + +export class <%= h.changeCase.pascal(name) %>Command extends ApplicationWithUserCommand { + static create(data: <%= h.changeCase.pascal(name) %>Command) { + return CommandHelper.create<<%= h.changeCase.pascal(name) %>Command>(<%= h.changeCase.pascal(name) %>Command, data); + } +} + + diff --git a/_templates/usecase/new/import-inject.ejs.t b/_templates/usecase/new/import-inject.ejs.t new file mode 100644 index 00000000000..5f56029e825 --- /dev/null +++ b/_templates/usecase/new/import-inject.ejs.t @@ -0,0 +1,8 @@ +--- +to: apps/api/src/app/<%= module %>/usecases/index.ts +inject: true +skip_if: <%= h.changeCase.pascal(name) %> +after: "const USE_CASES = \\[" +eof_last: false +--- + <%= h.changeCase.pascal(name) %>, diff --git a/_templates/usecase/new/import-row-inject.ejs.t b/_templates/usecase/new/import-row-inject.ejs.t new file mode 100644 index 00000000000..3fec183ca64 --- /dev/null +++ b/_templates/usecase/new/import-row-inject.ejs.t @@ -0,0 +1,8 @@ +--- +to: apps/api/src/app/<%= module %>/usecases/index.ts +inject: true +skip_if: import { <%= h.changeCase.pascal(name) %> +prepend: true +eof_last: false +--- +import { <%= h.changeCase.pascal(name) %> } from './<%= name %>/<%= name %>.usecase'; diff --git a/_templates/usecase/new/prompt.ejs.t b/_templates/usecase/new/prompt.ejs.t new file mode 100644 index 00000000000..fafba29ac51 --- /dev/null +++ b/_templates/usecase/new/prompt.ejs.t @@ -0,0 +1,15 @@ +// see types of prompts: +// https://github.com/enquirer/enquirer/tree/master/examples +// +module.exports = [ + { + type: 'input', + name: 'module', + message: "What module add this use case to?" + }, + { + type: 'input', + name: 'name', + message: "What's the name of the usecase?" + } +] diff --git a/_templates/usecase/new/usecase.ejs.t b/_templates/usecase/new/usecase.ejs.t new file mode 100644 index 00000000000..64188fc3e27 --- /dev/null +++ b/_templates/usecase/new/usecase.ejs.t @@ -0,0 +1,14 @@ +--- +to: apps/api/src/app/<%= module %>/usecases/<%= name %>/<%= name %>.usecase.ts +--- +import { Injectable } from '@nestjs/common'; +import { <%= h.changeCase.pascal(name) %>Command } from './<%= name %>.command'; + +@Injectable() +export class <%= h.changeCase.pascal(name) %> { + constructor() {} + + async execute(command: <%= h.changeCase.pascal(name) %>Command): Promise { + return 'Is working'; + } +} diff --git a/apps/api/.eslintrc.js b/apps/api/.eslintrc.js new file mode 100644 index 00000000000..a57fabcc485 --- /dev/null +++ b/apps/api/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: ['../../.eslintrc.js'], + rules: { + 'func-names': 'off', + }, + ignorePatterns: '*.spec.ts', +}; diff --git a/apps/api/.gitignore b/apps/api/.gitignore new file mode 100644 index 00000000000..78bd28b805f --- /dev/null +++ b/apps/api/.gitignore @@ -0,0 +1,120 @@ +# Created by .ignore support plugin (hsz.mobi) +### Node template +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.idea +.build +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +dist +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# next.js build output +.next +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/*/workspace.xml +.idea/**/*/tasks.xml +.idea/**/*/dictionaries +.idea/**/*/shelf + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# CMake +cmake-build-debug/ +cmake-build-release/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +.serverless +newrelic_agent.log diff --git a/apps/api/.mocharc.json b/apps/api/.mocharc.json new file mode 100644 index 00000000000..19e868a6e9d --- /dev/null +++ b/apps/api/.mocharc.json @@ -0,0 +1,7 @@ +{ + "timeout": 10000, + "require": "ts-node/register", + "file": ["e2e/setup.ts"], + "exit": true, + "files": ["e2e/**/*.e2e.ts", "src/**/*.e2e.ts", "src/**/**/*.spec.ts"] +} diff --git a/apps/api/README.md b/apps/api/README.md new file mode 100644 index 00000000000..71059336214 --- /dev/null +++ b/apps/api/README.md @@ -0,0 +1,79 @@ +

+ Nest Logo +

+ +[travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master +[travis-url]: https://travis-ci.org/nestjs/nest +[linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux +[linux-url]: https://travis-ci.org/nestjs/nest + +

A progressive Node.js framework for building efficient and scalable server-side applications, heavily inspired by Angular.

+

+NPM Version +Package License +NPM Downloads +Travis +Linux +Coverage +Gitter +Backers on Open Collective +Sponsors on Open Collective + + +

+ + +## Description + +[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. + +## Installation + +```bash +$ npm install +``` + +## Running the app + +```bash +# development +$ npm run start + +# watch mode +$ npm run start:dev + +# incremental rebuild (webpack) +$ npm run webpack +$ npm run start:hmr + +# production mode +$ npm run start:prod +``` + +## Test + +```bash +# unit tests +$ npm run test + +# e2e tests +$ npm run test:e2e + +# test coverage +$ npm run test:cov +``` + +## Support + +Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). + +## Stay in touch + +- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) +- Website - [https://nestjs.com](https://nestjs.com/) +- Twitter - [@nestframework](https://twitter.com/nestframework) + +## License + +Nest is [MIT licensed](LICENSE). diff --git a/apps/api/e2e/api/healthcheck/health-check.e2e.ts b/apps/api/e2e/api/healthcheck/health-check.e2e.ts new file mode 100644 index 00000000000..32bd3dc8fc4 --- /dev/null +++ b/apps/api/e2e/api/healthcheck/health-check.e2e.ts @@ -0,0 +1,19 @@ +import { UserSession } from '@notifire/testing'; +import { expect } from 'chai'; + +describe('Health-check', () => { + const session = new UserSession(); + + before(async () => { + await session.initialize(); + }); + + describe('/health-check (GET)', () => { + it('should correctly return a health check', async () => { + const { + body: { data }, + } = await session.testAgent.get('/v1/health-check'); + expect(data.status).to.equal('ok'); + }); + }); +}); diff --git a/apps/api/e2e/api/organization/create-organization.e2e.ts b/apps/api/e2e/api/organization/create-organization.e2e.ts new file mode 100644 index 00000000000..c3bc31815ab --- /dev/null +++ b/apps/api/e2e/api/organization/create-organization.e2e.ts @@ -0,0 +1,43 @@ +import { MemberRepository, OrganizationRepository } from '@notifire/dal'; +import { UserSession } from '@notifire/testing'; +import { MemberRoleEnum } from '@notifire/shared'; +import { expect } from 'chai'; + +describe('Create Organization - /organizations (POST)', async () => { + let session: UserSession; + const organizationRepository = new OrganizationRepository(); + const memberRepository = new MemberRepository(); + + before(async () => { + session = new UserSession(); + await session.initialize({ + noOrganization: true, + }); + }); + + describe('Valid Creation', () => { + it('should add the user as admin', async () => { + const { body } = await session.testAgent + .post('/v1/organizations') + .send({ + name: 'Test Org 2', + }) + .expect(201); + const dbOrganization = await organizationRepository.findById(body.data._id); + + const members = await memberRepository.getOrganizationMembers(dbOrganization._id); + + expect(members.length).to.eq(1); + expect(members[0]._userId).to.eq(session.user._id); + expect(members[0].roles[0]).to.eq(MemberRoleEnum.ADMIN); + }); + + it('should create organization with correct name', async () => { + const demoOrganization = { + name: 'Hello Org', + }; + const { body } = await session.testAgent.post('/v1/organizations').send(demoOrganization).expect(201); + expect(body.data.name).to.eq(demoOrganization.name); + }); + }); +}); diff --git a/apps/api/e2e/api/organization/get-my-organization.e2e.ts b/apps/api/e2e/api/organization/get-my-organization.e2e.ts new file mode 100644 index 00000000000..9048a584f2a --- /dev/null +++ b/apps/api/e2e/api/organization/get-my-organization.e2e.ts @@ -0,0 +1,19 @@ +import { UserSession } from '@notifire/testing'; +import { expect } from 'chai'; + +describe('Get my organization - /organizations/me (GET)', async () => { + let session: UserSession; + + before(async () => { + session = new UserSession(); + await session.initialize(); + }); + + describe('Get organization profile', () => { + it('should return the correct organization', async () => { + const { body } = await session.testAgent.get('/v1/organizations/me').expect(200); + + expect(body.data._id).to.eq(session.organization._id); + }); + }); +}); diff --git a/apps/api/e2e/api/organization/members/change-member-role.e2e.ts b/apps/api/e2e/api/organization/members/change-member-role.e2e.ts new file mode 100644 index 00000000000..04c77a39ff0 --- /dev/null +++ b/apps/api/e2e/api/organization/members/change-member-role.e2e.ts @@ -0,0 +1,64 @@ +import { OrganizationRepository, MemberRepository } from '@notifire/dal'; +import { UserSession } from '@notifire/testing'; +import { MemberRoleEnum, MemberStatusEnum } from '@notifire/shared'; +import { expect } from 'chai'; +import { describe } from 'mocha'; + +describe('Change member role - /organizations/members/:memberId/role (PUT)', async () => { + const organizationRepository = new OrganizationRepository(); + const memberRepository = new MemberRepository(); + let session: UserSession; + let user2: UserSession; + let user3: UserSession; + + beforeEach(async () => { + session = new UserSession(); + await session.initialize(); + + user2 = new UserSession(); + await user2.initialize({ + noOrganization: true, + }); + + user3 = new UserSession(); + await user3.initialize({ + noOrganization: true, + }); + }); + + it('should update admin to member', async () => { + await memberRepository.addMember(session.organization._id, { + _userId: user2.user._id, + invite: null, + roles: [MemberRoleEnum.ADMIN], + memberStatus: MemberStatusEnum.ACTIVE, + }); + + const member = await memberRepository.findMemberByUserId(session.organization._id, user2.user._id); + const { body } = await session.testAgent.put(`/v1/organizations/members/${member._id}/roles`).send({ + role: MemberRoleEnum.MEMBER, + }); + + expect(body.data.roles.length).to.equal(1); + expect(body.data.roles[0]).to.equal(MemberRoleEnum.MEMBER); + }); + + it('should update member to admin', async () => { + await memberRepository.addMember(session.organization._id, { + _userId: user3.user._id, + invite: null, + roles: [MemberRoleEnum.MEMBER], + memberStatus: MemberStatusEnum.ACTIVE, + }); + + const member = await memberRepository.findMemberByUserId(session.organization._id, user3.user._id); + + const { body } = await session.testAgent.put(`/v1/organizations/members/${member._id}/roles`).send({ + role: MemberRoleEnum.ADMIN, + }); + + expect(body.data.roles.length).to.equal(1); + expect(body.data.roles.includes(MemberRoleEnum.ADMIN)).to.be.ok; + expect(body.data.roles.includes(MemberRoleEnum.MEMBER)).not.to.be.ok; + }); +}); diff --git a/apps/api/e2e/api/organization/members/get-members.e2e.ts b/apps/api/e2e/api/organization/members/get-members.e2e.ts new file mode 100644 index 00000000000..84859207d98 --- /dev/null +++ b/apps/api/e2e/api/organization/members/get-members.e2e.ts @@ -0,0 +1,57 @@ +import { MemberEntity, OrganizationRepository, MemberRepository } from '@notifire/dal'; +import { UserSession } from '@notifire/testing'; +import { MemberRoleEnum, MemberStatusEnum } from '@notifire/shared'; +import { expect } from 'chai'; +import { describe } from 'mocha'; + +describe('Get Organization members - /organizations/members (GET)', async () => { + let session: UserSession; + const organizationRepository = new OrganizationRepository(); + const memberRepository = new MemberRepository(); + let user2: UserSession; + let user3: UserSession; + + beforeEach(async () => { + session = new UserSession(); + await session.initialize(); + + user2 = new UserSession(); + await user2.initialize({ + noOrganization: true, + }); + + user3 = new UserSession(); + await user3.initialize({ + noOrganization: true, + }); + }); + + it('should return all organization members', async () => { + await memberRepository.addMember(session.organization._id, { + _userId: user2.user._id, + invite: null, + roles: [MemberRoleEnum.ADMIN], + memberStatus: MemberStatusEnum.ACTIVE, + }); + + await memberRepository.addMember(session.organization._id, { + _userId: user3.user._id, + invite: null, + roles: [MemberRoleEnum.ADMIN], + memberStatus: MemberStatusEnum.ACTIVE, + }); + + const { body } = await session.testAgent.get('/v1/organizations/members'); + + const response: MemberEntity[] = body.data; + + expect(response.length).to.equal(3); + const user2Member = response.find((i) => i._userId === user2.user._id); + + expect(user2Member).to.be.ok; + expect(user2Member.memberStatus).to.equal(MemberStatusEnum.ACTIVE); + expect(user2Member.user).to.be.ok; + expect(user2Member.user.firstName).to.equal(user2.user.firstName); + expect(user2Member.user.email).to.equal(user2.user.email); + }); +}); diff --git a/apps/api/e2e/api/organization/members/remove-member.e2e.ts b/apps/api/e2e/api/organization/members/remove-member.e2e.ts new file mode 100644 index 00000000000..ca7096c07a5 --- /dev/null +++ b/apps/api/e2e/api/organization/members/remove-member.e2e.ts @@ -0,0 +1,66 @@ +import { MemberEntity, OrganizationRepository, MemberRepository } from '@notifire/dal'; +import { UserSession } from '@notifire/testing'; + +import { MemberRoleEnum, MemberStatusEnum } from '@notifire/shared'; +import { expect } from 'chai'; +import { describe } from 'mocha'; + +describe('Remove organization member - /organizations/members/:memberId (DELETE)', async () => { + let session: UserSession; + const organizationRepository = new OrganizationRepository(); + const memberRepository = new MemberRepository(); + + let user2: UserSession; + let user3: UserSession; + + beforeEach(async () => { + session = new UserSession(); + await session.initialize(); + + user2 = new UserSession(); + await user2.initialize({ + noOrganization: true, + }); + + user3 = new UserSession(); + await user3.initialize({ + noOrganization: true, + }); + + await memberRepository.addMember(session.organization._id, { + _userId: user2.user._id, + invite: null, + roles: [MemberRoleEnum.ADMIN], + memberStatus: MemberStatusEnum.ACTIVE, + }); + + await memberRepository.addMember(session.organization._id, { + _userId: user3.user._id, + invite: null, + roles: [MemberRoleEnum.ADMIN], + memberStatus: MemberStatusEnum.ACTIVE, + }); + + user2.organization = session.organization; + user3.organization = session.organization; + }); + + it('should remove the member by his id', async () => { + const members: MemberEntity[] = await getOrganizationMembers(); + const user2Member = members.find((i) => i._userId === user2.user._id); + + const { body } = await session.testAgent.delete(`/v1/organizations/members/${user2Member._id}`).expect(200); + + expect(body.data._id).to.equal(user2Member._id); + + const membersAfterRemoval: MemberEntity[] = await getOrganizationMembers(); + const user2Removed = membersAfterRemoval.find((i) => i._userId === user2.user._id); + expect(user2Removed).to.not.be.ok; + }); + + async function getOrganizationMembers() { + const { body } = await session.testAgent.get('/v1/organizations/members'); + + return body.data; + } +}); diff --git a/apps/api/e2e/api/user/get-me.e2e.ts b/apps/api/e2e/api/user/get-me.e2e.ts new file mode 100644 index 00000000000..1560272bb3d --- /dev/null +++ b/apps/api/e2e/api/user/get-me.e2e.ts @@ -0,0 +1,21 @@ +import { UserSession } from '@notifire/testing'; +import { expect } from 'chai'; + +describe('User get my profile', async () => { + let session: UserSession; + + before(async () => { + session = new UserSession(); + await session.initialize(); + }); + + it('should return a correct user profile', async () => { + const { body } = await session.testAgent.get('/v1/users/me').expect(200); + + const me = body.data; + expect(me._id).to.equal(session.user._id); + expect(me.firstName).to.equal(session.user.firstName); + expect(me.lastName).to.equal(session.user.lastName); + expect(me.email).to.equal(session.user.email); + }); +}); diff --git a/apps/api/e2e/mocha.e2e.opts b/apps/api/e2e/mocha.e2e.opts new file mode 100644 index 00000000000..e69de29bb2d diff --git a/apps/api/e2e/setup.ts b/apps/api/e2e/setup.ts new file mode 100644 index 00000000000..03a2d80f909 --- /dev/null +++ b/apps/api/e2e/setup.ts @@ -0,0 +1,25 @@ +import { DalService } from '@notifire/dal'; +import { testServer } from '@notifire/testing'; +import * as sinon from 'sinon'; +import { bootstrap } from '../src/bootstrap'; + +const dalService = new DalService(); +before(async () => { + await testServer.create(await bootstrap()); + await dalService.connect(process.env.MONGO_URL); +}); + +after(async () => { + await testServer.teardown(); + try { + await dalService.destroy(); + } catch (e) { + if (e.code !== 12586) { + throw e; + } + } +}); + +afterEach(() => { + sinon.restore(); +}); diff --git a/apps/api/nodemon-debug.json b/apps/api/nodemon-debug.json new file mode 100644 index 00000000000..052b0236723 --- /dev/null +++ b/apps/api/nodemon-debug.json @@ -0,0 +1,6 @@ +{ + "watch": ["src"], + "ext": "ts", + "ignore": ["src/**/*.spec.ts"], + "exec": "node --inspect-brk -r ts-node/register -r tsconfig-paths/register src/main.ts" +} diff --git a/apps/api/nodemon.json b/apps/api/nodemon.json new file mode 100644 index 00000000000..4e2bc9177c9 --- /dev/null +++ b/apps/api/nodemon.json @@ -0,0 +1,8 @@ +{ + "watch": ["src", "../core/dist"], + "ext": "ts", + "delay": 2, + "ignoreRoot": [".git"], + "ignore": ["src/**/*.spec.ts"], + "exec": "ts-node -r tsconfig-paths/register src/main.ts" +} diff --git a/apps/api/package.json b/apps/api/package.json new file mode 100644 index 00000000000..e14fb1e52a0 --- /dev/null +++ b/apps/api/package.json @@ -0,0 +1,89 @@ +{ + "name": "@notifire/api", + "version": "0.2.63", + "description": "description", + "author": "", + "private": "true", + "license": "MIT", + "scripts": { + "build": "node --max-old-space-size=1500 node_modules/.bin/tsc -p tsconfig.build.json", + "format": "prettier --write \"src/**/*.ts\"", + "precommit": "lint-staged", + "start": "TZ=UTC ts-node src/main.ts", + "start:dev": "cross-env TZ=UTC nodemon", + "start:test": "cross-env NODE_ENV=test PORT=1336 TZ=UTC nodemon", + "start:debug": "TZ=UTC nodemon --config nodemon-debug.json", + "start:prod": "TZ=UTC node dist/main.js", + "lint": "eslint --fix", + "test": "cross-env TZ=UTC NODE_ENV=test mocha --timeout 10000 --require ts-node/register --exit --file e2e/setup.ts src/**/**/*.spec.ts", + "test:e2e": "cross-env TZ=UTC NODE_ENV=test mocha --timeout 10000 --require ts-node/register --exit --file e2e/setup.ts e2e/**/*.e2e.ts src/**/*.e2e.ts" + }, + "dependencies": { + "@godaddy/terminus": "^4.3.1", + "@nestjs/common": "^7.6.12", + "@nestjs/core": "^7.6.12", + "@nestjs/graphql": "^7.9.8", + "@nestjs/jwt": "^7.2.0", + "@nestjs/passport": "^7.1.5", + "@nestjs/platform-express": "^7.6.12", + "@nestjs/swagger": "^4.7.12", + "@nestjs/terminus": "^7.1.0", + "@nestjsx/crud": "^4.6.2", + "@notifire/dal": "^0.2.33", + "@notifire/testing": "^0.2.33", + "@notifire/node": "^1.0.4", + "@notifire/shared": "^0.2.29", + "@sentry/node": "^6.1.0", + "@sentry/tracing": "^6.3.6", + "@types/handlebars": "^4.1.0", + "@vendia/serverless-express": "^4.3.4", + "bcrypt": "^5.0.0", + "class-transformer": "^0.4.0", + "class-validator": "^0.12.2", + "compression": "^1.7.4", + "dotenv": "^8.2.0", + "envalid": "^6.0.1", + "handlebars": "^4.7.7", + "hat": "^0.0.3", + "jsonwebtoken": "^8.5.1", + "lodash": "^4.17.15", + "moment": "^2.29.1", + "nanoid": "^3.1.20", + "nest-raven": "^7.2.0", + "newrelic": "^7.4.0", + "passport": "^0.4.1", + "passport-github": "^1.1.0", + "passport-jwt": "^4.0.0", + "reflect-metadata": "^0.1.13", + "rxjs": "^6.5.5", + "sanitize-html": "^2.4.0", + "shortid": "^2.2.16", + "slugify": "^1.4.6", + "swagger-ui-express": "^4.1.4", + "typescript": "^4.1.3", + "uuid": "^8.3.2" + }, + "devDependencies": { + "@nestjs/testing": "^7.4.2", + "@types/bcrypt": "^3.0.0", + "@types/chai": "^4.2.11", + "@types/express": "4.17.7", + "@types/mocha": "^8.0.1", + "@types/node": "^14.6.0", + "@types/passport-github": "^1.1.5", + "@types/passport-jwt": "^3.0.3", + "@types/sinon": "^9.0.0", + "@types/supertest": "^2.0.8", + "chai": "^4.2.0", + "faker": "^5.5.3", + "mocha": "^8.1.1", + "nodemon": "^2.0.3", + "sinon": "^9.0.2", + "ts-node": "^9.0.0" + }, + "lint-staged": { + "*.{js,jsx,ts,tsx}": [ + "eslint --fix" + ] + } +} diff --git a/apps/api/src/.example.env b/apps/api/src/.example.env new file mode 100644 index 00000000000..f9763c77d0c --- /dev/null +++ b/apps/api/src/.example.env @@ -0,0 +1,32 @@ +NODE_ENV=dev +PORT=3000 +API_ROOT_URL=http://localhost:3000 +FRONT_BASE_URL=http://localhost:4200 +NEST_STARTER_MAIL=support@notifire.co + +MONGO_URL=mongodb://localhost:27017/notifire-db +REDIS_PORT=6379 +REDIS_HOST=localhost +REDIS_DB_INDEX=2 + +JWT_SECRET=%TEST_REPLACE_THIS +SENDGRID_API_KEY=1 + +S3_BUCKET_NAME=notifire-dev +S3_ACCESS_KEY=1 +S3_SECRET=1 +S3_REGION=us-east-1 + +SENTRY_DSN=1 +MIXPANEL_TOKEN=1 + +CLIENT_SUCCESS_AUTH_REDIRECT=http://localhost:4200/login + +GITHUB_OAUTH_CLIENT_ID=1 +GITHUB_OAUTH_CLIENT_SECRET=1 +GITHUB_OAUTH_REDIRECT=1 + +GOOGLE_OAUTH_CLIENT_ID=1 +GOOGLE_OAUTH_CLIENT_SECRET=1 +GOOGLE_OAUTH_REDIRECT=http://localhost:4200/login + diff --git a/apps/api/src/app.module.ts b/apps/api/src/app.module.ts new file mode 100644 index 00000000000..972f6bb7315 --- /dev/null +++ b/apps/api/src/app.module.ts @@ -0,0 +1,71 @@ +import { DynamicModule, Module, OnModuleInit } from '@nestjs/common'; +import { RavenInterceptor, RavenModule } from 'nest-raven'; +import { APP_INTERCEPTOR } from '@nestjs/core'; +import { Type } from '@nestjs/common/interfaces/type.interface'; +import { ForwardReference } from '@nestjs/common/interfaces/modules/forward-reference.interface'; +import { SharedModule } from './app/shared/shared.module'; +import { UserModule } from './app/user/user.module'; +import { AuthModule } from './app/auth/auth.module'; +import { TestingModule } from './app/testing/testing.module'; +import { HealthModule } from './app/health/health.module'; +import { AdminModule } from './app/admin/admin.module'; +import { OrganizationModule } from './app/organization/organization.module'; +import { ApplicationsModule } from './app/applications/applications.module'; +import { NotificationTemplateModule } from './app/notification-template/notification-template.module'; +import { EventsModule } from './app/events/events.module'; +import { WidgetsModule } from './app/widgets/widgets.module'; +import { ActivityModule } from './app/activity/activity.module'; +import { ChannelsModule } from './app/channels/channels.module'; +import { StorageModule } from './app/storage/storage.module'; +import { NotificationGroupsModule } from './app/notification-groups/notification-groups.module'; +import { InvitesModule } from './app/invites/invites.module'; +import { ContentTemplatesModule } from './app/content-templates/content-templates.module'; +import { QueueService } from './app/shared/services/queue'; + +const modules: Array | DynamicModule | Promise | ForwardReference> = [ + OrganizationModule, + SharedModule, + UserModule, + AuthModule, + HealthModule, + AdminModule, + ApplicationsModule, + NotificationTemplateModule, + EventsModule, + WidgetsModule, + ActivityModule, + ChannelsModule, + StorageModule, + NotificationGroupsModule, + InvitesModule, + ContentTemplatesModule, +]; + +const providers = []; + +if (process.env.SENTRY_DSN) { + modules.push(RavenModule); + providers.push({ + provide: APP_INTERCEPTOR, + useValue: new RavenInterceptor({ + user: ['_id', 'firstName', 'email', 'organizationId', 'applicationId'], + }), + }); +} + +if (process.env.NODE_ENV === 'test') { + modules.push(TestingModule); +} + +@Module({ + imports: modules, + controllers: [], + providers, +}) +export class AppModule implements OnModuleInit { + constructor(private queueService: QueueService) {} + + async onModuleInit() { + // + } +} diff --git a/apps/api/src/app/activity/activity.controller.ts b/apps/api/src/app/activity/activity.controller.ts new file mode 100644 index 00000000000..07a9c7ce374 --- /dev/null +++ b/apps/api/src/app/activity/activity.controller.ts @@ -0,0 +1,58 @@ +import { Controller, Get, Query, UseGuards } from '@nestjs/common'; +import { ChannelTypeEnum, IJwtPayload } from '@notifire/shared'; +import { GetActivityFeed } from './usecases/get-activity-feed/get-activity-feed.usecase'; +import { GetActivityFeedCommand } from './usecases/get-activity-feed/get-activity-feed.command'; +import { UserSession } from '../shared/framework/user.decorator'; +import { JwtAuthGuard } from '../auth/framework/auth.guard'; +import { GetActivityStats } from './usecases/get-activity-stats/get-activity-stats.usecase'; +import { GetActivityStatsCommand } from './usecases/get-activity-stats/get-activity-stats.command'; + +@Controller('/activity') +export class ActivityController { + constructor(private getActivityFeedUsecase: GetActivityFeed, private getActivityStatsUsecase: GetActivityStats) {} + + @Get('') + @UseGuards(JwtAuthGuard) + getActivityFeed( + @UserSession() user: IJwtPayload, + @Query('page') page = 0, + @Query('channels') channels: ChannelTypeEnum[] | ChannelTypeEnum, + @Query('templates') templates: string[] | string, + @Query('search') search: string + ) { + let channelsQuery: ChannelTypeEnum[]; + + if (channels) { + channelsQuery = Array.isArray(channels) ? channels : [channels]; + } + + let templatesQuery: string[]; + if (templates) { + templatesQuery = Array.isArray(templates) ? templates : [templates]; + } + + return this.getActivityFeedUsecase.execute( + GetActivityFeedCommand.create({ + page: page ? Number(page) : 0, + organizationId: user.organizationId, + applicationId: user.applicationId, + userId: user._id, + channels: channelsQuery, + templates: templatesQuery, + search, + }) + ); + } + + @Get('/stats') + @UseGuards(JwtAuthGuard) + getActivityStats(@UserSession() user: IJwtPayload, @Query('page') page = 0) { + return this.getActivityStatsUsecase.execute( + GetActivityStatsCommand.create({ + organizationId: user.organizationId, + applicationId: user.applicationId, + userId: user._id, + }) + ); + } +} diff --git a/apps/api/src/app/activity/activity.module.ts b/apps/api/src/app/activity/activity.module.ts new file mode 100644 index 00000000000..ed7f968f896 --- /dev/null +++ b/apps/api/src/app/activity/activity.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { USE_CASES } from './usecases'; +import { ActivityController } from './activity.controller'; +import { SharedModule } from '../shared/shared.module'; + +@Module({ + imports: [SharedModule], + providers: [...USE_CASES], + controllers: [ActivityController], +}) +export class ActivityModule {} diff --git a/apps/api/src/app/activity/e2e/get-activity-feed.e2e.ts b/apps/api/src/app/activity/e2e/get-activity-feed.e2e.ts new file mode 100644 index 00000000000..d21f402ee57 --- /dev/null +++ b/apps/api/src/app/activity/e2e/get-activity-feed.e2e.ts @@ -0,0 +1,126 @@ +import { NotificationTemplateEntity } from '@notifire/dal'; +import { UserSession } from '@notifire/testing'; +import { expect } from 'chai'; +import { ChannelTypeEnum, IMessage } from '@notifire/shared'; + +describe('Get activity feed - /activity (GET)', async () => { + let session: UserSession; + let template: NotificationTemplateEntity; + let smsOnlyTemplate: NotificationTemplateEntity; + + beforeEach(async () => { + session = new UserSession(); + await session.initialize(); + template = await session.createTemplate(); + smsOnlyTemplate = await session.createChannelTemplate(ChannelTypeEnum.SMS); + await session.testAgent + .post('/v1/widgets/session/initialize') + .send({ + applicationIdentifier: session.application.identifier, + $user_id: '12345', + $first_name: 'Test', + $last_name: 'User', + $email: 'test@example.com', + }) + .expect(201); + }); + + it('should get the current activity feed of user', async function () { + await session.triggerEvent(template.triggers[0].identifier, { + $user_id: '12345', + firstName: 'Test', + }); + + await session.triggerEvent(template.triggers[0].identifier, { + $user_id: '12345', + firstName: 'Test', + }); + + const { body } = await session.testAgent.get('/v1/activity?page=0'); + + const activities = body.data; + expect(body.totalCount).to.equal(4); + expect(activities.length).to.equal(4); + expect(activities[0].template.name).to.equal(template.name); + expect(activities[0].template._id).to.equal(template._id); + expect(activities[0].subscriber.firstName).to.equal('Test'); + expect(activities[0].channel).to.be.oneOf(Object.keys(ChannelTypeEnum).map((i) => ChannelTypeEnum[i])); + }); + + it('should filter by channel', async function () { + await session.triggerEvent(template.triggers[0].identifier, { + $user_id: '12345', + firstName: 'Test', + }); + + await session.triggerEvent(smsOnlyTemplate.triggers[0].identifier, { + $user_id: '12345', + firstName: 'Test', + }); + + await session.triggerEvent(smsOnlyTemplate.triggers[0].identifier, { + $user_id: '12345', + firstName: 'Test', + }); + + const { body } = await session.testAgent.get(`/v1/activity?page=0&channels=${ChannelTypeEnum.SMS}`); + const activities: IMessage[] = body.data; + expect(activities.length).to.equal(2); + expect(activities[0].channel).to.equal(ChannelTypeEnum.SMS); + expect(activities[0].template.name).to.equal(smsOnlyTemplate.name); + }); + + it('should filter by templateId', async function () { + await session.triggerEvent(smsOnlyTemplate.triggers[0].identifier, { + $user_id: '12345', + firstName: 'Test', + }); + + await session.triggerEvent(template.triggers[0].identifier, { + $user_id: '12345', + firstName: 'Test', + }); + + await session.triggerEvent(template.triggers[0].identifier, { + $user_id: '12345', + firstName: 'Test', + }); + + const { body } = await session.testAgent.get(`/v1/activity?page=0&templates=${template._id}`); + const activities: IMessage[] = body.data; + expect(activities.length).to.equal(4); + expect(activities[0]._templateId).to.equal(template._id); + expect(activities[1]._templateId).to.equal(template._id); + expect(activities[2]._templateId).to.equal(template._id); + expect(activities[3]._templateId).to.equal(template._id); + }); + + it('should filter by email', async function () { + await session.triggerEvent(smsOnlyTemplate.triggers[0].identifier, { + $user_id: '12345', + firstName: 'Test', + }); + + await session.triggerEvent(template.triggers[0].identifier, { + $user_id: '1234564', + firstName: 'Test', + $email: 'test@email.coms', + }); + + await session.triggerEvent(template.triggers[0].identifier, { + $user_id: '12345', + firstName: 'Test', + }); + + await session.triggerEvent(template.triggers[0].identifier, { + $user_id: '12345', + firstName: 'Test', + }); + + const { body } = await session.testAgent.get(`/v1/activity?page=0&search=test@email.coms`); + const activities: IMessage[] = body.data; + expect(activities.length).to.equal(2); + expect(activities[0]._templateId).to.equal(template._id); + expect(activities[1]._templateId).to.equal(template._id); + }); +}); diff --git a/apps/api/src/app/activity/e2e/get-activity-stats.e2e.ts b/apps/api/src/app/activity/e2e/get-activity-stats.e2e.ts new file mode 100644 index 00000000000..e5ad50ea604 --- /dev/null +++ b/apps/api/src/app/activity/e2e/get-activity-stats.e2e.ts @@ -0,0 +1,69 @@ +import { MessageRepository, NotificationTemplateEntity } from '@notifire/dal'; +import { UserSession } from '@notifire/testing'; +import { expect } from 'chai'; +import * as moment from 'moment'; + +describe('Get activity stats - /activity/stats (GET)', async () => { + let session: UserSession; + let template: NotificationTemplateEntity; + const messageRepository = new MessageRepository(); + + beforeEach(async () => { + session = new UserSession(); + await session.initialize(); + template = await session.createTemplate(); + + await session.testAgent + .post('/v1/widgets/session/initialize') + .send({ + applicationIdentifier: session.application.identifier, + $user_id: '12345', + $first_name: 'Test', + $last_name: 'User', + $email: 'test@example.com', + }) + .expect(201); + }); + + it('should retrieve last month and last week activity', async function () { + await session.triggerEvent(template.triggers[0].identifier, { + $user_id: '12345', + firstName: 'Test', + }); + + await session.triggerEvent(template.triggers[0].identifier, { + $user_id: '12345', + firstName: 'Test', + }); + + const existing = await messageRepository.find( + { + _applicationId: session.application._id, + }, + null, + { limit: 2 } + ); + + await messageRepository._model.updateMany( + { + _id: existing.map((i) => i._id), + }, + { + $set: { + createdAt: moment().subtract(12, 'days').toDate(), + }, + }, + { + multi: true, + timestamps: false, + } + ); + + const { + body: { data }, + } = await session.testAgent.get('/v1/activity/stats'); + + expect(data.weeklySent).to.equal(2); + expect(data.monthlySent).to.equal(4); + }); +}); diff --git a/apps/api/src/app/activity/usecases/get-activity-feed/get-activity-feed.command.ts b/apps/api/src/app/activity/usecases/get-activity-feed/get-activity-feed.command.ts new file mode 100644 index 00000000000..cbbc35e8712 --- /dev/null +++ b/apps/api/src/app/activity/usecases/get-activity-feed/get-activity-feed.command.ts @@ -0,0 +1,29 @@ +import { IsArray, IsEnum, IsMongoId, IsNumber, IsOptional, IsPositive, IsString } from 'class-validator'; +import { ChannelTypeEnum } from '@notifire/shared'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; + +export class GetActivityFeedCommand extends ApplicationWithUserCommand { + static create(data: GetActivityFeedCommand) { + return CommandHelper.create(GetActivityFeedCommand, data); + } + + @IsNumber() + @IsOptional() + page: number; + + @IsOptional() + @IsEnum(ChannelTypeEnum, { + each: true, + }) + channels?: ChannelTypeEnum[]; + + @IsOptional() + @IsArray() + @IsMongoId({ each: true }) + templates?: string[]; + + @IsOptional() + @IsString() + search?: string; +} diff --git a/apps/api/src/app/activity/usecases/get-activity-feed/get-activity-feed.usecase.ts b/apps/api/src/app/activity/usecases/get-activity-feed/get-activity-feed.usecase.ts new file mode 100644 index 00000000000..d4cb939b920 --- /dev/null +++ b/apps/api/src/app/activity/usecases/get-activity-feed/get-activity-feed.usecase.ts @@ -0,0 +1,53 @@ +import { Injectable } from '@nestjs/common'; +import { + MessageEntity, + MessageRepository, + NotificationEntity, + NotificationRepository, + SubscriberRepository, +} from '@notifire/dal'; +import { GetActivityFeedCommand } from './get-activity-feed.command'; + +@Injectable() +export class GetActivityFeed { + constructor( + private notificationRepository: NotificationRepository, + private messageRepository: MessageRepository, + private subscribersRepository: SubscriberRepository + ) {} + + async execute( + command: GetActivityFeedCommand + ): Promise<{ totalCount: number; data: MessageEntity[]; pageSize: number; page: number }> { + const LIMIT = 10; + + let subscriberId: string; + if (command.search) { + const foundSubscriber = await this.subscribersRepository.searchSubscriber(command.applicationId, command.search); + subscriberId = foundSubscriber?._id; + + if (!subscriberId) { + return { + page: 0, + totalCount: 0, + pageSize: LIMIT, + data: [], + }; + } + } + + const { data: messages, totalCount } = await this.messageRepository.getFeed( + command.applicationId, + { channels: command.channels, templates: command.templates, subscriberId }, + command.page * LIMIT, + LIMIT + ); + + return { + page: command.page, + totalCount, + pageSize: LIMIT, + data: messages, + }; + } +} diff --git a/apps/api/src/app/activity/usecases/get-activity-stats/get-activity-stats.command.ts b/apps/api/src/app/activity/usecases/get-activity-stats/get-activity-stats.command.ts new file mode 100644 index 00000000000..cb4d8e6279b --- /dev/null +++ b/apps/api/src/app/activity/usecases/get-activity-stats/get-activity-stats.command.ts @@ -0,0 +1,8 @@ +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; + +export class GetActivityStatsCommand extends ApplicationWithUserCommand { + static create(data: GetActivityStatsCommand) { + return CommandHelper.create(GetActivityStatsCommand, data); + } +} diff --git a/apps/api/src/app/activity/usecases/get-activity-stats/get-activity-stats.usecase.ts b/apps/api/src/app/activity/usecases/get-activity-stats/get-activity-stats.usecase.ts new file mode 100644 index 00000000000..e73afe34ee9 --- /dev/null +++ b/apps/api/src/app/activity/usecases/get-activity-stats/get-activity-stats.usecase.ts @@ -0,0 +1,37 @@ +import { Injectable } from '@nestjs/common'; +import { MessageRepository } from '@notifire/dal'; +import * as moment from 'moment'; +import { GetActivityStatsCommand } from './get-activity-stats.command'; + +@Injectable() +export class GetActivityStats { + constructor(private messageRepository: MessageRepository) {} + + async execute( + command: GetActivityStatsCommand + ): Promise<{ + weeklySent: number; + monthlySent: number; + }> { + const monthly = await this.messageRepository.count({ + _applicationId: command.applicationId, + _organizationId: command.organizationId, + createdAt: { + $gte: String(moment().subtract(1, 'month').toDate()), + }, + }); + + const weekly = await this.messageRepository.count({ + _applicationId: command.applicationId, + _organizationId: command.organizationId, + createdAt: { + $gte: String(moment().subtract(1, 'week').toDate()), + }, + }); + + return { + weeklySent: weekly, + monthlySent: monthly, + }; + } +} diff --git a/apps/api/src/app/activity/usecases/index.ts b/apps/api/src/app/activity/usecases/index.ts new file mode 100644 index 00000000000..463e637d501 --- /dev/null +++ b/apps/api/src/app/activity/usecases/index.ts @@ -0,0 +1,8 @@ +import { GetActivityStats } from './get-activity-stats/get-activity-stats.usecase'; +import { GetActivityFeed } from './get-activity-feed/get-activity-feed.usecase'; + +export const USE_CASES = [ + GetActivityStats, + GetActivityFeed, + // +]; diff --git a/apps/api/src/app/admin/admin.module.ts b/apps/api/src/app/admin/admin.module.ts new file mode 100644 index 00000000000..af238ee0413 --- /dev/null +++ b/apps/api/src/app/admin/admin.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { SharedModule } from '../shared/shared.module'; +import { UsersController } from './entities/users/users.controller'; +import { UsersService } from './entities/users/users.service'; + +@Module({ + imports: [SharedModule], + controllers: [UsersController], + providers: [UsersService], +}) +export class AdminModule {} diff --git a/apps/api/src/app/admin/entities/users/users.controller.ts b/apps/api/src/app/admin/entities/users/users.controller.ts new file mode 100644 index 00000000000..f7818dd1287 --- /dev/null +++ b/apps/api/src/app/admin/entities/users/users.controller.ts @@ -0,0 +1,21 @@ +import { Controller } from '@nestjs/common'; +import { Crud } from '@nestjsx/crud'; +import { UserEntity } from '@notifire/dal'; +import { UsersService } from './users.service'; + +@Crud({ + model: { + type: UserEntity, + }, + params: { + id: { + type: 'string', + primary: true, + field: 'id', + }, + }, +}) +@Controller('/admin/entities/users') +export class UsersController { + constructor(public service: UsersService) {} +} diff --git a/apps/api/src/app/admin/entities/users/users.service.ts b/apps/api/src/app/admin/entities/users/users.service.ts new file mode 100644 index 00000000000..fdf24de3599 --- /dev/null +++ b/apps/api/src/app/admin/entities/users/users.service.ts @@ -0,0 +1,10 @@ +import { Injectable } from '@nestjs/common'; +import { UserEntity, UserRepository } from '@notifire/dal'; +import { MongooseCrudService } from '../../../shared/crud/mongoose-crud.service'; + +@Injectable() +export class UsersService extends MongooseCrudService { + constructor(private usersRepository: UserRepository) { + super(usersRepository._model); + } +} diff --git a/apps/api/src/app/applications/applications.controller.ts b/apps/api/src/app/applications/applications.controller.ts new file mode 100644 index 00000000000..f35108bc74e --- /dev/null +++ b/apps/api/src/app/applications/applications.controller.ts @@ -0,0 +1,90 @@ +import { + Body, + ClassSerializerInterceptor, + Controller, + Get, + Post, + Put, + UseGuards, + UseInterceptors, +} from '@nestjs/common'; +import { IJwtPayload } from '@notifire/shared'; +import { ApplicationEntity } from '@notifire/dal'; +import { AuthGuard } from '@nestjs/passport'; +import { UserSession } from '../shared/framework/user.decorator'; +import { CreateApplication } from './usecases/create-application/create-application.usecase'; +import { CreateApplicationCommand } from './usecases/create-application/create-application.command'; +import { CreateApplicationBodyDto } from './dto/create-application.dto'; +import { GetApiKeysCommand } from './usecases/get-api-keys/get-api-keys.command'; +import { GetApiKeys } from './usecases/get-api-keys/get-api-keys.usecase'; +import { GetApplication, GetApplicationCommand } from './usecases/get-application'; +import { JwtAuthGuard } from '../auth/framework/auth.guard'; +import { UpdateBrandingDetails } from './usecases/update-branding-details/update-branding-details.usecase'; +import { UpdateBrandingDetailsCommand } from './usecases/update-branding-details/update-branding-details.command'; + +@Controller('/applications') +@UseInterceptors(ClassSerializerInterceptor) +@UseGuards(JwtAuthGuard) +export class ApplicationsController { + constructor( + private createApplicationUsecase: CreateApplication, + private getApiKeysUsecase: GetApiKeys, + private getApplicationUsecase: GetApplication, + private updateBrandingDetailsUsecase: UpdateBrandingDetails + ) {} + + @Get('/me') + async getCurrentApplication(@UserSession() user: IJwtPayload): Promise { + return await this.getApplicationUsecase.execute( + GetApplicationCommand.create({ + applicationId: user.applicationId, + userId: user._id, + organizationId: user.organizationId, + }) + ); + } + + @Post('/') + async createApplication( + @UserSession() user: IJwtPayload, + @Body() body: CreateApplicationBodyDto + ): Promise { + return await this.createApplicationUsecase.execute( + CreateApplicationCommand.create({ + name: body.name, + userId: user._id, + organizationId: user.organizationId, + }) + ); + } + + @Put('/branding') + async updateBrandingDetails( + @UserSession() user: IJwtPayload, + @Body() body: { color: string; logo: string; fontColor: string; contentBackground: string; fontFamily: string } + ) { + return await this.updateBrandingDetailsUsecase.execute( + UpdateBrandingDetailsCommand.create({ + logo: body.logo, + color: body.color, + applicationId: user.applicationId, + userId: user._id, + organizationId: user.organizationId, + fontColor: body.fontColor, + fontFamily: body.fontFamily, + contentBackground: body.contentBackground, + }) + ); + } + + @Get('/api-keys') + async getOrganizationApiKeys(@UserSession() user: IJwtPayload) { + const command = GetApiKeysCommand.create({ + userId: user._id, + organizationId: user.organizationId, + applicationId: user.applicationId, + }); + + return await this.getApiKeysUsecase.execute(command); + } +} diff --git a/apps/api/src/app/applications/applications.module.ts b/apps/api/src/app/applications/applications.module.ts new file mode 100644 index 00000000000..5801458b34f --- /dev/null +++ b/apps/api/src/app/applications/applications.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; +import { SharedModule } from '../shared/shared.module'; +import { USE_CASES } from './usecases'; +import { ApplicationsController } from './applications.controller'; + +@Module({ + imports: [SharedModule], + controllers: [ApplicationsController], + providers: [...USE_CASES], + exports: [...USE_CASES], +}) +export class ApplicationsModule {} diff --git a/apps/api/src/app/applications/dto/create-application.dto.ts b/apps/api/src/app/applications/dto/create-application.dto.ts new file mode 100644 index 00000000000..6d58113b8e9 --- /dev/null +++ b/apps/api/src/app/applications/dto/create-application.dto.ts @@ -0,0 +1,6 @@ +import { IsDefined, IsEnum } from 'class-validator'; + +export class CreateApplicationBodyDto { + @IsDefined() + name: string; +} diff --git a/apps/api/src/app/applications/e2e/update-branding-details.e2e.ts b/apps/api/src/app/applications/e2e/update-branding-details.e2e.ts new file mode 100644 index 00000000000..ded51688fb0 --- /dev/null +++ b/apps/api/src/app/applications/e2e/update-branding-details.e2e.ts @@ -0,0 +1,32 @@ +import { ApplicationRepository } from '@notifire/dal'; +import { UserSession } from '@notifire/testing'; +import { expect } from 'chai'; + +describe('Update Branding Details - /applications/branding (PUT)', function () { + let session: UserSession; + const applicationRepository = new ApplicationRepository(); + + beforeEach(async () => { + session = new UserSession(); + await session.initialize(); + }); + + it('should update the branding details', async function () { + const payload = { + color: '#fefefe', + fontColor: '#f4f4f4', + contentBackground: '#fefefe', + fontFamily: 'Nunito', + logo: 'https://st.depositphotos.com/1186248/2404/i/600/depositphotos_24043595-stock-photo-fake-rubber-stamp.jpg', + }; + + await session.testAgent.put('/v1/applications/branding').send(payload); + + const application = await applicationRepository.findById(session.application._id); + expect(application.branding.color).to.equal(payload.color); + expect(application.branding.logo).to.equal(payload.logo); + expect(application.branding.fontColor).to.equal(payload.fontColor); + expect(application.branding.fontFamily).to.equal(payload.fontFamily); + expect(application.branding.contentBackground).to.equal(payload.contentBackground); + }); +}); diff --git a/apps/api/src/app/applications/usecases/create-application/create-application.command.ts b/apps/api/src/app/applications/usecases/create-application/create-application.command.ts new file mode 100644 index 00000000000..23345e14b26 --- /dev/null +++ b/apps/api/src/app/applications/usecases/create-application/create-application.command.ts @@ -0,0 +1,12 @@ +import { IsDefined, IsEnum } from 'class-validator'; +import { OrganizationCommand } from '../../../shared/commands/organization.command'; +import { CommandHelper } from '../../../shared/commands/command.helper'; + +export class CreateApplicationCommand extends OrganizationCommand { + static create(data: CreateApplicationCommand) { + return CommandHelper.create(CreateApplicationCommand, data); + } + + @IsDefined() + name: string; +} diff --git a/apps/api/src/app/applications/usecases/create-application/create-application.e2e.ts b/apps/api/src/app/applications/usecases/create-application/create-application.e2e.ts new file mode 100644 index 00000000000..dfe72ffc0b5 --- /dev/null +++ b/apps/api/src/app/applications/usecases/create-application/create-application.e2e.ts @@ -0,0 +1,34 @@ +import { ApplicationRepository } from '@notifire/dal'; +import { UserSession } from '@notifire/testing'; +import { expect } from 'chai'; + +describe('Create Application - /applications (POST)', async () => { + let session: UserSession; + const applicationRepository = new ApplicationRepository(); + before(async () => { + session = new UserSession(); + await session.initialize({ + noApplication: true, + }); + }); + + it('should create application entity correctly', async () => { + const demoApplication = { + name: 'Hello App', + }; + const { body } = await session.testAgent.post('/v1/applications').send(demoApplication).expect(201); + expect(body.data.name).to.eq(demoApplication.name); + expect(body.data._organizationId).to.eq(session.organization._id); + expect(body.data.identifier).to.be.ok; + const dbApp = await applicationRepository.findById(body.data._id); + expect(dbApp.apiKeys.length).to.equal(1); + expect(dbApp.apiKeys[0].key).to.be.ok; + expect(dbApp.apiKeys[0]._userId).to.equal(session.user._id); + }); + + it('should fail when no name provided', async () => { + const demoApplication = {}; + const { body } = await session.testAgent.post('/v1/applications').send(demoApplication).expect(400); + expect(body.message[0]).to.contain('name should not be null'); + }); +}); diff --git a/apps/api/src/app/applications/usecases/create-application/create-application.usecase.ts b/apps/api/src/app/applications/usecases/create-application/create-application.usecase.ts new file mode 100644 index 00000000000..66444458cea --- /dev/null +++ b/apps/api/src/app/applications/usecases/create-application/create-application.usecase.ts @@ -0,0 +1,24 @@ +import { Injectable } from '@nestjs/common'; +import { ApplicationRepository } from '@notifire/dal'; +import * as hat from 'hat'; +import { nanoid } from 'nanoid'; +import { CreateApplicationCommand } from './create-application.command'; + +@Injectable() +export class CreateApplication { + constructor(private applicationRepository: ApplicationRepository) {} + + async execute(command: CreateApplicationCommand) { + return await this.applicationRepository.create({ + _organizationId: command.organizationId, + name: command.name, + identifier: nanoid(12), + apiKeys: [ + { + key: hat(), + _userId: command.userId, + }, + ], + }); + } +} diff --git a/apps/api/src/app/applications/usecases/get-api-keys/get-api-keys.command.ts b/apps/api/src/app/applications/usecases/get-api-keys/get-api-keys.command.ts new file mode 100644 index 00000000000..407b8d813e5 --- /dev/null +++ b/apps/api/src/app/applications/usecases/get-api-keys/get-api-keys.command.ts @@ -0,0 +1,8 @@ +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; + +export class GetApiKeysCommand extends ApplicationWithUserCommand { + static create(data: GetApiKeysCommand) { + return CommandHelper.create(GetApiKeysCommand, data); + } +} diff --git a/apps/api/src/app/applications/usecases/get-api-keys/get-api-keys.usecase.ts b/apps/api/src/app/applications/usecases/get-api-keys/get-api-keys.usecase.ts new file mode 100644 index 00000000000..ed0c934a041 --- /dev/null +++ b/apps/api/src/app/applications/usecases/get-api-keys/get-api-keys.usecase.ts @@ -0,0 +1,12 @@ +import { Injectable } from '@nestjs/common'; +import { IApiKey, ApplicationRepository } from '@notifire/dal'; +import { GetApiKeysCommand } from './get-api-keys.command'; + +@Injectable() +export class GetApiKeys { + constructor(private applicationRepository: ApplicationRepository) {} + + async execute(command: GetApiKeysCommand): Promise { + return await this.applicationRepository.getApiKeys(command.applicationId); + } +} diff --git a/apps/api/src/app/applications/usecases/get-application/get-application.command.ts b/apps/api/src/app/applications/usecases/get-application/get-application.command.ts new file mode 100644 index 00000000000..ccc3662a729 --- /dev/null +++ b/apps/api/src/app/applications/usecases/get-application/get-application.command.ts @@ -0,0 +1,8 @@ +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; + +export class GetApplicationCommand extends ApplicationWithUserCommand { + static create(data: GetApplicationCommand) { + return CommandHelper.create(GetApplicationCommand, data); + } +} diff --git a/apps/api/src/app/applications/usecases/get-application/get-application.e2e.ts b/apps/api/src/app/applications/usecases/get-application/get-application.e2e.ts new file mode 100644 index 00000000000..20b9af67dc6 --- /dev/null +++ b/apps/api/src/app/applications/usecases/get-application/get-application.e2e.ts @@ -0,0 +1,18 @@ +import { ApplicationRepository } from '@notifire/dal'; +import { UserSession } from '@notifire/testing'; +import { expect } from 'chai'; + +describe('Get Application - /applications/me (GET)', async () => { + let session: UserSession; + before(async () => { + session = new UserSession(); + await session.initialize(); + }); + + it('should return correct application to user', async () => { + const { body } = await session.testAgent.get('/v1/applications/me'); + expect(body.data.name).to.eq(session.application.name); + expect(body.data._organizationId).to.eq(session.organization._id); + expect(body.data.identifier).to.equal(session.application.identifier); + }); +}); diff --git a/apps/api/src/app/applications/usecases/get-application/get-application.usecase.ts b/apps/api/src/app/applications/usecases/get-application/get-application.usecase.ts new file mode 100644 index 00000000000..ee3f10167ed --- /dev/null +++ b/apps/api/src/app/applications/usecases/get-application/get-application.usecase.ts @@ -0,0 +1,18 @@ +import { Injectable } from '@nestjs/common'; +import { ApplicationRepository } from '@notifire/dal'; +import { GetApplicationCommand } from './get-application.command'; + +@Injectable() +export class GetApplication { + constructor(private applicationRepository: ApplicationRepository) {} + + async execute(command: GetApplicationCommand) { + return await this.applicationRepository.findOne( + { + _id: command.applicationId, + _organizationId: command.organizationId, + }, + '-apiKeys' + ); + } +} diff --git a/apps/api/src/app/applications/usecases/get-application/index.ts b/apps/api/src/app/applications/usecases/get-application/index.ts new file mode 100644 index 00000000000..39427581a75 --- /dev/null +++ b/apps/api/src/app/applications/usecases/get-application/index.ts @@ -0,0 +1,2 @@ +export * from './get-application.command'; +export * from './get-application.usecase'; diff --git a/apps/api/src/app/applications/usecases/index.ts b/apps/api/src/app/applications/usecases/index.ts new file mode 100644 index 00000000000..1c200c08e9c --- /dev/null +++ b/apps/api/src/app/applications/usecases/index.ts @@ -0,0 +1,12 @@ +import { UpdateBrandingDetails } from './update-branding-details/update-branding-details.usecase'; +import { CreateApplication } from './create-application/create-application.usecase'; +import { GetApiKeys } from './get-api-keys/get-api-keys.usecase'; +import { GetApplication } from './get-application'; + +export const USE_CASES = [ + // + CreateApplication, + GetApiKeys, + GetApplication, + UpdateBrandingDetails, +]; diff --git a/apps/api/src/app/applications/usecases/update-branding-details/update-branding-details.command.ts b/apps/api/src/app/applications/usecases/update-branding-details/update-branding-details.command.ts new file mode 100644 index 00000000000..19be48c87d5 --- /dev/null +++ b/apps/api/src/app/applications/usecases/update-branding-details/update-branding-details.command.ts @@ -0,0 +1,27 @@ +import { IsHexColor, IsOptional, IsUrl } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; + +export class UpdateBrandingDetailsCommand extends ApplicationWithUserCommand { + static create(data: UpdateBrandingDetailsCommand) { + return CommandHelper.create(UpdateBrandingDetailsCommand, data); + } + + @IsUrl({ require_tld: false }) + logo: string; + + @IsOptional() + @IsHexColor() + color: string; + + @IsOptional() + @IsHexColor() + fontColor: string; + + @IsOptional() + @IsHexColor() + contentBackground: string; + + @IsOptional() + fontFamily?: string; +} diff --git a/apps/api/src/app/applications/usecases/update-branding-details/update-branding-details.usecase.ts b/apps/api/src/app/applications/usecases/update-branding-details/update-branding-details.usecase.ts new file mode 100644 index 00000000000..c8eccad729c --- /dev/null +++ b/apps/api/src/app/applications/usecases/update-branding-details/update-branding-details.usecase.ts @@ -0,0 +1,22 @@ +import { Injectable } from '@nestjs/common'; +import { ApplicationRepository } from '@notifire/dal'; +import { UpdateBrandingDetailsCommand } from './update-branding-details.command'; + +@Injectable() +export class UpdateBrandingDetails { + constructor(private applicationRepository: ApplicationRepository) {} + + async execute(command: UpdateBrandingDetailsCommand) { + const payload = { + color: command.color, + logo: command.logo, + fontColor: command.fontColor, + contentBackground: command.contentBackground, + fontFamily: command.fontFamily, + }; + + await this.applicationRepository.updateBrandingDetails(command.applicationId, payload); + + return payload; + } +} diff --git a/apps/api/src/app/auth/auth.controller.ts b/apps/api/src/app/auth/auth.controller.ts new file mode 100644 index 00000000000..2010730da83 --- /dev/null +++ b/apps/api/src/app/auth/auth.controller.ts @@ -0,0 +1,176 @@ +import { + BadRequestException, + Body, + ClassSerializerInterceptor, + Controller, + Get, + HttpCode, + NotFoundException, + Param, + Post, + Query, + Req, + Res, + UseGuards, + UseInterceptors, +} from '@nestjs/common'; +import { MemberRepository, OrganizationRepository, UserRepository } from '@notifire/dal'; +import { JwtService } from '@nestjs/jwt'; +import { AuthGuard } from '@nestjs/passport'; +import { IJwtPayload } from '@notifire/shared'; +import { AuthService } from './services/auth.service'; +import { UserRegistrationBodyDto } from './dtos/user-registration.dto'; +import { UserRegister } from './usecases/register/user-register.usecase'; +import { UserRegisterCommand } from './usecases/register/user-register.command'; +import { Login } from './usecases/login/login.usecase'; +import { LoginBodyDto } from './dtos/login.dto'; +import { LoginCommand } from './usecases/login/login.command'; +import { UserSession } from '../shared/framework/user.decorator'; +import { SwitchApplication } from './usecases/switch-application/switch-application.usecase'; +import { SwitchApplicationCommand } from './usecases/switch-application/switch-application.command'; +import { SwitchOrganization } from './usecases/switch-organization/switch-organization.usecase'; +import { SwitchOrganizationCommand } from './usecases/switch-organization/switch-organization.command'; +import { JwtAuthGuard } from './framework/auth.guard'; +import { PasswordResetRequestCommand } from './usecases/password-reset-request/password-reset-request.command'; +import { PasswordResetRequest } from './usecases/password-reset-request/password-reset-request.usecase'; +import { PasswordResetCommand } from './usecases/password-reset/password-reset.command'; +import { PasswordReset } from './usecases/password-reset/password-reset.usecase'; + +@Controller('/auth') +@UseInterceptors(ClassSerializerInterceptor) +export class AuthController { + constructor( + private userRepository: UserRepository, + private jwtService: JwtService, + private authService: AuthService, + private userRegisterUsecase: UserRegister, + private loginUsecase: Login, + private organizationRepository: OrganizationRepository, + private switchApplicationUsecase: SwitchApplication, + private switchOrganizationUsecase: SwitchOrganization, + private memberRepository: MemberRepository, + private passwordResetRequestUsecase: PasswordResetRequest, + private passwordResetUsecase: PasswordReset + ) {} + + @Get('/github') + githubTestAuth() { + return { + success: true, + }; + } + + @Get('/github/callback') + @UseGuards(AuthGuard('github')) + async githubCallback(@Req() request, @Res() response) { + if (!request.user || !request.user.token) { + return response.redirect(`${process.env.CLIENT_SUCCESS_AUTH_REDIRECT}?error=AuthenticationError`); + } + + let url = `${process.env.CLIENT_SUCCESS_AUTH_REDIRECT}?token=${request.user.token}`; + if (request.user.newUser) { + url += '&newUser=true'; + } + + return response.redirect(url); + } + + @Get('/refresh') + @UseGuards(JwtAuthGuard) + refreshToken(@UserSession() user: IJwtPayload) { + if (!user || !user._id) throw new BadRequestException(); + + return this.authService.refreshToken(user._id); + } + + @Post('/register') + async userRegistration(@Body() body: UserRegistrationBodyDto) { + return await this.userRegisterUsecase.execute( + UserRegisterCommand.create({ + email: body.email, + password: body.password, + firstName: body.firstName, + lastName: body.lastName, + organizationName: body.organizationName, + }) + ); + } + + @Post('/reset/request') + async forgotPasswordRequest(@Body() body: { email: string }) { + return await this.passwordResetRequestUsecase.execute( + PasswordResetRequestCommand.create({ + email: body.email, + }) + ); + } + + @Post('/reset') + async passwordReset(@Body() body: { password: string; token: string }) { + return await this.passwordResetUsecase.execute( + PasswordResetCommand.create({ + password: body.password, + token: body.token, + }) + ); + } + + @Post('/login') + async userLogin(@Body() body: LoginBodyDto) { + return await this.loginUsecase.execute( + LoginCommand.create({ + email: body.email, + password: body.password, + }) + ); + } + + @Post('/organizations/:organizationId/switch') + @UseGuards(JwtAuthGuard) + @HttpCode(200) + async organizationSwitch( + @UserSession() user: IJwtPayload, + @Param('organizationId') organizationId: string + ): Promise { + const command = SwitchOrganizationCommand.create({ + userId: user._id, + newOrganizationId: organizationId, + }); + + return await this.switchOrganizationUsecase.execute(command); + } + + @Post('/applications/:applicationId/switch') + @UseGuards(JwtAuthGuard) + @HttpCode(200) + async projectSwitch( + @UserSession() user: IJwtPayload, + @Param('applicationId') applicationId: string + ): Promise<{ token: string }> { + const command = SwitchApplicationCommand.create({ + userId: user._id, + newApplicationId: applicationId, + organizationId: user.organizationId, + }); + + return { + token: await this.switchApplicationUsecase.execute(command), + }; + } + + @Get('/test/token/:userId') + async authenticateTest( + @Param('userId') userId: string, + @Query('organizationId') organizationId: string, + @Query('applicationId') applicationId: string + ) { + if (process.env.NODE_ENV !== 'test') throw new NotFoundException(); + + const user = await this.userRepository.findById(userId); + if (!user) throw new BadRequestException('No user found'); + + const member = organizationId ? await this.memberRepository.findMemberByUserId(organizationId, user._id) : null; + + return await this.authService.getSignedToken(user, organizationId, member, applicationId); + } +} diff --git a/apps/api/src/app/auth/auth.module.ts b/apps/api/src/app/auth/auth.module.ts new file mode 100644 index 00000000000..04fc65903dd --- /dev/null +++ b/apps/api/src/app/auth/auth.module.ts @@ -0,0 +1,68 @@ +import { MiddlewareConsumer, Module, NestModule, RequestMethod } from '@nestjs/common'; +import { JwtModule } from '@nestjs/jwt'; +import { PassportModule } from '@nestjs/passport'; +import { authenticate } from 'passport'; +import { RolesGuard } from './framework/roles.guard'; +import { JwtStrategy } from './services/passport/jwt.strategy'; +import { AuthController } from './auth.controller'; +import { UserModule } from '../user/user.module'; +import { AuthService } from './services/auth.service'; +import { USE_CASES } from './usecases'; +import { SharedModule } from '../shared/shared.module'; +import { GithubStrategy } from './services/passport/github.strategy'; +import { OrganizationModule } from '../organization/organization.module'; +import { ApplicationsModule } from '../applications/applications.module'; +import { JwtSubscriberStrategy } from './services/passport/subscriber-jwt.strategy'; +import { JwtAuthGuard } from './framework/auth.guard'; + +const AUTH_STRATEGIES = []; + +if (process.env.GITHUB_OAUTH_CLIENT_ID) { + AUTH_STRATEGIES.push(GithubStrategy); +} + +@Module({ + imports: [ + OrganizationModule, + SharedModule, + UserModule, + PassportModule.register({ + defaultStrategy: 'jwt', + }), + JwtModule.register({ + secretOrKeyProvider: () => process.env.JWT_SECRET as string, + signOptions: { + expiresIn: 360000, + }, + }), + ApplicationsModule, + ], + controllers: [AuthController], + providers: [ + JwtAuthGuard, + ...USE_CASES, + ...AUTH_STRATEGIES, + JwtStrategy, + AuthService, + RolesGuard, + JwtSubscriberStrategy, + ], + exports: [RolesGuard, AuthService, ...USE_CASES, JwtAuthGuard], +}) +export class AuthModule implements NestModule { + public configure(consumer: MiddlewareConsumer) { + if (process.env.GITHUB_OAUTH_CLIENT_ID) { + consumer + .apply( + authenticate('github', { + session: false, + scope: [], + }) + ) + .forRoutes({ + path: '/auth/github', + method: RequestMethod.GET, + }); + } + } +} diff --git a/apps/api/src/app/auth/dtos/login.dto.ts b/apps/api/src/app/auth/dtos/login.dto.ts new file mode 100644 index 00000000000..f724aebbe67 --- /dev/null +++ b/apps/api/src/app/auth/dtos/login.dto.ts @@ -0,0 +1,10 @@ +import { IsDefined, IsEmail } from 'class-validator'; + +export class LoginBodyDto { + @IsDefined() + @IsEmail() + email: string; + + @IsDefined() + password: string; +} diff --git a/apps/api/src/app/auth/dtos/user-registration.dto.ts b/apps/api/src/app/auth/dtos/user-registration.dto.ts new file mode 100644 index 00000000000..1dace8014fc --- /dev/null +++ b/apps/api/src/app/auth/dtos/user-registration.dto.ts @@ -0,0 +1,20 @@ +import { IsDefined, IsEmail, IsNotEmpty, IsOptional, MinLength } from 'class-validator'; + +export class UserRegistrationBodyDto { + @IsDefined() + @IsEmail() + email: string; + + @IsDefined() + @MinLength(8) + password: string; + + @IsDefined() + firstName: string; + + @IsDefined() + lastName: string; + + @IsOptional() + organizationName: string; +} diff --git a/apps/api/src/app/auth/e2e/login.e2e.ts b/apps/api/src/app/auth/e2e/login.e2e.ts new file mode 100644 index 00000000000..9834d3c6d00 --- /dev/null +++ b/apps/api/src/app/auth/e2e/login.e2e.ts @@ -0,0 +1,49 @@ +import { UserSession } from '@notifire/testing'; +import * as jwt from 'jsonwebtoken'; +import { expect } from 'chai'; +import { IJwtPayload } from '@notifire/shared'; + +describe('User login - /auth/login (POST)', async () => { + let session: UserSession; + const userCredentials = { + email: 'Testy.test22@gmail.com', + password: '123456789', + }; + + before(async () => { + session = new UserSession(); + await session.initialize(); + + const { body } = await session.testAgent + .post('/v1/auth/register') + .send({ + email: userCredentials.email, + password: userCredentials.password, + firstName: 'Test', + lastName: 'User', + }) + .expect(201); + }); + + it('should login the user correctly', async () => { + const { body } = await session.testAgent.post('/v1/auth/login').send({ + email: userCredentials.email, + password: userCredentials.password, + }); + + const jwtContent = ((await jwt.decode(body.data.token)) as unknown) as IJwtPayload; + expect(jwtContent.firstName).to.equal('test'); + expect(jwtContent.lastName).to.equal('user'); + expect(jwtContent.email).to.equal('testytest22@gmail.com'); + }); + + it('should fail on bad password', async () => { + const { body } = await session.testAgent.post('/v1/auth/login').send({ + email: userCredentials.email, + password: '123123213123', + }); + + expect(body.statusCode).to.equal(400); + expect(body.message).to.contain('Wrong credentials provided'); + }); +}); diff --git a/apps/api/src/app/auth/e2e/password-reset.e2e.ts b/apps/api/src/app/auth/e2e/password-reset.e2e.ts new file mode 100644 index 00000000000..8803895dd73 --- /dev/null +++ b/apps/api/src/app/auth/e2e/password-reset.e2e.ts @@ -0,0 +1,76 @@ +import { UserRepository } from '@notifire/dal'; +import { UserSession } from '@notifire/testing'; +import { expect } from 'chai'; +import * as moment from 'moment'; + +describe('Password reset - /auth/reset (POST)', async () => { + let session: UserSession; + const userRepository = new UserRepository(); + + beforeEach(async () => { + session = new UserSession(); + await session.initialize(); + }); + + it('should request a password reset for existing user', async () => { + const { body } = await session.testAgent.post('/v1/auth/reset/request').send({ + email: session.user.email, + }); + + expect(body.data.success).to.equal(true); + const found = await userRepository.findById(session.user._id); + expect(found.resetToken).to.be.ok; + }); + + it('should change a password after reset', async () => { + const { body } = await session.testAgent.post('/v1/auth/reset/request').send({ + email: session.user.email, + }); + + expect(body.data.success).to.equal(true); + const foundUser = await userRepository.findById(session.user._id); + + const { body: resetChange } = await session.testAgent.post('/v1/auth/reset').send({ + password: 'ASd3ASD$Fdfdf', + token: foundUser.resetToken, + }); + expect(resetChange.data.token).to.be.ok; + + const { body: loginBody } = await session.testAgent.post('/v1/auth/login').send({ + email: session.user.email, + password: 'ASd3ASD$Fdfdf', + }); + + expect(loginBody.data.token).to.be.ok; + + const foundUserAfterChange = await userRepository.findById(session.user._id); + expect(foundUserAfterChange.resetToken).to.not.be.ok; + expect(foundUserAfterChange.resetTokenDate).to.not.be.ok; + }); + + it('should fail to change password for bad token', async () => { + const { body } = await session.testAgent.post('/v1/auth/reset/request').send({ + email: session.user.email, + }); + + expect(body.data.success).to.equal(true); + await userRepository.update( + { + _id: session.user._id, + }, + { + $set: { + resetTokenDate: moment().subtract(20, 'days').toDate(), + }, + } + ); + + const foundUser = await userRepository.findById(session.user._id); + + const { body: resetChange } = await session.testAgent.post('/v1/auth/reset').send({ + password: 'ASd3ASD$Fdfdf', + token: foundUser.resetToken, + }); + expect(resetChange.message).to.contain('Token has expired'); + }); +}); diff --git a/apps/api/src/app/auth/e2e/switch-organization.e2e.ts b/apps/api/src/app/auth/e2e/switch-organization.e2e.ts new file mode 100644 index 00000000000..7aa750b7b6e --- /dev/null +++ b/apps/api/src/app/auth/e2e/switch-organization.e2e.ts @@ -0,0 +1,72 @@ +import * as jwt from 'jsonwebtoken'; +import { expect } from 'chai'; +import { OrganizationEntity } from '@notifire/dal'; +import { UserSession } from '@notifire/testing'; +import { IJwtPayload, MemberRoleEnum } from '@notifire/shared'; + +describe('Switch Organization - /auth/organizations/:id/switch (POST)', async () => { + let session: UserSession; + + describe('no organization for user', () => { + before(async () => { + session = new UserSession(); + await session.initialize({ + noOrganization: true, + }); + }); + + it('should fail for not authorized organization', async () => { + const { body } = await session.testAgent + .post('/v1/auth/organizations/5c573a9941a86c60689cf63a/switch') + .expect(401); + }); + }); + + describe('user has single organizations', () => { + before(async () => { + session = new UserSession(); + await session.initialize({ + noOrganization: true, + }); + }); + + it('should switch the user current organization', async () => { + const content = jwt.decode(session.token.split(' ')[1]) as IJwtPayload; + expect(content._id).to.equal(session.user._id); + const organization = await session.addOrganization(); + + const { body } = await session.testAgent.post(`/v1/auth/organizations/${organization._id}/switch`).expect(200); + + const newJwt = jwt.decode(body.data) as IJwtPayload; + expect(newJwt._id).to.equal(session.user._id); + expect(newJwt.organizationId).to.equal(organization._id); + expect(newJwt.roles.length).to.equal(1); + expect(newJwt.roles[0]).to.equal(MemberRoleEnum.ADMIN); + }); + }); + + describe('user has multiple organizations', () => { + let secondOrganization: OrganizationEntity; + let firstOrganization: OrganizationEntity; + + before(async () => { + session = new UserSession(); + await session.initialize(); + firstOrganization = session.organization; + secondOrganization = await session.addOrganization(); + }); + + it('should switch to second organization', async () => { + const content = jwt.decode(session.token.split(' ')[1]) as IJwtPayload; + expect(content.organizationId).to.equal(firstOrganization._id); + + const { body } = await session.testAgent + .post(`/v1/auth/organizations/${secondOrganization._id}/switch`) + .expect(200); + + const newJwt = jwt.decode(body.data) as IJwtPayload; + expect(newJwt._id).to.equal(session.user._id); + expect(newJwt.organizationId).to.equal(secondOrganization._id); + }); + }); +}); diff --git a/apps/api/src/app/auth/e2e/user-registration.e2e.ts b/apps/api/src/app/auth/e2e/user-registration.e2e.ts new file mode 100644 index 00000000000..3710443fb9d --- /dev/null +++ b/apps/api/src/app/auth/e2e/user-registration.e2e.ts @@ -0,0 +1,86 @@ +import { ApplicationRepository, OrganizationRepository } from '@notifire/dal'; +import { UserSession } from '@notifire/testing'; +import * as jwt from 'jsonwebtoken'; +import { expect } from 'chai'; +import { IJwtPayload, MemberRoleEnum } from '@notifire/shared'; + +describe('User registration - /auth/register (POST)', async () => { + let session: UserSession; + const applicationRepository = new ApplicationRepository(); + const organizationRepository = new OrganizationRepository(); + + before(async () => { + session = new UserSession(); + await session.initialize(); + }); + + it('should throw validation error for not enough information', async () => { + const { body } = await session.testAgent.post('/v1/auth/register').send({ + email: '123', + }); + + expect(body.statusCode).to.equal(400); + expect(body.message.find((i) => i.includes('email'))).to.be.ok; + expect(body.message.find((i) => i.includes('password'))).to.be.ok; + expect(body.message.find((i) => i.includes('firstName'))).to.be.ok; + expect(body.message.find((i) => i.includes('lastName'))).to.be.ok; + }); + + it('should create a new user successfully', async () => { + const { body } = await session.testAgent.post('/v1/auth/register').send({ + email: 'Testy.test@gmail.com', + firstName: 'Test', + lastName: 'User', + password: '123456789', + }); + + expect(body.data.token).to.be.ok; + + const jwtContent = ((await jwt.decode(body.data.token)) as unknown) as IJwtPayload; + + expect(jwtContent.firstName).to.equal('test'); + expect(jwtContent.lastName).to.equal('user'); + expect(jwtContent.email).to.equal('testytest@gmail.com'); + }); + + it('should create a user with organization', async () => { + const { body } = await session.testAgent.post('/v1/auth/register').send({ + email: 'Testy.test-org@gmail.com', + firstName: 'Test', + lastName: 'User', + password: '123456789', + organizationName: 'Sample org', + }); + + expect(body.data.token).to.be.ok; + + const jwtContent = ((await jwt.decode(body.data.token)) as unknown) as IJwtPayload; + + expect(jwtContent.firstName).to.equal('test'); + expect(jwtContent.lastName).to.equal('user'); + + // Should generate organization + expect(jwtContent.organizationId).to.be.ok; + const organization = await organizationRepository.findById(jwtContent.organizationId); + expect(organization.name).to.equal('Sample org'); + + // Should generate application and api keys + expect(jwtContent.applicationId).to.be.ok; + const application = await applicationRepository.findById(jwtContent.applicationId); + expect(application.apiKeys.length).to.equal(1); + expect(application.apiKeys[0].key).to.ok; + + expect(jwtContent.roles[0]).to.equal(MemberRoleEnum.ADMIN); + }); + + it('should throw error when registering same user twice', async () => { + const { body } = await session.testAgent.post('/v1/auth/register').send({ + email: 'Testy.test@gmail.com', + firstName: 'Test', + lastName: 'User', + password: '123456789', + }); + + expect(body.message).to.contain('User already exists'); + }); +}); diff --git a/apps/api/src/app/auth/framework/auth.guard.ts b/apps/api/src/app/auth/framework/auth.guard.ts new file mode 100644 index 00000000000..a6a9f1b8eee --- /dev/null +++ b/apps/api/src/app/auth/framework/auth.guard.ts @@ -0,0 +1,34 @@ +import { ExecutionContext, forwardRef, Inject, Injectable, UnauthorizedException } from '@nestjs/common'; +import { AuthGuard } from '@nestjs/passport'; +import { Reflector } from '@nestjs/core'; +import { AuthService } from '../services/auth.service'; + +@Injectable() +export class JwtAuthGuard extends AuthGuard('jwt') { + constructor( + @Inject(forwardRef(() => AuthService)) private authService: AuthService, + private readonly reflector: Reflector + ) { + super(); + } + + canActivate(context: ExecutionContext) { + const request = context.switchToHttp().getRequest(); + const authorizationHeader = request.headers.authorization; + + if (authorizationHeader && authorizationHeader.includes('ApiKey')) { + const apiEnabled = this.reflector.get('external_api_accessible', context.getHandler()); + if (!apiEnabled) throw new UnauthorizedException('API endpoint not available'); + + const key = authorizationHeader.split(' ')[1]; + + return this.authService.apiKeyAuthenticate(key).then((result) => { + request.headers.authorization = `Bearer ${result}`; + + return super.canActivate(context); + }); + } + + return super.canActivate(context); + } +} diff --git a/apps/api/src/app/auth/framework/external-api.decorator.ts b/apps/api/src/app/auth/framework/external-api.decorator.ts new file mode 100644 index 00000000000..0b0b95f7fb5 --- /dev/null +++ b/apps/api/src/app/auth/framework/external-api.decorator.ts @@ -0,0 +1,3 @@ +import { SetMetadata } from '@nestjs/common'; + +export const ExternalApiAccessible = () => SetMetadata('external_api_accessible', true); diff --git a/apps/api/src/app/auth/framework/roles.decorator.ts b/apps/api/src/app/auth/framework/roles.decorator.ts new file mode 100644 index 00000000000..b0376727cc3 --- /dev/null +++ b/apps/api/src/app/auth/framework/roles.decorator.ts @@ -0,0 +1,3 @@ +import { SetMetadata } from '@nestjs/common'; + +export const Roles = (...roles: string[]) => SetMetadata('roles', roles); diff --git a/apps/api/src/app/auth/framework/roles.guard.ts b/apps/api/src/app/auth/framework/roles.guard.ts new file mode 100644 index 00000000000..e4e69e20cfd --- /dev/null +++ b/apps/api/src/app/auth/framework/roles.guard.ts @@ -0,0 +1,27 @@ +import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; +import { Reflector } from '@nestjs/core'; +import { IJwtPayload } from '@notifire/shared'; +import * as jwt from 'jsonwebtoken'; + +@Injectable() +export class RolesGuard implements CanActivate { + constructor(private readonly reflector: Reflector) {} + + canActivate(context: ExecutionContext): boolean { + const roles = this.reflector.get('roles', context.getHandler()); + if (!roles) { + return true; + } + + const request = context.switchToHttp().getRequest(); + if (!request.headers.authorization) return false; + + const token = request.headers.authorization.split(' ')[1]; + if (!token) return false; + + const user = jwt.decode(token) as IJwtPayload; + if (!user) return false; + + return true; + } +} diff --git a/apps/api/src/app/auth/framework/subscriber-route.decorator.ts b/apps/api/src/app/auth/framework/subscriber-route.decorator.ts new file mode 100644 index 00000000000..2e609dd877b --- /dev/null +++ b/apps/api/src/app/auth/framework/subscriber-route.decorator.ts @@ -0,0 +1,3 @@ +import { SetMetadata } from '@nestjs/common'; + +export const SubscriberRoute = () => SetMetadata('subscriberRouteGuard', true); diff --git a/apps/api/src/app/auth/framework/subscriber-route.guard.ts b/apps/api/src/app/auth/framework/subscriber-route.guard.ts new file mode 100644 index 00000000000..fd254ea31ca --- /dev/null +++ b/apps/api/src/app/auth/framework/subscriber-route.guard.ts @@ -0,0 +1,29 @@ +import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; +import { Reflector } from '@nestjs/core'; +import { ISubscriberJwt } from '@notifire/shared'; +import * as jwt from 'jsonwebtoken'; + +@Injectable() +export class SubscriberRouteGuard implements CanActivate { + constructor(private readonly reflector: Reflector) {} + + canActivate(context: ExecutionContext): boolean { + const subscriberRouteGuard = this.reflector.get('subscriberRouteGuard', context.getHandler()); + if (!subscriberRouteGuard) { + return true; + } + + const request = context.switchToHttp().getRequest(); + if (!request.headers.authorization) return false; + + const token = request.headers.authorization.split(' ')[1]; + if (!token) return false; + + const tokenContent = jwt.decode(token) as ISubscriberJwt; + if (!tokenContent) return false; + if (tokenContent.aud !== 'widget_user') return false; + if (!tokenContent.applicationId) return false; + + return true; + } +} diff --git a/apps/api/src/app/auth/services/auth.interface.ts b/apps/api/src/app/auth/services/auth.interface.ts new file mode 100644 index 00000000000..e69de29bb2d diff --git a/apps/api/src/app/auth/services/auth.service.ts b/apps/api/src/app/auth/services/auth.service.ts new file mode 100644 index 00000000000..f6d59ba0212 --- /dev/null +++ b/apps/api/src/app/auth/services/auth.service.ts @@ -0,0 +1,235 @@ +import { forwardRef, Inject, Injectable, UnauthorizedException } from '@nestjs/common'; +import { JwtService } from '@nestjs/jwt'; +import { + UserEntity, + UserRepository, + MemberEntity, + OrganizationRepository, + ApplicationRepository, + SubscriberEntity, + SubscriberRepository, + MemberRepository, +} from '@notifire/dal'; +import { AuthProviderEnum, IJwtPayload, ISubscriberJwt, MemberRoleEnum } from '@notifire/shared'; + +import { CreateUserCommand } from '../../user/usecases/create-user/create-user.dto'; +import { CreateUser } from '../../user/usecases/create-user/create-user.usecase'; +import { SwitchApplicationCommand } from '../usecases/switch-application/switch-application.command'; +import { SwitchApplication } from '../usecases/switch-application/switch-application.usecase'; +import { SwitchOrganization } from '../usecases/switch-organization/switch-organization.usecase'; +import { SwitchOrganizationCommand } from '../usecases/switch-organization/switch-organization.command'; +import { QueueService } from '../../shared/services/queue'; +import { AnalyticsService } from '../../shared/services/analytics/analytics.service'; + +@Injectable() +export class AuthService { + constructor( + private userRepository: UserRepository, + private subscriberRepository: SubscriberRepository, + private createUserUsecase: CreateUser, + private jwtService: JwtService, + private queueService: QueueService, + private analyticsService: AnalyticsService, + private organizationRepository: OrganizationRepository, + private applicationRepository: ApplicationRepository, + private memberRepository: MemberRepository, + @Inject(forwardRef(() => SwitchOrganization)) private switchOrganizationUsecase: SwitchOrganization, + @Inject(forwardRef(() => SwitchApplication)) private switchApplicationUsecase: SwitchApplication + ) {} + + async authenticate( + authProvider: AuthProviderEnum, + accessToken: string, + refreshToken: string, + profile: { name: string; login: string; email: string; avatar_url: string; id: string }, + distinctId: string + ) { + let user = await this.userRepository.findByLoginProvider(profile.id, authProvider); + let newUser = false; + + if (!user) { + user = await this.createUserUsecase.execute( + CreateUserCommand.create({ + picture: profile.avatar_url, + email: profile.email, + lastName: profile.name ? profile.name.split(' ').slice(-1).join(' ') : null, + firstName: profile.name ? profile.name.split(' ').slice(0, -1).join(' ') : profile.login, + auth: { + profileId: profile.id, + provider: authProvider, + accessToken, + refreshToken, + }, + }) + ); + newUser = true; + + this.analyticsService.upsertUser(user, distinctId || user._id); + + if (distinctId) { + this.analyticsService.alias(distinctId, user._id); + } + } else { + this.analyticsService.track('[Authentication] - Login', user._id, { + loginType: authProvider, + }); + } + + return { + newUser, + token: await this.generateUserToken(user), + }; + } + + async refreshToken(userId: string) { + const user = await this.userRepository.findById(userId); + + return this.getSignedToken(user); + } + + async isAuthenticatedForOrganization(userId: string, organizationId: string): Promise { + return !!(await this.memberRepository.isMemberOfOrganization(organizationId, userId)); + } + + async apiKeyAuthenticate(apiKey: string) { + const application = await this.applicationRepository.findByApiKey(apiKey); + if (!application) throw new UnauthorizedException('API Key not found'); + + const key = application.apiKeys.find((i) => i.key === apiKey); + const user = await this.userRepository.findById(key._userId); + + return await this.getApiSignedToken(user, application._organizationId, application._id, key.key); + } + + async getSubscriberWidgetToken(subscriber: SubscriberEntity) { + return this.jwtService.sign( + { + _id: subscriber._id, + firstName: subscriber.firstName, + lastName: subscriber.lastName, + email: subscriber.email, + organizationId: subscriber._organizationId, + applicationId: subscriber._applicationId, + subscriberId: subscriber.subscriberId, + }, + { + expiresIn: '15 day', + issuer: 'notifire_api', + audience: 'widget_user', + } + ); + } + + async getApiSignedToken( + user: UserEntity, + organizationId: string, + applicationId: string, + apiKey: string + ): Promise { + return this.jwtService.sign( + { + _id: user._id, + firstName: null, + lastName: null, + email: null, + profilePicture: null, + organizationId, + roles: [MemberRoleEnum.ADMIN], + apiKey, + applicationId, + }, + { + expiresIn: '1 day', + issuer: 'notifire_api', + audience: 'api_token', + } + ); + } + + async generateUserToken(user: UserEntity) { + const userActiveOrganizations = await this.organizationRepository.findUserActiveOrganizations(user._id); + + if (userActiveOrganizations && userActiveOrganizations.length) { + const organizationToSwitch = userActiveOrganizations[0]; + + const userActiveProjects = await this.applicationRepository.findOrganizationApplications( + organizationToSwitch._id + ); + const applicationToSwitch = userActiveProjects[0]; + + if (applicationToSwitch) { + return await this.switchApplicationUsecase.execute( + SwitchApplicationCommand.create({ + newApplicationId: applicationToSwitch._id, + organizationId: organizationToSwitch._id, + userId: user._id, + }) + ); + } + + return await this.switchOrganizationUsecase.execute( + SwitchOrganizationCommand.create({ + newOrganizationId: organizationToSwitch._id, + userId: user._id, + }) + ); + } + + return this.getSignedToken(user); + } + + async getSignedToken( + user: UserEntity, + organizationId?: string, + member?: MemberEntity, + applicationId?: string + ): Promise { + const roles = []; + if (member && member.roles) { + roles.push(...member.roles); + } + + return this.jwtService.sign( + { + _id: user._id, + firstName: user.firstName, + lastName: user.lastName, + email: user.email, + profilePicture: user.profilePicture, + organizationId: organizationId || null, + roles, + applicationId: applicationId || null, + }, + { + expiresIn: '30 days', + issuer: 'notifire_api', + } + ); + } + + async validateUser(payload: IJwtPayload): Promise { + const user = await this.userRepository.findById(payload._id); + if (payload.organizationId) { + const isMember = await this.isAuthenticatedForOrganization(payload._id, payload.organizationId); + if (!isMember) throw new UnauthorizedException(`No authorized for organization ${payload.organizationId}`); + } + + return user; + } + + async validateSubscriber(payload: ISubscriberJwt): Promise { + const subscriber = await this.subscriberRepository.findOne({ + _applicationId: payload.applicationId, + _id: payload._id, + }); + return subscriber; + } + + async decodeJwt(token: string) { + return this.jwtService.decode(token) as T; + } + + async verifyJwt(jwt: string) { + return this.jwtService.verify(jwt); + } +} diff --git a/apps/api/src/app/auth/services/passport/github.strategy.ts b/apps/api/src/app/auth/services/passport/github.strategy.ts new file mode 100644 index 00000000000..9ca5b057112 --- /dev/null +++ b/apps/api/src/app/auth/services/passport/github.strategy.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@nestjs/common'; +import { PassportStrategy } from '@nestjs/passport'; +import * as githubPassport from 'passport-github'; +import { Metadata, StateStoreStoreCallback, StateStoreVerifyCallback } from 'passport-oauth2'; +import { AuthProviderEnum } from '@notifire/shared'; +import { AuthService } from '../auth.service'; + +@Injectable() +export class GithubStrategy extends PassportStrategy(githubPassport.Strategy, 'github') { + constructor(private authService: AuthService) { + super({ + clientID: process.env.GITHUB_OAUTH_CLIENT_ID, + clientSecret: process.env.GITHUB_OAUTH_CLIENT_SECRET, + callbackURL: process.env.GITHUB_OAUTH_REDIRECT, + passReqToCallback: true, + store: { + verify(req, state: string, meta: Metadata, callback: StateStoreVerifyCallback) { + callback(null, true, req.query.distinctId); + }, + store(req, meta: Metadata, callback: StateStoreStoreCallback) { + callback(null, req.query.distinctId); + }, + }, + }); + } + + async validate(req, accessToken: string, refreshToken: string, profile, done: (err, data) => void) { + try { + const response = await this.authService.authenticate( + AuthProviderEnum.GITHUB, + accessToken, + refreshToken, + profile._json, + req.query.state + ); + + done(null, { + token: response.token, + newUser: response.newUser, + }); + } catch (err) { + done(err, false); + } + } +} diff --git a/apps/api/src/app/auth/services/passport/jwt.strategy.ts b/apps/api/src/app/auth/services/passport/jwt.strategy.ts new file mode 100644 index 00000000000..60dab7f978a --- /dev/null +++ b/apps/api/src/app/auth/services/passport/jwt.strategy.ts @@ -0,0 +1,24 @@ +import { ExtractJwt, Strategy } from 'passport-jwt'; +import { PassportStrategy } from '@nestjs/passport'; +import { Injectable, UnauthorizedException } from '@nestjs/common'; +import { IJwtPayload } from '@notifire/shared'; +import { AuthService } from '../auth.service'; + +@Injectable() +export class JwtStrategy extends PassportStrategy(Strategy) { + constructor(private readonly authService: AuthService) { + super({ + jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), + secretOrKey: process.env.JWT_SECRET, + }); + } + + async validate(payload: IJwtPayload) { + const user = await this.authService.validateUser(payload); + if (!user) { + throw new UnauthorizedException(); + } + + return payload; + } +} diff --git a/apps/api/src/app/auth/services/passport/subscriber-jwt.strategy.ts b/apps/api/src/app/auth/services/passport/subscriber-jwt.strategy.ts new file mode 100644 index 00000000000..bade8e71fc1 --- /dev/null +++ b/apps/api/src/app/auth/services/passport/subscriber-jwt.strategy.ts @@ -0,0 +1,29 @@ +import { ExtractJwt, Strategy } from 'passport-jwt'; +import { PassportStrategy } from '@nestjs/passport'; +import { Injectable, UnauthorizedException } from '@nestjs/common'; +import { IJwtPayload, ISubscriberJwt } from '@notifire/shared'; +import { AuthService } from '../auth.service'; + +@Injectable() +export class JwtSubscriberStrategy extends PassportStrategy(Strategy, 'subscriberJwt') { + constructor(private readonly authService: AuthService) { + super({ + jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), + secretOrKey: process.env.JWT_SECRET, + }); + } + + async validate(payload: ISubscriberJwt) { + const subscriber = await this.authService.validateSubscriber(payload); + + if (!subscriber) { + throw new UnauthorizedException(); + } + + if (payload.aud !== 'widget_user') { + throw new UnauthorizedException(); + } + + return subscriber; + } +} diff --git a/apps/api/src/app/auth/usecases/index.ts b/apps/api/src/app/auth/usecases/index.ts new file mode 100644 index 00000000000..ff92ff637ef --- /dev/null +++ b/apps/api/src/app/auth/usecases/index.ts @@ -0,0 +1,16 @@ +import { PasswordResetRequest } from './password-reset-request/password-reset-request.usecase'; +import { UserRegister } from './register/user-register.usecase'; +import { Login } from './login/login.usecase'; +import { SwitchApplication } from './switch-application/switch-application.usecase'; +import { SwitchOrganization } from './switch-organization/switch-organization.usecase'; +import { PasswordReset } from './password-reset/password-reset.usecase'; + +export const USE_CASES = [ + // + UserRegister, + Login, + SwitchApplication, + SwitchOrganization, + PasswordResetRequest, + PasswordReset, +]; diff --git a/apps/api/src/app/auth/usecases/login/login.command.ts b/apps/api/src/app/auth/usecases/login/login.command.ts new file mode 100644 index 00000000000..96c7f386daf --- /dev/null +++ b/apps/api/src/app/auth/usecases/login/login.command.ts @@ -0,0 +1,16 @@ +import { IsDefined, IsEmail, IsNotEmpty } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; + +export class LoginCommand { + static create(data: LoginCommand) { + return CommandHelper.create(LoginCommand, data); + } + + @IsDefined() + @IsNotEmpty() + @IsEmail() + email: string; + + @IsDefined() + password: string; +} diff --git a/apps/api/src/app/auth/usecases/login/login.usecase.ts b/apps/api/src/app/auth/usecases/login/login.usecase.ts new file mode 100644 index 00000000000..25c98927f0d --- /dev/null +++ b/apps/api/src/app/auth/usecases/login/login.usecase.ts @@ -0,0 +1,27 @@ +import * as bcrypt from 'bcrypt'; +import { Injectable } from '@nestjs/common'; +import { UserRepository } from '@notifire/dal'; +import { LoginCommand } from './login.command'; +import { ApiException } from '../../../shared/exceptions/api.exception'; + +import { normalizeEmail } from '../../../shared/helpers/email-normalization.service'; +import { AuthService } from '../../services/auth.service'; + +@Injectable() +export class Login { + constructor(private userRepository: UserRepository, private authService: AuthService) {} + + async execute(command: LoginCommand) { + const email = normalizeEmail(command.email); + const user = await this.userRepository.findByEmail(email); + if (!user) throw new ApiException('User not found'); + if (!user.password) throw new ApiException('OAuth user login attempt'); + + const isMatching = await bcrypt.compare(command.password, user.password); + if (!isMatching) throw new ApiException('Wrong credentials provided'); + + return { + token: await this.authService.generateUserToken(user), + }; + } +} diff --git a/apps/api/src/app/auth/usecases/password-reset-request/password-reset-request.command.ts b/apps/api/src/app/auth/usecases/password-reset-request/password-reset-request.command.ts new file mode 100644 index 00000000000..5c8d020284e --- /dev/null +++ b/apps/api/src/app/auth/usecases/password-reset-request/password-reset-request.command.ts @@ -0,0 +1,13 @@ +import { IsDefined, IsEmail } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; + +export class PasswordResetRequestCommand { + static create(data: PasswordResetRequestCommand) { + return CommandHelper.create(PasswordResetRequestCommand, data); + } + + @IsEmail() + @IsDefined() + email: string; +} diff --git a/apps/api/src/app/auth/usecases/password-reset-request/password-reset-request.usecase.ts b/apps/api/src/app/auth/usecases/password-reset-request/password-reset-request.usecase.ts new file mode 100644 index 00000000000..38b69f19f5a --- /dev/null +++ b/apps/api/src/app/auth/usecases/password-reset-request/password-reset-request.usecase.ts @@ -0,0 +1,31 @@ +import { Injectable } from '@nestjs/common'; +import { Notifire } from '@notifire/node'; +import { UserRepository } from '@notifire/dal'; +import { v4 as uuidv4 } from 'uuid'; +import { PasswordResetRequestCommand } from './password-reset-request.command'; + +@Injectable() +export class PasswordResetRequest { + constructor(private userRepository: UserRepository) {} + + async execute(command: PasswordResetRequestCommand): Promise<{ success: boolean }> { + const foundUser = await this.userRepository.findByEmail(command.email); + if (foundUser) { + const token = uuidv4(); + await this.userRepository.updatePasswordResetToken(foundUser._id, token); + + if (process.env.NODE_ENV === 'dev' || process.env.NODE_ENV === 'prod') { + const notifire = new Notifire(process.env.NOTIFIRE_API_KEY); + await notifire.trigger('password-reset-request-8bTC73NsY', { + $user_id: foundUser._id, + resetPasswordLink: `${process.env.FRONT_BASE_URL}/auth/reset/${token}`, + $email: foundUser.email, + }); + } + } + + return { + success: true, + }; + } +} diff --git a/apps/api/src/app/auth/usecases/password-reset/password-reset.command.ts b/apps/api/src/app/auth/usecases/password-reset/password-reset.command.ts new file mode 100644 index 00000000000..dae9bff77a9 --- /dev/null +++ b/apps/api/src/app/auth/usecases/password-reset/password-reset.command.ts @@ -0,0 +1,20 @@ +import { IsDefined, IsString, IsUUID, MinLength } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; + +export class PasswordResetCommand { + static create(data: PasswordResetCommand) { + return CommandHelper.create(PasswordResetCommand, data); + } + + @IsString() + @IsDefined() + @MinLength(8) + password: string; + + @IsUUID(4, { + message: 'Bad token provided', + }) + @IsDefined() + token: string; +} diff --git a/apps/api/src/app/auth/usecases/password-reset/password-reset.usecase.ts b/apps/api/src/app/auth/usecases/password-reset/password-reset.usecase.ts new file mode 100644 index 00000000000..d19a9d7b384 --- /dev/null +++ b/apps/api/src/app/auth/usecases/password-reset/password-reset.usecase.ts @@ -0,0 +1,43 @@ +import { Injectable } from '@nestjs/common'; +import { UserRepository } from '@notifire/dal'; +import * as bcrypt from 'bcrypt'; +import * as moment from 'moment'; +import { PasswordResetCommand } from './password-reset.command'; +import { ApiException } from '../../../shared/exceptions/api.exception'; +import { AuthService } from '../../services/auth.service'; + +@Injectable() +export class PasswordReset { + constructor(private userRepository: UserRepository, private authService: AuthService) {} + + async execute(command: PasswordResetCommand): Promise<{ token: string }> { + const user = await this.userRepository.findUserByToken(command.token); + if (!user) { + throw new ApiException('Bad token provided'); + } + + if (moment(user.resetTokenDate).isBefore(moment().subtract(7, 'days'))) { + throw new ApiException('Token has expired'); + } + + const passwordHash = await bcrypt.hash(command.password, 10); + await this.userRepository.update( + { + _id: user._id, + }, + { + $set: { + password: passwordHash, + }, + $unset: { + resetToken: 1, + resetTokenDate: 1, + }, + } + ); + + return { + token: await this.authService.generateUserToken(user), + }; + } +} diff --git a/apps/api/src/app/auth/usecases/register/user-register.command.ts b/apps/api/src/app/auth/usecases/register/user-register.command.ts new file mode 100644 index 00000000000..7e6897a0e13 --- /dev/null +++ b/apps/api/src/app/auth/usecases/register/user-register.command.ts @@ -0,0 +1,26 @@ +import { IsDefined, IsEmail, IsNotEmpty, IsOptional, MinLength } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; + +export class UserRegisterCommand { + static create(data: UserRegisterCommand) { + return CommandHelper.create(UserRegisterCommand, data); + } + + @IsDefined() + @IsNotEmpty() + @IsEmail() + email: string; + + @IsDefined() + @MinLength(8) + password: string; + + @IsDefined() + firstName: string; + + @IsDefined() + lastName: string; + + @IsOptional() + organizationName?: string; +} diff --git a/apps/api/src/app/auth/usecases/register/user-register.usecase.ts b/apps/api/src/app/auth/usecases/register/user-register.usecase.ts new file mode 100644 index 00000000000..f640cc75b6f --- /dev/null +++ b/apps/api/src/app/auth/usecases/register/user-register.usecase.ts @@ -0,0 +1,74 @@ +import { Injectable } from '@nestjs/common'; +import { MemberEntity, MemberRepository, OrganizationEntity, UserRepository } from '@notifire/dal'; +import * as bcrypt from 'bcrypt'; +import { AuthService } from '../../services/auth.service'; +import { UserRegisterCommand } from './user-register.command'; +import { normalizeEmail } from '../../../shared/helpers/email-normalization.service'; +import { ApiException } from '../../../shared/exceptions/api.exception'; +import { CreateOrganization } from '../../../organization/usecases/create-organization/create-organization.usecase'; +import { CreateOrganizationCommand } from '../../../organization/usecases/create-organization/create-organization.command'; +import { CreateApplication } from '../../../applications/usecases/create-application/create-application.usecase'; +import { CreateApplicationCommand } from '../../../applications/usecases/create-application/create-application.command'; +import { AnalyticsService } from '../../../shared/services/analytics/analytics.service'; +// eslint-disable-next-line max-len + +@Injectable() +export class UserRegister { + constructor( + private authService: AuthService, + private userRepository: UserRepository, + private createOrganizationUsecase: CreateOrganization, + private createApplicationUsecase: CreateApplication, + private memberRepository: MemberRepository, + private analyticsService: AnalyticsService + ) {} + + async execute(command: UserRegisterCommand) { + const email = normalizeEmail(command.email); + const existingUser = await this.userRepository.findByEmail(email); + if (existingUser) throw new ApiException('User already exists'); + + const passwordHash = await bcrypt.hash(command.password, 10); + const user = await this.userRepository.create({ + email, + firstName: command.firstName.toLowerCase(), + lastName: command.lastName.toLowerCase(), + password: passwordHash, + }); + + let organization: OrganizationEntity; + let member: MemberEntity; + if (command.organizationName) { + organization = await this.createOrganizationUsecase.execute( + CreateOrganizationCommand.create({ + name: command.organizationName, + userId: user._id, + }) + ); + + this.analyticsService.upsertUser( + { + firstName: command.organizationName, + lastName: '', + email: user.email, + _id: user._id, + createdAt: user.createdAt, + } as never, + organization._id + ); + + await this.createApplicationUsecase.execute( + CreateApplicationCommand.create({ + userId: user._id, + name: `${organization.name} App`, + organizationId: organization._id, + }) + ); + } + + return { + user: await this.userRepository.findById(user._id), + token: await this.authService.generateUserToken(user), + }; + } +} diff --git a/apps/api/src/app/auth/usecases/switch-application/switch-application.command.ts b/apps/api/src/app/auth/usecases/switch-application/switch-application.command.ts new file mode 100644 index 00000000000..e5280483d0f --- /dev/null +++ b/apps/api/src/app/auth/usecases/switch-application/switch-application.command.ts @@ -0,0 +1,12 @@ +import { IsNotEmpty } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { OrganizationCommand } from '../../../shared/commands/organization.command'; + +export class SwitchApplicationCommand extends OrganizationCommand { + static create(data: SwitchApplicationCommand) { + return CommandHelper.create(SwitchApplicationCommand, data); + } + + @IsNotEmpty() + newApplicationId: string; +} diff --git a/apps/api/src/app/auth/usecases/switch-application/switch-application.e2e.ts b/apps/api/src/app/auth/usecases/switch-application/switch-application.e2e.ts new file mode 100644 index 00000000000..6e4131afcdd --- /dev/null +++ b/apps/api/src/app/auth/usecases/switch-application/switch-application.e2e.ts @@ -0,0 +1,35 @@ +import * as jwt from 'jsonwebtoken'; +import { expect } from 'chai'; +import { ApplicationEntity } from '@notifire/dal'; +import { UserSession } from '@notifire/testing'; +import { IJwtPayload } from '@notifire/shared'; + +describe('Switch Application - /auth/applications/:id/switch (POST)', async () => { + let session: UserSession; + + describe('user has multiple applications', () => { + let secondApplication: ApplicationEntity; + let firstApplication: ApplicationEntity; + + before(async () => { + session = new UserSession(); + await session.initialize(); + firstApplication = session.application; + secondApplication = await session.createApplication(); + }); + + it('should switch to second application', async () => { + const content = jwt.decode(session.token.split(' ')[1]) as IJwtPayload; + expect(content.applicationId).to.equal(firstApplication._id); + + const { body } = await session.testAgent + .post(`/v1/auth/applications/${secondApplication._id}/switch`) + .expect(200); + + const newJwt = jwt.decode(body.data.token) as IJwtPayload; + expect(newJwt._id).to.equal(session.user._id); + expect(newJwt.organizationId).to.equal(session.organization._id); + expect(newJwt.applicationId).to.equal(secondApplication._id); + }); + }); +}); diff --git a/apps/api/src/app/auth/usecases/switch-application/switch-application.usecase.ts b/apps/api/src/app/auth/usecases/switch-application/switch-application.usecase.ts new file mode 100644 index 00000000000..fed02c1d2bc --- /dev/null +++ b/apps/api/src/app/auth/usecases/switch-application/switch-application.usecase.ts @@ -0,0 +1,28 @@ +import { forwardRef, Inject, Injectable, NotFoundException, UnauthorizedException } from '@nestjs/common'; +import { ApplicationRepository, MemberRepository, OrganizationRepository, UserRepository } from '@notifire/dal'; +import { AuthService } from '../../services/auth.service'; +import { SwitchApplicationCommand } from './switch-application.command'; + +@Injectable() +export class SwitchApplication { + constructor( + private applicationRepository: ApplicationRepository, + private userRepository: UserRepository, + private memberRepository: MemberRepository, + @Inject(forwardRef(() => AuthService)) private authService: AuthService + ) {} + + async execute(command: SwitchApplicationCommand) { + const project = await this.applicationRepository.findById(command.newApplicationId); + if (!project) throw new NotFoundException('Application not found'); + if (project._organizationId !== command.organizationId) { + throw new UnauthorizedException('Not authorized for organization'); + } + + const member = await this.memberRepository.findMemberByUserId(command.organizationId, command.userId); + const user = await this.userRepository.findById(command.userId); + const token = await this.authService.getSignedToken(user, command.organizationId, member, command.newApplicationId); + + return token; + } +} diff --git a/apps/api/src/app/auth/usecases/switch-organization/switch-organization.command.ts b/apps/api/src/app/auth/usecases/switch-organization/switch-organization.command.ts new file mode 100644 index 00000000000..485430cf0e5 --- /dev/null +++ b/apps/api/src/app/auth/usecases/switch-organization/switch-organization.command.ts @@ -0,0 +1,12 @@ +import { IsNotEmpty } from 'class-validator'; +import { AuthenticatedCommand } from '../../../shared/commands/authenticated.command'; +import { CommandHelper } from '../../../shared/commands/command.helper'; + +export class SwitchOrganizationCommand extends AuthenticatedCommand { + static create(data: SwitchOrganizationCommand) { + return CommandHelper.create(SwitchOrganizationCommand, data); + } + + @IsNotEmpty() + newOrganizationId: string; +} diff --git a/apps/api/src/app/auth/usecases/switch-organization/switch-organization.usecase.ts b/apps/api/src/app/auth/usecases/switch-organization/switch-organization.usecase.ts new file mode 100644 index 00000000000..6d2fc35d123 --- /dev/null +++ b/apps/api/src/app/auth/usecases/switch-organization/switch-organization.usecase.ts @@ -0,0 +1,30 @@ +import { forwardRef, Inject, Injectable, UnauthorizedException } from '@nestjs/common'; +import { MemberRepository, OrganizationRepository, UserRepository } from '@notifire/dal'; +import { SwitchOrganizationCommand } from './switch-organization.command'; +import { AuthService } from '../../services/auth.service'; + +@Injectable() +export class SwitchOrganization { + constructor( + private organizationRepository: OrganizationRepository, + private userRepository: UserRepository, + private memberRepository: MemberRepository, + @Inject(forwardRef(() => AuthService)) private authService: AuthService + ) {} + + async execute(command: SwitchOrganizationCommand): Promise { + const isAuthenticated = await this.authService.isAuthenticatedForOrganization( + command.userId, + command.newOrganizationId + ); + if (!isAuthenticated) { + throw new UnauthorizedException(`Not authorized for organization ${command.newOrganizationId}`); + } + + const member = await this.memberRepository.findMemberByUserId(command.newOrganizationId, command.userId); + const user = await this.userRepository.findById(command.userId); + const token = await this.authService.getSignedToken(user, command.newOrganizationId, member); + + return token; + } +} diff --git a/apps/api/src/app/channels/channels.controller.ts b/apps/api/src/app/channels/channels.controller.ts new file mode 100644 index 00000000000..26af5f2117c --- /dev/null +++ b/apps/api/src/app/channels/channels.controller.ts @@ -0,0 +1,49 @@ +import { Body, ClassSerializerInterceptor, Controller, Put, UseGuards, UseInterceptors } from '@nestjs/common'; +import { IJwtPayload, MemberRoleEnum } from '@notifire/shared'; +import { UserSession } from '../shared/framework/user.decorator'; +import { JwtAuthGuard } from '../auth/framework/auth.guard'; +import { Roles } from '../auth/framework/roles.decorator'; +import { UpdateMailSettings } from './usecases/update-mail-settings/update-mail-settings.usecase'; +import { UpdateMailSettingsCommand } from './usecases/update-mail-settings/update-mail-settings.command'; +import { UpdateSmsSettings } from './usecases/update-sms-settings/update-sms-settings.usecase'; +import { UpdateSmsSettingsCommand } from './usecases/update-sms-settings/update-sms-settings.command'; + +@Controller('/channels') +@UseInterceptors(ClassSerializerInterceptor) +@UseGuards(JwtAuthGuard) +export class ChannelsController { + constructor( + private updateMailSettingsUsecase: UpdateMailSettings, + private updateSmsSettingsUsecase: UpdateSmsSettings + ) {} + + @Put('/email/settings') + @Roles(MemberRoleEnum.ADMIN) + updateMailSettings(@UserSession() user: IJwtPayload, @Body() body: { senderEmail: string; senderName: string }) { + return this.updateMailSettingsUsecase.execute( + UpdateMailSettingsCommand.create({ + userId: user._id, + applicationId: user.applicationId, + organizationId: user.organizationId, + senderEmail: body.senderEmail, + senderName: body.senderName, + }) + ); + } + + @Put('/sms/settings') + @Roles(MemberRoleEnum.ADMIN) + updateSmsSettings( + @UserSession() user: IJwtPayload, + @Body() body: { twillio: { authToken: string; accountSid: string; phoneNumber: string } } + ) { + return this.updateSmsSettingsUsecase.execute( + UpdateSmsSettingsCommand.create({ + userId: user._id, + applicationId: user.applicationId, + organizationId: user.organizationId, + twillio: body.twillio, + }) + ); + } +} diff --git a/apps/api/src/app/channels/channels.module.ts b/apps/api/src/app/channels/channels.module.ts new file mode 100644 index 00000000000..5f8c1e9c539 --- /dev/null +++ b/apps/api/src/app/channels/channels.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { USE_CASES } from './usecases'; +import { ChannelsController } from './channels.controller'; +import { SharedModule } from '../shared/shared.module'; + +@Module({ + imports: [SharedModule], + providers: [...USE_CASES], + controllers: [ChannelsController], +}) +export class ChannelsModule {} diff --git a/apps/api/src/app/channels/e2e/update-email-settings.e2e.ts b/apps/api/src/app/channels/e2e/update-email-settings.e2e.ts new file mode 100644 index 00000000000..bb7d2d87c84 --- /dev/null +++ b/apps/api/src/app/channels/e2e/update-email-settings.e2e.ts @@ -0,0 +1,23 @@ +import { UserSession } from '@notifire/testing'; +import { expect } from 'chai'; + +describe('Update Email Settings - /channels/email/settings (PUT)', function () { + let session: UserSession; + + beforeEach(async () => { + session = new UserSession(); + await session.initialize(); + }); + + it('should update the senderEmail', async function () { + const { + body: { data }, + } = await session.testAgent.put('/v1/channels/email/settings').send({ + senderEmail: 'new-test-email@ntest.co', + senderName: 'new test name', + }); + + expect(data.channels.email.senderEmail).to.equal('new-test-email@ntest.co'); + expect(data.channels.email.senderName).to.equal('new test name'); + }); +}); diff --git a/apps/api/src/app/channels/e2e/update-sms-settings.e2e.ts b/apps/api/src/app/channels/e2e/update-sms-settings.e2e.ts new file mode 100644 index 00000000000..89d7056e4ed --- /dev/null +++ b/apps/api/src/app/channels/e2e/update-sms-settings.e2e.ts @@ -0,0 +1,25 @@ +import { UserSession } from '@notifire/testing'; +import { expect } from 'chai'; + +describe('Update SMS Settings - /channels/sms/settings (PUT)', function () { + let session: UserSession; + + beforeEach(async () => { + session = new UserSession(); + await session.initialize(); + }); + + it('should update the sms settings', async function () { + const { body } = await session.testAgent.put('/v1/channels/sms/settings').send({ + twillio: { + authToken: '5678', + accountSid: '12345', + phoneNumber: '+11111111', + }, + }); + const { data } = body; + expect(data.channels.sms.twillio.authToken).to.equal('5678'); + expect(data.channels.sms.twillio.accountSid).to.equal('12345'); + expect(data.channels.sms.twillio.phoneNumber).to.equal('+11111111'); + }); +}); diff --git a/apps/api/src/app/channels/usecases/index.ts b/apps/api/src/app/channels/usecases/index.ts new file mode 100644 index 00000000000..2d58c9a99d5 --- /dev/null +++ b/apps/api/src/app/channels/usecases/index.ts @@ -0,0 +1,8 @@ +import { UpdateSmsSettings } from './update-sms-settings/update-sms-settings.usecase'; +import { UpdateMailSettings } from './update-mail-settings/update-mail-settings.usecase'; + +export const USE_CASES = [ + UpdateSmsSettings, + UpdateMailSettings, + // +]; diff --git a/apps/api/src/app/channels/usecases/update-mail-settings/update-mail-settings.command.ts b/apps/api/src/app/channels/usecases/update-mail-settings/update-mail-settings.command.ts new file mode 100644 index 00000000000..c30bb468271 --- /dev/null +++ b/apps/api/src/app/channels/usecases/update-mail-settings/update-mail-settings.command.ts @@ -0,0 +1,16 @@ +import { IsDefined, IsEmail } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; + +export class UpdateMailSettingsCommand extends ApplicationWithUserCommand { + static create(data: UpdateMailSettingsCommand) { + return CommandHelper.create(UpdateMailSettingsCommand, data); + } + + @IsDefined() + @IsEmail() + senderEmail: string; + + @IsDefined() + senderName: string; +} diff --git a/apps/api/src/app/channels/usecases/update-mail-settings/update-mail-settings.usecase.ts b/apps/api/src/app/channels/usecases/update-mail-settings/update-mail-settings.usecase.ts new file mode 100644 index 00000000000..c3b29ea2a0e --- /dev/null +++ b/apps/api/src/app/channels/usecases/update-mail-settings/update-mail-settings.usecase.ts @@ -0,0 +1,24 @@ +import { Injectable } from '@nestjs/common'; +import { ApplicationEntity, ApplicationRepository } from '@notifire/dal'; +import { UpdateMailSettingsCommand } from './update-mail-settings.command'; + +@Injectable() +export class UpdateMailSettings { + constructor(private applicationRepository: ApplicationRepository) {} + + async execute(command: UpdateMailSettingsCommand): Promise { + await this.applicationRepository.update( + { + _id: command.applicationId, + }, + { + $set: { + 'channels.email.senderEmail': command.senderEmail, + 'channels.email.senderName': command.senderName, + }, + } + ); + + return await this.applicationRepository.findById(command.applicationId); + } +} diff --git a/apps/api/src/app/channels/usecases/update-sms-settings/update-sms-settings.command.ts b/apps/api/src/app/channels/usecases/update-sms-settings/update-sms-settings.command.ts new file mode 100644 index 00000000000..29ec56330b7 --- /dev/null +++ b/apps/api/src/app/channels/usecases/update-sms-settings/update-sms-settings.command.ts @@ -0,0 +1,24 @@ +import { IsDefined, ValidateNested } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; + +class TwillioSettings { + @IsDefined() + authToken: string; + + @IsDefined() + accountSid: string; + + @IsDefined() + phoneNumber; +} + +export class UpdateSmsSettingsCommand extends ApplicationWithUserCommand { + static create(data: UpdateSmsSettingsCommand) { + return CommandHelper.create(UpdateSmsSettingsCommand, data); + } + + @IsDefined() + @ValidateNested() + twillio: TwillioSettings; +} diff --git a/apps/api/src/app/channels/usecases/update-sms-settings/update-sms-settings.usecase.ts b/apps/api/src/app/channels/usecases/update-sms-settings/update-sms-settings.usecase.ts new file mode 100644 index 00000000000..d8f4aa98748 --- /dev/null +++ b/apps/api/src/app/channels/usecases/update-sms-settings/update-sms-settings.usecase.ts @@ -0,0 +1,25 @@ +import { Injectable } from '@nestjs/common'; +import { ApplicationEntity, ApplicationRepository } from '@notifire/dal'; +import { UpdateSmsSettingsCommand } from './update-sms-settings.command'; + +@Injectable() +export class UpdateSmsSettings { + constructor(private applicationRepository: ApplicationRepository) {} + + async execute(command: UpdateSmsSettingsCommand): Promise { + await this.applicationRepository.update( + { + _id: command.applicationId, + }, + { + $set: { + 'channels.sms.twillio.accountSid': command.twillio.accountSid, + 'channels.sms.twillio.authToken': command.twillio.authToken, + 'channels.sms.twillio.phoneNumber': command.twillio.phoneNumber, + }, + } + ); + + return await this.applicationRepository.findById(command.applicationId); + } +} diff --git a/apps/api/src/app/content-templates/content-templates.controller.ts b/apps/api/src/app/content-templates/content-templates.controller.ts new file mode 100644 index 00000000000..e8881266c01 --- /dev/null +++ b/apps/api/src/app/content-templates/content-templates.controller.ts @@ -0,0 +1,4 @@ +import { Controller } from '@nestjs/common'; + +@Controller('/content-templates') +export class ContentTemplatesController {} diff --git a/apps/api/src/app/content-templates/content-templates.module.ts b/apps/api/src/app/content-templates/content-templates.module.ts new file mode 100644 index 00000000000..550b2fdea32 --- /dev/null +++ b/apps/api/src/app/content-templates/content-templates.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; +import { USE_CASES } from './usecases'; +import { ContentTemplatesController } from './content-templates.controller'; +import { SharedModule } from '../shared/shared.module'; + +@Module({ + imports: [SharedModule], + providers: [...USE_CASES], + exports: [...USE_CASES], + controllers: [ContentTemplatesController], +}) +export class ContentTemplatesModule {} diff --git a/apps/api/src/app/content-templates/usecases/compile-template/compile-template.command.ts b/apps/api/src/app/content-templates/usecases/compile-template/compile-template.command.ts new file mode 100644 index 00000000000..9d7686842f8 --- /dev/null +++ b/apps/api/src/app/content-templates/usecases/compile-template/compile-template.command.ts @@ -0,0 +1,17 @@ +import { IsDefined, IsObject, IsOptional } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; + +export class CompileTemplateCommand { + static create(data: CompileTemplateCommand) { + return CommandHelper.create(CompileTemplateCommand, data); + } + + @IsDefined() + templateId: 'basic' | 'custom'; + + @IsOptional() + customTemplate?: string; + + @IsObject() + data: any; +} diff --git a/apps/api/src/app/content-templates/usecases/compile-template/compile-template.spec.ts b/apps/api/src/app/content-templates/usecases/compile-template/compile-template.spec.ts new file mode 100644 index 00000000000..6ff21e9a8ef --- /dev/null +++ b/apps/api/src/app/content-templates/usecases/compile-template/compile-template.spec.ts @@ -0,0 +1,70 @@ +import { Test } from '@nestjs/testing'; +import { UserSession } from '@notifire/testing'; +import { expect } from 'chai'; +import { SharedModule } from '../../../shared/shared.module'; +import { ContentTemplatesModule } from '../../content-templates.module'; +import { CompileTemplate } from './compile-template.usecase'; +import { CompileTemplateCommand } from './compile-template.command'; + +describe('Compile Template', function () { + let useCase: CompileTemplate; + let session: UserSession; + + beforeEach(async () => { + const moduleRef = await Test.createTestingModule({ + imports: [SharedModule, ContentTemplatesModule], + providers: [], + }).compile(); + + session = new UserSession(); + await session.initialize(); + + useCase = moduleRef.get(CompileTemplate); + }); + + it('should render custom html', async function () { + const result = await useCase.execute( + CompileTemplateCommand.create({ + templateId: 'custom', + data: { + branding: { + color: '#e7e7e7e9', + }, + name: 'Test Name', + }, + customTemplate: '
{{name}}
', + }) + ); + + expect(result).to.equal('
Test Name
'); + }); + + it('should compile basic template successfully', async function () { + const result = await useCase.execute( + CompileTemplateCommand.create({ + templateId: 'basic', + data: { + branding: { + color: '#e7e7e7e9', + }, + blocks: [ + { + type: 'text', + content: 'Hello TESTTTT content ', + }, + { + type: 'button', + content: 'Button content of text', + }, + ], + }, + }) + ); + + expect(result).to.contain('Hello TESTTTT content'); + expect(result).to.not.contain('{{#each blocks}}'); + expect(result).to.not.contains('ff6f61'); + expect(result).to.contain('#e7e7e7e9'); + expect(result).to.contain('Button content of text'); + }); +}); diff --git a/apps/api/src/app/content-templates/usecases/compile-template/compile-template.usecase.ts b/apps/api/src/app/content-templates/usecases/compile-template/compile-template.usecase.ts new file mode 100644 index 00000000000..cb6242b136f --- /dev/null +++ b/apps/api/src/app/content-templates/usecases/compile-template/compile-template.usecase.ts @@ -0,0 +1,41 @@ +import { Injectable } from '@nestjs/common'; +import * as Handlebars from 'handlebars'; +import * as fs from 'fs'; +import { CompileTemplateCommand } from './compile-template.command'; + +Handlebars.registerHelper('equals', function (arg1, arg2, options) { + // eslint-disable-next-line eqeqeq + return arg1 == arg2 ? options.fn(this) : options.inverse(this); +}); + +const cache = new Map(); + +@Injectable() +export class CompileTemplate { + async execute(command: CompileTemplateCommand): Promise { + let templateContent = cache.get(command.templateId); + if (!templateContent) { + templateContent = await this.loadTemplateContent('basic.handlebars'); + cache.set(command.templateId, templateContent); + } + + if (command.templateId === 'custom') { + templateContent = command.customTemplate; + } + + const template = Handlebars.compile(templateContent); + return template(command.data); + } + + private async loadTemplateContent(name: string) { + return new Promise((resolve, reject) => { + fs.readFile(`${__dirname}/templates/${name}`, (err, content) => { + if (err) { + return reject(err); + } + + return resolve(content.toString()); + }); + }); + } +} diff --git a/apps/api/src/app/content-templates/usecases/compile-template/templates/basic.handlebars b/apps/api/src/app/content-templates/usecases/compile-template/templates/basic.handlebars new file mode 100644 index 00000000000..4a0789239a9 --- /dev/null +++ b/apps/api/src/app/content-templates/usecases/compile-template/templates/basic.handlebars @@ -0,0 +1,468 @@ + + + + + + + + + + + + + + + + +
+
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ +
+ + + + + + +
+ + + + + + + + +
+ {{#each blocks}} +
+ {{#equals type 'text'}} +
+
+

+ {{{content}}} +

+
+
+ {{/equals}} + {{#equals type 'button'}} + + {{/equals}} +
+ {{/each}} +
+ + + + + + + +
+ + + + + + +
+ +
+ + + + + + +
+ + + + + + +
+
+ +
+
+
+
+
+ + diff --git a/apps/api/src/app/content-templates/usecases/index.ts b/apps/api/src/app/content-templates/usecases/index.ts new file mode 100644 index 00000000000..c86dead8e8a --- /dev/null +++ b/apps/api/src/app/content-templates/usecases/index.ts @@ -0,0 +1,6 @@ +import { CompileTemplate } from './compile-template/compile-template.usecase'; + +export const USE_CASES = [ + CompileTemplate, + // +]; diff --git a/apps/api/src/app/events/dto/trigger-event.dto.ts b/apps/api/src/app/events/dto/trigger-event.dto.ts new file mode 100644 index 00000000000..84ec767a22d --- /dev/null +++ b/apps/api/src/app/events/dto/trigger-event.dto.ts @@ -0,0 +1,10 @@ +import { IsDefined, IsObject, IsString } from 'class-validator'; + +export class TriggerEventDto { + @IsString() + @IsDefined() + name: string; + + @IsObject() + payload: any; +} diff --git a/apps/api/src/app/events/e2e/trigger-event.e2e.ts b/apps/api/src/app/events/e2e/trigger-event.e2e.ts new file mode 100644 index 00000000000..3763cc0f9fc --- /dev/null +++ b/apps/api/src/app/events/e2e/trigger-event.e2e.ts @@ -0,0 +1,373 @@ +import { + LogRepository, + MessageRepository, + NotificationRepository, + NotificationTemplateEntity, + SubscriberEntity, + SubscriberRepository, +} from '@notifire/dal'; +import { UserSession, SubscribersService } from '@notifire/testing'; + +import { expect } from 'chai'; +import { ChannelTypeEnum, IEmailBlock } from '@notifire/shared'; +import axios from 'axios'; +import { mock, stub } from 'sinon'; +import { SmsService } from '../../shared/services/sms/sms.service'; + +const axiosInstance = axios.create(); + +describe('Trigger event - /v1/events/trigger (POST)', function () { + let session: UserSession; + let template: NotificationTemplateEntity; + let subscriber: SubscriberEntity; + let subscriberService: SubscribersService; + const notificationRepository = new NotificationRepository(); + const messageRepository = new MessageRepository(); + const subscriberRepository = new SubscriberRepository(); + const logRepository = new LogRepository(); + + beforeEach(async () => { + session = new UserSession(); + await session.initialize(); + template = await session.createTemplate(); + subscriberService = new SubscribersService(session.organization._id, session.application._id); + subscriber = await subscriberService.createSubscriber(); + }); + + it('should generate logs for the notification', async function () { + const response = await axiosInstance.post( + `${session.serverUrl}/v1/events/trigger`, + { + name: template.triggers[0].identifier, + payload: { + $user_id: subscriber.subscriberId, + firstName: 'Testing of User Name', + urlVariable: '/test/url/path', + }, + }, + { + headers: { + authorization: `ApiKey ${session.apiKey}`, + }, + } + ); + await new Promise((resolve) => setTimeout(resolve, 100)); + const logs = await logRepository.find({ + _applicationId: session.application._id, + _organizationId: session.organization._id, + }); + + expect(logs.length).to.be.gt(2); + }); + + it('should trigger an event successfully', async function () { + const response = await axiosInstance.post( + `${session.serverUrl}/v1/events/trigger`, + { + name: template.triggers[0].identifier, + payload: { + $user_id: subscriber.subscriberId, + firstName: 'Testing of User Name', + urlVariable: '/test/url/path', + }, + }, + { + headers: { + authorization: `ApiKey ${session.apiKey}`, + }, + } + ); + + const { data: body } = response; + expect(body.data).to.be.ok; + expect(body.data.status).to.equal('processed'); + expect(body.data.acknowledged).to.equal(true); + }); + + it('should create a subscriber based on event', async function () { + const payload = { + $user_id: 'new-test-if-id', + $first_name: 'Test Name', + $last_name: 'Last of name', + $email: 'test@email.notifire', + firstName: 'Testing of User Name', + urlVar: '/test/url/path', + }; + const { data: body } = await axiosInstance.post( + `${session.serverUrl}/v1/events/trigger`, + { + name: template.triggers[0].identifier, + payload, + }, + { + headers: { + authorization: `ApiKey ${session.apiKey}`, + }, + } + ); + + const createdSubscriber = await subscriberRepository.findBySubscriberId(session.application._id, 'new-test-if-id'); + + expect(createdSubscriber.subscriberId).to.equal(payload.$user_id); + expect(createdSubscriber.firstName).to.equal(payload.$first_name); + expect(createdSubscriber.lastName).to.equal(payload.$last_name); + expect(createdSubscriber.email).to.equal(payload.$email); + }); + + it('should override subscriber email based on event data', async function () { + const { data: body } = await axiosInstance.post( + `${session.serverUrl}/v1/events/trigger`, + { + name: template.triggers[0].identifier, + payload: { + $user_id: subscriber.subscriberId, + $email: 'new-test-email@gmail.com', + firstName: 'Testing of User Name', + urlVar: '/test/url/path', + }, + }, + { + headers: { + authorization: `ApiKey ${session.apiKey}`, + }, + } + ); + + const messages = await messageRepository.findBySubscriberChannel( + session.application._id, + subscriber._id, + ChannelTypeEnum.EMAIL + ); + expect(subscriber.email).to.not.equal('new-test-email@gmail.com'); + expect(messages[0].email).to.equal('new-test-email@gmail.com'); + }); + + it('should generate message and notification based on event', async function () { + const { data: body } = await axiosInstance.post( + `${session.serverUrl}/v1/events/trigger`, + { + name: template.triggers[0].identifier, + payload: { + $user_id: subscriber.subscriberId, + firstName: 'Testing of User Name', + urlVar: '/test/url/path', + }, + }, + { + headers: { + authorization: `ApiKey ${session.apiKey}`, + }, + } + ); + const notifications = await notificationRepository.findBySubscriberId(session.application._id, subscriber._id); + expect(notifications.length).to.equal(1); + + const notification = notifications[0]; + expect(notification._organizationId).to.equal(session.organization._id); + expect(notification._templateId).to.equal(template._id); + + const messages = await messageRepository.findBySubscriberChannel( + session.application._id, + subscriber._id, + ChannelTypeEnum.IN_APP + ); + + expect(messages.length).to.equal(1); + const message = messages[0]; + + expect(message.channel).to.equal(ChannelTypeEnum.IN_APP); + expect(message.content as string).to.equal('Test content for Testing of User Name'); + expect(message.seen).to.equal(false); + expect(message.cta.data.url).to.equal('/cypress/test-shell/example/test?test-param=true'); + expect(message.lastSeenDate).to.be.not.ok; + + const emails = await messageRepository.findBySubscriberChannel( + session.application._id, + subscriber._id, + ChannelTypeEnum.EMAIL + ); + expect(emails.length).to.equal(1); + const email = emails[0]; + + expect(email.channel).to.equal(ChannelTypeEnum.EMAIL); + expect(Array.isArray(email.content)).to.be.ok; + expect((email.content[0] as IEmailBlock).type).to.equal('text'); + expect((email.content[0] as IEmailBlock).content).to.equal( + 'This are the text contents of the template for Testing of User Name' + ); + }); + + it('should trigger based on $channels in payload', async function () { + template = await session.createTemplate({ + messages: [ + { + type: ChannelTypeEnum.SMS, + content: 'Hello world {{firstName}}' as string, + }, + { + type: ChannelTypeEnum.IN_APP, + content: 'Hello world {{firstName}}' as string, + }, + ], + }); + + const { data: body } = await axiosInstance.post( + `${session.serverUrl}/v1/events/trigger`, + { + name: template.triggers[0].identifier, + payload: { + $user_id: subscriber.subscriberId, + $phone: '+972547801111', + $channels: [ChannelTypeEnum.IN_APP], + firstName: 'Testing of User Name', + }, + }, + { + headers: { + authorization: `ApiKey ${session.apiKey}`, + }, + } + ); + + const message = await messageRepository._model.findOne({ + _applicationId: session.application._id, + _templateId: template._id, + _subscriberId: subscriber._id, + channel: ChannelTypeEnum.SMS, + }); + + expect(message).to.not.be.ok; + + const inAppMessages = await messageRepository._model.findOne({ + _applicationId: session.application._id, + _templateId: template._id, + _subscriberId: subscriber._id, + channel: ChannelTypeEnum.IN_APP, + }); + + expect(inAppMessages).to.be.ok; + }); + + it('should ignore all templates if $channels is empty', async function () { + template = await session.createTemplate({ + messages: [ + { + type: ChannelTypeEnum.SMS, + content: 'Hello world {{firstName}}' as string, + }, + { + type: ChannelTypeEnum.IN_APP, + content: 'Hello world {{firstName}}' as string, + }, + ], + }); + + const { data: body } = await axiosInstance.post( + `${session.serverUrl}/v1/events/trigger`, + { + name: template.triggers[0].identifier, + payload: { + $user_id: subscriber.subscriberId, + $phone: '+972547801111', + $channels: [], + firstName: 'Testing of User Name', + }, + }, + { + headers: { + authorization: `ApiKey ${session.apiKey}`, + }, + } + ); + + const message = await messageRepository._model.findOne({ + _applicationId: session.application._id, + _templateId: template._id, + _subscriberId: subscriber._id, + channel: ChannelTypeEnum.SMS, + }); + + expect(message).to.not.be.ok; + + const inAppMessages = await messageRepository._model.findOne({ + _applicationId: session.application._id, + _templateId: template._id, + _subscriberId: subscriber._id, + channel: ChannelTypeEnum.IN_APP, + }); + + expect(inAppMessages).to.not.be.ok; + }); + + it('should trigger SMS notification', async function () { + template = await session.createTemplate({ + messages: [ + { + type: ChannelTypeEnum.SMS, + content: 'Hello world {{firstName}}' as string, + }, + ], + }); + + const { data: body } = await axiosInstance.post( + `${session.serverUrl}/v1/events/trigger`, + { + name: template.triggers[0].identifier, + payload: { + $user_id: subscriber.subscriberId, + $phone: '+972547801111', + firstName: 'Testing of User Name', + }, + }, + { + headers: { + authorization: `ApiKey ${session.apiKey}`, + }, + } + ); + + const message = await messageRepository._model.findOne({ + _applicationId: session.application._id, + _templateId: template._id, + _subscriberId: subscriber._id, + channel: ChannelTypeEnum.SMS, + }); + + expect(message.phone).to.equal('+972547801111'); + }); + + it('should trigger an sms error', async function () { + template = await session.createTemplate({ + messages: [ + { + type: ChannelTypeEnum.SMS, + content: 'Hello world {{firstName}}' as string, + }, + ], + }); + const mocked = stub(SmsService.prototype, 'sendMessage').throws(new Error('Error from twillio')); + const { data: body } = await axiosInstance.post( + `${session.serverUrl}/v1/events/trigger`, + { + name: template.triggers[0].identifier, + payload: { + $user_id: subscriber.subscriberId, + $phone: '+972547802737', + firstName: 'Testing of User Name', + }, + }, + { + headers: { + authorization: `ApiKey ${session.apiKey}`, + }, + } + ); + const message = await messageRepository._model.findOne({ + _applicationId: session.application._id, + _templateId: template._id, + _subscriberId: subscriber._id, + }); + expect(message.status).to.equal('error'); + expect(message.errorText).to.equal('Error from twillio'); + }); +}); diff --git a/apps/api/src/app/events/events.controller.ts b/apps/api/src/app/events/events.controller.ts new file mode 100644 index 00000000000..ecb485808fb --- /dev/null +++ b/apps/api/src/app/events/events.controller.ts @@ -0,0 +1,29 @@ +import { Body, Controller, Post, UseGuards } from '@nestjs/common'; +import { IJwtPayload } from '@notifire/shared'; +import { v4 as uuidv4 } from 'uuid'; +import { TriggerEvent, TriggerEventCommand } from './usecases/trigger-event'; +import { UserSession } from '../shared/framework/user.decorator'; +import { TriggerEventDto } from './dto/trigger-event.dto'; +import { ExternalApiAccessible } from '../auth/framework/external-api.decorator'; +import { JwtAuthGuard } from '../auth/framework/auth.guard'; + +@Controller('events') +export class EventsController { + constructor(private triggerEvent: TriggerEvent) {} + + @ExternalApiAccessible() + @UseGuards(JwtAuthGuard) + @Post('/trigger') + trackEvent(@UserSession() user: IJwtPayload, @Body() body: TriggerEventDto) { + return this.triggerEvent.execute( + TriggerEventCommand.create({ + userId: user._id, + applicationId: user.applicationId, + organizationId: user.organizationId, + identifier: body.name, + payload: body.payload, + transactionId: uuidv4(), + }) + ); + } +} diff --git a/apps/api/src/app/events/events.module.ts b/apps/api/src/app/events/events.module.ts new file mode 100644 index 00000000000..90d2a49afdb --- /dev/null +++ b/apps/api/src/app/events/events.module.ts @@ -0,0 +1,25 @@ +import { Module } from '@nestjs/common'; +import { TerminusModule } from '@nestjs/terminus'; +import { SharedModule } from '../shared/shared.module'; +import { EventsController } from './events.controller'; +import { USE_CASES } from './usecases'; +import { WidgetsModule } from '../widgets/widgets.module'; +import { AuthModule } from '../auth/auth.module'; +import { SubscribersModule } from '../subscribers/subscribers.module'; +import { LogsModule } from '../logs/logs.module'; +import { ContentTemplatesModule } from '../content-templates/content-templates.module'; + +@Module({ + imports: [ + SharedModule, + TerminusModule, + WidgetsModule, + AuthModule, + SubscribersModule, + LogsModule, + ContentTemplatesModule, + ], + controllers: [EventsController], + providers: [...USE_CASES], +}) +export class EventsModule {} diff --git a/apps/api/src/app/events/usecases/index.ts b/apps/api/src/app/events/usecases/index.ts new file mode 100644 index 00000000000..c5557b55bdc --- /dev/null +++ b/apps/api/src/app/events/usecases/index.ts @@ -0,0 +1,3 @@ +import { TriggerEvent } from './trigger-event'; + +export const USE_CASES = [TriggerEvent]; diff --git a/apps/api/src/app/events/usecases/trigger-event/index.ts b/apps/api/src/app/events/usecases/trigger-event/index.ts new file mode 100644 index 00000000000..469dcb99e99 --- /dev/null +++ b/apps/api/src/app/events/usecases/trigger-event/index.ts @@ -0,0 +1,2 @@ +export * from './trigger-event.command'; +export * from './trigger-event.usecase'; diff --git a/apps/api/src/app/events/usecases/trigger-event/message-filter.matcher.spec.ts b/apps/api/src/app/events/usecases/trigger-event/message-filter.matcher.spec.ts new file mode 100644 index 00000000000..c295050e5b4 --- /dev/null +++ b/apps/api/src/app/events/usecases/trigger-event/message-filter.matcher.spec.ts @@ -0,0 +1,239 @@ +import { BuilderFieldOperator, ChannelTypeEnum } from '@notifire/shared'; +import { expect } from 'chai'; +import { MessageEntity, MessageFilter, NotificationMessagesEntity } from '@notifire/dal'; +import { matchMessageWithFilters } from './message-filter.matcher'; + +describe('Message filter matcher', function () { + it('should filter correct message by the filter value', function () { + const matchedMessage = matchMessageWithFilters( + ChannelTypeEnum.EMAIL, + [ + messageWrapper('Correct Match', 'OR', [ + { + operator: 'EQUAL', + value: 'firstVar', + field: 'varField', + }, + ]), + messageWrapper('Bad Match', 'OR', [ + { + operator: 'EQUAL', + value: 'otherValue', + field: 'varField', + }, + ]), + ], + { + varField: 'firstVar', + } + ); + + expect(matchedMessage.length).to.equal(1); + expect(matchedMessage[0].template.name).to.equal('Correct Match'); + }); + + it('should filter correct message by the channel', function () { + const matchedMessage = matchMessageWithFilters( + ChannelTypeEnum.EMAIL, + [ + messageWrapper('Correct Match', 'OR', [ + { + operator: 'EQUAL', + value: 'firstVar', + field: 'varField', + }, + ]), + messageWrapper( + 'Bad Match', + 'OR', + [ + { + operator: 'EQUAL', + value: 'firstVar', + field: 'varField', + }, + ], + ChannelTypeEnum.IN_APP + ), + ], + { + varField: 'firstVar', + } + ); + + expect(matchedMessage.length).to.equal(1); + expect(matchedMessage[0].template.name).to.equal('Correct Match'); + }); + + it('should handle multiple message matches', function () { + const matchedMessage = matchMessageWithFilters( + ChannelTypeEnum.EMAIL, + [ + messageWrapper('Correct Match', 'OR', [ + { + operator: 'EQUAL', + value: 'firstVar', + field: 'varField', + }, + ]), + messageWrapper('Correct Message', 'OR', [ + { + operator: 'EQUAL', + value: 'secondVar', + field: 'secondField', + }, + ]), + ], + { + varField: 'firstVar', + secondField: 'secondVar', + } + ); + + expect(matchedMessage.length).to.equal(2); + expect(matchedMessage[0].template.name).to.equal('Correct Match'); + }); + + it('should match a message for AND filter group', function () { + const matchedMessage = matchMessageWithFilters( + ChannelTypeEnum.EMAIL, + [ + messageWrapper('Correct Match', 'AND', [ + { + operator: 'EQUAL', + value: 'firstVar', + field: 'varField', + }, + { + operator: 'EQUAL', + value: 'secondVar', + field: 'secondField', + }, + ]), + ], + { + varField: 'firstVar', + secondField: 'secondVar', + } + ); + + expect(matchedMessage.length).to.equal(1); + expect(matchedMessage[0].template.name).to.equal('Correct Match'); + }); + + it('should not match AND group for single bad item', function () { + const matchedMessage = matchMessageWithFilters( + ChannelTypeEnum.EMAIL, + [ + messageWrapper('Title', 'AND', [ + { + operator: 'EQUAL', + value: 'firstVar', + field: 'varField', + }, + { + operator: 'EQUAL', + value: 'secondVar', + field: 'secondField', + }, + ]), + ], + { + varField: 'firstVar', + secondField: 'secondVarBad', + } + ); + + expect(matchedMessage.length).to.equal(0); + }); + + it('should match a NOT_EQUAL for EQUAL var', function () { + const matchedMessage = matchMessageWithFilters( + ChannelTypeEnum.EMAIL, + [ + messageWrapper('Correct Match', 'AND', [ + { + operator: 'EQUAL', + value: 'firstVar', + field: 'varField', + }, + { + operator: 'NOT_EQUAL', + value: 'secondVar', + field: 'secondField', + }, + ]), + ], + { + varField: 'firstVar', + secondField: 'secondVarBad', + } + ); + + expect(matchedMessage.length).to.equal(1); + expect(matchedMessage[0].template.name).to.equal('Correct Match'); + }); + + it('should fall thru for no filters item', function () { + const matchedMessage = matchMessageWithFilters( + ChannelTypeEnum.EMAIL, + [ + messageWrapper('Correct Match', 'AND', [ + { + operator: 'EQUAL', + value: 'firstVar', + field: 'varField', + }, + { + operator: 'NOT_EQUAL', + value: 'secondVar', + field: 'secondField', + }, + ]), + messageWrapper('Correct Match 2', 'OR', []), + ], + { + varField: 'firstVar', + secondField: 'secondVarBad', + } + ); + + expect(matchedMessage.length).to.equal(2); + expect(matchedMessage[0].template.name).to.equal('Correct Match'); + expect(matchedMessage[1].template.name).to.equal('Correct Match 2'); + }); +}); + +function messageWrapper( + name: string, + groupOperator: 'AND' | 'OR', + filters: { + field: string; + value: string; + operator: BuilderFieldOperator; + }[], + channel = ChannelTypeEnum.EMAIL +): NotificationMessagesEntity { + return { + _templateId: '123', + template: { + subject: 'Test Subject', + type: channel, + name, + content: 'Test', + _organizationId: '123', + _applicationId: 'asdas', + _creatorId: '123', + }, + filters: filters?.length + ? [ + { + isNegated: false, + type: 'GROUP', + value: groupOperator, + children: filters, + }, + ] + : [], + }; +} diff --git a/apps/api/src/app/events/usecases/trigger-event/message-filter.matcher.ts b/apps/api/src/app/events/usecases/trigger-event/message-filter.matcher.ts new file mode 100644 index 00000000000..3f75754bfa4 --- /dev/null +++ b/apps/api/src/app/events/usecases/trigger-event/message-filter.matcher.ts @@ -0,0 +1,58 @@ +import { ChannelTypeEnum } from '@notifire/shared'; +import { NotificationMessagesEntity } from '@notifire/dal'; + +export function matchMessageWithFilters( + channel: ChannelTypeEnum, + messages: NotificationMessagesEntity[], + payloadVariables: { [key: string]: string | string[] | { [key: string]: string } } +): NotificationMessagesEntity[] { + return messages.filter((message) => { + const channelIsMatching = message.template.type === channel; + + if (message.filters?.length) { + const foundFilter = message.filters.find((filter) => { + if (filter.type === 'GROUP') { + return handleGroupFilters(filter, payloadVariables); + } + + return false; + }); + + return channelIsMatching && foundFilter; + } + + return channelIsMatching; + }); +} + +function handleGroupFilters(filter, payloadVariables) { + if (filter.value === 'OR') { + return handleOrFilters(filter, payloadVariables); + } + + if (filter.value === 'AND') { + return handleAndFilters(filter, payloadVariables); + } + + return false; +} + +function handleAndFilters(filter, payloadVariables) { + const foundFilterMatches = filter.children.filter((i) => processFilterEquality(i, payloadVariables)); + + return foundFilterMatches.length === filter.children.length; +} + +function handleOrFilters(filter, payloadVariables) { + return filter.children.find((i) => processFilterEquality(i, payloadVariables)); +} + +function processFilterEquality(i, payloadVariables) { + if (i.operator === 'EQUAL') { + return payloadVariables[i.field] === i.value; + } + if (i.operator === 'NOT_EQUAL') { + return payloadVariables[i.field] !== i.value; + } + return false; +} diff --git a/apps/api/src/app/events/usecases/trigger-event/trigger-event.command.ts b/apps/api/src/app/events/usecases/trigger-event/trigger-event.command.ts new file mode 100644 index 00000000000..13ab1bf15b6 --- /dev/null +++ b/apps/api/src/app/events/usecases/trigger-event/trigger-event.command.ts @@ -0,0 +1,20 @@ +import { IsDefined, IsString, IsUUID } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; + +export class TriggerEventCommand extends ApplicationWithUserCommand { + static create(data: TriggerEventCommand) { + return CommandHelper.create(TriggerEventCommand, data); + } + + @IsDefined() + @IsString() + identifier: string; + + @IsDefined() + payload: any; + + @IsUUID() + @IsDefined() + transactionId: string; +} diff --git a/apps/api/src/app/events/usecases/trigger-event/trigger-event.usecase.ts b/apps/api/src/app/events/usecases/trigger-event/trigger-event.usecase.ts new file mode 100644 index 00000000000..d10539f0ce0 --- /dev/null +++ b/apps/api/src/app/events/usecases/trigger-event/trigger-event.usecase.ts @@ -0,0 +1,566 @@ +import { Injectable } from '@nestjs/common'; +import { + ApplicationEntity, + ApplicationRepository, + IEmailBlock, + MessageRepository, + NotificationEntity, + NotificationMessagesEntity, + NotificationRepository, + NotificationTemplateEntity, + NotificationTemplateRepository, + SubscriberEntity, + SubscriberRepository, +} from '@notifire/dal'; +import { ChannelTypeEnum, LogCodeEnum, LogStatusEnum } from '@notifire/shared'; +import * as Sentry from '@sentry/node'; +import { TriggerEventCommand } from './trigger-event.command'; +import { ContentService } from '../../../shared/helpers/content.service'; +import { CreateSubscriber, CreateSubscriberCommand } from '../../../subscribers/usecases/create-subscriber'; +import { matchMessageWithFilters } from './message-filter.matcher'; +import { CreateLog } from '../../../logs/usecases/create-log/create-log.usecase'; +import { CreateLogCommand } from '../../../logs/usecases/create-log/create-log.command'; +import { CompileTemplate } from '../../../content-templates/usecases/compile-template/compile-template.usecase'; +import { CompileTemplateCommand } from '../../../content-templates/usecases/compile-template/compile-template.command'; +import { ISendMail, MailService } from '../../../shared/services/mail/mail.service'; +import { QueueService } from '../../../shared/services/queue'; +import { AnalyticsService } from '../../../shared/services/analytics/analytics.service'; +import { SmsService } from '../../../shared/services/sms/sms.service'; + +@Injectable() +export class TriggerEvent { + constructor( + private notificationTemplateRepository: NotificationTemplateRepository, + private subscriberRepository: SubscriberRepository, + private notificationRepository: NotificationRepository, + private messageRepository: MessageRepository, + private mailService: MailService, + private queueService: QueueService, + private applicationRepository: ApplicationRepository, + private createSubscriberUsecase: CreateSubscriber, + private createLogUsecase: CreateLog, + private analyticsService: AnalyticsService, + private compileTemplate: CompileTemplate + ) {} + + async execute(command: TriggerEventCommand) { + Sentry.addBreadcrumb({ + message: 'Sending trigger', + data: { + triggerIdentifier: command.identifier, + }, + }); + + this.createLogUsecase + .execute( + CreateLogCommand.create({ + transactionId: command.transactionId, + status: LogStatusEnum.INFO, + applicationId: command.applicationId, + organizationId: command.organizationId, + text: 'Trigger request received', + userId: command.userId, + code: LogCodeEnum.TRIGGER_RECEIVED, + raw: { + payload: command.payload, + }, + }) + ) + .catch((e) => console.error(e)); + + const template = await this.notificationTemplateRepository.findByTriggerIdentifier( + command.organizationId, + command.identifier + ); + + if (!template) { + this.createLogUsecase.execute( + CreateLogCommand.create({ + transactionId: command.transactionId, + status: LogStatusEnum.ERROR, + applicationId: command.applicationId, + organizationId: command.organizationId, + text: 'Template not found', + userId: command.userId, + code: LogCodeEnum.TEMPLATE_NOT_FOUND, + raw: { + triggerIdentifier: command.identifier, + }, + }) + ); + + return { + acknowledged: true, + status: 'template_not_found', + }; + } + + if (!template.active || template.draft) { + this.createLogUsecase.execute( + CreateLogCommand.create({ + transactionId: command.transactionId, + status: LogStatusEnum.ERROR, + applicationId: command.applicationId, + organizationId: command.organizationId, + text: 'Template not active', + userId: command.userId, + code: LogCodeEnum.TEMPLATE_NOT_ACTIVE, + templateId: template._id, + raw: { + payload: command.payload, + triggerIdentifier: command.identifier, + }, + }) + ); + + return { + acknowledged: true, + status: 'trigger_not_active', + }; + } + + let subscriber = await this.subscriberRepository.findBySubscriberId( + command.applicationId, + command.payload.$user_id + ); + + if (!subscriber) { + if (command.payload.$email || command.payload.$phone) { + subscriber = await this.createSubscriberUsecase.execute( + CreateSubscriberCommand.create({ + applicationId: command.applicationId, + organizationId: command.organizationId, + subscriberId: command.payload.$user_id, + email: command.payload.$email, + firstName: command.payload.$first_name, + lastName: command.payload.$last_name, + phone: command.payload.$phone, + }) + ); + } else { + this.createLogUsecase.execute( + CreateLogCommand.create({ + transactionId: command.transactionId, + status: LogStatusEnum.ERROR, + applicationId: command.applicationId, + organizationId: command.organizationId, + text: 'Subscriber not found', + userId: command.userId, + code: LogCodeEnum.SUBSCRIBER_NOT_FOUND, + templateId: template._id, + raw: { + payload: command.payload, + triggerIdentifier: command.identifier, + }, + }) + ); + + return { + acknowledged: true, + status: 'subscriber_not_found', + }; + } + } + + const notification = await this.notificationRepository.create({ + _applicationId: command.applicationId, + _organizationId: command.organizationId, + _subscriberId: subscriber._id, + _templateId: template._id, + transactionId: command.transactionId, + }); + + const application = await this.applicationRepository.findById(command.applicationId); + const { smsMessages, inAppChannelMessages, emailChannelMessages } = this.extractMatchingMessages( + template, + command.payload + ); + + let channelsToSend: ChannelTypeEnum[] = []; + if (!command.payload.$channels || !Array.isArray(command.payload.$channels)) { + if (smsMessages?.length) { + channelsToSend.push(ChannelTypeEnum.SMS); + } + + if (inAppChannelMessages?.length) { + channelsToSend.push(ChannelTypeEnum.IN_APP); + } + + if (emailChannelMessages?.length) { + channelsToSend.push(ChannelTypeEnum.EMAIL); + } + } else { + channelsToSend = command.payload.$channels; + } + + if (smsMessages?.length && this.shouldSendChannel(channelsToSend, ChannelTypeEnum.SMS)) { + await this.sendSmsMessage(smsMessages, command, notification, subscriber, template, application); + } + + if (inAppChannelMessages?.length && this.shouldSendChannel(channelsToSend, ChannelTypeEnum.IN_APP)) { + await this.sendInAppMessage(inAppChannelMessages, command, notification, subscriber, template); + } + + if (emailChannelMessages.length && this.shouldSendChannel(channelsToSend, ChannelTypeEnum.EMAIL)) { + await this.sendEmailMessage(emailChannelMessages, command, notification, subscriber, template, application); + } + + this.createLogUsecase.execute( + CreateLogCommand.create({ + transactionId: command.transactionId, + status: LogStatusEnum.INFO, + applicationId: command.applicationId, + organizationId: command.organizationId, + notificationId: notification._id, + text: 'Request processed', + userId: command.userId, + subscriberId: subscriber._id, + code: LogCodeEnum.TRIGGER_PROCESSED, + templateId: template._id, + }) + ); + + this.analyticsService.track('Notification event trigger - [Triggers]', command.userId, { + smsChannel: !!smsMessages?.length, + emailChannel: !!emailChannelMessages?.length, + inAppChannel: !!inAppChannelMessages?.length, + }); + + return { + acknowledged: true, + status: 'processed', + }; + } + + private shouldSendChannel(channels: ChannelTypeEnum[], channel: ChannelTypeEnum) { + return channels.includes(channel); + } + + private extractMatchingMessages(template: NotificationTemplateEntity, payload) { + const smsMessages = matchMessageWithFilters(ChannelTypeEnum.SMS, template.messages, payload); + const inAppChannelMessages = matchMessageWithFilters(ChannelTypeEnum.IN_APP, template.messages, payload); + const emailChannelMessages = matchMessageWithFilters(ChannelTypeEnum.EMAIL, template.messages, payload); + + return { smsMessages, inAppChannelMessages, emailChannelMessages }; + } + + private async sendSmsMessage( + smsMessages: NotificationMessagesEntity[], + command: TriggerEventCommand, + notification: NotificationEntity, + subscriber: SubscriberEntity, + template: NotificationTemplateEntity, + application: ApplicationEntity + ) { + Sentry.addBreadcrumb({ + message: 'Sending SMS', + }); + const smsChannel = smsMessages[0]; + const contentService = new ContentService(); + const content = contentService.replaceVariables(smsChannel.template.content as string, command.payload); + + const message = await this.messageRepository.create({ + _notificationId: notification._id, + _applicationId: command.applicationId, + _organizationId: command.organizationId, + _subscriberId: subscriber._id, + _templateId: template._id, + _messageTemplateId: smsChannel.template._id, + channel: ChannelTypeEnum.SMS, + transactionId: command.transactionId, + phone: command.payload.$phone, + content, + }); + + if ( + command.payload.$phone && + application.channels?.sms?.twillio?.authToken && + application.channels?.sms?.twillio?.accountSid + ) { + try { + const smsService = new SmsService( + application.channels?.sms?.twillio?.authToken, + application.channels?.sms?.twillio?.accountSid + ); + const smsResponse = await smsService.sendMessage( + command.payload.$phone, + application.channels?.sms?.twillio?.phoneNumber, + content + ); + } catch (e) { + this.createLogUsecase.execute( + CreateLogCommand.create({ + transactionId: command.transactionId, + status: LogStatusEnum.ERROR, + applicationId: command.applicationId, + organizationId: command.organizationId, + text: e.message || e.name || 'Un-expect SMS provider error', + userId: command.userId, + code: LogCodeEnum.SMS_ERROR, + templateId: template._id, + raw: { + payload: command.payload, + triggerIdentifier: command.identifier, + }, + }) + ); + + await this.messageRepository.updateMessageStatus( + message._id, + 'error', + e, + 'unexpected_sms_error', + e.message || e.name || 'Un-expect SMS provider error' + ); + } + } else if (!command.payload.$phone) { + this.createLogUsecase.execute( + CreateLogCommand.create({ + transactionId: command.transactionId, + status: LogStatusEnum.ERROR, + applicationId: command.applicationId, + organizationId: command.organizationId, + text: 'Subscriber does not have active phone', + userId: command.userId, + subscriberId: subscriber._id, + code: LogCodeEnum.SUBSCRIBER_MISSING_PHONE, + templateId: template._id, + raw: { + payload: command.payload, + triggerIdentifier: command.identifier, + }, + }) + ); + await this.messageRepository.updateMessageStatus( + message._id, + 'warning', + null, + 'no_subscriber_phone', + 'Subscriber does not have active phone' + ); + } else if (!application.channels?.sms?.twillio?.authToken) { + this.createLogUsecase.execute( + CreateLogCommand.create({ + transactionId: command.transactionId, + status: LogStatusEnum.ERROR, + applicationId: command.applicationId, + organizationId: command.organizationId, + text: 'No sms provider was configured', + userId: command.userId, + subscriberId: subscriber._id, + code: LogCodeEnum.MISSING_SMS_PROVIDER, + templateId: template._id, + raw: { + payload: command.payload, + triggerIdentifier: command.identifier, + }, + }) + ); + await this.messageRepository.updateMessageStatus( + message._id, + 'warning', + null, + 'no_sms_provider_connection', + 'No SMS provider token found' + ); + } + } + + private async sendInAppMessage( + inAppChannelMessages: NotificationMessagesEntity[], + command: TriggerEventCommand, + notification: NotificationEntity, + subscriber: SubscriberEntity, + template: NotificationTemplateEntity + ) { + Sentry.addBreadcrumb({ + message: 'Sending In App', + }); + const inAppChannel = inAppChannelMessages[0]; + + const contentService = new ContentService(); + + const content = contentService.replaceVariables(inAppChannel.template.content as string, command.payload); + if (inAppChannel.template.cta?.data?.url) { + inAppChannel.template.cta.data.url = contentService.replaceVariables( + inAppChannel.template.cta?.data?.url, + command.payload + ); + } + + const message = await this.messageRepository.create({ + _notificationId: notification._id, + _applicationId: command.applicationId, + _organizationId: command.organizationId, + _subscriberId: subscriber._id, + _templateId: template._id, + _messageTemplateId: inAppChannel.template._id, + channel: ChannelTypeEnum.IN_APP, + cta: inAppChannel.template.cta, + transactionId: command.transactionId, + content, + }); + + const count = await this.messageRepository.getUnseenCount( + command.applicationId, + subscriber._id, + ChannelTypeEnum.IN_APP + ); + + this.createLogUsecase.execute( + CreateLogCommand.create({ + transactionId: command.transactionId, + status: LogStatusEnum.SUCCESS, + applicationId: command.applicationId, + organizationId: command.organizationId, + notificationId: notification._id, + messageId: message._id, + text: 'In App message created', + userId: command.userId, + subscriberId: subscriber._id, + code: LogCodeEnum.IN_APP_MESSAGE_CREATED, + templateId: template._id, + raw: { + payload: command.payload, + triggerIdentifier: command.identifier, + }, + }) + ); + + this.queueService.wsSocketQueue.add({ + event: 'unseen_count_changed', + userId: subscriber._id, + payload: { + unseenCount: count, + }, + }); + } + + private async sendEmailMessage( + emailChannelMessages: NotificationMessagesEntity[], + command: TriggerEventCommand, + notification: NotificationEntity, + subscriber: SubscriberEntity, + template: NotificationTemplateEntity, + application: ApplicationEntity + ) { + const email = command.payload.$email || subscriber.email; + Sentry.addBreadcrumb({ + message: 'Sending Email', + }); + const emailChannel = emailChannelMessages[0]; + const isEditorMode = !emailChannel.template.contentType || emailChannel.template.contentType === 'editor'; + + let content: string | IEmailBlock[] = ''; + + if (isEditorMode) { + content = [...emailChannel.template.content] as IEmailBlock[]; + for (const block of content) { + const contentService = new ContentService(); + block.content = contentService.replaceVariables(block.content, command.payload); + block.url = contentService.replaceVariables(block.url, command.payload); + } + } else { + content = emailChannel.template.content; + } + + const message = await this.messageRepository.create({ + _notificationId: notification._id, + _applicationId: command.applicationId, + _organizationId: command.organizationId, + _subscriberId: subscriber._id, + _templateId: template._id, + _messageTemplateId: emailChannel.template._id, + content, + channel: ChannelTypeEnum.EMAIL, + transactionId: command.transactionId, + email, + }); + + const contentService = new ContentService(); + const subject = contentService.replaceVariables(emailChannel.template.subject, command.payload); + + const html = await this.compileTemplate.execute( + CompileTemplateCommand.create({ + templateId: isEditorMode ? 'basic' : 'custom', + customTemplate: emailChannel.template.contentType === 'customHtml' ? (content as string) : undefined, + data: { + subject, + branding: { + logo: application.branding?.logo, + color: application.branding?.color || '#f47373', + }, + blocks: isEditorMode ? content : [], + ...command.payload, + }, + }) + ); + + const mailData: ISendMail = { + from: { + name: command.payload.$sender_name || application.channels?.email?.senderName || application.name, + email: command.payload.$sender_email || application.channels?.email?.senderEmail || 'no-reply@notifire.co', + }, + html, + subject, + to: email, + }; + + if (email) { + this.mailService.sendMail(mailData).catch((error) => { + Sentry.captureException(error?.response?.body || error?.response || error); + this.messageRepository.updateMessageStatus( + message._id, + 'error', + error?.response?.body || error?.response || error, + 'mail_unexpected_error', + 'Error while sending email with provider' + ); + + this.createLogUsecase.execute( + CreateLogCommand.create({ + transactionId: command.transactionId, + status: LogStatusEnum.ERROR, + applicationId: command.applicationId, + organizationId: command.organizationId, + notificationId: notification._id, + messageId: message._id, + text: 'Error while sending email with provider', + userId: command.userId, + subscriberId: subscriber._id, + code: LogCodeEnum.MAIL_PROVIDER_DELIVERY_ERROR, + templateId: template._id, + raw: { + error: error?.response?.body || error?.response || error, + payload: command.payload, + triggerIdentifier: command.identifier, + }, + }) + ); + }); + } else { + await this.messageRepository.updateMessageStatus( + message._id, + 'warning', + null, + 'mail_unexpected_error', + 'Subscriber does not have an email address' + ); + + this.createLogUsecase.execute( + CreateLogCommand.create({ + transactionId: command.transactionId, + status: LogStatusEnum.ERROR, + applicationId: command.applicationId, + organizationId: command.organizationId, + notificationId: notification._id, + text: 'Subscriber does not have an email address', + userId: command.userId, + subscriberId: subscriber._id, + code: LogCodeEnum.SUBSCRIBER_MISSING_EMAIL, + templateId: template._id, + }) + ); + } + } +} diff --git a/apps/api/src/app/health/health.controller.ts b/apps/api/src/app/health/health.controller.ts new file mode 100644 index 00000000000..969210d6d15 --- /dev/null +++ b/apps/api/src/app/health/health.controller.ts @@ -0,0 +1,36 @@ +import { Controller, Get } from '@nestjs/common'; +import { HealthCheck, HealthCheckService, HttpHealthIndicator } from '@nestjs/terminus'; +import { DalService } from '@notifire/dal'; +import { version } from '../../../package.json'; + +@Controller('health-check') +export class HealthController { + constructor( + private healthCheckService: HealthCheckService, + private healthIndicator: HttpHealthIndicator, + private dalService: DalService + ) {} + + @Get() + @HealthCheck() + healthCheck() { + return this.healthCheckService.check([ + async () => { + return { + db: { + status: this.dalService.connection.readyState === 1 ? 'up' : 'down', + }, + }; + }, + async () => this.healthIndicator.pingCheck('dns', 'https://google.com'), + async () => { + return { + apiVersion: { + version, + status: 'up', + }, + }; + }, + ]); + } +} diff --git a/apps/api/src/app/health/health.module.ts b/apps/api/src/app/health/health.module.ts new file mode 100644 index 00000000000..b9d9898ee43 --- /dev/null +++ b/apps/api/src/app/health/health.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { TerminusModule } from '@nestjs/terminus'; +import { SharedModule } from '../shared/shared.module'; +import { HealthController } from './health.controller'; + +@Module({ + imports: [SharedModule, TerminusModule], + controllers: [HealthController], + providers: [], +}) +export class HealthModule {} diff --git a/apps/api/src/app/invites/e2e/accept-invite.e2e.ts b/apps/api/src/app/invites/e2e/accept-invite.e2e.ts new file mode 100644 index 00000000000..966a08c2f02 --- /dev/null +++ b/apps/api/src/app/invites/e2e/accept-invite.e2e.ts @@ -0,0 +1,75 @@ +import { OrganizationRepository, MemberRepository } from '@notifire/dal'; +import { UserSession } from '@notifire/testing'; +import { MemberStatusEnum } from '@notifire/shared'; +import { expect } from 'chai'; + +describe('Accept invite - /invites/:inviteToken/accept (POST)', async () => { + let session: UserSession; + let invitedUserSession: UserSession; + const organizationRepository = new OrganizationRepository(); + const memberRepository = new MemberRepository(); + + async function setup() { + session = new UserSession(); + invitedUserSession = new UserSession(); + await invitedUserSession.initialize({ + noOrganization: true, + noApplication: true, + }); + + await session.initialize(); + + await session.testAgent.post('/v1/invites/bulk').send({ + invitees: [ + { + email: 'asdas@dasdas.com', + }, + ], + }); + } + + describe('Valid invite accept flow', async () => { + let response; + before(async () => { + await setup(); + + const organization = await organizationRepository.findById(session.organization._id); + const members = await memberRepository.getOrganizationMembers(session.organization._id); + const invitee = members.find((i) => !i._userId); + + const { body } = await invitedUserSession.testAgent + .post(`/v1/invites/${invitee.invite.token}/accept`) + .expect(201); + + response = body.data; + }); + + it('should change the member status to active', async () => { + const member = await memberRepository.findMemberByUserId(session.organization._id, invitedUserSession.user._id); + + expect(member._userId).to.equal(invitedUserSession.user._id); + expect(member.memberStatus).to.equal(MemberStatusEnum.ACTIVE); + }); + }); + + describe('Invalid accept requests handling', async () => { + before(async () => { + await setup(); + }); + + it('should reject expired token', async () => { + const organization = await organizationRepository.findById(session.organization._id); + const members = await memberRepository.getOrganizationMembers(session.organization._id); + const invitee = members.find((i) => !i._userId); + expect(invitee.memberStatus).to.eq(MemberStatusEnum.INVITED); + + await invitedUserSession.testAgent.post(`/v1/invites/${invitee.invite.token}/accept`).expect(201); + + const { body } = await invitedUserSession.testAgent + .post(`/v1/invites/${invitee.invite.token}/accept`) + .expect(400); + + expect(body.message).to.contain('expired'); + }); + }); +}); diff --git a/apps/api/src/app/invites/e2e/bulk-invite.e2e.ts b/apps/api/src/app/invites/e2e/bulk-invite.e2e.ts new file mode 100644 index 00000000000..a8914359a3f --- /dev/null +++ b/apps/api/src/app/invites/e2e/bulk-invite.e2e.ts @@ -0,0 +1,143 @@ +import { OrganizationRepository, MemberRepository } from '@notifire/dal'; +import { UserSession } from '@notifire/testing'; +import { IBulkInviteResponse, MemberRoleEnum, MemberStatusEnum } from '@notifire/shared'; +import { expect } from 'chai'; + +describe('Bulk invite members - /invites/bulk (POST)', async () => { + let session: UserSession; + const organizationRepository = new OrganizationRepository(); + const memberRepository = new MemberRepository(); + + before(async () => { + session = new UserSession(); + await session.initialize(); + }); + + it('should fail without passing invitees', async () => { + const { body } = await session.testAgent + .post('/v1/invites/bulk') + .send({ + invitees: [], + }) + .expect(400); + }); + + it('should fail with bad emails', async () => { + const { body } = await session.testAgent + .post('/v1/invites/bulk') + .send({ + invitees: [ + { + email: 'asdasda', + role: 'admin', + }, + ], + }) + .expect(400); + }); + + it('should invite member as admin', async () => { + session = new UserSession(); + await session.initialize(); + + const { body } = await session.testAgent + .post('/v1/invites/bulk') + .send({ + invitees: [ + { + email: 'dddd@asdas.com', + role: 'admin', + }, + ], + }) + .expect(201); + + const members = await memberRepository.getOrganizationMembers(session.organization._id); + expect(members.length).to.eq(2); + + const member = members.find((i) => !i._userId); + expect(member.invite.email).to.equal('dddd@asdas.com'); + expect(member.invite._inviterId).to.equal(session.user._id); + expect(member.roles.length).to.equal(1); + expect(member.roles[0]).to.equal(MemberRoleEnum.ADMIN); + expect(member.memberStatus).to.equal(MemberStatusEnum.INVITED); + }); + + it('should invite member as member', async () => { + session = new UserSession(); + await session.initialize(); + + const { body } = await session.testAgent + .post('/v1/invites/bulk') + .send({ + invitees: [ + { + email: 'aaaaa2@asdas.com', + role: 'member', + }, + ], + }) + .expect(201); + + const members = await memberRepository.getOrganizationMembers(session.organization._id); + expect(members.length).to.eq(2); + + const member = members.find((i) => !i._userId); + expect(member.roles[0]).to.equal(MemberRoleEnum.MEMBER); + expect(member.memberStatus).to.equal(MemberStatusEnum.INVITED); + }); + + describe('send valid invites', () => { + let inviteResponse: IBulkInviteResponse[]; + + const invitee = { + email: 'asdasda@asdas.com', + role: 'member', + }; + + before(async () => { + session = new UserSession(); + await session.initialize(); + + const { body } = await session.testAgent + .post('/v1/invites/bulk') + .send({ + invitees: [invitee], + }) + .expect(201); + + inviteResponse = body.data; + }); + + it('should return a matching response', async () => { + expect(inviteResponse.length).to.equal(1); + expect(inviteResponse[0].success).to.equal(true); + expect(inviteResponse[0].email).to.equal(invitee.email); + }); + + it('should create invited member entity', async () => { + const members = await memberRepository.getOrganizationMembers(session.organization._id); + + expect(members.length).to.eq(2); + + const member = members.find((i) => !i._userId); + expect(member.invite.email).to.equal(invitee.email); + expect(member.invite._inviterId).to.equal(session.user._id); + expect(member.roles.length).to.equal(1); + expect(member.roles[0]).to.equal(MemberRoleEnum.MEMBER); + + expect(member.memberStatus).to.equal(MemberStatusEnum.INVITED); + expect(member._userId).to.be.not.ok; + }); + + it('should fail invite already invited person', async () => { + const { body } = await session.testAgent.post('/v1/invites/bulk').send({ + invitees: [invitee], + }); + + expect(body.data.length).to.equal(1); + expect(body.data[0].failReason).to.include('Already invited'); + expect(body.data[0].success).to.equal(false); + }); + }); +}); diff --git a/apps/api/src/app/invites/e2e/get-invite.e2e.ts b/apps/api/src/app/invites/e2e/get-invite.e2e.ts new file mode 100644 index 00000000000..29faf075e82 --- /dev/null +++ b/apps/api/src/app/invites/e2e/get-invite.e2e.ts @@ -0,0 +1,72 @@ +import { OrganizationRepository, MemberRepository } from '@notifire/dal'; +import { UserSession } from '@notifire/testing'; +import { MemberStatusEnum } from '@notifire/shared'; +import { expect } from 'chai'; + +describe('Get invite object - /invites/:inviteToken (GET)', async () => { + let session: UserSession; + const organizationRepository = new OrganizationRepository(); + const memberRepository = new MemberRepository(); + + describe('valid token returned', async () => { + before(async () => { + session = new UserSession(); + await session.initialize(); + + await session.testAgent.post('/v1/invites/bulk').send({ + invitees: [ + { + email: 'asdas@dasdas.com', + }, + ], + }); + }); + + it('should return a valid invite object', async () => { + const members = await memberRepository.getOrganizationMembers(session.organization._id); + const member = members.find((i) => i.memberStatus === MemberStatusEnum.INVITED); + + const { body } = await session.testAgent.get(`/v1/invites/${member.invite.token}`); + + const response = body.data; + + expect(response.inviter._id).to.equal(session.user._id); + expect(response.organization._id).to.equal(session.organization._id); + }); + }); + + describe('error state validation', async () => { + before(async () => { + session = new UserSession(); + await session.initialize(); + + await session.testAgent.post('/v1/invites/bulk').send({ + invitees: [ + { + email: 'asdas@dasdas.com', + }, + ], + }); + }); + + it('should return an error for expired token', async () => { + const organization = await organizationRepository.findById(session.organization._id); + const members = await memberRepository.getOrganizationMembers(session.organization._id); + const member = members.find((i) => i.memberStatus === MemberStatusEnum.INVITED); + + await memberRepository.update( + { + _id: member._id, + 'invite.token': member.invite.token, + }, + { + memberStatus: MemberStatusEnum.ACTIVE, + } + ); + + const { body } = await session.testAgent.get(`/v1/invites/${member.invite.token}`).expect(400); + + expect(body.message).to.contain('expired'); + }); + }); +}); diff --git a/apps/api/src/app/invites/invites.controller.ts b/apps/api/src/app/invites/invites.controller.ts new file mode 100644 index 00000000000..006d4fab112 --- /dev/null +++ b/apps/api/src/app/invites/invites.controller.ts @@ -0,0 +1,94 @@ +import { + Body, + ClassSerializerInterceptor, + Controller, + Get, + Param, + Post, + UseGuards, + UseInterceptors, +} from '@nestjs/common'; +import { AuthGuard } from '@nestjs/passport'; +import { IBulkInviteResponse, IGetInviteResponseDto, IJwtPayload, MemberRoleEnum } from '@notifire/shared'; +import { UserSession } from '../shared/framework/user.decorator'; +import { GetInviteCommand } from './usecases/get-invite/get-invite.command'; +import { AcceptInviteCommand } from './usecases/accept-invite/accept-invite.command'; +import { Roles } from '../auth/framework/roles.decorator'; +import { InviteMemberDto } from '../organization/dtos/invite-member.dto'; +import { InviteMemberCommand } from './usecases/invite-member/invite-member.command'; +import { BulkInviteMembersDto } from '../organization/dtos/bulk-invite-members.dto'; +import { BulkInviteCommand } from './usecases/bulk-invite/bulk-invite.command'; +import { InviteMember } from './usecases/invite-member/invite-member.usecase'; +import { BulkInvite } from './usecases/bulk-invite/bulk-invite.usecase'; +import { AcceptInvite } from './usecases/accept-invite/accept-invite.usecase'; +import { GetInvite } from './usecases/get-invite/get-invite.usecase'; + +@UseInterceptors(ClassSerializerInterceptor) +@Controller('/invites') +export class InvitesController { + constructor( + private inviteMemberUsecase: InviteMember, + private bulkInviteUsecase: BulkInvite, + private acceptInviteUsecase: AcceptInvite, + private getInvite: GetInvite + ) {} + + @Get('/:inviteToken') + async getInviteData(@Param('inviteToken') inviteToken: string): Promise { + const command = GetInviteCommand.create({ + token: inviteToken, + }); + + return await this.getInvite.execute(command); + } + + @Post('/:inviteToken/accept') + @UseGuards(AuthGuard('jwt')) + async acceptInviteToken( + @UserSession() user: IJwtPayload, + @Param('inviteToken') inviteToken: string + ): Promise { + const command = AcceptInviteCommand.create({ + token: inviteToken, + userId: user._id, + }); + + return await this.acceptInviteUsecase.execute(command); + } + + @Post('/') + @Roles(MemberRoleEnum.ADMIN) + @UseGuards(AuthGuard('jwt')) + async inviteMember(@UserSession() user: IJwtPayload, @Body() body: InviteMemberDto): Promise<{ success: boolean }> { + const command = InviteMemberCommand.create({ + userId: user._id, + organizationId: user.organizationId, + email: body.email, + role: body.role, + }); + + await this.inviteMemberUsecase.execute(command); + + return { + success: true, + }; + } + + @Post('/bulk') + @UseGuards(AuthGuard('jwt')) + @Roles(MemberRoleEnum.ADMIN) + async bulkInviteMembers( + @UserSession() user: IJwtPayload, + @Body() body: BulkInviteMembersDto + ): Promise { + const command = BulkInviteCommand.create({ + userId: user._id, + organizationId: user.organizationId, + invitees: body.invitees, + }); + + const response = await this.bulkInviteUsecase.execute(command); + + return response; + } +} diff --git a/apps/api/src/app/invites/invites.module.ts b/apps/api/src/app/invites/invites.module.ts new file mode 100644 index 00000000000..f6968f0a263 --- /dev/null +++ b/apps/api/src/app/invites/invites.module.ts @@ -0,0 +1,13 @@ +import { Module } from '@nestjs/common'; +import { SharedModule } from '../shared/shared.module'; +import { InvitesController } from './invites.controller'; +import { USE_CASES } from './usecases'; +import { AuthModule } from '../auth/auth.module'; + +@Module({ + imports: [SharedModule, AuthModule], + controllers: [InvitesController], + providers: [...USE_CASES], + exports: [...USE_CASES], +}) +export class InvitesModule {} diff --git a/apps/api/src/app/invites/usecases/accept-invite/accept-invite.command.ts b/apps/api/src/app/invites/usecases/accept-invite/accept-invite.command.ts new file mode 100644 index 00000000000..f9c9105e879 --- /dev/null +++ b/apps/api/src/app/invites/usecases/accept-invite/accept-invite.command.ts @@ -0,0 +1,12 @@ +import { IsString } from 'class-validator'; +import { AuthenticatedCommand } from '../../../shared/commands/authenticated.command'; +import { CommandHelper } from '../../../shared/commands/command.helper'; + +export class AcceptInviteCommand extends AuthenticatedCommand { + static create(data: AcceptInviteCommand) { + return CommandHelper.create(AcceptInviteCommand, data); + } + + @IsString() + readonly token: string; +} diff --git a/apps/api/src/app/invites/usecases/accept-invite/accept-invite.usecase.ts b/apps/api/src/app/invites/usecases/accept-invite/accept-invite.usecase.ts new file mode 100644 index 00000000000..ace13761293 --- /dev/null +++ b/apps/api/src/app/invites/usecases/accept-invite/accept-invite.usecase.ts @@ -0,0 +1,62 @@ +import { Injectable, Logger, Scope } from '@nestjs/common'; +import { MemberEntity, OrganizationRepository, UserEntity, MemberRepository, UserRepository } from '@notifire/dal'; +import { MemberRoleEnum, MemberStatusEnum } from '@notifire/shared'; +import { Notifire } from '@notifire/node'; +import { ApiException } from '../../../shared/exceptions/api.exception'; +import { AcceptInviteCommand } from './accept-invite.command'; +import { AuthService } from '../../../auth/services/auth.service'; +import { capitalize } from '../../../shared/services/helper/helper.service'; + +@Injectable({ + scope: Scope.REQUEST, +}) +export class AcceptInvite { + private organizationId: string; + + constructor( + private organizationRepository: OrganizationRepository, + private memberRepository: MemberRepository, + private userRepository: UserRepository, + private authService: AuthService + ) {} + + async execute(command: AcceptInviteCommand): Promise { + const member = await this.memberRepository.findByInviteToken(command.token); + if (!member) throw new ApiException('No organization found'); + const organization = await this.organizationRepository.findById(member._organizationId); + const user = await this.userRepository.findById(command.userId); + + this.organizationId = organization._id; + + if (member.memberStatus !== MemberStatusEnum.INVITED) throw new ApiException('Token expired'); + + const inviter = await this.userRepository.findById(member.invite._inviterId); + + await this.memberRepository.convertInvitedUserToMember(command.token, { + memberStatus: MemberStatusEnum.ACTIVE, + _userId: command.userId, + answerDate: new Date(), + }); + + this.sendInviterAcceptedEmail(inviter, member); + + return this.authService.generateUserToken(user); + } + + async sendInviterAcceptedEmail(inviter: UserEntity, member: MemberEntity) { + try { + if (process.env.NODE_ENV === 'dev' || process.env.NODE_ENV === 'prod') { + const notifire = new Notifire(process.env.NOTIFIRE_API_KEY); + await notifire.trigger('invite-accepted-r5Q7-sQE-', { + $user_id: inviter._id, + $email: inviter.email, + firstName: capitalize(inviter.firstName), + invitedUserEmail: member.invite.email, + ctaUrl: '/settings/organization', + }); + } + } catch (e) { + Logger.error(e.message, e.stack, 'Accept inviter send email'); + } + } +} diff --git a/apps/api/src/app/invites/usecases/bulk-invite/bulk-invite.command.ts b/apps/api/src/app/invites/usecases/bulk-invite/bulk-invite.command.ts new file mode 100644 index 00000000000..9fd513f4b04 --- /dev/null +++ b/apps/api/src/app/invites/usecases/bulk-invite/bulk-invite.command.ts @@ -0,0 +1,14 @@ +import { MemberRoleEnum } from '@notifire/shared'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { OrganizationCommand } from '../../../shared/commands/organization.command'; + +export class BulkInviteCommand extends OrganizationCommand { + static create(data: BulkInviteCommand) { + return CommandHelper.create(BulkInviteCommand, data); + } + + invitees: { + email: string; + role?: MemberRoleEnum; + }[]; +} diff --git a/apps/api/src/app/invites/usecases/bulk-invite/bulk-invite.usecase.ts b/apps/api/src/app/invites/usecases/bulk-invite/bulk-invite.usecase.ts new file mode 100644 index 00000000000..aceafba8dd1 --- /dev/null +++ b/apps/api/src/app/invites/usecases/bulk-invite/bulk-invite.usecase.ts @@ -0,0 +1,59 @@ +import * as Sentry from '@sentry/node'; +import { Injectable, Logger, Scope } from '@nestjs/common'; +import { MemberRoleEnum } from '@notifire/shared'; +import { InviteMemberCommand } from '../invite-member/invite-member.command'; +import { InviteMember } from '../invite-member/invite-member.usecase'; +import { BulkInviteCommand } from './bulk-invite.command'; + +interface IBulkInviteResponse { + success: boolean; + email: string; + failReason?: string; +} + +@Injectable({ + scope: Scope.REQUEST, +}) +export class BulkInvite { + constructor(private inviteMemberUsecase: InviteMember) {} + + async execute(command: BulkInviteCommand): Promise { + const invites: IBulkInviteResponse[] = []; + + for (const invitee of command.invitees) { + try { + await this.inviteMemberUsecase.execute( + InviteMemberCommand.create({ + email: invitee.email, + role: invitee.role || MemberRoleEnum.MEMBER, + organizationId: command.organizationId, + userId: command.userId, + }) + ); + + invites.push({ + success: true, + email: invitee.email, + }); + } catch (e) { + if (e.message.includes('Already invited')) { + invites.push({ + failReason: 'Already invited', + success: false, + email: invitee.email, + }); + } else { + Logger.error(e); + Sentry.captureException(e); + invites.push({ + failReason: null, + success: false, + email: invitee.email, + }); + } + } + } + + return invites; + } +} diff --git a/apps/api/src/app/invites/usecases/get-invite/get-invite.command.ts b/apps/api/src/app/invites/usecases/get-invite/get-invite.command.ts new file mode 100644 index 00000000000..705bd788d6c --- /dev/null +++ b/apps/api/src/app/invites/usecases/get-invite/get-invite.command.ts @@ -0,0 +1,11 @@ +import { IsNotEmpty } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; + +export class GetInviteCommand { + static create(data: GetInviteCommand) { + return CommandHelper.create(GetInviteCommand, data); + } + + @IsNotEmpty() + readonly token: string; +} diff --git a/apps/api/src/app/invites/usecases/get-invite/get-invite.usecase.ts b/apps/api/src/app/invites/usecases/get-invite/get-invite.usecase.ts new file mode 100644 index 00000000000..2bb626e7432 --- /dev/null +++ b/apps/api/src/app/invites/usecases/get-invite/get-invite.usecase.ts @@ -0,0 +1,44 @@ +import { Injectable, Scope } from '@nestjs/common'; +import { OrganizationRepository, UserRepository, MemberRepository } from '@notifire/dal'; +import { MemberStatusEnum } from '@notifire/shared'; +import { ApiException } from '../../../shared/exceptions/api.exception'; +import { GetInviteCommand } from './get-invite.command'; + +@Injectable({ + scope: Scope.REQUEST, +}) +export class GetInvite { + constructor( + private organizationRepository: OrganizationRepository, + private memberRepository: MemberRepository, + private userRepository: UserRepository + ) {} + + async execute(command: GetInviteCommand) { + const member = await this.memberRepository.findByInviteToken(command.token); + if (!member) throw new ApiException('No invite found'); + const organization = await this.organizationRepository.findById(member._organizationId); + const invitedMember = member; + + if (invitedMember.memberStatus !== MemberStatusEnum.INVITED) { + throw new ApiException('Invite token expired'); + } + + const user = await this.userRepository.findById(invitedMember.invite._inviterId); + + return { + inviter: { + _id: user._id, + firstName: user.firstName, + lastName: user.lastName, + profilePicture: user.profilePicture, + }, + organization: { + _id: organization._id, + name: organization.name, + logo: organization.logo, + }, + email: member.invite.email, + }; + } +} diff --git a/apps/api/src/app/invites/usecases/index.ts b/apps/api/src/app/invites/usecases/index.ts new file mode 100644 index 00000000000..ca12832c09f --- /dev/null +++ b/apps/api/src/app/invites/usecases/index.ts @@ -0,0 +1,6 @@ +import { AcceptInvite } from './accept-invite/accept-invite.usecase'; +import { GetInvite } from './get-invite/get-invite.usecase'; +import { BulkInvite } from './bulk-invite/bulk-invite.usecase'; +import { InviteMember } from './invite-member/invite-member.usecase'; + +export const USE_CASES = [AcceptInvite, GetInvite, BulkInvite, InviteMember]; diff --git a/apps/api/src/app/invites/usecases/invite-member/invite-member.command.ts b/apps/api/src/app/invites/usecases/invite-member/invite-member.command.ts new file mode 100644 index 00000000000..350f41bbcfe --- /dev/null +++ b/apps/api/src/app/invites/usecases/invite-member/invite-member.command.ts @@ -0,0 +1,17 @@ +import { IsDefined, IsEmail, IsString, IsEnum } from 'class-validator'; +import { MemberRoleEnum } from '@notifire/shared'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { OrganizationCommand } from '../../../shared/commands/organization.command'; + +export class InviteMemberCommand extends OrganizationCommand { + static create(data: InviteMemberCommand) { + return CommandHelper.create(InviteMemberCommand, data); + } + + @IsEmail() + readonly email: string; + + @IsDefined() + @IsEnum(MemberRoleEnum) + readonly role: MemberRoleEnum; +} diff --git a/apps/api/src/app/invites/usecases/invite-member/invite-member.usecase.ts b/apps/api/src/app/invites/usecases/invite-member/invite-member.usecase.ts new file mode 100644 index 00000000000..bd94ec8b55c --- /dev/null +++ b/apps/api/src/app/invites/usecases/invite-member/invite-member.usecase.ts @@ -0,0 +1,56 @@ +import { Injectable, Scope } from '@nestjs/common'; +import { OrganizationRepository, UserRepository, MemberRepository } from '@notifire/dal'; +import { MemberRoleEnum, MemberStatusEnum } from '@notifire/shared'; +import { Notifire } from '@notifire/node'; +import { ApiException } from '../../../shared/exceptions/api.exception'; +import { InviteMemberCommand } from './invite-member.command'; +import { MailService } from '../../../shared/services/mail/mail.service'; +import { capitalize, createGuid } from '../../../shared/services/helper/helper.service'; + +@Injectable({ + scope: Scope.REQUEST, +}) +export class InviteMember { + constructor( + private organizationRepository: OrganizationRepository, + private mailService: MailService, + private userRepository: UserRepository, + private memberRepository: MemberRepository + ) {} + + async execute(command: InviteMemberCommand) { + const organization = await this.organizationRepository.findById(command.organizationId); + if (!organization) throw new ApiException('No organization found'); + + const foundInvitee = await this.memberRepository.findInviteeByEmail(organization._id, command.email); + + if (foundInvitee) throw new ApiException('Already invited'); + + const inviterUser = await this.userRepository.findById(command.userId); + + const token = createGuid(); + + if (process.env.NODE_ENV === 'dev' || process.env.NODE_ENV === 'prod') { + const notifire = new Notifire(process.env.NOTIFIRE_API_KEY); + await notifire.trigger('invite-to-organization-qUE8d-GRq', { + $user_id: command.email, + $email: command.email, + inviteeName: capitalize(command.email.split('@')[0]), + organizationName: capitalize(organization.name), + inviterName: capitalize(inviterUser.firstName), + acceptInviteUrl: `${process.env.FRONT_BASE_URL}/auth/invitation/${token}`, + }); + } + + await this.memberRepository.addMember(organization._id, { + roles: [command.role], + memberStatus: MemberStatusEnum.INVITED, + invite: { + token, + _inviterId: command.userId, + email: command.email, + invitationDate: new Date(), + }, + }); + } +} diff --git a/apps/api/src/app/logs/logs.controller.ts b/apps/api/src/app/logs/logs.controller.ts new file mode 100644 index 00000000000..52ebf0f1c44 --- /dev/null +++ b/apps/api/src/app/logs/logs.controller.ts @@ -0,0 +1,4 @@ +import { Controller } from '@nestjs/common'; + +@Controller('/logs') +export class LogsController {} diff --git a/apps/api/src/app/logs/logs.module.ts b/apps/api/src/app/logs/logs.module.ts new file mode 100644 index 00000000000..e3cac9adc07 --- /dev/null +++ b/apps/api/src/app/logs/logs.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; +import { USE_CASES } from './usecases'; +import { LogsController } from './logs.controller'; +import { SharedModule } from '../shared/shared.module'; + +@Module({ + imports: [SharedModule], + providers: [...USE_CASES], + exports: [...USE_CASES], + controllers: [LogsController], +}) +export class LogsModule {} diff --git a/apps/api/src/app/logs/usecases/create-log/create-log.command.ts b/apps/api/src/app/logs/usecases/create-log/create-log.command.ts new file mode 100644 index 00000000000..4a202bed2b6 --- /dev/null +++ b/apps/api/src/app/logs/usecases/create-log/create-log.command.ts @@ -0,0 +1,44 @@ +import { IsDefined, IsEnum, IsMongoId, IsOptional, IsString, IsUUID } from 'class-validator'; +import { LogCodeEnum, LogStatusEnum } from '@notifire/shared'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; + +export class CreateLogCommand extends ApplicationWithUserCommand { + static create(data: CreateLogCommand) { + return CommandHelper.create(CreateLogCommand, data); + } + + @IsDefined() + @IsUUID() + transactionId: string; + + @IsOptional() + @IsMongoId() + notificationId?: string; + + @IsOptional() + @IsMongoId() + messageId?: string; + + @IsOptional() + @IsMongoId() + templateId?: string; + + @IsOptional() + @IsMongoId() + subscriberId?: string; + + @IsOptional() + @IsEnum(LogStatusEnum) + status: LogStatusEnum; + + @IsString() + text: string; + + @IsOptional() + @IsEnum(LogCodeEnum) + code?: LogCodeEnum; + + @IsOptional() + raw?: any; +} diff --git a/apps/api/src/app/logs/usecases/create-log/create-log.usecase.ts b/apps/api/src/app/logs/usecases/create-log/create-log.usecase.ts new file mode 100644 index 00000000000..f7bd9d036b2 --- /dev/null +++ b/apps/api/src/app/logs/usecases/create-log/create-log.usecase.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@nestjs/common'; +import { LogEntity, LogRepository } from '@notifire/dal'; +import { CreateLogCommand } from './create-log.command'; + +@Injectable() +export class CreateLog { + constructor(private logRepository: LogRepository) {} + + async execute(command: CreateLogCommand): Promise { + let rawData: string = null; + if (command.raw) { + try { + rawData = JSON.stringify(command.raw); + // eslint-disable-next-line no-empty + } catch (e) {} + } + + // + return await this.logRepository.create({ + _applicationId: command.applicationId, + transactionId: command.transactionId, + _organizationId: command.organizationId, + _notificationId: command.notificationId, + _messageId: command.messageId, + _subscriberId: command.subscriberId, + status: command.status, + text: command.text, + code: command.code, + raw: rawData, + }); + } +} diff --git a/apps/api/src/app/logs/usecases/index.ts b/apps/api/src/app/logs/usecases/index.ts new file mode 100644 index 00000000000..c07812e566b --- /dev/null +++ b/apps/api/src/app/logs/usecases/index.ts @@ -0,0 +1,6 @@ +import { CreateLog } from './create-log/create-log.usecase'; + +export const USE_CASES = [ + CreateLog, + // +]; diff --git a/apps/api/src/app/message-template/message-template.controller.ts b/apps/api/src/app/message-template/message-template.controller.ts new file mode 100644 index 00000000000..f8f2091fd88 --- /dev/null +++ b/apps/api/src/app/message-template/message-template.controller.ts @@ -0,0 +1,4 @@ +import { Controller } from '@nestjs/common'; + +@Controller('/message-templates') +export class MessageTemplateController {} diff --git a/apps/api/src/app/message-template/message-template.module.ts b/apps/api/src/app/message-template/message-template.module.ts new file mode 100644 index 00000000000..f04c75a30e8 --- /dev/null +++ b/apps/api/src/app/message-template/message-template.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; +import { USE_CASES } from './usecases'; +import { MessageTemplateController } from './message-template.controller'; +import { SharedModule } from '../shared/shared.module'; + +@Module({ + imports: [SharedModule], + providers: [...USE_CASES], + exports: [...USE_CASES], + controllers: [MessageTemplateController], +}) +export class MessageTemplateModule {} diff --git a/apps/api/src/app/message-template/shared/sanitizer.service.spec.ts b/apps/api/src/app/message-template/shared/sanitizer.service.spec.ts new file mode 100644 index 00000000000..947cddf6021 --- /dev/null +++ b/apps/api/src/app/message-template/shared/sanitizer.service.spec.ts @@ -0,0 +1,27 @@ +import { expect } from 'chai'; +import { sanitizeHTML, sanitizeMessageContent } from './sanitizer.service'; + +describe('HTML Sanitizer', function () { + it('should sanitize bad html', function () { + const sanitizedHtml = sanitizeHTML('hello bold '); + expect(sanitizedHtml).to.equal('hello bold '); + }); + + it('should sanitized message text content', function () { + const result = sanitizeMessageContent('hello bold '); + expect(result).to.equal('hello bold '); + }); + + it('should sanitized message email block content', function () { + const result = sanitizeMessageContent([ + { + subject: 'subject', + type: 'text', + content: 'hello bold ', + url: '', + }, + ]); + expect(result[0].content).to.equal('hello bold '); + expect(result[0].subject).to.equal('subject'); + }); +}); diff --git a/apps/api/src/app/message-template/shared/sanitizer.service.ts b/apps/api/src/app/message-template/shared/sanitizer.service.ts new file mode 100644 index 00000000000..341ff082eab --- /dev/null +++ b/apps/api/src/app/message-template/shared/sanitizer.service.ts @@ -0,0 +1,26 @@ +import * as sanitize from 'sanitize-html'; +import { IEmailBlock } from '@notifire/shared'; + +export function sanitizeHTML(html: string) { + if (!html) return html; + + return sanitize(html); +} + +export function sanitizeMessageContent(content: string | IEmailBlock[]) { + if (typeof content === 'string') { + return sanitizeHTML(content); + } + + if (Array.isArray(content)) { + return content.map((i) => { + return { + ...i, + subject: sanitizeHTML(i.subject), + content: sanitizeHTML(i.content), + }; + }); + } + + return content; +} diff --git a/apps/api/src/app/message-template/usecases/create-message-template/create-message-template.command.ts b/apps/api/src/app/message-template/usecases/create-message-template/create-message-template.command.ts new file mode 100644 index 00000000000..1110f5b3106 --- /dev/null +++ b/apps/api/src/app/message-template/usecases/create-message-template/create-message-template.command.ts @@ -0,0 +1,31 @@ +import { IsDefined, IsEnum, IsOptional, IsString, ValidateNested } from 'class-validator'; +import { ChannelTypeEnum, IEmailBlock } from '@notifire/shared'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; +import { ChannelCTADto } from '../../../notification-template/dto/create-notification-template.dto'; + +export class CreateMessageTemplateCommand extends ApplicationWithUserCommand { + static create(data: CreateMessageTemplateCommand) { + return CommandHelper.create(CreateMessageTemplateCommand, data); + } + + @IsDefined() + @IsEnum(ChannelTypeEnum) + type: ChannelTypeEnum; + + @IsOptional() + name?: string; + + @IsOptional() + subject?: string; + + @IsDefined() + content: string | IEmailBlock[]; + + @IsOptional() + contentType: 'editor' | 'customHtml'; + + @IsOptional() + @ValidateNested() + cta: ChannelCTADto; +} diff --git a/apps/api/src/app/message-template/usecases/create-message-template/create-message-template.usecase.ts b/apps/api/src/app/message-template/usecases/create-message-template/create-message-template.usecase.ts new file mode 100644 index 00000000000..0ca30f55f28 --- /dev/null +++ b/apps/api/src/app/message-template/usecases/create-message-template/create-message-template.usecase.ts @@ -0,0 +1,23 @@ +import { Injectable } from '@nestjs/common'; +import { MessageTemplateEntity, MessageTemplateRepository } from '@notifire/dal'; +import { CreateMessageTemplateCommand } from './create-message-template.command'; +import { sanitizeMessageContent } from '../../shared/sanitizer.service'; + +@Injectable() +export class CreateMessageTemplate { + constructor(private messageTemplateRepository: MessageTemplateRepository) {} + + async execute(command: CreateMessageTemplateCommand): Promise { + return await this.messageTemplateRepository.create({ + cta: command.cta, + name: command.name, + content: command.contentType === 'editor' ? sanitizeMessageContent(command.content) : command.content, + contentType: command.contentType, + subject: command.subject, + type: command.type, + _organizationId: command.organizationId, + _applicationId: command.applicationId, + _creatorId: command.userId, + }); + } +} diff --git a/apps/api/src/app/message-template/usecases/index.ts b/apps/api/src/app/message-template/usecases/index.ts new file mode 100644 index 00000000000..d3ffab0c2cd --- /dev/null +++ b/apps/api/src/app/message-template/usecases/index.ts @@ -0,0 +1,8 @@ +import { UpdateMessageTemplate } from './update-message-template/update-message-template.usecase'; +import { CreateMessageTemplate } from './create-message-template/create-message-template.usecase'; + +export const USE_CASES = [ + UpdateMessageTemplate, + CreateMessageTemplate, + // +]; diff --git a/apps/api/src/app/message-template/usecases/update-message-template/update-message-template.command.ts b/apps/api/src/app/message-template/usecases/update-message-template/update-message-template.command.ts new file mode 100644 index 00000000000..494699d1b7e --- /dev/null +++ b/apps/api/src/app/message-template/usecases/update-message-template/update-message-template.command.ts @@ -0,0 +1,35 @@ +import { IsDefined, IsEnum, IsMongoId, IsOptional, ValidateNested } from 'class-validator'; +import { ChannelTypeEnum, IEmailBlock } from '@notifire/shared'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; +import { ChannelCTADto } from '../../../notification-template/dto/create-notification-template.dto'; + +export class UpdateMessageTemplateCommand extends ApplicationWithUserCommand { + static create(data: UpdateMessageTemplateCommand) { + return CommandHelper.create(UpdateMessageTemplateCommand, data); + } + + @IsDefined() + @IsMongoId() + templateId: string; + + @IsOptional() + @IsEnum(ChannelTypeEnum) + type: ChannelTypeEnum; + + @IsOptional() + name?: string; + + @IsOptional() + subject?: string; + + @IsOptional() + content: string | IEmailBlock[]; + + @IsOptional() + contentType: 'editor' | 'customHtml'; + + @IsOptional() + @ValidateNested() + cta: ChannelCTADto; +} diff --git a/apps/api/src/app/message-template/usecases/update-message-template/update-message-template.usecase.ts b/apps/api/src/app/message-template/usecases/update-message-template/update-message-template.usecase.ts new file mode 100644 index 00000000000..c102aa5a7d3 --- /dev/null +++ b/apps/api/src/app/message-template/usecases/update-message-template/update-message-template.usecase.ts @@ -0,0 +1,48 @@ +import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'; +import { MessageTemplateEntity, MessageTemplateRepository } from '@notifire/dal'; +import { UpdateMessageTemplateCommand } from './update-message-template.command'; +import { sanitizeMessageContent } from '../../shared/sanitizer.service'; + +@Injectable() +export class UpdateMessageTemplate { + constructor(private messageTemplateRepository: MessageTemplateRepository) {} + + async execute(command: UpdateMessageTemplateCommand): Promise { + const existingTemplate = await this.messageTemplateRepository.findById(command.templateId); + if (!existingTemplate) throw new NotFoundException(`Entity with id ${command.templateId} not found`); + + const updatePayload: Partial = {}; + if (command.name) { + updatePayload.name = command.name; + } + + if (command.content) { + updatePayload.content = + command.contentType === 'editor' ? sanitizeMessageContent(command.content) : command.content; + } + + if (command.cta) { + updatePayload.cta = command.cta; + } + + if (command.subject) { + updatePayload.subject = command.subject; + } + + if (!Object.keys(updatePayload).length) { + throw new BadRequestException('No properties found for update'); + } + + await this.messageTemplateRepository.update( + { + _id: command.templateId, + _organizationId: command.organizationId, + }, + { + $set: updatePayload, + } + ); + + return await this.messageTemplateRepository.findById(command.templateId); + } +} diff --git a/apps/api/src/app/notification-groups/dto/create-notification-group.dto.ts b/apps/api/src/app/notification-groups/dto/create-notification-group.dto.ts new file mode 100644 index 00000000000..92ff457ea72 --- /dev/null +++ b/apps/api/src/app/notification-groups/dto/create-notification-group.dto.ts @@ -0,0 +1,7 @@ +import { IsArray, IsDefined, IsOptional, IsString, MaxLength, ValidateNested } from 'class-validator'; + +export class CreateNotificationGroupDto { + @IsString() + @IsDefined() + name: string; +} diff --git a/apps/api/src/app/notification-groups/e2e/create-notification-group.e2e.ts b/apps/api/src/app/notification-groups/e2e/create-notification-group.e2e.ts new file mode 100644 index 00000000000..e6be30b6472 --- /dev/null +++ b/apps/api/src/app/notification-groups/e2e/create-notification-group.e2e.ts @@ -0,0 +1,22 @@ +import { expect } from 'chai'; +import { UserSession } from '@notifire/testing'; + +describe('Create Notification Group - /notification-groups (POST)', async () => { + let session: UserSession; + before(async () => { + session = new UserSession(); + await session.initialize(); + }); + + it('should create notification group', async function () { + const testTemplate = { + name: 'Test name', + }; + + const { body } = await session.testAgent.post(`/v1/notification-groups`).send(testTemplate); + expect(body.data).to.be.ok; + const group = body.data; + expect(group.name).to.equal(`Test name`); + expect(group._applicationId).to.equal(session.application._id); + }); +}); diff --git a/apps/api/src/app/notification-groups/e2e/get-notification-groups.e2e.ts b/apps/api/src/app/notification-groups/e2e/get-notification-groups.e2e.ts new file mode 100644 index 00000000000..e80ebe371b1 --- /dev/null +++ b/apps/api/src/app/notification-groups/e2e/get-notification-groups.e2e.ts @@ -0,0 +1,33 @@ +import { expect } from 'chai'; +import { UserSession } from '@notifire/testing'; + +describe('Get Notification Groups - /notification-groups (GET)', async () => { + let session: UserSession; + beforeEach(async () => { + session = new UserSession(); + await session.initialize(); + }); + + it('should get all notification groups', async function () { + await session.testAgent.post(`/v1/notification-groups`).send({ + name: 'Test name', + }); + await session.testAgent.post(`/v1/notification-groups`).send({ + name: 'Test name 2', + }); + + const { body } = await session.testAgent.get(`/v1/notification-groups`); + expect(body.data.length).to.equal(3); + const group = body.data.find((i) => i.name === 'Test name'); + expect(group.name).to.equal(`Test name`); + expect(group._applicationId).to.equal(session.application._id); + }); + + it('should create a default group when fetching', async function () { + const { body } = await session.testAgent.get(`/v1/notification-groups`); + expect(body.data.length).to.equal(1); + + const group = body.data[0]; + expect(group.name).to.equal(`General`); + }); +}); diff --git a/apps/api/src/app/notification-groups/notification-groups.controller.ts b/apps/api/src/app/notification-groups/notification-groups.controller.ts new file mode 100644 index 00000000000..686c34d86f6 --- /dev/null +++ b/apps/api/src/app/notification-groups/notification-groups.controller.ts @@ -0,0 +1,45 @@ +import { Body, ClassSerializerInterceptor, Controller, Get, Post, UseGuards, UseInterceptors } from '@nestjs/common'; +import { IJwtPayload, MemberRoleEnum } from '@notifire/shared'; +import { CreateNotificationGroup } from './usecases/create-notification-group/create-notification-group.usecase'; +import { Roles } from '../auth/framework/roles.decorator'; +import { UserSession } from '../shared/framework/user.decorator'; +import { CreateNotificationGroupCommand } from './usecases/create-notification-group/create-notification-group.command'; +import { CreateNotificationGroupDto } from './dto/create-notification-group.dto'; +import { JwtAuthGuard } from '../auth/framework/auth.guard'; +import { GetNotificationGroups } from './usecases/get-notification-groups/get-notification-groups.usecase'; +import { GetNotificationGroupsCommand } from './usecases/get-notification-groups/get-notification-groups.command'; + +@Controller('/notification-groups') +@UseInterceptors(ClassSerializerInterceptor) +@UseGuards(JwtAuthGuard) +export class NotificationGroupsController { + constructor( + private createNotificationGroupUsecase: CreateNotificationGroup, + private getNotificationGroupsUsecase: GetNotificationGroups + ) {} + + @Post('') + @Roles(MemberRoleEnum.ADMIN) + createNotificationGroup(@UserSession() user: IJwtPayload, @Body() body: CreateNotificationGroupDto) { + return this.createNotificationGroupUsecase.execute( + CreateNotificationGroupCommand.create({ + organizationId: user.organizationId, + userId: user._id, + applicationId: user.applicationId, + name: body.name, + }) + ); + } + + @Get('') + @Roles(MemberRoleEnum.ADMIN) + getNotificationGroups(@UserSession() user: IJwtPayload) { + return this.getNotificationGroupsUsecase.execute( + GetNotificationGroupsCommand.create({ + organizationId: user.organizationId, + userId: user._id, + applicationId: user.applicationId, + }) + ); + } +} diff --git a/apps/api/src/app/notification-groups/notification-groups.module.ts b/apps/api/src/app/notification-groups/notification-groups.module.ts new file mode 100644 index 00000000000..fee1513dcff --- /dev/null +++ b/apps/api/src/app/notification-groups/notification-groups.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { USE_CASES } from './usecases'; +import { NotificationGroupsController } from './notification-groups.controller'; +import { SharedModule } from '../shared/shared.module'; + +@Module({ + imports: [SharedModule], + providers: [...USE_CASES], + controllers: [NotificationGroupsController], +}) +export class NotificationGroupsModule {} diff --git a/apps/api/src/app/notification-groups/usecases/create-notification-group/create-notification-group.command.ts b/apps/api/src/app/notification-groups/usecases/create-notification-group/create-notification-group.command.ts new file mode 100644 index 00000000000..0be9870a4a7 --- /dev/null +++ b/apps/api/src/app/notification-groups/usecases/create-notification-group/create-notification-group.command.ts @@ -0,0 +1,12 @@ +import { IsString } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; + +export class CreateNotificationGroupCommand extends ApplicationWithUserCommand { + static create(data: CreateNotificationGroupCommand) { + return CommandHelper.create(CreateNotificationGroupCommand, data); + } + + @IsString() + name: string; +} diff --git a/apps/api/src/app/notification-groups/usecases/create-notification-group/create-notification-group.usecase.ts b/apps/api/src/app/notification-groups/usecases/create-notification-group/create-notification-group.usecase.ts new file mode 100644 index 00000000000..ed95c714e06 --- /dev/null +++ b/apps/api/src/app/notification-groups/usecases/create-notification-group/create-notification-group.usecase.ts @@ -0,0 +1,16 @@ +import { Injectable } from '@nestjs/common'; +import { NotificationGroupRepository, NotificationGroupEntity } from '@notifire/dal'; +import { CreateNotificationGroupCommand } from './create-notification-group.command'; + +@Injectable() +export class CreateNotificationGroup { + constructor(private notificationGroupRepository: NotificationGroupRepository) {} + + async execute(command: CreateNotificationGroupCommand): Promise { + return await this.notificationGroupRepository.create({ + _applicationId: command.applicationId, + _organizationId: command.organizationId, + name: command.name, + }); + } +} diff --git a/apps/api/src/app/notification-groups/usecases/get-notification-groups/get-notification-groups.command.ts b/apps/api/src/app/notification-groups/usecases/get-notification-groups/get-notification-groups.command.ts new file mode 100644 index 00000000000..ec7afbc4519 --- /dev/null +++ b/apps/api/src/app/notification-groups/usecases/get-notification-groups/get-notification-groups.command.ts @@ -0,0 +1,8 @@ +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; + +export class GetNotificationGroupsCommand extends ApplicationWithUserCommand { + static create(data: GetNotificationGroupsCommand) { + return CommandHelper.create(GetNotificationGroupsCommand, data); + } +} diff --git a/apps/api/src/app/notification-groups/usecases/get-notification-groups/get-notification-groups.usecase.ts b/apps/api/src/app/notification-groups/usecases/get-notification-groups/get-notification-groups.usecase.ts new file mode 100644 index 00000000000..4c38fe8b763 --- /dev/null +++ b/apps/api/src/app/notification-groups/usecases/get-notification-groups/get-notification-groups.usecase.ts @@ -0,0 +1,34 @@ +import { Injectable } from '@nestjs/common'; +import { NotificationGroupRepository, NotificationGroupEntity } from '@notifire/dal'; +import { GetNotificationGroupsCommand } from './get-notification-groups.command'; +import { CreateNotificationGroup } from '../create-notification-group/create-notification-group.usecase'; +import { CreateNotificationGroupCommand } from '../create-notification-group/create-notification-group.command'; + +@Injectable() +export class GetNotificationGroups { + constructor( + private notificationGroupRepository: NotificationGroupRepository, + private createNotificationGroup: CreateNotificationGroup + ) {} + + async execute(command: GetNotificationGroupsCommand): Promise { + const groups = await this.notificationGroupRepository.find({ + _applicationId: command.applicationId, + }); + + if (!groups.length) { + await this.createNotificationGroup.execute( + CreateNotificationGroupCommand.create({ + organizationId: command.organizationId, + applicationId: command.applicationId, + userId: command.userId, + name: 'General', + }) + ); + } + + return await this.notificationGroupRepository.find({ + _applicationId: command.applicationId, + }); + } +} diff --git a/apps/api/src/app/notification-groups/usecases/index.ts b/apps/api/src/app/notification-groups/usecases/index.ts new file mode 100644 index 00000000000..a9e60b2dd3f --- /dev/null +++ b/apps/api/src/app/notification-groups/usecases/index.ts @@ -0,0 +1,8 @@ +import { GetNotificationGroups } from './get-notification-groups/get-notification-groups.usecase'; +import { CreateNotificationGroup } from './create-notification-group/create-notification-group.usecase'; + +export const USE_CASES = [ + GetNotificationGroups, + CreateNotificationGroup, + // +]; diff --git a/apps/api/src/app/notification-template/dto/change-template-status.dto.ts b/apps/api/src/app/notification-template/dto/change-template-status.dto.ts new file mode 100644 index 00000000000..388108c1a22 --- /dev/null +++ b/apps/api/src/app/notification-template/dto/change-template-status.dto.ts @@ -0,0 +1,7 @@ +import { IsBoolean, IsDefined } from 'class-validator'; + +export class ChangeTemplateStatusDto { + @IsDefined() + @IsBoolean() + active: boolean; +} diff --git a/apps/api/src/app/notification-template/dto/create-notification-template.dto.ts b/apps/api/src/app/notification-template/dto/create-notification-template.dto.ts new file mode 100644 index 00000000000..bfd72b62aba --- /dev/null +++ b/apps/api/src/app/notification-template/dto/create-notification-template.dto.ts @@ -0,0 +1,89 @@ +import { IsArray, IsDefined, IsEnum, IsOptional, IsString, MaxLength, ValidateNested } from 'class-validator'; +import { + BuilderFieldOperator, + BuilderFieldType, + BuilderGroupValues, + ChannelCTATypeEnum, + ChannelTypeEnum, + ICreateNotificationTemplateDto, + IEmailBlock, +} from '@notifire/shared'; + +export class ChannelCTADto { + @IsEnum(ChannelCTATypeEnum) + type: ChannelCTATypeEnum; + + data: { + url: string; + }; +} + +export class NotificationChannelDto { + @IsDefined() + @IsEnum(ChannelTypeEnum) + type: ChannelTypeEnum; + + @IsOptional() + @IsString() + subject?: string; + + @IsOptional() + name?: string; + + @IsDefined() + content: string | IEmailBlock[]; + + @IsOptional() + contentType?: 'editor' | 'customHtml'; + + @ValidateNested() + cta?: ChannelCTADto; + + @IsArray() + @ValidateNested() + @IsOptional() + filters?: MessageFilter[]; +} + +export class MessageFilter { + isNegated: boolean; + + @IsString() + type: BuilderFieldType; + + @IsString() + value: BuilderGroupValues; + + @IsArray() + children: { + field: string; + value: string; + operator: BuilderFieldOperator; + }[]; +} + +export class CreateNotificationTemplateDto implements ICreateNotificationTemplateDto { + @IsString() + @IsDefined() + name: string; + + @IsString() + @IsDefined({ + message: 'Notification group must be provided', + }) + notificationGroupId: string; + + @IsOptional() + @IsArray() + tags: string[]; + + @IsString() + @IsOptional() + @MaxLength(100) + description: string; + + @IsDefined() + @IsArray() + @ValidateNested() + messages: NotificationChannelDto[]; +} diff --git a/apps/api/src/app/notification-template/dto/update-notification-template.dto.ts b/apps/api/src/app/notification-template/dto/update-notification-template.dto.ts new file mode 100644 index 00000000000..96b9e8a1b9a --- /dev/null +++ b/apps/api/src/app/notification-template/dto/update-notification-template.dto.ts @@ -0,0 +1,58 @@ +import { + IsArray, + IsDefined, + IsEnum, + IsMongoId, + IsOptional, + IsString, + MaxLength, + ValidateNested, +} from 'class-validator'; +import { ChannelCTATypeEnum, ChannelTypeEnum, ICreateNotificationTemplateDto } from '@notifire/shared'; + +export class ChannelCTADto { + @IsEnum(ChannelCTATypeEnum) + type: ChannelCTATypeEnum; + + data: { + url: string; + }; +} + +export class NotificationChannelDto { + @IsDefined() + @IsEnum(ChannelTypeEnum) + type: ChannelTypeEnum; + + @IsString() + @IsDefined() + content: string; + + @IsDefined() + @ValidateNested() + cta: ChannelCTADto; +} + +export class UpdateNotificationTemplateDto implements ICreateNotificationTemplateDto { + @IsString() + @IsOptional() + name: string; + + @IsArray() + @IsOptional() + tags: string[]; + + @IsString() + @IsOptional() + @MaxLength(100) + description: string; + + @IsArray() + @IsOptional() + @ValidateNested() + messages: NotificationChannelDto[]; + + @IsOptional() + @IsMongoId() + notificationGroupId: string; +} diff --git a/apps/api/src/app/notification-template/e2e/change-template-status.e2e.ts b/apps/api/src/app/notification-template/e2e/change-template-status.e2e.ts new file mode 100644 index 00000000000..2e5336d20a9 --- /dev/null +++ b/apps/api/src/app/notification-template/e2e/change-template-status.e2e.ts @@ -0,0 +1,33 @@ +import { expect } from 'chai'; +import { NotificationTemplateRepository } from '@notifire/dal'; +import { UserSession, NotificationTemplateService } from '@notifire/testing'; + +describe('Change template status by id - /notification-templates/:templateId/status (PUT)', async () => { + let session: UserSession; + const notificationTemplateRepository = new NotificationTemplateRepository(); + before(async () => { + session = new UserSession(); + await session.initialize(); + }); + + it('should change the status from active false to active true', async function () { + const notificationTemplateService = new NotificationTemplateService( + session.user._id, + session.organization._id, + session.application._id + ); + const template = await notificationTemplateService.createTemplate({ + active: false, + draft: true, + }); + const beforeChange = await notificationTemplateRepository.findById(template._id, template._organizationId); + expect(beforeChange.active).to.equal(false); + expect(beforeChange.draft).to.equal(true); + const { body } = await session.testAgent.put(`/v1/notification-templates/${template._id}/status`).send({ + active: true, + }); + const found = await notificationTemplateRepository.findById(template._id, template._organizationId); + expect(found.active).to.equal(true); + expect(found.draft).to.equal(false); + }); +}); diff --git a/apps/api/src/app/notification-template/e2e/create-notification-templates.e2e.ts b/apps/api/src/app/notification-template/e2e/create-notification-templates.e2e.ts new file mode 100644 index 00000000000..c7843d93818 --- /dev/null +++ b/apps/api/src/app/notification-template/e2e/create-notification-templates.e2e.ts @@ -0,0 +1,137 @@ +import { expect } from 'chai'; +import { UserSession } from '@notifire/testing'; +import { ChannelCTATypeEnum, ChannelTypeEnum, INotificationTemplate, TriggerTypeEnum } from '@notifire/shared'; +import * as moment from 'moment'; +import { CreateNotificationTemplateDto } from '../dto/create-notification-template.dto'; + +describe('Create Notification template - /notification-templates (POST)', async () => { + let session: UserSession; + before(async () => { + session = new UserSession(); + await session.initialize(); + }); + + it('should create email template', async function () { + const testTemplate: Partial = { + name: 'test email template', + description: 'This is a test description', + tags: ['test-tag'], + notificationGroupId: session.notificationGroups[0]._id, + messages: [ + { + name: 'Message Name', + subject: 'Test email subject', + type: ChannelTypeEnum.EMAIL, + filters: [ + { + isNegated: false, + type: 'GROUP', + value: 'AND', + children: [ + { + field: 'firstName', + value: 'test value', + operator: 'EQUAL', + }, + ], + }, + ], + content: [ + { + type: 'text', + content: 'This is a sample text block', + }, + ], + }, + ], + }; + + const { body } = await session.testAgent.post(`/v1/notification-templates`).send(testTemplate); + expect(body.data).to.be.ok; + const template: INotificationTemplate = body.data; + + expect(template._notificationGroupId).to.equal(testTemplate.notificationGroupId); + const message = template.messages[0]; + expect(message.template.name).to.equal(`${testTemplate.messages[0].name}`); + expect(message.template.subject).to.equal(`${testTemplate.messages[0].subject}`); + expect(message.filters[0].type).to.equal(testTemplate.messages[0].filters[0].type); + expect(message.filters[0].children.length).to.equal(testTemplate.messages[0].filters[0].children.length); + + expect(message.filters[0].children[0].value).to.equal(testTemplate.messages[0].filters[0].children[0].value); + + expect(message.filters[0].children[0].operator).to.equal(testTemplate.messages[0].filters[0].children[0].operator); + + expect(message.template.type).to.equal(ChannelTypeEnum.EMAIL); + expect(template.tags[0]).to.equal('test-tag'); + if (Array.isArray(message.template.content) && Array.isArray(testTemplate.messages[0].content)) { + expect(message.template.content[0].type).to.equal(testTemplate.messages[0].content[0].type); + } else { + throw new Error('content must be an array'); + } + }); + + it('should create a valid notification', async () => { + const testTemplate: Partial = { + name: 'test template', + description: 'This is a test description', + notificationGroupId: session.notificationGroups[0]._id, + messages: [ + { + type: ChannelTypeEnum.IN_APP, + content: 'Test Template', + cta: { + type: ChannelCTATypeEnum.REDIRECT, + data: { + url: 'https://example.org/profile', + }, + }, + }, + ], + }; + const { body } = await session.testAgent.post(`/v1/notification-templates`).send(testTemplate); + + expect(body.data).to.be.ok; + + const template: INotificationTemplate = body.data; + expect(template._id).to.be.ok; + expect(template.description).to.equal(testTemplate.description); + expect(template.name).to.equal(testTemplate.name); + expect(template.draft).to.equal(true); + expect(template.active).to.equal(false); + expect(moment(template.createdAt).isSame(moment(), 'day')); + + expect(template.messages.length).to.equal(1); + expect(template.messages[0].template.type).to.equal(ChannelTypeEnum.IN_APP); + expect(template.messages[0].template.content).to.equal(testTemplate.messages[0].content); + expect(template.messages[0].template.cta.data.url).to.equal(testTemplate.messages[0].cta.data.url); + }); + + it('should create event trigger', async () => { + const testTemplate: Partial = { + name: 'test template', + notificationGroupId: session.notificationGroups[0]._id, + description: 'This is a test description', + messages: [ + { + type: ChannelTypeEnum.IN_APP, + content: 'Test Template {{name}} {{lastName}}', + cta: { + type: ChannelCTATypeEnum.REDIRECT, + data: { + url: 'https://example.org/profile', + }, + }, + }, + ], + }; + + const { body } = await session.testAgent.post(`/v1/notification-templates`).send(testTemplate); + + expect(body.data).to.be.ok; + + const template: INotificationTemplate = body.data; + expect(template.triggers.length).to.equal(1); + expect(template.triggers[0].identifier).to.include('test'); + expect(template.triggers[0].type).to.equal(TriggerTypeEnum.EVENT); + }); +}); diff --git a/apps/api/src/app/notification-template/e2e/get-notification-template.e2e.ts b/apps/api/src/app/notification-template/e2e/get-notification-template.e2e.ts new file mode 100644 index 00000000000..53088a69455 --- /dev/null +++ b/apps/api/src/app/notification-template/e2e/get-notification-template.e2e.ts @@ -0,0 +1,31 @@ +import { expect } from 'chai'; +import { NotificationTemplateService, UserSession } from '@notifire/testing'; +import { INotificationTemplate } from '@notifire/shared'; + +describe('Get notification template by id - /notification-templates/:templateId (GET)', async () => { + let session: UserSession; + before(async () => { + session = new UserSession(); + await session.initialize(); + }); + + it('should return the template by its id', async function () { + const notificationTemplateService = new NotificationTemplateService( + session.user._id, + session.organization._id, + session.application._id + ); + const template = await notificationTemplateService.createTemplate(); + const { body } = await session.testAgent.get(`/v1/notification-templates/${template._id}`); + + const foundTemplate: INotificationTemplate = body.data; + + expect(foundTemplate._id).to.equal(template._id); + expect(foundTemplate.name).to.equal(template.name); + expect(foundTemplate.messages.length).to.equal(template.messages.length); + expect(foundTemplate.messages[0].template).to.be.ok; + expect(foundTemplate.messages[0].template.content).to.equal(template.messages[0].template.content); + expect(foundTemplate.messages[0]._templateId).to.be.ok; + expect(foundTemplate.triggers.length).to.equal(template.triggers.length); + }); +}); diff --git a/apps/api/src/app/notification-template/e2e/get-notification-templates.e2e.ts b/apps/api/src/app/notification-template/e2e/get-notification-templates.e2e.ts new file mode 100644 index 00000000000..fe679189696 --- /dev/null +++ b/apps/api/src/app/notification-template/e2e/get-notification-templates.e2e.ts @@ -0,0 +1,31 @@ +import { expect } from 'chai'; +import { NotificationTemplateEntity } from '@notifire/dal'; +import { UserSession, NotificationTemplateService } from '@notifire/testing'; + +describe('Get Notification templates - /notification-templates (GET)', async () => { + let session: UserSession; + const templates: NotificationTemplateEntity[] = []; + before(async () => { + session = new UserSession(); + await session.initialize(); + + const notificationTemplateService = new NotificationTemplateService( + session.user._id, + session.organization._id, + session.application._id + ); + templates.push(await notificationTemplateService.createTemplate()); + templates.push(await notificationTemplateService.createTemplate()); + templates.push(await notificationTemplateService.createTemplate()); + }); + + it('should return all templates for organization', async () => { + const { body } = await session.testAgent.get(`/v1/notification-templates`); + expect(body.data.length).to.equal(3); + + const found = body.data.find((i) => templates[0]._id === i._id); + expect(found).to.be.ok; + expect(found.name).to.equal(templates[0].name); + expect(found.notificationGroup.name).to.equal('General'); + }); +}); diff --git a/apps/api/src/app/notification-template/e2e/update-notification-template.e2e.ts b/apps/api/src/app/notification-template/e2e/update-notification-template.e2e.ts new file mode 100644 index 00000000000..ed31c9c8d27 --- /dev/null +++ b/apps/api/src/app/notification-template/e2e/update-notification-template.e2e.ts @@ -0,0 +1,66 @@ +import { expect } from 'chai'; +import { UserSession, NotificationTemplateService } from '@notifire/testing'; +import { ChannelTypeEnum, INotificationTemplate, IUpdateNotificationTemplate } from '@notifire/shared'; + +describe('Update notification template by id - /notification-templates/:templateId (PUT)', async () => { + let session: UserSession; + before(async () => { + session = new UserSession(); + await session.initialize(); + }); + + it('should update the notification template', async function () { + const notificationTemplateService = new NotificationTemplateService( + session.user._id, + session.organization._id, + session.application._id + ); + const template = await notificationTemplateService.createTemplate(); + const update: IUpdateNotificationTemplate = { + name: 'new name for notification', + messages: [ + { + type: ChannelTypeEnum.IN_APP, + content: 'This is new content for notification', + }, + ], + }; + const { body } = await session.testAgent.put(`/v1/notification-templates/${template._id}`).send(update); + const foundTemplate: INotificationTemplate = body.data; + expect(foundTemplate._id).to.equal(template._id); + expect(foundTemplate.name).to.equal('new name for notification'); + expect(foundTemplate.description).to.equal(template.description); + expect(foundTemplate.messages.length).to.equal(1); + expect(foundTemplate.messages[0].template.content).to.equal(update.messages[0].content); + }); + + it('should generate new variables on update', async function () { + const notificationTemplateService = new NotificationTemplateService( + session.user._id, + session.organization._id, + session.application._id + ); + + const template = await notificationTemplateService.createTemplate({ + messages: [ + { + type: ChannelTypeEnum.IN_APP, + content: 'This is new content for notification {{otherVariable}}', + }, + ], + }); + + const update: IUpdateNotificationTemplate = { + messages: [ + { + type: ChannelTypeEnum.IN_APP, + content: 'This is new content for notification {{newVariableFromUpdate}}', + }, + ], + }; + const { body } = await session.testAgent.put(`/v1/notification-templates/${template._id}`).send(update); + const foundTemplate: INotificationTemplate = body.data; + expect(foundTemplate._id).to.equal(template._id); + expect(foundTemplate.triggers[0].variables[0].name).to.equal('newVariableFromUpdate'); + }); +}); diff --git a/apps/api/src/app/notification-template/notification-template.controller.ts b/apps/api/src/app/notification-template/notification-template.controller.ts new file mode 100644 index 00000000000..1b61d078169 --- /dev/null +++ b/apps/api/src/app/notification-template/notification-template.controller.ts @@ -0,0 +1,122 @@ +import { + Body, + ClassSerializerInterceptor, + Controller, + Get, + Param, + Post, + Put, + UseGuards, + UseInterceptors, +} from '@nestjs/common'; +import { IJwtPayload, IUpdateNotificationTemplate, MemberRoleEnum } from '@notifire/shared'; +import { UserSession } from '../shared/framework/user.decorator'; +import { Roles } from '../auth/framework/roles.decorator'; +import { GetNotificationTemplates } from './usecases/get-notification-templates/get-notification-templates.usecase'; +import { GetNotificationTemplatesCommand } from './usecases/get-notification-templates/get-notification-templates.command'; +import { CreateNotificationTemplate, CreateNotificationTemplateCommand } from './usecases/create-notification-template'; +import { CreateNotificationTemplateDto } from './dto/create-notification-template.dto'; +import { GetNotificationTemplate } from './usecases/get-notification-template/get-notification-template.usecase'; +import { GetNotificationTemplateCommand } from './usecases/get-notification-template/get-notification-template.command'; +import { UpdateNotificationTemplate } from './usecases/update-notification-template/update-notification-template.usecase'; +import { UpdateNotificationTemplateCommand } from './usecases/update-notification-template/update-notification-template.command'; +import { UpdateNotificationTemplateDto } from './dto/update-notification-template.dto'; +import { ChangeTemplateActiveStatus } from './usecases/change-template-active-status/change-template-active-status.usecase'; +import { ChangeTemplateActiveStatusCommand } from './usecases/change-template-active-status/change-template-active-status.command'; +import { ChangeTemplateStatusDto } from './dto/change-template-status.dto'; +import { JwtAuthGuard } from '../auth/framework/auth.guard'; + +@Controller('/notification-templates') +@UseInterceptors(ClassSerializerInterceptor) +@UseGuards(JwtAuthGuard) +export class NotificationTemplateController { + constructor( + private getNotificationTemplatesUsecase: GetNotificationTemplates, + private createNotificationTemplateUsecase: CreateNotificationTemplate, + private getNotificationTemplateUsecase: GetNotificationTemplate, + private updateTemplateByIdUsecase: UpdateNotificationTemplate, + private changeTemplateActiveStatusUsecase: ChangeTemplateActiveStatus + ) {} + + @Get('') + @Roles(MemberRoleEnum.ADMIN) + getNotificationTemplates(@UserSession() user: IJwtPayload) { + return this.getNotificationTemplatesUsecase.execute( + GetNotificationTemplatesCommand.create({ + organizationId: user.organizationId, + userId: user._id, + applicationId: user.applicationId, + }) + ); + } + + @Put('/:templateId') + @Roles(MemberRoleEnum.ADMIN) + updateTemplateById( + @UserSession() user: IJwtPayload, + @Param('templateId') templateId: string, + @Body() body: UpdateNotificationTemplateDto + ) { + return this.updateTemplateByIdUsecase.execute( + UpdateNotificationTemplateCommand.create({ + applicationId: user.applicationId, + organizationId: user.organizationId, + userId: user._id, + templateId, + name: body.name, + tags: body.tags, + description: body.description, + messages: body.messages, + notificationGroupId: body.notificationGroupId, + }) + ); + } + + @Get('/:templateId') + @Roles(MemberRoleEnum.ADMIN) + getNotificationTemplateById(@UserSession() user: IJwtPayload, @Param('templateId') templateId: string) { + return this.getNotificationTemplateUsecase.execute( + GetNotificationTemplateCommand.create({ + applicationId: user.applicationId, + organizationId: user.organizationId, + userId: user._id, + templateId, + }) + ); + } + + @Post('') + @Roles(MemberRoleEnum.ADMIN) + createNotificationTemplates(@UserSession() user: IJwtPayload, @Body() body: CreateNotificationTemplateDto) { + return this.createNotificationTemplateUsecase.execute( + CreateNotificationTemplateCommand.create({ + organizationId: user.organizationId, + userId: user._id, + applicationId: user.applicationId, + name: body.name, + tags: body.tags, + description: body.description, + messages: body.messages, + notificationGroupId: body.notificationGroupId, + }) + ); + } + + @Put('/:templateId/status') + @Roles(MemberRoleEnum.ADMIN) + changeActiveStatus( + @UserSession() user: IJwtPayload, + @Body() body: ChangeTemplateStatusDto, + @Param('templateId') templateId: string + ) { + return this.changeTemplateActiveStatusUsecase.execute( + ChangeTemplateActiveStatusCommand.create({ + organizationId: user.organizationId, + userId: user._id, + applicationId: user.applicationId, + active: body.active, + templateId, + }) + ); + } +} diff --git a/apps/api/src/app/notification-template/notification-template.module.ts b/apps/api/src/app/notification-template/notification-template.module.ts new file mode 100644 index 00000000000..e8f35640b66 --- /dev/null +++ b/apps/api/src/app/notification-template/notification-template.module.ts @@ -0,0 +1,15 @@ +import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common'; +import { SharedModule } from '../shared/shared.module'; +import { USE_CASES } from './usecases'; +import { NotificationTemplateController } from './notification-template.controller'; +import { MessageTemplateModule } from '../message-template/message-template.module'; + +@Module({ + imports: [SharedModule, MessageTemplateModule], + controllers: [NotificationTemplateController], + providers: [...USE_CASES], + exports: [...USE_CASES], +}) +export class NotificationTemplateModule implements NestModule { + configure(consumer: MiddlewareConsumer): MiddlewareConsumer | void {} +} diff --git a/apps/api/src/app/notification-template/usecases/change-template-active-status/change-template-active-status.command.ts b/apps/api/src/app/notification-template/usecases/change-template-active-status/change-template-active-status.command.ts new file mode 100644 index 00000000000..97221d4b0bf --- /dev/null +++ b/apps/api/src/app/notification-template/usecases/change-template-active-status/change-template-active-status.command.ts @@ -0,0 +1,17 @@ +import { IsBoolean, IsDefined, IsMongoId } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; + +export class ChangeTemplateActiveStatusCommand extends ApplicationWithUserCommand { + static create(data: ChangeTemplateActiveStatusCommand) { + return CommandHelper.create(ChangeTemplateActiveStatusCommand, data); + } + + @IsBoolean() + @IsDefined() + active: boolean; + + @IsMongoId() + @IsDefined() + templateId: string; +} diff --git a/apps/api/src/app/notification-template/usecases/change-template-active-status/change-template-active-status.usecase.ts b/apps/api/src/app/notification-template/usecases/change-template-active-status/change-template-active-status.usecase.ts new file mode 100644 index 00000000000..ab54a139092 --- /dev/null +++ b/apps/api/src/app/notification-template/usecases/change-template-active-status/change-template-active-status.usecase.ts @@ -0,0 +1,36 @@ +import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'; +import { NotificationTemplateEntity, NotificationTemplateRepository } from '@notifire/dal'; +import { ChangeTemplateActiveStatusCommand } from './change-template-active-status.command'; + +@Injectable() +export class ChangeTemplateActiveStatus { + constructor(private notificationTemplateRepository: NotificationTemplateRepository) {} + + async execute(command: ChangeTemplateActiveStatusCommand): Promise { + const foundTemplate = await this.notificationTemplateRepository.findOne({ + _organizationId: command.organizationId, + _id: command.templateId, + }); + if (!foundTemplate) { + throw new NotFoundException(`Template with id ${command.templateId} not found`); + } + + if (foundTemplate.active === command.active) { + throw new BadRequestException('You must provide a different status from the current status'); + } + + await this.notificationTemplateRepository.update( + { + _id: command.templateId, + }, + { + $set: { + active: command.active, + draft: command.active === false, + }, + } + ); + + return await this.notificationTemplateRepository.findById(command.templateId, command.organizationId); + } +} diff --git a/apps/api/src/app/notification-template/usecases/create-notification-template/create-notification-template.command.ts b/apps/api/src/app/notification-template/usecases/create-notification-template/create-notification-template.command.ts new file mode 100644 index 00000000000..613b74d9924 --- /dev/null +++ b/apps/api/src/app/notification-template/usecases/create-notification-template/create-notification-template.command.ts @@ -0,0 +1,106 @@ +import { + ArrayNotEmpty, + IsArray, + IsDefined, + IsEnum, + IsMongoId, + IsOptional, + IsString, + MaxLength, + ValidateNested, +} from 'class-validator'; +import { + BuilderFieldOperator, + BuilderFieldType, + BuilderGroupValues, + ChannelCTATypeEnum, + ChannelTypeEnum, + IEmailBlock, +} from '@notifire/shared'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; + +export class CreateNotificationTemplateCommand extends ApplicationWithUserCommand { + static create(data: CreateNotificationTemplateCommand) { + return CommandHelper.create(CreateNotificationTemplateCommand, data); + } + + @IsMongoId() + @IsDefined() + notificationGroupId: string; + + @IsOptional() + @IsArray() + tags: string[]; + + @IsDefined() + @IsString() + name: string; + + @IsString() + @IsOptional() + description: string; + + @IsDefined() + @IsArray() + @ValidateNested() + @ArrayNotEmpty() + messages: NotificationChannelDto[]; +} + +export class ChannelCTADto { + @IsEnum(ChannelCTATypeEnum) + type: ChannelCTATypeEnum; + + data: { + url: string; + }; +} + +export class NotificationChannelDto { + @IsOptional() + @IsEnum(ChannelTypeEnum) + type: ChannelTypeEnum; + + @IsDefined() + content: string | IEmailBlock[]; + + @IsOptional() + contentType?: 'editor' | 'customHtml'; + + @IsOptional() + @ValidateNested() + cta?: ChannelCTADto; + + @IsOptional() + name?: string; + + @IsOptional() + subject?: string; + + @IsOptional() + @IsArray() + @ValidateNested() + filters?: MessageFilter[]; + + @IsMongoId() + @IsOptional() + _id?: string; +} + +export class MessageFilter { + isNegated: boolean; + + @IsString() + type: BuilderFieldType; + + @IsString() + value: BuilderGroupValues; + + @IsArray() + children: { + field: string; + value: string; + operator: BuilderFieldOperator; + }[]; +} diff --git a/apps/api/src/app/notification-template/usecases/create-notification-template/create-notification-template.usecase.ts b/apps/api/src/app/notification-template/usecases/create-notification-template/create-notification-template.usecase.ts new file mode 100644 index 00000000000..1193fb117ac --- /dev/null +++ b/apps/api/src/app/notification-template/usecases/create-notification-template/create-notification-template.usecase.ts @@ -0,0 +1,71 @@ +import { Injectable } from '@nestjs/common'; +import { NotificationTemplateRepository } from '@notifire/dal'; +import { INotificationTrigger, TriggerTypeEnum } from '@notifire/shared'; +import slugify from 'slugify'; +import * as shortid from 'shortid'; +import { CreateNotificationTemplateCommand } from './create-notification-template.command'; +import { ContentService } from '../../../shared/helpers/content.service'; +import { CreateMessageTemplate } from '../../../message-template/usecases/create-message-template/create-message-template.usecase'; +import { CreateMessageTemplateCommand } from '../../../message-template/usecases/create-message-template/create-message-template.command'; + +@Injectable() +export class CreateNotificationTemplate { + constructor( + private notificationTemplateRepository: NotificationTemplateRepository, + private createMessageTemplate: CreateMessageTemplate + ) {} + + async execute(command: CreateNotificationTemplateCommand) { + const contentService = new ContentService(); + const variables = contentService.extractMessageVariables(command.messages); + + const trigger: INotificationTrigger = { + type: TriggerTypeEnum.EVENT, + identifier: `${slugify(command.name, { + lower: true, + strict: true, + })}-${shortid.generate()}`, + variables: variables.map((i) => { + return { + name: i, + }; + }), + }; + + const templateMessages = []; + for (const message of command.messages) { + const template = await this.createMessageTemplate.execute( + CreateMessageTemplateCommand.create({ + type: message.type, + name: message.name, + content: message.content, + contentType: message.contentType, + organizationId: command.organizationId, + applicationId: command.applicationId, + userId: command.userId, + cta: message.cta, + subject: message.subject, + }) + ); + + templateMessages.push({ + _templateId: template._id, + filters: message.filters, + }); + } + + const savedTemplate = await this.notificationTemplateRepository.create({ + _organizationId: command.organizationId, + _creatorId: command.userId, + _applicationId: command.applicationId, + name: command.name, + tags: command.tags, + description: command.description, + messages: templateMessages, + triggers: [trigger], + _notificationGroupId: command.notificationGroupId, + }); + + return await this.notificationTemplateRepository.findById(savedTemplate._id, command.organizationId); + } +} diff --git a/apps/api/src/app/notification-template/usecases/create-notification-template/index.ts b/apps/api/src/app/notification-template/usecases/create-notification-template/index.ts new file mode 100644 index 00000000000..1721621522c --- /dev/null +++ b/apps/api/src/app/notification-template/usecases/create-notification-template/index.ts @@ -0,0 +1,2 @@ +export * from './create-notification-template.command'; +export * from './create-notification-template.usecase'; diff --git a/apps/api/src/app/notification-template/usecases/get-notification-template/get-notification-template.command.ts b/apps/api/src/app/notification-template/usecases/get-notification-template/get-notification-template.command.ts new file mode 100644 index 00000000000..dd843f030e6 --- /dev/null +++ b/apps/api/src/app/notification-template/usecases/get-notification-template/get-notification-template.command.ts @@ -0,0 +1,13 @@ +import { IsDefined, IsMongoId } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; + +export class GetNotificationTemplateCommand extends ApplicationWithUserCommand { + static create(data: GetNotificationTemplateCommand) { + return CommandHelper.create(GetNotificationTemplateCommand, data); + } + + @IsDefined() + @IsMongoId() + templateId: string; +} diff --git a/apps/api/src/app/notification-template/usecases/get-notification-template/get-notification-template.usecase.ts b/apps/api/src/app/notification-template/usecases/get-notification-template/get-notification-template.usecase.ts new file mode 100644 index 00000000000..4329ddca22c --- /dev/null +++ b/apps/api/src/app/notification-template/usecases/get-notification-template/get-notification-template.usecase.ts @@ -0,0 +1,17 @@ +import { Injectable, NotFoundException } from '@nestjs/common'; +import { NotificationTemplateEntity, NotificationTemplateRepository } from '@notifire/dal'; +import { GetNotificationTemplateCommand } from './get-notification-template.command'; + +@Injectable() +export class GetNotificationTemplate { + constructor(private notificationTemplateRepository: NotificationTemplateRepository) {} + + async execute(command: GetNotificationTemplateCommand): Promise { + const template = await this.notificationTemplateRepository.findById(command.templateId, command.organizationId); + if (!template) { + throw new NotFoundException(`Template with id ${command.templateId} not found`); + } + + return template; + } +} diff --git a/apps/api/src/app/notification-template/usecases/get-notification-templates/get-notification-templates.command.ts b/apps/api/src/app/notification-template/usecases/get-notification-templates/get-notification-templates.command.ts new file mode 100644 index 00000000000..3369dcf8ee3 --- /dev/null +++ b/apps/api/src/app/notification-template/usecases/get-notification-templates/get-notification-templates.command.ts @@ -0,0 +1,9 @@ +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { OrganizationCommand } from '../../../shared/commands/organization.command'; +import { ApplicationCommand, ApplicationWithUserCommand } from '../../../shared/commands/project.command'; + +export class GetNotificationTemplatesCommand extends ApplicationWithUserCommand { + static create(data: GetNotificationTemplatesCommand) { + return CommandHelper.create(GetNotificationTemplatesCommand, data); + } +} diff --git a/apps/api/src/app/notification-template/usecases/get-notification-templates/get-notification-templates.usecase.ts b/apps/api/src/app/notification-template/usecases/get-notification-templates/get-notification-templates.usecase.ts new file mode 100644 index 00000000000..f27244c8d58 --- /dev/null +++ b/apps/api/src/app/notification-template/usecases/get-notification-templates/get-notification-templates.usecase.ts @@ -0,0 +1,13 @@ +import { Injectable } from '@nestjs/common'; +import { NotificationTemplateEntity, NotificationTemplateRepository, OrganizationEntity } from '@notifire/dal'; +import { GetNotificationTemplatesCommand } from './get-notification-templates.command'; + +@Injectable() +export class GetNotificationTemplates { + constructor(private notificationTemplateRepository: NotificationTemplateRepository) {} + + async execute(command: GetNotificationTemplatesCommand): Promise { + const list = await this.notificationTemplateRepository.getList(command.organizationId, command.applicationId); + return list; + } +} diff --git a/apps/api/src/app/notification-template/usecases/index.ts b/apps/api/src/app/notification-template/usecases/index.ts new file mode 100644 index 00000000000..1dc8932b61f --- /dev/null +++ b/apps/api/src/app/notification-template/usecases/index.ts @@ -0,0 +1,14 @@ +import { ChangeTemplateActiveStatus } from './change-template-active-status/change-template-active-status.usecase'; +import { UpdateNotificationTemplate } from './update-notification-template/update-notification-template.usecase'; +import { GetNotificationTemplates } from './get-notification-templates/get-notification-templates.usecase'; +import { CreateNotificationTemplate } from './create-notification-template'; +import { GetNotificationTemplate } from './get-notification-template/get-notification-template.usecase'; + +export const USE_CASES = [ + // + ChangeTemplateActiveStatus, + UpdateNotificationTemplate, + GetNotificationTemplates, + CreateNotificationTemplate, + GetNotificationTemplate, +]; diff --git a/apps/api/src/app/notification-template/usecases/update-notification-template/update-notification-template.command.ts b/apps/api/src/app/notification-template/usecases/update-notification-template/update-notification-template.command.ts new file mode 100644 index 00000000000..c67491912bc --- /dev/null +++ b/apps/api/src/app/notification-template/usecases/update-notification-template/update-notification-template.command.ts @@ -0,0 +1,88 @@ +import { + ArrayNotEmpty, + IsArray, + IsDefined, + IsEnum, + IsMongoId, + IsOptional, + IsString, + ValidateNested, +} from 'class-validator'; +import { ChannelCTATypeEnum, ChannelTypeEnum } from '@notifire/shared'; +import { IEmailBlock } from '@notifire/dal'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; +import { MessageFilter } from '../create-notification-template'; + +export class UpdateNotificationTemplateCommand extends ApplicationWithUserCommand { + static create(data: UpdateNotificationTemplateCommand) { + return CommandHelper.create(UpdateNotificationTemplateCommand, data); + } + + @IsDefined() + @IsMongoId() + templateId: string; + + @IsArray() + @IsOptional() + tags: string[]; + + @IsString() + @IsOptional() + name: string; + + @IsString() + @IsOptional() + description: string; + + @IsOptional() + @IsMongoId({ + message: 'Bad group id name', + }) + notificationGroupId: string; + + @IsArray() + @ValidateNested() + @IsOptional() + messages: NotificationChannelDto[]; +} + +export class ChannelCTADto { + @IsEnum(ChannelCTATypeEnum) + type: ChannelCTATypeEnum; + + data: { + url: string; + }; +} + +export class NotificationChannelDto { + @IsOptional() + @IsEnum(ChannelTypeEnum) + type: ChannelTypeEnum; + + @IsDefined() + content: string | IEmailBlock[]; + + @IsOptional() + contentType?: 'editor' | 'customHtml'; + + @IsOptional() + @ValidateNested() + cta: ChannelCTADto; + + @IsOptional() + name?: string; + + @IsOptional() + subject?: string; + + @IsOptional() + @IsArray() + @ValidateNested() + filters?: MessageFilter[]; + + @IsMongoId() + @IsOptional() + _id?: string; +} diff --git a/apps/api/src/app/notification-template/usecases/update-notification-template/update-notification-template.usecase.ts b/apps/api/src/app/notification-template/usecases/update-notification-template/update-notification-template.usecase.ts new file mode 100644 index 00000000000..0a2baed1cea --- /dev/null +++ b/apps/api/src/app/notification-template/usecases/update-notification-template/update-notification-template.usecase.ts @@ -0,0 +1,118 @@ +// eslint-ignore max-len + +import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'; +import { NotificationTemplateEntity, NotificationTemplateRepository, NotificationMessagesEntity } from '@notifire/dal'; + +import { UpdateNotificationTemplateCommand } from './update-notification-template.command'; +import { ContentService } from '../../../shared/helpers/content.service'; +import { CreateMessageTemplate } from '../../../message-template/usecases/create-message-template/create-message-template.usecase'; +import { CreateMessageTemplateCommand } from '../../../message-template/usecases/create-message-template/create-message-template.command'; +import { UpdateMessageTemplateCommand } from '../../../message-template/usecases/update-message-template/update-message-template.command'; +import { UpdateMessageTemplate } from '../../../message-template/usecases/update-message-template/update-message-template.usecase'; + +@Injectable() +export class UpdateNotificationTemplate { + constructor( + private notificationTemplateRepository: NotificationTemplateRepository, + private createMessageTemplate: CreateMessageTemplate, + private updateMessageTemplate: UpdateMessageTemplate + ) {} + + async execute(command: UpdateNotificationTemplateCommand): Promise { + const existingTemplate = await this.notificationTemplateRepository.findById( + command.templateId, + command.organizationId + ); + if (!existingTemplate) throw new NotFoundException(`Entity with id ${command.templateId} not found`); + + const updatePayload: Partial = {}; + if (command.name) { + updatePayload.name = command.name; + } + + if (command.description) { + updatePayload.description = command.description; + } + + if (command.notificationGroupId) { + updatePayload._notificationGroupId = command.notificationGroupId; + } + + if (command.messages) { + const contentService = new ContentService(); + const { messages } = command; + + const variables = contentService.extractMessageVariables(command.messages); + updatePayload['triggers.0.variables'] = variables.map((i) => { + return { + name: i, + }; + }); + + const templateMessages: NotificationMessagesEntity[] = []; + for (const message of messages) { + if (message._id) { + const template = await this.updateMessageTemplate.execute( + UpdateMessageTemplateCommand.create({ + templateId: message._id, + type: message.type, + name: message.name, + content: message.content, + organizationId: command.organizationId, + applicationId: command.applicationId, + userId: command.userId, + contentType: message.contentType, + cta: message.cta, + subject: message.subject, + }) + ); + + templateMessages.push({ + _templateId: template._id, + filters: message.filters, + }); + } else { + const template = await this.createMessageTemplate.execute( + CreateMessageTemplateCommand.create({ + type: message.type, + name: message.name, + content: message.content, + organizationId: command.organizationId, + applicationId: command.applicationId, + contentType: message.contentType, + userId: command.userId, + cta: message.cta, + subject: message.subject, + }) + ); + + templateMessages.push({ + _templateId: template._id, + filters: message.filters, + }); + } + } + updatePayload.messages = templateMessages; + } + + if (command.tags) { + updatePayload.tags = command.tags; + } + + if (!Object.keys(updatePayload).length) { + throw new BadRequestException('No properties found for update'); + } + + await this.notificationTemplateRepository.update( + { + _id: command.templateId, + _organizationId: command.organizationId, + }, + { + $set: updatePayload, + } + ); + + return await this.notificationTemplateRepository.findById(command.templateId, command.organizationId); + } +} diff --git a/apps/api/src/app/organization/dtos/bulk-invite-members.dto.ts b/apps/api/src/app/organization/dtos/bulk-invite-members.dto.ts new file mode 100644 index 00000000000..762b685e5d6 --- /dev/null +++ b/apps/api/src/app/organization/dtos/bulk-invite-members.dto.ts @@ -0,0 +1,18 @@ +import { IBulkInviteRequestDto } from '@notifire/shared'; +import { Type } from 'class-transformer'; +import { ArrayNotEmpty, IsArray, IsDefined, IsEmail, IsNotEmpty, ValidateNested } from 'class-validator'; + +class EmailInvitee { + @IsDefined() + @IsNotEmpty() + @IsEmail() + email: string; +} + +export class BulkInviteMembersDto implements IBulkInviteRequestDto { + @ArrayNotEmpty() + @IsArray() + @ValidateNested() + @Type(() => EmailInvitee) + invitees: EmailInvitee[]; +} diff --git a/apps/api/src/app/organization/dtos/create-organization.dto.ts b/apps/api/src/app/organization/dtos/create-organization.dto.ts new file mode 100644 index 00000000000..100df3f7a0e --- /dev/null +++ b/apps/api/src/app/organization/dtos/create-organization.dto.ts @@ -0,0 +1,11 @@ +import { IsOptional, IsString } from 'class-validator'; +import { ICreateOrganizationDto } from '@notifire/shared'; + +export class CreateOrganizationDto implements ICreateOrganizationDto { + @IsString() + name: string; + + @IsString() + @IsOptional() + logo?: string; +} diff --git a/apps/api/src/app/organization/dtos/get-invite.dto.ts b/apps/api/src/app/organization/dtos/get-invite.dto.ts new file mode 100644 index 00000000000..e69de29bb2d diff --git a/apps/api/src/app/organization/dtos/get-my-organization.dto.ts b/apps/api/src/app/organization/dtos/get-my-organization.dto.ts new file mode 100644 index 00000000000..3952ecc9ee2 --- /dev/null +++ b/apps/api/src/app/organization/dtos/get-my-organization.dto.ts @@ -0,0 +1,3 @@ +import { OrganizationEntity } from '@notifire/dal'; + +export type IGetMyOrganizationDto = OrganizationEntity; diff --git a/apps/api/src/app/organization/dtos/invite-member.dto.ts b/apps/api/src/app/organization/dtos/invite-member.dto.ts new file mode 100644 index 00000000000..a6934e10426 --- /dev/null +++ b/apps/api/src/app/organization/dtos/invite-member.dto.ts @@ -0,0 +1,11 @@ +import { IsEmail, IsEnum, IsNotEmpty } from 'class-validator'; +import { MemberRoleEnum } from '@notifire/shared'; + +export class InviteMemberDto { + @IsEmail() + @IsNotEmpty() + email: string; + + @IsEnum(MemberRoleEnum) + role: MemberRoleEnum; +} diff --git a/apps/api/src/app/organization/organization.controller.ts b/apps/api/src/app/organization/organization.controller.ts new file mode 100644 index 00000000000..4c6e56dfc0d --- /dev/null +++ b/apps/api/src/app/organization/organization.controller.ts @@ -0,0 +1,119 @@ +import { + Body, + ClassSerializerInterceptor, + Controller, + Delete, + Get, + Param, + Post, + Put, + UseGuards, + UseInterceptors, +} from '@nestjs/common'; +import { OrganizationEntity } from '@notifire/dal'; +import { IJwtPayload, MemberRoleEnum } from '@notifire/shared'; +import { AuthGuard } from '@nestjs/passport'; +import { Roles } from '../auth/framework/roles.decorator'; +import { UserSession } from '../shared/framework/user.decorator'; +import { CreateOrganizationDto } from './dtos/create-organization.dto'; +import { CreateOrganizationCommand } from './usecases/create-organization/create-organization.command'; +import { CreateOrganization } from './usecases/create-organization/create-organization.usecase'; +import { GetMyOrganizationCommand } from './usecases/get-my-organization/get-my-organization.command'; +import { GetMyOrganization } from './usecases/get-my-organization/get-my-organization.usecase'; +import { RemoveMember } from './usecases/membership/remove-member/remove-member.usecase'; +import { RemoveMemberCommand } from './usecases/membership/remove-member/remove-member.command'; +import { IGetMyOrganizationDto } from './dtos/get-my-organization.dto'; +import { JwtAuthGuard } from '../auth/framework/auth.guard'; +import { GetMembersCommand } from './usecases/membership/membership/get-members/get-members.command'; +import { GetMembers } from './usecases/membership/membership/get-members/get-members.usecase'; +import { ChangeMemberRoleCommand } from './usecases/membership/membership/change-member-role/change-member-role.command'; +import { ChangeMemberRole } from './usecases/membership/membership/change-member-role/change-member-role.usecase'; + +@Controller('/organizations') +@UseInterceptors(ClassSerializerInterceptor) +@UseGuards(JwtAuthGuard) +export class OrganizationController { + constructor( + private createOrganizationUsecase: CreateOrganization, + private getMyOrganizationUsecase: GetMyOrganization, + private getMembers: GetMembers, + private removeMemberUsecase: RemoveMember, + private changeMemberRoleUsecase: ChangeMemberRole + ) {} + + @Post('/') + async createOrganization( + @UserSession() user: IJwtPayload, + @Body() body: CreateOrganizationDto + ): Promise { + const command = CreateOrganizationCommand.create({ + userId: user._id, + logo: body.logo, + name: body.name, + }); + const organization = await this.createOrganizationUsecase.execute(command); + + return organization; + } + + @Delete('/members/:memberId') + @Roles(MemberRoleEnum.ADMIN) + async removeMember(@UserSession() user: IJwtPayload, @Param('memberId') memberId: string) { + return await this.removeMemberUsecase.execute( + RemoveMemberCommand.create({ + userId: user._id, + organizationId: user.organizationId, + memberId, + }) + ); + } + + @Put('/members/:memberId/roles') + @Roles(MemberRoleEnum.ADMIN) + async updateMemberRoles( + @UserSession() user: IJwtPayload, + @Param('memberId') memberId: string, + @Body('role') role: MemberRoleEnum + ) { + return await this.changeMemberRoleUsecase.execute( + ChangeMemberRoleCommand.create({ + memberId, + role, + userId: user._id, + organizationId: user.organizationId, + }) + ); + } + + @Get('/members') + @Roles(MemberRoleEnum.ADMIN) + async getMember(@UserSession() user: IJwtPayload) { + return await this.getMembers.execute( + GetMembersCommand.create({ + userId: user._id, + organizationId: user.organizationId, + }) + ); + } + + @Post('/members/invite') + @Roles(MemberRoleEnum.ADMIN) + async inviteMember(@UserSession() user: IJwtPayload) { + return await this.getMembers.execute( + GetMembersCommand.create({ + userId: user._id, + organizationId: user.organizationId, + }) + ); + } + + @Get('/me') + async getMyOrganization(@UserSession() user: IJwtPayload): Promise { + const command = GetMyOrganizationCommand.create({ + userId: user._id, + id: user.organizationId, + }); + + return await this.getMyOrganizationUsecase.execute(command); + } +} diff --git a/apps/api/src/app/organization/organization.module.ts b/apps/api/src/app/organization/organization.module.ts new file mode 100644 index 00000000000..27393892b8c --- /dev/null +++ b/apps/api/src/app/organization/organization.module.ts @@ -0,0 +1,21 @@ +import { MiddlewareConsumer, Module, NestModule, RequestMethod } from '@nestjs/common'; +import { AuthGuard } from '@nestjs/passport'; +import { SharedModule } from '../shared/shared.module'; +import { UserModule } from '../user/user.module'; +import { OrganizationController } from './organization.controller'; +import { USE_CASES } from './usecases'; + +@Module({ + imports: [SharedModule, UserModule], + controllers: [OrganizationController], + providers: [...USE_CASES], + exports: [...USE_CASES], +}) +export class OrganizationModule implements NestModule { + configure(consumer: MiddlewareConsumer): MiddlewareConsumer | void { + consumer.apply(AuthGuard).exclude({ + method: RequestMethod.GET, + path: '/organizations/invite/:inviteToken', + }); + } +} diff --git a/apps/api/src/app/organization/usecases/create-organization/create-organization.command.ts b/apps/api/src/app/organization/usecases/create-organization/create-organization.command.ts new file mode 100644 index 00000000000..83cfe7d999c --- /dev/null +++ b/apps/api/src/app/organization/usecases/create-organization/create-organization.command.ts @@ -0,0 +1,12 @@ +import { AuthenticatedCommand } from '../../../shared/commands/authenticated.command'; +import { CommandHelper } from '../../../shared/commands/command.helper'; + +export class CreateOrganizationCommand extends AuthenticatedCommand { + static create(data: CreateOrganizationCommand) { + return CommandHelper.create(CreateOrganizationCommand, data); + } + + public readonly logo?: string; + + public readonly name: string; +} diff --git a/apps/api/src/app/organization/usecases/create-organization/create-organization.usecase.ts b/apps/api/src/app/organization/usecases/create-organization/create-organization.usecase.ts new file mode 100644 index 00000000000..cb4ec7c96b6 --- /dev/null +++ b/apps/api/src/app/organization/usecases/create-organization/create-organization.usecase.ts @@ -0,0 +1,73 @@ +import { Injectable, Logger, Scope } from '@nestjs/common'; +import { OrganizationEntity, OrganizationRepository, UserEntity, UserRepository } from '@notifire/dal'; +import { MemberRoleEnum } from '@notifire/shared'; +import { capitalize } from '../../../shared/services/helper/helper.service'; +import { MailService } from '../../../shared/services/mail/mail.service'; +import { QueueService } from '../../../shared/services/queue'; +import { GetOrganizationCommand } from '../get-organization/get-organization.command'; +import { GetOrganization } from '../get-organization/get-organization.usecase'; +import { AddMemberCommand } from '../membership/add-member/add-member.command'; +import { AddMember } from '../membership/add-member/add-member.usecase'; +import { CreateOrganizationCommand } from './create-organization.command'; + +@Injectable({ + scope: Scope.REQUEST, +}) +export class CreateOrganization { + constructor( + private readonly organizationRepository: OrganizationRepository, + private readonly addMemberUsecase: AddMember, + private readonly getOrganizationUsecase: GetOrganization, + private readonly queueService: QueueService, + private readonly userRepository: UserRepository, + private readonly mailService: MailService + ) {} + + async execute(command: CreateOrganizationCommand): Promise { + const organization = new OrganizationEntity(); + organization.logo = command.logo; + organization.name = command.name; + + const user = await this.userRepository.findById(command.userId); + + const createdOrganization = await this.organizationRepository.create(organization); + + await this.addMemberUsecase.execute( + AddMemberCommand.create({ + roles: [MemberRoleEnum.ADMIN], + organizationId: createdOrganization._id, + userId: command.userId, + }) + ); + + await this.sendWelcomeEmail(user, organization); + + const organizationAfterChanges = await this.getOrganizationUsecase.execute( + GetOrganizationCommand.create({ + id: createdOrganization._id, + userId: command.userId, + }) + ); + + return organizationAfterChanges; + } + + private async sendWelcomeEmail(user: UserEntity, organization: OrganizationEntity) { + try { + await this.mailService.sendMail({ + templateId: '35339302-a24e-4dc2-bff5-02f32b8537cc', + to: user.email, + from: { + email: 'hi@notifire.co', + name: 'Notifire', + }, + params: { + firstName: capitalize(user.firstName), + organizationName: capitalize(organization.name), + }, + }); + } catch (e) { + Logger.error(e.message); + } + } +} diff --git a/apps/api/src/app/organization/usecases/get-my-organization/get-my-organization.command.ts b/apps/api/src/app/organization/usecases/get-my-organization/get-my-organization.command.ts new file mode 100644 index 00000000000..a8462a520a3 --- /dev/null +++ b/apps/api/src/app/organization/usecases/get-my-organization/get-my-organization.command.ts @@ -0,0 +1,12 @@ +import { IsDefined } from 'class-validator'; +import { AuthenticatedCommand } from '../../../shared/commands/authenticated.command'; +import { CommandHelper } from '../../../shared/commands/command.helper'; + +export class GetMyOrganizationCommand extends AuthenticatedCommand { + static create(data: GetMyOrganizationCommand) { + return CommandHelper.create(GetMyOrganizationCommand, data); + } + + @IsDefined() + public readonly id: string; +} diff --git a/apps/api/src/app/organization/usecases/get-my-organization/get-my-organization.usecase.ts b/apps/api/src/app/organization/usecases/get-my-organization/get-my-organization.usecase.ts new file mode 100644 index 00000000000..0426a7d6949 --- /dev/null +++ b/apps/api/src/app/organization/usecases/get-my-organization/get-my-organization.usecase.ts @@ -0,0 +1,23 @@ +import { Injectable, Scope, UnauthorizedException } from '@nestjs/common'; +import { GetMyOrganizationCommand } from './get-my-organization.command'; +import { GetOrganization } from '../get-organization/get-organization.usecase'; +import { GetOrganizationCommand } from '../get-organization/get-organization.command'; + +@Injectable({ + scope: Scope.REQUEST, +}) +export class GetMyOrganization { + constructor(private getOrganizationUseCase: GetOrganization) {} + + async execute(command: GetMyOrganizationCommand) { + const organization = await this.getOrganizationUseCase.execute( + GetOrganizationCommand.create({ + id: command.id, + userId: command.userId, + }) + ); + if (!organization) throw new UnauthorizedException('No organization found'); + + return organization; + } +} diff --git a/apps/api/src/app/organization/usecases/get-organization/get-organization.command.ts b/apps/api/src/app/organization/usecases/get-organization/get-organization.command.ts new file mode 100644 index 00000000000..f17290ed99f --- /dev/null +++ b/apps/api/src/app/organization/usecases/get-organization/get-organization.command.ts @@ -0,0 +1,10 @@ +import { AuthenticatedCommand } from '../../../shared/commands/authenticated.command'; +import { CommandHelper } from '../../../shared/commands/command.helper'; + +export class GetOrganizationCommand extends AuthenticatedCommand { + static create(data: GetOrganizationCommand) { + return CommandHelper.create(GetOrganizationCommand, data); + } + + public readonly id: string; +} diff --git a/apps/api/src/app/organization/usecases/get-organization/get-organization.usecase.ts b/apps/api/src/app/organization/usecases/get-organization/get-organization.usecase.ts new file mode 100644 index 00000000000..65050bd6b38 --- /dev/null +++ b/apps/api/src/app/organization/usecases/get-organization/get-organization.usecase.ts @@ -0,0 +1,16 @@ +import { Injectable, Scope } from '@nestjs/common'; +import { OrganizationRepository } from '@notifire/dal'; +import { GetOrganizationCommand } from './get-organization.command'; + +@Injectable({ + scope: Scope.REQUEST, +}) +export class GetOrganization { + constructor(private readonly organizationRepository: OrganizationRepository) {} + + async execute(command: GetOrganizationCommand) { + const organization = await this.organizationRepository.findById(command.id); + + return organization; + } +} diff --git a/apps/api/src/app/organization/usecases/index.ts b/apps/api/src/app/organization/usecases/index.ts new file mode 100644 index 00000000000..3034583d77b --- /dev/null +++ b/apps/api/src/app/organization/usecases/index.ts @@ -0,0 +1,17 @@ +import { CreateOrganization } from './create-organization/create-organization.usecase'; +import { GetOrganization } from './get-organization/get-organization.usecase'; +import { GetMyOrganization } from './get-my-organization/get-my-organization.usecase'; +import { AddMember } from './membership/add-member/add-member.usecase'; +import { RemoveMember } from './membership/remove-member/remove-member.usecase'; +import { GetMembers } from './membership/membership/get-members/get-members.usecase'; +import { ChangeMemberRole } from './membership/membership/change-member-role/change-member-role.usecase'; + +export const USE_CASES = [ + AddMember, + CreateOrganization, + GetOrganization, + GetMyOrganization, + GetMembers, + RemoveMember, + ChangeMemberRole, +]; diff --git a/apps/api/src/app/organization/usecases/membership/add-member/add-member.command.ts b/apps/api/src/app/organization/usecases/membership/add-member/add-member.command.ts new file mode 100644 index 00000000000..0e95ec33bb7 --- /dev/null +++ b/apps/api/src/app/organization/usecases/membership/add-member/add-member.command.ts @@ -0,0 +1,13 @@ +import { MemberRoleEnum } from '@notifire/shared'; +import { ArrayNotEmpty } from 'class-validator'; +import { CommandHelper } from '../../../../shared/commands/command.helper'; +import { OrganizationCommand } from '../../../../shared/commands/organization.command'; + +export class AddMemberCommand extends OrganizationCommand { + static create(data: AddMemberCommand) { + return CommandHelper.create(AddMemberCommand, data); + } + + @ArrayNotEmpty() + public readonly roles: MemberRoleEnum[]; +} diff --git a/apps/api/src/app/organization/usecases/membership/add-member/add-member.usecase.ts b/apps/api/src/app/organization/usecases/membership/add-member/add-member.usecase.ts new file mode 100644 index 00000000000..7f6b8c3f343 --- /dev/null +++ b/apps/api/src/app/organization/usecases/membership/add-member/add-member.usecase.ts @@ -0,0 +1,34 @@ +import { Injectable, Scope } from '@nestjs/common'; +import { MemberRepository, OrganizationRepository } from '@notifire/dal'; +import { MemberStatusEnum } from '@notifire/shared'; +import { ApiException } from '../../../../shared/exceptions/api.exception'; +import { AddMemberCommand } from './add-member.command'; + +@Injectable({ + scope: Scope.REQUEST, +}) +export class AddMember { + private organizationId: string; + + constructor( + private readonly organizationRepository: OrganizationRepository, + private readonly memberRepository: MemberRepository + ) {} + + async execute(command: AddMemberCommand): Promise { + this.organizationId = command.organizationId; + + const isAlreadyMember = await this.isMember(command.userId); + if (isAlreadyMember) throw new ApiException('Member already exists'); + + await this.memberRepository.addMember(command.organizationId, { + _userId: command.userId, + roles: command.roles, + memberStatus: MemberStatusEnum.ACTIVE, + }); + } + + private async isMember(userId: string): Promise { + return !!(await this.memberRepository.findMemberByUserId(this.organizationId, userId)); + } +} diff --git a/apps/api/src/app/organization/usecases/membership/membership/add-member/add-member.command.ts b/apps/api/src/app/organization/usecases/membership/membership/add-member/add-member.command.ts new file mode 100644 index 00000000000..7587a8c71f0 --- /dev/null +++ b/apps/api/src/app/organization/usecases/membership/membership/add-member/add-member.command.ts @@ -0,0 +1,13 @@ +import { MemberRoleEnum } from '@notifire/shared'; +import { ArrayNotEmpty } from 'class-validator'; +import { OrganizationCommand } from '../../../../../shared/commands/organization.command'; +import { CommandHelper } from '../../../../../shared/commands/command.helper'; + +export class AddMemberCommand extends OrganizationCommand { + static create(data: AddMemberCommand) { + return CommandHelper.create(AddMemberCommand, data); + } + + @ArrayNotEmpty() + public readonly roles: MemberRoleEnum[]; +} diff --git a/apps/api/src/app/organization/usecases/membership/membership/add-member/add-member.usecase.ts b/apps/api/src/app/organization/usecases/membership/membership/add-member/add-member.usecase.ts new file mode 100644 index 00000000000..7eff041f7d2 --- /dev/null +++ b/apps/api/src/app/organization/usecases/membership/membership/add-member/add-member.usecase.ts @@ -0,0 +1,34 @@ +import { Injectable, Scope } from '@nestjs/common'; +import { OrganizationRepository, UserRepository, MemberRepository } from '@notifire/dal'; +import { MemberStatusEnum } from '@notifire/shared'; +import { AddMemberCommand } from './add-member.command'; +import { ApiException } from '../../../../../shared/exceptions/api.exception'; + +@Injectable({ + scope: Scope.REQUEST, +}) +export class AddMember { + private organizationId: string; + + constructor( + private readonly organizationRepository: OrganizationRepository, + private readonly memberRepository: MemberRepository + ) {} + + async execute(command: AddMemberCommand): Promise { + this.organizationId = command.organizationId; + + const isAlreadyMember = await this.isMember(command.userId); + if (isAlreadyMember) throw new ApiException('Member already exists'); + + await this.memberRepository.addMember(command.organizationId, { + _userId: command.userId, + roles: command.roles, + memberStatus: MemberStatusEnum.ACTIVE, + }); + } + + private async isMember(userId: string): Promise { + return !!(await this.memberRepository.findMemberByUserId(this.organizationId, userId)); + } +} diff --git a/apps/api/src/app/organization/usecases/membership/membership/change-member-role/change-member-role.command.ts b/apps/api/src/app/organization/usecases/membership/membership/change-member-role/change-member-role.command.ts new file mode 100644 index 00000000000..77aac47f511 --- /dev/null +++ b/apps/api/src/app/organization/usecases/membership/membership/change-member-role/change-member-role.command.ts @@ -0,0 +1,17 @@ +import { MemberRoleEnum } from '@notifire/shared'; +import { IsDefined, IsEnum } from 'class-validator'; +import { OrganizationCommand } from '../../../../../shared/commands/organization.command'; +import { CommandHelper } from '../../../../../shared/commands/command.helper'; + +export class ChangeMemberRoleCommand extends OrganizationCommand { + static create(data: ChangeMemberRoleCommand) { + return CommandHelper.create(ChangeMemberRoleCommand, data); + } + + @IsEnum(MemberRoleEnum) + @IsDefined() + role: MemberRoleEnum; + + @IsDefined() + memberId: string; +} diff --git a/apps/api/src/app/organization/usecases/membership/membership/change-member-role/change-member-role.usecase.ts b/apps/api/src/app/organization/usecases/membership/membership/change-member-role/change-member-role.usecase.ts new file mode 100644 index 00000000000..7af88176339 --- /dev/null +++ b/apps/api/src/app/organization/usecases/membership/membership/change-member-role/change-member-role.usecase.ts @@ -0,0 +1,36 @@ +import { Injectable } from '@nestjs/common'; +import { OrganizationRepository, UserRepository, MemberRepository } from '@notifire/dal'; +import { MemberRoleEnum } from '@notifire/shared'; +import { ChangeMemberRoleCommand } from './change-member-role.command'; +import { ApiException } from '../../../../../shared/exceptions/api.exception'; + +@Injectable() +export class ChangeMemberRole { + constructor( + private organizationRepository: OrganizationRepository, + private userRepository: UserRepository, + private memberRepository: MemberRepository + ) {} + + async execute(command: ChangeMemberRoleCommand) { + const organization = await this.organizationRepository.findById(command.organizationId); + const user = await this.userRepository.findById(command.userId); + + const member = await this.memberRepository.findMemberById(organization._id, command.memberId); + if (!member) throw new ApiException('No member was found'); + + if (![MemberRoleEnum.MEMBER, MemberRoleEnum.ADMIN].includes(command.role)) { + throw new ApiException('Not supported role type'); + } + + /* if (organization._creatorId === member._userId && command.role === MemberRoleEnum.MEMBER) { + throw new ApiException('Could not remove admin permission to organization creator'); + } +*/ + const roles = [command.role]; + + await this.memberRepository.updateMemberRoles(organization._id, command.memberId, roles); + + return this.memberRepository.findMemberByUserId(organization._id, member._userId); + } +} diff --git a/apps/api/src/app/organization/usecases/membership/membership/get-members/get-members.command.ts b/apps/api/src/app/organization/usecases/membership/membership/get-members/get-members.command.ts new file mode 100644 index 00000000000..876c3ebd95e --- /dev/null +++ b/apps/api/src/app/organization/usecases/membership/membership/get-members/get-members.command.ts @@ -0,0 +1,8 @@ +import { OrganizationCommand } from '../../../../../shared/commands/organization.command'; +import { CommandHelper } from '../../../../../shared/commands/command.helper'; + +export class GetMembersCommand extends OrganizationCommand { + static create(data: GetMembersCommand) { + return CommandHelper.create(GetMembersCommand, data); + } +} diff --git a/apps/api/src/app/organization/usecases/membership/membership/get-members/get-members.usecase.ts b/apps/api/src/app/organization/usecases/membership/membership/get-members/get-members.usecase.ts new file mode 100644 index 00000000000..53b6f376cd7 --- /dev/null +++ b/apps/api/src/app/organization/usecases/membership/membership/get-members/get-members.usecase.ts @@ -0,0 +1,14 @@ +import { Injectable, NotFoundException, Scope } from '@nestjs/common'; +import { OrganizationRepository, MemberRepository } from '@notifire/dal'; +import { GetMembersCommand } from './get-members.command'; + +@Injectable({ + scope: Scope.REQUEST, +}) +export class GetMembers { + constructor(private organizationRepository: OrganizationRepository, private membersRepository: MemberRepository) {} + + async execute(command: GetMembersCommand) { + return await this.membersRepository.getOrganizationMembers(command.organizationId); + } +} diff --git a/apps/api/src/app/organization/usecases/membership/membership/remove-member/remove-member.command.ts b/apps/api/src/app/organization/usecases/membership/membership/remove-member/remove-member.command.ts new file mode 100644 index 00000000000..f0e97ebb9ff --- /dev/null +++ b/apps/api/src/app/organization/usecases/membership/membership/remove-member/remove-member.command.ts @@ -0,0 +1,12 @@ +import { IsString } from 'class-validator'; +import { OrganizationCommand } from '../../../../../shared/commands/organization.command'; +import { CommandHelper } from '../../../../../shared/commands/command.helper'; + +export class RemoveMemberCommand extends OrganizationCommand { + static create(data: RemoveMemberCommand) { + return CommandHelper.create(RemoveMemberCommand, data); + } + + @IsString() + memberId: string; +} diff --git a/apps/api/src/app/organization/usecases/membership/membership/remove-member/remove-member.usecase.ts b/apps/api/src/app/organization/usecases/membership/membership/remove-member/remove-member.usecase.ts new file mode 100644 index 00000000000..d7b4066dd57 --- /dev/null +++ b/apps/api/src/app/organization/usecases/membership/membership/remove-member/remove-member.usecase.ts @@ -0,0 +1,25 @@ +import { Injectable, NotFoundException, Scope } from '@nestjs/common'; +import { OrganizationRepository, MemberRepository } from '@notifire/dal'; +import { RemoveMemberCommand } from './remove-member.command'; +import { ApiException } from '../../../../../shared/exceptions/api.exception'; + +@Injectable({ + scope: Scope.REQUEST, +}) +export class RemoveMember { + constructor(private organizationRepository: OrganizationRepository, private memberRepository: MemberRepository) {} + + async execute(command: RemoveMemberCommand) { + const members = await this.memberRepository.getOrganizationMembers(command.organizationId); + const memberToRemove = members.find((i) => i._id === command.memberId); + + if (!memberToRemove) throw new NotFoundException('Member not found'); + if (memberToRemove._userId && memberToRemove._userId && memberToRemove._userId === command.userId) { + throw new ApiException('Cannot remove self from members'); + } + + await this.memberRepository.removeMemberById(command.organizationId, memberToRemove._id); + + return memberToRemove; + } +} diff --git a/apps/api/src/app/organization/usecases/membership/remove-member/remove-member.command.ts b/apps/api/src/app/organization/usecases/membership/remove-member/remove-member.command.ts new file mode 100644 index 00000000000..7d6e16ffbbe --- /dev/null +++ b/apps/api/src/app/organization/usecases/membership/remove-member/remove-member.command.ts @@ -0,0 +1,12 @@ +import { IsString } from 'class-validator'; +import { CommandHelper } from '../../../../shared/commands/command.helper'; +import { OrganizationCommand } from '../../../../shared/commands/organization.command'; + +export class RemoveMemberCommand extends OrganizationCommand { + static create(data: RemoveMemberCommand) { + return CommandHelper.create(RemoveMemberCommand, data); + } + + @IsString() + memberId: string; +} diff --git a/apps/api/src/app/organization/usecases/membership/remove-member/remove-member.usecase.ts b/apps/api/src/app/organization/usecases/membership/remove-member/remove-member.usecase.ts new file mode 100644 index 00000000000..05fb8f0989d --- /dev/null +++ b/apps/api/src/app/organization/usecases/membership/remove-member/remove-member.usecase.ts @@ -0,0 +1,25 @@ +import { Injectable, NotFoundException, Scope } from '@nestjs/common'; +import { MemberRepository, OrganizationRepository } from '@notifire/dal'; +import { RemoveMemberCommand } from './remove-member.command'; +import { ApiException } from '../../../../shared/exceptions/api.exception'; + +@Injectable({ + scope: Scope.REQUEST, +}) +export class RemoveMember { + constructor(private organizationRepository: OrganizationRepository, private memberRepository: MemberRepository) {} + + async execute(command: RemoveMemberCommand) { + const members = await this.memberRepository.getOrganizationMembers(command.organizationId); + const memberToRemove = members.find((i) => i._id === command.memberId); + + if (!memberToRemove) throw new NotFoundException('Member not found'); + if (memberToRemove._userId && memberToRemove._userId && memberToRemove._userId === command.userId) { + throw new ApiException('Cannot remove self from members'); + } + + await this.memberRepository.removeMemberById(command.organizationId, memberToRemove._id); + + return memberToRemove; + } +} diff --git a/apps/api/src/app/shared/commands/authenticated.command.ts b/apps/api/src/app/shared/commands/authenticated.command.ts new file mode 100644 index 00000000000..b436cb899f5 --- /dev/null +++ b/apps/api/src/app/shared/commands/authenticated.command.ts @@ -0,0 +1,6 @@ +import { IsNotEmpty } from 'class-validator'; + +export abstract class AuthenticatedCommand { + @IsNotEmpty() + public readonly userId: string; +} diff --git a/apps/api/src/app/shared/commands/command.helper.ts b/apps/api/src/app/shared/commands/command.helper.ts new file mode 100644 index 00000000000..d80f8ca726d --- /dev/null +++ b/apps/api/src/app/shared/commands/command.helper.ts @@ -0,0 +1,21 @@ +import { ClassConstructor, plainToClass } from 'class-transformer'; +import { validateSync } from 'class-validator'; +import { BadRequestException, flatten } from '@nestjs/common'; + +export class CommandHelper { + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types + static create(command: ClassConstructor, data: any): T { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const convertedObject = plainToClass(command, { + ...data, + }); + + const errors = validateSync(convertedObject); + if (errors?.length) { + const mappedErrors = flatten(errors.map((item) => Object.values(item.constraints))); + throw new BadRequestException(mappedErrors); + } + + return convertedObject; + } +} diff --git a/apps/api/src/app/shared/commands/organization.command.ts b/apps/api/src/app/shared/commands/organization.command.ts new file mode 100644 index 00000000000..f0750198c38 --- /dev/null +++ b/apps/api/src/app/shared/commands/organization.command.ts @@ -0,0 +1,7 @@ +import { IsNotEmpty } from 'class-validator'; +import { AuthenticatedCommand } from './authenticated.command'; + +export abstract class OrganizationCommand extends AuthenticatedCommand { + @IsNotEmpty() + readonly organizationId: string; +} diff --git a/apps/api/src/app/shared/commands/project.command.ts b/apps/api/src/app/shared/commands/project.command.ts new file mode 100644 index 00000000000..4f3a7e76f40 --- /dev/null +++ b/apps/api/src/app/shared/commands/project.command.ts @@ -0,0 +1,31 @@ +import { IsNotEmpty } from 'class-validator'; + +export abstract class ApplicationWithUserCommand { + @IsNotEmpty() + readonly applicationId: string; + + @IsNotEmpty() + readonly organizationId: string; + + @IsNotEmpty() + readonly userId: string; +} + +export abstract class ApplicationWithSubscriber { + @IsNotEmpty() + readonly applicationId: string; + + @IsNotEmpty() + readonly organizationId: string; + + @IsNotEmpty() + readonly subscriberId: string; +} + +export abstract class ApplicationCommand { + @IsNotEmpty() + readonly applicationId: string; + + @IsNotEmpty() + readonly organizationId: string; +} diff --git a/apps/api/src/app/shared/constants.ts b/apps/api/src/app/shared/constants.ts new file mode 100644 index 00000000000..806cf48024b --- /dev/null +++ b/apps/api/src/app/shared/constants.ts @@ -0,0 +1,2 @@ +export const QUEUE_SERVICE = 'QueueService'; +export const DAL_SERVICE = 'DalService'; diff --git a/apps/api/src/app/shared/crud/mongoose-crud.service.ts b/apps/api/src/app/shared/crud/mongoose-crud.service.ts new file mode 100644 index 00000000000..df7bba73100 --- /dev/null +++ b/apps/api/src/app/shared/crud/mongoose-crud.service.ts @@ -0,0 +1,168 @@ +/* eslint-disable no-sequences */ +import { CrudRequest, CreateManyDto, CrudService } from '@nestjsx/crud'; +import { Model } from 'mongoose'; + +export class MongooseCrudService extends CrudService { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + constructor(public model: Model) { + super(); + } + + buildQuery(req: CrudRequest) { + const { limit = 10, page = 1, filter = [], fields = [], sort = [], join = [], paramsFilter = [] } = req.parsed; + + let { offset: skip = 0 } = req.parsed; + if (page > 1) { + skip = (page - 1) * limit; + } + + const options = { + page, + skip, + limit, + // eslint-disable-next-line no-return-assign + sort: sort.reduce((acc, v) => ((acc[v.field] = v.order === 'ASC' ? 1 : -1), acc), {}), + populate: join.map((v) => v.field), + select: fields.join(' '), + }; + + const where = filter.reduce((acc, { field, operator, value }) => { + let cond = null; + switch (operator) { + case 'starts': + cond = new RegExp(`^${value}`, 'i'); + break; + case 'ends': + cond = new RegExp(`${value}$`, 'i'); + break; + case 'cont': + cond = new RegExp(`${value}`, 'i'); + break; + case 'excl': + cond = { $ne: new RegExp(`${value}`, 'i') }; + break; + case 'notin': + cond = { $nin: value }; + break; + case 'isnull': + cond = null; + break; + case 'notnull': + cond = { $ne: null }; + break; + case 'between': { + const [min, max] = value; + cond = { $gte: min, $lte: max }; + break; + } + default: + cond = { [`$${operator}`]: value }; + } + acc[field] = cond; + return acc; + }, {}); + + const idParam = paramsFilter.find((v) => v.field === 'id'); + return { options, where, id: idParam ? idParam.value : null }; + } + + async getMany(req: CrudRequest) { + const { options, where } = this.buildQuery(req); + const queryBuilder = this.model + .find() + .setOptions({ + ...options, + } as never) + .where({ + ...where, + }); + + options.populate.forEach((v) => { + queryBuilder.populate(v); + }); + + const data = await queryBuilder.exec(); + if (options.page) { + const total = await this.model.countDocuments(where); + return this.createPageInfo( + data.map((i) => JSON.parse(JSON.stringify(i))), + total, + options.limit, + options.skip + ); + } + return data; + } + + async getOne(req: CrudRequest): Promise { + const { options, where, id } = this.buildQuery(req); + const queryBuilder = this.model + .findById(id) + .setOptions({ + ...options, + } as never) + .where({ + ...where, + }); + options.populate.forEach((v) => { + queryBuilder.populate(v); + }); + + const data = await queryBuilder.exec(); + + if (!data) { + this.throwNotFoundException(this.model.modelName); + } + + return data; + } + + async createOne(req: CrudRequest, dto: T): Promise { + return await this.model.create(dto); + } + + async createMany(req: CrudRequest, dto: CreateManyDto): Promise { + return await this.model.insertMany(dto.bulk); + } + + async updateOne(req: CrudRequest, dto: T): Promise { + const { id } = this.buildQuery(req); + const data = await this.model.findByIdAndUpdate(id, dto, { + new: true, + runValidators: true, + }); + if (!data) { + this.throwNotFoundException(this.model.modelName); + } + + return data; + } + + async replaceOne(req: CrudRequest, dto: T): Promise { + const { id } = this.buildQuery(req); + const data = await this.model.replaceOne( + { + _id: id, + }, + dto + ); + + if (!data) { + this.throwNotFoundException(this.model.modelName); + } + + return this.model.findById(id); + } + + async deleteOne(req: CrudRequest): Promise { + const { id } = this.buildQuery(req); + const data = await this.model.findById(id); + if (!data) { + this.throwNotFoundException(this.model.modelName); + } + + await this.model.findByIdAndDelete(id); + + return data; + } +} diff --git a/apps/api/src/app/shared/exceptions/api.exception.ts b/apps/api/src/app/shared/exceptions/api.exception.ts new file mode 100644 index 00000000000..94acedff15d --- /dev/null +++ b/apps/api/src/app/shared/exceptions/api.exception.ts @@ -0,0 +1,3 @@ +import { BadRequestException } from '@nestjs/common'; + +export class ApiException extends BadRequestException {} diff --git a/apps/api/src/app/shared/framework/response.interceptor.ts b/apps/api/src/app/shared/framework/response.interceptor.ts new file mode 100644 index 00000000000..92cb9ab08bd --- /dev/null +++ b/apps/api/src/app/shared/framework/response.interceptor.ts @@ -0,0 +1,44 @@ +import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { isObject, isArray } from 'lodash'; +import { classToPlain } from 'class-transformer'; + +export interface Response { + data: T; +} + +@Injectable() +export class ResponseInterceptor implements NestInterceptor> { + intercept(context, next: CallHandler): Observable> { + if (context.getType() === 'graphql') return next.handle(); + + return next.handle().pipe( + map((data) => { + // For paginated results that already contain the data wrapper, return the whole object + if (data?.data) { + return { + ...data, + data: isObject(data.data) ? this.transformResponse(data.data) : data.data, + }; + } + + return { + data: isObject(data) ? this.transformResponse(data) : data, + }; + }) + ); + } + + private transformResponse(response) { + if (isArray(response)) { + return response.map((item) => this.transformToPlain(item)); + } + + return this.transformToPlain(response); + } + + private transformToPlain(plainOrClass) { + return plainOrClass && plainOrClass.constructor !== Object ? classToPlain(plainOrClass) : plainOrClass; + } +} diff --git a/apps/api/src/app/shared/framework/user.decorator.ts b/apps/api/src/app/shared/framework/user.decorator.ts new file mode 100644 index 00000000000..16f852bdab3 --- /dev/null +++ b/apps/api/src/app/shared/framework/user.decorator.ts @@ -0,0 +1,50 @@ +import { createParamDecorator, UnauthorizedException } from '@nestjs/common'; +import * as jwt from 'jsonwebtoken'; + +export const UserSession = createParamDecorator((data, ctx) => { + let req; + if (ctx.getType() === 'graphql') { + req = ctx.getArgs()[2].req; + } else { + req = ctx.switchToHttp().getRequest(); + } + + if (req.user) return req.user; + + if (req.headers) { + if (req.headers.authorization) { + const tokenParts = req.headers.authorization.split(' '); + if (tokenParts[0] !== 'Bearer') throw new UnauthorizedException('bad_token'); + if (!tokenParts[1]) throw new UnauthorizedException('bad_token'); + + const user = jwt.decode(tokenParts[1]); + return user; + } + } + + return null; +}); + +export const SubscriberSession = createParamDecorator((data, ctx) => { + let req; + if (ctx.getType() === 'graphql') { + req = ctx.getArgs()[2].req; + } else { + req = ctx.switchToHttp().getRequest(); + } + + if (req.user) return req.user; + + if (req.headers) { + if (req.headers.authorization) { + const tokenParts = req.headers.authorization.split(' '); + if (tokenParts[0] !== 'Bearer') throw new UnauthorizedException('bad_token'); + if (!tokenParts[1]) throw new UnauthorizedException('bad_token'); + + const user = jwt.decode(tokenParts[1]); + return user; + } + } + + return null; +}); diff --git a/apps/api/src/app/shared/helpers/content.service.spec.ts b/apps/api/src/app/shared/helpers/content.service.spec.ts new file mode 100644 index 00000000000..bb1e91206ef --- /dev/null +++ b/apps/api/src/app/shared/helpers/content.service.spec.ts @@ -0,0 +1,184 @@ +import { expect } from 'chai'; +import { ChannelTypeEnum } from '@notifire/shared'; +import { ContentService } from './content.service'; + +describe('ContentService', function () { + describe('replaceVariables', function () { + it('should replace duplicates entries', function () { + const variables = { + firstName: 'Name', + lastName: 'Last Name', + }; + + const contentService = new ContentService(); + const modified = contentService.replaceVariables( + '{{firstName}} is the first {{firstName}} of {{firstName}}', + variables + ); + expect(modified).to.equal('Name is the first Name of Name'); + }); + + it('should replace multiple variables', function () { + const variables = { + firstName: 'Name', + lastName: 'Last Name', + }; + + const contentService = new ContentService(); + const modified = contentService.replaceVariables( + '{{firstName}} is the first {{lastName}} of {{firstName}}', + variables + ); + expect(modified).to.equal('Name is the first Last Name of Name'); + }); + + it('should not manipulate variables for text without them', function () { + const variables = { + firstName: 'Name', + lastName: 'Last Name', + }; + + const contentService = new ContentService(); + const modified = contentService.replaceVariables('This is a text without variables', variables); + expect(modified).to.equal('This is a text without variables'); + }); + }); + + describe('extractVariables', function () { + it('should not find any variables', function () { + const contentService = new ContentService(); + const extractVariables = contentService.extractVariables( + 'This is a text without variables {{ asdasdas }} {{ aasdasda sda{ {na}}' + ); + expect(extractVariables.length).to.equal(0); + expect(Array.isArray(extractVariables)).to.equal(true); + }); + + it('should extract all valid variables', function () { + const contentService = new ContentService(); + const extractVariables = contentService.extractVariables( + ' {{name}} d {{lastName}} dd {{_validName}} {{not valid}} aa {{0notValid}}tr {{organization_name}}' + ); + expect(extractVariables.length).to.equal(4); + expect(extractVariables).to.include('_validName'); + expect(extractVariables).to.include('lastName'); + expect(extractVariables).to.include('name'); + expect(extractVariables).to.include('organization_name'); + }); + }); + + describe('extractMessageVariables', function () { + it('should not extract variables', function () { + const contentService = new ContentService(); + const variables = contentService.extractMessageVariables([ + { + type: ChannelTypeEnum.IN_APP, + subject: 'Test', + content: 'Text', + }, + ]); + expect(variables.length).to.equal(0); + }); + + it('should extract subject variables', function () { + const contentService = new ContentService(); + const variables = contentService.extractMessageVariables([ + { + type: ChannelTypeEnum.EMAIL, + subject: 'Test {{firstName}}', + content: [], + }, + ]); + expect(variables.length).to.equal(2); + expect(variables).to.include('firstName'); + }); + + it('should add $phone when SMS channel Exists', function () { + const contentService = new ContentService(); + const variables = contentService.extractMessageVariables([ + { + type: ChannelTypeEnum.IN_APP, + subject: 'Test', + content: 'Text', + }, + { + type: ChannelTypeEnum.SMS, + content: 'Text', + }, + ]); + expect(variables.length).to.equal(1); + expect(variables[0]).to.equal('$phone'); + }); + + it('should add $email when EMAIL channel Exists', function () { + const contentService = new ContentService(); + const variables = contentService.extractMessageVariables([ + { + type: ChannelTypeEnum.EMAIL, + subject: 'Test', + content: 'Text', + }, + { + type: ChannelTypeEnum.IN_APP, + content: 'Text', + }, + ]); + expect(variables.length).to.equal(1); + expect(variables[0]).to.equal('$email'); + }); + + it('should extract email content variables', function () { + const contentService = new ContentService(); + const variables = contentService.extractMessageVariables([ + { + type: ChannelTypeEnum.EMAIL, + subject: 'Test {{firstName}}', + content: [ + { + content: 'Test of {{lastName}}', + type: 'text', + }, + { + content: 'Test of {{lastName}}', + type: 'text', + url: 'Test of {{url}}', + }, + ], + }, + { + type: ChannelTypeEnum.EMAIL, + subject: 'Test {{email}}', + content: [ + { + content: 'Test of {{lastName}}', + type: 'text', + }, + { + content: 'Test of {{lastName}}', + type: 'text', + url: 'Test of {{url}}', + }, + ], + }, + ]); + expect(variables.length).to.equal(5); + expect(variables).to.include('lastName'); + expect(variables).to.include('url'); + expect(variables).to.include('firstName'); + expect(variables).to.include('email'); + }); + + it('should extract in-app content variables', function () { + const contentService = new ContentService(); + const variables = contentService.extractMessageVariables([ + { + type: ChannelTypeEnum.IN_APP, + content: '{{customVariables}}', + }, + ]); + + expect(variables.length).to.equal(1); + expect(variables).to.include('customVariables'); + }); + }); +}); diff --git a/apps/api/src/app/shared/helpers/content.service.ts b/apps/api/src/app/shared/helpers/content.service.ts new file mode 100644 index 00000000000..68ce0005f94 --- /dev/null +++ b/apps/api/src/app/shared/helpers/content.service.ts @@ -0,0 +1,77 @@ +import { ChannelTypeEnum, IMessageTemplate } from '@notifire/shared'; + +export class ContentService { + replaceVariables(content: string, variables: { [key: string]: string }) { + if (!content) return content; + let modifiedContent = content; + + for (const key in variables) { + if (!variables.hasOwnProperty(key)) continue; + modifiedContent = modifiedContent.replace(new RegExp(`{{${key}}}`, 'g'), variables[key]); + } + + return modifiedContent; + } + + extractVariables(content: string): string[] { + if (!content) return []; + + const regExp = /{{([a-zA-Z_][a-zA-Z0-9_-]*?)}}/gm; + const matchedItems = content.match(regExp); + + const result = []; + if (!matchedItems || !Array.isArray(matchedItems)) { + return result; + } + + for (const item of matchedItems) { + result.push(item.replace('{{', '').replace('}}', '')); + } + + return result; + } + + extractMessageVariables(messages: IMessageTemplate[]): string[] { + const variables = []; + + for (const text of this.messagesTextIterator(messages)) { + const extractedVariables = this.extractVariables(text); + variables.push(...extractedVariables); + } + + const hasSmsMessage = !!messages.find((i) => i.type === ChannelTypeEnum.SMS); + if (hasSmsMessage) { + variables.push('$phone'); + } + + const hasEmailMessage = !!messages.find((i) => i.type === ChannelTypeEnum.EMAIL); + if (hasEmailMessage) { + variables.push('$email'); + } + + return Array.from(new Set(variables)); + } + + private *messagesTextIterator(messages: IMessageTemplate[]): Generator { + for (const message of messages) { + if (message.type === ChannelTypeEnum.IN_APP) { + yield message.content as string; + + if (message?.cta?.data?.url) { + yield message.cta.data.url; + } + } else if (message.type === ChannelTypeEnum.SMS) { + yield message.content as string; + } else if (Array.isArray(message.content)) { + yield message.subject; + + for (const block of message.content) { + yield block.url; + yield block.content; + } + } else if (typeof message.content === 'string') { + yield message.content; + } + } + } +} diff --git a/apps/api/src/app/shared/helpers/email-normalization.service.ts b/apps/api/src/app/shared/helpers/email-normalization.service.ts new file mode 100644 index 00000000000..7293c9a604f --- /dev/null +++ b/apps/api/src/app/shared/helpers/email-normalization.service.ts @@ -0,0 +1,48 @@ +const PLUS_ONLY = /\+.*$/; +const PLUS_AND_DOT = /\.|\+.*$/g; +const normalizeableProviders = { + 'gmail.com': { + cut: PLUS_AND_DOT, + }, + 'googlemail.com': { + cut: PLUS_AND_DOT, + aliasOf: 'gmail.com', + }, + 'hotmail.com': { + cut: PLUS_ONLY, + }, + 'live.com': { + cut: PLUS_AND_DOT, + }, + 'outlook.com': { + cut: PLUS_ONLY, + }, +}; + +export function normalizeEmail(email: string): string { + if (typeof email !== 'string') { + throw new TypeError('normalize-email expects a string'); + } + + const lowerCasedEmail = email.toLowerCase(); + const emailParts = lowerCasedEmail.split(/@/); + + if (emailParts.length !== 2) { + return email; + } + + let username = emailParts[0]; + let domain = emailParts[1]; + + if (normalizeableProviders.hasOwnProperty(domain)) { + if (normalizeableProviders[domain].hasOwnProperty('cut')) { + username = username.replace(normalizeableProviders[domain].cut, ''); + } + + if (normalizeableProviders[domain].hasOwnProperty('aliasOf')) { + domain = normalizeableProviders[domain].aliasOf; + } + } + + return `${username}@${domain}`; +} diff --git a/apps/api/src/app/shared/helpers/regex.service.ts b/apps/api/src/app/shared/helpers/regex.service.ts new file mode 100644 index 00000000000..56da4f3c4f7 --- /dev/null +++ b/apps/api/src/app/shared/helpers/regex.service.ts @@ -0,0 +1,5 @@ +export function escapeRegExp(text: string): string { + if (!text) return text; + + return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); +} diff --git a/apps/api/src/app/shared/services/analytics/analytics.service.ts b/apps/api/src/app/shared/services/analytics/analytics.service.ts new file mode 100644 index 00000000000..f4218f5c8aa --- /dev/null +++ b/apps/api/src/app/shared/services/analytics/analytics.service.ts @@ -0,0 +1,51 @@ +import * as MixpanelInstance from 'mixpanel'; + +import { Mixpanel } from 'mixpanel'; +import { UserEntity } from '@notifire/dal'; + +export class AnalyticsService { + private mixpanel: Mixpanel; + + async initialize() { + if (process.env.MIXPANEL_TOKEN) { + this.mixpanel = MixpanelInstance.init(process.env.MIXPANEL_TOKEN); + } + } + + alias(distinctId: string, userId: string) { + if (!this.analyticsEnabled) return; + + this.mixpanel.alias(distinctId, userId); + } + + upsertUser(user: UserEntity, distinctId: string) { + if (!this.analyticsEnabled) return; + + this.mixpanel.people.set(distinctId, { + $first_name: user.firstName, + $last_name: user.lastName, + $created: user.createdAt || new Date(), + $email: user.email, + userId: user._id, + }); + } + + setValue(userId: string, propertyName: string, value: string | number) { + if (!this.analyticsEnabled) return; + + this.mixpanel.people.set(userId, propertyName, value); + } + + track(name: string, userId: string, data: object = {}) { + if (!this.analyticsEnabled) return; + + this.mixpanel.track(name, { + distinct_id: userId, + ...data, + }); + } + + private get analyticsEnabled() { + return process.env.NODE_ENV !== 'test' && this.mixpanel; + } +} diff --git a/apps/api/src/app/shared/services/cron/cron.service.ts b/apps/api/src/app/shared/services/cron/cron.service.ts new file mode 100644 index 00000000000..227719ed957 --- /dev/null +++ b/apps/api/src/app/shared/services/cron/cron.service.ts @@ -0,0 +1,30 @@ +// eslint-disable-next-line import/no-named-default, import/no-duplicates +import { AgendaConfig, Processor } from 'agenda'; +// eslint-disable-next-line import/no-duplicates +import * as Agenda from 'agenda'; + +export class CronService { + private agenda: Agenda.Agenda = new (Agenda as any)({ + db: { + address: this.config.mongoUrl, + }, + } as AgendaConfig); + + constructor(private config: { mongoUrl: string }) {} + + async initialize() { + await this.agenda.start(); + } + + define(name: string, callback: Processor): void { + this.agenda.define(name, callback); + } + + async processEvery(name: string, interval: string) { + await this.agenda.every(interval, name, {}, {}); + } + + async processNow(name: string) { + await this.agenda.now(name, null); + } +} diff --git a/apps/api/src/app/shared/services/helper/helper.service.ts b/apps/api/src/app/shared/services/helper/helper.service.ts new file mode 100644 index 00000000000..976f00d76ef --- /dev/null +++ b/apps/api/src/app/shared/services/helper/helper.service.ts @@ -0,0 +1,18 @@ +import { v1 as uuidv1 } from 'uuid'; + +export function createGuid(): string { + return uuidv1(); +} + +export function capitalize(text: string) { + if (typeof text !== 'string') return ''; + + return text.charAt(0).toUpperCase() + text.slice(1); +} + +export function getFileExtensionFromPath(filePath: string): string { + const regexp = /\.([0-9a-z]+)(?:[?#]|$)/i; + const extension = filePath.match(regexp); + + return extension && extension[1]; +} diff --git a/apps/api/src/app/shared/services/mail/mail.service.ts b/apps/api/src/app/shared/services/mail/mail.service.ts new file mode 100644 index 00000000000..cc855fae386 --- /dev/null +++ b/apps/api/src/app/shared/services/mail/mail.service.ts @@ -0,0 +1,56 @@ +import * as sgApi from '@sendgrid/mail'; + +export type IEmailRecipient = string | { name?: string; email: string }; + +export interface ISendMail { + to: IEmailRecipient | IEmailRecipient[]; + from: { + name: string; + email: string; + }; + subject?: string; + text?: string; + html?: string; + templateId?: string; + params?: { + [key: string]: string | any[] | any; + }; +} + +export class MailService { + private sendgrid = sgApi; + + constructor() { + this.sendgrid.setApiKey(process.env.SENDGRID_API_KEY); + } + + async sendMail(mail: ISendMail) { + if (!mail.templateId && !mail.subject) throw new Error('Either templateId or subject must be present'); + if (process.env.NODE_ENV === 'test') return null; + + const mailObject: sgApi.MailDataRequired = { + subject: mail.subject, + dynamicTemplateData: mail.params, + to: mail.to, + from: { + name: mail.from.name, + email: mail.from.email, + }, + templateId: undefined, + }; + + if (mail.templateId) { + mailObject.templateId = mail.templateId; + } + + if (mail.text) { + mailObject.text = mail.text; + } + + if (mail.html) { + mailObject.html = mail.html; + } + + return await this.sendgrid.send(mailObject as never, false); + } +} diff --git a/apps/api/src/app/shared/services/queue/index.ts b/apps/api/src/app/shared/services/queue/index.ts new file mode 100644 index 00000000000..532c20b83fb --- /dev/null +++ b/apps/api/src/app/shared/services/queue/index.ts @@ -0,0 +1 @@ +export * from './queue.service'; diff --git a/apps/api/src/app/shared/services/queue/queue.interface.ts b/apps/api/src/app/shared/services/queue/queue.interface.ts new file mode 100644 index 00000000000..fe32c2f31c0 --- /dev/null +++ b/apps/api/src/app/shared/services/queue/queue.interface.ts @@ -0,0 +1,9 @@ +export interface IDemoQueuePayload { + userId: string; +} + +export interface IWsQueuePayload { + userId: string; + event: string; + payload: any; +} diff --git a/apps/api/src/app/shared/services/queue/queue.service.ts b/apps/api/src/app/shared/services/queue/queue.service.ts new file mode 100644 index 00000000000..bef42f63dcf --- /dev/null +++ b/apps/api/src/app/shared/services/queue/queue.service.ts @@ -0,0 +1,38 @@ +import * as Bull from 'bull'; +import { Queue } from 'bull'; +import { IWsQueuePayload } from './queue.interface'; + +export const WS_SOCKET_QUEUE = 'ws_socket_queue'; + +export class QueueService { + private bullConfig: Bull.QueueOptions = { + settings: { + lockDuration: 90000, + }, + redis: { + db: Number(process.env.REDIS_DB_INDEX), + port: Number(process.env.REDIS_PORT), + host: process.env.REDIS_HOST, + connectTimeout: 50000, + keepAlive: 30000, + family: 4, + }, + }; + + public wsSocketQueue: Queue = new Bull(WS_SOCKET_QUEUE, this.bullConfig) as Queue; + + async getJobStats(type: 'ws_socket_queue'): Promise<{ waiting: number; active: number }> { + if (type === WS_SOCKET_QUEUE) { + return { + waiting: await this.wsSocketQueue.getWaitingCount(), + active: await this.wsSocketQueue.getActiveCount(), + }; + } + + throw new Error(`Unexpected type ${type}`); + } + + async cleanAllQueues() { + await this.wsSocketQueue.empty(); + } +} diff --git a/apps/api/src/app/shared/services/sms/sms.service.ts b/apps/api/src/app/shared/services/sms/sms.service.ts new file mode 100644 index 00000000000..a53a13fc74b --- /dev/null +++ b/apps/api/src/app/shared/services/sms/sms.service.ts @@ -0,0 +1,19 @@ +import * as twilio from 'twilio'; + +export class SmsService { + private provider = process.env.NODE_ENV === 'test' ? null : twilio(this.SID, this.AUTH_TOKEN); + + constructor(private AUTH_TOKEN: string, private SID: string) {} + + async sendMessage(to: string, from: string, body: string) { + if (process.env.NODE_ENV === 'test') { + return null; + } + + return await this.provider.messages.create({ + body, + to, + from, + }); + } +} diff --git a/apps/api/src/app/shared/services/storage/storage.service.ts b/apps/api/src/app/shared/services/storage/storage.service.ts new file mode 100644 index 00000000000..08a41a2a935 --- /dev/null +++ b/apps/api/src/app/shared/services/storage/storage.service.ts @@ -0,0 +1,33 @@ +import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; +import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'; +import { URL } from 'url'; + +export interface IFilePath { + path: string; + name: string; +} + +export class StorageService { + private s3 = new S3Client({ + region: process.env.S3_REGION, + endpoint: process.env.S3_LOCAL_STACK || undefined, + forcePathStyle: true, + }); + + async getSignedUrl(key: string, contentType?: string) { + const command = new PutObjectCommand({ + Key: key, + Bucket: process.env.S3_BUCKET_NAME, + ACL: 'public-read', + ContentType: contentType, + }); + + const signedUrl = await getSignedUrl(this.s3, command, { expiresIn: 3600 }); + const parsedUrl = new URL(signedUrl); + + return { + signedUrl, + path: `${parsedUrl.origin}${parsedUrl.pathname}`, + }; + } +} diff --git a/apps/api/src/app/shared/shared.module.ts b/apps/api/src/app/shared/shared.module.ts new file mode 100644 index 00000000000..094f10b2c2d --- /dev/null +++ b/apps/api/src/app/shared/shared.module.ts @@ -0,0 +1,71 @@ +import { Module } from '@nestjs/common'; +import { + DalService, + UserRepository, + OrganizationRepository, + ApplicationRepository, + NotificationTemplateRepository, + SubscriberRepository, + NotificationRepository, + MessageRepository, + NotificationGroupRepository, + MessageTemplateRepository, + MemberRepository, + LogRepository, +} from '@notifire/dal'; +import { AnalyticsService } from './services/analytics/analytics.service'; +import { MailService } from './services/mail/mail.service'; +import { QueueService } from './services/queue'; +import { StorageService } from './services/storage/storage.service'; + +const DAL_MODELS = [ + UserRepository, + OrganizationRepository, + ApplicationRepository, + NotificationTemplateRepository, + SubscriberRepository, + NotificationRepository, + MessageRepository, + MessageTemplateRepository, + NotificationGroupRepository, + MemberRepository, + LogRepository, +]; + +const dalService = new DalService(); +export const ANALYTICS_SERVICE = 'AnalyticsService'; + +const PROVIDERS = [ + { + provide: QueueService, + useFactory: () => { + return new QueueService(); + }, + }, + { + provide: DalService, + useFactory: async () => { + await dalService.connect(process.env.MONGO_URL); + return dalService; + }, + }, + ...DAL_MODELS, + StorageService, + { + provide: ANALYTICS_SERVICE, + useFactory: async () => { + const analyticsService = new AnalyticsService(); + await analyticsService.initialize(); + + return analyticsService; + }, + }, + MailService, +]; + +@Module({ + imports: [], + providers: [...PROVIDERS], + exports: [...PROVIDERS], +}) +export class SharedModule {} diff --git a/apps/api/src/app/storage/e2e/get-signed-url.e2e.ts b/apps/api/src/app/storage/e2e/get-signed-url.e2e.ts new file mode 100644 index 00000000000..9a2eb9bf9cf --- /dev/null +++ b/apps/api/src/app/storage/e2e/get-signed-url.e2e.ts @@ -0,0 +1,21 @@ +import { UserSession } from '@notifire/testing'; +import { expect } from 'chai'; + +describe('Get Signed Url - /storage/upload-url (GET)', function () { + let session: UserSession; + + beforeEach(async () => { + session = new UserSession(); + await session.initialize(); + }); + + it('should return an S3 signed URL', async function () { + const { + body: { data }, + } = await session.testAgent.get('/v1/storage/upload-url?extension=jpg'); + + expect(data.path).to.contain('.jpg'); + expect(data.signedUrl).to.contain('.jpg'); + expect(data.signedUrl).to.contain(`${session.organization._id}/${session.application._id}`); + }); +}); diff --git a/apps/api/src/app/storage/storage.controller.ts b/apps/api/src/app/storage/storage.controller.ts new file mode 100644 index 00000000000..95155de58fd --- /dev/null +++ b/apps/api/src/app/storage/storage.controller.ts @@ -0,0 +1,25 @@ +import { Body, ClassSerializerInterceptor, Controller, Get, Query, UseGuards, UseInterceptors } from '@nestjs/common'; +import { IJwtPayload } from '@notifire/shared'; +import { GetSignedUrl } from './usecases/get-signed-url/get-signed-url.usecase'; +import { GetSignedUrlCommand } from './usecases/get-signed-url/get-signed-url.command'; +import { UserSession } from '../shared/framework/user.decorator'; +import { JwtAuthGuard } from '../auth/framework/auth.guard'; + +@Controller('/storage') +@UseInterceptors(ClassSerializerInterceptor) +@UseGuards(JwtAuthGuard) +export class StorageController { + constructor(private getSignedUrlUsecase: GetSignedUrl) {} + + @Get('/upload-url') + async signedUrl(@UserSession() user: IJwtPayload, @Query('extension') extension: string) { + return await this.getSignedUrlUsecase.execute( + GetSignedUrlCommand.create({ + applicationId: user.applicationId, + organizationId: user.organizationId, + userId: user._id, + extension, + }) + ); + } +} diff --git a/apps/api/src/app/storage/storage.module.ts b/apps/api/src/app/storage/storage.module.ts new file mode 100644 index 00000000000..1855ee2dd3d --- /dev/null +++ b/apps/api/src/app/storage/storage.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { USE_CASES } from './usecases'; +import { StorageController } from './storage.controller'; +import { SharedModule } from '../shared/shared.module'; + +@Module({ + imports: [SharedModule], + providers: [...USE_CASES], + controllers: [StorageController], +}) +export class StorageModule {} diff --git a/apps/api/src/app/storage/usecases/get-signed-url/get-signed-url.command.ts b/apps/api/src/app/storage/usecases/get-signed-url/get-signed-url.command.ts new file mode 100644 index 00000000000..f13d5f27a25 --- /dev/null +++ b/apps/api/src/app/storage/usecases/get-signed-url/get-signed-url.command.ts @@ -0,0 +1,13 @@ +import { IsEnum, IsIn, IsString } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithUserCommand } from '../../../shared/commands/project.command'; + +export class GetSignedUrlCommand extends ApplicationWithUserCommand { + static create(data: GetSignedUrlCommand) { + return CommandHelper.create(GetSignedUrlCommand, data); + } + + @IsString() + @IsIn(['jpg', 'png', 'jpeg']) + extension: string; +} diff --git a/apps/api/src/app/storage/usecases/get-signed-url/get-signed-url.usecase.ts b/apps/api/src/app/storage/usecases/get-signed-url/get-signed-url.usecase.ts new file mode 100644 index 00000000000..bb2ecba285b --- /dev/null +++ b/apps/api/src/app/storage/usecases/get-signed-url/get-signed-url.usecase.ts @@ -0,0 +1,27 @@ +import { Injectable } from '@nestjs/common'; +import * as hat from 'hat'; +import { StorageService } from '../../../shared/services/storage/storage.service'; +import { GetSignedUrlCommand } from './get-signed-url.command'; + +const mimeTypes = { + jpeg: 'image/jpeg', + png: 'image/png', +}; + +@Injectable() +export class GetSignedUrl { + constructor(private storageService: StorageService) {} + + async execute( + command: GetSignedUrlCommand + ): Promise<{ + signedUrl: string; + path: string; + }> { + const path = `${command.organizationId}/${command.applicationId}/${hat()}.${command.extension}`; + + const response = await this.storageService.getSignedUrl(path, mimeTypes[command.extension]); + + return response; + } +} diff --git a/apps/api/src/app/storage/usecases/index.ts b/apps/api/src/app/storage/usecases/index.ts new file mode 100644 index 00000000000..4a3311405f1 --- /dev/null +++ b/apps/api/src/app/storage/usecases/index.ts @@ -0,0 +1,6 @@ +import { GetSignedUrl } from './get-signed-url/get-signed-url.usecase'; + +export const USE_CASES = [ + GetSignedUrl, + // +]; diff --git a/apps/api/src/app/subscribers/subscribers.module.ts b/apps/api/src/app/subscribers/subscribers.module.ts new file mode 100644 index 00000000000..e420dc7bdce --- /dev/null +++ b/apps/api/src/app/subscribers/subscribers.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; +import { TerminusModule } from '@nestjs/terminus'; +import { SharedModule } from '../shared/shared.module'; +import { USE_CASES } from './usecases'; + +@Module({ + imports: [SharedModule, TerminusModule], + controllers: [], + providers: [...USE_CASES], + exports: [...USE_CASES], +}) +export class SubscribersModule {} diff --git a/apps/api/src/app/subscribers/usecases/create-subscriber/create-subscriber.command.ts b/apps/api/src/app/subscribers/usecases/create-subscriber/create-subscriber.command.ts new file mode 100644 index 00000000000..d47cd1c8cec --- /dev/null +++ b/apps/api/src/app/subscribers/usecases/create-subscriber/create-subscriber.command.ts @@ -0,0 +1,29 @@ +import { IsDefined, IsEmail, IsOptional, IsString } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationCommand } from '../../../shared/commands/project.command'; + +export class CreateSubscriberCommand extends ApplicationCommand { + static create(data: CreateSubscriberCommand) { + return CommandHelper.create(CreateSubscriberCommand, data); + } + + @IsString() + @IsDefined() + subscriberId: string; + + @IsEmail() + @IsOptional() + email?: string; + + @IsString() + @IsOptional() + firstName?: string; + + @IsString() + @IsOptional() + lastName?: string; + + @IsString() + @IsOptional() + phone?: string; +} diff --git a/apps/api/src/app/subscribers/usecases/create-subscriber/create-subscriber.spec.ts b/apps/api/src/app/subscribers/usecases/create-subscriber/create-subscriber.spec.ts new file mode 100644 index 00000000000..2a1c7355b63 --- /dev/null +++ b/apps/api/src/app/subscribers/usecases/create-subscriber/create-subscriber.spec.ts @@ -0,0 +1,60 @@ +import { Test } from '@nestjs/testing'; +import { UserSession } from '@notifire/testing'; +import { expect } from 'chai'; +import { CreateSubscriber } from './create-subscriber.usecase'; +import { SharedModule } from '../../../shared/shared.module'; +import { CreateSubscriberCommand } from './create-subscriber.command'; +import { SubscribersModule } from '../../subscribers.module'; + +describe('Create Subscriber', function () { + let useCase: CreateSubscriber; + let session: UserSession; + + beforeEach(async () => { + const moduleRef = await Test.createTestingModule({ + imports: [SharedModule, SubscribersModule], + providers: [], + }).compile(); + + session = new UserSession(); + await session.initialize(); + + useCase = moduleRef.get(CreateSubscriber); + }); + + it('should create a subscriber', async function () { + const result = await useCase.execute( + CreateSubscriberCommand.create({ + organizationId: session.organization._id, + applicationId: session.application._id, + subscriberId: '1234', + email: 'dima@asdasdas.com', + firstName: 'ASDAS', + }) + ); + }); + + it('should update the subscriber when same id provided', async function () { + await useCase.execute( + CreateSubscriberCommand.create({ + organizationId: session.organization._id, + applicationId: session.application._id, + subscriberId: '1234', + email: 'dima@asdasdas.com', + firstName: 'First Name', + }) + ); + + const result = await useCase.execute( + CreateSubscriberCommand.create({ + organizationId: session.organization._id, + applicationId: session.application._id, + subscriberId: '1234', + email: 'dima@asdasdas.com', + firstName: 'Second Name', + }) + ); + + expect(result.firstName).to.equal('Second Name'); + }); +}); diff --git a/apps/api/src/app/subscribers/usecases/create-subscriber/create-subscriber.usecase.ts b/apps/api/src/app/subscribers/usecases/create-subscriber/create-subscriber.usecase.ts new file mode 100644 index 00000000000..c61f3d5b220 --- /dev/null +++ b/apps/api/src/app/subscribers/usecases/create-subscriber/create-subscriber.usecase.ts @@ -0,0 +1,39 @@ +import { Injectable } from '@nestjs/common'; +import { SubscriberRepository } from '@notifire/dal'; +import { CreateSubscriberCommand } from './create-subscriber.command'; +import { UpdateSubscriber, UpdateSubscriberCommand } from '../update-subscriber'; + +@Injectable() +export class CreateSubscriber { + constructor(private subscriberRepository: SubscriberRepository, private updateSubscriber: UpdateSubscriber) {} + + async execute(command: CreateSubscriberCommand) { + let subscriber = await this.subscriberRepository.findBySubscriberId(command.applicationId, command.subscriberId); + + if (!subscriber) { + subscriber = await this.subscriberRepository.create({ + _applicationId: command.applicationId, + _organizationId: command.organizationId, + firstName: command.firstName, + lastName: command.lastName, + subscriberId: command.subscriberId, + email: command.email, + phone: command.phone, + }); + } else { + subscriber = await this.updateSubscriber.execute( + UpdateSubscriberCommand.create({ + applicationId: command.applicationId, + organizationId: command.organizationId, + firstName: command.firstName, + lastName: command.lastName, + subscriberId: command.subscriberId, + email: command.email, + phone: command.phone, + }) + ); + } + + return subscriber; + } +} diff --git a/apps/api/src/app/subscribers/usecases/create-subscriber/index.ts b/apps/api/src/app/subscribers/usecases/create-subscriber/index.ts new file mode 100644 index 00000000000..b63793678d2 --- /dev/null +++ b/apps/api/src/app/subscribers/usecases/create-subscriber/index.ts @@ -0,0 +1,2 @@ +export * from './create-subscriber.command'; +export * from './create-subscriber.usecase'; diff --git a/apps/api/src/app/subscribers/usecases/index.ts b/apps/api/src/app/subscribers/usecases/index.ts new file mode 100644 index 00000000000..6ec268d8f4c --- /dev/null +++ b/apps/api/src/app/subscribers/usecases/index.ts @@ -0,0 +1,4 @@ +import { CreateSubscriber } from './create-subscriber'; +import { UpdateSubscriber } from './update-subscriber'; + +export const USE_CASES = [CreateSubscriber, UpdateSubscriber]; diff --git a/apps/api/src/app/subscribers/usecases/update-subscriber/index.ts b/apps/api/src/app/subscribers/usecases/update-subscriber/index.ts new file mode 100644 index 00000000000..48db0462947 --- /dev/null +++ b/apps/api/src/app/subscribers/usecases/update-subscriber/index.ts @@ -0,0 +1,2 @@ +export * from './update-subscriber.command'; +export * from './update-subscriber.usecase'; diff --git a/apps/api/src/app/subscribers/usecases/update-subscriber/update-subscriber.command.ts b/apps/api/src/app/subscribers/usecases/update-subscriber/update-subscriber.command.ts new file mode 100644 index 00000000000..9a11eb51e86 --- /dev/null +++ b/apps/api/src/app/subscribers/usecases/update-subscriber/update-subscriber.command.ts @@ -0,0 +1,26 @@ +import { IsEmail, IsOptional, IsString } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationCommand } from '../../../shared/commands/project.command'; + +export class UpdateSubscriberCommand extends ApplicationCommand { + static create(data: UpdateSubscriberCommand) { + return CommandHelper.create(UpdateSubscriberCommand, data); + } + + @IsString() + subscriberId: string; + + @IsOptional() + firstName?: string; + + @IsOptional() + lastName?: string; + + @IsOptional() + @IsEmail() + email?: string; + + @IsOptional() + @IsString() + phone?: string; +} diff --git a/apps/api/src/app/subscribers/usecases/update-subscriber/update-subscriber.spec.ts b/apps/api/src/app/subscribers/usecases/update-subscriber/update-subscriber.spec.ts new file mode 100644 index 00000000000..eadaa3a3e07 --- /dev/null +++ b/apps/api/src/app/subscribers/usecases/update-subscriber/update-subscriber.spec.ts @@ -0,0 +1,42 @@ +import { SubscriberRepository } from '@notifire/dal'; +import { UserSession, SubscribersService } from '@notifire/testing'; +import { Test } from '@nestjs/testing'; +import { expect } from 'chai'; +import { SharedModule } from '../../../shared/shared.module'; +import { UpdateSubscriber } from './update-subscriber.usecase'; +import { UpdateSubscriberCommand } from './update-subscriber.command'; + +describe('Update Subscriber', function () { + let useCase: UpdateSubscriber; + let session: UserSession; + const subscriberRepository = new SubscriberRepository(); + beforeEach(async () => { + const moduleRef = await Test.createTestingModule({ + imports: [SharedModule], + providers: [UpdateSubscriber], + }).compile(); + + session = new UserSession(); + await session.initialize(); + + useCase = moduleRef.get(UpdateSubscriber); + }); + + it('should update subscribers name', async function () { + const subscriberService = new SubscribersService(session.organization._id, session.application._id); + const subscriber = await subscriberService.createSubscriber(); + await useCase.execute( + UpdateSubscriberCommand.create({ + organizationId: subscriber._organizationId, + subscriberId: subscriber.subscriberId, + lastName: 'Test Last Name', + applicationId: session.application._id, + }) + ); + + const updatedSubscriber = await subscriberRepository.findById(subscriber._id); + expect(updatedSubscriber.lastName).to.equal('Test Last Name'); + expect(updatedSubscriber.firstName).to.equal(subscriber.firstName); + expect(updatedSubscriber.email).to.equal(subscriber.email); + }); +}); diff --git a/apps/api/src/app/subscribers/usecases/update-subscriber/update-subscriber.usecase.ts b/apps/api/src/app/subscribers/usecases/update-subscriber/update-subscriber.usecase.ts new file mode 100644 index 00000000000..322ea8baeaf --- /dev/null +++ b/apps/api/src/app/subscribers/usecases/update-subscriber/update-subscriber.usecase.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@nestjs/common'; +import { SubscriberEntity, SubscriberRepository } from '@notifire/dal'; +import { UpdateSubscriberCommand } from './update-subscriber.command'; +import { ApiException } from '../../../shared/exceptions/api.exception'; + +@Injectable() +export class UpdateSubscriber { + constructor(private subscriberRepository: SubscriberRepository) {} + + async execute(command: UpdateSubscriberCommand) { + const foundSubscriber = await this.subscriberRepository.findBySubscriberId( + command.applicationId, + command.subscriberId + ); + + if (!foundSubscriber) { + throw new ApiException(`SubscriberId: ${command.subscriberId} not found`); + } + + const updatePayload: Partial = {}; + if (command.email != null) { + updatePayload.email = command.email; + } + + if (command.firstName != null) { + updatePayload.firstName = command.firstName; + } + + if (command.lastName != null) { + updatePayload.lastName = command.lastName; + } + + await this.subscriberRepository.update( + { + _id: foundSubscriber, + }, + { $set: updatePayload } + ); + + return { + ...foundSubscriber, + ...updatePayload, + }; + } +} diff --git a/apps/api/src/app/testing/dtos/seed-data.dto.ts b/apps/api/src/app/testing/dtos/seed-data.dto.ts new file mode 100644 index 00000000000..400b8e7de06 --- /dev/null +++ b/apps/api/src/app/testing/dtos/seed-data.dto.ts @@ -0,0 +1,8 @@ +import { UserEntity } from '@notifire/dal'; + +export class SeedDataBodyDto {} + +export interface ISeedDataResponseDto { + token: string; + user: UserEntity; +} diff --git a/apps/api/src/app/testing/testing.controller.ts b/apps/api/src/app/testing/testing.controller.ts new file mode 100644 index 00000000000..322aef30069 --- /dev/null +++ b/apps/api/src/app/testing/testing.controller.ts @@ -0,0 +1,48 @@ +import { Body, Controller, NotFoundException, Post } from '@nestjs/common'; +import { DalService } from '@notifire/dal'; +import { IUserEntity } from '@notifire/shared'; +import { ISeedDataResponseDto, SeedDataBodyDto } from './dtos/seed-data.dto'; +import { SeedData } from './usecases/seed-data/seed-data.usecase'; +import { SeedDataCommand } from './usecases/seed-data/seed-data.command'; +import { CreateSession } from './usecases/create-session/create-session.usecase'; +import { CreateSessionCommand } from './usecases/create-session/create-session.command'; + +@Controller('/testing') +export class TestingController { + constructor( + private seedDataUsecase: SeedData, + private dalService: DalService, + private createSessionUsecase: CreateSession + ) {} + + @Post('/clear-db') + async clearDB(@Body() body: SeedDataBodyDto): Promise<{ ok: boolean }> { + if (process.env.NODE_ENV !== 'test') throw new NotFoundException(); + + await this.dalService.destroy(); + + return { + ok: true, + }; + } + + /** + * Used for seeding data for client e2e tests, + * Currently just creates a new user session and returns signed JWT + */ + @Post('/session') + async getSession(@Body() body: SeedDataBodyDto): Promise { + if (process.env.NODE_ENV !== 'test') throw new NotFoundException(); + const command = CreateSessionCommand.create({}); + + return await this.createSessionUsecase.execute(command); + } + + @Post('/seed') + async seedData(@Body() body: SeedDataBodyDto): Promise<{ password_user: IUserEntity }> { + if (process.env.NODE_ENV !== 'test') throw new NotFoundException(); + const command = SeedDataCommand.create({}); + + return await this.seedDataUsecase.execute(command); + } +} diff --git a/apps/api/src/app/testing/testing.module.ts b/apps/api/src/app/testing/testing.module.ts new file mode 100644 index 00000000000..5b6b34a0ac1 --- /dev/null +++ b/apps/api/src/app/testing/testing.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; +import { USE_CASES } from './usecases'; +import { TestingController } from './testing.controller'; +import { SharedModule } from '../shared/shared.module'; +import { AuthModule } from '../auth/auth.module'; + +@Module({ + imports: [SharedModule, AuthModule], + providers: [...USE_CASES], + controllers: [TestingController], +}) +export class TestingModule {} diff --git a/apps/api/src/app/testing/usecases/create-session/create-session.command.ts b/apps/api/src/app/testing/usecases/create-session/create-session.command.ts new file mode 100644 index 00000000000..7b6df95e098 --- /dev/null +++ b/apps/api/src/app/testing/usecases/create-session/create-session.command.ts @@ -0,0 +1,7 @@ +import { CommandHelper } from '../../../shared/commands/command.helper'; + +export class CreateSessionCommand { + static create(data: CreateSessionCommand) { + return CommandHelper.create(CreateSessionCommand, data); + } +} diff --git a/apps/api/src/app/testing/usecases/create-session/create-session.usecase.ts b/apps/api/src/app/testing/usecases/create-session/create-session.usecase.ts new file mode 100644 index 00000000000..4460deada36 --- /dev/null +++ b/apps/api/src/app/testing/usecases/create-session/create-session.usecase.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@nestjs/common'; +import { UserSession } from '@notifire/testing'; +import { CreateSessionCommand } from './create-session.command'; + +@Injectable() +export class CreateSession { + async execute(command: CreateSessionCommand) { + const userSession = new UserSession(); + userSession.testServer = null; + await userSession.initialize(); + + return { + token: userSession.token, + user: userSession.user, + }; + } +} diff --git a/apps/api/src/app/testing/usecases/index.ts b/apps/api/src/app/testing/usecases/index.ts new file mode 100644 index 00000000000..289fa8ac809 --- /dev/null +++ b/apps/api/src/app/testing/usecases/index.ts @@ -0,0 +1,4 @@ +import { SeedData } from './seed-data/seed-data.usecase'; +import { CreateSession } from './create-session/create-session.usecase'; + +export const USE_CASES = [SeedData, CreateSession]; diff --git a/apps/api/src/app/testing/usecases/seed-data/seed-data.command.ts b/apps/api/src/app/testing/usecases/seed-data/seed-data.command.ts new file mode 100644 index 00000000000..87d941e0fb1 --- /dev/null +++ b/apps/api/src/app/testing/usecases/seed-data/seed-data.command.ts @@ -0,0 +1,7 @@ +import { CommandHelper } from '../../../shared/commands/command.helper'; + +export class SeedDataCommand { + static create(data: SeedDataCommand) { + return CommandHelper.create(SeedDataCommand, data); + } +} diff --git a/apps/api/src/app/testing/usecases/seed-data/seed-data.usecase.ts b/apps/api/src/app/testing/usecases/seed-data/seed-data.usecase.ts new file mode 100644 index 00000000000..87182730aee --- /dev/null +++ b/apps/api/src/app/testing/usecases/seed-data/seed-data.usecase.ts @@ -0,0 +1,27 @@ +import { Injectable } from '@nestjs/common'; +import * as faker from 'faker'; +import { SeedDataCommand } from './seed-data.command'; +import { AuthService } from '../../../auth/services/auth.service'; +import { UserRegister } from '../../../auth/usecases/register/user-register.usecase'; +import { UserRegisterCommand } from '../../../auth/usecases/register/user-register.command'; + +@Injectable() +export class SeedData { + constructor(private authService: AuthService, private userRegister: UserRegister) {} + + async execute(command: SeedDataCommand) { + const { user } = await this.userRegister.execute( + UserRegisterCommand.create({ + email: 'test-user-1@example.com', + firstName: faker.name.firstName(), + lastName: faker.name.lastName(), + password: '123qwe!@#', + organizationName: 'Test Organization', + }) + ); + + return { + password_user: user, + }; + } +} diff --git a/apps/api/src/app/user/dtos/get-my-profile.ts b/apps/api/src/app/user/dtos/get-my-profile.ts new file mode 100644 index 00000000000..280cfea17d1 --- /dev/null +++ b/apps/api/src/app/user/dtos/get-my-profile.ts @@ -0,0 +1,3 @@ +import { UserEntity } from '@notifire/dal'; + +export type IGetMyProfileDto = UserEntity; diff --git a/apps/api/src/app/user/usecases/create-user/create-user.dto.ts b/apps/api/src/app/user/usecases/create-user/create-user.dto.ts new file mode 100644 index 00000000000..ed5adcd5f21 --- /dev/null +++ b/apps/api/src/app/user/usecases/create-user/create-user.dto.ts @@ -0,0 +1,23 @@ +import { AuthProviderEnum } from '@notifire/shared'; +import { CommandHelper } from '../../../shared/commands/command.helper'; + +export class CreateUserCommand { + static create(data: CreateUserCommand) { + return CommandHelper.create(CreateUserCommand, data); + } + + email: string; + + firstName: string; + + lastName: string; + + picture?: string; + + auth: { + profileId: string; + provider: AuthProviderEnum; + accessToken: string; + refreshToken: string; + }; +} diff --git a/apps/api/src/app/user/usecases/create-user/create-user.usecase.ts b/apps/api/src/app/user/usecases/create-user/create-user.usecase.ts new file mode 100644 index 00000000000..916708ba9f1 --- /dev/null +++ b/apps/api/src/app/user/usecases/create-user/create-user.usecase.ts @@ -0,0 +1,29 @@ +import { Injectable } from '@nestjs/common'; +import { UserEntity, UserRepository } from '@notifire/dal'; +import { CreateUserCommand } from './create-user.dto'; + +@Injectable() +export class CreateUser { + constructor(private readonly userRepository: UserRepository) {} + + async execute(data: CreateUserCommand): Promise { + const user = new UserEntity(); + + user.email = data.email ? data.email.toLowerCase() : null; + user.firstName = data.firstName ? data.firstName.toLowerCase() : null; + user.lastName = data.lastName ? data.lastName.toLowerCase() : data.lastName; + user.profilePicture = data.picture; + user.tokens = [ + { + providerId: data.auth.profileId, + provider: data.auth.provider, + accessToken: data.auth.accessToken, + refreshToken: data.auth.refreshToken, + valid: true, + lastUsed: null, + }, + ]; + + return await this.userRepository.create(user); + } +} diff --git a/apps/api/src/app/user/usecases/get-my-profile/get-my-profile.dto.ts b/apps/api/src/app/user/usecases/get-my-profile/get-my-profile.dto.ts new file mode 100644 index 00000000000..4cd424d2dbc --- /dev/null +++ b/apps/api/src/app/user/usecases/get-my-profile/get-my-profile.dto.ts @@ -0,0 +1,8 @@ +import { AuthenticatedCommand } from '../../../shared/commands/authenticated.command'; +import { CommandHelper } from '../../../shared/commands/command.helper'; + +export class GetMyProfileCommand extends AuthenticatedCommand { + static create(data: GetMyProfileCommand) { + return CommandHelper.create(GetMyProfileCommand, data); + } +} diff --git a/apps/api/src/app/user/usecases/get-my-profile/get-my-profile.usecase.ts b/apps/api/src/app/user/usecases/get-my-profile/get-my-profile.usecase.ts new file mode 100644 index 00000000000..c756554406b --- /dev/null +++ b/apps/api/src/app/user/usecases/get-my-profile/get-my-profile.usecase.ts @@ -0,0 +1,12 @@ +import { Injectable } from '@nestjs/common'; +import { UserRepository } from '@notifire/dal'; +import { GetMyProfileCommand } from './get-my-profile.dto'; + +@Injectable() +export class GetMyProfileUsecase { + constructor(private readonly userRepository: UserRepository) {} + + async execute(command: GetMyProfileCommand) { + return await this.userRepository.findById(command.userId); + } +} diff --git a/apps/api/src/app/user/usecases/index.ts b/apps/api/src/app/user/usecases/index.ts new file mode 100644 index 00000000000..e518928959a --- /dev/null +++ b/apps/api/src/app/user/usecases/index.ts @@ -0,0 +1,4 @@ +import { CreateUser } from './create-user/create-user.usecase'; +import { GetMyProfileUsecase } from './get-my-profile/get-my-profile.usecase'; + +export const USE_CASES = [CreateUser, GetMyProfileUsecase]; diff --git a/apps/api/src/app/user/user.controller.ts b/apps/api/src/app/user/user.controller.ts new file mode 100644 index 00000000000..e9e3003bed2 --- /dev/null +++ b/apps/api/src/app/user/user.controller.ts @@ -0,0 +1,24 @@ +import { ClassSerializerInterceptor, Controller, Get, UseGuards, UseInterceptors } from '@nestjs/common'; +import { AuthGuard } from '@nestjs/passport'; +import { IJwtPayload } from '@notifire/shared'; +import { UserSession } from '../shared/framework/user.decorator'; +import { GetMyProfileUsecase } from './usecases/get-my-profile/get-my-profile.usecase'; +import { GetMyProfileCommand } from './usecases/get-my-profile/get-my-profile.dto'; +import { IGetMyProfileDto } from './dtos/get-my-profile'; +import { JwtAuthGuard } from '../auth/framework/auth.guard'; + +@Controller('/users') +@UseInterceptors(ClassSerializerInterceptor) +@UseGuards(JwtAuthGuard) +export class UsersController { + constructor(private getMyProfileUsecase: GetMyProfileUsecase) {} + + @Get('/me') + async getMyProfile(@UserSession() user: IJwtPayload): Promise { + const command = GetMyProfileCommand.create({ + userId: user._id, + }); + + return await this.getMyProfileUsecase.execute(command); + } +} diff --git a/apps/api/src/app/user/user.module.ts b/apps/api/src/app/user/user.module.ts new file mode 100644 index 00000000000..75b03882a2c --- /dev/null +++ b/apps/api/src/app/user/user.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; +import { SharedModule } from '../shared/shared.module'; +import { USE_CASES } from './usecases'; +import { UsersController } from './user.controller'; + +@Module({ + imports: [SharedModule], + controllers: [UsersController], + providers: [...USE_CASES], + exports: [...USE_CASES], +}) +export class UserModule {} diff --git a/apps/api/src/app/widgets/dtos/session-initialize.dto.ts b/apps/api/src/app/widgets/dtos/session-initialize.dto.ts new file mode 100644 index 00000000000..1875944362e --- /dev/null +++ b/apps/api/src/app/widgets/dtos/session-initialize.dto.ts @@ -0,0 +1,24 @@ +import { IsDefined, IsEmail, IsOptional, IsString } from 'class-validator'; + +export class SessionInitializeBodyDto { + @IsString() + @IsDefined() + $user_id: string; + + @IsString() + @IsDefined() + applicationIdentifier: string; + + @IsString() + $first_name: string; + + @IsString() + $last_name: string; + + @IsEmail() + $email: string; + + @IsString() + @IsOptional() + $phone: string; +} diff --git a/apps/api/src/app/widgets/e2e/initialize-widget-session.e2e.ts b/apps/api/src/app/widgets/e2e/initialize-widget-session.e2e.ts new file mode 100644 index 00000000000..c4858e9ec53 --- /dev/null +++ b/apps/api/src/app/widgets/e2e/initialize-widget-session.e2e.ts @@ -0,0 +1,32 @@ +import { UserSession } from '@notifire/testing'; +import * as jwt from 'jsonwebtoken'; +import { expect } from 'chai'; + +describe('Initialize Session - /widgets/session/initialize (POST)', async () => { + let session: UserSession; + + before(async () => { + session = new UserSession(); + await session.initialize(); + }); + + it('should create a valid app session for current widget user', async function () { + const { body } = await session.testAgent + .post('/v1/widgets/session/initialize') + .send({ + applicationIdentifier: session.application.identifier, + $user_id: '12345', + $first_name: 'Test', + $last_name: 'User', + $email: 'test@example.com', + $phone: '054777777', + }) + .expect(201); + + expect(body.data.token).to.be.ok; + expect(body.data.profile._id).to.be.ok; + expect(body.data.profile.firstName).to.equal('Test'); + expect(body.data.profile.phone).to.equal('054777777'); + expect(body.data.profile.lastName).to.equal('User'); + }); +}); diff --git a/apps/api/src/app/widgets/e2e/mark-as-seen.e2e.ts b/apps/api/src/app/widgets/e2e/mark-as-seen.e2e.ts new file mode 100644 index 00000000000..a25623284ea --- /dev/null +++ b/apps/api/src/app/widgets/e2e/mark-as-seen.e2e.ts @@ -0,0 +1,58 @@ +import { MessageRepository, NotificationTemplateEntity } from '@notifire/dal'; +import { UserSession } from '@notifire/testing'; +import axios from 'axios'; +import { ChannelTypeEnum } from '@notifire/shared'; +import { expect } from 'chai'; + +describe('Mark as Seen - /widgets/messages/:messageId/seen (POST)', async () => { + const messageRepository = new MessageRepository(); + let session: UserSession; + let template: NotificationTemplateEntity; + before(async () => { + session = new UserSession(); + await session.initialize(); + template = await session.createTemplate(); + }); + + it('should change the seen status', async function () { + const { body } = await session.testAgent + .post('/v1/widgets/session/initialize') + .send({ + applicationIdentifier: session.application.identifier, + $user_id: '12345', + $first_name: 'Test', + $last_name: 'User', + $email: 'test@example.com', + }) + .expect(201); + + await session.triggerEvent(template.triggers[0].identifier, { + $user_id: '12345', + }); + + await session.triggerEvent(template.triggers[0].identifier, { + $user_id: '12345', + }); + const { token } = body.data; + const messages = await messageRepository.findBySubscriberChannel( + session.application._id, + body.data.profile._id, + ChannelTypeEnum.IN_APP + ); + const messageId = messages[0]._id; + expect(messages[0].seen).to.equal(false); + await axios.post( + `http://localhost:${process.env.PORT}/v1/widgets/messages/${messageId}/seen`, + {}, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + ); + + const modifiedMessage = await messageRepository.findById(messageId); + expect(modifiedMessage.seen).to.equal(true); + expect(modifiedMessage.lastSeenDate).to.be.ok; + }); +}); diff --git a/apps/api/src/app/widgets/usecases/get-application-data/get-application-data.command.ts b/apps/api/src/app/widgets/usecases/get-application-data/get-application-data.command.ts new file mode 100644 index 00000000000..65224abfbae --- /dev/null +++ b/apps/api/src/app/widgets/usecases/get-application-data/get-application-data.command.ts @@ -0,0 +1,8 @@ +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithSubscriber } from '../../../shared/commands/project.command'; + +export class GetApplicationDataCommand extends ApplicationWithSubscriber { + static create(data: GetApplicationDataCommand) { + return CommandHelper.create(GetApplicationDataCommand, data); + } +} diff --git a/apps/api/src/app/widgets/usecases/get-application-data/get-application-data.usecase.ts b/apps/api/src/app/widgets/usecases/get-application-data/get-application-data.usecase.ts new file mode 100644 index 00000000000..3afbe0af0cd --- /dev/null +++ b/apps/api/src/app/widgets/usecases/get-application-data/get-application-data.usecase.ts @@ -0,0 +1,18 @@ +import { Injectable } from '@nestjs/common'; +import { ApplicationEntity, ApplicationRepository } from '@notifire/dal'; +import { GetApplicationDataCommand } from './get-application-data.command'; + +@Injectable() +export class GetApplicationData { + constructor(private applicationRepository: ApplicationRepository) {} + + async execute(command: GetApplicationDataCommand): Promise> { + const application = await this.applicationRepository.findById(command.applicationId); + + return { + _id: application._id, + name: application.name, + branding: application.branding, + }; + } +} diff --git a/apps/api/src/app/widgets/usecases/get-notifications-feed/get-notifications-feed.command.ts b/apps/api/src/app/widgets/usecases/get-notifications-feed/get-notifications-feed.command.ts new file mode 100644 index 00000000000..9cb9c8d8df6 --- /dev/null +++ b/apps/api/src/app/widgets/usecases/get-notifications-feed/get-notifications-feed.command.ts @@ -0,0 +1,12 @@ +import { IsNumber, IsPositive } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithSubscriber } from '../../../shared/commands/project.command'; + +export class GetNotificationsFeedCommand extends ApplicationWithSubscriber { + static create(data: GetNotificationsFeedCommand) { + return CommandHelper.create(GetNotificationsFeedCommand, data); + } + + @IsNumber() + page: number; +} diff --git a/apps/api/src/app/widgets/usecases/get-notifications-feed/get-notifications-feed.usecase.ts b/apps/api/src/app/widgets/usecases/get-notifications-feed/get-notifications-feed.usecase.ts new file mode 100644 index 00000000000..4b226ca9316 --- /dev/null +++ b/apps/api/src/app/widgets/usecases/get-notifications-feed/get-notifications-feed.usecase.ts @@ -0,0 +1,21 @@ +import { Injectable } from '@nestjs/common'; +import { MessageEntity, MessageRepository } from '@notifire/dal'; +import { ChannelTypeEnum } from '@notifire/shared'; +import { GetNotificationsFeedCommand } from './get-notifications-feed.command'; + +@Injectable() +export class GetNotificationsFeed { + constructor(private messageRepository: MessageRepository) {} + + async execute(command: GetNotificationsFeedCommand): Promise { + return await this.messageRepository.findBySubscriberChannel( + command.applicationId, + command.subscriberId, + ChannelTypeEnum.IN_APP, + { + limit: 10, + skip: command.page * 10, + } + ); + } +} diff --git a/apps/api/src/app/widgets/usecases/get-unseen-count/get-unseen-count.command.ts b/apps/api/src/app/widgets/usecases/get-unseen-count/get-unseen-count.command.ts new file mode 100644 index 00000000000..a284261fc48 --- /dev/null +++ b/apps/api/src/app/widgets/usecases/get-unseen-count/get-unseen-count.command.ts @@ -0,0 +1,8 @@ +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithSubscriber } from '../../../shared/commands/project.command'; + +export class GetUnseenCountCommand extends ApplicationWithSubscriber { + static create(data: GetUnseenCountCommand) { + return CommandHelper.create(GetUnseenCountCommand, data); + } +} diff --git a/apps/api/src/app/widgets/usecases/get-unseen-count/get-unseen-count.usecase.ts b/apps/api/src/app/widgets/usecases/get-unseen-count/get-unseen-count.usecase.ts new file mode 100644 index 00000000000..15a6fe7a180 --- /dev/null +++ b/apps/api/src/app/widgets/usecases/get-unseen-count/get-unseen-count.usecase.ts @@ -0,0 +1,21 @@ +import { Injectable } from '@nestjs/common'; +import { MessageRepository } from '@notifire/dal'; +import { ChannelTypeEnum } from '@notifire/shared'; +import { GetUnseenCountCommand } from './get-unseen-count.command'; + +@Injectable() +export class GetUnseenCount { + constructor(private messageRepository: MessageRepository) {} + + async execute(command: GetUnseenCountCommand): Promise<{ count: number }> { + const count = await this.messageRepository.getUnseenCount( + command.applicationId, + command.subscriberId, + ChannelTypeEnum.IN_APP + ); + + return { + count, + }; + } +} diff --git a/apps/api/src/app/widgets/usecases/get-widget-settings/get-widget-settings.command.ts b/apps/api/src/app/widgets/usecases/get-widget-settings/get-widget-settings.command.ts new file mode 100644 index 00000000000..99a7ec85ce9 --- /dev/null +++ b/apps/api/src/app/widgets/usecases/get-widget-settings/get-widget-settings.command.ts @@ -0,0 +1,12 @@ +import { IsDefined, IsString } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; + +export class GetWidgetSettingsCommand { + static create(data: GetWidgetSettingsCommand) { + return CommandHelper.create(GetWidgetSettingsCommand, data); + } + + @IsDefined() + @IsString() + identifier: string; +} diff --git a/apps/api/src/app/widgets/usecases/get-widget-settings/get-widget-settings.usecase.ts b/apps/api/src/app/widgets/usecases/get-widget-settings/get-widget-settings.usecase.ts new file mode 100644 index 00000000000..4090afda120 --- /dev/null +++ b/apps/api/src/app/widgets/usecases/get-widget-settings/get-widget-settings.usecase.ts @@ -0,0 +1,22 @@ +import { Injectable } from '@nestjs/common'; +import { ApplicationRepository } from '@notifire/dal'; +import { GetWidgetSettingsCommand } from './get-widget-settings.command'; + +@Injectable() +export class GetWidgetSettings { + constructor(private applicationRepository: ApplicationRepository) {} + + async execute( + command: GetWidgetSettingsCommand + ): Promise<{ + _id: string; + _organizationId: string; + }> { + const application = await this.applicationRepository.findApplicationByIdentifier(command.identifier); + + return { + _id: application._id, + _organizationId: application._organizationId, + }; + } +} diff --git a/apps/api/src/app/widgets/usecases/index.ts b/apps/api/src/app/widgets/usecases/index.ts new file mode 100644 index 00000000000..d448cec002b --- /dev/null +++ b/apps/api/src/app/widgets/usecases/index.ts @@ -0,0 +1,16 @@ +import { GetApplicationData } from './get-application-data/get-application-data.usecase'; +import { MarkMessageAsSeen } from './mark-message-as-seen/mark-message-as-seen.usecase'; +import { GetUnseenCount } from './get-unseen-count/get-unseen-count.usecase'; +import { GetNotificationsFeed } from './get-notifications-feed/get-notifications-feed.usecase'; +import { InitializeSession } from './initialize-session/initialize-session.usecase'; +import { GetWidgetSettings } from './get-widget-settings/get-widget-settings.usecase'; + +export const USE_CASES = [ + GetApplicationData, + MarkMessageAsSeen, + GetUnseenCount, + GetNotificationsFeed, + InitializeSession, + GetWidgetSettings, + // +]; diff --git a/apps/api/src/app/widgets/usecases/initialize-session/initialize-session.command.ts b/apps/api/src/app/widgets/usecases/initialize-session/initialize-session.command.ts new file mode 100644 index 00000000000..42dc1422bfe --- /dev/null +++ b/apps/api/src/app/widgets/usecases/initialize-session/initialize-session.command.ts @@ -0,0 +1,27 @@ +import { IsDefined, IsEmail, IsOptional, IsString } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; + +export class InitializeSessionCommand { + static create(data: InitializeSessionCommand) { + return CommandHelper.create(InitializeSessionCommand, data); + } + + @IsDefined() + @IsString() + subscriberId: string; + + @IsDefined() + @IsString() + applicationIdentifier: string; + + firstName?: string; + + lastName?: string; + + @IsEmail() + email?: string; + + @IsString() + @IsOptional() + phone?: string; +} diff --git a/apps/api/src/app/widgets/usecases/initialize-session/initialize-session.usecase.ts b/apps/api/src/app/widgets/usecases/initialize-session/initialize-session.usecase.ts new file mode 100644 index 00000000000..dafdd6d79ab --- /dev/null +++ b/apps/api/src/app/widgets/usecases/initialize-session/initialize-session.usecase.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@nestjs/common'; +import { ApplicationRepository, SubscriberEntity } from '@notifire/dal'; +import { AuthService } from '../../../auth/services/auth.service'; +import { CreateSubscriber, CreateSubscriberCommand } from '../../../subscribers/usecases/create-subscriber'; +import { InitializeSessionCommand } from './initialize-session.command'; + +@Injectable() +export class InitializeSession { + constructor( + private applicationRepository: ApplicationRepository, + private createSubscriber: CreateSubscriber, + private authService: AuthService + ) {} + + async execute( + command: InitializeSessionCommand + ): Promise<{ + token: string; + profile: Partial; + }> { + const application = await this.applicationRepository.findApplicationByIdentifier(command.applicationIdentifier); + + const commandos = CreateSubscriberCommand.create({ + applicationId: application._id, + organizationId: application._organizationId, + subscriberId: command.subscriberId, + firstName: command.firstName, + lastName: command.lastName, + email: command.email, + phone: command.phone, + }); + + const subscriber = await this.createSubscriber.execute(commandos); + + return { + token: await this.authService.getSubscriberWidgetToken(subscriber), + profile: { + _id: subscriber._id, + firstName: subscriber.firstName, + lastName: subscriber.lastName, + phone: subscriber.phone, + }, + }; + } +} diff --git a/apps/api/src/app/widgets/usecases/mark-message-as-seen/mark-message-as-seen.command.ts b/apps/api/src/app/widgets/usecases/mark-message-as-seen/mark-message-as-seen.command.ts new file mode 100644 index 00000000000..d8f95c8d447 --- /dev/null +++ b/apps/api/src/app/widgets/usecases/mark-message-as-seen/mark-message-as-seen.command.ts @@ -0,0 +1,12 @@ +import { IsMongoId } from 'class-validator'; +import { CommandHelper } from '../../../shared/commands/command.helper'; +import { ApplicationWithSubscriber } from '../../../shared/commands/project.command'; + +export class MarkMessageAsSeenCommand extends ApplicationWithSubscriber { + static create(data: MarkMessageAsSeenCommand) { + return CommandHelper.create(MarkMessageAsSeenCommand, data); + } + + @IsMongoId() + messageId: string; +} diff --git a/apps/api/src/app/widgets/usecases/mark-message-as-seen/mark-message-as-seen.usecase.ts b/apps/api/src/app/widgets/usecases/mark-message-as-seen/mark-message-as-seen.usecase.ts new file mode 100644 index 00000000000..ec30f730f04 --- /dev/null +++ b/apps/api/src/app/widgets/usecases/mark-message-as-seen/mark-message-as-seen.usecase.ts @@ -0,0 +1,30 @@ +import { Injectable } from '@nestjs/common'; +import { MessageEntity, MessageRepository } from '@notifire/dal'; +import { ChannelTypeEnum } from '@notifire/shared'; +import { QueueService } from '../../../shared/services/queue'; +import { MarkMessageAsSeenCommand } from './mark-message-as-seen.command'; + +@Injectable() +export class MarkMessageAsSeen { + constructor(private messageRepository: MessageRepository, private queueService: QueueService) {} + + async execute(command: MarkMessageAsSeenCommand): Promise { + await this.messageRepository.changeSeenStatus(command.subscriberId, command.messageId, true); + + const count = await this.messageRepository.getUnseenCount( + command.applicationId, + command.subscriberId, + ChannelTypeEnum.IN_APP + ); + + this.queueService.wsSocketQueue.add({ + event: 'unseen_count_changed', + userId: command.subscriberId, + payload: { + unseenCount: count, + }, + }); + + return await this.messageRepository.findById(command.messageId); + } +} diff --git a/apps/api/src/app/widgets/widgets.controller.ts b/apps/api/src/app/widgets/widgets.controller.ts new file mode 100644 index 00000000000..c18f4793b3a --- /dev/null +++ b/apps/api/src/app/widgets/widgets.controller.ts @@ -0,0 +1,110 @@ +import { Body, Controller, Get, Param, Post, Query, UseGuards } from '@nestjs/common'; +import { AuthGuard } from '@nestjs/passport'; +import { MessageEntity, SubscriberEntity } from '@notifire/dal'; +import { SessionInitializeBodyDto } from './dtos/session-initialize.dto'; +import { InitializeSessionCommand } from './usecases/initialize-session/initialize-session.command'; +import { InitializeSession } from './usecases/initialize-session/initialize-session.usecase'; +import { GetNotificationsFeed } from './usecases/get-notifications-feed/get-notifications-feed.usecase'; +import { GetNotificationsFeedCommand } from './usecases/get-notifications-feed/get-notifications-feed.command'; +import { SubscriberSession } from '../shared/framework/user.decorator'; +import { GetUnseenCount } from './usecases/get-unseen-count/get-unseen-count.usecase'; +import { GetUnseenCountCommand } from './usecases/get-unseen-count/get-unseen-count.command'; +import { MarkMessageAsSeenCommand } from './usecases/mark-message-as-seen/mark-message-as-seen.command'; +import { MarkMessageAsSeen } from './usecases/mark-message-as-seen/mark-message-as-seen.usecase'; +import { GetApplicationData } from './usecases/get-application-data/get-application-data.usecase'; +import { GetApplicationDataCommand } from './usecases/get-application-data/get-application-data.command'; +import { AnalyticsService } from '../shared/services/analytics/analytics.service'; + +@Controller('/widgets') +export class WidgetsController { + constructor( + private initializeSessionUsecase: InitializeSession, + private getNotificationsFeedUsecase: GetNotificationsFeed, + private genUnseenCountUsecase: GetUnseenCount, + private markMessageAsSeenUsecase: MarkMessageAsSeen, + private getApplicationUsecase: GetApplicationData, + private analyticsService: AnalyticsService + ) {} + + @Post('/session/initialize') + async sessionInitialize(@Body() body: SessionInitializeBodyDto) { + return await this.initializeSessionUsecase.execute( + InitializeSessionCommand.create({ + subscriberId: body.$user_id, + applicationIdentifier: body.applicationIdentifier, + email: body.$email, + firstName: body.$first_name, + lastName: body.$last_name, + phone: body.$phone, + }) + ); + } + + @UseGuards(AuthGuard('subscriberJwt')) + @Get('/notifications/feed') + async getNotificationsFeed(@SubscriberSession() subscriberSession: SubscriberEntity, @Query('page') page: number) { + const command = GetNotificationsFeedCommand.create({ + organizationId: subscriberSession._organizationId, + subscriberId: subscriberSession._id, + applicationId: subscriberSession._applicationId, + page, + }); + + return await this.getNotificationsFeedUsecase.execute(command); + } + + @UseGuards(AuthGuard('subscriberJwt')) + @Get('/notifications/unseen') + async getUnseenCount(@SubscriberSession() subscriberSession: SubscriberEntity): Promise<{ count: number }> { + const command = GetUnseenCountCommand.create({ + organizationId: subscriberSession._organizationId, + subscriberId: subscriberSession._id, + applicationId: subscriberSession._applicationId, + }); + return await this.genUnseenCountUsecase.execute(command); + } + + @UseGuards(AuthGuard('subscriberJwt')) + @Post('/messages/:messageId/seen') + async markMessageAsSeen( + @SubscriberSession() subscriberSession: SubscriberEntity, + @Param('messageId') messageId: string + ): Promise { + const command = MarkMessageAsSeenCommand.create({ + organizationId: subscriberSession._organizationId, + subscriberId: subscriberSession._id, + applicationId: subscriberSession._applicationId, + messageId, + }); + + return await this.markMessageAsSeenUsecase.execute(command); + } + + @UseGuards(AuthGuard('subscriberJwt')) + @Get('/application') + async getApplication(@SubscriberSession() subscriberSession: SubscriberEntity) { + const command = GetApplicationDataCommand.create({ + organizationId: subscriberSession._organizationId, + subscriberId: subscriberSession._id, + applicationId: subscriberSession._applicationId, + }); + + return await this.getApplicationUsecase.execute(command); + } + + @UseGuards(AuthGuard('subscriberJwt')) + @Post('/usage/log') + async logUsage( + @SubscriberSession() subscriberSession: SubscriberEntity, + @Body() body: { name: string; payload: any } + ) { + this.analyticsService.track(body.name, subscriberSession._organizationId, { + applicationId: subscriberSession._applicationId, + ...(body.payload || {}), + }); + + return { + success: true, + }; + } +} diff --git a/apps/api/src/app/widgets/widgets.module.ts b/apps/api/src/app/widgets/widgets.module.ts new file mode 100644 index 00000000000..6f3f736fbd0 --- /dev/null +++ b/apps/api/src/app/widgets/widgets.module.ts @@ -0,0 +1,14 @@ +import { Module } from '@nestjs/common'; +import { USE_CASES } from './usecases'; +import { WidgetsController } from './widgets.controller'; +import { SharedModule } from '../shared/shared.module'; +import { AuthModule } from '../auth/auth.module'; +import { SubscribersModule } from '../subscribers/subscribers.module'; + +@Module({ + imports: [SharedModule, SubscribersModule, AuthModule], + providers: [...USE_CASES], + exports: [], + controllers: [WidgetsController], +}) +export class WidgetsModule {} diff --git a/apps/api/src/bootstrap.ts b/apps/api/src/bootstrap.ts new file mode 100644 index 00000000000..360548f24db --- /dev/null +++ b/apps/api/src/bootstrap.ts @@ -0,0 +1,93 @@ +import './config'; +import 'newrelic'; +import '@sentry/tracing'; + +import { INestApplication, ValidationPipe, Logger } from '@nestjs/common'; +import * as passport from 'passport'; +import * as compression from 'compression'; +import { NestFactory, Reflector } from '@nestjs/core'; + +import * as Sentry from '@sentry/node'; +import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; + +import { ExpressAdapter } from '@nestjs/platform-express'; +import { version } from '../package.json'; +import { AppModule } from './app.module'; +import { ResponseInterceptor } from './app/shared/framework/response.interceptor'; +import { RolesGuard } from './app/auth/framework/roles.guard'; +import { SubscriberRouteGuard } from './app/auth/framework/subscriber-route.guard'; +import { validateEnv } from './config/env-validator'; + +if (process.env.SENTRY_DSN) { + Sentry.init({ + dsn: process.env.SENTRY_DSN, + environment: process.env.NODE_ENV, + release: `v${version}`, + integrations: [ + // enable HTTP calls tracing + new Sentry.Integrations.Http({ tracing: true }), + ], + }); +} + +// Validate the ENV variables after launching SENTRY, so missing variables will report to sentry +validateEnv(); +// +export async function bootstrap(expressApp?): Promise { + let app; + if (expressApp) { + app = await NestFactory.create(AppModule, new ExpressAdapter(expressApp)); + } else { + app = await NestFactory.create(AppModule); + } + + if (process.env.SENTRY_DSN) { + app.use(Sentry.Handlers.requestHandler()); + app.use(Sentry.Handlers.tracingHandler()); + } + + app.enableCors({ + origin: + process.env.NODE_ENV === 'dev' || process.env.NODE_ENV === 'test' + ? '*' + : [process.env.FRONT_BASE_URL, process.env.WIDGET_BASE_URL], + preflightContinue: false, + allowedHeaders: ['Content-Type', 'Authorization', 'sentry-trace'], + methods: ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'OPTIONS'], + }); + + app.setGlobalPrefix('v1'); + + app.use(passport.initialize()); + + app.useGlobalPipes( + new ValidationPipe({ + transform: true, + }) + ); + + app.useGlobalInterceptors(new ResponseInterceptor()); + app.useGlobalGuards(new RolesGuard(app.get(Reflector))); + app.useGlobalGuards(new SubscriberRouteGuard(app.get(Reflector))); + + app.use(compression()); + + if (process.env.NODE_ENV === 'dev' || process.env.NODE_ENV === 'local') { + const options = new DocumentBuilder() + .setTitle('notifire API') + .setDescription('The notifire API description') + .setVersion('1.0') + .build(); + const document = SwaggerModule.createDocument(app, options); + SwaggerModule.setup('api', app, document); + } + + if (expressApp) { + await app.init(); + } else { + await app.listen(process.env.PORT); + } + + Logger.log(`Started application in NODE_ENV=${process.env.NODE_ENV} port ${process.env.PORT}`); + return app; +} diff --git a/apps/api/src/config/env-validator.ts b/apps/api/src/config/env-validator.ts new file mode 100644 index 00000000000..070b3443d3d --- /dev/null +++ b/apps/api/src/config/env-validator.ts @@ -0,0 +1,32 @@ +import { port, str, url, ValidatorSpec } from 'envalid'; +import * as envalid from 'envalid'; + +const validators: { [K in keyof any]: ValidatorSpec } = { + NODE_ENV: str({ + choices: ['dev', 'test', 'prod', 'ci', 'local'], + default: 'local', + }), + S3_LOCAL_STACK: str({ + default: '', + }), + S3_BUCKET_NAME: str(), + S3_REGION: str(), + PORT: port(), + FRONT_BASE_URL: url(), + REDIS_HOST: str(), + REDIS_PORT: port(), + JWT_SECRET: str(), + SENDGRID_API_KEY: str(), + MONGO_URL: str(), + AWS_ACCESS_KEY_ID: str(), + AWS_SECRET_ACCESS_KEY: str(), + NOTIFIRE_API_KEY: str(), +}; + +if (process.env.NODE_ENV !== 'local' && process.env.NODE_ENV !== 'test') { + validators.SENTRY_DSN = str(); +} + +export function validateEnv() { + envalid.cleanEnv(process.env, validators); +} diff --git a/apps/api/src/config/index.ts b/apps/api/src/config/index.ts new file mode 100644 index 00000000000..105ed542d97 --- /dev/null +++ b/apps/api/src/config/index.ts @@ -0,0 +1,29 @@ +import * as dotenv from 'dotenv'; +import * as envalid from 'envalid'; +import { str, url, port, ValidatorSpec } from 'envalid'; + +dotenv.config(); + +let path; +switch (process.env.NODE_ENV) { + case 'prod': + path = `${__dirname}/../.env.production`; + break; + case 'test': + path = `${__dirname}/../.env.test`; + break; + case 'ci': + path = `${__dirname}/../.env.ci`; + break; + case 'local': + path = `${__dirname}/../.env.local`; + break; + case 'dev': + path = `${__dirname}/../.env.development`; + break; + default: + path = `${__dirname}/../.env.local`; +} +// +const { error } = dotenv.config({ path }); +if (error && !process.env.LAMBDA_TASK_ROOT) throw error; diff --git a/apps/api/src/main.ts b/apps/api/src/main.ts new file mode 100644 index 00000000000..2fb9dfe34e7 --- /dev/null +++ b/apps/api/src/main.ts @@ -0,0 +1,3 @@ +import { bootstrap } from './bootstrap'; + +bootstrap(); diff --git a/apps/api/src/newrelic.js b/apps/api/src/newrelic.js new file mode 100644 index 00000000000..5be72789fa0 --- /dev/null +++ b/apps/api/src/newrelic.js @@ -0,0 +1,68 @@ +/** + * New Relic agent configuration. + * + * See lib/config/default.js in the agent distribution for a more complete + * description of configuration variables and their potential values. + */ +exports.config = { + /** + * Array of application names. + */ + app_name: [process.env.NEW_RELIC_APP_NAME], + /** + * Your New Relic license key. + */ + license_key: process.env.NEW_RELIC_LICENSE_KEY, + /** + * This setting controls distributed tracing. + * Distributed tracing lets you see the path that a request takes through your + * distributed system. Enabling distributed tracing changes the behavior of some + * New Relic features, so carefully consult the transition guide before you enable + * this feature: https://docs.newrelic.com/docs/transition-guide-distributed-tracing + * Default is true. + */ + distributed_tracing: { + /** + * Enables/disables distributed tracing. + * + * @env NEW_RELIC_DISTRIBUTED_TRACING_ENABLED + */ + enabled: true, + }, + logging: { + /** + * Level at which to log. 'trace' is most useful to New Relic when diagnosing + * issues with the agent, 'info' and higher will impose the least overhead on + * production applications. + */ + level: 'info', + }, + /** + * When true, all request headers except for those listed in attributes.exclude + * will be captured for all traces, unless otherwise specified in a destination's + * attributes include/exclude lists. + */ + allow_all_headers: true, + attributes: { + /** + * Prefix of attributes to exclude from all destinations. Allows * as wildcard + * at end. + * + * NOTE: If excluding headers, they must be in camelCase form to be filtered. + * + * @env NEW_RELIC_ATTRIBUTES_EXCLUDE + */ + exclude: [ + 'request.headers.cookie', + 'request.headers.authorization', + 'request.headers.proxyAuthorization', + 'request.headers.setCookie*', + 'request.headers.x*', + 'response.headers.cookie', + 'response.headers.authorization', + 'response.headers.proxyAuthorization', + 'response.headers.setCookie*', + 'response.headers.x*', + ], + }, +}; diff --git a/apps/api/src/types/env.d.ts b/apps/api/src/types/env.d.ts new file mode 100644 index 00000000000..c32ee225825 --- /dev/null +++ b/apps/api/src/types/env.d.ts @@ -0,0 +1,13 @@ +declare namespace NodeJS { + export interface ProcessEnv { + MONGO_URL: string; + REDIS_URL: string; + SYNC_PATH: string; + GOOGLE_OAUTH_CLIENT_SECRET: string; + GOOGLE_OAUTH_CLIENT_ID: string; + NODE_ENV: 'test' | 'prod' | 'dev' | 'ci' | 'local'; + PORT: string; + FRONT_BASE_URL: string; + SENTRY_DSN: string; + } +} diff --git a/apps/api/tsconfig.build.json b/apps/api/tsconfig.build.json new file mode 100644 index 00000000000..ce43a4259c3 --- /dev/null +++ b/apps/api/tsconfig.build.json @@ -0,0 +1,20 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "module": "commonjs", + "declaration": true, + "noImplicitAny": false, + "removeComments": true, + "allowSyntheticDefaultImports": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "target": "es6", + "esModuleInterop": false, + "sourceMap": true, + "outDir": "./dist", + "baseUrl": "./src", + "types": ["node", "mocha"] + }, + "include": [".eslintrc.js", "src/**/*", "src/**/*.d.ts"], + "exclude": ["node_modules", "**/*.spec.ts"] +} diff --git a/apps/api/tsconfig.json b/apps/api/tsconfig.json new file mode 100644 index 00000000000..5ade64e83dd --- /dev/null +++ b/apps/api/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "module": "commonjs", + "allowSyntheticDefaultImports": true, + "types": ["node", "mocha", "chai", "sinon"], + "target": "es2017", + "allowJs": false, + "esModuleInterop": false, + "declarationMap": true + } +} diff --git a/apps/api/tsconfig.spec.json b/apps/api/tsconfig.spec.json new file mode 100644 index 00000000000..1be0ce0aeb7 --- /dev/null +++ b/apps/api/tsconfig.spec.json @@ -0,0 +1,7 @@ +{ + "extends": "apps/api/tsconfig.json", + "compilerOptions": { + "types": ["mocha", "node"], + "esModuleInterop": false + } +} diff --git a/apps/web/.babelrc b/apps/web/.babelrc new file mode 100644 index 00000000000..5bcf3a7ba3b --- /dev/null +++ b/apps/web/.babelrc @@ -0,0 +1,18 @@ +{ + "presets": [ + "@babel/preset-typescript", + [ + "@babel/preset-react", + { + "runtime": "automatic" + } + ], + "@babel/preset-env" + ], + "plugins": ["babel-plugin-styled-components", "@babel/plugin-proposal-optional-chaining",[ + "@babel/plugin-transform-runtime", + { + "regenerator": true + } + ]] +} diff --git a/apps/web/.env b/apps/web/.env new file mode 100644 index 00000000000..6f809cc2540 --- /dev/null +++ b/apps/web/.env @@ -0,0 +1 @@ +SKIP_PREFLIGHT_CHECK=true diff --git a/apps/web/.eslintrc.js b/apps/web/.eslintrc.js new file mode 100644 index 00000000000..cdb38c1f519 --- /dev/null +++ b/apps/web/.eslintrc.js @@ -0,0 +1,33 @@ +module.exports = { + rules: { + 'react/jsx-props-no-spreading': 'off', + 'react/no-array-index-key': 'off', + 'no-empty-pattern': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + 'react/no-unescaped-entities': 'off', + 'react/jsx-closing-bracket-location': 'off', + '@typescript-eslint/ban-types': 'off', + 'react/jsx-wrap-multilines': 'off', + 'jsx-a11y/anchor-is-valid': 'off', + 'promise/catch-or-return': 'off', + 'react/jsx-one-expression-per-line': 'off', + '@typescript-eslint/no-explicit-any': 'off', + 'no-console': 'off', + 'jsx-a11y/aria-role': 'off', + 'jsx-a11y/no-static-element-interactions': 'off', + 'react/require-default-props': 'off', + 'react/no-danger': 'off', + 'jsx-a11y/click-events-have-key-events': 'off', + }, + env: { + 'cypress/globals': true, + }, + ignorePatterns: ['craco.config.js', 'cypress/*'], + extends: ['plugin:cypress/recommended', '../../.eslintrc.js'], + plugins: ['cypress'], + parserOptions: { + project: './tsconfig.json', + ecmaVersion: 2020, + sourceType: 'module', + }, +}; diff --git a/apps/web/.gitignore b/apps/web/.gitignore new file mode 100644 index 00000000000..3ec1e0edf03 --- /dev/null +++ b/apps/web/.gitignore @@ -0,0 +1,26 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +cypress/videos +cypress/screenshots diff --git a/apps/web/.vscode/settings.json b/apps/web/.vscode/settings.json new file mode 100644 index 00000000000..2c63c085104 --- /dev/null +++ b/apps/web/.vscode/settings.json @@ -0,0 +1,2 @@ +{ +} diff --git a/apps/web/README.md b/apps/web/README.md new file mode 100644 index 00000000000..b58e0af830e --- /dev/null +++ b/apps/web/README.md @@ -0,0 +1,46 @@ +# Getting Started with Create React App + +This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). + +## Available Scripts + +In the project directory, you can run: + +### `yarn start` + +Runs the app in the development mode.\ +Open [http://localhost:3000](http://localhost:3000) to view it in the browser. + +The page will reload if you make edits.\ +You will also see any lint errors in the console. + +### `yarn test` + +Launches the test runner in the interactive watch mode.\ +See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. + +### `yarn build` + +Builds the app for production to the `build` folder.\ +It correctly bundles React in production mode and optimizes the build for the best performance. + +The build is minified and the filenames include the hashes.\ +Your app is ready to be deployed! + +See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. + +### `yarn eject` + +**Note: this is a one-way operation. Once you `eject`, you can’t go back!** + +If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. + +Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. + +You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. + +## Learn More + +You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). + +To learn React, check out the [React documentation](https://reactjs.org/). diff --git a/apps/web/craco.config.js b/apps/web/craco.config.js new file mode 100644 index 00000000000..b4b855c8dd7 --- /dev/null +++ b/apps/web/craco.config.js @@ -0,0 +1,19 @@ +const CracoAntDesignPlugin = require('craco-antd'); +const path = require('path'); +const BabelRcPlugin = require('@jackwilsdon/craco-use-babelrc'); + +module.exports = { + eslint: { + enable: false, + }, + plugins: [ + { plugin: BabelRcPlugin }, + + { + plugin: CracoAntDesignPlugin, + options: { + customizeThemeLessPath: path.join(__dirname, 'src/styles/index.less'), + }, + }, + ], +}; diff --git a/apps/web/cypress.json b/apps/web/cypress.json new file mode 100644 index 00000000000..06c6cfe2f7f --- /dev/null +++ b/apps/web/cypress.json @@ -0,0 +1,20 @@ +{ + "baseUrl": "http://localhost:4200", + "integrationFolder": "cypress/tests", + "viewportHeight": 700, + "viewportWidth": 1200, + "componentFolder": "src", + "testFiles": "**/*.spec.*", + "firefoxGcInterval": null, + "video": false, + "retries": { + "runMode": 2, + "openMode": 1 + }, + "env": { + "NODE_ENV": "test", + "apiUrl": "http://localhost:1336", + "coverage": false + }, + "projectId": "cayav5" +} diff --git a/apps/web/cypress/.eslintrc.js b/apps/web/cypress/.eslintrc.js new file mode 100644 index 00000000000..3b4c2c0e4cf --- /dev/null +++ b/apps/web/cypress/.eslintrc.js @@ -0,0 +1,10 @@ +module.exports = { + extends: ['plugin:cypress/recommended'], + plugins: ['cypress'], + ignorePatterns: ['tests/*'], + parserOptions: { + project: './tsconfig.json', + ecmaVersion: 2020, + sourceType: 'module', + }, +}; diff --git a/apps/web/cypress/fixtures/test-logo.png b/apps/web/cypress/fixtures/test-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6485aac5ddca9b74856c89fa260dd437e42c11b2 GIT binary patch literal 8713 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 k5F9nJtp2;y@qdxjdq0Vce=X + +import { INotificationTemplate } from '@notifire/shared'; + +declare namespace Cypress { + interface Chainable { + getByTestId(dataTestAttribute: string, args?: any): Chainable; + getBySelectorLike(dataTestPrefixAttribute: string, args?: any): Chainable; + + /** + * Window object with additional properties used during test. + */ + window(options?: Partial): Chainable; + + seed(): Chainable; + + clear(): Chainable; + /** + * Logs-in user by using UI + */ + login(username: string, password: string): void; + + /** + * Logs-in user by using API request + */ + initializeSession(settings?: { + noApplication?: boolean; + partialTemplate?: Partial; + }): Chainable; + } +} diff --git a/apps/web/cypress/plugins/index.ts b/apps/web/cypress/plugins/index.ts new file mode 100644 index 00000000000..b95663003d4 --- /dev/null +++ b/apps/web/cypress/plugins/index.ts @@ -0,0 +1,98 @@ +/** + * @type {Cypress.PluginConfig} + */ +const injectReactScriptsDevServer = require('@cypress/react/plugins/react-scripts'); +import { DalService, NotificationTemplateEntity, UserRepository } from '@notifire/dal'; +import { UserSession, SubscribersService, NotificationTemplateService, NotificationsService } from '@notifire/testing'; + +const preprocess = require('@cypress/react/plugins/react-scripts'); + +const userRepository = new UserRepository(); +module.exports = (on, config) => { + // `on` is used to hook into various events Cypress emits + // `config` is the resolved Cypress config + on('task', { + async createNotifications({ identifier, token, count = 1, applicationId, organizationId }) { + const subscriberService = new SubscribersService(organizationId, applicationId); + const subscriber = await subscriberService.createSubscriber(); + + const triggerIdentifier = identifier; + const service = new NotificationsService(token); + + // eslint-disable-next-line no-plusplus + for (let i = 0; i < count; i++) { + await service.triggerEvent(triggerIdentifier, { + $user_id: subscriber.subscriberId, + }); + } + + return 'ok'; + }, + async clearDatabase() { + const dal = new DalService(); + await dal.connect('mongodb://localhost:27017/notifire-test'); + await dal.destroy(); + return true; + }, + async seedDatabase() { + const dal = new DalService(); + await dal.connect('mongodb://localhost:27017/notifire-test'); + + const session = new UserSession('http://localhost:1336'); + + return true; + }, + async passwordResetToken(id: string) { + const dal = new DalService(); + await dal.connect('mongodb://localhost:27017/notifire-test'); + const user = await userRepository.findOne({ + _id: id, + }); + return user?.resetToken; + }, + async getSession( + settings: { noApplication?: boolean; partialTemplate?: Partial } = {} + ) { + const dal = new DalService(); + await dal.connect('mongodb://localhost:27017/notifire-test'); + + const session = new UserSession('http://localhost:1336'); + await session.initialize({ + noApplication: settings?.noApplication, + }); + + const notificationTemplateService = new NotificationTemplateService( + session.user._id, + session.organization._id, + session.application._id + ); + + let templates; + if (!settings?.noApplication) { + let templatePartial = settings?.partialTemplate || {}; + + templates = await Promise.all([ + notificationTemplateService.createTemplate({ ...templatePartial }), + notificationTemplateService.createTemplate({ + active: false, + draft: true, + }), + notificationTemplateService.createTemplate(), + notificationTemplateService.createTemplate(), + notificationTemplateService.createTemplate(), + notificationTemplateService.createTemplate(), + ]); + } + + return { + token: session.token.split(' ')[1], + user: session.user, + organization: session.organization, + application: session.application, + templates, + }; + }, + }); + + injectReactScriptsDevServer(on, config); +}; diff --git a/apps/web/cypress/support/commands.ts b/apps/web/cypress/support/commands.ts new file mode 100644 index 00000000000..d24af1591cf --- /dev/null +++ b/apps/web/cypress/support/commands.ts @@ -0,0 +1,30 @@ +// load the global Cypress types +/// + +import 'cypress-file-upload'; + +Cypress.Commands.add('getByTestId', (selector, ...args) => { + return cy.get(`[data-test-id=${selector}]`, ...args); +}); + +Cypress.Commands.add('getBySelectorLike', (selector, ...args) => { + return cy.get(`[data-test*=${selector}]`, ...args); +}); + +Cypress.Commands.add('seed', () => { + return cy.request('POST', `${Cypress.env('apiUrl')}/v1/testing/seed`, {}); +}); + +Cypress.Commands.add('initializeSession', (settings = {}) => { + return cy.task('getSession', settings).then((response: any) => { + window.localStorage.setItem('auth_token', response.token); + + return response; + }); +}); + +Cypress.Commands.add('logout', (settings = {}) => { + return window.localStorage.removeItem('auth_token'); +}); + +export {}; diff --git a/apps/web/cypress/support/index.ts b/apps/web/cypress/support/index.ts new file mode 100644 index 00000000000..ff4289280e5 --- /dev/null +++ b/apps/web/cypress/support/index.ts @@ -0,0 +1,24 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** +// load the global Cypress types +/// + +import 'cypress-localstorage-commands'; + +// Import commands.js using ES2015 syntax: +import './commands'; + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/apps/web/cypress/tests/activities-page.spec.ts b/apps/web/cypress/tests/activities-page.spec.ts new file mode 100644 index 00000000000..b87fd70b3ab --- /dev/null +++ b/apps/web/cypress/tests/activities-page.spec.ts @@ -0,0 +1,69 @@ +describe('Activity Feed Screen', function () { + beforeEach(function () { + cy.initializeSession() + .as('session') + .then((session: any) => { + cy.wait(500); + + return cy.task('createNotifications', { + identifier: session.templates[0].triggers[0].identifier, + token: session.token, + count: 25, + organizationId: session.organization._id, + applicationId: session.application._id, + }); + }); + }); + + it('should display notification templates list', function () { + cy.visit('/activities'); + cy.getByTestId('activities-table') + .find('tbody tr') + .first() + .getByTestId('row-template-name') + .contains(this.session.templates[0].name); + + cy.getByTestId('activities-table').find('tbody tr').first().getByTestId('row-in-app-channel').should('be.visible'); + cy.getByTestId('activities-table').find('tbody tr').first().getByTestId('row-email-channel').should('be.visible'); + }); + + it('should display stats on top of page', function () { + cy.visit('/activities'); + cy.get('.ant-statistic') + .contains('Sent this month', { + matchCase: false, + }) + .parent('.ant-statistic') + .contains('50'); + cy.get('.ant-statistic') + .contains('Sent this week', { + matchCase: false, + }) + .parent('.ant-statistic') + .contains('50'); + }); + + it('should show errors and warning', function () { + cy.intercept(/.*activity\?page.*/, (r) => { + r.continue((res) => { + res.body.data[0].status = 'error'; + res.body.data[0].errorText = 'Test Error Text'; + res.body.data[2].status = 'warning'; + + res.send({ body: res.body }); + }); + }); + cy.visit('/activities'); + cy.get('tbody tr').eq(0).get('.ant-badge-status-error').should('be.visible'); + cy.get('tbody tr').eq(1).get('.ant-badge-status-success').should('be.visible'); + cy.get('tbody tr').eq(2).get('.ant-badge-status-warning').should('be.visible'); + }); + + it('should filter by email channel', function () { + cy.visit('/activities'); + cy.getByTestId('row-email-channel').should('not.have.length', 10); + cy.getByTestId('activities-filter').click(); + cy.get('.ant-select-item').contains('Email').click(); + cy.getByTestId('row-email-channel').should('have.length', 10); + }); +}); diff --git a/apps/web/cypress/tests/auth.spec.ts b/apps/web/cypress/tests/auth.spec.ts new file mode 100644 index 00000000000..27392e10241 --- /dev/null +++ b/apps/web/cypress/tests/auth.spec.ts @@ -0,0 +1,69 @@ +import { MemberRoleEnum } from '@notifire/shared'; + +describe('User Sign-up and Login', function () { + describe('Sign up', function () { + beforeEach(function () { + cy.task('clearDatabase'); + cy.seed(); + }); + + it('should allow a visitor to sign-up, login, and logout', function () { + cy.visit('/auth/signup'); + cy.getByTestId('fullName').type('Test User'); + cy.getByTestId('email').type('example@example.com'); + cy.getByTestId('password').type('usEr_password_123'); + cy.getByTestId('companyName').type('Mega Corp Company'); + cy.getByTestId('submitButton').click(); + cy.location('pathname').should('equal', '/templates'); + }); + }); + + describe('Password Reset', function () { + before(() => { + cy.initializeSession().as('session'); + }); + + it('should request a password reset flow', function () { + cy.visit('/auth/reset/request'); + cy.getByTestId('email').type(this.session.user.email); + cy.getByTestId('submit-btn').click(); + cy.getByTestId('success-screen-reset').should('be.visible'); + cy.task('passwordResetToken', this.session.user._id).then((token) => { + cy.visit('/auth/reset/' + token); + }); + cy.getByTestId('password').type('123e3e3e3'); + cy.getByTestId('password-repeat').type('123e3e3e3'); + + cy.getByTestId('submit-btn').click(); + }); + }); + + describe('Login', function () { + beforeEach(function () { + cy.task('clearDatabase'); + cy.seed(); + }); + it('should be redirect login with no auth', function () { + cy.visit('/'); + cy.location('pathname').should('equal', '/auth/login'); + }); + + it('should successfully login the user', function () { + cy.visit('/auth/login'); + + cy.getByTestId('email').type('test-user-1@example.com'); + cy.getByTestId('password').type('123qwe!@#'); + cy.getByTestId('submit-btn').click(); + cy.location('pathname').should('equal', '/templates'); + }); + + it('should show bad password error when authenticating with bad credentials', function () { + cy.visit('/auth/login'); + + cy.getByTestId('email').type('test-user-1@example.com'); + cy.getByTestId('password').type('123456'); + cy.getByTestId('submit-btn').click(); + cy.getByTestId('error-alert-banner').contains('Wrong credentials'); + }); + }); +}); diff --git a/apps/web/cypress/tests/explore.spec.ts b/apps/web/cypress/tests/explore.spec.ts new file mode 100644 index 00000000000..abff83539ff --- /dev/null +++ b/apps/web/cypress/tests/explore.spec.ts @@ -0,0 +1,9 @@ +describe('Just launch the app for exploration', function () { + beforeEach(function () { + cy.initializeSession().as('session'); + }); + + it('should launch the app', function () { + cy.visit('/'); + }); +}); diff --git a/apps/web/cypress/tests/invites.spec.ts b/apps/web/cypress/tests/invites.spec.ts new file mode 100644 index 00000000000..292b5a3c797 --- /dev/null +++ b/apps/web/cypress/tests/invites.spec.ts @@ -0,0 +1,43 @@ +import { MemberRoleEnum, MemberStatusEnum } from '@notifire/shared'; + +describe('Invites module', function () { + beforeEach(function () { + cy.task('clearDatabase'); + cy.initializeSession() + .then((session) => { + cy.request({ + method: 'POST', + url: `${Cypress.env('apiUrl')}/v1/invites`, + body: { + email: 'testing-amazing@user.com', + role: MemberRoleEnum.ADMIN, + }, + auth: { + bearer: session.token, + }, + }); + cy.request({ + method: 'GET', + url: `${Cypress.env('apiUrl')}/v1/organizations/members`, + auth: { + bearer: session.token, + }, + }) + .then((response) => { + const member = response.body.data.find((i) => i.memberStatus === MemberStatusEnum.INVITED); + return member.invite.token; + }) + .as('token'); + + cy.logout(); + }) + .as('session'); + }); + + it('should accept invite to organization', function () { + cy.visit('/auth/invitation/' + this.token); + cy.getByTestId('fullName').type('Invited to org user'); + cy.getByTestId('password').type('asd#Faf4fd'); + cy.getByTestId('submitButton').click(); + }); +}); diff --git a/apps/web/cypress/tests/layout/header.spec.ts b/apps/web/cypress/tests/layout/header.spec.ts new file mode 100644 index 00000000000..fbf60b1530e --- /dev/null +++ b/apps/web/cypress/tests/layout/header.spec.ts @@ -0,0 +1,41 @@ +describe('App Header', function () { + beforeEach(function () { + cy.initializeSession().as('session'); + cy.visit('/'); + }); + + it('should display correct user photo', function () { + cy.getByTestId('header-profile-avatar') + .find('img') + .should('have.attr', 'src') + .should('include', this.session.user.profilePicture); + }); + + it('should display user name in dropdown', function () { + cy.getByTestId('header-profile-avatar').click(); + cy.getByTestId('header-dropdown-username').should('contain', this.session.user.firstName); + cy.getByTestId('header-dropdown-username').should('contain', this.session.user.lastName); + }); + + it('should display organization name in dropdown', function () { + cy.getByTestId('header-profile-avatar').click(); + cy.getByTestId('header-dropdown-organization-name').contains(this.session.organization.name, { + matchCase: false, + }); + }); + + it('logout user successfully', function () { + cy.getByTestId('header-profile-avatar').click(); + cy.getByTestId('logout-button').click(); + cy.location('pathname').should('equal', '/auth/login'); + + cy.window() + .then((win) => { + return win.localStorage.getItem('auth_token'); + }) + .should('not.be.ok'); + + cy.visit('/'); + cy.location('pathname').should('equal', '/auth/login'); + }); +}); diff --git a/apps/web/cypress/tests/layout/side-menu.spec.ts b/apps/web/cypress/tests/layout/side-menu.spec.ts new file mode 100644 index 00000000000..0f99ee668ad --- /dev/null +++ b/apps/web/cypress/tests/layout/side-menu.spec.ts @@ -0,0 +1,14 @@ +describe('Side Menu', function () { + beforeEach(function () { + cy.initializeSession().as('session'); + cy.visit('/'); + }); + + it('should navigate correctly to notification-templates', function () { + cy.getByTestId('side-nav-templates-link').should('have.attr', 'href').should('include', '/templates'); + }); + + it('should navigate correctly to settings', function () { + cy.getByTestId('side-nav-settings-link').should('have.attr', 'href').should('include', '/settings/widget'); + }); +}); diff --git a/apps/web/cypress/tests/notifications-editor.spec.ts b/apps/web/cypress/tests/notifications-editor.spec.ts new file mode 100644 index 00000000000..681660299f1 --- /dev/null +++ b/apps/web/cypress/tests/notifications-editor.spec.ts @@ -0,0 +1,384 @@ +import { ChannelTypeEnum, INotificationTemplate } from '@notifire/shared'; + +describe('Notifications Creator', function () { + beforeEach(function () { + cy.initializeSession().as('session'); + }); + + it('should not reset data when switching channel types', function () { + cy.visit('/templates/create'); + cy.getByTestId('inAppSelector').click({ force: true }); + cy.getByTestId('in-app-editor-content-input').type('{{firstName}} someone assigned you to {{taskName}}', { + parseSpecialCharSequences: false, + }); + cy.getByTestId('emailSelector').click({ force: true }); + cy.getByTestId('editable-text-content').clear().type('This text is written from a test {{firstName}}', { + parseSpecialCharSequences: false, + }); + cy.getByTestId('emailSubject').type('this is email subject'); + + cy.getByTestId('inAppSelector').click({ force: true }); + cy.getByTestId('in-app-editor-content-input').contains('someone assigned you to'); + + cy.getByTestId('emailSelector').click({ force: true }); + cy.getByTestId('editable-text-content').contains('This text is written from a test'); + cy.getByTestId('emailSubject').should('have.value', 'this is email subject'); + }); + + it('should create in-app notification', function () { + cy.visit('/templates/create'); + cy.getByTestId('title').type('Test Notification Title'); + cy.getByTestId('description').type('This is a test description for a test title'); + cy.getByTestId('tags').type('General {enter}'); + cy.getByTestId('tags').type('Tasks {enter}'); + cy.get('body').click(); + cy.getByTestId('trigger-code-snippet').should('not.exist'); + cy.getByTestId('groupSelector').contains('General'); + + cy.getByTestId('inAppSelector').click({ force: true }); + cy.getByTestId('inAppRedirect').type('/example/test'); + cy.getByTestId('in-app-editor-content-input').type('{{firstName}} someone assigned you to {{taskName}}', { + parseSpecialCharSequences: false, + }); + cy.getByTestId('submit-btn').click(); + + cy.getByTestId('success-trigger-modal').should('be.visible'); + cy.getByTestId('success-trigger-modal').getByTestId('trigger-code-snippet').contains('test-notification'); + cy.getByTestId('success-trigger-modal') + .getByTestId('trigger-code-snippet') + .contains("import { Notifire } from '@notifire/node'"); + + cy.get('.ant-tabs-tab-btn').contains('Curl').click(); + cy.getByTestId('success-trigger-modal') + .getByTestId('trigger-curl-snippet') + .contains("--header 'Authorization: ApiKey"); + + cy.getByTestId('success-trigger-modal').getByTestId('trigger-curl-snippet').contains('taskName'); + + cy.get('.ant-modal-footer .ant-btn.ant-btn-primary').click(); + cy.location('pathname').should('equal', '/templates'); + }); + + it('should create email notification', function () { + cy.visit('/templates/create'); + cy.getByTestId('title').type('Test Notification Title'); + cy.getByTestId('description').type('This is a test description for a test title'); + cy.getByTestId('tags').type('General {enter}'); + cy.getByTestId('tags').type('Tasks {enter}'); + cy.get('body').click(); + + cy.getByTestId('emailSelector').click({ force: true }); + + cy.getByTestId('email-editor').getByTestId('editor-row').click(); + cy.getByTestId('control-add').click({ force: true }); + cy.getByTestId('add-btn-block').click(); + cy.getByTestId('button-block-wrapper').should('be.visible'); + cy.getByTestId('button-block-wrapper').find('button').click(); + cy.getByTestId('button-text-input').clear().type('Example Text Of {{ctaName}}', { + parseSpecialCharSequences: false, + }); + cy.getByTestId('button-block-wrapper').find('button').contains('Example Text Of {{ctaName}}'); + cy.getByTestId('editable-text-content').clear().type('This text is written from a test {{firstName}}', { + parseSpecialCharSequences: false, + }); + + cy.getByTestId('email-editor').getByTestId('editor-row').eq(1).click(); + cy.getByTestId('control-add').click({ force: true }); + cy.getByTestId('add-text-block').click(); + cy.getByTestId('editable-text-content').eq(1).clear().type('This another text will be {{customVariable}}', { + parseSpecialCharSequences: false, + }); + cy.getByTestId('editable-text-content').eq(1).click(); + + cy.getByTestId('settings-row-btn').eq(1).invoke('show').click(); + cy.getByTestId('remove-row-btn').click(); + cy.getByTestId('button-block-wrapper').should('not.exist'); + + cy.getByTestId('emailSubject').type('this is email subject'); + + cy.getByTestId('submit-btn').click(); + + cy.getByTestId('success-trigger-modal').should('be.visible'); + cy.getByTestId('success-trigger-modal').getByTestId('trigger-code-snippet').contains('test-notification'); + cy.getByTestId('success-trigger-modal').getByTestId('trigger-code-snippet').contains('firstName:'); + cy.getByTestId('success-trigger-modal').getByTestId('trigger-code-snippet').contains('customVariable:'); + }); + + it('should create and edit group id', function () { + const template = this.session.templates[0]; + cy.visit('/templates/edit/' + template._id); + + cy.getByTestId('groupSelector').click(); + cy.getByTestId('category-text-input').type('New Test Category'); + cy.getByTestId('submit-category-btn').click(); + cy.getByTestId('groupSelector').contains('New Test Category'); + + cy.getByTestId('submit-btn').click(); + + cy.getByTestId('template-edit-link'); + cy.visit('/templates/edit/' + template._id); + cy.getByTestId('groupSelector').contains('New Test Category'); + }); + + it('should edit notification', function () { + const template = this.session.templates[0]; + cy.visit('/templates/edit/' + template._id); + cy.getByTestId('inAppSelector').click({ force: true }); + cy.getByTestId('title').get('input').should('have.value', template.name); + cy.getByTestId('in-app-editor-content-input') + .getByTestId('in-app-editor-content-input') + .contains('Test content for {{firstName}}'); + + cy.getByTestId('title').type(' This is the new notification title'); + cy.getByTestId('in-app-editor-content-input').clear().type('new content for notification'); + cy.getByTestId('submit-btn').click(); + + cy.getByTestId('template-edit-link'); + cy.getByTestId('notifications-template').get('tbody tr td').contains('This is the new notification title', { + matchCase: false, + }); + }); + + it('should update notification active status', function () { + const template = this.session.templates[0]; + cy.visit('/templates/edit/' + template._id); + cy.getByTestId('active-toggle-switch').contains('Active'); + cy.getByTestId('active-toggle-switch').click(); + cy.getByTestId('active-toggle-switch').contains('Disabled'); + + cy.visit('/templates/edit/' + template._id); + cy.getByTestId('active-toggle-switch').contains('Disabled'); + }); + + it('should toggle active states of channels', function () { + cy.visit('/templates/create'); + // Enable email from button click + cy.getByTestId('emailSelector').click({ force: true }); + cy.getByTestId('emailSelector').find('.ant-switch-checked').should('exist'); + cy.getByTestId('emailSelector').find('.ant-switch').click({ force: true }); + + // should hide when switch clicked + cy.getByTestId('email-editor-wrapper').should('not.visible'); + + // enable email selector + cy.getByTestId('emailSelector').click(); + + // enable in app without changing select item + cy.getByTestId('inAppSelector').find('.ant-switch').click({ force: true }); + cy.getByTestId('inAppSelector').find('.ant-switch-checked').should('exist'); + cy.getByTestId('email-editor-wrapper').should('exist'); + + // when hiding current selector, should navigate to closest available + cy.getByTestId('emailSelector').find('.ant-switch').click({ force: true }); + cy.getByTestId('in-app-editor-wrapper').should('be.visible'); + }); + + it('should show trigger snippet block when editing', function () { + const template = this.session.templates[0]; + cy.visit('/templates/edit/' + template._id); + + cy.getByTestId('trigger-code-snippet').contains('test-event'); + }); + + it('should handle multiple email messages', function () { + cy.visit('/templates/create'); + cy.getByTestId('emailSelector').click({ force: true }); + cy.getByTestId('emailSubject').eq(1).should('not.exist'); + + cy.getByTestId('add-message-button').click(); + cy.getByTestId('emailSubject').eq(1).click(); + cy.getByTestId('emailSubject').eq(1).should('be.visible'); + cy.getByTestId('emailSubject').eq(1).type('this is email subject 2'); + cy.getByTestId('emailSubject').eq(0).should('not.be.visible'); + cy.getByTestId('message-header-title').eq(0).click(); + cy.getByTestId('emailSubject').eq(0).should('be.visible'); + cy.getByTestId('emailSubject').eq(1).should('not.be.visible'); + cy.getByTestId('emailSubject').eq(0).type('this is email subject 1'); + cy.getByTestId('message-header-title').eq(1).find('.ant-typography-edit').click(); + cy.getByTestId('message-header-title').eq(1).find('textarea').type(' editing message name {enter}'); + cy.getByTestId('message-header-title').eq(1).contains('editing message name'); + + cy.getByTestId('AddRule').eq(0).click(); + cy.getByTestId('filters-builder').eq(0).find('[title="Select your option"]').click(); + cy.get('.ant-select-item-option-content').contains('First Name').click(); + cy.getByTestId('filter-builder-row').find('input[type="text"]').type('First Value'); + + cy.getByTestId('AddRule').eq(0).click(); + cy.getByTestId('filter-builder-row').eq(1).find('[title="Select your option"]').click(); + + cy.getByTestId('remove-message-template-btn').eq(0).click(); + cy.get('.ant-popover-placement-bottom button').contains('Yes').click(); + + cy.getByTestId('emailSubject').eq(1).should('not.exist'); + cy.getByTestId('emailSubject').should('have.value', 'this is email subject 2'); + }); + + describe('Email Filters', function () { + beforeEach(function () { + cy.initializeSession({ + partialTemplate: { + messages: [ + { + type: ChannelTypeEnum.EMAIL, + subject: 'Test', + name: 'Test Name of message', + content: [ + { + type: 'button', + content: 'Test button', + }, + ], + filters: [ + { + type: 'GROUP', + value: 'OR', + children: [ + { + field: 'firstName', + value: 'Test', + operator: 'EQUAL', + }, + ], + }, + ], + }, + { + type: ChannelTypeEnum.EMAIL, + subject: 'Test 2', + name: 'Test Name of message 2', + content: [ + { + type: 'button', + content: 'Test button 2', + }, + ], + filters: [ + { + type: 'GROUP', + value: 'OR', + children: [ + { + field: 'firstName', + value: 'Test 2', + operator: 'EQUAL', + }, + ], + }, + ], + }, + ], + } as Partial, + }).as('session'); + }); + + it('should prefill saved multiple email messages and filters', function () { + const template = this.session.templates[0]; + cy.visit('/templates/edit/' + template._id); + cy.getByTestId('message-header-title').eq(0).contains('Test Name of message'); + cy.getByTestId('message-header-title').eq(1).contains('Test Name of message 2'); + cy.getByTestId('filter-builder-row').eq(1).find('input[type=text]').should('have.value', 'Test 2'); + cy.getByTestId('filter-builder-row').eq(1).find('.ant-select-selection-item').contains('First Name'); + }); + }); + + it('should validate form inputs', function () { + cy.visit('/templates/create'); + cy.getByTestId('submit-btn').click(); + + cy.getByTestId('title').should('have.class', 'ant-form-item-has-error'); + + cy.getByTestId('inAppSelector').click({ force: true }); + cy.getByTestId('submit-btn').click(); + cy.getByTestId('in-app-content-form-item').should('have.class', 'ant-form-item-has-error'); + }); + + it('should allow uploading a logo from email editor', function () { + cy.intercept(/.*applications\/me.*/, (r) => { + r.continue((res) => { + if (res.body) { + delete res.body.data.branding.logo; + } + + res.send({ body: res.body }); + }); + }); + cy.visit('/templates/create'); + cy.getByTestId('emailSelector').click({ force: true }); + + cy.getByTestId('logo-upload-button').click(); + cy.get('.ant-popconfirm button').contains('Yes').click(); + cy.location('pathname').should('equal', '/settings/widget'); + }); + + it('should show the brand logo on main page', function () { + cy.visit('/templates/create'); + cy.getByTestId('emailSelector').click({ force: true }); + + cy.getByTestId('email-editor') + .getByTestId('brand-logo') + .should('have.attr', 'src', 'https://notifire.co/img/logo.png'); + }); + + it('should support RTL text content', function () { + cy.visit('/templates/create'); + cy.getByTestId('emailSelector').click({ force: true }); + cy.getByTestId('settings-row-btn').eq(0).invoke('show').click(); + cy.getByTestId('editable-text-content').should('have.css', 'direction', 'ltr'); + cy.getByTestId('style-setting-row-btn-drawer').click(); + cy.getByTestId('text-direction-input').get('.ant-radio-button-wrapper').contains('RTL').click(); + cy.getByTestId('drawer-submit-btn').click(); + cy.getByTestId('editable-text-content').should('have.css', 'direction', 'rtl'); + }); + + it('should create an SMS channel message', function () { + cy.visit('/templates/create'); + cy.getByTestId('title').type('Test SMS Notification Title'); + cy.getByTestId('description').type('This is a SMS test description for a test title'); + + cy.getByTestId('smsSelector').click({ force: true }); + cy.getByTestId('smsNotificationContent').type('{{firstName}} someone assigned you to {{taskName}}', { + parseSpecialCharSequences: false, + }); + cy.getByTestId('submit-btn').click(); + + cy.getByTestId('success-trigger-modal').should('be.visible'); + cy.getByTestId('success-trigger-modal').getByTestId('trigger-code-snippet').contains('test-sms-notification'); + cy.getByTestId('success-trigger-modal') + .getByTestId('trigger-code-snippet') + .contains("import { Notifire } from '@notifire/node'"); + + cy.getByTestId('success-trigger-modal').getByTestId('trigger-code-snippet').contains('taskName'); + + cy.getByTestId('success-trigger-modal').getByTestId('trigger-code-snippet').contains('firstName'); + + cy.get('.ant-modal-footer .ant-btn.ant-btn-primary').click(); + cy.location('pathname').should('equal', '/templates'); + }); + + it('should prompt for filling sms settings before accessing the data', function () { + cy.intercept(/.*applications\/me.*/, (r) => { + r.continue((res) => { + delete res.body.data.channels.sms; + res.send({ body: res.body }); + }); + }); + + cy.visit('/templates/create'); + cy.getByTestId('configure-sms-button').click(); + cy.get('.ant-popover button').contains('Yes').click(); + cy.url().should('include', '/settings/widget'); + }); + + it('should save HTML template email', function () { + cy.visit('/templates/create'); + cy.getByTestId('title').type('Custom Code HTML Notification Title'); + cy.getByTestId('emailSelector').click({ force: true }); + cy.getByTestId('emailSubject').type('this is email subject'); + cy.getByTestId('editor-type-selector').find('label').contains('Custom Code', { matchCase: false }).click(); + cy.get('#codeEditor').type('Hello world code {{name}}
Test', { parseSpecialCharSequences: false }); + cy.getByTestId('submit-btn').click(); + cy.get('.ant-modal-footer .ant-btn.ant-btn-primary').click(); + cy.get('tbody').contains('Custom Code HTML Notification').parent('tr').find('button').click(); + cy.get('#codeEditor').contains('Hello world code {{name}}
Test
'); + }); +}); diff --git a/apps/web/cypress/tests/notifications.spec.ts b/apps/web/cypress/tests/notifications.spec.ts new file mode 100644 index 00000000000..f246542e63a --- /dev/null +++ b/apps/web/cypress/tests/notifications.spec.ts @@ -0,0 +1,27 @@ +describe('Notification Templates Screen', function () { + beforeEach(function () { + cy.initializeSession().as('session'); + }); + + it('should display notification templates list', function () { + cy.visit('/templates'); + cy.getByTestId('notifications-template') + .find('tbody tr') + .first() + .getByTestId('template-edit-link') + .then((a: any) => { + const found = this.session.templates.find((i) => a.attr('href').includes(i._id)); + expect(found).to.be.ok; + return expect(a.attr('href')).to.equal(`/templates/edit/${found._id}`); + }); + + cy.getByTestId('notifications-template') + .find('tbody tr') + .first() + .getByTestId('active-status-label') + .should('be.visible'); + + cy.getByTestId('create-template-btn').should('have.attr', 'href', '/templates/create'); + cy.getByTestId('category-label').contains('General'); + }); +}); diff --git a/apps/web/cypress/tests/organization-settings.spec.ts b/apps/web/cypress/tests/organization-settings.spec.ts new file mode 100644 index 00000000000..45b8e3a675c --- /dev/null +++ b/apps/web/cypress/tests/organization-settings.spec.ts @@ -0,0 +1,11 @@ +describe('Settings Screen', function () { + beforeEach(function () { + cy.initializeSession().as('session'); + cy.visit('/settings/organization'); + }); + + it('should send organization invitation', function () { + cy.getByTestId('invite-email-field').type('test-user@email.com'); + cy.getByTestId('submit-btn').click(); + }); +}); diff --git a/apps/web/cypress/tests/settings.spec.ts b/apps/web/cypress/tests/settings.spec.ts new file mode 100644 index 00000000000..feeebd9456e --- /dev/null +++ b/apps/web/cypress/tests/settings.spec.ts @@ -0,0 +1,112 @@ +describe('Settings Screen', function () { + beforeEach(function () { + cy.initializeSession().as('session'); + cy.visit('/settings/widget'); + }); + + it('should update the twilio credentials', function () { + cy.get('.ant-tabs-tab-btn').contains('SMS').click(); + cy.getByTestId('account-sid').clear().type('12345'); + cy.getByTestId('auth-token').clear().type('56789'); + cy.getByTestId('phone-number').clear().type('+1111111'); + cy.getByTestId('submit-update-settings').click(); + cy.reload(); + cy.get('.ant-tabs-tab-btn').contains('SMS').click(); + cy.getByTestId('auth-token').should('have.value', '56789'); + cy.getByTestId('account-sid').should('have.value', '12345'); + }); + + it('should display the embed code successfully', function () { + cy.get('.ant-tabs-tab-btn').contains('In App Center').click(); + + cy.getByTestId('embed-code-snippet').then(function (a) { + expect(a).to.contain(this.session.application.identifier); + expect(a).to.contain('notifire.init'); + }); + }); + + it('should display the api key of the app', function () { + cy.get('.ant-tabs-tab-btn').contains('Api Keys').click(); + cy.getByTestId('api-key-container').contains(this.session.application.apiKeys[0].key); + }); + + it('should update the email channel senderEmail', function () { + cy.get('.ant-tabs-tab-btn').contains('Email settings').click(); + cy.getByTestId('sender-email').type('new-testing@email.com'); + cy.getByTestId('sender-name').type('Test Sender Name'); + cy.getByTestId('submit-update-settings').click(); + cy.reload(); + + cy.get('.ant-tabs-tab-btn').contains('Email settings').click(); + cy.getByTestId('sender-email').should('have.value', 'new-testing@email.com'); + cy.getByTestId('sender-name').should('have.value', 'Test Sender Name'); + }); + + it('should update logo', function () { + cy.fixture('test-logo.png').then((fileContent) => { + cy.getByTestId('upload-image-button').attachFile({ + fileContent: b64toBlob(fileContent), + fileName: 'test-logo.png', + mimeType: 'image/png', + }); + }); + + cy.get('.ant-upload-picture-card-wrapper img').should('have.attr', 'src').should('include', '.png'); + cy.get('.ant-upload-picture-card-wrapper img') + .should('have.attr', 'src') + .should('include', this.session.organization._id); + cy.getByTestId('submit-branding-settings').click(); + + cy.get('.ant-upload-picture-card-wrapper img').should('have.attr', 'src').should('include', '.png'); + cy.get('.ant-upload-picture-card-wrapper img') + .should('have.attr', 'src') + .should('include', this.session.organization._id); + }); + + it.skip('should change look and feel settings', function () { + cy.getByTestId('color-picker').click({ force: true }); + cy.get('.block-picker:visible div[title="#ba68c8"]').click({ force: true }); + cy.getByTestId('color-picker').click({ force: true }); + cy.getByTestId('color-picker-value').should('have.value', '#ba68c8'); + + cy.getByTestId('font-color-picker').click({ force: true }); + cy.get('body').click(); + cy.get('.block-picker:visible div[title="#37D67A"]').click({ force: true }); + cy.getByTestId('font-color-picker').click({ force: true }); + cy.getByTestId('font-color-picker-value').should('have.value', '#37d67a'); + + cy.getByTestId('content-background-picker').click({ force: true }); + cy.get('.block-picker:visible div[title="#2CCCE4"]').click({ force: true }); + cy.getByTestId('content-background-picker').click({ force: true }); + cy.getByTestId('content-background-picker-value').should('have.value', '#2ccce4'); + + cy.getByTestId('font-family-selector').type('Nunito{enter}'); + + cy.getByTestId('submit-branding-settings').click({ force: true }); + cy.reload(); + cy.getByTestId('color-picker-value').should('have.value', '#ba68c8'); + cy.getByTestId('font-color-picker-value').should('have.value', '#37d67a'); + cy.getByTestId('content-background-picker-value').should('have.value', '#2ccce4'); + cy.getByTestId('font-family-selector').contains('Nunito'); + }); +}); + +function b64toBlob(b64Data, contentType = '', sliceSize = 512) { + const byteCharacters = atob(b64Data); + const byteArrays: any[] = []; + + for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) { + const slice = byteCharacters.slice(offset, offset + sliceSize); + + const byteNumbers = new Array(slice.length); + for (let i = 0; i < slice.length; i++) { + byteNumbers[i] = slice.charCodeAt(i); + } + + const byteArray = new Uint8Array(byteNumbers); + byteArrays.push(byteArray); + } + + const blob = new Blob(byteArrays, { type: contentType }); + return blob; +} diff --git a/apps/web/cypress/tsconfig.json b/apps/web/cypress/tsconfig.json new file mode 100644 index 00000000000..9b5b966c676 --- /dev/null +++ b/apps/web/cypress/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../tsconfig.json", + "include": ["./**/*.ts", "global.d.ts"], + "exclude": [], + "compilerOptions": { + "types": ["cypress", "cypress-file-upload"], + "lib": ["es2015", "dom"], + "isolatedModules": false, + "allowJs": true, + "noEmit": true + } +} diff --git a/apps/web/netlify.toml b/apps/web/netlify.toml new file mode 100644 index 00000000000..b87b8d3ddaa --- /dev/null +++ b/apps/web/netlify.toml @@ -0,0 +1,4 @@ +[[redirects]] + from = "/*" + to = "/index.html" + status = 200 diff --git a/apps/web/package.json b/apps/web/package.json new file mode 100644 index 00000000000..b8bd41ffc77 --- /dev/null +++ b/apps/web/package.json @@ -0,0 +1,109 @@ +{ + "name": "@notifire/web", + "version": "0.2.58", + "private": true, + "dependencies": { + "@ant-design/icons": "^4.6.2", + "@auth0/nextjs-auth0": "^0.16.0", + "@craco/craco": "^6.1.1", + "@cypress/react": "^5.3.2", + "@cypress/webpack-dev-server": "^1.1.2", + "@editorjs/editorjs": "^2.19.3", + "@editorjs/paragraph": "^2.8.0", + "@jackwilsdon/craco-use-babelrc": "^1.0.0", + "@notifire/shared": "^0.2.29", + "@sentry/react": "^6.3.1", + "@sentry/tracing": "^6.3.1", + "@testing-library/jest-dom": "^5.11.4", + "@testing-library/react": "^11.1.0", + "@testing-library/user-event": "^12.1.10", + "@types/jest": "^26.0.15", + "@types/node": "^12.0.0", + "@types/react": "^17.0.0", + "@types/react-dom": "^17.0.0", + "ace-builds": "^1.4.12", + "antd": "^4.10.0", + "autoprefixer": "^9.8.6", + "babel-plugin-import": "^1.13.3", + "graphql": "^15.4.0", + "history": "^5.0.0", + "jwt-decode": "^3.1.2", + "less": "^4.1.0", + "lodash.capitalize": "^4.2.1", + "polished": "^4.1.3", + "react": "^17.0.1", + "react-ace": "^9.4.3", + "react-color": "^2.19.3", + "react-css-theme-switcher": "^0.2.2", + "react-custom-scrollbars": "^4.2.1", + "react-dom": "^17.0.1", + "react-editor-js": "^1.9.0", + "react-hook-form": "^7.2.3", + "react-query": "^3.5.16", + "react-router-dom": "^5.2.0", + "react-scripts": "4.0.3", + "react-syntax-highlighter": "^15.4.3", + "styled-components": "^5.2.1", + "typescript": "^4.1.2", + "uniqid": "^5.3.0", + "web-vitals": "^1.0.1" + }, + "devDependencies": { + "@babel/polyfill": "^7.12.1", + "@babel/preset-env": "^7.13.15", + "@babel/preset-react": "^7.13.13", + "@babel/preset-typescript": "^7.13.0", + "@babel/runtime": "^7.14.6", + "@notifire/dal": "^0.2.33", + "@notifire/testing": "^0.2.33", + "@types/react": "^17.0.0", + "@types/styled-components": "^5.1.7", + "babel-plugin-styled-components": "^1.12.0", + "craco-antd": "^1.19.0", + "cypress": "^7.3.0", + "cypress-file-upload": "^5.0.7", + "cypress-localstorage-commands": "^1.4.0", + "eslint-plugin-cypress": "^2.11.2", + "http-server": "^0.12.3", + "less-loader": "4.1.0", + "start-server-and-test": "1.11.6" + }, + "scripts": { + "start": "PORT=4200 craco start", + "build": "craco build", + "test": "craco test", + "precommit": "lint-staged", + "start:static:build": "http-server build -p 4200 --proxy http://localhost:4200?", + "start:dev": "npm run start", + "cypress:run": "NODE_ENV=test cypress run", + "cypress:open": "NODE_ENV=test cypress open", + "start:api": "cd ../../ && yarn run start:e2e:api" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "workspaces": { + "nohoist": [ + "**/react-scripts", + "**/react-scripts/**", + "**/react", + "**/react-dom", + "**/@cypress", + "**/@cypress/**" + ] + }, + "lint-staged": { + "*.{js,jsx,ts,tsx}": [ + "eslint" + ] + } +} diff --git a/apps/web/public/favicon.ico b/apps/web/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..4965832f2c9b0605eaa189b7c7fb11124d24e48a GIT binary patch literal 15086 zcmeHOOH5Q(7(R0cc?bh2AT>N@1PWL!LLfZKyG5c!MTHoP7_p!sBz0k$?pjS;^lmgJ zU6^i~bWuZYHL)9$wuvEKm~qo~(5=Lvx5&Hv;?X#m}i|`yaGY4gX+&b>tew;gcnRQA1kp zBbm04SRuuE{Hn+&1wk%&g;?wja_Is#1gKoFlI7f`Gt}X*-nsMO30b_J@)EFNhzd1QM zdH&qFb9PVqQOx@clvc#KAu}^GrN`q5oP(8>m4UOcp`k&xwzkTio*p?kI4BPtIwX%B zJN69cGsm=x90<;Wmh-bs>43F}ro$}Of@8)4KHndLiR$nW?*{Rl72JPUqRr3ta6e#A z%DTEbi9N}+xPtd1juj8;(CJt3r9NOgb>KTuK|z7!JB_KsFW3(pBN4oh&M&}Nb$Ee2 z$-arA6a)CdsPj`M#1DS>fqj#KF%0q?w50GN4YbmMZIoF{e1yTR=4ablqXHBB2!`wM z1M1ke9+<);|AI;f=2^F1;G6Wfpql?1d5D4rMr?#f(=hkoH)U`6Gb)#xDLjoKjp)1;Js@2Iy5yk zMXUqj+gyk1i0yLjWS|3sM2-1ECc;MAz<4t0P53%7se$$+5Ex`L5TQO_MMXXi04UDIU+3*7Ez&X|mj9cFYBXqM{M;mw_ zpw>azP*qjMyNSD4hh)XZt$gqf8f?eRSFX8VQ4Y+H3jAtvyTrXr`qHAD6`m;aYmH2zOhJC~_*AuT} zvUxC38|JYN94i(05R)dVKgUQF$}#cxV7xZ4FULqFCNX*Forhgp*yr6;DsIk=ub0Hv zpk2L{9Q&|uI^b<6@i(Y+iSxeO_n**4nRLc`P!3ld5jL=nZRw6;DEJ*1z6Pvg+eW|$lnnjO zjd|8>6l{i~UxI244CGn2kK@cJ|#ecwgSyt&HKA2)z zrOO{op^o*- + + + + + + + + + + + + Notifire Manage Platform + + + +
+ + + diff --git a/apps/web/public/logo192.png b/apps/web/public/logo192.png new file mode 100644 index 0000000000000000000000000000000000000000..fc44b0a3796c0e0a64c3d858ca038bd4570465d9 GIT binary patch literal 5347 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 b{|{}U^kRn2wo}j7|0ATu<;8xA7zX}7|B6mN literal 0 HcmV?d00001 diff --git a/apps/web/public/manifest.json b/apps/web/public/manifest.json new file mode 100644 index 00000000000..080d6c77ac2 --- /dev/null +++ b/apps/web/public/manifest.json @@ -0,0 +1,25 @@ +{ + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/apps/web/public/robots.txt b/apps/web/public/robots.txt new file mode 100644 index 00000000000..e9e57dc4d41 --- /dev/null +++ b/apps/web/public/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/apps/web/public/static/images/avatar.png b/apps/web/public/static/images/avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..09892098aa943af5fe95e7dd434a07fe03e7ccd1 GIT binary patch literal 2011 zcmV<12PF83P)D!y%g4vZ*x1<2%*?Q`u)x5;+S=OH)zz}HvdGBD zw6wIs!oteR%FWHqrlzLJ$;r^r(7(UGt*x!9s;a}o!>FjJ#>U3Iy}i%R&$YF+x3{;h zuCCtR-nO>3udlDMv9Z$9(zv*|ySuyA*4EqG+ZlWNivR!y*-1n}RCr$O+*gj>NDPM2 zpNco<96RTn9rwSi8F&oCZFlz#Qq{xgJ4+x4LZrx&UjP6A00000000000000000000 z0000000000h)13Iv~gIg9X6)(&Ma2$kko6>k^LchuGJIe1?9VT%ih&$-<6da;(GtY zRygU`V`YKSGPJdX%aOK)>O)}bd#Gv~*uA$6-S28s*y-CA`a9YL;;WKvrF0c*ZKyul z)*h=`7wH^W2Elqsjqd}?Xz*Ptp%PkVVMQxo5?Bs`i9Upe<)onxU}?Eo>Ro7Cj@nv* ze0H1D=vvOYdIRQ`ySe^?YRPg}s_G9&F3o|+E;KJf72K|Qva4ddGB4O%8ki>o6?HI`i*6#+w#5|Y?<y|LwN+|wJ-DOs*c9lZ(lz;YDS^$r~880p|x z??Sy~IVsik0el`?F2Y>=KFtcZ1R zaGELyc&axa?H!NJ`jhg5v~%-y@6vvAx%c&^lgbGsy=v!Q)n20Y000000000000000 z0000001(G=0_9$3(l{U9f4Ydqf&CDSql-`X!}G?Z(<>_@q?M!EmqlnRgo`h=qe`mH zp^F!L#dKMP=0-j66q)X!m2_UKU< z?=gcl`PrjD-Z_UQ!Oo*l-Y$R@ac4on7M&O-j9L_~HG+QG8x@#l(9NwQst~Om6uTU# z#^D0B?jkA@-9e`x4^-yi2NWuOs^gbXXX{ZRZwp;qmr8Y=vc4+;?DuSiV=6Wdp+vB! zYWn~xgnKHt51~MOqTGjPD@PoaW3S(TV1qAdpLGPU;{}n+CNZ&z1&l zAk)yBhI<>K$Szko#25&!NK0f~qZEphQ8{ z3aIf)#a^Mvnrf|~$}^REhB95M)P*|TX3iCPq&kn#$aR|+5*6uFl|Ix;s7M0Ewp3#a z)kYpw@J3LsOsPOxLcOd<@p>5y2p=fiLkJUGpQ800tayqjR`dizEyTFw96Gb|` z!YX_?aV~Q~zz%VD}8+~-=U|TkA>Od+oZ}G}nbJRjS zi+DxREJj@nPrRDb5Owl07n$q)ia(q8)f$NXg*KhY?6EB-U9U5WqIxO65S z|C%@HT<{BxaK1b6FYI^o5WlAp7RhA6Kem`8MTkGt$mX+;7JpOgV>ZtqfL8IK*!Dm6 zzQ>>P{QXCNTMXj=+Nnb$0D%|)f;hy>mx(1hlm3f?BA8dZ4V=5bdfd6DDtbSk-BC3w tPksUb00000000000000000000fEW70#Mag`cL)Fg002ovPDHLkV1gNB=am2e literal 0 HcmV?d00001 diff --git a/apps/web/public/static/images/login_bg.jpg b/apps/web/public/static/images/login_bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2adb050ee2ecbd92b6a38f407fcefe32b145e35f GIT binary patch literal 44377 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 M+l$z7)W6mL1BuXd)c^nh literal 0 HcmV?d00001 diff --git a/apps/web/public/static/images/login_bg.png b/apps/web/public/static/images/login_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..97542da9d24383b78ffcb003ac5f7e4e3e8fffa0 GIT binary patch literal 762612 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 z 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ව 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

E4f;QMfbyvjX|B-T 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 z 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�EEZ|0Emb^UkGG4Mh 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 z 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

*_gtSOZN` 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

)w1Ci!_Lhw8T0ULEVsj47i^$vN;N%kJw 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%0Ao=6c9*nx7I=A<@OXCrH`%AF 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 cTc0tz;J2c_^M|^SUO!bDOeN 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 literal 0 HcmV?d00001 diff --git a/apps/web/public/static/images/login_illustration.png b/apps/web/public/static/images/login_illustration.png new file mode 100644 index 0000000000000000000000000000000000000000..ad0252cfb2eb7ef4a74881c8ebf71eff0eda32e6 GIT binary patch literal 37475 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


hiSbMMJsbgXm&Sa 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 literal 0 HcmV?d00001 diff --git a/apps/web/public/static/images/login_illustration.svg b/apps/web/public/static/images/login_illustration.svg new file mode 100644 index 00000000000..e0a5d06981e --- /dev/null +++ b/apps/web/public/static/images/login_illustration.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/web/public/static/images/logo-black-white.png b/apps/web/public/static/images/logo-black-white.png new file mode 100644 index 0000000000000000000000000000000000000000..4285a1453e287d2f88f316db5765f83f71a92d1f GIT binary patch literal 168496 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 ATL1t6 literal 0 HcmV?d00001 diff --git a/apps/web/public/static/images/logo-light.png b/apps/web/public/static/images/logo-light.png new file mode 100644 index 0000000000000000000000000000000000000000..4ec35000c47b225f96156fda1a19b4df39037a86 GIT binary patch literal 25516 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 literal 0 HcmV?d00001 diff --git a/apps/web/public/static/images/logo.png b/apps/web/public/static/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e439e7fc10e0337b7974dbce0b5c51ab69de7bda GIT binary patch literal 27428 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

$Vx!+n+LN(g;yi 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 AS^xk5 literal 0 HcmV?d00001 diff --git a/apps/web/public/vercel.svg b/apps/web/public/vercel.svg new file mode 100644 index 00000000000..fbf0e25a651 --- /dev/null +++ b/apps/web/public/vercel.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/apps/web/src/App.test.tsx b/apps/web/src/App.test.tsx new file mode 100644 index 00000000000..2a68616d984 --- /dev/null +++ b/apps/web/src/App.test.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import App from './App'; + +test('renders learn react link', () => { + render(); + const linkElement = screen.getByText(/learn react/i); + expect(linkElement).toBeInTheDocument(); +}); diff --git a/apps/web/src/App.tsx b/apps/web/src/App.tsx new file mode 100644 index 00000000000..0a33f9a14e9 --- /dev/null +++ b/apps/web/src/App.tsx @@ -0,0 +1,149 @@ +import React from 'react'; +import * as Sentry from '@sentry/react'; +import { QueryClient, QueryClientProvider } from 'react-query'; +import { Route, Switch, Redirect, BrowserRouter } from 'react-router-dom'; +import { Integrations } from '@sentry/tracing'; +import { AuthContext } from './store/authContext'; +import { applyToken, getToken, useAuthController } from './store/use-auth-controller'; +import './styles/index.less'; +import { ActivitiesPage } from './pages/activities/ActivitiesPage'; +import LoginPage from './pages/auth/login'; +import SignUpPage from './pages/auth/signup'; +import HomePage from './pages/HomePage'; +import ApplicationOnBoarding from './pages/onboarding/application'; +import TemplateEditorPage from './pages/templates/editor/TemplateEditorPage'; +import NotificationList from './pages/templates/TemplatesListPage'; +import { AppLayout } from './components/layout/app-layout/AppLayout'; +import { WidgetSettingsPage } from './pages/settings/WidgetSettingsPage'; +import { OrganizationSettingsPage } from './pages/organization-settings/OrganizationSettingsPage'; +import InvitationScreen from './pages/auth/InvitationScreen'; +import { api } from './api/api.client'; +import PasswordResetPage from './pages/auth/password-reset'; + +if (process.env.REACT_APP_SENTRY_DSN) { + Sentry.init({ + dsn: process.env.REACT_APP_SENTRY_DSN, + integrations: [new Integrations.BrowserTracing()], + environment: process.env.REACT_APP_ENVIRONMENT, + // Set tracesSampleRate to 1.0 to capture 100% + // of transactions for performance monitoring. + // We recommend adjusting this value in production + tracesSampleRate: 1.0, + }); +} + +const defaultQueryFn = async ({ queryKey }: { queryKey: string }) => { + const response = await api.get(`${queryKey[0]}`); + return response.data?.data; +}; + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + queryFn: defaultQueryFn as any, + }, + }, +}); + +const tokenStoredToken: string = getToken(); +applyToken(tokenStoredToken); + +function App() { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +function PrivateRoute({ children, ...rest }: any) { + return ( + { + return getToken() ? ( + children + ) : ( + + ); + }} + /> + ); +} + +function AuthHandlerComponent({ children }: { children: React.ReactNode }) { + const { token, setToken, user, logout } = useAuthController(); + + return ( + + {children} + + ); +} + +export default Sentry.withProfiler(App); + +// diff --git a/apps/web/src/api/activity.ts b/apps/web/src/api/activity.ts new file mode 100644 index 00000000000..c7077d6ee69 --- /dev/null +++ b/apps/web/src/api/activity.ts @@ -0,0 +1,14 @@ +import { api } from './api.client'; + +export function getActivityList(page = 0, filters) { + return api.getFullResponse(`/v1/activity`, { + page, + channels: filters?.channels, + templates: filters?.templates, + search: filters?.search, + }); +} + +export function getActivityStats() { + return api.get(`/v1/activity/stats`); +} diff --git a/apps/web/src/api/api.client.ts b/apps/web/src/api/api.client.ts new file mode 100644 index 00000000000..a560ccaba8c --- /dev/null +++ b/apps/web/src/api/api.client.ts @@ -0,0 +1,45 @@ +import axios from 'axios'; +import { API_ROOT } from '../config'; + +export const api = { + get(url: string) { + return axios + .get(`${API_ROOT}${url}`) + .then((response) => { + return response.data?.data; + }) + .catch((error) => { + // eslint-disable-next-line promise/no-return-wrap + return Promise.reject(error?.response?.data || error?.response || error); + }); + }, + getFullResponse(url: string, params?: { [key: string]: string | string[] | number }) { + return axios + .get(`${API_ROOT}${url}`, { + params, + }) + .then((response) => response.data) + .catch((error) => { + // eslint-disable-next-line promise/no-return-wrap + return Promise.reject(error?.response?.data || error?.response || error); + }); + }, + put(url: string, payload) { + return axios + .put(`${API_ROOT}${url}`, payload) + .then((response) => response.data?.data) + .catch((error) => { + // eslint-disable-next-line promise/no-return-wrap + return Promise.reject(error?.response?.data || error?.response || error); + }); + }, + post(url: string, payload) { + return axios + .post(`${API_ROOT}${url}`, payload) + .then((response) => response.data?.data) + .catch((error) => { + // eslint-disable-next-line promise/no-return-wrap + return Promise.reject(error?.response?.data || error?.response || error); + }); + }, +}; diff --git a/apps/web/src/api/application.ts b/apps/web/src/api/application.ts new file mode 100644 index 00000000000..de0e7a33355 --- /dev/null +++ b/apps/web/src/api/application.ts @@ -0,0 +1,21 @@ +import { api } from './api.client'; + +export function getCurrentApplication() { + return api.get('/v1/applications/me'); +} + +export function getApiKeys() { + return api.get(`/v1/applications/api-keys`); +} + +export function updateEmailSettings(payload: { senderEmail: string; senderName: string }) { + return api.put(`/v1/channels/email/settings`, payload); +} + +export function updateSmsSettings(payload: { authToken: string; accountSid: string; phoneNumber: string }) { + return api.put(`/v1/channels/sms/settings`, { twillio: payload }); +} + +export function updateBrandingSettings(payload: { color: string | undefined; logo: string | undefined }) { + return api.put(`/v1/applications/branding`, payload); +} diff --git a/apps/web/src/api/hooks/use-application.ts b/apps/web/src/api/hooks/use-application.ts new file mode 100644 index 00000000000..68ebd96d452 --- /dev/null +++ b/apps/web/src/api/hooks/use-application.ts @@ -0,0 +1,13 @@ +import { useQuery } from 'react-query'; +import { IApplication } from '@notifire/shared'; +import { getCurrentApplication } from '../application'; + +export function useApplication() { + const { data: application, isLoading, refetch } = useQuery('currentApplication', getCurrentApplication); + + return { + application, + loading: isLoading, + refetch, + }; +} diff --git a/apps/web/src/api/hooks/use-templates.ts b/apps/web/src/api/hooks/use-templates.ts new file mode 100644 index 00000000000..5b0dadcf30f --- /dev/null +++ b/apps/web/src/api/hooks/use-templates.ts @@ -0,0 +1,12 @@ +import { useQuery } from 'react-query'; +import { INotificationTemplate } from '@notifire/shared'; +import { getNotificationsList } from '../notifications'; + +export function useTemplates() { + const { data, isLoading } = useQuery('notificationsList', getNotificationsList); + + return { + templates: data, + loading: isLoading, + }; +} diff --git a/apps/web/src/api/invitation.ts b/apps/web/src/api/invitation.ts new file mode 100644 index 00000000000..55e01e3d799 --- /dev/null +++ b/apps/web/src/api/invitation.ts @@ -0,0 +1,5 @@ +import { api } from './api.client'; + +export function getInviteTokenData(token: string) { + return api.get(`/v1/invites/${token}`); +} diff --git a/apps/web/src/api/notifications.ts b/apps/web/src/api/notifications.ts new file mode 100644 index 00000000000..27df0f837f3 --- /dev/null +++ b/apps/web/src/api/notifications.ts @@ -0,0 +1,9 @@ +import { api } from './api.client'; + +export function getNotificationsList() { + return api.get(`/v1/notification-templates`); +} + +export function getNotificationGroups() { + return api.get(`/v1/notification-groups`); +} diff --git a/apps/web/src/api/organization.ts b/apps/web/src/api/organization.ts new file mode 100644 index 00000000000..49caabf1c2b --- /dev/null +++ b/apps/web/src/api/organization.ts @@ -0,0 +1,17 @@ +import { MemberRoleEnum } from '@notifire/shared'; +import { api } from './api.client'; + +export function getOrganizationMembers() { + return api.get(`/v1/organizations/members`); +} + +export function getCurrentOrganization() { + return api.get(`/v1/organizations/me`); +} + +export function inviteMember(email: string) { + return api.post(`/v1/invites`, { + email, + role: MemberRoleEnum.ADMIN, + }); +} diff --git a/apps/web/src/api/storage.ts b/apps/web/src/api/storage.ts new file mode 100644 index 00000000000..bfe2f40973c --- /dev/null +++ b/apps/web/src/api/storage.ts @@ -0,0 +1,5 @@ +import { api } from './api.client'; + +export function getSignedUrl(extension: string) { + return api.get(`/v1/storage/upload-url?extension=${extension}`); +} diff --git a/apps/web/src/api/templates.ts b/apps/web/src/api/templates.ts new file mode 100644 index 00000000000..4a90a5c31fa --- /dev/null +++ b/apps/web/src/api/templates.ts @@ -0,0 +1,18 @@ +import { ICreateNotificationTemplateDto } from '@notifire/shared'; +import { api } from './api.client'; + +export async function createTemplate(data: ICreateNotificationTemplateDto) { + return api.post(`/v1/notification-templates`, data); +} + +export async function updateTemplate(templateId: string, data: Partial) { + return api.put(`/v1/notification-templates/${templateId}`, data); +} + +export async function getTemplateById(id: string) { + return api.get(`/v1/notification-templates/${id}`); +} + +export async function updateTemplateStatus(templateId: string, active: boolean) { + return api.put(`/v1/notification-templates/${templateId}/status`, { active }); +} diff --git a/apps/web/src/api/user.ts b/apps/web/src/api/user.ts new file mode 100644 index 00000000000..df1699b1902 --- /dev/null +++ b/apps/web/src/api/user.ts @@ -0,0 +1,5 @@ +import { api } from './api.client'; + +export async function getUser() { + return api.get('/v1/users/me'); +} diff --git a/apps/web/src/components/auth/LoginForm.tsx b/apps/web/src/components/auth/LoginForm.tsx new file mode 100644 index 00000000000..1d3c5510a73 --- /dev/null +++ b/apps/web/src/components/auth/LoginForm.tsx @@ -0,0 +1,100 @@ +import { Button, Form, Input, Divider, Alert } from 'antd'; +import Icon, { MailOutlined, LockOutlined } from '@ant-design/icons'; +import { useHistory, Link } from 'react-router-dom'; +import { useContext } from 'react'; +import { useMutation } from 'react-query'; +import * as Sentry from '@sentry/react'; +import { AuthContext } from '../../store/authContext'; +import { api } from '../../api/api.client'; + +type Props = {}; + +export function LoginForm({}: Props) { + const router = useHistory(); + const { setToken } = useContext(AuthContext); + const { isLoading, mutateAsync, isError, error } = useMutation< + { token: string }, + { error: string; message: string; statusCode: number }, + { + email: string; + password: string; + } + >((data) => api.post(`/v1/auth/login`, data)); + + const onLogin = async (data) => { + const itemData = { + email: data.email, + password: data.password, + }; + + try { + const response = await mutateAsync(itemData); + setToken((response as any).token); + router.push('/templates'); + } catch (e: any) { + if (e.statusCode !== 400) { + Sentry.captureException(e); + } + } + }; + + return ( + <> +

+ + } /> + + + Password + + Forget Password? + +
+ } + rules={[ + { + required: true, + message: 'Please input your password', + }, + ]}> + } /> + + + + + {/*
+ + or + +
+ +
+
*/} + + {isError ? ( + + ) : null} + + ); +} diff --git a/apps/web/src/components/auth/PasswordResetForm.tsx b/apps/web/src/components/auth/PasswordResetForm.tsx new file mode 100644 index 00000000000..c2cae9b9f63 --- /dev/null +++ b/apps/web/src/components/auth/PasswordResetForm.tsx @@ -0,0 +1,113 @@ +import { Button, Form, Input, Divider, Alert, message } from 'antd'; +import { LockOutlined, MailOutlined } from '@ant-design/icons'; +import { useHistory, Link } from 'react-router-dom'; +import { useMutation } from 'react-query'; +import * as Sentry from '@sentry/react'; +import { useContext } from 'react'; +import { AuthContext } from '../../store/authContext'; +import { api } from '../../api/api.client'; + +type Props = { + token: string; +}; + +export function PasswordResetForm({ token }: Props) { + const { setToken } = useContext(AuthContext); + + const history = useHistory(); + const { isLoading, mutateAsync, isError, error } = useMutation< + { token: string }, + { error: string; message: string; statusCode: number }, + { + password: string; + token: string; + } + >((data) => api.post(`/v1/auth/reset`, data)); + + const onForgotPassword = async (data) => { + if (data.password !== data.passwordRepeat) { + return message.error('Passwords do not match'); + } + + const itemData = { + password: data.password, + token, + }; + + try { + const response = await mutateAsync(itemData); + setToken(response.token); + message.success('Password was changed successfully'); + history.push('/templates'); + } catch (e: any) { + if (e.statusCode !== 400) { + Sentry.captureException(e); + } + } + + return true; + }; + + return ( + <> +
+ + Password + + } + rules={[ + { + required: true, + message: 'Please input your password', + }, + { + min: 8, + message: 'Minimum 8 characters', + }, + { + pattern: /^(?=.*\d)(?=.*[a-z])(?!.*\s).{8,}$/, + message: 'The password must contain numbers and letters', + }, + ]}> + } /> + + + Repeat Password + + } + rules={[ + { + required: true, + message: 'Please input your password', + }, + { + min: 8, + message: 'Minimum 8 characters', + }, + { + pattern: /^(?=.*\d)(?=.*[a-z])(?!.*\s).{8,}$/, + message: 'The password must contain numbers and letters', + }, + ]}> + } /> + + + + +
+ {isError ? ( + + ) : null} + + ); +} diff --git a/apps/web/src/components/auth/PasswordResetRequestForm.tsx b/apps/web/src/components/auth/PasswordResetRequestForm.tsx new file mode 100644 index 00000000000..dd807d61535 --- /dev/null +++ b/apps/web/src/components/auth/PasswordResetRequestForm.tsx @@ -0,0 +1,63 @@ +import { Button, Form, Input, Divider, Alert, Result } from 'antd'; +import { MailOutlined } from '@ant-design/icons'; +import { Link } from 'react-router-dom'; +import { useMutation } from 'react-query'; +import * as Sentry from '@sentry/react'; +import { api } from '../../api/api.client'; + +type Props = { + onSent: () => void; +}; + +export function PasswordRequestResetForm({ onSent }: Props) { + const { isLoading, mutateAsync } = useMutation< + { success: boolean }, + { error: string; message: string; statusCode: number }, + { + email: string; + } + >((data) => api.post(`/v1/auth/reset/request`, data)); + + const onForgotPassword = async (data) => { + const itemData = { + email: data.email, + }; + + try { + const response = await mutateAsync(itemData); + onSent(); + } catch (e: any) { + if (e.statusCode !== 400) { + Sentry.captureException(e); + } + } + }; + + return ( + <> +
+ + } /> + + + + +
+ + ); +} diff --git a/apps/web/src/components/auth/SignUpForm.tsx b/apps/web/src/components/auth/SignUpForm.tsx new file mode 100644 index 00000000000..4ac225b4168 --- /dev/null +++ b/apps/web/src/components/auth/SignUpForm.tsx @@ -0,0 +1,146 @@ +import { Alert, Button, Form, Input, message } from 'antd'; +import { LockOutlined, MailOutlined, UserOutlined, TeamOutlined } from '@ant-design/icons'; +import { useContext } from 'react'; +import { useMutation } from 'react-query'; +import { useHistory } from 'react-router-dom'; +import { AuthContext } from '../../store/authContext'; +import { api } from '../../api/api.client'; + +type Props = { + token?: string; + email?: string; +}; + +export function SignUpForm({ token, email }: Props) { + const router = useHistory(); + const { setToken } = useContext(AuthContext); + const { isLoading: loadingAcceptInvite, mutateAsync: acceptInvite } = useMutation< + string, + { error: string; message: string; statusCode: number }, + string + >((tokenItem) => api.post(`/v1/invites/${tokenItem}/accept`, {})); + + const { isLoading, mutateAsync, isError, error } = useMutation< + { token: string }, + { error: string; message: string; statusCode: number }, + { + firstName: string; + lastName: string; + email: string; + password: string; + } + >((data) => api.post(`/v1/auth/register`, data)); + + const onSubmit = async (data) => { + const itemData = { + firstName: data.fullName.split(' ')[0], + lastName: data.fullName.split(' ')[1], + email: data.email, + password: data.password, + organizationName: data.organizationName, + }; + + if (!itemData.lastName) { + return message.error('Please write your full name including last name'); + } + const response = await mutateAsync(itemData); + setToken((response as any).token); + + if (token) { + const responseInvite = await acceptInvite(token); + setToken(responseInvite); + } + + router.push('/templates'); + return true; + }; + + return ( + <> + {isError ? : null} + +
+ + } placeholder="Your full name goes here" /> + + + } + placeholder="Work email goes here" + /> + + + } + placeholder="Password, not your birthdate" + /> + + {!token ? ( + + } placeholder="Mega Corp" /> + + ) : null} + + + + +
+ + ); +} diff --git a/apps/web/src/components/layout/LoginLayout.tsx b/apps/web/src/components/layout/LoginLayout.tsx new file mode 100644 index 00000000000..0711f4bddc3 --- /dev/null +++ b/apps/web/src/components/layout/LoginLayout.tsx @@ -0,0 +1,13 @@ +import styled from 'styled-components'; + +type Props = { + children: JSX.Element; +}; + +export function AuthLayout({ children }: Props) { + return ( + <> +
{children}
+ + ); +} diff --git a/apps/web/src/components/layout/app-layout/AppLayout.tsx b/apps/web/src/components/layout/app-layout/AppLayout.tsx new file mode 100644 index 00000000000..722903b9535 --- /dev/null +++ b/apps/web/src/components/layout/app-layout/AppLayout.tsx @@ -0,0 +1,116 @@ +import React, { useContext, useEffect } from 'react'; +import { Layout, Grid, Result, Button, Divider } from 'antd'; +import * as Sentry from '@sentry/react'; +import { ThemeProvider } from 'styled-components'; +import { HeaderNav } from '../components/HeaderNav'; +import { SideNav } from '../components/SideNav'; +import { AuthContext } from '../../../store/authContext'; +import { useApplication } from '../../../api/hooks/use-application'; + +const { Header, Content, Footer } = Layout; + +export function AppLayout({ children }: { children: any }) { + const authContext = useContext(AuthContext); + const { application } = useApplication(); + const theme = { + colors: { + main: application?.branding?.color || '#cd5450', + }, + layout: { + direction: application?.branding?.direction || 'ltr', + }, + }; + + useEffect(() => { + if ( + (process.env.REACT_APP_ENVIRONMENT === 'dev' || process.env.REACT_APP_ENVIRONMENT === 'prod') && + authContext.currentUser + ) { + (function (n, o, t, i, f) { + let m; + /* eslint-disable */ + (n[i] = {}), (m = ['init']); + n[i]._c = []; + m.forEach( + (me) => + (n[i][me] = function () { + n[i]._c.push([me, arguments]); + }) + ); + const elt: any = o.createElement(f); + elt.type = 'text/javascript'; + elt.async = true; + elt.src = t; + const before = o.getElementsByTagName(f)[0]; + before.parentNode?.insertBefore(elt, before); + })(window, document, process.env.REACT_APP_WIDGET_SDK_PATH, 'notifire', 'script'); + + (window as any).notifire.init( + process.env.REACT_APP_NOTIFIRE_APP_ID, + { bellSelector: '#notification-bell', unseenBadgeSelector: '#unseen-badge-selector' }, + { + $user_id: authContext.currentUser?._id, + $last_name: authContext.currentUser?.lastName, + $first_name: authContext.currentUser?.firstName, + $email: authContext.currentUser?.email, + } + ); + } + }, [authContext.currentUser]); + + return ( + <> + + + + + + + ( + <> + + Sorry, but something went wrong.
+ Our team been notified about it and we will look at it asap. +
+ + } + extra={ + <> +
+
+ +
+ + + + Event Id: {eventId}. +
+ {error.toString()} +
+
+
+ + } + /> + + )}> + + {children} +
Notifire ©2021
+
+
+
+
+
+
+ + ); +} diff --git a/apps/web/src/components/layout/components/HeaderNav.tsx b/apps/web/src/components/layout/components/HeaderNav.tsx new file mode 100644 index 00000000000..041068de979 --- /dev/null +++ b/apps/web/src/components/layout/components/HeaderNav.tsx @@ -0,0 +1,112 @@ +import styled from 'styled-components'; +import { Menu, Dropdown, Avatar, Layout, Button } from 'antd'; +import { MenuUnfoldOutlined, SettingOutlined, LogoutOutlined, BellOutlined } from '@ant-design/icons'; +import { useQuery } from 'react-query'; +import { IOrganizationEntity, IUserEntity } from '@notifire/shared'; +import { useContext } from 'react'; +import * as capitalize from 'lodash.capitalize'; +import { AuthContext } from '../../../store/authContext'; +import { getUser } from '../../../api/user'; +import { getCurrentOrganization } from '../../../api/organization'; + +const { Header } = Layout; + +type Props = {}; +const menuItem = [ + { + title: 'Invite Members', + icon: SettingOutlined, + path: '/settings/organization', + }, +]; + +export function HeaderNav({}: Props) { + const authContext = useContext(AuthContext); + const { data: user, isLoading: isUserLoading } = useQuery('/v1/users/me', getUser); + const { data: organization, isLoading: isOrganizationLoading } = useQuery( + '/v1/organizations/me', + getCurrentOrganization + ); + + const profileMenu = ( +
+ ); + + return ( + <> +
+
+ logo +
+
+
+
+ +
+ + + + + + + + +
+
+
+ + ); +} + +const StyledUnseenCounter = styled.span` + position: absolute !important; +`; diff --git a/apps/web/src/components/layout/components/PageHeader.tsx b/apps/web/src/components/layout/components/PageHeader.tsx new file mode 100644 index 00000000000..f1a49d455d2 --- /dev/null +++ b/apps/web/src/components/layout/components/PageHeader.tsx @@ -0,0 +1,27 @@ +import styled from 'styled-components'; + +export function PageHeader({ actions, title }: { actions?: JSX.Element; title: string }) { + return ( + +
+
+

{title}

+ {actions &&
{actions}
} +
+
+
+ ); +} + +const HeaderWrapper = styled.div` + padding: 25px; + background: white; + margin-top: -25px; + margin-left: -25px; + margin-right: -25px; + margin-bottom: 25px; + + h2 { + margin-bottom: 0; + } +`; diff --git a/apps/web/src/components/layout/components/SideNav.tsx b/apps/web/src/components/layout/components/SideNav.tsx new file mode 100644 index 00000000000..58d87e47891 --- /dev/null +++ b/apps/web/src/components/layout/components/SideNav.tsx @@ -0,0 +1,46 @@ +import styled from 'styled-components'; +import { Layout, Menu } from 'antd'; +import { Scrollbars } from 'react-custom-scrollbars'; +import { useQuery } from 'react-query'; +import { IOrganizationEntity } from '@notifire/shared'; +import { NavLink } from 'react-router-dom'; +import { SettingOutlined, NotificationOutlined, MonitorOutlined, TeamOutlined } from '@ant-design/icons'; + +const { Sider } = Layout; + +type Props = {}; + +export function SideNav({}: Props) { + const { data: organization, isLoading: isOrganizationLoading } = useQuery( + '/v1/organizations/me' + ); + + return ( + + + + }> + + Notifications + + + }> + + Activity Feed + + + }> + + Settings + + + }> + + Team Members + + + + + + ); +} diff --git a/apps/web/src/components/layout/components/TopNav.tsx b/apps/web/src/components/layout/components/TopNav.tsx new file mode 100644 index 00000000000..dd3796a8106 --- /dev/null +++ b/apps/web/src/components/layout/components/TopNav.tsx @@ -0,0 +1,20 @@ +import styled from 'styled-components'; +import { Menu } from 'antd'; + +type Props = {}; + +export function TopNav({}: Props) { + return ( + <> +
+
+ + + Test Path + + +
+
+ + ); +} diff --git a/apps/web/src/components/onboarding/ApplicationCreateForm.tsx b/apps/web/src/components/onboarding/ApplicationCreateForm.tsx new file mode 100644 index 00000000000..e4b3674cdf0 --- /dev/null +++ b/apps/web/src/components/onboarding/ApplicationCreateForm.tsx @@ -0,0 +1,72 @@ +import { Button, Form, Input } from 'antd'; +import { TeamOutlined } from '@ant-design/icons'; +import { useContext, useEffect, useState } from 'react'; +import { useMutation } from 'react-query'; +import decode from 'jwt-decode'; +import { IJwtPayload } from '@notifire/shared'; +import { useHistory } from 'react-router-dom'; +import { AuthContext } from '../../store/authContext'; +import { api } from '../../api/api.client'; + +type Props = {}; + +export function ApplicationCreateForm({}: Props) { + const history = useHistory(); + + const { setToken, token } = useContext(AuthContext); + + const [loading, setLoading] = useState(); + const { mutateAsync } = useMutation< + { _id: string }, + { error: string; message: string; statusCode: number }, + { + name: string; + } + >((data) => api.post(`/v1/applications`, data)); + + useEffect(() => { + if (token) { + const userData = decode(token); + if (userData.applicationId) { + history.push('/'); + } + } + }, []); + + const onSubmit = async (data) => { + setLoading(true); + const itemData = { + name: data.applicationName, + }; + + const response = (await mutateAsync(itemData)) as any; + const tokenResponse = await api.post(`/v1/auth/applications/${response.data._id}/switch`, data); + setToken(tokenResponse.data.token); + setLoading(false); + history.push('/'); + }; + + return ( + <> +
+ + } placeholder="Amazing App" /> + + + + +
+ + ); +} diff --git a/apps/web/src/components/query-builder/components/Builder.tsx b/apps/web/src/components/query-builder/components/Builder.tsx new file mode 100644 index 00000000000..1ceed738903 --- /dev/null +++ b/apps/web/src/components/query-builder/components/Builder.tsx @@ -0,0 +1,136 @@ +import React, { useEffect, useState } from 'react'; +import styled from 'styled-components'; +import uniqid from 'uniqid'; +import { BuilderFieldOperator, BuilderFieldType } from '@notifire/shared'; +import { Strings, strings as defaultStrings } from '../constants/strings'; +import { assignIds } from '../utils/assignIds'; +import { denormalizeTree } from '../utils/denormalizeTree'; +import { normalizeTree } from '../utils/normalizeTree'; +import { Button } from './Button'; +import { Component } from './Component/Component'; +import { BuilderContextProvider } from './Context'; +import { Input } from './Form/Input'; +import { Select } from './Form/Select'; +import { SelectMulti } from './Form/SelectMulti'; +import { Switch } from './Form/Switch'; +import { Group } from './Group/Group'; +import { Option as GroupHeaderOption } from './Group/Option'; +import { Iterator } from './Iterator'; +import { Text } from './Text'; +import { DeleteButton } from './RemoveButton'; +/* eslint react/prop-types: 0 */ +/* eslint no-param-reassign: 0 */ + +export const StyledBuilder = styled.div` + background: #fff; +`; + +export interface BuilderFieldProps { + field: string; + label: string; + value?: string | string[] | boolean | Array<{ value: React.ReactText; label: string }>; + type: BuilderFieldType; + /* List of available operators */ + operators?: BuilderFieldOperator[]; +} + +export interface BuilderComponentsProps { + form?: { + Select?: any; + SelectMulti?: any; + Switch?: any; + Input?: any; + }; + Remove?: any; + Add?: any; + Component?: any; + Group?: any; + GroupHeaderOption?: any; + Text?: any; +} + +export interface BuilderProps { + fields: BuilderFieldProps[]; + data: any; + components?: BuilderComponentsProps; + strings?: Strings; + readOnly?: boolean; + onChange?: (data: any) => any; +} + +export const defaultComponents: BuilderComponentsProps = { + form: { + Input, + Select, + SelectMulti, + Switch, + }, + Remove: DeleteButton, + Add: Button, + Component, + Group, + GroupHeaderOption, + Text, +}; + +export const Builder: React.FC = ({ + data: originalData, + fields, + components = defaultComponents, + strings = defaultStrings, + readOnly = false, + onChange, +}) => { + let normalizedData: any; + originalData = assignIds(originalData); + + if (originalData.length === 0) { + originalData = [ + { + type: 'GROUP', + value: 'AND', + isNegated: false, + id: uniqid(), + children: originalData, + }, + ]; + } + + try { + normalizedData = normalizeTree(originalData); + } catch (e) { + throw new Error('Input data tree is in invalid format'); + } + + const [data, setData] = useState(normalizedData); + const filteredData = data.filter((item: any) => !item.parent); + + useEffect(() => { + handleChange(normalizedData); + }, []); + + const handleChange = (nextData: any) => { + if (onChange) { + try { + onChange(denormalizeTree(nextData)); + } catch (e) { + throw new Error('Input data tree is in invalid format'); + } + } + }; + + return ( + + + + + + ); +}; diff --git a/apps/web/src/components/query-builder/components/Button.tsx b/apps/web/src/components/query-builder/components/Button.tsx new file mode 100644 index 00000000000..11dd1071fdf --- /dev/null +++ b/apps/web/src/components/query-builder/components/Button.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import { Button as ButtonBase } from 'antd'; + +export interface ButtonProps { + onClick: () => void; + className?: string; + label: string; +} + +export const Button: React.FC = ({ label, onClick, ...rest }: ButtonProps) => ( + + {label} + +); diff --git a/apps/web/src/components/query-builder/components/Component/Component.tsx b/apps/web/src/components/query-builder/components/Component/Component.tsx new file mode 100644 index 00000000000..f8b57fe9eb6 --- /dev/null +++ b/apps/web/src/components/query-builder/components/Component/Component.tsx @@ -0,0 +1,52 @@ +import React from 'react'; +import styled, { css } from 'styled-components'; + +export interface ComponentProps { + children: React.ReactNode | React.ReactNodeArray; + controls: React.ReactNode | React.ReactNodeArray; + className?: string; +} + +export const Paper = styled.div<{ hideBorder?: boolean }>` + background-color: #ffffff; + + ${({ hideBorder }) => { + return hideBorder + ? css` + border: none; + ` + : css` + border: 1px solid #edf2f9 !important; + `; + }} +`; + +const Container = styled(Paper)` + display: grid; + grid-template-columns: 1fr auto; + align-items: center; + margin: 0.5rem 0; +`; + +const Content = styled.div` + padding: 1rem; + display: grid; + grid-auto-columns: max-content; + grid-auto-flow: column; + grid-gap: 0.5rem; +`; + +const Header = styled.div` + padding: 1rem; + display: grid; + grid-auto-columns: max-content; + grid-auto-flow: column; + justify-content: flex-end; +`; + +export const Component: React.FC = ({ children, controls, ...rest }: ComponentProps) => ( + + {children} +
{controls}
+
+); diff --git a/apps/web/src/components/query-builder/components/Component/index.tsx b/apps/web/src/components/query-builder/components/Component/index.tsx new file mode 100644 index 00000000000..8700860e447 --- /dev/null +++ b/apps/web/src/components/query-builder/components/Component/index.tsx @@ -0,0 +1,135 @@ +import React, { useContext } from 'react'; +import styled from 'styled-components'; +import { BuilderFieldOperator } from '@notifire/shared'; +import { clone } from '../../utils/clone'; +import { isBoolean, isOptionList, isString, isStringArray, isUndefined } from '../../utils/types'; +import { BuilderContext } from '../Context'; +import { Boolean } from '../Widgets/Boolean'; +import { FieldSelect } from '../Widgets/FieldSelect'; +import { Input } from '../Widgets/Input'; +import { OperatorSelect } from '../Widgets/OperatorSelect'; +import { Select } from '../Widgets/Select'; +import { SelectMulti } from '../Widgets/SelectMulti'; + +const BooleanContainer = styled.div` + align-self: center; +`; + +export interface ComponentProps { + field: string; + value?: string | string[] | boolean; + operator?: BuilderFieldOperator; + id: string; +} + +export const Component: React.FC = ({ + field: fieldRef, + value: selectedValue, + operator, + id, +}: ComponentProps) => { + const { fields, data, setData, onChange, components, strings, readOnly } = useContext(BuilderContext); + const { Component: ComponentContainer, Remove } = components; + + const handleDelete = () => { + let clonedData = clone(data); + const index = clonedData.findIndex((item: any) => item.id === id); + const parentIndex = clonedData.findIndex((item: any) => item.id === clonedData[index].parent); + const parent = clonedData[parentIndex]; + + parent.children = parent.children.filter((item: string) => item !== id); + clonedData = clonedData.filter((item: any) => item.id !== id); + + setData(clonedData); + if (onChange) { + onChange(clonedData); + } + }; + + if (fields && strings.component) { + if (fieldRef === '') { + return ( + } + data-test-id="filter-builder-row"> + + + ); + } + try { + const fieldIndex = fields.findIndex((item) => item.field === fieldRef); + + const { field, operators, type, value: fieldValue } = fields[fieldIndex]; + + const operatorsOptionList = + operators && + operators.map((item) => ({ + value: item, + label: strings.operators && strings.operators[item], + })); + + return ( + } + data-test-id="filter-builder-row"> + + + {type === 'BOOLEAN' && isBoolean(selectedValue) && ( + + + + )} + + {type === 'LIST' && isString(selectedValue) && isOptionList(fieldValue) && isOptionList(operatorsOptionList) && ( + <> + + {operator && } + + )} + + {type === 'NUMBER' && + isOptionList(operatorsOptionList) && + (isString(selectedValue) || isStringArray(selectedValue)) && ( + <> + + {operator && } + + )} + + {type === 'DATE' && + isOptionList(operatorsOptionList) && + (isString(selectedValue) || isStringArray(selectedValue)) && ( + <> + + {!isUndefined(operator) && } + + )} + + ); + } catch (e) { + // tslint:disable-next-line: no-console + console.error(`Field "${fieldRef}" not found in fields definition.`); + } + } + + return null; +}; diff --git a/apps/web/src/components/query-builder/components/Context.tsx b/apps/web/src/components/query-builder/components/Context.tsx new file mode 100644 index 00000000000..a3b17fcee77 --- /dev/null +++ b/apps/web/src/components/query-builder/components/Context.tsx @@ -0,0 +1,77 @@ +import React, { createContext } from 'react'; +import { Strings, strings as defaultStrings } from '../constants/strings'; +import { BuilderComponentsProps, BuilderFieldProps, defaultComponents } from './Builder'; +/* eslint react/prop-types: 0 */ +export interface BuilderContextProps { + fields: BuilderFieldProps[]; + data: any; + readOnly: boolean; + components: BuilderComponentsProps; + strings: Strings; + setData: React.Dispatch; + onChange?: (data: any) => void; +} + +export const BuilderContext = createContext( + // tslint:disable-next-line: no-object-literal-type-assertion + {} as BuilderContextProps +); + +export interface BuilderContextProviderProps extends BuilderContextProps { + children: React.ReactNode | React.ReactNodeArray; +} + +export const BuilderContextProvider: React.FC = ({ + fields, + components, + strings, + data, + readOnly, + setData, + onChange, + children, +}) => { + // eslint-disable-next-line no-param-reassign + components = { + ...defaultComponents, + ...components, + form: { ...defaultComponents.form, ...components.form }, + }; + + // eslint-disable-next-line no-param-reassign + strings = { + ...defaultStrings, + ...strings, + component: { + ...defaultStrings.component, + ...strings.component, + }, + form: { + ...defaultStrings.form, + ...strings.form, + }, + group: { + ...defaultStrings.group, + ...strings.group, + }, + operators: { + ...defaultStrings.operators, + ...strings.operators, + }, + }; + + return ( + + {children} + + ); +}; diff --git a/apps/web/src/components/query-builder/components/Form/Input.tsx b/apps/web/src/components/query-builder/components/Form/Input.tsx new file mode 100644 index 00000000000..f31626b4e2b --- /dev/null +++ b/apps/web/src/components/query-builder/components/Form/Input.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { Input as InputBase, DatePicker } from 'antd'; +import moment from 'moment'; + +export interface InputProps { + type: 'date' | 'number' | 'text'; + value: string; + onChange: (value: string) => void; + className?: string; + disabled?: boolean; +} + +export const Input: React.FC = ({ onChange, value, type }: InputProps) => { + const handleChange = (event: React.ChangeEvent) => { + onChange(event.target.value); + }; + + const handleChangeDate = (date: any) => { + onChange(date.format('YYYY-MM-DD')); + }; + + if (type === 'date') { + return ; + } + return ; +}; diff --git a/apps/web/src/components/query-builder/components/Form/Select.tsx b/apps/web/src/components/query-builder/components/Form/Select.tsx new file mode 100644 index 00000000000..6b192809a1f --- /dev/null +++ b/apps/web/src/components/query-builder/components/Form/Select.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { Select as SelectBase } from 'antd'; + +export interface SelectProps { + values: Array<{ value: string; label: string }>; + selectedValue?: string; + emptyValue?: string; + onChange: (value: any) => void; + className?: string; + disabled?: boolean; +} + +const { Option } = SelectBase; + +export const Select: React.FC = ({ onChange, selectedValue, values }: SelectProps) => { + const handleChange = (value: string) => { + onChange(value); + }; + + return ( + + + {values.map((option) => ( + + ))} + + ); +}; diff --git a/apps/web/src/components/query-builder/components/Form/SelectMulti.tsx b/apps/web/src/components/query-builder/components/Form/SelectMulti.tsx new file mode 100644 index 00000000000..6e1e90e3efb --- /dev/null +++ b/apps/web/src/components/query-builder/components/Form/SelectMulti.tsx @@ -0,0 +1,49 @@ +import React from 'react'; +import { Select } from 'antd'; +import { SelectProps } from './Select'; + +const { Option } = Select; + +export interface SelectMultiProps extends Pick { + onDelete: (value: string) => void; + selectedValue: string[]; + emptyValue?: string; + disabled?: boolean; + className?: string; +} + +export const SelectMulti: React.FC = ({ + onChange, + onDelete, + selectedValue, + values, +}: SelectMultiProps) => { + const handleChange = (value: any) => { + onChange(String(value)); + }; + + const handleDelete = (value: any) => { + onDelete(String(value)); + }; + + return ( + + ); +}; diff --git a/apps/web/src/components/query-builder/components/Form/Switch.tsx b/apps/web/src/components/query-builder/components/Form/Switch.tsx new file mode 100644 index 00000000000..626a5c85cd3 --- /dev/null +++ b/apps/web/src/components/query-builder/components/Form/Switch.tsx @@ -0,0 +1,67 @@ +import React from 'react'; +import styled, { css } from 'styled-components'; +import { colors } from '../../constants/colors'; + +const Knob = styled.div` + position: absolute; + width: 1.3rem; + height: 1.3rem; + background: white; + border: 1px solid ${colors.dark}; + border-radius: 50%; + box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.4); +`; + +const StyledSwitch = styled.div<{ switched: boolean; disabled: boolean }>` + position: relative; + width: 3rem; + height: 1.65rem; + background-color: ${({ switched }) => (switched ? colors.primary : colors.darker)}; + border: 1px solid ${colors.dark}; + border-radius: 1.4rem; + cursor: pointer; + transition: all 0.5s; + + ${({ disabled }) => + disabled && + css` + background-color: ${colors.darker}; + cursor: initial; + + ${Knob} { + background: ${colors.disabled}; + } + `} + + ${Knob} { + top: 0.1rem; + left: ${({ switched }) => (switched ? '1.3rem' : '0.1rem')}; + transition: all 0.5s; + } +`; + +export interface SwitchProps { + switched: boolean; + onChange?: (value: boolean) => void; + disabled?: boolean; + className?: string; +} + +export const Switch: React.FC = ({ switched, onChange, disabled = false, className }: SwitchProps) => { + const handleClick = () => { + if (onChange && !disabled) { + onChange(!switched); + } + }; + + return ( + + + + ); +}; diff --git a/apps/web/src/components/query-builder/components/Group/Group.tsx b/apps/web/src/components/query-builder/components/Group/Group.tsx new file mode 100644 index 00000000000..b99b277735d --- /dev/null +++ b/apps/web/src/components/query-builder/components/Group/Group.tsx @@ -0,0 +1,56 @@ +import React from 'react'; +import ButtonGroup from 'antd/es/button/button-group'; +import styled, { css } from 'styled-components'; +import { Paper } from '../Component/Component'; + +export interface GroupProps { + controlsLeft?: React.ReactNode | React.ReactNodeArray; + controlsRight?: React.ReactNode | React.ReactNodeArray; + children: React.ReactNode | React.ReactNodeArray; + className?: string; + isRoot?: boolean; + show?: boolean; +} + +const Container = styled(Paper)` + margin: 0.5rem 0; + background-color: #f9f9f9; + + && { + background-color: #f9f9f9; +`; + +const Content = styled.div` + padding: 1rem; +`; + +const Header = styled.div` + padding: 1rem 1rem 0; + display: flex; + justify-content: center; +`; + +const Right = styled.div` + display: grid; + grid-auto-flow: column; + grid-auto-columns: min-content; + grid-auto-rows: min-content; + align-items: center; + justify-content: end; + grid-gap: 0.5rem; +`; + +export const Group: React.FC = ({ children, controlsLeft, controlsRight, isRoot, show }: GroupProps) => { + return ( + + {show && ( +
+
+ {controlsLeft} +
+
+ )} + {children} +
+ ); +}; diff --git a/apps/web/src/components/query-builder/components/Group/Option.tsx b/apps/web/src/components/query-builder/components/Group/Option.tsx new file mode 100644 index 00000000000..7ce829e8be9 --- /dev/null +++ b/apps/web/src/components/query-builder/components/Group/Option.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { Button } from 'antd'; + +export interface OptionProps { + children: React.ReactNode | React.ReactNodeArray; + value: any; + onClick: (value: any) => void; + disabled: boolean; + isSelected: boolean; + className?: string; +} + +export const Option: React.FC = ({ children, isSelected, onClick, value }: OptionProps) => { + const handleClick = () => { + onClick(value); + }; + + return ( + + ); +}; diff --git a/apps/web/src/components/query-builder/components/Group/index.tsx b/apps/web/src/components/query-builder/components/Group/index.tsx new file mode 100644 index 00000000000..673542a2694 --- /dev/null +++ b/apps/web/src/components/query-builder/components/Group/index.tsx @@ -0,0 +1,163 @@ +import React, { useContext } from 'react'; +import uniqid from 'uniqid'; +import { BuilderGroupValues } from '@notifire/shared'; +import { Switch } from 'antd'; +import { clone } from '../../utils/clone'; +import { BuilderContext } from '../Context'; + +export interface GroupProps { + value?: BuilderGroupValues; + isNegated?: boolean; + children?: React.ReactNode | React.ReactNodeArray; + id: string; + isRoot: boolean; +} + +export const Group: React.FC = ({ value, isNegated, children, id, isRoot }: GroupProps) => { + const { components, data, setData, onChange, strings, readOnly } = useContext(BuilderContext); + const { Add, Group: GroupContainer, GroupHeaderOption: Option, Remove } = components; + + const findIndex = () => { + const clonedData = clone(data); + const parentIndex = clonedData.findIndex((item: any) => item.id === id); + let insertAfter = parentIndex; + + if (data[parentIndex].children && data[parentIndex].children.length > 0) { + const lastChildren = clonedData[parentIndex].children.slice(-1)[0]; + insertAfter = clonedData.findIndex((item: any) => item.id === lastChildren); + } + + return { insertAfter, parentIndex, clonedData }; + }; + + const addItem = (payload: any) => { + const { insertAfter, parentIndex, clonedData } = findIndex(); + + if (!clonedData[parentIndex].children) { + clonedData[insertAfter].children = []; + } + + clonedData[parentIndex].children.push(payload.id); + clonedData.splice(Number(insertAfter) + 1, 0, payload); + + setData(clonedData); + if (onChange) { + onChange(clonedData); + } + }; + + const handleAddGroup = () => { + const EmptyGroup: any = { + type: 'GROUP', + value: 'AND', + isNegated: false, + id: uniqid(), + parent: id, + children: [], + }; + + addItem(EmptyGroup); + }; + + const handleAddRule = () => { + const EmptyRule: any = { + field: '', + id: uniqid(), + parent: id, + }; + + addItem(EmptyRule); + }; + + const handleChangeGroupType = (nextValue: BuilderGroupValues) => { + const { clonedData, parentIndex } = findIndex(); + clonedData[parentIndex].value = nextValue; + + setData(clonedData); + if (onChange) { + onChange(clonedData); + } + }; + + const handleToggleNegateGroup = (nextValue: boolean) => { + const { clonedData, parentIndex } = findIndex(); + clonedData[parentIndex].isNegated = nextValue; + + setData(clonedData); + + if (onChange) { + onChange(clonedData); + } + }; + + const handleDeleteGroup = () => { + let clonedData = clone(data).filter((item: any) => item.id !== id); + + clonedData = clonedData.map((item: any) => { + if (item.children && item.children.length > 0) { + // eslint-disable-next-line no-param-reassign + item.children = item.children.filter((childId: string) => childId !== id); + } + + return item; + }); + + setData(clonedData); + if (onChange) { + onChange(clonedData); + } + }; + + if (strings.group) { + return ( + 2} + controlsLeft={ + <> + {data?.length > 2 && ( + <> + + + + )} + {/* */} + + }> + {children} + {!readOnly && ( +
+ + {/* + +*/} + {!isRoot && } +
+ )} +
+ ); + } + + return null; +}; diff --git a/apps/web/src/components/query-builder/components/Iterator.tsx b/apps/web/src/components/query-builder/components/Iterator.tsx new file mode 100644 index 00000000000..175854b2cfd --- /dev/null +++ b/apps/web/src/components/query-builder/components/Iterator.tsx @@ -0,0 +1,50 @@ +import React from 'react'; +import { Component, ComponentProps } from './Component/index'; +import { Group, GroupProps } from './Group/index'; +/* eslint react/prop-types: 0 */ + +export interface IteratorProps { + originalData: any; + filteredData: any; + isRoot?: boolean; +} + +export const Iterator: React.FC = ({ originalData, filteredData, isRoot = true }) => { + return ( + <> + {filteredData.map((item: any) => { + if (typeof item.children !== 'undefined') { + const items: any = []; + + item.children.forEach((id: any) => { + items.push(originalData.filter((fitem: any) => id === fitem.id)[0]); + }); + + if (item.type === 'GROUP') { + const { id, value, isNegated } = item as GroupProps; + + return ( + + + + ); + } + + return null; + } + const { field, value, id, operator } = item as ComponentProps; + + return ( + + ); + })} + + ); +}; diff --git a/apps/web/src/components/query-builder/components/RemoveButton.tsx b/apps/web/src/components/query-builder/components/RemoveButton.tsx new file mode 100644 index 00000000000..b5e98c35807 --- /dev/null +++ b/apps/web/src/components/query-builder/components/RemoveButton.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import { Button as ButtonBase, Tooltip } from 'antd'; +import styled from 'styled-components'; +import { MinusCircleOutlined } from '@ant-design/icons'; +import { ButtonProps } from './Button'; + +const StyledButton = styled(ButtonBase)` + white-space: nowrap; +`; + +export const DeleteButton: React.FC = ({ label, onClick }: ButtonProps) => ( + + } ghost /> + +); diff --git a/apps/web/src/components/query-builder/components/SecondaryButton.tsx b/apps/web/src/components/query-builder/components/SecondaryButton.tsx new file mode 100644 index 00000000000..6a0612087d6 --- /dev/null +++ b/apps/web/src/components/query-builder/components/SecondaryButton.tsx @@ -0,0 +1,7 @@ +import styled from 'styled-components'; +import { colors } from '../constants/colors'; +import { Button, ButtonProps } from './Button'; + +export const SecondaryButton = styled(Button)` + background-color: ${colors.tertiary}; +`; diff --git a/apps/web/src/components/query-builder/components/Text.tsx b/apps/web/src/components/query-builder/components/Text.tsx new file mode 100644 index 00000000000..135f4e6e267 --- /dev/null +++ b/apps/web/src/components/query-builder/components/Text.tsx @@ -0,0 +1,11 @@ +import styled from 'styled-components'; +import { colors } from '../constants/colors'; + +export const Text = styled.span` + min-width: 160px; + padding: 0.4rem 0.6rem; + color: ${colors.dark}; + line-height: 1.3; + border: 1px solid ${colors.medium}; + border-radius: 3px; +`; diff --git a/apps/web/src/components/query-builder/components/Widgets/Boolean.tsx b/apps/web/src/components/query-builder/components/Widgets/Boolean.tsx new file mode 100644 index 00000000000..d32c3722fda --- /dev/null +++ b/apps/web/src/components/query-builder/components/Widgets/Boolean.tsx @@ -0,0 +1,33 @@ +import React, { useContext } from 'react'; +import { clone } from '../../utils/clone'; +import { BuilderContext } from '../Context'; + +export interface BooleanProps { + selectedValue: boolean; + id: string; +} + +// tslint:disable-next-line: variable-name +export const Boolean: React.FC = ({ selectedValue, id }: BooleanProps) => { + const { data, setData, onChange, components, readOnly } = useContext(BuilderContext); + + const { form } = components; + + const handleChange = (value: boolean) => { + const clonedData = clone(data); + const parentIndex = clonedData.findIndex((item: any) => item.id === id); + + clonedData[parentIndex].value = value; + + setData(clonedData); + if (onChange) { + onChange(clonedData); + } + }; + + if (form) { + return ; + } + + return null; +}; diff --git a/apps/web/src/components/query-builder/components/Widgets/FieldSelect.tsx b/apps/web/src/components/query-builder/components/Widgets/FieldSelect.tsx new file mode 100644 index 00000000000..c9f1b9fafd0 --- /dev/null +++ b/apps/web/src/components/query-builder/components/Widgets/FieldSelect.tsx @@ -0,0 +1,102 @@ +import React, { useContext } from 'react'; +import { clone } from '../../utils/clone'; +import { isOptionList } from '../../utils/types'; +import { BuilderContext } from '../Context'; + +interface FieldSelectProps { + selectedValue: string; + id: string; +} + +export const FieldSelect: React.FC = ({ selectedValue, id }: FieldSelectProps) => { + const { fields, data, setData, onChange, components, strings, readOnly } = useContext(BuilderContext); + + const { form } = components; + + const handleChange = (value: string) => { + const clonedData = clone(data); + const parentIndex = clonedData.findIndex((item: any) => item.id === id); + const nextField = fields.filter((item) => item.field === value)[0]; + + clonedData[parentIndex].field = value; + delete clonedData[parentIndex].value; + delete clonedData[parentIndex].operators; + delete clonedData[parentIndex].operator; + + // eslint-disable-next-line default-case + switch (nextField.type) { + case 'BOOLEAN': + clonedData[parentIndex].value = false; + break; + + case 'DATE': + clonedData[parentIndex].value = + nextField.operators && ['BETWEEN', 'NOT_BETWEEN'].includes(nextField.operators[0]) ? ['', ''] : ''; + + clonedData[parentIndex].operator = nextField.operators && nextField.operators[0]; + clonedData[parentIndex].operators = nextField.operators; + break; + + case 'TEXT': + clonedData[parentIndex].value = + nextField.operators && ['BETWEEN', 'NOT_BETWEEN'].includes(nextField.operators[0]) ? ['', ''] : ''; + + clonedData[parentIndex].operator = nextField.operators && nextField.operators[0]; + clonedData[parentIndex].operators = nextField.operators; + break; + + case 'NUMBER': + clonedData[parentIndex].value = + nextField.operators && ['BETWEEN', 'NOT_BETWEEN'].includes(nextField.operators[0]) ? ['0', '0'] : '0'; + + clonedData[parentIndex].operator = nextField.operators && nextField.operators[0]; + clonedData[parentIndex].operators = nextField.operators; + break; + + case 'LIST': + if (isOptionList(nextField.value)) { + clonedData[parentIndex].value = nextField.value[0].value; + } + + clonedData[parentIndex].operator = nextField.operators && nextField.operators[0]; + clonedData[parentIndex].operators = nextField.operators; + break; + + case 'MULTI_LIST': + if (isOptionList(nextField.value)) { + clonedData[parentIndex].value = []; + } + + clonedData[parentIndex].operator = nextField.operators && nextField.operators[0]; + clonedData[parentIndex].operators = nextField.operators; + break; + case 'STATEMENT': + clonedData[parentIndex].value = nextField.value; + break; + } + + setData(clonedData); + if (onChange) { + onChange(clonedData); + } + }; + + const fieldNames = fields.map((field) => ({ + value: field.field, + label: field.label, + })); + + if (form && strings.form) { + return ( + + ); + } + + return null; +}; diff --git a/apps/web/src/components/query-builder/components/Widgets/Input.tsx b/apps/web/src/components/query-builder/components/Widgets/Input.tsx new file mode 100644 index 00000000000..961546045f2 --- /dev/null +++ b/apps/web/src/components/query-builder/components/Widgets/Input.tsx @@ -0,0 +1,57 @@ +import React, { useContext } from 'react'; +import { clone } from '../../utils/clone'; +import { isStringArray, isUndefined } from '../../utils/types'; +import { BuilderContext } from '../Context'; + +interface InputProps { + type: 'date' | 'number' | 'text'; + value: string | string[]; + id: string; +} + +export const Input: React.FC = ({ type, value, id }: InputProps) => { + const { data, setData, onChange, components, readOnly } = useContext(BuilderContext); + + const { form } = components; + + const handleChange = (changedValue: any, index?: number) => { + const clonedData = clone(data); + const parentIndex = clonedData.findIndex((item: any) => item.id === id); + + if (!isUndefined(index)) { + clonedData[parentIndex].value[index] = changedValue; + } else { + clonedData[parentIndex].value = changedValue; + } + + setData(clonedData); + if (onChange) { + onChange(clonedData); + } + }; + + if (form) { + if (isStringArray(value)) { + return ( + <> + handleChange(changedValue, 0)} + disabled={readOnly} + /> + handleChange(changedValue, 1)} + disabled={readOnly} + /> + + ); + } + + return ; + } + + return null; +}; diff --git a/apps/web/src/components/query-builder/components/Widgets/OperatorSelect.tsx b/apps/web/src/components/query-builder/components/Widgets/OperatorSelect.tsx new file mode 100644 index 00000000000..de7ba08c3e7 --- /dev/null +++ b/apps/web/src/components/query-builder/components/Widgets/OperatorSelect.tsx @@ -0,0 +1,57 @@ +import React, { useContext } from 'react'; +import { BuilderFieldOperator } from '@notifire/shared'; +import { clone } from '../../utils/clone'; +import { isStringArray } from '../../utils/types'; +import { BuilderContext } from '../Context'; + +export interface OperatorSelectValuesProps { + value: BuilderFieldOperator; + label?: string; +} + +export interface OperatorSelectProps { + values: OperatorSelectValuesProps[]; + selectedValue?: BuilderFieldOperator; + id: string; +} + +export const OperatorSelect: React.FC = ({ values, selectedValue, id }: OperatorSelectProps) => { + const { fields, data, setData, onChange, components, strings, readOnly } = useContext(BuilderContext); + + const { form } = components; + + const handleChange = (value: BuilderFieldOperator) => { + const clonedData = clone(data); + const parentIndex = clonedData.findIndex((item: any) => item.id === id); + const fieldIndex = fields.findIndex((item: any) => clonedData[parentIndex].field === item.field); + + if (['DATE', 'TEXT', 'NUMBER'].includes(fields[fieldIndex].type)) { + if (!['BETWEEN', 'NOT_BETWEEN'].includes(value) && isStringArray(clonedData[parentIndex].value)) { + clonedData[parentIndex].value = fields[fieldIndex].type === 'NUMBER' ? '0' : ''; + } else if (['BETWEEN', 'NOT_BETWEEN'].includes(value) && !isStringArray(clonedData[parentIndex].value)) { + clonedData[parentIndex].value = fields[fieldIndex].type === 'NUMBER' ? ['0', '0'] : ['', '']; + } + } + + clonedData[parentIndex].operator = value; + + setData(clonedData); + if (onChange) { + onChange(clonedData); + } + }; + + if (form && strings.form) { + return ( + + ); + } + + return null; +}; diff --git a/apps/web/src/components/query-builder/components/Widgets/Select.tsx b/apps/web/src/components/query-builder/components/Widgets/Select.tsx new file mode 100644 index 00000000000..c36bd7b2e59 --- /dev/null +++ b/apps/web/src/components/query-builder/components/Widgets/Select.tsx @@ -0,0 +1,41 @@ +import React, { useContext } from 'react'; +import { clone } from '../../utils/clone'; +import { BuilderContext } from '../Context'; + +export interface SelectProps { + selectedValue: string; + values: Array<{ value: string; label: string }>; + id: string; +} + +export const Select: React.FC = ({ selectedValue, values, id }: SelectProps) => { + const { data, setData, onChange, components, strings, readOnly } = useContext(BuilderContext); + + const { form } = components; + + const handleChange = (value: string) => { + const clonedData = clone(data); + const parentIndex = clonedData.findIndex((item: any) => item.id === id); + + clonedData[parentIndex].value = value; + + setData(clonedData); + if (onChange) { + onChange(clonedData); + } + }; + + if (form && strings.form && !readOnly) { + return ( + + ); + } + + return null; +}; diff --git a/apps/web/src/components/query-builder/components/Widgets/SelectMulti.tsx b/apps/web/src/components/query-builder/components/Widgets/SelectMulti.tsx new file mode 100644 index 00000000000..f1f7365efbc --- /dev/null +++ b/apps/web/src/components/query-builder/components/Widgets/SelectMulti.tsx @@ -0,0 +1,56 @@ +import React, { useContext } from 'react'; +import { clone } from '../../utils/clone'; +import { BuilderContext } from '../Context'; + +export interface SelectMultiProps { + values: Array<{ value: string; label: string }>; + selectedValue: string[]; + id: string; +} + +export const SelectMulti: React.FC = ({ values, selectedValue, id }: SelectMultiProps) => { + const { data, setData, onChange, components, strings, readOnly } = useContext(BuilderContext); + + const { form } = components; + + const handleChange = (value: string) => { + if (setData && onChange) { + const clonedData = clone(data); + const parentIndex = clonedData.findIndex((item: any) => item.id === id); + + clonedData[parentIndex].value = clonedData[parentIndex].value.filter((item: any) => item !== value); + clonedData[parentIndex].value.push(value); + + setData(clonedData); + onChange(clonedData); + } + }; + + const handleDelete = (value: string) => { + const clonedData = clone(data); + const parentIndex = clonedData.findIndex((item: any) => item.id === id); + + clonedData[parentIndex].value = clonedData[parentIndex].value.filter((item: any) => item !== value); + + setData(clonedData); + + if (onChange) { + onChange(clonedData); + } + }; + + if (form && strings.form) { + return ( + + ); + } + + return null; +}; diff --git a/apps/web/src/components/query-builder/constants/colors.ts b/apps/web/src/components/query-builder/constants/colors.ts new file mode 100644 index 00000000000..75b2120e7ca --- /dev/null +++ b/apps/web/src/components/query-builder/constants/colors.ts @@ -0,0 +1,13 @@ +export const colors = { + primary: '#20639B', + secondary: '#3CAEA3', + tertiary: '#911803', + + light: '#f4f4f4', + medium: '#d9d9d9', + darker: '#bfbfbf', + dark: '#848484', + + enabled: '#3caea3', + disabled: '#9fb2b0', +}; diff --git a/apps/web/src/components/query-builder/constants/strings.ts b/apps/web/src/components/query-builder/constants/strings.ts new file mode 100644 index 00000000000..41914691c14 --- /dev/null +++ b/apps/web/src/components/query-builder/constants/strings.ts @@ -0,0 +1,63 @@ +export interface Strings { + group?: { + not?: string; + or?: string; + and?: string; + addRule?: string; + addGroup?: string; + delete?: string; + }; + component?: { + delete?: string; + }; + form?: { + selectYourValue?: string; + }; + operators?: { + LARGER?: string; + SMALLER?: string; + LARGER_EQUAL?: string; + SMALLER_EQUAL?: string; + EQUAL?: string; + NOT_EQUAL?: string; + ALL_IN?: string; + ANY_IN?: string; + NOT_IN?: string; + BETWEEN?: string; + NOT_BETWEEN?: string; + LIKE?: string; + NOT_LIKE?: string; + }; +} + +export const strings: Strings = { + group: { + not: 'Not', + or: 'Or', + and: 'And', + addRule: 'Add Filter', + addGroup: 'Add Group', + delete: 'Delete', + }, + component: { + delete: 'Delete', + }, + form: { + selectYourValue: 'Select your value', + }, + operators: { + LARGER: 'Larger', + SMALLER: 'Smaller', + LARGER_EQUAL: 'Larger or equal', + SMALLER_EQUAL: 'Smaller or equal', + EQUAL: 'Equal', + NOT_EQUAL: 'Not equal', + ALL_IN: 'All in', + ANY_IN: 'Any in', + NOT_IN: 'Not in', + BETWEEN: 'Between', + NOT_BETWEEN: 'Not between', + LIKE: 'Like', + NOT_LIKE: 'Not like', + }, +}; diff --git a/apps/web/src/components/query-builder/utils/assignIds.ts b/apps/web/src/components/query-builder/utils/assignIds.ts new file mode 100644 index 00000000000..fc7960bc331 --- /dev/null +++ b/apps/web/src/components/query-builder/utils/assignIds.ts @@ -0,0 +1,21 @@ +import uniqid from 'uniqid'; +import { clone } from './clone'; +/* eslint react/prop-types: 0 */ +/* eslint no-param-reassign: 0 */ + +export const assignIds = (data: any): any => { + data = { children: clone(data) }; + + const run = (d: any): any => { + if (typeof d.children !== 'undefined') { + d.children = d.children.map((item: any) => { + item.id = uniqid(); + return run(item); + }); + } + + return d; + }; + + return run(data).children; +}; diff --git a/apps/web/src/components/query-builder/utils/clone.ts b/apps/web/src/components/query-builder/utils/clone.ts new file mode 100644 index 00000000000..af89b327f91 --- /dev/null +++ b/apps/web/src/components/query-builder/utils/clone.ts @@ -0,0 +1 @@ +export const clone = (data: any) => JSON.parse(JSON.stringify(data)); diff --git a/apps/web/src/components/query-builder/utils/denormalizeTree.ts b/apps/web/src/components/query-builder/utils/denormalizeTree.ts new file mode 100644 index 00000000000..0f6b1f024ff --- /dev/null +++ b/apps/web/src/components/query-builder/utils/denormalizeTree.ts @@ -0,0 +1,40 @@ +import { clone } from './clone'; +/* eslint no-param-reassign: 0 */ + +export const denormalizeTree = (data: any) => { + const clonedData: any = clone(data); + const denormalizedData: any = clonedData.filter((item: any) => !item.parent); + + const run = (d: any, originalData: any) => { + // eslint-disable-next-line array-callback-return + d.map((item: any) => { + if (typeof item.children !== 'undefined') { + const tmpItem = clone(item); + + // eslint-disable-next-line no-param-reassign + delete item.children; + delete item.id; + delete item.parent; + delete item.operators; + + item.children = []; + + // eslint-disable-next-line array-callback-return + tmpItem.children.map((id: any) => { + const clonedChildrenData = clone(originalData.filter((oItem: any) => oItem.id === id)[0]); + + delete clonedChildrenData.id; + delete clonedChildrenData.parent; + delete clonedChildrenData.operators; + + item.children.push(clonedChildrenData); + }); + + run(item.children, originalData); + } + }); + }; + + run(denormalizedData, clonedData); + return denormalizedData; +}; diff --git a/apps/web/src/components/query-builder/utils/normalizeTree.ts b/apps/web/src/components/query-builder/utils/normalizeTree.ts new file mode 100644 index 00000000000..5d498b094a3 --- /dev/null +++ b/apps/web/src/components/query-builder/utils/normalizeTree.ts @@ -0,0 +1,39 @@ +import { clone } from './clone'; +/* eslint no-param-reassign: 0 */ + +export const normalizeTree = (data: any[]) => { + const clonedData: any = { children: clone(data) }; + const normalizedData: any = []; + + const run = (d: any, parentId = 0) => { + if (typeof d.children !== 'undefined') { + const children: any = []; + + // eslint-disable-next-line array-callback-return + d.children.map((item: any) => { + if (parentId !== 0) { + item.parent = parentId; + } + + const tmpItem = clone(item); + delete tmpItem.children; + + normalizedData.push(tmpItem); + children.push(tmpItem.id); + + run(item, item.id); + }); + + if (parentId !== 0) { + for (const item of normalizedData) { + if (item.id === parentId) { + item.children = children; + } + } + } + } + }; + + run(clonedData); + return normalizedData; +}; diff --git a/apps/web/src/components/query-builder/utils/types.ts b/apps/web/src/components/query-builder/utils/types.ts new file mode 100644 index 00000000000..3e7f72e5838 --- /dev/null +++ b/apps/web/src/components/query-builder/utils/types.ts @@ -0,0 +1,33 @@ +import { BuilderFieldOperator } from '@notifire/shared'; + +export const isBoolean = (value: any): value is boolean => { + return typeof value === 'boolean'; +}; + +export const isString = (value: any): value is string => { + return typeof value === 'string'; +}; + +export const isNumber = (value: any): value is number => { + return typeof value === 'number'; +}; + +export const isUndefined = (value: any): value is undefined => { + return typeof value === 'undefined'; +}; + +export const isArray = (value: any): value is any[] => { + return Array.isArray(value); +}; + +export const isStringArray = (value: any): value is string[] => { + return isArray(value) && value.every((item: any) => isString(item)); +}; + +export const isOptionList = (value: any): value is Array<{ value: string; label: string }> => { + return isArray(value) && value.every((item: any) => isString(item.value) && isString(item.label)); +}; + +export const isOperator = (value: any): value is BuilderFieldOperator => { + return !!value; +}; diff --git a/apps/web/src/components/templates/EmailContentCard.tsx b/apps/web/src/components/templates/EmailContentCard.tsx new file mode 100644 index 00000000000..dd05b0fea5b --- /dev/null +++ b/apps/web/src/components/templates/EmailContentCard.tsx @@ -0,0 +1,186 @@ +import { Card, Collapse, Form, Input, Radio } from 'antd'; +import { Control, Controller, useFormContext } from 'react-hook-form'; +import { IApplication, IEmailBlock } from '@notifire/shared'; +import AceEditor from 'react-ace'; + +import 'ace-builds/src-noconflict/mode-handlebars'; +import 'ace-builds/src-noconflict/theme-monokai'; +import styled from 'styled-components'; +import { EmailMessageEditor } from './email-editor/EmailMessageEditor'; +import { Builder, BuilderFieldProps } from '../query-builder/components/Builder'; + +export function EmailContentCard({ + index, + showFilters, + variables = [], + application, +}: { + index: number; + showFilters: boolean; + variables: { + name: string; + }[]; + application: IApplication | undefined; +}) { + const { + control, + formState: { errors }, + getValues, + watch, + } = useFormContext(); // retrieve all hook methods + const contentType = watch(`emailMessages.${index}.template.contentType`); + + const fields: BuilderFieldProps[] = [ + { + field: 'firstName', + type: 'TEXT', + label: 'First Name', + operators: ['EQUAL', 'NOT_EQUAL'], + }, + { + field: 'lastName', + type: 'TEXT', + label: 'Last Name', + operators: ['EQUAL', 'NOT_EQUAL'], + }, + { + field: 'companyName', + type: 'TEXT', + label: 'Company Name', + operators: ['EQUAL', 'NOT_EQUAL'], + }, + { + field: 'companyId', + type: 'TEXT', + label: 'Company Id', + operators: ['EQUAL', 'NOT_EQUAL'], + }, + ]; + + for (const variable of variables) { + const found = fields.find((i) => i.field === variable.name); + + if (!found) { + fields.push({ + field: variable.name, + type: 'TEXT', + label: variable.name, + operators: ['EQUAL', 'NOT_EQUAL'], + }); + } + } + + return ( + <> + + + + { + return ( + + ); + }} + /> + + + + ( + + )} + /> + + {!contentType || contentType === 'editor' ? ( + + { + return ( + + ); + }} + /> + + ) : null} + {contentType === 'customHtml' ? ( + + { + return ( + <> + + + ); + }} + /> + + ) : null} + + + {showFilters && ( + + ( + + )} + /> + + )} + + ); +} + +const SubjectLineWrapper = styled.div``; diff --git a/apps/web/src/components/templates/EmailMessagesCards.tsx b/apps/web/src/components/templates/EmailMessagesCards.tsx new file mode 100644 index 00000000000..fa331a8570f --- /dev/null +++ b/apps/web/src/components/templates/EmailMessagesCards.tsx @@ -0,0 +1,127 @@ +import { FieldArrayWithId, useFormContext } from 'react-hook-form'; +import { useEffect, useState } from 'react'; +import { Button, Collapse, Popconfirm } from 'antd'; +import { MinusCircleOutlined } from '@ant-design/icons'; +import styled, { css } from 'styled-components'; +import { useQuery } from 'react-query'; +import { IApplication } from '@notifire/shared'; +import { MessageNameEditorHeader } from './MessageNameEditorHeader'; +import { EmailContentCard } from './EmailContentCard'; +import { IForm } from '../../pages/templates/editor/use-template-controller.hook'; +import { getCurrentApplication } from '../../api/application'; + +export function EmailMessagesCards({ + emailMessagesFields, + onRemoveTab, + variables, +}: { + emailMessagesFields: FieldArrayWithId[]; + onRemoveTab: (index: number) => void; + variables: { name: string }[]; +}) { + const { data: application } = useQuery('currentApplication', getCurrentApplication); + + const [activeTab, setActiveTab] = useState(); + + useEffect(() => { + const messageToSelect = emailMessagesFields[emailMessagesFields.length - 1]; + + if (messageToSelect) { + setActiveTab(messageToSelect.id); + } + }, [emailMessagesFields]); + + const showCollapse = emailMessagesFields.length !== 1; + const collapseProps: { expandIcon?: () => null; ghost?: boolean } = {}; + if (!showCollapse) { + collapseProps.expandIcon = () => null; + collapseProps.ghost = true; + } + + useEffect(() => { + setActiveTab(null as any); + setTimeout(() => { + const messageToSelect = emailMessagesFields[emailMessagesFields.length - 1]; + + if (messageToSelect) { + setActiveTab(messageToSelect.id); + } + }, 100); + }, [emailMessagesFields]); + + if (!emailMessagesFields?.length) { + return null; + } + + return ( + <> + + (emailMessagesFields?.length === 1 ? id && setActiveTab(id) : setActiveTab(id))}> + {emailMessagesFields.map((message, index) => { + return ( + { + e.preventDefault(); + e.stopPropagation(); + }}> + onRemoveTab(index)} + okText="Yes" + cancelText="No"> + + + + ); +} + +const ButtonOptionsMenu = styled.div` + padding: 5px; + background: white; + box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 9px 28px 8px rgba(0, 0, 0, 0.05); +`; diff --git a/apps/web/src/components/templates/email-editor/ContentRow.tsx b/apps/web/src/components/templates/email-editor/ContentRow.tsx new file mode 100644 index 00000000000..7c98d53472a --- /dev/null +++ b/apps/web/src/components/templates/email-editor/ContentRow.tsx @@ -0,0 +1,149 @@ +import styled from 'styled-components'; +import { Button, Col, Drawer, Dropdown, Form, Input, Menu, Radio, Row } from 'antd'; +import { EllipsisOutlined, SettingOutlined } from '@ant-design/icons'; +import { useRef, useState } from 'react'; +import { IEmailBlock } from '@notifire/shared'; + +export function ContentRow({ + children, + onHoverElement, + onRemove, + allowRemove, + block, + onStyleChanged, +}: { + children: JSX.Element | JSX.Element[]; + onHoverElement: (data: { top: number; height: number }) => void; + onRemove: () => void; + allowRemove: boolean; + block: IEmailBlock; + onStyleChanged: (data: { textDirection: 'ltr' | 'rtl' }) => void; +}) { + const [form] = Form.useForm(); + + const [drawerVisible, setDrawerVisible] = useState(); + const parentRef = useRef(null); + function onHover() { + if (!parentRef.current) return; + + onHoverElement({ + top: parentRef.current.offsetTop, + height: parentRef.current.offsetHeight, + }); + } + + const menu = ( + + setDrawerVisible(true)}> + Style Settings + + {allowRemove && ( + <> + + + Remove Row + + + )} + + ); + + function submitRowStyles() { + setDrawerVisible(false); + onStyleChanged({ + textDirection: form.getFieldsValue().textDirection, + }); + } + + return ( + <> +
+ +
{children}
+
+ + } + /> + +
+
+
+ + setDrawerVisible(false)} + visible={drawerVisible} + bodyStyle={{ paddingBottom: 80 }} + footer={ +
+ + +
+ }> +
+ + + + + + + +
+
+ + ); +} + +const SettingsButton = styled(Button)` + display: none; + right: -10px; + position: absolute; +`; + +const StyledButton = styled(Button)` + display: none; + right: -25px; + position: absolute; +`; + +const ContentRowWrapper = styled.div` + width: 100%; + outline: transparent; + padding-bottom: 10px; + display: flex; + + &:hover { + ${StyledButton} { + display: inline-block; + } + + ${SettingsButton} { + display: inline-block; + } + } +`; diff --git a/apps/web/src/components/templates/email-editor/ControlBar.tsx b/apps/web/src/components/templates/email-editor/ControlBar.tsx new file mode 100644 index 00000000000..e6f1611349a --- /dev/null +++ b/apps/web/src/components/templates/email-editor/ControlBar.tsx @@ -0,0 +1,72 @@ +import { Button, Dropdown, Menu } from 'antd'; +import { BuildOutlined, MenuOutlined, PlusOutlined } from '@ant-design/icons'; +import styled from 'styled-components'; + +export function ControlBar({ top, onBlockAdd }: { top: number; onBlockAdd: (type: 'button' | 'text') => void }) { + const menu = ( + + + + + + + + + ); + + return ( + + + + +
+ + )} + + setActionBarVisible(true)} onMouseLeave={() => setActionBarVisible(false)}> +
+ + {blocks.map((block, index) => { + return ( + onBlockStyleChanged(index, data)} + key={index} + block={block} + onHoverElement={onHoverElement} + onRemove={() => removeBlock(index)} + allowRemove={blocks?.length > 1}> + {[block.type].map((type, blockIndex) => { + if (type === 'text') { + return ( +
onTextChange(block, e)} + style={{ + display: 'inline-block', + width: '100%', + direction: block.styles?.textDirection || 'ltr', + }} + /> + ); + } + + if (type === 'button') { + return ( + { + // eslint-disable-next-line no-param-reassign + block.url = url; + }} + onTextChange={(text) => { + // eslint-disable-next-line no-param-reassign + block.content = text; + }} + /> + ); + } + + return <>; + })} + + ); + })} + + {controlBarVisible && } +
+ + + + ); +} + +const Body = styled.div` + outline: transparent; + z-index: 2; + background: transparent; + position: relative; + display: inline-block; + width: 100%; + * { + outline: none; + } +`; + +const Wrapper = styled.div` + width: 590px; + background: white; + border: 1px solid #e0e0e0; + border-top: 5px solid #ff6f61; + padding: 30px; + position: relative; +`; + +const SectionWrapper = styled.div` + background-color: #f9f9f9; + display: flex; + padding: 30px; + flex-direction: column; + justify-content: space-between; + width: 100%; + align-items: center; +`; + +const LogoWrapper = styled.div` + margin-bottom: 20px; + + img { + max-width: 240px; + } +`; + +const LogoUploaderWrapper = styled.div` + border: 1px dashed #cdcdcd; + padding: 15px 25px; + display: flex; + align-items: center; + justify-content: center; + + flex-direction: column; +`; diff --git a/apps/web/src/components/widget/InAppWidgetPreview.tsx b/apps/web/src/components/widget/InAppWidgetPreview.tsx new file mode 100644 index 00000000000..c5cdd5eb52d --- /dev/null +++ b/apps/web/src/components/widget/InAppWidgetPreview.tsx @@ -0,0 +1,198 @@ +import styled, { css, ThemeProvider, useTheme } from 'styled-components'; +import { lighten } from 'polished'; +import moment from 'moment'; +import { Badge } from 'antd'; +import { BellOutlined } from '@ant-design/icons'; + +export function InAppWidgetPreview({ children }: { children: JSX.Element }) { + const theme = useTheme(); + + return ( + + + + + + + + Notifications + + {/* */} + + + + {children} + + {moment(moment().subtract(5, 'minutes')).fromNow()} + + + + + Example content of notification + + {moment(moment().subtract(25, 'minutes')).fromNow()} + + + + Content of notification + + {moment(moment().subtract(25, 'minutes')).fromNow()} + + + +
+ + + + ); +} + +const HeaderWrapper = styled.div` + border-bottom: 1px solid #edf2f9; + padding: 10px 15px; + display: flex; + justify-content: space-between; + align-items: center; + background: white; +`; + +const Text = styled.div` + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 22px; + text-align: center; +`; + +const ContentWrapper = styled.div` + overflow: auto; + min-height: 200px; + display: flex; + flex-direction: column; +`; + +const LayoutWrapper = styled.div` + border-radius: 7px; + height: auto; + background: #efefef; +`; + +const Wrap = styled.div<{ layoutDirection: 'ltr' | 'rtl' }>` + border-radius: 3px; + overflow: hidden; + box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 7px 0px; + direction: ${({ layoutDirection }) => layoutDirection}; + max-width: 300px; +`; + +const MainWrapper = styled.div` + background: #efefef; + height: 100%; +`; + +const BottomBar = styled.div` + display: flex; +`; + +const TextContent = styled.div` + line-height: 16px; +`; + +const unseenStyleNotificationStyles = css` + background: ${({ theme }) => { + return lighten(0.6, theme.colors.main); + }}; + border-bottom: 1px solid #f9f9f9; + + &:last-child { + border-bottom: none; + } + + &:before { + content: ''; + position: absolute; + left: 0; + top: 2px; + width: 3px; + border-radius: 2px; + background: ${({ theme }) => theme.colors.main}; + height: calc(100% - 4px); + } +`; + +const ItemWrapper = styled.div<{ unseen?: boolean; blurred?: boolean }>` + padding: 15px; + border-bottom: 1px solid #edf2f9; + position: relative; + font-size: 12px; + justify-content: space-between; + align-items: center; + + &:hover { + cursor: pointer; + } + ${({ blurred }) => { + return blurred + ? css` + filter: blur(2px); + ` + : null; + }} + + ${({ unseen }) => { + return unseen ? unseenStyleNotificationStyles : null; + }} +`; + +const TimeMark = styled.div` + min-width: 55px; + font-size: 10px; + opacity: 0.5; + margin-top: 5px; +`; + +export function Footer() { + return ( + + + + + + + + + + ); +} + +const FooterWrapper = styled.div` + text-align: center; + font-size: 8px; + border-top: 1px solid #edf2f9; + height: 25px; + display: flex; + justify-content: center; + align-items: center; + direction: ltr; + margin-top: auto; + background: white; + svg { + margin-left: 5px; + width: 60px; + position: relative; + top: -1px; + } +`; diff --git a/apps/web/src/config/index.ts b/apps/web/src/config/index.ts new file mode 100644 index 00000000000..214117fcf89 --- /dev/null +++ b/apps/web/src/config/index.ts @@ -0,0 +1,6 @@ +import { isBrowser } from '../utils/utils'; + +export const API_ROOT = + process.env.REACT_APP_API_URL || (isBrowser() && (window as any).Cypress) + ? process.env.REACT_APP_API_URL || 'http://localhost:1336' + : process.env.REACT_APP_API_URL || 'http://localhost:3000'; diff --git a/apps/web/src/index.tsx b/apps/web/src/index.tsx new file mode 100644 index 00000000000..c3ff8348ce1 --- /dev/null +++ b/apps/web/src/index.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import * as Sentry from '@sentry/react'; +import { Integrations } from '@sentry/tracing'; +import App from './App'; +import reportWebVitals from './reportWebVitals'; + +// +ReactDOM.render( + + + , + document.getElementById('root') +); + +// If you want to start measuring performance in your app, pass a function +// to log results (for example: reportWebVitals(console.log)) +// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals +reportWebVitals(); diff --git a/apps/web/src/logo.svg b/apps/web/src/logo.svg new file mode 100644 index 00000000000..9dfc1c058ce --- /dev/null +++ b/apps/web/src/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/web/src/pages/HomePage.tsx b/apps/web/src/pages/HomePage.tsx new file mode 100644 index 00000000000..fd4a6d71f88 --- /dev/null +++ b/apps/web/src/pages/HomePage.tsx @@ -0,0 +1,5 @@ +function HomePage() { + return null; +} + +export default HomePage; diff --git a/apps/web/src/pages/activities/ActivitiesPage.tsx b/apps/web/src/pages/activities/ActivitiesPage.tsx new file mode 100644 index 00000000000..0c3f168ecc4 --- /dev/null +++ b/apps/web/src/pages/activities/ActivitiesPage.tsx @@ -0,0 +1,210 @@ +import { useQuery } from 'react-query'; +import { Badge, Col, Form, Input, Row, Select, Statistic, Table, Tag, Tooltip } from 'antd'; +import moment from 'moment'; +import { ChannelTypeEnum } from '@notifire/shared'; +import styled from 'styled-components'; +import { useState } from 'react'; +import { PageHeader } from '../../components/layout/components/PageHeader'; +import { getActivityList, getActivityStats } from '../../api/activity'; +import { useTemplates } from '../../api/hooks/use-templates'; + +const { Column } = Table; + +interface IFiltersForm { + channels: ChannelTypeEnum[]; +} + +export function ActivitiesPage() { + const { templates, loading: loadingTemplates } = useTemplates(); + const [page, setPage] = useState(0); + const [filters, setFilters] = useState({ channels: [] }); + const { data, isLoading, isFetching } = useQuery<{ data: any[]; totalCount: number; pageSize: number }>( + ['activitiesList', page, filters], + () => getActivityList(page, filters), + { keepPreviousData: true } + ); + + const { data: activityStats, isLoading: loadingActivityStats } = useQuery<{ + monthlySent: number; + weeklySent: number; + }>('activityStats', getActivityStats); + + function handleTableChange(pagination) { + setPage(pagination.current - 1); + } + + function onFiltersChange(formData: IFiltersForm) { + setFilters(formData); + } + + return ( + <> + + + + +
+ + +
+ + +
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + + ( +
+ {record.status === 'sent' ? : null} + {record.status === 'error' ? ( + + + + ) : null} + {record.status === 'warning' ? ( + + + + ) : null} +
+ )} + /> +
{record.template.name}
} + /> + ( + <> + {record.subscriber.firstName} {record.subscriber.lastName} + + )} + /> + ( + <> + {record.channel === ChannelTypeEnum.EMAIL ? record.email : ''}{' '} + {record.channel === ChannelTypeEnum.SMS ? record.phone : ''} + + )} + /> + ( + + {record.channel === ChannelTypeEnum.EMAIL ? ( + + + Email + + + ) : null} + {record.channel === ChannelTypeEnum.IN_APP ? ( + + + In-App + + + ) : null} + {record.channel === ChannelTypeEnum.SMS ? ( + + + SMS + + + ) : null} + + )} + /> + { + return moment(record.createdAt).isAfter(moment().subtract(1, 'day')) + ? moment(record.createdAt).fromNow() + : moment(record.createdAt).format('DD/MM/YYYY HH:mm'); + }} + /> +
+ +
+ + ); +} + +const ChannelsItemWrapper = styled.div` + display: flex; + align-items: center; + svg { + margin-right: 10px; + font-size: 12px; + } +`; diff --git a/apps/web/src/pages/auth/InvitationScreen.tsx b/apps/web/src/pages/auth/InvitationScreen.tsx new file mode 100644 index 00000000000..7d6f818e2ab --- /dev/null +++ b/apps/web/src/pages/auth/InvitationScreen.tsx @@ -0,0 +1,70 @@ +import { Col, Row, Spin } from 'antd'; +import { useQuery } from 'react-query'; +import { useParams } from 'react-router-dom'; +import { IGetInviteResponseDto } from '@notifire/shared'; +import { SignUpForm } from '../../components/auth/SignUpForm'; +import { AuthLayout } from '../../components/layout/LoginLayout'; +import { getInviteTokenData } from '../../api/invitation'; + +export default function InvitationScreen() { + const { token } = useParams<{ token: string }>(); + const { data, isLoading } = useQuery( + 'getInviteTokenData', + () => getInviteTokenData(token), + { + enabled: !!token, + } + ); + + return ( + +
+ + +
+ + +

Get started

+

+ You've been invited by {data?.inviter?.firstName} to join {data?.organization.name} +

+
{isLoading ? : }
+ +
+
+ + + + +
+
+
+ ); +} diff --git a/apps/web/src/pages/auth/login.tsx b/apps/web/src/pages/auth/login.tsx new file mode 100644 index 00000000000..c3ad0dd564f --- /dev/null +++ b/apps/web/src/pages/auth/login.tsx @@ -0,0 +1,63 @@ +import { Row, Col } from 'antd'; +import { Link } from 'react-router-dom'; +import { LoginForm } from '../../components/auth/LoginForm'; +import { AuthLayout } from '../../components/layout/LoginLayout'; + +export default function LoginPage() { + return ( + +
+ + +
+ + +

Sign In

+

+ Don't have an account yet? + + Sign Up + +

+
+ +
+ +
+
+ + + + +
+
+
+ ); +} diff --git a/apps/web/src/pages/auth/password-reset.tsx b/apps/web/src/pages/auth/password-reset.tsx new file mode 100644 index 00000000000..cf914558378 --- /dev/null +++ b/apps/web/src/pages/auth/password-reset.tsx @@ -0,0 +1,105 @@ +import { Row, Col, Result, Button } from 'antd'; +import { Link, useParams } from 'react-router-dom'; + +import { useEffect, useState } from 'react'; +import { AuthLayout } from '../../components/layout/LoginLayout'; +import { PasswordRequestResetForm } from '../../components/auth/PasswordResetRequestForm'; +import { PasswordResetForm } from '../../components/auth/PasswordResetForm'; + +export default function PasswordResetPage() { + const { token } = useParams<{ token: string }>(); + const [showSentSuccess, setShowSentSuccess] = useState(); + + function onSent() { + setShowSentSuccess(true); + } + + return ( + +
+ + +
+ + {!showSentSuccess && !token && ( + +

Password Reset

+

+ Know your password? + + Login + +

+
+ +
+ + )} + {!showSentSuccess && token && ( + +

Password Reset

+ +
+ +
+ + )} + + {showSentSuccess && ( + + + + , + ]} + /> + + )} +
+
+ + +
+
+ logo +
+ + + +

Welcome to notifire

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ullamcorper nisl erat, vel + convallis elit fermentum pellentesque. +

+ +
+ +
+ +
+
+
+ ); +} diff --git a/apps/web/src/pages/auth/signup.tsx b/apps/web/src/pages/auth/signup.tsx new file mode 100644 index 00000000000..fbf9aac5e38 --- /dev/null +++ b/apps/web/src/pages/auth/signup.tsx @@ -0,0 +1,60 @@ +import { Col, Row } from 'antd'; +import { SignUpForm } from '../../components/auth/SignUpForm'; +import { AuthLayout } from '../../components/layout/LoginLayout'; + +export default function SignUpPage() { + return ( + +
+ + +
+ + +

Sign Up

+

+ Already have an account? + Sign In +

+
+ +
+ +
+
+ + + + +
+
+
+ ); +} diff --git a/apps/web/src/pages/onboarding/application.tsx b/apps/web/src/pages/onboarding/application.tsx new file mode 100644 index 00000000000..38222400a5c --- /dev/null +++ b/apps/web/src/pages/onboarding/application.tsx @@ -0,0 +1,58 @@ +import { Col, Row } from 'antd'; +import { AuthLayout } from '../../components/layout/LoginLayout'; +import { ApplicationCreateForm } from '../../components/onboarding/ApplicationCreateForm'; + +function ApplicationOnBoarding() { + return ( + +
+ + +
+
+ logo +
+ + + +

Applications in Notifire

+ +
+ +
+ + +
+ + +

Tell us about your app

+
+ +
+ +
+
+ +
+
+
+ ); +} + +export default ApplicationOnBoarding; diff --git a/apps/web/src/pages/organization-settings/OrganizationSettingsPage.tsx b/apps/web/src/pages/organization-settings/OrganizationSettingsPage.tsx new file mode 100644 index 00000000000..397b6eff87a --- /dev/null +++ b/apps/web/src/pages/organization-settings/OrganizationSettingsPage.tsx @@ -0,0 +1,103 @@ +import { Avatar, Button, Card, Divider, Form, Input, message, Tabs, Tag, Typography, Upload } from 'antd'; +import { useMutation, useQuery } from 'react-query'; +import styled from 'styled-components'; +import { MemberStatusEnum } from '@notifire/shared'; +import * as capitalize from 'lodash.capitalize'; +import { PageHeader } from '../../components/layout/components/PageHeader'; +import { getOrganizationMembers, inviteMember } from '../../api/organization'; +import { updateEmailSettings } from '../../api/application'; + +export function OrganizationSettingsPage() { + const [form] = Form.useForm(); + + const { data: members, isLoading: loadingMembers, refetch } = useQuery( + 'getOrganizationMembers', + getOrganizationMembers + ); + const { isLoading: loadingSendInvite, mutateAsync: sendInvite } = useMutation< + string, + { error: string; message: string; statusCode: number }, + string + >((email) => inviteMember(email)); + + async function onSubmit({ email }) { + if (!email) return; + + await sendInvite(email); + await refetch(); + form.resetFields(['email']); + } + + return ( + <> + + + + {members?.map((i) => { + return ( + <> + + + {capitalize(i.user?.firstName[0])} {capitalize(i.user?.lastName[0])} + + {i.user + ? `${capitalize(i.user?.firstName as string)} ${capitalize(i.user?.lastName as string)}` + : i.invite.email}{' '} + +
+ {/* eslint-disable-next-line no-nested-ternary */} + {i.memberStatus === MemberStatusEnum.INVITED ? ( + Invite Pending + ) : i.roles.find((role) => role === 'admin') ? ( + Admin + ) : ( + Member + )} +
+
+
+ + + ); + })} + + +
+
+ + + + +
+
+
+
+ + ); +} + +const AddMemberRow = styled.div` + margin-top: 30px; +`; + +const ActionsSider = styled.div` + margin-left: auto; +`; + +const MemberRowWrapper = styled.div` + display: flex; + justify-content: center; + align-items: center; +`; diff --git a/apps/web/src/pages/settings/WidgetSettingsPage.tsx b/apps/web/src/pages/settings/WidgetSettingsPage.tsx new file mode 100644 index 00000000000..1518f2613d3 --- /dev/null +++ b/apps/web/src/pages/settings/WidgetSettingsPage.tsx @@ -0,0 +1,186 @@ +import { Button, Card, Form, Input, message, Tabs, Typography, Upload } from 'antd'; +import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; +import { atomDark } from 'react-syntax-highlighter/dist/cjs/styles/prism'; +import { useMutation, useQuery } from 'react-query'; +import { useEffect, useState } from 'react'; +import { useLocation, useParams } from 'react-router-dom'; +import { PageHeader } from '../../components/layout/components/PageHeader'; +import { getApiKeys, getCurrentApplication, updateEmailSettings, updateSmsSettings } from '../../api/application'; +import { BrandingForm } from './components/BrandingForm'; +import { useApplication } from '../../api/hooks/use-application'; + +const { TabPane } = Tabs; + +export function WidgetSettingsPage() { + const location = useLocation(); + const [selectedTab, setSelectedTab] = useState('0'); + const { isLoading: isLoadingEmailSettings, mutateAsync: changeEmailSettings } = useMutation< + { senderEmail: string }, + { error: string; message: string; statusCode: number }, + { senderEmail: string; senderName: string } + >(updateEmailSettings); + + const { isLoading: isLoadingSmsSettings, mutateAsync: updateSmsSettingsMutation } = useMutation< + { senderEmail: string }, + { error: string; message: string; statusCode: number }, + { authToken: string; accountSid: string; phoneNumber: string } + >(updateSmsSettings); + + const { application, loading: isLoadingApplication, refetch } = useApplication(); + + const { data: apiKeys, isLoading: isLoadingApiKeys } = useQuery<{ key: string }[]>('getApiKeys', getApiKeys); + const embedCode = ` + + `; + + useEffect(() => { + const params = new URLSearchParams(location.search); + if (params.get('screen') && params.get('screen') === 'sms') { + setSelectedTab('sms'); + } + }, [location]); + async function onEmailSettingsSubmit({ senderEmail, senderName }) { + await changeEmailSettings({ + senderEmail, + senderName, + }); + refetch(); + + message.success('Successfully updated email settings'); + } + + async function onSmsSettingsSubmit({ authToken, accountSid, phoneNumber }) { + await updateSmsSettingsMutation({ + authToken, + accountSid, + phoneNumber, + }); + refetch(); + + message.success('Successfully updated sms settings'); + } + + return ( + <> + + + setSelectedTab(tab)}> + + + + + +

+ Copy this snippet to your code before the closing body tag. Change the #notification-bell selector + with the appropriate bell css selector in your app layout. +

+ + {embedCode} + +
+
+ + +
+ + + + + + + + + +
+
+
+ + +
+ + + + + + + + + + + + +
+
+
+ + +

Use this api key to interact with the notifire api

+
+ + {apiKeys?.length ? apiKeys[0].key : ''} + +
+
+
+
+ + ); +} diff --git a/apps/web/src/pages/settings/components/BrandingForm.tsx b/apps/web/src/pages/settings/components/BrandingForm.tsx new file mode 100644 index 00000000000..e5b0e6cf3bc --- /dev/null +++ b/apps/web/src/pages/settings/components/BrandingForm.tsx @@ -0,0 +1,322 @@ +import { Button, Card, Form, Input, message, notification, Popover, Select, Upload } from 'antd'; +import { LoadingOutlined, PlusOutlined } from '@ant-design/icons'; +import { useEffect, useState } from 'react'; +import { useMutation } from 'react-query'; +import { RcFile } from 'antd/lib/upload/interface'; +import axios from 'axios'; +import { BlockPicker } from 'react-color'; +import styled from 'styled-components'; +import { IApplication } from '@notifire/shared'; +import { getSignedUrl } from '../../../api/storage'; +import { updateBrandingSettings } from '../../../api/application'; + +const mimeTypes = { + 'image/jpeg': 'jpeg', + 'image/png': 'png', +}; + +export function BrandingForm({ + isLoading, + application, +}: { + isLoading: boolean; + application: IApplication | undefined; +}) { + const [fontFamily, setFontFamily] = useState('Roboto'); + const [contentBackground, setContentBackground] = useState('#efefef'); + const [fontColor, setFontColor] = useState('#333737'); + const [color, setColor] = useState('#f47373'); + const [image, setImage] = useState(); + const [file, setFile] = useState(); + const [imageLoading, setImageLoading] = useState(false); + const { mutateAsync: getSignedUrlAction } = useMutation< + { signedUrl: string; path: string }, + { error: string; message: string; statusCode: number }, + string + >(getSignedUrl); + + const { mutateAsync: updateBrandingSettingsMutation, isLoading: isUpdateBrandingLoading } = useMutation< + { logo: string; path: string }, + { error: string; message: string; statusCode: number }, + { logo: string | undefined; color: string | undefined } + >(updateBrandingSettings); + + useEffect(() => { + if (application) { + if (application.branding?.color) { + setColor(application.branding.color); + } + + if (application.branding?.logo) { + setImage(application.branding.logo); + } + + if (application.branding?.fontColor) { + setFontColor(application.branding.fontColor); + } + + if (application.branding?.contentBackground) { + setContentBackground(application.branding.contentBackground); + } + + if (application.branding?.fontFamily) { + setFontFamily(application.branding.fontFamily); + } + } + }, [application]); + + function beforeUpload(data: RcFile) { + if (!mimeTypes[data.type]) { + return false; + } + + setFile(data); + + return false; + } + + useEffect(() => { + if (file) { + handleUpload(); + } + }, [file]); + + async function handleUpload() { + if (!file) return; + + setImageLoading(true); + const { signedUrl, path } = await getSignedUrlAction(mimeTypes[file.type]); + + const response = await axios.put(signedUrl, file, { + headers: { + 'Content-Type': file.type, + }, + transformRequest: [ + (data, headers) => { + // eslint-disable-next-line + delete headers.common.Authorization; + + return data; + }, + ], + }); + + setImage(path); + setImageLoading(false); + } + + async function saveBrandsForm() { + if (!color || !image) { + message.warning('Please provide a logo and a brand color'); + return; + } + + const brandData = { + color, + logo: image, + fontColor, + contentBackground, + fontFamily, + }; + + await updateBrandingSettingsMutation(brandData); + + message.success('Branding info updated successfully'); + } + + return ( + +
+ +

+ Your logo will be used on email templates and inbox +

+ + {image ? ( + avatar + ) : ( +
+ {imageLoading ? : } +
Upload
+
+ )} +
+
+ + +

+ You brand color will be used to style emails and inbox experience +

+ { + setColor(selectedColor.hex); + }} + /> + } + placement="topLeft"> + { + setColor(selectedColor.hex); + }} + /> + } + placement="topLeft"> + + + } + style={{ maxWidth: 150 }} + value={color} + /> + +
+ +

In-app widget customizations

+ +

+ Font color will be used for text in the in-app widget +

+ { + setFontColor(selectedColor.hex); + }} + /> + } + placement="topLeft"> + { + setFontColor(selectedColor.hex); + }} + /> + } + placement="topLeft"> + + + } + style={{ maxWidth: 150 }} + value={fontColor} + /> + +
+ + +

+ Will be used as the background color for the inner content of the in-app widget +

+ { + setContentBackground(selectedColor.hex); + }} + /> + } + placement="topLeft"> + { + setContentBackground(selectedColor.hex); + }} + /> + } + placement="topLeft"> + + + } + style={{ maxWidth: 150 }} + value={contentBackground} + /> + +
+ +

+ Will be used as the main font-family in the in-app widget +

+ +
+ + + +
+
+ ); +} + +const ColorPreview = styled.div<{ $color: string }>` + width: 15px; + height: 15px; + border-radius: 2px; + background-color: ${({ $color }) => $color}; + + &:hover { + cursor: pointer; + } +`; diff --git a/apps/web/src/pages/templates/TemplateTriggerModal.tsx b/apps/web/src/pages/templates/TemplateTriggerModal.tsx new file mode 100644 index 00000000000..e679cdf0604 --- /dev/null +++ b/apps/web/src/pages/templates/TemplateTriggerModal.tsx @@ -0,0 +1,39 @@ +import { Modal, Tabs, Typography } from 'antd'; +import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; +import { dark } from 'react-syntax-highlighter/dist/cjs/styles/prism'; + +export function TemplateTriggerModal({ + isVisible, + onDismiss, + triggerSlug, +}: { + isVisible: boolean; + onDismiss: () => void; + triggerSlug: string | undefined; +}) { + const triggerCodeSnippet = ` +import notifire from '@notifire/node'; + +notifire.trigger('${triggerSlug}', { + firstName: "", + taskName: "" +});`; + + return ( + +
+ Trigger implementation code + + + + {triggerCodeSnippet} + + + + Content of Tab Pane 2 + + +
+
+ ); +} diff --git a/apps/web/src/pages/templates/TemplatesListPage.tsx b/apps/web/src/pages/templates/TemplatesListPage.tsx new file mode 100644 index 00000000000..4cf1c9469fc --- /dev/null +++ b/apps/web/src/pages/templates/TemplatesListPage.tsx @@ -0,0 +1,85 @@ +import { Button, Col, Row, Table, Tag, Typography } from 'antd'; +import moment from 'moment'; +import { Link } from 'react-router-dom'; +import { PlusOutlined } from '@ant-design/icons'; +import styled from 'styled-components'; +import { PageHeader } from '../../components/layout/components/PageHeader'; +import { useTemplates } from '../../api/hooks/use-templates'; + +const { Column } = Table; + +function NotificationList() { + const { templates, loading: isLoading } = useTemplates(); + + return ( + <> + + + + } + /> + + + +
+ + + + ( + <> + {record.notificationGroup?.name} + + )} + /> + moment(record.createdAt).format('DD/MM/YYYY HH:mm')} + /> + ( + <> + {record.draft ? Disabled : null} + {record.active ? ( + + Active + + ) : null} + + )} + /> + ( + + + + )} + /> +
+
+ +
+ + ); +} + +const GroupWrapper = styled.div``; + +const GroupTitle = styled(Typography.Title)``; +export default NotificationList; diff --git a/apps/web/src/pages/templates/editor/TemplateEditorPage.tsx b/apps/web/src/pages/templates/editor/TemplateEditorPage.tsx new file mode 100644 index 00000000000..a511e5e2d45 --- /dev/null +++ b/apps/web/src/pages/templates/editor/TemplateEditorPage.tsx @@ -0,0 +1,509 @@ +import { + Alert, + Button, + Card, + Col, + Divider, + Form, + Input, + Popconfirm, + Row, + Select, + Switch, + Tooltip, + Typography, +} from 'antd'; +import { + AlertTwoTone, + CheckOutlined, + CloseOutlined, + MailTwoTone, + MobileTwoTone, + PlusCircleOutlined, + PlusOutlined, + SettingOutlined, +} from '@ant-design/icons'; +import { Controller, FormProvider } from 'react-hook-form'; +import { useHistory } from 'react-router'; + +import styled, { css } from 'styled-components'; +import { useParams } from 'react-router-dom'; +import { ChannelTypeEnum } from '@notifire/shared'; +import { useEffect, useState } from 'react'; +import { useMutation, useQuery } from 'react-query'; +import { TemplateTriggerModal } from '../../../components/templates/TemplateTriggerModal'; +import { TemplateInAppEditor } from '../../../components/templates/TemplateInAppEditor'; +import { useTemplateController } from './use-template-controller.hook'; +import { useStatusChangeControllerHook } from './use-status-change-controller.hook'; +import { TriggerSnippetTabs } from '../../../components/templates/TriggerSnippetTabs'; +import { EmailMessagesCards } from '../../../components/templates/EmailMessagesCards'; +import { TemplateSMSEditor } from '../../../components/templates/TemplateSMSEditor'; +import { useApplication } from '../../../api/hooks/use-application'; +import { getNotificationGroups } from '../../../api/notifications'; +import { api } from '../../../api/api.client'; + +function TemplateEditorPage() { + const { data: serverGroups, isLoading: loadingGroups, refetch: refetchGroups } = useQuery( + 'notificationGroups', + getNotificationGroups + ); + const { isLoading: loadingCreateGroup, mutateAsync: createNotificationGroup } = useMutation< + { name: string; _id: string }, + { error: string; message: string; statusCode: number }, + { + name: string; + } + >((data) => api.post(`/v1/notification-groups`, data)); + const router = useHistory(); + const [groups, setGroups] = useState<{ name: string; _id: string }[]>([]); + const [categoryText, setCategoryText] = useState(); + const { templateId } = useParams<{ templateId: string }>(); + const { application, loading: isLoadingApplication } = useApplication(); + + const { + selectedMessageType, + editMode, + template, + changeSelectedMessage, + isEmbedModalVisible, + trigger, + isLoading, + isUpdateLoading, + setValue, + onSubmit, + loadingEditTemplate, + activeChannels, + toggleChannel, + onTriggerModalDismiss, + addMessage, + handleSubmit, + control, + emailMessagesFields, + inAppFields, + errors, + smsFields, + methods, + removeEmailMessage, + } = useTemplateController(templateId); + + const { isTemplateActive, changeActiveStatus, isStatusChangeLoading } = useStatusChangeControllerHook( + templateId, + template + ); + + useEffect(() => { + if (serverGroups) { + setGroups(serverGroups); + if (!editMode && serverGroups?.length) { + setValue('notificationGroup', serverGroups[0]._id); + } + } + }, [serverGroups]); + + function navigateToSmsSettings() { + router.push('/settings/widget?screen=sms'); + } + + async function addGroupItem() { + if (categoryText) { + const response = await createNotificationGroup({ + name: categoryText, + }); + await refetchGroups(); + setCategoryText(''); + setValue('notificationGroup', response._id); + } + } + + if (isLoading) return null; + return ( +
+ +
+
+
+

{editMode ? 'Edit template' : 'Create new template'}

+ + {editMode && ( + + )} +
+
+
+
+
+ + + + + } + /> + + + } + /> + + + + + ( + setCategoryText(e.target.value)} + /> + +
+
+ )}> + {(groups || []).map((item) => ( + + {item.name} + + ))} + + )} + /> + + + + + ( +