| Age | Commit message (Collapse) | Author |
|
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.
|
|
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.
|
|
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.
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
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.
|
|
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.
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
|
The public views were never part of the admin extraction and were
broken in both directions: German visitors got "Featured", "Calendar"
and "Tags", English visitors got "Suchergebnisse für Suchbegriff:".
Also picks up the unlock-confirm message in link_helper, a straggler
from the revisions/menu_items batch, and drops two raw() calls in the
application layout in favour of link_to blocks.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Enforced at restore via a login-time stamp, written only at genuine
logins so the limit stays absolute rather than sliding. The cookie
name rotation logs everyone out once at deploy. Second-factor users
are deliberately not treated worse than password-only ones.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Asset names in summaries and publish deltas link to assets#show with
an inline Chronik beside each, suppressed inside that asset's own
zoom, per the node convention. assets#show gains a history button.
Also renames the details summary (no longer only translations) and
moves View Diff onto its own line.
|
|
|
|
|
|
|
|
|
|
A starred PDF previously ran through the same crop-and-lightbox path
a photo does -- exactly the awkward treatment explicit headline
designation was meant to avoid. _headline_image.html.erb now branches
on @headline_asset.pdf?: a PDF renders as a linked card (a :medium
thumbnail, a file icon, its name), no gallery participation at all.
The existing image-headline and gallery-fallback logic is otherwise
unchanged, now scoped to an image-specific headline only.
Other attached PDFs -- headlined or not -- list below as plain links,
same reasoning as why non-headline photos still get a gallery
trigger: an attached document shouldn't go invisible just because
nothing's been starred yet.
headline_image's own render guard needed widening to cover a page
with PDFs attached but no images and no headline at all -- the one
case none of the existing conditions accounted for.
|
|
image_interface and meta_data (admin_interface.js), the sort_images
action and route, and their admin.css rules -- the old vertical
image_browser sidebar this all depended on isn't rendered by any
current view. related_assets.js and the star-toggle sidebar fully
supersede what this did.
Confirmed unreachable via full grep across app/, config/routes.rb,
and admin_bundle.js before removal -- route, controller action, and
JS handler were all individually real and functional, just with
nothing left anywhere that could ever trigger them.
|
|
- related_assets gains a `headline` boolean (DB-enforced: at most one
per page), replacing "first image by position" as the headline
rule. A rake task backfills the current first image on every live
head/draft, so nothing changes visually until an editor changes it.
- The image picker sidebar gets a star toggle reflecting the flag;
the TinyMCE inline-image picker's badge now reads it too, instead
of assuming position 0.
- No headline chosen (or none attached) now falls back to the
gallery-count caption itself becoming the lightbox trigger, instead
of the gallery being unreachable.
- Assets gain creator, source_url, and license_key (against a new
config/asset_licenses.yml dictionary). asset_credit renders a
degrading attribution line, reused as a hidden per-image glightbox
caption so credit is one click away for every image, not only the
headline's always-visible one.
- Fixed: asset thumbnails rendered unconditionally regardless of
whether a real variant exists on disk. Asset#has_variant? checks
file existence, not content type -- some legacy PDFs have real
pre-rewrite thumbnails a content-type check would have hidden.
- assets#new/edit rebuilt onto the same node_description/node_content
layout as assets#show, picking up the three new fields in the
process.
|
|
|
|
|
|
|
|
|
|
- dark-mode restore now travels nonced, the admin constants likewise
- AUTH_TOKEN deleted in favour of the csrf meta tag
- new report collector at /csp_reports
|
|
Each row in nodes#show's History section now carries terse badges
from the action log: created, published, and restored (rollback
re-promotion), with date and actor, rendered from entry metadata
alone. Backfilled entries wear the inferred marker, so
reconstructed provenance stays distinguishable from witnessed
history. A revision that was published and later restored shows
both badges chronologically -- its true biography.
Only create and publish entries carry page_id; trash, restore, and
destroy annotate the node's own log zoom instead of any single
revision, by design.
|
|
Sentences for trash (with the pre-trash path), restore_from_trash
(with the destination), and destroy (with the final path, read
from its flat create-symmetric key).
|
|
nodes#show gains a Trash section on trashed nodes: provenance from
the trash entry, a restore form whose parent picker pre-fills the
old parent while it still lives, and permanent deletion. A
Move-to-Trash button joins the status actions on living nodes.
nodes#trashed lists trashed subtree roots with weight, provenance,
and deletion; the dashboard housekeeping row links to it, and
trash/destroy redirect there.
Deletion from Trash now removes the whole subtree, deepest first,
each node through a real destroy! so every per-node cascade runs --
amending the never-recursive rule for this one sanctioned path
(both confirms state the count; the root entry carries
destroyed_descendants). Bare Node#destroy still refuses children.
|