6 Commits
Author SHA1 Message Date
OpenClaw Sub-agent 909e4214f5 fix: short-link redirect overhaul — alnum-only aliases, signal cache invalidation, slim v2 cache, no-slash one-hop redirect
- alias charset: create/update now reject '-'/'_' (stripped by the lookup,
  making such links unreachable — movie-web/n8n-creator/ask-chatgpt were hit)
- data migration 0057 normalizes existing aliases (movie-web → movieweb);
  legacy dash URLs keep working via the stripped lookup
- cache invalidation unified into pre_save/post_save/post_delete signals
  (covers admin/shell/bulk-delete/rename — previously missed by delete_selected)
- redirect hot path: slim dict cache (was full model pickle incl. KB text),
  versioned key link:alias:v2:*, best-effort cache ops (Redis down no longer 500s),
  single-pass template URL parsing (dead regex branch removed)
- no-slash single-segment catch-all: go/ip resolves in one hop; unknown aliases
  still 301 to slash-appended known routes via resolve() fallback
- removed dead link_detail_by_alias route (shadowed by catch-all, unused)
- forms: alias help_text + HTML5 pattern; tests: 169 passed
2026-08-08 21:44:36 +10:00
junv 174b296c62 feat(links): log CONTENT_EDIT on text changes (no content persisted)
Previously, editing a custom link's text content created a spurious
URL_CHANGE row (fixed last commit) but no audit entry at all for the
actual content change. The product requirement: a change-log row SHOULD
be created so auditors see content was edited, but should NOT persist
the content itself.

LinkUpdateView now:

- Captures self.original_text in get_initial() alongside
  self.original_url.
- After super().form_valid() writes the new text, compares old vs new
  text. If different, creates a LinkChangeLog with
  change_type=CONTENT_EDIT and metadata={'changed': True} — no content
  payload. Applies to both LINK and CUSTOM link types.
- URL-change logging behaviour is unchanged.

Tests in TestCustomLinkEditUrlChangeLog now cover:
  - custom link text edit creates CONTENT_EDIT, no URL_CHANGE
  - custom link text unchanged creates no log
  - regular link text change creates CONTENT_EDIT
  - regular link URL change still logs URL_CHANGE
2026-07-16 11:24:04 +10:00
junv f7ac32cf4c fix(links): custom link edits spuriously logged URL changes
When editing a CUSTOM link's text content, the ViewUpdateView's
URL-change check was comparing the captured original_url (e.g.
'/custom/mynote') against form.cleaned_data['original_url'], which
for custom links is blank because the original_url input is hidden in
link_form.html and not submitted. They never matched, so every edit
produced a spurious LinkChangeLog 'URL changed' row.

Use the recomputed /custom/{alias} value (already set on
form.instance.original_url) for custom links, and only the submitted
form value for regular links. So the log now fires only when:

- a regular link's URL actually changes, or
- a custom link's alias changes (which derives a new /custom/{alias}).

Add TestCustomLinkEditUrlChangeLog covering:
  - custom link text-edit produces no URL-change log
  - regular link edit leaving URL unchanged produces no log
  - regular link URL change logs once with old/new URL
  - custom link alias change logs once with old/new derived URL
2026-07-16 11:11:25 +10:00
junv bf3e2e80cf feat(links): auto-create non-existent tags on link create, lowercase all
Select2 submits raw text as the value for new tags typed into the tag
box (tags: true + createTag in link_form.html). The previous
ModelMultipleChoiceField silently dropped those values because they
were not PKs of existing tags, so new tags were never persisted.

Add TagInputField, a tolerant ModelMultipleChoiceField subclass:
  - existing tag PKs resolve as before
  - raw text is treated as a new (or case-insensitive-existing) tag
  - names are stripped and lowercased before get_or_create so the tag
    namespace stays consistent and case-insensitive duplicates are
    avoided. The Tag.save() hook still derives the slug.

LinkForm now uses TagInputField for its tags field, so both
LinkCreateView and LinkUpdateView pick up the new behaviour. The
Select2 createTag callback in link_form.html now lowercases the term
so users see immediately what will be stored.

Add 7 regression tests in TestLinkTagAutoCreate covering: new tag
created + lowercased; multiple new tags; existing tag reused (no
duplicate); mixed PK + new-text submission; no tags submitted; empty
or whitespace-only submission ignored; whitespace stripped.
2026-07-16 10:10:07 +10:00
copilot-swe-agent[bot]andwahyd4 3c57f4afb9 Allow static Unicode text mixed with template params in template URLs
Agent-Logs-Url: https://github.com/wahyd4/links/sessions/b1b352f0-55a8-4973-9df9-5e1f6a8e3768

Co-authored-by: wahyd4 <836576+wahyd4@users.noreply.github.com>
2026-03-27 00:17:34 +00:00
junv 2ff7ab85ed Add tests 2026-03-21 21:00:38 +11:00