Prepare for better version upgrade system + split admin panel into two
permissions + fix GraphQL generation detection
---------
Co-authored-by: ehconitin <nitinkoche03@gmail.com>
# Health Monitoring for Self-Hosted Instances
This PR implements basic health monitoring for self-hosted instances in
the admin panel.
## Service Status Checks
We're adding real-time health checks for:
- Redis Connection
- Database Connection
- Worker Status
- Message Sync Status
## Existing Functionality
We already have message sync and captcha counters that store aggregated
metrics in cache within a configurable time window (default: 5 minutes).
## New Endpoints
1. `/healthz` - Basic server health check for Kubernetes pod monitoring
2. `/healthz/{serviceName}` - Individual service health checks (returns
200 if healthy)
3. `/metricsz/{metricName}` - Time-windowed metrics (message sync,
captcha)
4. GraphQL resolver in admin panel for UI consumption
All endpoints use the same underlying service, with different
presentation layers for infrastructure and UI needs.
---------
Co-authored-by: Félix Malfait <felix@twenty.com>
## Context
With the new permissions system, we now need to hide some items from the
settings navigation and gate some routes so they can't be accessed
directly.
To avoid having to set permission gates in all the component pages, I'm
introducing wrapper at the route level and in the Navigation. This is
not required and is mostly for pages that are strictly mapped to a
single permission, for the rest we still need to use the different hooks
manually but it should avoid a bit of boilerplate for most of the cases.
- currentUserWorkspaceState to access settingsPermissions
- SettingsProtectedRouteWrapper in the router that can take a
settingFeature or a featureFlag as a gate logic, if the currentUser does
not have access to the settingFeature or the featureFlag is not enabled
they will be redirected to the profile page.
- SettingsNavigationItemWrapper & SettingsNavigationSectionWrapper. The
former will check the same logic as SettingsProtectedRouteWrapper and
not display the item if needed. The later will check if all
SettingsNavigationItemWrapper are not visible and hide itself if that's
the case.
- useHasSettingsPermission to get a specific permission state for the
current user
- useSettingsPermissionMap to get a map of all permissions with their
values for the current user
- useFeatureFlagsMap same but for featureFlags
In this huge (sorry!) PR:
- introducing objectMetadataItem in contextStore instead of
objectMetadataId which is more convenient
- splitting some big hooks into smaller parts to avoid re-renders
- removing Effects to avoid re-renders (especially onViewChange)
- making the view prefetch separate from favorites to avoid re-renders
- making the view prefetch load a state and add selectors on top of it
to avoir re-renders
As a result, the performance is WAY better (I suspect the favorite
implementation to trigger a lot of re-renders unfortunately).
However, we are still facing a random app freeze on view creation. I
could not investigate the root cause. As this seems to be already there
in the precedent release, we can move forward but this seems a urgent
follow up to me ==> EDIT: I've found the root cause after a few ours of
deep dive... an infinite loop in RecordTableNoRecordGroupBodyEffect...
prastoin edit: close https://github.com/twentyhq/twenty/issues/10253
---------
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
Co-authored-by: prastoin <paul@twenty.com>
Fixes https://github.com/twentyhq/twenty/issues/9772
In this PR:
- the root cause of the issue that the ContextStoreViewIdEffect was not
filtering the views on objectMetadata properly
- I'm also deleting some over complex in the latestVisited view logic
- Duplicated logic between ContextStoreViewIdEffect and
ViewBarViewIdEffect, see my comment
Adjusted URL construction to properly handle trailing slashes in base
paths, ensuring consistent matching logic. Added logic for setting the
hotkey scope when navigating to the domain settings path.
## Context
This PR adds a new SettingsRoleEdit page, the existing roles page now
redirects to the role edition page when clicking on it.
For now, we can't edit anything. Next step is to allow role assignment
in the corresponding tab.
<img width="941" alt="Screenshot 2025-02-05 at 17 16 14"
src="https://github.com/user-attachments/assets/ca46de15-6237-4de6-88e1-2384a09d4a27"
/>
- Fix SAML issue
- Fix the wrong state on the Invite page when multiple SSO provider
exists
- Allow to signup with SSO and public invite link
- For OIDC, use the property upn to guess email for Microsoft and enable
oidc with a specific context in azure
- Improve error in OIDC flow when email not found
# Introduction
Avoid having multiple `isDefined` definition across our pacakges
Also avoid importing `isDefined` from `twenty-ui` which exposes a huge
barrel for a such little util function
## In a nutshell
Removed own `isDefined.ts` definition from `twenty-ui` `twenty-front`
and `twenty-server` to move it to `twenty-shared`.
Updated imports for each packages, and added explicit dependencies to
`twenty-shared` if not already in place
Related PR https://github.com/twentyhq/twenty/pull/9941
## Context
This PR introduces a new Roles settings page, accessible through the
settings menu when the isPermissionsEnabled feature flag is enabled. The
page provides a foundation for managing user roles within the workspace.
This is not fetching the roles from the BE for now and will be done in a
followup PR.
Removes `isFunctionSettingsEnabled` feature flag
We consider this featureFlag as false for everyone. We decided to keep
the code in the code base for now
Fixes#9761
Instead of cleaning RecoilState we should keep the api key visible as
long as the user didn't refresh/leave the app, it's better from a UX
perspective and the code is also more elegant, removing a useEffect
Note: the root cause of the bug was a missing "/settings" path in
isMatchingLocation in useCleaningRecoilState (due to the recent
refactoring) ; but I think this fix is better
Refers #8128
Changes Introduced:
- Added i18n configuration.
- Added a feature flag for localization.
- Enabled language switching based on the flag.
---------
Co-authored-by: Félix Malfait <felix@twenty.com>
Before the `recordIndexId` was the name plural. This caused problems
because the component states were the same for every view of an object.
When we switched from one view to another, some states weren't reset.
This PR fixes this by:
- Creating an effect at the same level of page change effect to set the
`currentViewId` inside the object `contextStore`
- Adding the `currentViewId` to the `recordIndexId`
Follow ups:
- We need to get rid of
`packages/twenty-front/src/modules/views/states/currentViewIdComponentState.ts`
and use the context store instead
Closestwentyhq/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>
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>
Eliminated all references to `isSSOEnabled` across the frontend,
backend, and configuration files. This change simplifies the codebase by
removing unnecessary feature flag checks, associated logic, and
environment variables. The SSO feature remains available without
reliance on this flag.
The DX is not great when you need to do a lot of database
resets/command.
Should we disable Typescript validation to speed things up? With this
and caching database:reset takes 1min instead of 2 on my machine.
See also: https://github.com/typeorm/typeorm/issues/4136
And #9291 / #9293
---------
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
## Summary
- [x] Remove defaultWorkspace in user
- [x] Remove all occurrence of defaultWorkspace and defaultWorkspaceId
- [x] Improve activate workspace flow
- [x] Improve security on social login
- [x] Add `ImpersonateGuard`
- [x] Allow to use impersonation with couple `User/Workspace`
- [x] Prevent unexpected reload on activate workspace
- [x] Scope login token with workspaceId
Fix https://github.com/twentyhq/twenty/issues/9033#event-15714863042
In this PR, I'm
- removing setting up the isAppWaitingForFreshMetadata boolean state in
PageChangeEffect navigate (not robust) to some precise synchronous
places, improving the control we have on when the app considers it's
ready to be rendered based on fresh metadata
- fixing tests
## Summary
Add support for multi-workspace feature and adjust configurations and
states accordingly.
- Introduced new state isMultiWorkspaceEnabledState.
- Updated ClientConfigProviderEffect component to handle
multi-workspace.
- Modified GraphQL schema and queries to include multi-workspace related
configurations.
- Adjusted server environment variables and their respective
documentation to support multi-workspace toggle.
- Updated server-side logic to handle new multi-workspace configurations
and conditions.
Closes#8737
- Refactored actions by creating hooks to add the possibility to
register actions programatically.
- Small fixes from #8610 review
- Fixed shortcuts display inside the command menu
- Removed `actionMenuEntriesComponentState` and introduced
`actionMenuEntriesComponentSelector`
Fixes: #8487#5027
1. Summary
The purpose of these changes is to elevate the dev/user experience when
the initial config load call fails for whatever reason by displaying a
fallback component.
2. Solution
I ended up making more changes than I initially planned. I had to update
the order of the contexts a bit because `GenericErrorFallback` is
dependent on `AppThemeProvider` for styling and `AppThemeProvider` is
dependent on `ObjectMetadataItemsProvider` for
[`useObjectMetadataItem`](ae2f193d68/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts (L22))
hook (`AppThemeProvider` -> `useColorScheme` -> `useUpdateOneRecord` ->
`useObjectMetadataItem`). I had to create a wrapper component for
`AppThemeProvider` and stylize it in a way that it looks responsive on
both mobile and desktop devices. Finally, I had to introduce the
`isErrored` flag to differentiate the loading and error states.
There are some improvements we can make later -
- Display a loading state for the initial config load
- Implement a refetch logic for the initial config loading failure
3. Recording
https://github.com/user-attachments/assets/c2f43573-8006-4118-8e18-8576099d78fdhttps://github.com/user-attachments/assets/9c5853d3-539b-4880-aa38-c416c3e13594
---------
Co-authored-by: Félix Malfait <felix@twenty.com>
### Description
- This PR has as the base branch the TWNTY-5491 branch, but we also had
to include updates from the main branch, and currently, there are
conflicts in the TWNTY-5491, that cause errors on typescript in this PR,
so, we can update once the conflicts are resolved on the base branch,
but the functionality can be reviewed anyway
- We Implemented a new layout of object details settings and new, the
data is auto-saved in `Settings `tab of object detail
- There is no indication to the user that data are saved automatically
in the design, currently we are disabling the form
### Demo\
<https://www.loom.com/share/4198c0aa54b5450780a570ceee574838?sid=b4ef0a42-2d41-435f-9f5f-1b16816939f7>
### Refs
#TWNTY-5491
---------
Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: gitstart-twenty <140154534+gitstart-twenty@users.noreply.github.com>
Co-authored-by: Marie Stoppa <marie.stoppa@essec.edu>
Co-authored-by: Weiko <corentin@twenty.com>
## What it does
### Backend
- [x] Add a mutation to create OIDC and SAML configuration
- [x] Add a mutation to delete an SSO config
- [x] Add a feature flag to toggle SSO
- [x] Add a mutation to activate/deactivate an SSO config
- [x] Add a mutation to delete an SSO config
- [x] Add strategy to use OIDC or SAML
- [ ] Improve error management
### Frontend
- [x] Add section "security" in settings
- [x] Add page to list SSO configurations
- [x] Add page and forms to create OIDC or SAML configuration
- [x] Add field to "connect with SSO" in the signin/signup process
- [x] Trigger auth when a user switch to a workspace with SSO enable
- [x] Add an option on the security page to activate/deactivate the
global invitation link
- [ ] Add new Icons for SSO Identity Providers (okta, Auth0, Azure,
Microsoft)
---------
Co-authored-by: Félix Malfait <felix@twenty.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
First step of #https://github.com/twentyhq/twenty/issues/3298.
Here we update the search endpoint to allow for a filter argument, which
we currently use in the relation pickers to restrict or exclude ids from
search.
In a future PR we will try to simplify the search logic in the FE