789ff30dc7570da36ae9693afcdd203591c45b03
8
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f722a2d619 |
Add Email Verification for non-Microsoft/Google Emails (#9288)
Closes twentyhq/twenty#8240 This PR introduces email verification for non-Microsoft/Google Emails: ## Email Verification SignInUp Flow: https://github.com/user-attachments/assets/740e9714-5413-4fd8-b02e-ace728ea47ef The email verification link is sent as part of the `SignInUpStep.EmailVerification`. The email verification token validation is handled on a separate page (`AppPath.VerifyEmail`). A verification email resend can be triggered from both pages. ## Email Verification Flow Screenshots (In Order):    ## Sent Email Details (Subject & Template):   ### Successful Email Verification Redirect:  ### Unsuccessful Email Verification (invalid token, invalid email, token expired, user does not exist, etc.):  ### Force Sign In When Email Not Verified:  # TODOs: ## Sign Up Process - [x] Introduce server-level environment variable IS_EMAIL_VERIFICATION_REQUIRED (defaults to false) - [x] Ensure users joining an existing workspace through an invite are not required to validate their email - [x] Generate an email verification token - [x] Store the token in appToken - [x] Send email containing the verification link - [x] Create new email template for email verification - [x] Create a frontend page to handle verification requests ## Sign In Process - [x] After verifying user credentials, check if user's email is verified and prompt to to verify - [x] Show an option to resend the verification email ## Database - [x] Rename the `emailVerified` colum on `user` to to `isEmailVerified` for consistency ## During Deployment - [x] Run a script/sql query to set `isEmailVerified` to `true` for all users with a Google/Microsoft email and all users that show an indication of a valid subscription (e.g. linked credit card) - I have created a draft migration file below that shows one possible approach to implementing this change: ```typescript import { MigrationInterface, QueryRunner } from 'typeorm'; export class UpdateEmailVerifiedForActiveUsers1733318043628 implements MigrationInterface { name = 'UpdateEmailVerifiedForActiveUsers1733318043628'; public async up(queryRunner: QueryRunner): Promise<void> { await queryRunner.query(` CREATE TABLE core."user_email_verified_backup" AS SELECT id, email, "isEmailVerified" FROM core."user" WHERE "deletedAt" IS NULL; `); await queryRunner.query(` -- Update isEmailVerified for users who have been part of workspaces with active subscriptions UPDATE core."user" u SET "isEmailVerified" = true WHERE EXISTS ( -- Check if user has been part of a workspace through userWorkspace table SELECT 1 FROM core."userWorkspace" uw JOIN core."workspace" w ON uw."workspaceId" = w.id WHERE uw."userId" = u.id -- Check for valid subscription indicators AND ( w."activationStatus" = 'ACTIVE' -- Add any other subscription-related conditions here ) ) AND u."deletedAt" IS NULL; `); } public async down(queryRunner: QueryRunner): Promise<void> { await queryRunner.query(` UPDATE core."user" u SET "isEmailVerified" = b."isEmailVerified" FROM core."user_email_verified_backup" b WHERE u.id = b.id; `); await queryRunner.query(`DROP TABLE core."user_email_verified_backup";`); } } ``` --------- Co-authored-by: Antoine Moreaux <moreaux.antoine@gmail.com> Co-authored-by: Félix Malfait <felix@twenty.com> |
||
|
|
ba77091b06 |
fix: reset table selection when navigating away from index page (#9140)
Fixes #9132 ## Purpose Currently, when navigating away from an index page and returning, previously checked selections remain checked. This fix ensures the selection context is properly reset on navigation. ## Changes - Add `RecordIndexResetSelectionEffect` component to handle selection cleanup - Integrate effect into `RecordIndexPage` - Uses existing `useResetTableRowSelection` hook to clear selections ## Testing 1. Go to any index page (e.g., Companies) 2. Select some records using checkboxes 3. Navigate to a detail page 4. Return to the index page 5. Verify that no records are selected ## Demo I've recorded a short video demonstrating how this PR fixes the issue: [Loom Video Link](https://www.loom.com/share/72ca46a5dc194b5092e1944a985fa0d2?sid=55c95d8b-2376-4ac5-b406-6483aa7e341f) Before fix: Selections persist after navigation After fix: Selections are properly reset --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com> Co-authored-by: Charles Bochet <charles@twenty.com> |
||
|
|
2b82347fdc |
Refactor File Download Logic and Streamline Test Suite (#9281)
Closes #9277 ## Summary of Changes - Updated the file-download functionality to use the `saveAs` method from the `file-saver` library, ensuring a more reliable and consistent implementation. - Removed redundant tests to streamline the test suite and reduce maintenance overhead. ## Testing Performed - [x] Verified that exporting the view to a CSV file works as expected. |
||
|
|
0fa59d7718 |
Refactor SnackBar API (#9276)
Resolves #9259 ## Changes - Simplified API by removing `title` prop in favor of required `message` prop - Added `detailedMessage` prop for supporting additional context - Updated styling for improved message display - Renamed `defaultTitleByVariant` to `defaultAriaLabelByVariant` for clarity - Adjusted header alignment and icon styling ## Testing - [x] Verified all SnackBar variants display correctly - [x] Tested with and without detailed messages - [x] Checked responsive behavior ## Screenshots   --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com> |
||
|
|
ba2f55a627 |
Export Notes to PDF/Word Feature Implementation (#8439) (#9269)
Closes #8439 ## Overview This PR implements functionality to export notes/tasks to PDF and Word formats. https://github.com/user-attachments/assets/67eaf4eb-cabc-45ba-8727-13f22ba31067 ## Testing - [x] Verified that the export functionality works for both notes and tasks, whether exporting immediately after opening the editor or after editing. - [x] Ensured the export button appears in the action menu only when the object is a note/task. - [x] Ensured the export button appears in the RightDrawerActionMenuDropdown for a note/task. ## Notes - The code already supports exporting to Word, but only PDF export is currently available. To enable Word export, we just need a UI option allowing users to choose between PDF and Word. - After upgrading the Blocknote packages to the latest version, dependency conflicts arose with tiptap and prosemirror-model. To address this, all tiptap dependencies were consolidated in the root package.json, and a resolution was added for prosemirror-model. Also, some methods in CustomAddBlockItem.tsx were missing in the newer version, so I updated the code to accommodate these changes. - Exporting a note with an image works only if the image is embedded, as Blocknote doesn’t support actual image uploads. Uploaded images are omitted in the PDF export, while the text is retained. --------- Co-authored-by: Félix Malfait <felix.malfait@gmail.com> Co-authored-by: Félix Malfait <felix@twenty.com> |
||
|
|
df12ba6e98 |
Webhook Secret Field Implementation and Security Enhancements (#9187) (#9219)
Closes #9187 This pull request introduces a new feature and several enhancements for managing webhook security by adding a secret field and enabling HMAC signature-based authentication. Below is a detailed breakdown of the changes made: ## Frontend Updates ### Secret Field on Webhook Edit Page - Added a new **Secret** section on the webhook edit page. - Includes a text input field for entering a webhook secret. - Added a descriptive note explaining the purpose of the secret for webhook authentication. ### State Management and Persistence - Integrated the secret field into the Webhook type definition and state management. - Connected the secret field UI to the data layer, ensuring seamless persistence of the secret field. ### Validation Improvement - Trims leading and trailing whitespace from webhook secret inputs to avoid potential validation issues. ## Backend Updates ### Database and Entity Changes - Introduced a nullable `secret` field to the `WebhookWorkspaceEntity` for securely storing webhook signing secrets. - Field uses a standard field ID: `20202020-97ce-410f-bff9-e9ccb038fb67`. ### Signature Generation - Implemented HMAC-SHA256 signature generation for webhook payloads when a secret is present: - Signatures are added as a custom `X-Twenty-Webhook-Signature` header. - Secret is excluded from the payload to maintain security. ### Enhanced Security Measures - Added additional headers for enhanced security: - **Timestamp Header**: Prevents replay attacks. - **Nonce Header**: Mitigates duplicate requests. - Updated the OpenAPI specification to include documentation on these security-related headers and signature verification. ## Documentation Updates - Updated OpenAPI documentation for webhook endpoints: - Described security-related headers (signature, timestamp, nonce). - Included detailed instructions for verifying HMAC signatures to assist consumers. ## Testing and Demonstration - [Loom Video Link](https://www.loom.com/share/bd827e4d045f46d99f3c8186e5e5676a?sid=a5e61904-0536-4e82-8055-3d05e4598393): Demonstrating the functionality of the secret field and webhook security features. - [Script Example Link](https://runkit.com/samyakpiya/676af044040c0400086d400a): A script showing how consumers can verify webhook authenticity using the HMAC signature. - [Testing Site Instance](https://webhook.site/#!/view/3472468b-ebcd-4b7f-a083-c4ba20825bb4/6885fdce-8843-4d3f-8fe0-1d8abdd53f68/1): Contains the logged requests sent during testing and is available for review. ## Steps for Review 1. Verify the secret field functionality on the webhook edit page, including state persistence and UI updates. 2. Review the security enhancements, including header additions and HMAC signature generation. 3. Validate OpenAPI documentation changes for completeness and clarity. --------- Co-authored-by: Félix Malfait <felix@twenty.com> |
||
|
|
d7cda0f1c1 |
fix(spreadsheet-import): add background and border styles to DropdownMenu inMatchColumnSelect (#9255)
Fixes #9245 - CSV import column selection dropdown was missing background styles, making it difficult to read the options. ## Changes - Add styled component for DropdownMenu with background color - Include border and box shadow styles ## Screenshots   ## Testing - [x] Verify column selection dropdown has proper background color - [x] Confirm dropdown options are clearly visible - [x] Check that dropdown appears above other elements correctly |
||
|
|
2651379ccc |
Add automatic company logo fetching during workspace creation (#9158)
Closes #9151 ## Description This PR automatically sets a workspace's logo based on the user's work email domain during signup. When a user creates a new workspace using their work email (e.g., @airbnb.com), the system will fetch and set their company logo from twenty-icons.com as the default workspace logo. ## Implementation Details - Added a new `CompanyEnrichmentService` to handle company-related data enrichment - Created a modular architecture that supports future enrichment features (e.g., company name, details) - Integrated with existing work email detection - Maintains user ability to override the logo later ## Testing https://github.com/user-attachments/assets/f7855c99-462a-4053-9e52-29649e954275 I tested the following scenarios: - Signing up with a work email (e.g., @company.com) → Logo is automatically set - Signing up with a personal email (e.g., @gmail.com) → No logo is set - User can still upload a custom logo after automatic setting ## Technical Notes - Uses existing `isWorkEmail` utility - Structured for future extensibility (additional company data enrichment) - No breaking changes to existing functionality --------- Co-authored-by: Félix Malfait <felix@twenty.com> |