summaryrefslogtreecommitdiff
path: root/app
AgeCommit message (Collapse)Author
2026-08-01Report validation failures without the exception preambleerdgeist
2026-08-01Derive the Atom feed timestamp from its entrieserdgeist
2026-08-01Require a second factor for elevation, not for holding adminerdgeist
2026-08-01tidy up user list, make otp flag more visibleerdgeist
2026-08-01Allow aggregate to order by slug and paint chapters list more nicelyerdgeist
2026-08-01Fix some spacing issues in user table and the wrappererdgeist
2026-08-01Let Redaktion grant and revoke its own roleerdgeist
Any holder may add or remove another account, witnessed as redaktion_grant/revoke so the vouching is legible. Not behind elevation: onboarding must not wait for a keyholder, and a compromised Redaktion account can already publish.
2026-08-01Show and extend the elevation windowerdgeist
A banner appears while elevated, counting down in minutes and carrying extend and drop controls. Three extensions of 30 minutes are allowed, so the window is at most two hours without a fresh code; a code resets the budget. The countdown is advisory, the server-side check authoritative, so it says "expired" rather than vanishing. The post-login flash tells an admin the timer has started.
2026-08-01Require a fresh second factor for user managementerdgeist
Administrative actions are gated behind a 30-minute elevation window: creating and retiring accounts, editing roles, clearing a second factor. Reading the list is not gated, and content work is untouched. elevated? is tied to is_admin?, so losing the role closes the window at once. The window opens when the second factor verifies at login, so an admin heading straight for user management is already elevated, and closes on logout with the other session state. Five wrong codes end the session, mirroring the login challenge. users#update carries no elevation filter, since self-service reaches it; the role field is gated in user_params instead and fails closed.
2026-08-01Declare role requirements per controllererdgeist
RoleRequired supplies require_redaktion and require_admin for surfaces that are not nodes and so cannot be reached by Node#restricted?. Navigation is content rather than plumbing, so menu_items requires redaktion. User management is janitorial and requires admin: index, new, create, reset_otp, deactivate, reactivate. verify_status now also covers show, without which any logged-in user could read any account by walking a small id space. Editing your own account stays open. The dashboard hides the Users and Navigation buttons from those who cannot use them; everything else stays visible to everyone. Both denials share one message and land on the dashboard. Adds redella (redaktion) and alufa (redaktion + alumni) fixtures.
2026-07-31Warn before the gate refuses, and check restore destinationserdgeist
nodes#new marks the kinds that place under /updates, derived from each kind's own path_prefix. The three parent pickers mark candidates the current user cannot publish into; menu_search returns needs_redaktion per result, computed per user rather than as a bare restricted flag, and the menu-item picker opts out. restore_from_trash! checks its destination: the restore is the move, applied rather than staged, so no later publish would have caught it. The node returns as a draft either way.
2026-07-31Show the gate before it refuses, and check the destinationerdgeist
nodes#show renders publish and trash as disabled_action spans with a hint naming what an editor can still do, matching how locked_by_other already reads. Editing and reverting stay live: drafting is free everywhere.
2026-07-31Bind aggregates over scoped tags to their subtreeerdgeist
CccConventions::TAG_SCOPES maps "update" and "pressemitteilung" to /updates and "disclosure" to /disclosure. Page.aggregate applies the mapping, so an aggregate over one of those tags is bounded by its subtree regardless of what the shortcode says. Tags stay unrestricted; positions are publish-gated. Both RSS actions call Page.aggregate rather than repeating its tag join. Empty feeds no longer crash: Atom falls back to the current time for the required <updated>, and the optional dc:date is omitted.
2026-07-31Gate live-content changes on restricted surfaceserdgeist
publish_draft!, trash!, destroy_from_trash!, attach_asset! and Asset#destroy_witnessed! now refuse unless the acting user holds redaktion, and only when the subject is on a restricted surface: the front page, the updates tree that feeds ~100k subscribers, or disclosure. Drafting, autosaving, tagging and creating stay free everywhere for everyone. Enforcement is in the models rather than the controllers, since attach_asset! and the rest are reachable from rake tasks and internal paths. It follows the errors.add-plus-bare-raise pattern the rest of Node already uses, so every existing RecordInvalid rescue reports it with a localised message; only assets_controller#destroy needed a rescue added. A nil user is treated as a system context and bypasses the gate. The default nil on three of those verbs is what makes that reachable, and removing those defaults once every call site passes a user is the next tightening.
2026-07-31Replace user deletion with deactivationerdgeist
Deactivation adds the alumni role and leaves the others in place, so reactivation is lossless and nobody has to remember what an account held. login_from_session checks alumni? on every request, so a signed-in user is locked out on their next one without any session invalidation. Guards prevent deactivating yourself or the last active admin, and both verbs are witnessed in the action log.
2026-07-31Group user accounts by roleerdgeist
Replaces the two-way admin/user split with four groups ordered by capability: administration, Redaktion, editors, alumni. alumni takes precedence over capability in role_group, so a retired admin appears at the bottom rather than the top. Forms now offer the three roles as checkboxes rather than a single admin checkbox, with a trailing hidden blank so an empty set can be posted, and user_params permits roles only for admins. Three create buttons prefill the common combinations.
2026-07-31Retire the unused per-node permission subsystemerdgeist
Every path through Permission raised or lied: validates_presence_of on a boolean made granted = false unsaveable, since false.blank? is true; get_permission_for read a nonexistent identifier attribute; has_permission? called an undefined plural method and returned a truthy relation in every case; and set_permission mutated granted without saving. Nothing outside the model referenced it and the table was empty.
2026-07-31Translate the Copied! label indicator for copy-url buttonserdgeist
2026-07-31Validate format of slug to be alphanum or _-erdgeist
2026-07-31Enforce slug and parent_id changes only taking place through updateerdgeist
2026-07-31Set the rss locale more expliciterdgeist
2026-07-31Restrict editor provided partial names to alphanum(/alphanum)?erdgeist
2026-07-31Let shortcode aggregate log but remove failed shortcode itselferdgeist
2026-07-30Promote article title from h2 to h1 and fix css accordinglyerdgeist
2026-07-30Provide link cells for the i18n matrixerdgeist
2026-07-30Provide the full i18n matrix for public/admin-preview/shared-preview urlserdgeist
2026-07-30Replaces the grey slab and filled-box handle with the house card idiom,erdgeist
a tabler grip and icon-only edit and delete actions. Shows each item's non-default translations muted below the title, read from the translation rows rather than the accessor so the fallback chain cannot disguise a missing label as a translated one. Adds move up/down buttons via acts_as_list, the single-pointer alternative WCAG 2.5.7 requires: the jQuery UI sortable binds mouse events only, so dragging works neither on touch nor from the keyboard. The grip is hidden below the desktop breakpoint for the same reason. The sort handler dropped dataType: "json" against a head :ok response, which sent every success down the error path, and now reloads so the disabled chevron states match the stored order after a drag.
2026-07-30Give action_participants an explicit ordererdgeist
2026-07-30Localise model validation messages and refusal reasonserdgeist
2026-07-30Fixup favicon, iconv.svg and apple-touch-iconerdgeist
2026-07-30Use icon sets on the public page and add a public-site shortcut in admin realmerdgeist
2026-07-30Retire the unroutable scaffold viewserdgeist
Nine generator leftovers for actions that either do not exist or never render HTML. menu_items/show goes with its route and its action, since deleting the template alone would turn a dead page into a missing-template error; pages_controller has only #preview, so its four CRUD views were unreachable by any route; and nodes#update redirects on every path.
2026-07-30Canonicalise per locale and declare hreflang alternateserdgeist
German content is reachable at both /updates/foo and /de/updates/foo, and a page with no English translation renders German at /en/updates/foo through the fallback chain, so three URLs each claimed to be canonical. Both tags now derive from one locale-to-URL function, which points every duplicate at the address of the version actually served, the unprefixed German URL, matching default_url_options. Alternates are declared only for locales in which the page genuinely has a translation, since /en/ serving German through the fallback is not an English version of the page. x-default points at German, the site's primary language.
2026-07-30Bring some tags forward to 2026 and provide humanized asset nameerdgeist
2026-07-30Emit per-page Open Graph metadataerdgeist
Replaces one hardcoded German description and an unrenderable SVG with per-page title, description, canonical URL, locale and publication date, plus the card variant or a site-wide default.
2026-07-30Generate a 1200x630 social card variant for every asseterdgeist
2026-07-29Don't display file icon in headline card, it's superflouserdgeist
2026-07-28add partial for menu_item titles in both localeserdgeist
2026-07-28Let editors manage menu titles in both localeserdgeist
2026-07-27Permit editors to touch menu_items' titleerdgeist
2026-07-27Fix locale dependent param compareerdgeist
2026-07-27Pin the two translation editors as wellerdgeist
2026-07-27Pin admin content reads to the default localeerdgeist
2026-07-27Surface held locks in the dashboard's work-in-progress widgeterdgeist
A lock with no draft or autosave behind it was invisible to everyone including its holder, until the next editor collided with it. work_in_progress now admits those nodes, and the widget names the holder rather than the last editor on any locked row. Also flips the ordering to stalest-first, so a backlog reads as a queue rather than a feed, and gives the heading a real total: the count came from the already-limited relation and could never exceed five.
2026-07-27Retire orphaned drafts partial and their translationserdgeist
2026-07-27Consolidate all main nav items in a single partialerdgeist
2026-07-27Let Globalize decide what locale to display for a page translationerdgeist
2026-07-27Move switchers out of the user check, so it also works when logged outerdgeist
2026-07-26Fix redundant link_to in assets#showerdgeist
2026-07-26Fix redundant link_to in assets#newerdgeist