Add support for setting a user's default workspace during sign-in if a
target workspace subdomain exists. Enhance error feedback by displaying
authentication error messages using a Snackbar in the front-end and
improving redirect logic for workspace-specific errors.
`No Value` view groups wasn't properly created when we select a group by
field metadata, this PR fix the issue.
Also a script is added to backfill the current view groups.
---------
Co-authored-by: Marie <51697796+ijreilly@users.noreply.github.com>
Introduce `defaultWorkspaceId` to improve workspace redirection logic.
Updated GraphQL schema, server logic, and frontend components
accordingly to prioritize default workspaces when available.
## Summary
This PR adds a mechanism to handle and prioritize default workspace
selection for users during authentication. It updates the logic in
multiple components and services to ensure users are redirected to their
default workspaces if no specific selection is provided.
### Main changes:
- **GraphQL Schema Updates**:
- Enhanced `UserExists` GraphQL entity with a new `defaultWorkspaceId`
field to specify the user's default workspace.
- Updated queries and mutations to handle the `defaultWorkspaceId`.
- **Client-Side Updates**:
- Enhanced `useAuth` hook to include logic for managing default
workspace redirection.
- Adjusted UI logic in `SignInUpGlobalScopeForm` to utilize the
`defaultWorkspaceId`.
- **Server-Side Adjustments**:
- Modified `AuthService` to include `defaultWorkspaceId` in
`checkUserExists`.
- Default workspace logic added to the backend flow for consistent
handling.
- **Tests/Helpers**:
- Added utility and type changes to integrate the new backend response
changes (e.g., `UserExists` GraphQL).
- **Subsequent function lifecycle** was adjusted to include recheck for
workspace token states when performing sign-in flows.
**TLDR**
Solves: https://github.com/twentyhq/private-issues/issues/199
Partially solves: https://github.com/twentyhq/private-issues/issues/221
(more details below)
Updates the BillingMeter and BillingPrice tables while listening to the
events "price.created" and "price.updated" from the stripe webhook. Also
added the foreign keys, that couldn't be added to the BillingEntities.
**In Order To test**
Billing:
- Set IS_BILLING_ENABLED to true
- Add your BILLING_STRIPE_SECRET and BILLING_STRIPE_API_KEY
- Add your BILLING_STRIPE_BASE_PLAN_PRODUCT_ID (use the one in testMode
> Base Plan)
Authenticate with your account in the stripe CLI
Run the command: stripe listen --forward-to
http://localhost:3000/billing/webhooks
Run the twenty workker
Authenticate yourself on the app choose a plan and run the app normally.
In stripe and in posgress the customer table data should be added.
**Take Into Consideration**
In a previous migration the foreign key to workpaceId was taken down
this was due to the separation of the migrations if billing is enabled.
Because we want to separate in these two categories: we will be
polluting the Common Migrations with relations to tables that don't
exists. This will be addressed in a PR in the next sprint (perhaps a
decorator?)
**Doing**
Testing migrations, when we are in main and when billing is enabled.
closes https://github.com/twentyhq/twenty/issues/8727
@Bonapara wants to keep the code for now so I ended up by setting the
`isFunctionSettingsEnabled` constants to false in the codebase
Added a unique constraint to the "subdomain" column in the workspace
entity to ensure no duplicate subdomains exist in the database. Included
a TypeORM migration script to enforce this change at the database level.
We have conflicts which prevents us from running demo seed command after
a database-reset or/and if dev seed has already been populated. This is
because we are trying to create Tim user twice (but due to the
insert()...onConflict() in the seed creation, it does not create the
second one), for seed-dev and seed-demo .
This PR fixes that by using the same user id, allowing us to use the
same Tim apple for both dev/demo seeds
Test
<img width="802" alt="Screenshot 2024-12-16 at 15 36 56"
src="https://github.com/user-attachments/assets/72244978-130f-4561-8709-43376453b247"
/>
<img width="780" alt="Screenshot 2024-12-16 at 15 37 17"
src="https://github.com/user-attachments/assets/01ce221b-34f6-4e48-ae30-d84bdf9d3cc2"
/>
## Summary
This Pull Request centralizes the redirection logic by introducing a
reusable `useRedirect` hook, which replaces direct usage of
`window.location.href` with more standardized and testable functionality
across multiple modules.
- Introduced a new `useRedirect` hook for handling redirection logic
with optional controlled delays.
- Refactored redirection implementations in various modules (`useAuth`,
workspace, and settings-related hooks, etc.) to use the newly introduced
`useRedirect` or related high-level hooks.
- Updated API and documentation to include or improve support for SSO,
particularly OIDC and SAML setup processes in server logic.
- Enhanced frontend and backend configurability with new environment
variable settings for SSO.
---------
Co-authored-by: Félix Malfait <felix@twenty.com>
Fixes https://github.com/twentyhq/twenty/issues/8810
Fixes https://github.com/twentyhq/twenty/issues/5268
Fixes https://github.com/twentyhq/twenty/issues/8971
- Fixing Task/Note creation not sending position during creation
- Adding a command to backfill position being null, using existing
backfill command.
- Removed unused backfill job.
- Updated workspace entities to set position non-nullable and set a
default value to make it non-required on the API
- Updated position factory to set a default position for all objects
having a POSITION field instead of only company/people
- Moved the try/catch in each resolver factory calling
GraphqlQueryRunnerException handler, makes more sense to call it in the
actual graphql-query-runner and removing some duplicate codes
- Adding validations for input in QueryRunnerArgs factories
- Allow sync-metadata to override and sync defaultValues for certain
field types (that can't be updated by users)
- Removing health-check from sync-metadata command during force mode to
improve performances
Solves (https://github.com/twentyhq/private-issues/issues/198)
**TLDR**
Updates the billingProduct table data using stripe webhooks event. It
saves all the updates/creates of the products, but ensuring that it has
the lastest version of the correct metadata attributes (typeof
BillingProductMetadata)
**In order to test**
Billing:
Set IS_BILLING_ENABLED to true
Add your BILLING_STRIPE_SECRET and BILLING_STRIPE_API_KEY
Add your BILLING_STRIPE_BASE_PLAN_PRODUCT_ID (use the one in testMode >
Base Plan)
Authenticate with your account in the stripe CLI
Run the command: stripe listen --forward-to
http://localhost:3000/billing/webhooks
Go to Stripe In test mode and update or create a product using a
metadata of type of BillingProductMetadata, you can also update it using
a different values for metadata.
Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
We have recently introduced the possibility to specify workspace
specific auth providers.
I'm:
- introducing system wide auth providers (provided by clientConfig)
- making sure workspace specific auth providers belong to system wide
auth providers set
isLabelSyncedWithName should be nullable for fieldMetadata, as it is for
objectMetadata.
+ Adding missing validation on label and name sync in
fieldMetadataService for creation and update
+ adding metadata tests
- composite field need to be formatted before being saved
- repository.create() does not do it. So we simply lose the composite
fields on the way
- save() does it directly and doing create() before does not change
anything
Solves (https://github.com/twentyhq/private-issues/issues/194)
**TLDR**
Updates the billingCustomer table data using stripe webhooks event, also
updates the customer's metadata in stripe, in order to contain the
workspaceId associated to this customer.
**In order to test**
Billing:
- Set IS_BILLING_ENABLED to true
- Add your BILLING_STRIPE_SECRET and BILLING_STRIPE_API_KEY
- Add your BILLING_STRIPE_BASE_PLAN_PRODUCT_ID (use the one in testMode
> Base Plan)
-
Authenticate with your account in the stripe CLI
Run the command: stripe listen --forward-to
http://localhost:3000/billing/webhooks
Run the twenty workker
Authenticate yourself on the app choose a plan and run the app normally.
In stripe and in posgress the customer table data should be added.
**Next steps**
Learn more about integrations tests and implement some for this PR.
---------
Co-authored-by: Félix Malfait <felix@twenty.com>
removeBillingFKWithCore migration is in the wrong folder and is not
executed as intended.
Moving to billing folder to fix that and to be only run in billing mode
## Context
Fix add-subdomain-to-workspace command not included in global module
also fixing the command regex logic that was not generating subdomain
properly
## Summary
This Pull Request introduces a custom validator for checking forbidden
words in workspaces and refines how exceptions are handled within the
workspace module.
- Introduced `ForbiddenWords` custom class validator for validating
forbidden words against specific fields in `UpdateWorkspaceInput`.
- Added `EnvironmentService` usage in `WorkspaceService` to check
default subdomains.
- New file `workspaceGraphqlApiExceptionHandler` to handle GraphQL API
exceptions with specific error mappings.
- Expanded `WorkspaceExceptionCode` with `SUBDOMAIN_ALREADY_TAKEN`.
- Added new unit tests for validating forbidden words and exception
handler behavior.
Fixes#8601
We had 3 implementations of getImageAbsoluteURI: in twenty-front, in
twenty-ui and in twenty-emails. I was able to remove the one in
twenty-front but I could not remove it from twenty-emails as this is a
standalone for now. The vision is to introduce shared utils in a
twenty-shared package
Having a global record crud action adds complex logic.
We decided to split those actions. I only kept a common folder / module
in backend.
⚠️ this may break existing workflows if these were using previous
actions!
Implemented a feature to check the availability of subdomains when
updating workspace settings. This includes a new mutation,
`isSubdomainAvailable`, to validate subdomain availability through
GraphQL. The frontend now verifies if a subdomain is available to
prevent duplicates during updates.
---------
Co-authored-by: Weiko <corentin@twenty.com>
Beforehand, the name of the branch is not representative of the work
that has been done in this PR
**TLDR:**
Solves https://github.com/twentyhq/private-issues/issues/192
Add 3 tables BillingCustomer, BillingProduct and BillingPrice and
BillingMeter to core, inspired by the Stripe implementation. Separates
migration, between common and billing on order to not populate the db of
the self-hosting instances with unused tables.
**In order to test:**
Run the command:
npx nx typeorm -- migration:run -d
src/database/typeorm/core/core.datasource.ts
**Considerations:**
I only put the information we should use right now in the Billing
module, for instance columns like meter or agreggation formula where
omitted in the creation of the tables.
These columns and other ones who fall on the same spectrum will be added
as we need them.
If you want to add more information to the table, I'll leave some
utility links down bellow:
- BillingPrices: https://docs.stripe.com/api/prices/object
- BillingCustomer: https://docs.stripe.com/api/customers/object
- BillingProduct: https://docs.stripe.com/api/products/object
**Next Steps**
Use the Stripe Webhook in order to update the tables accordingly
---------
Co-authored-by: Félix Malfait <felix@twenty.com>
## Context
Fix wrong unique index on user email as we don't want an index on
email/deletedAt but a partial on a where condition on deletedAt. This
should enforce email unicity excluding the ones that have a deletedAt
## Test
Run
```sql
SELECT email, COUNT(*) as duplicate_count
FROM core."user"
WHERE "deletedAt" IS NULL
GROUP BY email
HAVING COUNT(*) > 1
ORDER BY duplicate_count DESC;
```
to check duplicates before running the migration
Output schema is now separated in two sections:
- object, that gather all informations on the selectable object
- fields, that display object fields in a record context, or simply the
available fields from the previous steps
The dropdown variable has now a new mode:
- if objectNameSingularToSelect is defined, it goes into an object mode.
Only objects of the right type will be shown
- if not set, it will use the already existing mode, to select a field
When an object is selected, it actually set the id of the object
https://github.com/user-attachments/assets/1c95f8fd-10f0-4c1c-aeb7-c7d847e89536
Updated email invitation logic to include sender details in the From
field.
Please feel free to provide comments so that we can make adjustments as
early as possible if needed
Fixes#7001
---------
Co-authored-by: Your Name <your@email.address>
Co-authored-by: Félix Malfait <felix@twenty.com>
This PR is fixing the following issues with record groups:
- [x] [Backend] - Only update view groups when a field is edited if this
one already has view groups
- [x] [Backend] - Editing a Select field metadata option brake view
groups
- [x] [Frontend] - Changing the group by field from one to another brake
record group and doesn't remove the previous ones
- [x] [Frontend & Backend] - Mark `kanbanFieldMetadataId` as deprecated
in favour of `viewGroups.fieldMetadataId`
Also the following has been checked:
- [x] Properly displayed a table with only one view groups
- [x] Properly displayed a table without view groups
## Context
Fix seed demo command since we added a subdomain non-nullable column we
needed to update the command to fill that info for the demo workspace