[Apps] App misc - fixes + settings permissions for apps + uploadFile (#17167)
In this PR - handle settings permission check for applications. Until then this was unhandled and applications could not perform actions requiring settings permissions, even if they were granted them - fix ties to attachment, noteTarget etc: When an object had their fields synchronized in the app, the system fields created as a side-effect of the object creation (relations to noteTarget, attachment, taskTarget, favorites, timelineActivities - created with `isCustom: true`, not sure that is correct btw) were then deleted because they are not declared in the app, and identified as deletable because of `isCustom: true`. Updating the logic to exclude system fields from the logic that detects fields to delete. I think this outline the confusion we have around isCustom, isSystem etc. - introduce uploadFile util in generated twenty client as it cannot be handled by the client's query / mutation. I had to use this for my invoicing app
This commit is contained in:
+19
-30
@@ -369,12 +369,16 @@ export class ApplicationSyncService {
|
||||
private isRelationFieldManifest(
|
||||
field: FieldManifest | RelationFieldManifest,
|
||||
): field is RelationFieldManifest {
|
||||
return field.type === FieldMetadataType.RELATION;
|
||||
return this.isFieldTypeRelation(field.type);
|
||||
}
|
||||
|
||||
private async syncFields({
|
||||
private isFieldTypeRelation(type: FieldMetadataType): boolean {
|
||||
return type === FieldMetadataType.RELATION;
|
||||
}
|
||||
|
||||
private async syncFieldsWithoutRelations({
|
||||
objectId,
|
||||
fieldsToSync,
|
||||
fieldsToSync: allFieldsToSync,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
}: {
|
||||
@@ -383,33 +387,14 @@ export class ApplicationSyncService {
|
||||
applicationId: string;
|
||||
fieldsToSync?: (FieldManifest | RelationFieldManifest)[];
|
||||
}) {
|
||||
if (!isDefined(fieldsToSync)) {
|
||||
if (!isDefined(allFieldsToSync)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const regularFields = fieldsToSync.filter(
|
||||
const fieldsToSync = allFieldsToSync.filter(
|
||||
(field): field is FieldManifest => !this.isRelationFieldManifest(field),
|
||||
);
|
||||
|
||||
await this.syncRegularFields({
|
||||
objectId,
|
||||
fieldsToSync: regularFields,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
});
|
||||
}
|
||||
|
||||
private async syncRegularFields({
|
||||
objectId,
|
||||
fieldsToSync,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
}: {
|
||||
objectId: string;
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
fieldsToSync: FieldManifest[];
|
||||
}) {
|
||||
if (fieldsToSync.length === 0) {
|
||||
return;
|
||||
}
|
||||
@@ -425,7 +410,10 @@ export class ApplicationSyncService {
|
||||
const existingFields = Object.values(
|
||||
existingFlatFieldMetadataMaps.byId,
|
||||
).filter(
|
||||
(field) => isDefined(field) && field.objectMetadataId === objectId,
|
||||
(field) =>
|
||||
isDefined(field) &&
|
||||
field.objectMetadataId === objectId &&
|
||||
!this.isFieldTypeRelation(field.type),
|
||||
) as FlatFieldMetadata[];
|
||||
|
||||
const fieldsToSyncUniversalIds = fieldsToSync.map(
|
||||
@@ -440,7 +428,8 @@ export class ApplicationSyncService {
|
||||
(field) =>
|
||||
isDefined(field.universalIdentifier) &&
|
||||
!fieldsToSyncUniversalIds.includes(field.universalIdentifier) &&
|
||||
field.isCustom === true,
|
||||
field.isCustom === true &&
|
||||
field.isSystem === false,
|
||||
);
|
||||
|
||||
const fieldsToUpdate = existingFields.filter(
|
||||
@@ -690,7 +679,7 @@ export class ApplicationSyncService {
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
await this.syncFields({
|
||||
await this.syncFieldsWithoutRelations({
|
||||
fieldsToSync: objectToSync.fields,
|
||||
objectId: objectToUpdate.id,
|
||||
workspaceId,
|
||||
@@ -712,8 +701,8 @@ export class ApplicationSyncService {
|
||||
icon: objectToCreate.icon || undefined,
|
||||
description: objectToCreate.description || undefined,
|
||||
standardId: objectToCreate.universalIdentifier,
|
||||
universalIdentifier: objectToCreate.universalIdentifier,
|
||||
dataSourceId: dataSourceMetadata.id,
|
||||
universalIdentifier: objectToCreate.universalIdentifier,
|
||||
applicationId,
|
||||
};
|
||||
|
||||
@@ -723,7 +712,7 @@ export class ApplicationSyncService {
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
await this.syncFields({
|
||||
await this.syncFieldsWithoutRelations({
|
||||
fieldsToSync: objectToCreate.fields,
|
||||
objectId: createdObject.id,
|
||||
workspaceId,
|
||||
@@ -837,7 +826,7 @@ export class ApplicationSyncService {
|
||||
}
|
||||
|
||||
// Sync regular fields for this extension
|
||||
await this.syncFields({
|
||||
await this.syncFieldsWithoutRelations({
|
||||
objectId: targetObjectId,
|
||||
fieldsToSync: fields,
|
||||
workspaceId,
|
||||
|
||||
@@ -25,6 +25,27 @@ export class ApplicationService {
|
||||
private readonly workspaceRepository: Repository<WorkspaceEntity>,
|
||||
) {}
|
||||
|
||||
async findApplicationRoleId(
|
||||
applicationId: string,
|
||||
workspaceId: string,
|
||||
): Promise<string> {
|
||||
const application = await this.applicationRepository.findOne({
|
||||
where: { id: applicationId, workspaceId },
|
||||
});
|
||||
|
||||
if (
|
||||
!isDefined(application) ||
|
||||
!isDefined(application.defaultServerlessFunctionRoleId)
|
||||
) {
|
||||
throw new ApplicationException(
|
||||
`Could not find application ${applicationId}`,
|
||||
ApplicationExceptionCode.APPLICATION_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return application.defaultServerlessFunctionRoleId;
|
||||
}
|
||||
|
||||
async findWorkspaceTwentyStandardAndCustomApplicationOrThrow({
|
||||
workspace: workspaceInput,
|
||||
workspaceId,
|
||||
|
||||
Reference in New Issue
Block a user