[PUT-456] fix: delete apps from marketplace when deleting anywhere else (#2310)
Docker Image CI / build-and-push-image (push) Has been cancelled
Maintain Release Merge PR / update-release-pr (push) Has been cancelled
release-please / release-please (push) Has been cancelled
test / test-backend (24.x) (push) Has been cancelled
test / API tests (node env, api-test) (24.x) (push) Has been cancelled
test / puterjs (node env, vitest) (24.x) (push) Has been cancelled

This commit is contained in:
Daniel Salazar
2026-01-20 23:42:24 -08:00
committed by GitHub
parent 4e6d9c9f33
commit 929fc6956e
5 changed files with 38 additions and 7 deletions
+4
View File
@@ -138,6 +138,10 @@ export interface ExtensionEventTypeMap {
[key: string]: unknown;
};
};
'app.changed': {
app_uid: string;
action: 'updated' | 'deleted';
};
}
interface Extension extends RouterMethods {
@@ -696,6 +696,11 @@ class AppInformationService extends BaseService {
}
}
const svc_event = this.services.get('event');
svc_event.emit('app.changed', {
app_uid: app.uid,
action: 'deleted',
});
}
// Helper function to generate array of all periods between start and end dates
@@ -88,7 +88,7 @@ export default class AppService extends BaseService {
// value of require('om/mappings/app.js').redundant_identifiers
static REDUNDANT_IDENTIFIERS = ['name'];
async #select ({ predicate, params, ...rest }) {
async #select ({ predicate, params, ..._rest }) {
const db = this.db;
if ( predicate === undefined ) predicate = [];
@@ -694,6 +694,12 @@ export default class AppService extends BaseService {
const merged_app = { ...old_app, ...object };
this.#refresh_cache(merged_app, old_app);
const svc_event = this.services.get('event');
svc_event.emit('app.changed', {
app_uid: old_app.uid,
action: 'updated',
});
// Return the updated app (re-fetch for client-safe output)
// TODO: optimize this
return await this.#read({ uid: old_app.uid });
@@ -16,10 +16,8 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
const { Actor } = require('../../services/auth/Actor');
const BaseService = require('../../services/BaseService');
const { DB_WRITE } = require('../../services/database/consts');
const { Context } = require('../../util/context');
class SelfhostedService extends BaseService {
static description = `
@@ -36,7 +34,7 @@ class SelfhostedService extends BaseService {
{
id: 'godmode-on',
description: 'Toggle godmode for an app',
handler: async (args, log) => {
handler: async (args, _log) => {
const svc_su = this.services.get('su');
await await svc_su.sudo(async () => {
const [app_uid] = args;
@@ -46,6 +44,11 @@ class SelfhostedService extends BaseService {
throw new Error(`App ${app_uid} not found`);
}
await db.write('UPDATE apps SET godmode = 1 WHERE uid = ?', [app_uid]);
const svc_event = this.services.get('event');
svc_event.emit('app.changed', {
app_uid,
action: 'updated',
});
});
},
},
@@ -54,7 +57,7 @@ class SelfhostedService extends BaseService {
{
id: 'godmode-off',
description: 'Toggle godmode for an app',
handler: async (args, log) => {
handler: async (args, _log) => {
const svc_su = this.services.get('su');
await await svc_su.sudo(async () => {
const [app_uid] = args;
@@ -64,6 +67,11 @@ class SelfhostedService extends BaseService {
throw new Error(`App ${app_uid} not found`);
}
await db.write('UPDATE apps SET godmode = 0 WHERE uid = ?', [app_uid]);
const svc_event = this.services.get('event');
svc_event.emit('app.changed', {
app_uid,
action: 'updated',
});
});
},
},
+10 -2
View File
@@ -56,7 +56,7 @@ class AppES extends BaseES {
});
}
},
async delete (uid, extra) {
async delete (uid, _extra) {
const svc_appInformation = this.context.get('services').get('app-information');
await svc_appInformation.delete_app(uid);
},
@@ -227,6 +227,14 @@ class AppES extends BaseES {
refresh_apps_cache({ uid: raw_app.uuid }, raw_app);
}
if ( extra.old_entity ) {
const svc_event = this.context.get('services').get('event');
svc_event.emit('app.changed', {
app_uid: await full_entity.get('uid'),
action: 'updated',
});
}
return result;
},
async retry_predicate_rewrite ({ predicate }) {
@@ -394,7 +402,7 @@ class AppES extends BaseES {
const svc_puterSite = this.context.get('services').get('puter-site');
const site = await svc_puterSite.get_subdomain(subdomain, { is_custom_domain: false });
if ( ! site || site.user_id !== user.id ) {
if ( !site || site.user_id !== user.id ) {
throw APIError.create('subdomain_not_owned', null, { subdomain });
}
},