Skip to content

Commit 163aaca

Browse files
committed
CHANGES:
- ModManager: only restrict RootFolder-mods, if restrict_commands is enabled.
1 parent a442ae6 commit 163aaca

File tree

9 files changed

+51
-39
lines changed

9 files changed

+51
-39
lines changed

core/utils/discord.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@
4747
"app_has_not_roles",
4848
"app_has_dcs_version",
4949
"cmd_has_roles",
50-
"restricted",
50+
"is_restricted",
51+
"restricted_check",
5152
"get_role_ids",
5253
"format_embed",
5354
"embed_to_text",
@@ -485,9 +486,11 @@ async def wrapper(interaction: Interaction):
485486
return cmd_has_roles
486487

487488

488-
def restricted(interaction: discord.Interaction) -> bool:
489-
return not interaction.client.node.locals.get('restrict_commands', False)
489+
def is_restricted(interaction: discord.Interaction) -> bool:
490+
return interaction.client.node.locals.get('restrict_commands', False)
490491

492+
def restricted_check(interaction: discord.Interaction) -> bool:
493+
return not is_restricted(interaction)
491494

492495
def get_role_ids(plugin: Plugin, role_names) -> list[int]:
493496
role_ids = []

plugins/admin/commands.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ async def bans(self, interaction: discord.Interaction, user: str):
372372

