HDNEXT-1967: port remaining v30 features to ionos-dev-v33 - #300
Merged
Conversation
lib/private/User/Session.php and ocs/v1.php both reference OC\Authentication\Exceptions\UserAgentForbidden, but the class file was never carried over when ionos-dev-v33 was rebuilt off vanilla v33.0.6. It exists in neither this branch nor upstream, so every basic-auth request fatals with "Class not found" as soon as core.login_flow_v2.allowed_user_agents is configured. Restore the file verbatim from ionos-dev-v30. Ported from ionos-dev-v30: 9391822 IONOS(feat): block unknown user agents 30df636 IONOS(fix): block unknown user agents
The backend half of this feature is already on ionos-dev-v33: LoadAdditionalListener provides the "accept_default" initial state from the sharing.enable_share_accept system config. Nothing consumed it, so the "Pending shares" navigation entry showed unconditionally. Restore the frontend gate. Upstream moved the file from apps/files_sharing/src/views/shares.ts to src/files_views/shares.ts, so the patch is applied there; the registration is last in the function, so an early return is enough. Default stays false so the entry fails closed. Ported from ionos-dev-v30: 9afff18 IONOS(files-sharing): show pending menu only if feature enabled
Upstream 64e852c ("only skip template initialization when both skeletondirectory and templatedirectory are empty") replaced the computed "templates_enabled" initial state with a hardcoded true, which removes the only way to hide the "Create templates folder" entry from the New menu. nc-config sets both skeletondirectory and templatedirectory to an empty string (configs/initial-files.config.php), so the entry was back. Restore the computed expression. Unlike ionos-dev-v30, which defaulted both lookups to an empty string, this uses the same SERVERROOT defaults as TemplateManager::initializeTemplateDirectory() (lib/private/Files/ Template/TemplateManager.php:320-323) so an instance that does not configure either value keeps upstream behaviour instead of silently losing the entry. For IONOS builds both are set explicitly, so the outcome is identical to v30. The frontend side (newMenu/newTemplatesFolder.ts) is already upstream and needs no change; the TemplateManager half of 64e852c is left alone. References: c7bcfbf fix: Hide "Create templates folder" option if templates are disabled in configuration (upstream; on ionos-dev-v30 as 7bb09be) 64e852c fix: only skip template initialization when both skeletondirectory and templatedirectory are empty (upstream regression this restores)
Let an admin set the instance-wide default for the files user configs via `occ config:app:set files <key>`: getConfigs() now reads the user value with a null default and, when the user has no explicit preference, falls back to the app config before the shipped default. setConfig() coerces booleans with filter_var() and validates strictly so "true"/"false" strings from the API are stored as real booleans. Deviation from ionos-dev-v30: v30 always used getAppValueBool(), which was safe because every entry in ALLOWED_CONFIGS was a boolean back then. NC33 added default_view (string, "files"/"personal"), and coercing that through getAppValueBool() would return true instead of "files" for every user without a stored preference. The fallback is therefore type-aware: getAppValueBool() for boolean defaults, getAppValueString() otherwise. Verified in the dev container: types preserved (default_view stays a string), an admin-set app value becomes the default for users without a preference, a users own preference still wins, and invalid values are still rejected. Ported from ionos-dev-v30: 85edc56 feat(files/user-config): make configs admin-configurable 8869c73 fix(files): strict check of default values
Upstream rewrote the admin mail settings as a Vue view, and apps/settings/templates/settings/admin/additional-mail.php is now just a mount point, so v30 IONOS patch has no place to apply anymore. The Vue view does carry the equivalent branch, but it can never trigger: <NcNoteCard v-if="smtpMode?.id === 'null'"> smtpMode resolves mail_smtpmode against settingsAdminMail.smtpModeOptions, and Admin\Mail::getForm() only ever offers smtp/sendmail/qmail there. With mail_smtpmode = "null" the lookup yields undefined, the notice is skipped and the v-else form renders instead - with an empty "Send mode" select. Verified in the dev container: smtpModeOptions ids were "smtp" while mail_smtpmode was "null". Compare against the raw config value instead, which is what the v30 template did ($_["mail_smtpmode"] === "null"). This matters for IONOS because nc-config ships mail.config.php with mail_smtpmode = "null", so this page is broken on every IONOS instance. Ported from ionos-dev-v30: 83c6dc5 feat(Mailer): hide admin settings for "null" transport
Picks up the fix for the local-setup breakage described in HDNEXT-1967: notify_push without a reachable Redis throws while its console commands are constructed and prints that error on stdout with exit code 0, which corrupts every occ call whose output configure.sh captures (most notably `occ app:list --enabled --output json` piped into jq). 90800e6..01b3f0f: 01b3f0f Merge pull request #145 from IONOS-Productivity/mk/fix/disable-notify-push-without-redis-password bafc421 fix(configure.sh): configure notify_push before the other apps e862a43 fix(configure.sh): disable notify_push unless Redis password is set 39a31bc refactor(configure.sh): use log_info for plain status output f1daad5 refactor(configure.sh): use log_warning instead of inline ANSI codes
4 tasks
bromiesTM
approved these changes
Aug 4, 2026
6b8957bfc..593107e1a:
593107e1a IONOS: fix: do not offer document creation to public share visitors
Restores the ionos-dev-v30 behaviour that anonymous public share visitors
are not offered Collabora document creation. The v30 patch worked through
the legacy OCA.Files.NewFileMenu plugin, which no longer exists in the
NC33 line, so the gate now lives in RegisterTemplateFileCreatorListener.
Ported from ionos-dev-v30 richdocuments:
f1db58f79 IONOS: fix: for shares allow document creation only for users
that can edit
bromiesTM
force-pushed
the
mk/dev/HDNEXT-1967-port-v30-features
branch
from
August 4, 2026 10:02
c00ece1 to
5642dce
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Depends on: IONOS-Productivity/nc-richdocuments#14 — must be merged first, the
apps-external/richdocumentsgitlink in this PR points at its commit.Summary
ionos-dev-v33was rebuilt as a ground slate off vanillav33.0.6(HDNEXT-1604) with a hand-curated set of IONOS patches — 39 changed paths against 60 onionos-dev-v30. Most of that difference is legitimate (patches that landed upstream in NC33), but a handful of IONOS features were lost in the reconstruction, including one runtime fatal.Gap list derived by diffing each branch against its own vanilla base (
v30.0.7..ionos-dev-v30vsv33.0.6..ionos-dev-v33), then checking every v30-only patch against vanillav33.0.6to separate upstreamed from lost, plus a cherry-pick-aware comparison of all 13 submodules.What this PR restores
IONOS(auth)UserAgentForbiddenexception class was missing entirelyIONOS(files-sharing)IONOS(files)templates_enabledIONOS(files)IONOS(settings)nullmail transport noticeIONOS(config)IONOSgitlink →01b3f0fIONOS(richdocuments)Each commit body names the original commit(s) it was ported from.
1.
UserAgentForbidden— runtime fatallib/private/User/Session.phpandocs/v1.phpboth referenceOC\Authentication\Exceptions\UserAgentForbidden, but the class file exists in neither this branch nor vanillav33.0.6.This is not theoretical: nc-config ships
ionos-apps-user-agents.config.phpwithcore.login_flow_v2.allowed_user_agents = ['/Hidrive Next/i'], so the allow-list is active on every IONOS instance. Reproduced:The request returns an empty
200instead of the intended403.2. Pending shares — half-ported
LoadAdditionalListeneralready provides theaccept_defaultinitial state fromsharing.enable_share_accept, but nothing consumed it, so Pending shares always showed. Upstream moved the filesrc/views/shares.ts→src/files_views/shares.ts; the gate is restored there, defaulting tofalseso it fails closed.3.
templates_enabled— upstream regressionUpstream
64e852c5906replaced the computed value with a hardcodedtrue, removing the only way to hide Create templates folder. nc-config sets bothskeletondirectoryandtemplatedirectoryto'', so the entry came back.Restored, but using the same
SERVERROOTdefaults asTemplateManager::initializeTemplateDirectory()rather than v30's empty-string defaults, so an instance that configures neither value keeps upstream behaviour. For IONOS builds both are set explicitly, so the outcome is identical to v30.4. UserConfig — deviates from v30 on purpose
v30 always used
getAppValueBool(), safe because everyALLOWED_CONFIGSentry was a boolean back then. NC33 addeddefault_view(string,files/personal), and coercing that throughgetAppValueBool()would returntrueinstead of'files'for every user without a stored preference. The fallback is therefore type-aware.5. Mail settings — upstream branch was dead code
additional-mail.phpis now just a Vue mount point, so v30's patch had nowhere to apply. The Vue view does carry the equivalent branch, but it can never fire:smtpModeresolvesmail_smtpmodeagainstsmtpModeOptions, andAdmin\Mail::getForm()only ever offerssmtp/sendmail/qmail. Withmail_smtpmode = 'null'the lookup yieldsundefined, the notice is skipped and thev-elseform renders instead — with an empty Send mode select. Verified:smtpModeOptionsids weresmtpwhilemail_smtpmodewasnull.Since nc-config ships
mail.config.phpwithmail_smtpmode = 'null', this page is broken on every IONOS instance today.Deliberately out of scope
Test backports (
UserConfigTest.php,LoadAdditionalListenerTest.php,SessionTest.phpuser-agent cases) and theFilesListVirtual.vuefolder-icon tweak (tied to the dropped FA Pro icon set, HDNEXT-1719).apps/files/js/fileactionsmenu.jsneeds nothing — the file no longer exists in NC33.Already upstreamed into NC33, so no work needed:
SetConfigsensitive values,MountPoint,Preview\MovieS3 guard,MailerNullTransport, LoginFlowV2 client allow-list,SearchComposerprovider filtering,Template::findTemplatecore fix, allconfig.sample.phpdoc changes.How it was verified
All in the dev container.
UserAgentForbidden: OCS + basic auth with a disallowed UA →403 Client not allowed; allowed UA →100 OK. Confirmed the failure mode without the fix, and that it works with the committed autoloader (OC\resolves via PSR-4 — no classmap regeneration needed). Note WebDAV does not go through this path (own Sabre backend); pre-existing.default_viewstays a string), admin-set app value becomes the default for users without a preference, a user's own preference still wins, invalid values still rejected.userCanEdit()was false; new test fails without the fix; suite89 tests, 208 assertionsgreen.apps/files/tests/Controller/,apps/files_sharing/tests/Listener/,tests/lib/User/SessionTest.php→65/65and32/32green.cs:checkfindings and 14 eslint errors were left alone — verified pre-existing (the cs ones exist verbatim in pristinev33.0.6; the eslint ones are inSidebarQuota.vue/SharesMixin.js).Compiled
dist/assets for the two frontend changes are committed alongside their sources; unrelated build drift in other bundles was deliberately excluded.TODO
apps-external/richdocumentsgitlink points at the merged commit (rebase the bump if the PR is squash-merged)Checklist