from odoo import http from odoo.http import request class AppSelectorController(http.Controller): @http.route('/custom_subscriptions/get_available_apps', type='json', auth='user', methods=['POST']) def get_available_apps(self): """ Securely fetches uninstalled apps for the selector. auth='user' ensures only logged-in users can access. """ # Security: Use sudo() to read module data, but filter safely modules = request.env['ir.module.module'].sudo().search([ ('state', '=', 'uninstalled'), ('application', '=', True), ('name', 'not in', ['web', 'base', 'custom_subscriptions', 'mail']), ], order='name') categories = {} for mod in modules: cat = mod.category_id.name or 'Other' if cat not in categories: categories[cat] = [] categories[cat].append({ 'id': mod.id, 'name': mod.name, 'shortdesc': mod.shortdesc or '', 'icon': mod.icon_image and f'/web/image/ir.module.module/{mod.id}/icon_image' or '/web/static/img/placeholder.png', }) return categories