Skip to content

Commit f627e67

Browse files
authored
fix(apps): prevent unwanted changes to app status (#36990)
1 parent fb0b24c commit f627e67

File tree

9 files changed

+353
-63
lines changed

9 files changed

+353
-63
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@rocket.chat/apps-engine': patch
3+
'@rocket.chat/meteor': patch
4+
---
5+
6+
Change app update strategies to prevent unwanted data changes in database

apps/meteor/ee/server/apps/storage/AppRealStorage.ts

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import type { AppStatus } from '@rocket.chat/apps-engine/definition/AppStatus';
2+
import type { IAppInfo } from '@rocket.chat/apps-engine/definition/metadata';
3+
import type { ISetting } from '@rocket.chat/apps-engine/definition/settings';
4+
import type { IMarketplaceInfo } from '@rocket.chat/apps-engine/server/marketplace';
15
import type { IAppStorageItem } from '@rocket.chat/apps-engine/server/storage';
26
import { AppMetadataStorage } from '@rocket.chat/apps-engine/server/storage';
37
import type { Apps } from '@rocket.chat/models';
@@ -48,20 +52,49 @@ export class AppRealStorage extends AppMetadataStorage {
4852
return items;
4953
}
5054

51-
public async update({ permissionsGranted, ...item }: IAppStorageItem): Promise<IAppStorageItem> {
55+
public async remove(id: string): Promise<{ success: boolean }> {
56+
await this.db.deleteOne({ id });
57+
return { success: true };
58+
}
59+
60+
public async updatePartialAndReturnDocument(
61+
{ _id, ...item }: IAppStorageItem,
62+
{ unsetPermissionsGranted = false } = {},
63+
): Promise<IAppStorageItem> {
64+
if (!_id) {
65+
throw new Error('Property _id is required to update an app storage item');
66+
}
67+
5268
const updateQuery: UpdateFilter<IAppStorageItem> = {
53-
$set: { ...item, ...(permissionsGranted && { permissionsGranted }) },
54-
// Note: This is really important, since we currently store the permissionsGranted as null if none are present
55-
// in the App's manifest. So, if there was a permissionGranted and it was removed, we must see the app as having
56-
// no permissionsGranted at all (which means default permissions). So we must actively unset the field.
57-
...(!permissionsGranted && { $unset: { permissionsGranted: 1 } }),
69+
$set: item,
5870
};
5971

60-
return this.db.findOneAndUpdate({ id: item.id, _id: item._id }, updateQuery, { returnDocument: 'after' });
72+
if (unsetPermissionsGranted) {
73+
delete item.permissionsGranted;
74+
updateQuery.$unset = { permissionsGranted: 1 };
75+
}
76+
77+
return this.db.findOneAndUpdate({ _id }, updateQuery, { returnDocument: 'after' });
6178
}
6279

63-
public async remove(id: string): Promise<{ success: boolean }> {
64-
await this.db.deleteOne({ id });
65-
return { success: true };
80+
public async updateStatus(_id: string, status: AppStatus): Promise<boolean> {
81+
const result = await this.db.updateOne({ _id }, { $set: { status } });
82+
return result.modifiedCount > 0;
83+
}
84+
85+
public async updateSetting(_id: string, setting: ISetting): Promise<boolean> {
86+
const result = await this.db.updateOne({ _id }, { $set: { [`settings.${setting.id}`]: setting } });
87+
88+
return result.modifiedCount > 0;
89+
}
90+
91+
public async updateAppInfo(_id: string, info: IAppInfo): Promise<boolean> {
92+
const result = await this.db.updateOne({ _id }, { $set: { info } });
93+
return result.modifiedCount > 0;
94+
}
95+
96+
public async updateMarketplaceInfo(_id: string, marketplaceInfo: IMarketplaceInfo[]): Promise<boolean> {
97+
const result = await this.db.updateOne({ _id }, { $set: { marketplaceInfo } });
98+
return result.modifiedCount > 0;
6699
}
67100
}

0 commit comments

Comments
 (0)