SSUI 5.14.x#169
Conversation
… API endpoint, a UI botton and a cli command (dev)
Feat add fedora support
|
Ah yes copilot spam the comments please |
There was a problem hiding this comment.
Pull request overview
This PR adds UI + API support for updating individual Steam Workshop mods, expands SteamCMD dependency installation to cover additional Linux distro families, and adjusts developer tooling (CLI/devcontainer) for the new workflows.
Changes:
- Add a per-mod “Update” button in the SLP UI that calls a new backend endpoint to update a single Workshop item.
- Add Linux distro-family detection (
/etc/os-release) to install SteamCMD dependencies via apt (Debian/Ubuntu) or dnf (RHEL-like). - Update CLI dev command naming/behavior and tweak devcontainer setup and version metadata.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| UIMod/onboard_bundled/assets/js/slp.js | Adds per-mod update action and loading-state behavior in the legacy SLP UI. |
| UIMod/onboard_bundled/assets/css/config.css | Styles the new per-mod update button. |
| src/web/slp-launchpad.go | Adds a new API handler to update a single Workshop mod. |
| src/web/routes.go | Registers the new /api/v2/steamcmd/updatemod route. |
| src/steamcmd/steamcmd-helper.go | Adds distro detection and splits SteamCMD dependency installation per distro family. |
| src/config/config.go | Bumps SSUI version string. |
| src/cli/devcommands.go | Replaces the test workshop download command with a parameterized dev command. |
| src/cli/commands.go | Registers the new CLI command and removes the old test command. |
| .devcontainer/Dockerfile | Adjusts Node/npm installation steps in the devcontainer image. |
| .devcontainer/devcontainer.json | Updates extensions and postCreate bootstrap command. |
| .devcontainer/devcontainer-lock.json | Adds a devcontainer lock file for feature resolution. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let updateButtonHtml = ''; | ||
| if (mod.WorkshopHandle) { | ||
| updateButtonHtml = `<button class="mod-update-button" id="update-mod-btn-${index}" onclick="updateSingleMod('${escapeHtml(mod.WorkshopHandle)}', ${index})">🔄 Update</button>`; | ||
| } | ||
|
|
||
| card.innerHTML = ` | ||
| ${imageHtml} | ||
| <div class="mod-title">${escapeHtml(mod.Name || 'Unknown Mod')}</div> | ||
| ${mod.Author ? `<div class="mod-author">By ${escapeHtml(mod.Author)}</div>` : ''} | ||
| ${mod.Version ? `<div class="mod-version">v${escapeHtml(mod.Version)}</div>` : ''} | ||
| ${descriptionHtml} | ||
| ${updateButtonHtml} | ||
| `; | ||
|
|
||
| return card; |
There was a problem hiding this comment.
This seems valid, if I understand correctly we don't control the workshop handle so this is a potential XSS vector. We should sanitize this
| if req.WorkshopHandle == "" { | ||
| w.WriteHeader(http.StatusBadRequest) | ||
| json.NewEncoder(w).Encode(map[string]interface{}{ | ||
| "success": false, | ||
| "error": "workshopHandle is required", | ||
| }) | ||
| return | ||
| } | ||
|
|
There was a problem hiding this comment.
This looks valid, we don't control the workshop handle so there's an injection risk here
| _, err := steamcmd.DownloadWorkshopItems(workshopHandles) | ||
| if err != nil { | ||
| logger.Core.Error("Error downloading workshop items: " + err.Error()) | ||
| } | ||
| return nil |
| default: | ||
| return fmt.Errorf("unsupported Linux distribution: only Ubuntu/Debian and RHEL-based distros are supported") | ||
| } |
There was a problem hiding this comment.
This is also a fair point. Will revisit this PR..later today or tomorrow, possibly
akirilov
left a comment
There was a problem hiding this comment.
I think there's a negligible risk here since the Steam API is unlikely to return malicious workshop handles, but we really SHOULD do this and the fix (validating/encoding) isn't that difficult
If I understand correctly handles are just numerical so we can easily validate this with a regex or something
| let updateButtonHtml = ''; | ||
| if (mod.WorkshopHandle) { | ||
| updateButtonHtml = `<button class="mod-update-button" id="update-mod-btn-${index}" onclick="updateSingleMod('${escapeHtml(mod.WorkshopHandle)}', ${index})">🔄 Update</button>`; | ||
| } | ||
|
|
||
| card.innerHTML = ` | ||
| ${imageHtml} | ||
| <div class="mod-title">${escapeHtml(mod.Name || 'Unknown Mod')}</div> | ||
| ${mod.Author ? `<div class="mod-author">By ${escapeHtml(mod.Author)}</div>` : ''} | ||
| ${mod.Version ? `<div class="mod-version">v${escapeHtml(mod.Version)}</div>` : ''} | ||
| ${descriptionHtml} | ||
| ${updateButtonHtml} | ||
| `; | ||
|
|
||
| return card; |
There was a problem hiding this comment.
This seems valid, if I understand correctly we don't control the workshop handle so this is a potential XSS vector. We should sanitize this
| if req.WorkshopHandle == "" { | ||
| w.WriteHeader(http.StatusBadRequest) | ||
| json.NewEncoder(w).Encode(map[string]interface{}{ | ||
| "success": false, | ||
| "error": "workshopHandle is required", | ||
| }) | ||
| return | ||
| } | ||
|
|
There was a problem hiding this comment.
This looks valid, we don't control the workshop handle so there's an injection risk here
17fcacf to
d9713a1
Compare
first step / immediate reaction for #172 [StationeersSUI] ]Remove legacy terrain system checks and enforce branch compatibility GameBranch is now forced to lowercase when loading the config. This prevents mismatches with branch naming checks and ensures consistent behavior regardless of how the value was saved.
d9713a1 to
21c4316
Compare
Update individual mods and support for more Linux versions thx to MensRea