Fixes, depending on the contextual current operation in order to
retrieve relation target and all morph related fields to be delete:
- DELETE Field,
- DELETE Object,
- UPDATE Field, that affects all others related fields
Fixes https://github.com/twentyhq/twenty/issues/13577.
When naming or renaming an object, we are already checking that the name
was available compared to other existing objects.
But we also need to check that the relation fields that will be created
or updated are available as well: we create relation fields on
Attachment, Note, Favorite, Task and TimelineActivites, that bear the
name of the object. Thus, it is not possible to create an object that
has the same name as one of the fields on Attachment, Note etc: name,
createdAt, ... are not valid names.
## Context
To simplify the way we inject our default datasource, I've recently
removed the token injection that was confusion since we only had once
configured on the module level. Now I'm removing TypeORM service which
allows us to instantiate a new Datasource with the same parameters as
the default one, it was redundant and confusing.
# Introduction
Migrating and improving performances of field enum integrations tests
success and failing tests cases to be using the new v2 api
## Discovered issue
When deleting an object in v1 it will leave related enums until the
object is re-created
Something not done anymore within the create in v2 but in the delete
operation
We should implem an upgrade command to remove such relicas
## Bugs
- Update/create default value multi select runner wrong sql query -> FIX
- Update default value multi select regression, we should allow option
without an id to be inserted -> FIX
- default value compare dynamic json stringify convertion or not in
compare tools for object and fields
## Context
View tables were missing some FK, we are also introducing delete cascade
on those tables when needed to leverage pg cascade deletion instead of
having to implement it.
Also renaming those classes with Entity suffix to follow repo
guidelines.
…PC validation
- Introduced full integration test suite for MCP controller, testing
`POST /mcp` with valid and invalid payloads.
- Added `@IsDefined` validation to ensure the `method` field is required
in JSON-RPC requests.
- Applied `RestApiExceptionFilter` to MCP controller for consistent
error handling.
- Enhanced validation pipe in MCP controller to whitelist and reject
non-whitelisted properties.
- Consolidated exception filters in SSOAuthController.
Parallel code path to read and write core views when
IS_CORE_VIEW_ENABLED.
Migrated view key to an enum.
---------
Co-authored-by: Charles Bochet <charles@twenty.com>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
# Introduction
- Implementing the delete one for the new object metadata service v2.
- Handling relation fields and fields in the first place to finally
remove the object
- puting back updatedAt and createdAt in flat metadatas
- duplicate criteria addition for flat object
- removing datasource id from object metadata dto
- Enable update to unique for composite field with defaultValue
different from default defaultValue on subfield not included in unique
constraint
- Enable update to unique for standard field + Disable update to
non-unique for standard index
- Fix typo
Fixes https://github.com/twentyhq/core-team-issues/issues/1360
# Morph Relation needs some work on the core API
Especially on the Morph types
<img width="682" height="394" alt="Screenshot 2025-07-31 at 12 19 40"
src="https://github.com/user-attachments/assets/8b185ae3-3fe7-4886-97b1-ec143bb1b0f4"
/>
## Focus Areas:
- GraphQL schema generation
- Query parsing and field selection
- Morph relation field support
- Input type definition preparation
Done :
- add isUnique prop availability on gql update/create fieldMetadata
resolvers
- add unique index creation logic at update & creation
- add unique index deletion logic at update
- update unique index if field name updated
- edge cases : can't have default value and unique fields / standard
default value excluded from index (where clause) / can't have composite
unique fields / can't create unique fields on MORPH
closes https://github.com/twentyhq/core-team-issues/issues/1222
Created:
- Services
- Resolvers
- Controllers
- Tests for services
- Integration tests for GraphQL and Rest
Updated the Rest API playground
Added new feature flag `IS_CORE_VIEW_ENABLED`
Updated `viewFilter` `operand` and `view` `type` to be enums rather than
strings and generated migration file.
Closes https://github.com/twentyhq/core-team-issues/issues/1259
---------
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
Fixes https://github.com/twentyhq/core-team-issues/issues/1262
In this PR we add the update permission check layer by
- for the graphql api: extracting columns to update from the
expressionMap
- for rest api: .save() is used so we need to add the permission layer
to .save directly. We also take advantage of this PR to filter out
non-readable fields from save response (other save returns the whole
entity) - this was planned in
https://github.com/twentyhq/core-team-issues/issues/1216
The current solution does not work with rest api depth 2 queries, but
this seem to already not work on main (for timeout reasons though, so
different). I offer to create a ticket to fix it altogether later.
# Introduction
- FlatFieldMetadataType validators hashmap
- Do not fail fast on validation but aggregate errors
- Implemented `enum` validation
- Plugged the new v2 dynamic call in the field metadata service v2
## What's next:
- Implem integration tests to make things run 🙃
- migrate existing settings valdiation
- Finish the create object metadata service
- Handle update input transpilation and validation
## Open question
Should we implement, not covered validation ?, adding strictness now or
never.
This will be required by the import anw
## Discovered issue with cache
Currently the cache is not accurately typed, `fieldsById` map are not
storing any relations.
Which means the current transpilation tools are hitting undefined at
runtime
In the best of the world we will refactor the cache to be storing
`FlatObjectMetadata` and `FlatFieldMetadata` so we don't even have to
transpile them for validation and so on
But it would require to refactor the loaders that returns the cache to
the front on hit as FieldMetadataEntity, so we might land on a lighter
solution to rather add a new `getExistingFlatCache` that handles the
transpilation itself
About to do that in an other PR to be discussed with Coco
- Replaced `getAuthTokensFromLoginToken` with
`getAccessTokensFromLoginToken` for clarity.
- Introduced `getWorkspaceAgnosticTokenFromEmailVerificationToken`.
- Extended mutation inputs to include `locale` and
`verifyEmailNextPath`.
- Added email verification check and sending to various handlers.
- Updated GraphQL types and hooks to reflect these changes.
Fix#13412
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
# Why
If we have a Morph Relation, like :
Opportunity <-> Company & People
Let's say it's a MANY_TO_ONE on Opportunity side
Then we have two joinColumnNames looking like
- ownerPersonId
- ownerCompanyId
Let's say someone renames the obejct Person (assume we can even though
standard obejcts cannot be renames per say at the moment in the API)
We need to update the joinColumnName and create the associated
migrations
Context :
Large PR with 600+ test files. Enable connect and disconnect logic in
createMany (upsert true) / updateOne / updateMany resolvers
- Add disconnect logic
- Gather disconnect and connect logic -> called relation nested queries
- Move logic to query builder (insert and update one) with a preparation
step in .set/.values and an execution step in .execute
- Add integration tests
Test :
- Test API call on updateMany, updateOne, createMany (upsert:true) with
connect/disconnect
This PR adapts teh deleteOneField to make sure morph relations can be
deleted, either
- from a relation type,
- or from a morph relation type (which is the most obvious case).
This PR covers
- the deletion of fieldMetadata
- and the migrationof workspace schemas, by using the already existing
definition of relation migrations
This PR implements a new test suite: "Delete Object metadata with morph
relation" and completes the other test suites for FieldMetadata and
ObjectMetadata creation/deletion.
Last, we added a nitpick from @paul I forgot on a previous PR on
process-nested-realtion-v2
Fixes https://github.com/twentyhq/core-team-issues/issues/1197
- Renamed `WorkflowActionAdapter` to `ToolExecutorWorkflowAction`
- Renamed `settingPermission` table to `permissionFlag` and `setting`
column to `flag`
- Decoupled the send email logic from workflows to tools
- Add new `Tools Permission` section in FE
---------
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
In this PR, behind a feature flag, we add a permission layer check based
on the read permission.
It is done by computing a map of an object's fields, where keys are the
column names and values the fieldMetadata id, making them comparable to
the restricted fields ids list stored in the permission cache.
For mutations (create, update, delete, destroy), we need to check the
read permission on the returned field, as they may differ from the
updated field. The write field permission will be tackled in a different
PR.
# Introduction
Following `FieldMetadataInterface` deprecation in
https://github.com/twentyhq/twenty/pull/13264
As for the previous PR will rename and remove all the file in a
secondary PR to avoid conflicts and over loading this one
## Improvements
Removed optional properties from the `objectMetadataEntity` model and
added utils to retrieve test data
## Notes
By touching to `ObjectMetadataDTO` I would have expected a twenty-front
codegenerated types mutation, but it does not seem to be granular enough
to null/undefined coercion
# Introduction
From the moment replaced the FieldMetadataInterface definition to:
```ts
import { FieldMetadataType } from 'twenty-shared/types';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
export type FieldMetadataInterface<
T extends FieldMetadataType = FieldMetadataType,
> = FieldMetadataEntity<T>;
```
After this PR merge will create a new one removing the type and
replacing it to `FieldMetadataEntity`.
Did not renamed it here to avoid conflicts on naming + type issues fixs
within the same PR
## Field metadata entity RELATION or MORPH
Relations fields cannot be null for those field metadata entity instance
anymore, but are never for the others see
`packages/twenty-server/src/engine/metadata-modules/field-metadata/types/field-metadata-entity-test.type.ts`
( introduced TypeScript tests )
## Concerns
- TS_VECTOR is the most at risk with the `generatedType` and
`asExpression` removal from interface
## What's next
- `FielMetadataInterface` removal and rename ( see introduction )
- Depcrecating `ObjectMetadataInterface`
- Refactor `FieldMetadataEntity` optional fiels to be nullable only
- TO DIG `never` occurences on settings, defaultValue etc
- Some interfaces will be replaced by the `FlatFieldMetadata` when
deprecating the current sync and comparators tools
Fixes: https://github.com/twentyhq/twenty/issues/13110
I'm deprecating note.body and task.body to remove confusion between body
and bodyV2
What will be left but should be done later to avoid breaking changes:
- re-add a body field in the graphql API only that points to the same
bodyV2 field in SQL (need to be handled in fields and filter for note
and task)
- (wait some time)
- remove bodyV2 field
- Added a generic HTTP request tool, allowing agents and workflows to
make HTTP requests to external APIs with configurable method, headers,
and body.
- Decoupled HTTP request workflow nodes from workflow-specific types and
factories, introducing a generic tool interface.
- Updated agent system prompts to include explicit guidance for the HTTP
request tool, including when and how to use it, and how to communicate
limitations.
### Demo
https://github.com/user-attachments/assets/129bc445-a277-4a19-95ab-09f890f8f051
## Context
Add an eventEmitter instance to twenty datasources so we can emit DB
events.
Add input and output formatting to twenty orm (formatData, formatResult)
Those 2 elements simplified existing logic when we interact with the
ORM, input will be formatted by the ORM so we can directly use
field-like structure instead of column-like. The output will be
formatted, for builder queries it will be in `result.generatedMaps`
where `result.raw` preserves the previous column-like structure.
Important change: We now have an authContext that we can pass when we
get a repository, this will be used for the different events emitted in
the ORM. We also removed the caching for repositories as it was not
scaling well and not necessary imho
Note: An upcoming PR should handle the onDelete: cascade behavior where
we send DESTROY events in cascade when there is an onDelete: CASCADE on
the FK.
---------
Co-authored-by: Charles Bochet <charles@twenty.com>
This PR will create the migration to be run for the morph relations
- We created a dedicated util to generate the column name and refactored
a little the code in order to have less dependencies and a clearer devX
(updated the snapshot that changed because of this)
- Moved the `createMigrationActions` to its own util as well
- Created the `MorphRelationColumnActionFactory` based on the relation
one
---------
Co-authored-by: Charles Bochet <charles@twenty.com>
# Introduction
Introduced `EachTesting` pattern for the builder unit tests.
As always any suggestions are more than welcomed !
Still need to:
- [x] implem basic tests for field
- [x] create `get-flat-index-field-metadata.mock.ts`
- [x] Implement basic tests for index and index-fields
- [ ] Implem standard edges cases tests TDD style
## Misc
- was https://github.com/twentyhq/twenty/pull/13132 closed due to mess
to rebase on main
_(AI generated)_
### Summary
This PR fixes a validation bug in the GraphQL API that prevented
relation fields from being programmatically deactivated. The validation
was incorrectly triggering a "name cannot be changed" error even when
the update payload did not include a name, making it impossible to
disable the field.
Issue #13200
### Problem
- The [updateOneField] mutation failed when trying to set `isActive:
false` on a `RELATION` field.
- The root cause was a validation check in
[FieldMetadataValidationService] that compared the incoming `name` with
the existing one. If the input `name` was `undefined`, the check
`undefined !== existingName` would incorrectly fail.
- This created a catch-22 where a field could not be deleted (because it
had to be deactivated first) and could not be deactivated (due to this
validation error).
### Solution
- The validation logic in [field-metadata-validation.service.ts] has
been updated to only check for a name change if a new name is
**explicitly provided** in the input
(`isDefined(fieldMetadataInput.name)`).
- This change correctly enforces the rule that relation field names
cannot be changed, while allowing other properties like `isActive` to be
updated without issue.
### How to Test
1. Create a custom field of type `RELATION`.
2. Using the GraphQL API, call the [updateOneField] mutation with the
field's ID and the payload `{ "isActive": false }`.
3. Verify that the mutation succeeds and the field is now inactive.
4. Call the [deleteOneField] mutation to delete the field.
5. Verify that the deletion is successful.
### Additional Changes
_to be deleted if not necessary_
- Added a new integration test
[successful-field-metadata-relation-update.integration-spec.ts] to cover
this specific use case and prevent future regressions. The existing test
for failing updates remains untouched and continues to pass.