373373
@dcs.command(description=_('Update your DCS installations'))
374374
@app_commands.guild_only()
375-
@app_commands.check(utils.restricted)
375+
@app_commands.check(utils.restricted_check)
376376
@utils.app_has_role('DCS Admin')
377377
@app_commands.describe(warn_time=_("Time in seconds to warn users before shutdown"))
378378
@app_commands.autocomplete(branch=get_dcs_branches)
@@ -452,7 +452,7 @@ async def update(self, interaction: discord.Interaction,
452452

453453
@dcs.command(description=_('Repair your DCS installations'))
454454
@app_commands.guild_only()
455-
@app_commands.check(utils.restricted)
455+
@app_commands.check(utils.restricted_check)
456456
@utils.app_has_role('DCS Admin')
457457
@app_commands.describe(warn_time=_("Time in seconds to warn users before shutdown"))
458458
async def repair(self, interaction: discord.Interaction,
@@ -498,7 +498,7 @@ async def repair(self, interaction: discord.Interaction,
498498

499499
@dcs.command(name='install', description=_('Install modules in your DCS server'))
500500
@app_commands.guild_only()
501-
@app_commands.check(utils.restricted)
501+
@app_commands.check(utils.restricted_check)
502502
@utils.app_has_role('Admin')
503503
@app_commands.autocomplete(module=available_modules_autocomplete)
504504
async def _install(self, interaction: discord.Interaction,
@@ -521,7 +521,7 @@ async def _install(self, interaction: discord.Interaction,
521521

522522
@dcs.command(name='uninstall', description=_('Uninstall modules from your DCS server'))
523523
@app_commands.guild_only()
524-
@app_commands.check(utils.restricted)
524+
@app_commands.check(utils.restricted_check)
525525
@utils.app_has_role('Admin')
526526
@app_commands.autocomplete(module=installed_modules_autocomplete)
527527
async def _uninstall(self, interaction: discord.Interaction,
@@ -825,7 +825,7 @@ async def run_on_nodes(self, interaction: discord.Interaction, method: str, node
825825

826826
@node_group.command(description=_('Shuts a specific node down'))
827827
@app_commands.guild_only()
828-
@app_commands.check(utils.restricted)
828+
@app_commands.check(utils.restricted_check)
829829
@utils.app_has_role('Admin')
830830
async def shutdown(self, interaction: discord.Interaction,
831831
node: Optional[app_commands.Transform[Node, utils.NodeTransformer]] = None):
@@ -836,7 +836,7 @@ async def shutdown(self, interaction: discord.Interaction,
836836

837837
@node_group.command(description=_('Restarts a specific node'))
838838
@app_commands.guild_only()
839-
@app_commands.check(utils.restricted)
839+
@app_commands.check(utils.restricted_check)
840840
@utils.app_has_role('Admin')
841841
async def restart(self, interaction: discord.Interaction,
842842
node: Optional[app_commands.Transform[Node, utils.NodeTransformer]] = None):
@@ -932,7 +932,7 @@ async def _node_online(node_name: str):
932932

933933
@node_group.command(description=_('Upgrade DCSServerBot'))
934934
@app_commands.guild_only()
935-
@app_commands.check(utils.restricted)
935+
@app_commands.check(utils.restricted_check)
936936
@utils.app_has_role('Admin')
937937
async def upgrade(self, interaction: discord.Interaction,
938938
node: Optional[app_commands.Transform[Node, utils.NodeTransformer]] = None):
@@ -958,7 +958,7 @@ async def upgrade(self, interaction: discord.Interaction,
958958

959959
@node_group.command(description=_('Run a shell command on a node'))
960960
@app_commands.guild_only()
961-
@app_commands.check(utils.restricted)
961+
@app_commands.check(utils.restricted_check)
962962
@utils.app_has_role('Admin')
963963
async def shell(self, interaction: discord.Interaction,
964964
node: app_commands.Transform[Node, utils.NodeTransformer],
@@ -982,7 +982,7 @@ async def shell(self, interaction: discord.Interaction,
982982

983983
@node_group.command(description=_("Add/create an instance\n"))
984984
@app_commands.guild_only()
985-
@app_commands.check(utils.restricted)
985+
@app_commands.check(utils.restricted_check)
986986
@utils.app_has_role('Admin')
987987
@app_commands.autocomplete(name=utils.InstanceTransformer(unused=True).autocomplete)
988988
@app_commands.describe(name=_("Either select an existing instance or enter the name of a new one"))
@@ -1038,7 +1038,7 @@ async def add_instance(self, interaction: discord.Interaction,
10381038

10391039
@node_group.command(description=_("Delete an instance\n"))
10401040
@app_commands.guild_only()
1041-
@app_commands.check(utils.restricted)
1041+
@app_commands.check(utils.restricted_check)
10421042
@utils.app_has_role('Admin')
10431043
async def delete_instance(self, interaction: discord.Interaction,
10441044
node: app_commands.Transform[Node, utils.NodeTransformer],
@@ -1076,7 +1076,7 @@ async def delete_instance(self, interaction: discord.Interaction,
10761076

10771077
@node_group.command(description=_("Rename an instance\n"))
10781078
@app_commands.guild_only()
1079-
@app_commands.check(utils.restricted)
1079+
@app_commands.check(utils.restricted_check)
10801080
@utils.app_has_role('Admin')
10811081
async def rename_instance(self, interaction: discord.Interaction,
10821082
node: app_commands.Transform[Node, utils.NodeTransformer],
@@ -1119,7 +1119,7 @@ async def rename_instance(self, interaction: discord.Interaction,
11191119

11201120
@node_group.command(description=_("Shows CPU topology"))
11211121
@app_commands.guild_only()
1122-
@app_commands.check(utils.restricted)
1122+
@app_commands.check(utils.restricted_check)
11231123
@app_commands.check(lambda interaction: sys.platform == 'win32')
11241124
@utils.app_has_role('Admin')
11251125
async def cpuinfo(self, interaction: discord.Interaction,
@@ -1133,7 +1133,7 @@ async def cpuinfo(self, interaction: discord.Interaction,
11331133

11341134
@plug.command(name='install', description=_("Install Plugin"))
11351135
@app_commands.guild_only()
1136-
@app_commands.check(utils.restricted)
1136+
@app_commands.check(utils.restricted_check)
11371137
@app_commands.autocomplete(plugin=installable_plugins)
11381138
@utils.app_has_role('Admin')
11391139
async def _install(self, interaction: discord.Interaction, plugin: str):
@@ -1151,7 +1151,7 @@ async def _install(self, interaction: discord.Interaction, plugin: str):
11511151

11521152
@plug.command(name='uninstall', description=_("Uninstall Plugin"))
11531153
@app_commands.guild_only()
1154-
@app_commands.check(utils.restricted)
1154+
@app_commands.check(utils.restricted_check)
11551155
@app_commands.autocomplete(plugin=uninstallable_plugins)
11561156
@utils.app_has_role('Admin')
11571157
async def _uninstall(self, interaction: discord.Interaction, plugin: str):
@@ -1169,7 +1169,7 @@ async def _uninstall(self, interaction: discord.Interaction, plugin: str):
11691169

11701170
@plug.command(description=_('Reload Plugin'))
11711171
@app_commands.guild_only()
1172-
@app_commands.check(utils.restricted)
1172+
@app_commands.check(utils.restricted_check)
11731173
@utils.app_has_role('Admin')
11741174
@app_commands.autocomplete(plugin=plugins_autocomplete)
11751175
async def reload(self, interaction: discord.Interaction, plugin: Optional[str]):

plugins/backup/commands.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def read_locals(self) -> dict:
7272

7373
@command(description=_('Backup your data'))
7474
@app_commands.guild_only()
75-
@app_commands.check(utils.restricted)
75+
@app_commands.check(utils.restricted_check)
7676
@utils.app_has_role('Admin')
7777
@app_commands.autocomplete(what=backup_autocomplete)
7878
async def backup(self, interaction: discord.Interaction, node: app_commands.Transform[Node, utils.NodeTransformer],
@@ -96,7 +96,7 @@ async def backup(self, interaction: discord.Interaction, node: app_commands.Tran
9696

9797
@command(description=_('Recover your data from an existing backup'))
9898
@app_commands.guild_only()
99-
@app_commands.check(utils.restricted)
99+
@app_commands.check(utils.restricted_check)
100100
@utils.app_has_role('Admin')
101101
@app_commands.autocomplete(what=backup_autocomplete)
102102
@app_commands.autocomplete(date=date_autocomplete)

plugins/lotatc/commands.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ async def get_server(self, message: discord.Message) -> Optional[Server]:
6868

6969
@lotatc.command(description=_('Update LotAtc'))
7070
@app_commands.guild_only()
71-
@app_commands.check(utils.restricted)
71+
@app_commands.check(utils.restricted_check)
7272
@utils.app_has_role('DCS Admin')
7373
async def update(self, interaction: discord.Interaction,
7474
server: app_commands.Transform[Server, utils.ServerTransformer(
@@ -126,7 +126,7 @@ async def _configure(self, interaction: discord.Interaction,
126126

127127
@lotatc.command(description=_('Configure LotAtc'))
128128
@app_commands.guild_only()
129-
@app_commands.check(utils.restricted)
129+
@app_commands.check(utils.restricted_check)
130130
@utils.app_has_role('DCS Admin')
131131
async def configure(self, interaction: discord.Interaction,
132132
server: app_commands.Transform[Server, utils.ServerTransformer(status=[Status.SHUTDOWN])],

plugins/modmanager/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,9 @@ packages (aka mods) into your DCS World servers. Read there for further details.
1111
| /mods uninstall | mod | admin-channel | Admin | Uninstalls a specific mod from the selected server. |
1212
| /mods list | | admin-channel | DCS Admin | Lists the installed mods on this server. |
1313
| /mods download | folder url [version] | admin-channel | Admin | Download a package from a GitHub URL or any other URL. Version only works for GitHub. |
14+
15+
> [!NOTE]
16+
> If `restricted_commands` is set to `true` in your nodes.yaml, you can only install and uninstall mods that are
17+
> in the SavedGames folder of your MoodManager directory.
18+
> This is to allow hosters to open mod commands to DCS Admin users without them being able to break the main
19+
> DCS installation.

plugins/modmanager/commands.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,14 @@ async def get_installed_mods(service: ModManagerService, server: Server) -> list
2525
return sorted(installed)
2626

2727

28-
async def get_available_mods(service: ModManagerService, server: Server) -> list[tuple[Folder, str, str]]:
28+
async def get_available_mods(
29+
interaction: discord.Interaction, service: ModManagerService, server: Server
30+
) -> list[tuple[Folder, str, str]]:
2931
available = []
3032
config = service.get_config(server)
3133
for folder in Folder:
34+
if folder == Folder.RootFolder and utils.is_restricted(interaction):
35+
continue
3236
packages = []
3337
for x in os.listdir(os.path.expandvars(config[folder.value])):
3438
if x.startswith('.') or x.casefold() in ['desktop.ini']:
@@ -73,8 +77,9 @@ async def available_mods_autocomplete(interaction: discord.Interaction, current:
7377
return []
7478
return [
7579
app_commands.Choice(name=name, value=f"{folder.value}/{name}")
76-
for folder, name in sorted(set((folder, name) for folder, name, _ in await get_available_mods(service,
77-
server)))
80+
for folder, name in sorted(set(
81+
(folder, name) for folder, name, _ in await get_available_mods(interaction, service, server))
82+
)
7883
if not current or current.casefold() in name.casefold()
7984
][:25]
8085
except Exception as ex:
@@ -153,7 +158,7 @@ async def rename(self, conn: psycopg.AsyncConnection, old_name: str, new_name: s
153158

154159
@mods.command(description=_('manage mods'))
155160
@app_commands.guild_only()
156-
@app_commands.check(utils.restricted)
161+
@app_commands.check(utils.restricted_check)
157162
@utils.app_has_roles(['Admin'])
158163
async def manage(self, interaction: discord.Interaction,
159164
server: app_commands.Transform[Server, utils.ServerTransformer(
@@ -263,7 +268,7 @@ async def install(derived, interaction: discord.Interaction):
263268
else:
264269
derived.embed.set_footer(text=_("Mod {} updated.").format(package))
265270
derived.installed = await get_installed_mods(self.service, server)
266-
derived.available = await get_available_mods(self.service, server)
271+
derived.available = await get_available_mods(interaction, self.service, server)
267272
await derived.render()
268273
else:
269274
derived.embed.set_footer(text=_("Installing mod {}, please wait ...").format(package))
@@ -274,7 +279,7 @@ async def install(derived, interaction: discord.Interaction):
274279
else:
275280
derived.embed.set_footer(text=_("Mod {} installed.").format(package))
276281
derived.installed = await get_installed_mods(self.service, server)
277-
derived.available = await get_available_mods(self.service, server)
282+
derived.available = await get_available_mods(interaction, self.service, server)
278283
await derived.render()
279284
await interaction.edit_original_response(embed=derived.embed, view=derived)
280285
except Exception as ex:
@@ -293,7 +298,7 @@ async def uninstall(derived, interaction: discord.Interaction):
293298
else:
294299
derived.embed.set_footer(text=_("Mod {} uninstalled.").format(mod))
295300
derived.installed = await get_installed_mods(self.service, server)
296-
derived.available = await get_available_mods(self.service, server)
301+
derived.available = await get_available_mods(interaction, self.service, server)
297302
await derived.render()
298303
await interaction.edit_original_response(embed=derived.embed, view=derived)
299304

@@ -337,7 +342,7 @@ async def download(modal: UploadModal):
337342
try:
338343
await download(modal)
339344
embed.remove_footer()
340-
derived.available = get_available_mods(self.service, server)
345+
derived.available = get_available_mods(interaction, self.service, server)
341346
except aiohttp.client_exceptions.ClientResponseError as ex:
342347
self.log.error(f"{ex.code}: {modal.url.value} {ex.message}")
343348
embed.set_footer(text=f"{ex.code}: {ex.message}", icon_url=WARNING_ICON)
@@ -355,7 +360,7 @@ async def cancel(derived, _: discord.Interaction):
355360
embed.description = _("Install or uninstall mods to {}").format(server.name)
356361
view = PackageView(embed,
357362
installed=await get_installed_mods(self.service, server),
358-
available=await get_available_mods(self.service, server))
363+
available=await get_available_mods(interaction, self.service, server))
359364
await view.render()
360365
# noinspection PyUnresolvedReferences
361366
await interaction.response.send_message(embed=embed, view=view, ephemeral=utils.get_ephemeral(interaction))
@@ -366,7 +371,6 @@ async def cancel(derived, _: discord.Interaction):
366371

367372
@mods.command(name="install", description=_('Install mods'))
368373
@app_commands.guild_only()
369-
@app_commands.check(utils.restricted)
370374
@utils.app_has_roles(['Admin'])
371375
@app_commands.autocomplete(mod=available_mods_autocomplete)
372376
@app_commands.autocomplete(version=available_versions_autocomplete)
@@ -417,7 +421,6 @@ async def _install(self, interaction: discord.Interaction,
417421

418422
@mods.command(description=_('Uninstall mods'))
419423
@app_commands.guild_only()
420-
@app_commands.check(utils.restricted)
421424
@utils.app_has_roles(['Admin'])
422425
@app_commands.autocomplete(mod=installed_mods_autocomplete)
423426
async def uninstall(self, interaction: discord.Interaction,
@@ -467,7 +470,7 @@ async def _list(self, interaction: discord.Interaction,
467470

468471
@mods.command(description=_('Download a mod'))
469472
@app_commands.guild_only()
470-
@app_commands.check(utils.restricted)
473+
@app_commands.check(utils.restricted_check)
471474
@utils.app_has_roles(['Admin'])
472475
@app_commands.describe(url=_("GitHub repo link or download URL"))
473476
@app_commands.autocomplete(version=repo_version_autocomplete)

plugins/scheduler/commands.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,7 @@ async def on_submit(derived, interaction: discord.Interaction):
932932

933933
@group.command(description='Change the configuration of a DCS server')
934934
@app_commands.guild_only()
935-
@app_commands.check(utils.restricted)
935+
@app_commands.check(utils.restricted_check)
936936
@utils.app_has_role('DCS Admin')
937937
async def config(self, interaction: discord.Interaction,
938938
server: app_commands.Transform[Server, utils.ServerTransformer]):
@@ -993,7 +993,7 @@ async def _rename(self, interaction: discord.Interaction,
993993

994994
@group.command(name="migrate", description="Migrate a server from one instance to another")
995995
@app_commands.guild_only()
996-
@app_commands.check(utils.restricted)
996+
@app_commands.check(utils.restricted_check)
997997
@utils.app_has_role('Admin')
998998
async def _migrate(self, interaction: discord.Interaction,
999999
server: app_commands.Transform[Server, utils.ServerTransformer],

plugins/srs/commands.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ async def _list(self, interaction: discord.Interaction,
5959

6060
@srs.command(description=_('Update DCS-SRS'))
6161
@app_commands.guild_only()
62-
@app_commands.check(utils.restricted)
62+
@app_commands.check(utils.restricted_check)
6363
@utils.app_has_role('DCS Admin')
6464
async def update(self, interaction: discord.Interaction,
6565
server: app_commands.Transform[Server, utils.ServerTransformer(
@@ -113,7 +113,7 @@ async def _configure(self, interaction: discord.Interaction,
113113

114114
@srs.command(description=_('Configure SRS'))
115115
@app_commands.guild_only()
116-
@app_commands.check(utils.restricted)
116+
@app_commands.check(utils.restricted_check)
117117
@utils.app_has_role('DCS Admin')
118118
async def configure(self, interaction: discord.Interaction,
119119
server: app_commands.Transform[Server, utils.ServerTransformer(status=[Status.SHUTDOWN])],

plugins/tacview/commands.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ async def _configure(self, interaction: discord.Interaction, *,
9595

9696
@tacview.command(description=_('Configure Tacview'))
9797
@app_commands.guild_only()
98-
@app_commands.check(utils.restricted)
98+
@app_commands.check(utils.restricted_check)
9999
@utils.app_has_role('DCS Admin')
100100
async def configure(self, interaction: discord.Interaction,
101101
server: app_commands.Transform[Server, utils.ServerTransformer(status=[Status.SHUTDOWN])],

0 commit comments

Comments
 (0)